package aima.core.search.csp.inference;
import aima.core.search.csp.Assignment;
import aima.core.search.csp.CSP;
import aima.core.search.csp.Constraint;
import aima.core.search.csp.Variable;
import java.util.List;
/**
* Implements forward checking. Constraints which are not binary are ignored here.
* @author Ruediger Lunde
*/
public class ForwardCheckingStrategy<VAR extends Variable, VAL> implements InferenceStrategy<VAR, VAL> {
/** The CSP is not changed at the beginning. */
@Override
public InferenceLog apply(CSP csp) {
return InferenceLog.emptyLog();
}
/**
* Is called after the assignment has (recursively) been extended by a value assignment
* for <code>var</code>.
*/
@Override
public InferenceLog<VAR, VAL> apply(VAR var, Assignment<VAR, VAL> assignment, CSP<VAR, VAL> csp) {
DomainLog<VAR, VAL> log = new DomainLog<>();
for (Constraint<VAR, VAL> constraint : csp.getConstraints(var)) {
List<VAR> scope = constraint.getScope();
if (scope.size() == 2) {
for (VAR neighbor : constraint.getScope()) {
if (!assignment.contains(neighbor)) {
if (revise(neighbor, constraint, assignment, csp, log)) {
if (csp.getDomain(neighbor).isEmpty()) {
log.setEmptyDomainFound(true);
return log;
}
}
}
}
}
}
return log;
}
private boolean revise(VAR var, Constraint<VAR, VAL> constraint,
Assignment<VAR, VAL> assignment, CSP<VAR, VAL> csp, DomainLog<VAR, VAL> log) {
boolean revised = false;
for (VAL value : csp.getDomain(var)) {
assignment.add(var, value);
if (!constraint.isSatisfiedWith(assignment)) {
log.storeDomainFor(var, csp.getDomain(var));
csp.removeValueFromDomain(var, value);
revised = true;
}
assignment.remove(var);
}
return revised;
}
}