1 /*
2
3 This file is part of the Maude 2 interpreter.
4
5 Copyright 1997-2008 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 ACU_UnificationSubproblem2.
25 //
26
27 // utility stuff
28 #include "macros.hh"
29 #include "vector.hh"
30 #include "indent.hh"
31 #include "intSystem.hh"
32
33 // forward declarations
34 #include "interface.hh"
35 #include "core.hh"
36 #include "variable.hh"
37 #include "ACU_Persistent.hh"
38 #include "ACU_Theory.hh"
39
40 // interface class definitions
41 #include "argVec.hh"
42 #include "associativeSymbol.hh"
43 #include "dagNode.hh"
44 #include "subproblem.hh"
45
46 // core class definitions
47 #include "variableInfo.hh"
48 #include "unificationContext.hh"
49 #include "localBinding.hh"
50
51 // variable class definitions
52 #include "variableSymbol.hh"
53 #include "variableDagNode.hh"
54
55 // ACU theory class definitions
56 #include "ACU_Symbol.hh"
57 #include "ACU_DagNode.hh"
58 #include "ACU_UnificationSubproblem2.hh"
59
ACU_UnificationSubproblem2(ACU_Symbol * topSymbol)60 ACU_UnificationSubproblem2::ACU_UnificationSubproblem2(ACU_Symbol* topSymbol)
61 : topSymbol(topSymbol),
62 savedSubstitution(0),
63 preSolveSubstitution(0)
64 {
65 DebugAdvisory("Created ACU_UnificationSubproblem2() base " << ((void*) this) <<
66 " for topSymbol " << topSymbol);
67 maximalSelections = 0;
68 }
69
~ACU_UnificationSubproblem2()70 ACU_UnificationSubproblem2::~ACU_UnificationSubproblem2()
71 {
72 delete maximalSelections;
73 }
74
75 void
markReachableNodes()76 ACU_UnificationSubproblem2::markReachableNodes()
77 {
78 //
79 // Protect dags in preSolveSubstitution.
80 //
81 int nrFragile = preSolveSubstitution.nrFragileBindings();
82 for (int i = 0; i < nrFragile; i++)
83 {
84 DagNode* d = preSolveSubstitution.value(i);
85 if (d != 0)
86 d->mark();
87 }
88 //
89 // No need to mark savedSubstitution since its dags are a subset of those in
90 // preSolveSubstitution; we get from preSolveSubstitution to savedSubstitution by
91 // unsolving bindings.
92 //
93 }
94
95 void
addUnification(DagNode * lhs,DagNode * rhs,bool marked,UnificationContext & solution)96 ACU_UnificationSubproblem2::addUnification(DagNode* lhs, DagNode* rhs, bool marked, UnificationContext& solution)
97 {
98 Assert(lhs->symbol() == topSymbol, "bad lhs dag " << lhs);
99 Assert(topSymbol->hasIdentity() ||
100 rhs->symbol() == topSymbol ||
101 dynamic_cast<VariableDagNode*>(rhs) != 0, "bad rhs for for non-collapse theory " << rhs);
102 Assert(topSymbol->hasIdentity() || !marked, "bad mark for non-collapse theory");
103
104 int nrSubterms = subterms.size();
105 {
106 //
107 // We start with all multiplicities as zero and increment or decrement them as we find subterms.
108 //
109 for (int i = 0; i < nrSubterms; ++i)
110 multiplicities[i] = 0;
111 }
112 //
113 // We are guaranteed that the lhs has the form f(...) where f is our top symbol.
114 // We first deal with the rhs.
115 //
116 if (rhs->symbol() == topSymbol)
117 {
118 //
119 // The usual case where the unification looks like f(...) =? f(...)
120 // We just insert the multiplicities into our table.
121 //
122 ArgVec<ACU_DagNode::Pair> rhsArgs = safeCast(ACU_DagNode*, rhs)->argArray;
123 FOR_EACH_CONST(i, ArgVec<ACU_DagNode::Pair>, rhsArgs)
124 setMultiplicity(i->dagNode, - i->multiplicity, solution);
125 }
126 else
127 {
128 //
129 // Must be of the form f(...) =? X
130 // or a theory clash of the form f(...) =? g(...)
131 //
132 Term* identity = topSymbol->getIdentity();
133 if (identity != 0 && identity->equal(rhs))
134 ; // rhs disappears in our theory
135 else
136 {
137 int subtermIndex = setMultiplicity(rhs, -1, solution);
138 if (marked && subtermIndex != NONE)
139 markedSubterms.insert(subtermIndex); // cannot be assigned multiple things
140 }
141 }
142 //
143 // Now deal with the lhs.
144 //
145 {
146 ArgVec<ACU_DagNode::Pair> lhsArgs = safeCast(ACU_DagNode*, lhs)->argArray;
147 FOR_EACH_CONST(i, ArgVec<ACU_DagNode::Pair>, lhsArgs)
148 setMultiplicity(i->dagNode, i->multiplicity, solution);
149 }
150 //
151 // Some of the subterms might have cancelled - if they were newly introduced they are not needed.
152 //
153 killCancelledSubterms(nrSubterms);
154 //
155 // Check to see if everything cancelled. If something did not there we need
156 // to record the Diophantine equation corresponding to this unification problem.
157 //
158 FOR_EACH_CONST(i, Vector<int>, multiplicities)
159 {
160 if (*i != 0)
161 {
162 unifications.push_back(multiplicities);
163 return;
164 }
165 }
166 //
167 // No non-zero entries so we can ignore unification problem.
168 //
169 }
170
171 int
setMultiplicity(DagNode * dagNode,int multiplicity,UnificationContext & solution)172 ACU_UnificationSubproblem2::setMultiplicity(DagNode* dagNode, int multiplicity, UnificationContext& solution)
173 {
174 //
175 // First we replace a variable with its current representative. Really we should also
176 // do this for variables within aliens as well.
177 //
178 if (VariableDagNode* varDagNode = dynamic_cast<VariableDagNode*>(dagNode))
179 {
180 varDagNode = varDagNode->lastVariableInChain(solution);
181 //
182 // Normally we don't care about variables bound into our theory since they
183 // will be unsolved as part of the AC/ACU unification procedure to ensure
184 // termination. The exception is variables bound to our identity.
185 //
186 if (Term* identity = topSymbol->getIdentity())
187 {
188 if (DagNode* subject = solution.value(varDagNode->getIndex()))
189 {
190 if (identity->equal(subject))
191 return NONE; // identity elements are just eliminated
192 }
193 }
194 //
195 // Otherwise we work with the representative variable.
196 //
197 dagNode = varDagNode;
198 }
199 //
200 // Now look for dag in list of nominally abstracted dags.
201 //
202 int nrSubterms = subterms.size();
203 for (int i = 0; i < nrSubterms; ++i)
204 {
205 if (dagNode->equal(subterms[i]))
206 {
207 multiplicities[i] += multiplicity;
208 return i;
209 }
210 }
211 //
212 // Not found so make a new entry.
213 //
214 subterms.append(dagNode);
215 multiplicities.append(multiplicity);
216 return nrSubterms;
217 }
218
219 void
killCancelledSubterms(int nrOldSubterms)220 ACU_UnificationSubproblem2::killCancelledSubterms(int nrOldSubterms)
221 {
222 int nrSubterms = subterms.size();
223 if (nrSubterms > nrOldSubterms)
224 {
225 //
226 // We added subterms that need to be removed if they cancelled.
227 //
228 int destination = nrOldSubterms;
229 for (int i = nrOldSubterms; i < nrSubterms; ++i)
230 {
231 int m = multiplicities[i];
232 if (m != 0)
233 {
234 //
235 // Didn't cancel - need to preserve subterm and its multiplicity.
236 //
237 if (destination < i)
238 {
239 subterms[destination] = subterms[i];
240 multiplicities[destination] = m;
241 }
242 ++destination;
243 }
244 }
245 if (destination < nrSubterms)
246 {
247 //
248 // We killed some subterms; get rid of the surplus entries.
249 //
250 subterms.resize(destination);
251 multiplicities.resize(destination);
252 }
253 }
254 }
255
256 void
unsolve(int index,UnificationContext & solution)257 ACU_UnificationSubproblem2::unsolve(int index, UnificationContext& solution)
258 {
259 //
260 // We take a solved form X = f(...), turn it into a Diophantine equation and
261 // remove it from the current solution.
262 //
263 DagNode* variable = solution.getVariableDagNode(index);
264 DagNode* value = solution.value(index);
265 solution.bind(index, 0);
266
267 Assert(variable != 0, "couldn't get variable for index " << index << " bound to " << value);
268 DebugAdvisory("### unsolving " << variable << " <- " << value);
269 //
270 // Start with all multiplicities zero.
271 //
272 {
273 int nrSubterms = subterms.size();
274 for (int i = 0; i < nrSubterms; ++i)
275 multiplicities[i] = 0;
276 }
277 //
278 // Increment multiplicities for subterms of f(...)
279 //
280 ArgVec<ACU_DagNode::Pair> args = safeCast(ACU_DagNode*, value)->argArray;
281 FOR_EACH_CONST(i, ArgVec<ACU_DagNode::Pair>, args)
282 setMultiplicity(i->dagNode, i->multiplicity, solution);
283 //
284 // Decrement multiplicity for X
285 //
286 setMultiplicity(variable, -1, solution);
287 //
288 // Record Diophantine equation (can never be all zero).
289 //
290 unifications.push_back(multiplicities);
291 }
292
293 bool
solve(bool findFirst,UnificationContext & solution,PendingUnificationStack & pending)294 ACU_UnificationSubproblem2::solve(bool findFirst, UnificationContext& solution, PendingUnificationStack& pending)
295 {
296 //
297 // Check for degenerate case where all of the unification problems cancelled.
298 //
299 if (unifications.empty())
300 return findFirst;
301
302 if (findFirst)
303 {
304 //
305 // Save the current substitution
306 //
307 preSolveSubstitution.clone(solution);
308 //
309 // Unsolve any solved forms that are in our theory. This seemingly wasteful step
310 // has to be done in order to avoid nontermination.
311 //
312 // The idea is that solved forms X = f(...) in our theory were created by us at some
313 // earlier invokation and represent decisions made about the solution on the current
314 // path. They must therefore be considered simultaneously with current unification
315 // subproblems otherwise we might generate an additional binding for X which is
316 // then resolved by creating yet another f-theory subproblem.
317 //
318 int nrFragile = solution.nrFragileBindings();
319 for (int i = 0; i < nrFragile; ++i)
320 {
321 DagNode* value = solution.value(i);
322 if (value != 0 && value->symbol() == topSymbol)
323 unsolve(i, solution);
324 }
325
326 if (!buildAndSolveDiophantineSystem(solution))
327 {
328 //
329 // Restore current solution and fail.
330 //
331 solution.restoreFromClone(preSolveSubstitution);
332 return false;
333 }
334 if (topSymbol->hasIdentity())
335 {
336 bdd legal = computeLegalSelections();
337 DebugAdvisory("legal = " << legal <<
338 " node count = " << bdd_nodecount(legal) <<
339 " path count = " << bdd_pathcount(legal));
340 int nrBasisElements = basis.size();
341 bdd maximal = legal;
342 if (topSymbol->hasUnequalLeftIdentityCollapse())
343 {
344 //
345 // Can't ignore non-maximal solutions because
346 // (1) Maximal solution may not have a sorting while a non-maximal solution may have.
347 // (2) The sorting of a maximal solution may exclude a non-maximal solution it was covering.
348 //
349 }
350 else
351 {
352 //
353 // Assume that each variable introduced for a Diophantine basis element will
354 // be able to disappear by taking the basis element. Thus we only want maximal
355 // vectors from legal.
356 //
357 for (int i = 0; i < nrBasisElements; ++i)
358 {
359 //
360 // bigger = not(ith var) /\ (legal restricted to ith var true)
361 //
362 // i.e. bigger represents those vectors where the ith variable is false and we get
363 // a legal solution by making it true. Clearly the original vector was not maximal,
364 // even if it was a legal solution.
365 //
366 // We need to eliminate these vectors if we want maximal solutions, so we compute the
367 // complement of this set of vectors and conjunct them in.
368 //
369 bdd notBigger = bdd_or(bdd_ithvar(i), bdd_not(bdd_restrict(legal, bdd_ithvar(i))));
370 maximal = bdd_and(maximal, notBigger);
371 }
372 }
373 DebugAdvisory("maximal = " << maximal <<
374 " node count = " << bdd_nodecount(maximal) <<
375 " path count = " << bdd_pathcount(maximal));
376 maximalSelections = new AllSat(maximal, 0, nrBasisElements - 1);
377 }
378 //
379 // Save state of the pending stack with the substitution so that
380 // we can restore both in order to undo each of our solutions.
381 //
382 savedSubstitution.clone(solution);
383 savedPendingState = pending.checkPoint();
384 }
385 else
386 {
387 //
388 // Restore pending stack and current substitution, implicitly deallocating
389 // any fresh variables we introduced.
390 //
391 pending.restore(savedPendingState);
392 solution.restoreFromClone(savedSubstitution);
393 }
394 //
395 // Look for a solution in our theory.
396 //
397 while (topSymbol->hasIdentity() ? nextSelectionWithIdentity(findFirst) : nextSelection(findFirst))
398 {
399 findFirst = false;
400
401 if (buildSolution(solution, pending))
402 return true;
403 //
404 // Restore pending stack and current substitution, implicitly deallocating
405 // any fresh variables we introduced.
406 //
407 pending.restore(savedPendingState);
408 solution.restoreFromClone(savedSubstitution);
409 }
410 //
411 // No more solutions; restore any solved forms that we unsolved.
412 //
413 solution.restoreFromClone(preSolveSubstitution);
414 return false;
415 }
416
417 void
classify(int subtermIndex,UnificationContext & solution,bool & canTakeIdentity,int & upperBound,Symbol * & stableSymbol)418 ACU_UnificationSubproblem2::classify(int subtermIndex,
419 UnificationContext& solution,
420 bool& canTakeIdentity,
421 int& upperBound,
422 Symbol*& stableSymbol)
423 {
424 //
425 // For a subterm that we have nominally abstraction by a Diophantine variable we determine:
426 // (1) Is is possible that the subject can be unified against identity.
427 // (2) Can we determine an upperbound on how many other subjects could be unified against it.
428 // (3) Can we determine what it will only unify against something with a specific stable top symbol.
429 //
430 Term* identity = topSymbol->getIdentity();
431 //
432 // Default determinations:
433 //
434 canTakeIdentity = (identity != 0); // can unify with identity if it exists
435 upperBound = markedSubterms.contains(subtermIndex) ? 1 : UNBOUNDED; // marked subterms are bounded by 1
436 stableSymbol = 0; // no stable symbol
437 //
438 // Now we try to tighten these restrictions.
439 //
440 DagNode* subject = subterms[subtermIndex];
441 if (VariableDagNode* v = dynamic_cast<VariableDagNode*>(subject))
442 {
443 //
444 // If subterm is a variable we may be able to constrain it based on its sort.
445 //
446 VariableSymbol* variableSymbol = safeCast(VariableSymbol*, v->symbol());
447 Sort* variableSort = variableSymbol->getSort();
448 int variableSortBound = topSymbol->sortBound(variableSort);
449 if (variableSortBound < upperBound)
450 upperBound = variableSortBound;
451 canTakeIdentity = canTakeIdentity && topSymbol->takeIdentity(variableSort);
452 subject = solution.value(v->getIndex());
453 if (subject == 0)
454 return; // unbound variable
455 Assert(subject->symbol() != topSymbol, "variable " << (DagNode*) v <<
456 " still bound into our theory " << subject << " even after unsolving phase");
457 }
458 //
459 // Now we have a nonvariable, or a variable bound to a nonvariable.
460 // We look to see if the top symbol is stable.
461 //
462 Symbol* symbol = subject->symbol();
463 DebugAdvisory("ACU_UnificationSubproblem2::classify() subject = " << subject <<
464 " symbol->isStable() = " << symbol->isStable() <<
465 " subject->isGround() = " << subject->isGround());
466 if (subject->isGround())
467 {
468 upperBound = 1; // ground alien can unify with at most one thing
469 canTakeIdentity = false; // identity should not appear as a subterm
470 stableSymbol = symbol;
471 }
472 else if (symbol->isStable())
473 {
474 //
475 // Anything that unifies with subject must have symbol on top.
476 //
477 upperBound = 1; // stable symbol can unify with at most one thing
478 canTakeIdentity = canTakeIdentity && (symbol == identity->symbol());
479 stableSymbol = symbol;
480 }
481 }
482
483 bool
buildAndSolveDiophantineSystem(UnificationContext & solution)484 ACU_UnificationSubproblem2::buildAndSolveDiophantineSystem(UnificationContext& solution)
485 {
486 #ifndef NO_ASSERT
487 DebugAdvisory("building DiophantineSystem for ACU_UnificationSubproblem2 " << ((void*) this));
488 if (globalAdvisoryFlag)
489 {
490 for (int i = 0; i < subterms.length(); ++i)
491 cerr << subterms[i] << '\t';
492 cerr << endl;
493 }
494 #endif
495 //
496 // Each distinct alien subdag from a unification problem that didn't get cancelled
497 // is represented by a Diophantine variable.
498 //
499 int nrDioVars = subterms.size();
500 Assert(nrDioVars > 0, "shouldn't be called in degenerate case");
501 //if (nrDioVars == 1)
502 // return false; // trivial failure
503 //
504 // Create the Diophantine system.
505 //
506 IntSystem system(nrDioVars);
507 FOR_EACH_CONST(i, list<Vector<int> >, unifications)
508 system.insertEqn(*i);
509 //
510 // Compute an upperbound on the assignment to each Diophantine variable.
511 //
512 upperBounds.resize(nrDioVars); // for basis selection use
513 IntSystem::IntVec upperBnds(nrDioVars); // for Diophantine system use
514 Vector<Symbol*> stableSymbols(nrDioVars); // if we know we can only unify against a stable alien
515 for (int i = 0; i < nrDioVars; ++i)
516 {
517 bool canTakeIdentity;
518 int upperBound;
519 classify(i, solution, canTakeIdentity, upperBound, stableSymbols[i]);
520 DebugAdvisory("ACU_UnificationSubproblem2::buildAndSolveDiophantineSystem() i = " << i <<
521 " subterms[i] = " << subterms[i] <<
522 " canTakeIdentity = " << canTakeIdentity <<
523 " upperBound = " << upperBound);
524
525 if (!canTakeIdentity)
526 needToCover.insert(i); // can't take identity so mark as uncovered and be sure to cover
527 upperBounds[i] = upperBound;
528 upperBnds[i] = upperBound;
529 }
530 system.setUpperBounds(upperBnds);
531 //
532 // Extract the basis.
533 //
534 Vector<int> dioSol;
535 for (int index = 0; system.findNextMinimalSolution(dioSol);)
536 {
537 #ifndef NO_ASSERT
538 DebugAdvisory("added basis element for ACU_UnificationSubproblem2 " << ((void*) this));
539 if (globalAdvisoryFlag)
540 {
541 for (int i = 0; i < dioSol.length(); ++i)
542 cerr << dioSol[i] << '\t';
543 cerr << endl;
544 }
545 #endif
546 Symbol* existingStableSymbol = 0;
547 for (int i = 0; i < nrDioVars; ++i)
548 {
549 int t = dioSol[i];
550 if (t != 0)
551 {
552 Symbol* stableSymbol = stableSymbols[i];
553 if (stableSymbol != 0)
554 {
555 //
556 // We have a basis element that is going to force a term with a stable symbol to
557 // unify with something.
558 //
559 if (existingStableSymbol == 0)
560 existingStableSymbol = stableSymbol;
561 else if (existingStableSymbol != stableSymbol)
562 {
563 //
564 // Forced unification is guaranteed to fail.
565 //
566 DebugAdvisory("killing basis element, " << existingStableSymbol << " vs " << stableSymbol);
567 goto killElement;
568 }
569 }
570 }
571 }
572 {
573 basis.push_front(Entry());
574 Entry& e = basis.front();
575 e.remainder = accumulator; // deep copy
576 e.element.resize(nrDioVars);
577 for (int i = 0; i < nrDioVars; ++i)
578 {
579 if ((e.element[i] = dioSol[i]) != 0)
580 accumulator.insert(i); // subterm i is covered
581 }
582 e.index = index;
583 ++index;
584 }
585 killElement:
586 ;
587 }
588 //
589 // Check that each term that needs to be covered is covered by at least one basis element.
590 //
591 if (!accumulator.contains(needToCover))
592 return false;
593 //
594 // Initialize totals vector and uncovered set.
595 //
596 totals.resize(nrDioVars);
597 for (int i = 0; i < nrDioVars; ++i)
598 totals[i] = 0;
599 uncovered = needToCover;
600 return true;
601 }
602
603 bool
nextSelection(bool findFirst)604 ACU_UnificationSubproblem2::nextSelection(bool findFirst)
605 {
606 int nrSubterms = subterms.size();
607 if (findFirst)
608 {
609 current = basis.begin();
610 forward:
611 //
612 // We keep adding basis elements to the selection as long as they don't violate
613 // an upper bound. When we do hit a violation, if we find that a covering is
614 // not possible without this element we backtrack.
615 //
616 for (; current != basis.end(); ++current)
617 {
618 if (includable(current))
619 {
620 for (int i = 0; i < nrSubterms; ++i)
621 {
622 if (int v = current->element[i])
623 {
624 totals[i] += v;
625 uncovered.subtract(i);
626 }
627 }
628 selection.append(current);
629 }
630 else
631 {
632 if (!(current->remainder.contains(uncovered)))
633 goto backtrack;
634 }
635 }
636 Assert(uncovered.empty(), "failed to cover");
637 return true;
638 }
639 else
640 {
641 backtrack:
642 //
643 // We backtrack by removing basis elements from the current selection. Each time
644 // we remove an element, if we can still get a covering with later elements we
645 // start forward again.
646 //
647 Assert(selection.size() > 0, "backtracking over empty selection");
648 for (int i = selection.size() - 1; i >= 0; --i)
649 {
650 current = selection[i];
651 for (int j = 0; j < nrSubterms; ++j)
652 {
653 if ((totals[j] -= current->element[j]) == 0)
654 uncovered.insert(j);
655 }
656 if (current->remainder.contains(uncovered))
657 {
658 ++current;
659 selection.resize(i);
660 goto forward;
661 }
662 }
663 }
664 return false;
665 }
666
667 bool
nextSelectionWithIdentity(bool)668 ACU_UnificationSubproblem2::nextSelectionWithIdentity(bool /* findFirst */)
669 {
670 if (maximalSelections->nextAssignment())
671 {
672 const Vector<Byte>& assignment = maximalSelections->getCurrentAssignment();
673 selection.clear();
674 FOR_EACH_CONST(i, Basis, basis)
675 {
676 if (assignment[i->index])
677 selection.append(i);
678 }
679 return true;
680 }
681 return false;
682 }
683
684 bool
includable(Basis::const_iterator potential)685 ACU_UnificationSubproblem2::includable(Basis::const_iterator potential)
686 {
687 int nrSubterms = subterms.size();
688 for (int i = 0; i < nrSubterms; ++i)
689 {
690 if (totals[i] + potential->element[i] > upperBounds[i])
691 return false;
692 }
693 return true;
694 }
695
696 bdd
computeLegalSelections()697 ACU_UnificationSubproblem2::computeLegalSelections()
698 {
699 int nrBasisElements = basis.size();
700 BddUser::setNrVariables(nrBasisElements);
701 bdd conjunction = bddtrue;
702 Vector<bdd> bounds;
703
704 int nrSubterms = subterms.size();
705 for (int i = 0; i < nrSubterms; ++i)
706 {
707 int upperBound = upperBounds[i];
708 if (upperBound != UNBOUNDED)
709 {
710 //
711 // Compute a BDD that ensures the selection of basis elements
712 // keeps the assignment to the subterm at or below upper bound.
713 //
714 bounds.resize(upperBound + 1);
715 for (int j = 0; j <= upperBound; ++j)
716 bounds[j] = bddtrue;
717 FOR_EACH_CONST(k, Basis, basis)
718 {
719 int value = k->element[i];
720 if (value != 0)
721 {
722 for (int j = upperBound; j >= 0; --j)
723 {
724 if (j - value >= 0)
725 bounds[j] = bdd_ite(bdd_ithvar(k->index), bounds[j - value], bounds[j]);
726 else
727 bounds[j] = bdd_ite(bdd_ithvar(k->index), bddfalse, bounds[j]);
728 }
729 }
730 }
731 DebugAdvisory("upperbound " << i <<
732 " bound = " << bounds[upperBound] <<
733 " node count = " << bdd_nodecount(bounds[upperBound]) <<
734 " path count = " << bdd_pathcount(bounds[upperBound]));
735 conjunction = bdd_and(conjunction, bounds[upperBound]);
736 }
737 if (needToCover.contains(i))
738 {
739 //
740 // Compute a BDD that ensures the selection of basis elements
741 // assigns at least one thing to the subterm.
742 //
743 bdd disjunction = bddfalse;
744 FOR_EACH_CONST(k, Basis, basis)
745 {
746 if (k->element[i] != 0)
747 disjunction = bdd_or(disjunction, bdd_ithvar(k->index));
748 }
749 DebugAdvisory("need to cover " << i <<
750 " disjunction = " << disjunction <<
751 " node count = " << bdd_nodecount(disjunction) <<
752 " path count = " << bdd_pathcount(disjunction));
753 conjunction = bdd_and(conjunction, disjunction);
754 }
755 }
756 return conjunction;
757 }
758
759 bool
buildSolution(UnificationContext & solution,PendingUnificationStack & pending)760 ACU_UnificationSubproblem2::buildSolution(UnificationContext& solution, PendingUnificationStack& pending)
761 {
762 #ifndef NO_ASSERT
763 DebugAdvisory("buildSolution() using basis elements:");
764 if (globalAdvisoryFlag)
765 {
766 for (int j = 0; j < selection.size(); ++j)
767 {
768 for (int i = 0; i < subterms.size(); ++i)
769 cerr << selection[j]->element[i] << '\t';
770 cerr << endl;
771 }
772 }
773 #endif
774 //
775 // First we allocate a fresh variable for each basis element selected.
776 //
777 ConnectedComponent* component = topSymbol->rangeComponent();
778 int selectionSize = selection.size();
779 Vector<DagNode*> freshVariables(selectionSize);
780 for (int i = 0; i < selectionSize; ++i)
781 freshVariables[i] = solution.makeFreshVariable(component);
782 //
783 // Now for each abstracted subterm we compute a solution in
784 // the purified problem.
785 //
786 int nrSubterms = subterms.size();
787 for (int i = 0; i < nrSubterms; ++i)
788 {
789 bool inTheory = true;
790 int nrElements = 0;
791 int lastElement = NONE;
792 for (int j = 0; j < selectionSize; ++j)
793 {
794 if (selection[j]->element[i] > 0)
795 {
796 ++nrElements;
797 lastElement = j;
798 }
799 }
800 Assert(nrElements <= upperBounds[i], "have at least " << nrElements <<
801 " assign variables vs upper bound of " << upperBounds[i] <<
802 " for subterm " << subterms[i]);
803 DagNode* d;
804 if (nrElements == 0)
805 {
806 d = topSymbol->getIdentityDag();
807 //
808 // If this is the first time we use the identity element it is possible
809 // that it will not have its sort computed or ground flag set.
810 //
811 if (!(d->isGround()))
812 d->computeBaseSortForGroundSubterms();
813 }
814 else if (nrElements == 1 && selection[lastElement]->element[i] == 1)
815 {
816 d = freshVariables[lastElement];
817 inTheory = false; // we are assigning an alien term
818 }
819 else
820 {
821 ACU_DagNode* a = new ACU_DagNode(topSymbol, nrElements);
822 int pos = 0;
823 for (int j = 0; j < selectionSize; ++j)
824 {
825 int m = selection[j]->element[i];
826 if (m > 0)
827 {
828 a->argArray[pos].dagNode = freshVariables[j];
829 a->argArray[pos].multiplicity = m;
830 ++pos;
831 }
832 }
833 //
834 // There is no guarantee that the fresh variables that we generate are
835 // is the same order as needed for AC normal form - so we call this
836 // private member function to fix this without too much overhead.
837 //
838 a->sortAndUniquize();
839 Assert(a->isTree() == false, "Oops we got a tree! " << a);
840 d = a;
841 }
842
843 DagNode* subterm = subterms[i];
844 if (VariableDagNode* varSubterm = dynamic_cast<VariableDagNode*>(subterm))
845 {
846 //
847 // We need to handle unbound variable subterms that we unify with something in our
848 // theory ourself to avoid generating another problem in our theory.
849 //
850 VariableDagNode* repVar = varSubterm->lastVariableInChain(solution);
851 if (solution.value(repVar->getIndex()) == 0 && inTheory)
852 {
853 solution.unificationBind(repVar, d);
854 continue;
855 }
856 }
857 // cerr << "solving " << subterms[i] << " vs " << d << endl;
858 if (!(subterms[i]->computeSolvedForm(d, solution, pending)))
859 return false;
860 }
861 return true;
862 }
863