/** * Makes a CSP consisting of binary constraints arc-consistent. * * @return An object which indicates success/failure and contains data to * undo the operation. */ public IInferenceLog <VAR, VAL> apply(CSP <VAR, VAL> csp) { ICollection <VAR> queue = CollectionFactory.CreateFifoQueueNoDuplicates <VAR>(); queue.AddAll(csp.getVariables()); DomainLog <VAR, VAL> log = new DomainLog <VAR, VAL>(); reduceDomains(queue, csp, log); return(log.compactify()); }
/** * Removes all values from the domain of <code>var</code> which are not consistent with * <code>constraint</code> and <code>assignment</code>. Modifies the domain log accordingly so * that all changes can be undone later on. */ private bool revise(VAR var, IConstraint <VAR, VAL> constraint, Assignment <VAR, VAL> assignment, CSP <VAR, VAL> csp, DomainLog <VAR, VAL> log) { bool revised = false; foreach (VAL value in 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); }
/** * For efficiency reasons the queue manages updated variables vj whereas the original AC3 * manages neighbor arcs (vi, vj). Constraints which are not binary are ignored. */ private void reduceDomains(ICollection <VAR> queue, CSP <VAR, VAL> csp, DomainLog <VAR, VAL> log) { while (!queue.IsEmpty()) { VAR var = queue.Pop(); foreach (IConstraint <VAR, VAL> constraint in csp.getConstraints(var)) { VAR neighbor = csp.getNeighbor(var, constraint); if (neighbor != null && revise(neighbor, var, constraint, csp, log)) { if (csp.getDomain(neighbor).isEmpty()) { log.setEmptyDomainFound(true); return; } queue.Add(neighbor); } } } }
/** * Removes all values from the domains of the neighbor variables of <code>var</code> in the * constraint graph which are not consistent with the new value for <code>var</code>. * It is called after <code>assignment</code> has (recursively) been extended with a value * assignment for <code>var</code>. */ public IInferenceLog <VAR, VAL> apply(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment, VAR var) { DomainLog <VAR, VAL> log = new DomainLog <VAR, VAL>(); foreach (IConstraint <VAR, VAL> constraint in csp.getConstraints(var)) { VAR neighbor = csp.getNeighbor(var, constraint); if (neighbor != null && !assignment.contains(neighbor)) { if (revise(neighbor, constraint, assignment, csp, log)) { if (csp.getDomain(neighbor).isEmpty()) { log.setEmptyDomainFound(true); return(log); } } } } return(log); }
/** * Reduces the domain of the specified variable to the specified value and * reestablishes arc-consistency. It is assumed that the provided CSP was * arc-consistent before the call. * * @return An object which indicates success/failure and contains data to * undo the operation. */ public IInferenceLog <VAR, VAL> apply(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment, VAR var) { Domain <VAL> domain = csp.getDomain(var); VAL value = assignment.getValue(var); if (!domain.contains(value)) { throw new Exception("domain does not contain value"); } DomainLog <VAR, VAL> log = new DomainLog <VAR, VAL>(); if (domain.size() > 1) { ICollection <VAR> queue = CollectionFactory.CreateFifoQueue <VAR>(); queue.Add(var); log.storeDomainFor(var, domain); csp.setDomain(var, new Domain <VAL>(value)); reduceDomains(queue, csp, log); } return(log.compactify()); }
/** * Establishes arc-consistency for (xi, xj). * @return value true if the domain of xi was reduced. */ private bool revise(VAR xi, VAR xj, IConstraint <VAR, VAL> constraint, CSP <VAR, VAL> csp, DomainLog <VAR, VAL> log) { Domain <VAL> currDomain = csp.getDomain(xi); ICollection <VAL> newValues = CollectionFactory.CreateQueue <VAL>(); Assignment <VAR, VAL> assignment = new Assignment <VAR, VAL>(); foreach (VAL vi in currDomain) { assignment.add(xi, vi); foreach (VAL vj in csp.getDomain(xj)) { assignment.add(xj, vj); if (constraint.isSatisfiedWith(assignment)) { newValues.Add(vi); break; } } } if (newValues.Size() < currDomain.size()) { log.storeDomainFor(xi, csp.getDomain(xi)); csp.setDomain(xi, new Domain <VAL>(newValues)); return(true); } return(false); }