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