1 /*
2 
3     This file is part of the Maude 2 interpreter.
4 
5     Copyright 1997-2010 SRI International, Menlo Park, CA 94025, USA.
6 
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20 
21 */
22 
23 //
24 //      Implementation for class Sort
25 //
26 
27 //	utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30 
31 //      forward declarations
32 #include "interface.hh"
33 #include "core.hh"
34 
35 //      core class definitions
36 #include "sort.hh"
37 #include "connectedComponent.hh"
38 #include "module.hh"
39 #include "sortBdds.hh"
40 
SortBdds(Module * module)41 SortBdds::SortBdds(Module* module)
42 {
43   //
44   //	For each connected component of sorts, we calculate how many BDD variables are
45   //	need to encode such a sort.
46   //
47   const Vector<ConnectedComponent*>& components = module->getConnectedComponents();
48   int nrComponents = components.size();
49   componentInfo.resize(nrComponents);
50   int maxNrSorts = 0;
51   for (int i = 0; i < nrComponents; i++)
52     {
53       int nrSorts = components[i]->nrSorts();
54       if (nrSorts > maxNrSorts)
55 	maxNrSorts = nrSorts;
56       componentInfo[i].nrVariables = calculateNrBits(nrSorts);
57     }
58   maxNrVariables = calculateNrBits(maxNrSorts);
59   setNrVariables(2 * maxNrVariables);
60   //
61   //	For each connected component c we build the BDD encoding the relation
62   //	  valid(s1) /\ valid(s2) /\ s1 > s2
63   //	for sorts s1 and s2 in c.
64   //
65   //	Here s1 is encoded by BDD variables:
66   //	  0,...,maxNrVariables-1
67   //	and s2 is encoded by BDD variables:
68   //	  maxNrVariables,...,2*maxNrVariables-1
69   //
70   for (int i = 0; i < nrComponents; ++i)
71     {
72       int nrVariables = componentInfo[i].nrVariables;
73       ConnectedComponent* c = components[i];
74       int nrSorts = c->nrSorts();
75       Bdd disjunct;  // initialized to false by default
76       for (int s1 = 0; s1 < nrSorts; ++s1)
77 	{
78 	  Bdd lesserSorts;   // initialized to false by default
79 	  const NatSet& leqSorts = c->sort(s1)->getLeqSorts();
80 	  for (int s2 = s1 + 1; s2 < nrSorts; ++s2)  // starting at s1+1 rules out the equals case
81 	    {
82 	      if (leqSorts.contains(s2))
83 		lesserSorts = bdd_or(lesserSorts, makeIndexBdd(maxNrVariables, nrVariables, s2));
84 	    }
85 	  //
86 	  //	At this point lesserSorts holds the relation less_than_s1(s2) for current s1.
87 	  //
88 	  disjunct = bdd_or(disjunct, bdd_and(makeIndexBdd(0, nrVariables, s1), lesserSorts));
89 	}
90       componentInfo[i].gtRelation = disjunct;
91     }
92   DebugAdvisory("After gtRelation computation: BDD nodes in use: " << bdd_getnodenum());
93   //
94   //	For each sort s we compute the BDD encoding the relation
95   //	  valid(s1) /\ s1 <= s
96   //
97   //	Here s1 is encoded by BDD variables:
98   //	  0,...,maxNrVariables-1
99   //
100   const Vector<Sort*>& sorts = module->getSorts();
101   int nrSorts = sorts.size();
102   leqRelations.resize(nrSorts);
103   for (int i = 0; i < nrSorts; ++i)
104     {
105       Bdd disjunct;
106       Sort* s = sorts[i];
107       int nrVariables = getNrVariables(s->component()->getIndexWithinModule());
108       const NatSet& leqSorts = s->getLeqSorts();
109       FOR_EACH_CONST(j, NatSet, leqSorts)
110 	disjunct = bdd_or(disjunct, makeIndexBdd(0, nrVariables, *j));
111       leqRelations[i] = disjunct;
112       DebugAdvisory("leq BDD for sort " << s << " is " << disjunct << " using " << nrVariables << " variables");
113     }
114   DebugAdvisory("After leqRelation computation: BDD nodes in use: " << bdd_getnodenum());
115 }
116 
117 const Vector<Bdd>&
getSortFunction(Symbol * symbol) const118 SortBdds::getSortFunction(Symbol* symbol) const
119 {
120   //
121   //	We construct the sort function on demand. This is partly to save time and space
122   //	on symbols that don't occur in unification problems, but mostly to handle
123   //	late symbols.
124   //
125   int symbolIndex = symbol->getIndexWithinModule();
126   int currentSize = sortFunctions.size();
127   if (currentSize <= symbolIndex)
128     {
129       //
130       //	Resizing a vector of vectors of BDDs is very expensive so make it as large
131       //	as we currently expect.
132       //
133       sortFunctions.resize(symbol->getModule()->getSymbols().size());
134     }
135   Vector<Bdd>& f = sortFunctions[symbolIndex];
136   if (f.isNull())
137     symbol->computeSortFunctionBdds(*this, f);
138   return f;
139 }
140 
141 void
makeIndexVector(int nrBdds,int index,Vector<Bdd> & vec) const142 SortBdds::makeIndexVector(int nrBdds, int index, Vector<Bdd>& vec) const
143 {
144   //
145   //	Make a vector of nrBdds true/false BDDs that encodes index.
146   //
147   //	This is useful for returning the vector of BDDs encoding of a constant sort.
148   //
149   vec.resize(nrBdds);
150   for (int i = 0; index != 0; ++i, (index >>= 1))
151     {
152       if (index & 1)
153 	vec[i] = bddtrue;
154     }
155 }
156 
157 void
makeVariableVector(int firstVariable,int nrVariables,Vector<Bdd> & vec) const158 SortBdds::makeVariableVector(int firstVariable, int nrVariables, Vector<Bdd>& vec) const
159 {
160   //
161   //	Make a vector of nrVariables BDDs that encodes the BDD variables
162   //	firstVariable,..., firstVariable + nrVariables - 1.
163   //
164   //	This is useful for returning the vector of BDDs encoding of the undetermined
165   //	sort of a variable.
166   //
167   vec.resize(nrVariables);
168   for (int i = 0; i < nrVariables; ++i)
169     vec[i] = bdd_ithvar(firstVariable + i);
170 }
171 
172 void
appendVariableVector(int firstBddVariable,int nrBddVariables,Vector<Bdd> & vec) const173 SortBdds::appendVariableVector(int firstBddVariable, int nrBddVariables, Vector<Bdd>& vec) const
174 {
175   //
176   //	Make a vector of nrBddVariables BDDs that encodes the BDD variables
177   //	firstBddVariable,..., firstBddVVariable + nrBddVVariables - 1 and append it to vec.
178   //
179   //	sort of a Maude variable.
180   //
181   for (int i = 0; i < nrBddVariables; ++i)
182     vec.append(bdd_ithvar(firstBddVariable + i));
183 }
184 
185 Bdd
makeIndexBdd(int firstVariable,int nrVariables,int index) const186 SortBdds::makeIndexBdd(int firstVariable, int nrVariables, int index) const
187 {
188   //
189   //	Return a BDD in (firstVariable,..., firstVariable + nrVariables - 1) which is true exactly if
190   //	for all k in 0,..., nrVariables - 1, BDD variable firstVariable + k corresponds to the kth
191   //	bit in the binary representation of index.
192   //
193   Bdd result = bdd_true();
194   int end = firstVariable + nrVariables;
195   for (int i = firstVariable; i < end; ++i, index >>= 1)
196     result = bdd_and(result, (index & 1) ? bdd_ithvar(i) : bdd_nithvar(i));
197   return result;
198 }
199 
200 Bdd
makeVariableBdd(int firstVariable,int nrVariables) const201 SortBdds::makeVariableBdd(int firstVariable, int nrVariables) const
202 {
203   //
204   //	Make a BDD that represents the set of BDD variables
205   //	  {firstVariable,  firstVariable + 1 firstVariable + nrVariables - 1}
206   //	as a conjunction.
207   //
208   //	This is useful for quantification over a set of BDD variables.
209   //
210   Bdd result = bdd_true();
211   int end = firstVariable + nrVariables;
212   for (int i = firstVariable; i < end; ++i)
213     result = bdd_and(result, bdd_ithvar(i));
214   return result;
215 }
216 
217 int
calculateNrBits(int nrIndicies)218 SortBdds::calculateNrBits(int nrIndicies)
219 {
220   //
221   //	Calculate the number of bits needed to represent 0,..., nrIndicies-1.
222   //
223   int nrBits = 1;
224   for (int representable = 2; representable < nrIndicies; ++nrBits, representable <<= 1)
225     ;
226   return nrBits;
227 }
228 
229 Bdd
getRemappedLeqRelation(Sort * sort,int firstVariable) const230 SortBdds::getRemappedLeqRelation(Sort* sort, int firstVariable) const
231 {
232   //
233   //	We return a BDD for the sort relation valid(s) /\ s <= sort
234   //	with the BDD variables representing s remapped to start from
235   //	firstVariable.
236   //
237   int nrVariables = getNrVariables(sort->component()->getIndexWithinModule());
238   //bddPair* varMap = bdd_newpair();
239   bddPair* varMap = getCachedPairing();
240   for (int i = 0; i < nrVariables; ++i)
241     bdd_setpair(varMap, i, firstVariable + i);
242   Bdd leqRelation = bdd_replace(getLeqRelation(sort->getIndexWithinModule()), varMap);
243   //bdd_freepair(varMap);
244   for (int i = 0; i < nrVariables; ++i)
245     bdd_setbddpair(varMap, i, bdd_false());
246   return leqRelation;
247 }
248 
249 Bdd
applyLeqRelation(Sort * sort,const Vector<Bdd> & argument) const250 SortBdds::applyLeqRelation(Sort* sort, const Vector<Bdd>& argument) const
251 {
252   //
253   //	We return a Bdd for the sort relation valid(s) /\ s <= sort
254   //	applied to an s given by a vector of BDDs.
255   //
256   int nrBdds = argument.size();
257   Assert(nrBdds == getNrVariables(sort->component()->getIndexWithinModule()),
258 	 "wrong number of BDD arguments: expecting " << getNrVariables(sort->component()->getIndexWithinModule()) <<
259 	 " passed " << nrBdds <<
260 	 " sort " << sort);
261 
262   //bddPair* argMap = bdd_newpair();
263   bddPair* argMap = getCachedPairing();
264   for (int i = 0; i < nrBdds; ++i)
265     bdd_setbddpair(argMap, i, argument[i]);
266   Bdd result = bdd_veccompose(getLeqRelation(sort->getIndexWithinModule()), argMap);
267   //bdd_freepair(argMap);
268   for (int i = 0; i < nrBdds; ++i)
269     bdd_setbddpair(argMap, i, bdd_false());
270   return result;
271 }
272 
273 // experimental code for faster sort computations
274 
275 void
appendIndexVector(int nrBdds,int index,Vector<Bdd> & vec) const276 SortBdds::appendIndexVector(int nrBdds, int index, Vector<Bdd>& vec) const
277 {
278   //
279   //	Make a vector of nrBdds true/false BDDs that encodes index.
280   //
281   //	This is useful for returning the vector of BDDs encoding of a constant sort.
282   //
283   int oldSize = vec.size();
284   vec.resize(nrBdds + oldSize);
285   for (int i = oldSize; index != 0; ++i, (index >>= 1))
286     {
287       if (index & 1)
288 	vec[i] = bddtrue;
289     }
290 }
291 
292 void
operatorCompose(Symbol * op,const Vector<Bdd> & inputBdds,Vector<Bdd> & outputBdds) const293 SortBdds::operatorCompose(Symbol* op, const Vector<Bdd>& inputBdds, Vector<Bdd>& outputBdds) const
294 {
295   //
296   //	Calling this could increase the number of BDD variables so need to
297   //	get it out of the way before we get the caching pairing.
298   //
299   const Vector<Bdd>& sortFunction = getSortFunction(op);
300   //
301   //	Now fill out the cached pairing with our input BDDs.
302   //
303   bddPair* cachedPairing = getCachedPairing();
304   int nrInputBdds = inputBdds.size();
305   for (int i = 0; i < nrInputBdds; ++i)
306     bdd_setbddpair(cachedPairing, i, inputBdds[i]);
307   //
308   //	Apply compose with each of BDDs representing the sort function
309   //	and append the result to the output BDDs.
310   //
311   FOR_EACH_CONST(i, Vector<Bdd>, sortFunction)
312     outputBdds.append(bdd_veccompose(*i, cachedPairing));
313   //
314   //	Clean up the cached pairing by setting all the used slots
315   //	to bdd_false(). This avoids the cached pairing containing pointers
316   //	to unused junk and messing with garbage collection.
317   //
318   for (int i = 0; i < nrInputBdds; ++i)
319     bdd_setbddpair(cachedPairing, i, bdd_false());
320 }
321