package aima.core.search.csp.inference; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import aima.core.search.csp.CSP; import aima.core.search.csp.Domain; import aima.core.search.csp.Variable; import aima.core.util.datastructure.Pair; /** * Provides information which might be useful for a caller of a constraint * propagation algorithm. It maintains old domains for variables and provides * means to restore the initial state of the CSP (before domain reduction * started). Additionally, a flag indicates whether an empty domain has been * found during propagation. * * @author Ruediger Lunde * */ public class DomainLog<VAR extends Variable, VAL> implements InferenceLog<VAR, VAL> { private List<Pair<VAR, Domain<VAL>>> savedDomains; private HashSet<VAR> affectedVariables; private boolean emptyDomainObserved; public DomainLog() { savedDomains = new ArrayList<>(); affectedVariables = new HashSet<>(); } public void clear() { savedDomains.clear(); affectedVariables.clear(); } /** * Stores the specified domain for the specified variable if a domain has * not yet been stored for the variable. */ public void storeDomainFor(VAR var, Domain<VAL> domain) { if (!affectedVariables.contains(var)) { savedDomains.add(new Pair<>(var, domain)); affectedVariables.add(var); } } public void setEmptyDomainFound(boolean b) { emptyDomainObserved = b; } /** * Can be called after all domain information has been collected to reduce * storage consumption. * * @return this object, after removing one hashtable. */ public DomainLog<VAR, VAL> compactify() { affectedVariables = null; return this; } @Override public boolean isEmpty() { return savedDomains.isEmpty(); } @Override public void undo(CSP<VAR, VAL> csp) { for (Pair<VAR, Domain<VAL>> pair : getSavedDomains()) csp.setDomain(pair.getFirst(), pair.getSecond()); } @Override public boolean inconsistencyFound() { return emptyDomainObserved; } private List<Pair<VAR, Domain<VAL>>> getSavedDomains() { return savedDomains; } public String toString() { StringBuilder result = new StringBuilder(); for (Pair<VAR, Domain<VAL>> pair : savedDomains) result.append(pair.getFirst()).append("=").append(pair.getSecond()).append(" "); if (emptyDomainObserved) result.append("!"); return result.toString(); } }