package jrummikub.ai.fdsolver.constraint; import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.concurrent.locks.Condition; import jrummikub.ai.fdsolver.Constraint; import jrummikub.ai.fdsolver.Propagator; import jrummikub.ai.fdsolver.Satisfiability; import jrummikub.ai.fdsolver.Var; public class IfConstraint extends Constraint { Var condition; Constraint child; Collection> vars; boolean negateCond; public IfConstraint(boolean negateCond, Var condition, Constraint child) { this.condition = condition; this.child = child; this.negateCond = negateCond; vars = new ArrayList>(); vars.addAll(child.getWatchedVars()); vars.add(condition); } @Override public Collection> getWatchedVars() { return vars; } private class IfPropagator implements Propagator { Propagator child; Collection> vars; public IfPropagator(Propagator child) { this.child = child; vars = new ArrayList>(); vars.addAll(child.getWatchedVars()); vars.add(condition); } @Override public Collection> getWatchedVars() { return vars; } @Override public void propagate() { if(condition.getRange().contains(negateCond)) { return; } child.propagate(); } } private class FailPropagator implements Propagator { @Override public Collection> getWatchedVars() { return child.getWatchedVars(); } @Override public void propagate() { if (!child.isSatisfiable()) { condition.invalidate(!negateCond); } } } @Override public Collection getPropagators(boolean negate) { List props = new ArrayList(); if (negate) { props.add(new FilterPropagator(new Filter() { @Override public boolean accept(Boolean value) { return value ^ negateCond; } }, condition)); props.addAll(child.getPropagators(true)); } else { for (Propagator p : child.getPropagators(false)) { props.add(new IfPropagator(p)); } props.add(new FailPropagator()); } return props; } @Override public Satisfiability getSatisfiability() { if (condition.getRange().contains(negateCond)) { if (condition.getRange().size() == 1) { return Satisfiability.TAUT; } else { if (child.getSatisfiability() == Satisfiability.TAUT) { return Satisfiability.TAUT; } else { return Satisfiability.SAT; } } } return child.getSatisfiability(); } }