// Extract a plan for resatisfaction starting from the given source // constraints, usually a set of input constraints. This method // assumes that stay optimization is desired; the plan will contain // only constraints whose output variables are not stay. Constraints // that do no computation, such as stay and edit constraints, are // not included in the plan. // Details: The outputs of a constraint are marked when it is added // to the plan under construction. A constraint may be appended to // the plan when all its input variables are known. A variable is // known if either a) the variable is marked (indicating that has // been computed by a constraint appearing earlier in the plan), b) // the variable is 'stay' (i.e. it is a constant at plan execution // time), or c) the variable is not determined by any // constraint. The last provision is for past states of history // variables, which are not stay but which are also not computed by // any constraint. // Assume: sources are all satisfied. // public Plan makePlan(ArrayList sources) { int mark = newMark(); Plan plan = new Plan(); ArrayList todo = sources; while (!(todo.Count == 0)) { #if USE_STACK Constraint c = (Constraint)todo[todo.Count - 1]; todo.RemoveAt(todo.Count - 1); #else Constraint c = (Constraint)todo[todo.Count - 1]; todo.RemoveAt(0); #endif if (c.output().mark != mark && c.inputsKnown(mark)) { // not in plan already and eligible for inclusion plan.addConstraint(c); c.output().mark = mark; addConstraintsConsumingTo(c.output(), todo); } } return(plan); }
// Recompute the walkabout strengths and stay flags of all variables // downstream of the given constraint and recompute the actual // values of all variables whose stay flag is true. If a cycle is // detected, remove the given constraint and answer // false. Otherwise, answer true. // Details: Cycles are detected when a marked variable is // encountered downstream of the given constraint. The sender is // assumed to have marked the inputs of the given constraint with // the given mark. Thus, encountering a marked node downstream of // the output constraint means that there is a path from the // constraint's output to one of its inputs. // public Boolean addPropagate(Constraint c, int mark) { ArrayList todo = new ArrayList(); todo.Add(c); while (!(todo.Count == 0)) { #if USE_STACK Constraint d = (Constraint)todo[todo.Count - 1]; todo.RemoveAt(todo.Count - 1); #else Constraint d = (Constraint)todo[0]; todo.RemoveAt(0); #endif if (d.output().mark == mark) { incrementalRemove(c); return(false); } d.recalculate(); addConstraintsConsumingTo(d.output(), todo); } return(true); }
// The given variable has changed. Propagate new values downstream. public void propagateFrom(Variable v) { ArrayList todo = new ArrayList(); addConstraintsConsumingTo(v, todo); while (!(todo.Count == 0)) { #if USE_STACK Constraint c = (Constraint)todo[todo.Count - 1]; todo.RemoveAt(0); #else Constraint c = (Constraint)todo[todo.Count - 1]; todo.RemoveAt(0); #endif c.execute(); addConstraintsConsumingTo(c.output(), todo); } }
// Update the walkabout strengths and stay flags of all variables // downstream of the given constraint. Answer a collection of // unsatisfied constraints sorted in order of decreasing strength. // public ArrayList removePropagateFrom(Variable outvar) { outvar.determinedBy = null; outvar.walkStrength = Strength.weakest; outvar.stay = true; ArrayList unsatisfied = new ArrayList(); ArrayList todo = new ArrayList(); todo.Add(outvar); while (!(todo.Count == 0)) { #if USE_STACK Variable v = (Variable)todo[todo.Count - 1]; todo.RemoveAt(todo.Count - 1); #else Variable v = (Variable)todo[0]; todo.RemoveAt(0); #endif for (int i = 0; i < v.constraints.Count; ++i) { Constraint c = (Constraint)v.constraints[i]; if (!c.isSatisfied()) { unsatisfied.Add(c); } } Constraint determiningC = v.determinedBy; for (int i = 0; i < v.constraints.Count; ++i) { Constraint nextC = (Constraint)v.constraints[i]; if (nextC != determiningC && nextC.isSatisfied()) { nextC.recalculate(); todo.Add(nextC.output()); } } } return(unsatisfied); }
// Entry point for retracting a constraint. Remove the given // constraint and incrementally update the dataflow graph. // Details: Retracting the given constraint may allow some currently // unsatisfiable downstream constraint to be satisfied. We therefore collect // a list of unsatisfied downstream constraints and attempt to // satisfy each one in turn. This list is traversed by constraint // strength, strongest first, as a heuristic for avoiding // unnecessarily adding and then overriding weak constraints. // Assume: c is satisfied. // public void incrementalRemove(Constraint c) { Variable outvar = c.output(); c.markUnsatisfied(); c.removeFromGraph(); ArrayList unsatisfied = removePropagateFrom(outvar); Strength strength = Strength.required; do { for (int i = 0; i < unsatisfied.Count; ++i) { Constraint u = (Constraint)unsatisfied[i]; if (u.strength == strength) { incrementalAdd(u); } } strength = strength.nextWeaker(); } while (strength != Strength.weakest); }
// Entry point for retracting a constraint. Remove the given // constraint and incrementally update the dataflow graph. // Details: Retracting the given constraint may allow some currently // unsatisfiable downstream constraint to be satisfied. We therefore collect // a list of unsatisfied downstream constraints and attempt to // satisfy each one in turn. This list is traversed by constraint // strength, strongest first, as a heuristic for avoiding // unnecessarily adding and then overriding weak constraints. // Assume: c is satisfied. // public void incrementalRemove(Constraint c) { Variable outvar = c.output(); c.markUnsatisfied(); c.removeFromGraph(); ArrayList unsatisfied = removePropagateFrom(outvar); Strength strength = Strength.required; do { for (int i = 0; i < unsatisfied.Count; ++i) { Constraint u = (Constraint)unsatisfied[i]; if (u.strength == strength) incrementalAdd(u); } strength = strength.nextWeaker(); } while (strength != Strength.weakest); }