chocoteam/choco3 — pull request #105 by JLiangWaterloo (2013-05-18 23:08:58+00:00)
Title: Optimize and and or by removing an unecessary constraint.

I believe this optimization is valid and correct. "and" saves one constraint and replaces the sum variable with a constant. The "or" saves one constraint.

I've also implemented (but didn't commit) an alternative implementation for "and(Constraint...CONS)" below:

```java
public class AndConstraint extends Constraint> {

private final Constraint[] operands;

public AndConstraint(Constraint... operands) {
super(getVariables(operands), operands[0].getSolver());
this.operands = operands;
Propagator[] props = getPropagators(operands);
PropAnd reifProp = new PropAnd(props);
props = ArrayUtils.append(new Propagator[]{reifProp}, props);
setPropagators(props);
for (Propagator prop : props) {
prop.setReifiedSilent();
}
}

private static Variable[] getVariables(Constraint[] operands) {
Variable[][] variables = new Variable[operands.length][];
for (int i = 0; i < variables.length; i++) {
variables[i] = operands[i].getVariables();
}
return ArrayUtils.append(variables);
}

private static Propagator[] getPropagators(Constraint[] operands) {
Propagator[][] propagators = new Propagator[operands.length][];
for (int i = 0; i < propagators.length; i++) {
propagators[i] = operands[i].getPropagators();
}
return ArrayUtils.append(propagators);
}

@Override
public ESat isSatisfied() {
boolean allTrue = true;
for (Constraint operand : operands) {
switch (operand.isSatisfied()) {
case FALSE:
return ESat.FALSE;
case UNDEFINED:
allTrue = false;
}
}
return allTrue ? ESat.TRUE : ESat.UNDEFINED;
}

@Override
public ESat isEntailed() {
boolean allTrue = true;
for (Constraint operand : operands) {
switch (operand.isEntailed()) {
case FALSE:
return ESat.FALSE;
case UNDEFINED:
allTrue = false;
}
}
return allTrue ? ESat.TRUE : ESat.UNDEFINED;
}

@Override
public String toString() {
throw new UnsupportedOperationException("TODO");
}
}
```
```java
public class PropAnd extends Propagator {

private final Propagator[] operands;

public PropAnd(Propagator[] operands) {
super(new Variable[]{
operands[0].getSolver().ZERO // Don't know what else to put here.
}, PropagatorPriority.LINEAR);
this.operands = operands;
}

@Override
public int getPropagationConditions(int vIdx) {
return EventType.ALL_FINE_EVENTS.mask;
}

@Override
public void propagate(int evtmask) throws ContradictionException {
for (Propagator operand : operands) {
assert (operand.isReifiedAndSilent());
operand.setReifiedTrue();
operand.propagate(EventType.FULL_PROPAGATION.strengthened_mask);
solver.getEngine().onPropagatorExecution(operand);
}
}

@Override
public void propagate(int idxVarInProp, int mask) throws ContradictionException {
forcePropagate(EventType.FULL_PROPAGATION);
}

@Override
public void explain(Deduction d, Explanation e) {
throw new UnsupportedOperationException("TODO");
}

@Override
public ESat isEntailed() {
boolean allTrue = true;
for (Propagator operand : operands) {
switch (operand.isEntailed()) {
case FALSE:
return ESat.FALSE;
case UNDEFINED:
allTrue = false;
}
}
return allTrue ? ESat.TRUE : ESat.UNDEFINED;
}

@Override
public String toString() {
throw new UnsupportedOperationException("TODO");
}
}
```

The implementation is straightforward and hopefully correct. The current "and(Constraint...CONS)" requires 1 reified var, 1 not view var, and 1 opposite constraint per CON parameter. The dedicated AndConstraint should be more economical but I'm doubting the performance would be that big of a difference though.