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