/** * After a value is assigned: explanations of other values of the value's variable are reset (to * contain only the assigned value), propagation over the assigned variable takes place. */ @Override public void afterAssigned(long iteration, T value) { sLogger.debug("After assign " + value.variable().getName() + " = " + value.getName()); iIteration = iteration; if (!isGood(value)) { sLogger.warn( value.variable().getName() + " = " + value.getName() + " -- not good value assigned (noGood:" + noGood(value) + ")"); setGood(value); } Set<T> noGood = new HashSet<T>(1); noGood.add(value); List<T> queue = new ArrayList<T>(); for (Iterator<T> i = value.variable().values().iterator(); i.hasNext(); ) { T anotherValue = i.next(); if (anotherValue.equals(value) || !isGood(anotherValue)) continue; setNoGood(anotherValue, noGood); queue.add(anotherValue); } propagate(queue); }
@Override public double getPerturbationPenalty( Assignment<V, T> assignment, Model<V, T> model, T selectedValue, Collection<T> conflicts) { double penalty = 0; Set<T> violations = (getViolatedInitials() == null ? null : getViolatedInitials().getViolatedInitials(selectedValue)); if (violations != null) for (T aValue : violations) { if (assignment.getValue(aValue.variable()) == null) penalty += getPenaltyA(assignment, selectedValue, aValue); } if (conflicts != null) { for (T conflictValue : conflicts) { T initialValue = conflictValue.variable().getInitialAssignment(); if (initialValue != null) { if (initialValue.equals(conflictValue)) penalty += getPenaltyB(assignment, selectedValue, conflictValue, initialValue); else { if (violations == null || !violations.contains(initialValue)) penalty += getPenaltyC(assignment, selectedValue, conflictValue, initialValue); } } } } if (selectedValue.variable().getInitialAssignment() != null && !selectedValue.equals(selectedValue.variable().getInitialAssignment())) penalty += getPenaltyD(assignment, selectedValue, selectedValue.variable().getInitialAssignment()); return penalty; }
/** sets value's explanation */ public void setNoGood(T value, Set<T> reason) { sLogger.debug( " -- set nogood " + value.variable().getName() + " = " + value.getName() + "(expl:" + expl2str(reason) + ")"); if (value.equals(value.variable().getAssignment())) { try { throw new Exception( "An assigned value " + value.variable().getName() + " = " + value.getName() + " become no good (noGood:" + reason + ")!!"); } catch (Exception e) { sLogger.warn(e.getMessage(), e); } checkExpl(reason); printAssignments(); } Set<T> noGood = noGood(value); if (noGood != null) for (T v : noGood) removeSupport(v.variable(), value); value.setExtra(reason); for (T aValue : reason) { addSupport(aValue.variable(), value); } goodnessChanged(value); }
/** notification that a nogood value becomes good or vice versa */ private void goodnessChanged(T value) { if (isGood(value)) { goodValues(value.variable()).add(value); } else { goodValues(value.variable()).remove(value); } }
/** sets value to be good */ protected void setGood(T value) { sLogger.debug(" -- set good " + value.variable().getName() + " = " + value.getName()); Set<T> noGood = noGood(value); if (noGood != null) for (T v : noGood) removeSupport(v.variable(), value); value.setExtra(null); goodnessChanged(value); }
/** * After a value is unassigned: explanations of all values of unassigned variable are recomputed * ({@link Value#conflicts()}), propagation undo over the unassigned variable takes place. */ @Override public void afterUnassigned(long iteration, T value) { sLogger.debug("After unassign " + value.variable().getName() + " = " + value.getName()); iIteration = iteration; if (!isGood(value)) sLogger.error( value.variable().getName() + " = " + value.getName() + " -- not good value unassigned (noGood:" + noGood(value) + ")"); List<T> back = new ArrayList<T>(supportValues(value.variable())); for (T aValue : back) { if (aValue.variable().getAssignment() != null) { Set<T> noGood = new HashSet<T>(1); noGood.add(aValue.variable().getAssignment()); setNoGood(aValue, noGood); } else setGood(aValue); } List<T> queue = new ArrayList<T>(); for (T aValue : back) { if (!isGood(aValue) || revise(aValue)) queue.add(aValue); } propagate(queue); }
public boolean revise(T value) { sLogger.debug(" -- revise " + value.variable().getName() + " = " + value.getName()); for (Constraint<V, T> constraint : value.variable().hardConstraints()) { if (!contains(constraint)) continue; if (revise(constraint, value)) return true; } return false; }
public void propagate(Constraint<V, T> constraint, T noGoodValue, List<T> queue) { for (V aVariable : constraint.variables()) { if (aVariable.equals(noGoodValue.variable())) continue; for (Iterator<T> j = aVariable.values().iterator(); j.hasNext(); ) { T aValue = j.next(); if (isGood(aValue) && constraint.isConsistent(noGoodValue, aValue) && !hasSupport(constraint, aValue, noGoodValue.variable())) { setNoGood(aValue, explanation(constraint, aValue, noGoodValue.variable())); queue.add(aValue); } } } }
/** * Before a value is unassigned: until the value is inconsistent with the current solution, an * assignment from its explanation is picked and unassigned. */ @Override public void beforeAssigned(long iteration, T value) { if (value == null) return; sLogger.debug("Before assign " + value.variable().getName() + " = " + value.getName()); iIteration = iteration; while (!isGood(value) && !noGood(value).isEmpty()) { if (iDbt) sLogger.warn( "Going to assign a no-good value " + value + " (noGood:" + noGood(value) + ")."); T noGoodValue = noGood(value).iterator().next(); noGoodValue.variable().unassign(iteration); } if (!isGood(value)) { sLogger.warn("Going to assign a bad value " + value + " with empty no-good."); } }
private void checkExpl(Set<T> expl) { sLogger.debug(" -- checking explanation: " + expl2str(expl)); for (Iterator<T> i = expl.iterator(); i.hasNext(); ) { T value = i.next(); if (!value.equals(value.variable().getAssignment())) { if (value.variable().getAssignment() == null) sLogger.warn(" -- variable " + value.variable().getName() + " unassigned"); else sLogger.warn( " -- variable " + value.variable().getName() + " assigned to a different value " + value.variable().getAssignment().getName()); } } }
private String expl2str(Set<T> expl) { StringBuffer sb = new StringBuffer("["); for (Iterator<T> i = expl.iterator(); i.hasNext(); ) { T value = i.next(); sb.append(value.variable().getName() + "=" + value.getName()); if (i.hasNext()) sb.append(", "); } sb.append("]"); return sb.toString(); }
public boolean revise(Constraint<V, T> constraint, T value) { for (V aVariable : constraint.variables()) { if (aVariable.equals(value.variable())) continue; if (!hasSupport(constraint, value, aVariable)) { setNoGood(value, explanation(constraint, value, aVariable)); return true; } } return false; }
public void propagate(List<T> queue) { int idx = 0; while (queue.size() > idx) { T value = queue.get(idx++); sLogger.debug( " -- propagate " + value.variable().getName() + " = " + value.getName() + " (noGood:" + noGood(value) + ")"); if (goodValues(value.variable()).isEmpty()) { sLogger.info("Empty domain detected for variable " + value.variable().getName()); continue; } for (Constraint<V, T> constraint : value.variable().hardConstraints()) { if (!contains(constraint)) continue; propagate(constraint, value, queue); } } }