/** * Template method, which can be configured by overriding the three * primitive operations below. */ private Assignment recursiveBackTrackingSearch(CSP csp, Assignment assignment) { Assignment result = null; if (assignment.isComplete(csp.getVariables())) { result = assignment; } else { Variable var = selectUnassignedVariable(assignment, csp); foreach (Object value in orderDomainValues(var, assignment, csp)) { assignment.setAssignment(var, value); fireStateChanged(assignment, csp); if (assignment.isConsistent(csp.getConstraints(var))) { DomainRestoreInfo info = inference(var, assignment, csp); if (!info.isEmpty()) fireStateChanged(csp); if (!info.isEmptyDomainFound()) { result = recursiveBackTrackingSearch(csp, assignment); if (result != null) break; } info.restoreDomains(csp); } assignment.removeAssignment(var); } } return result; }
/** * Makes a CSP consisting of binary constraints arc-consistent. * @return An object which indicates success/failure and contains * data to undo the operation. */ public DomainRestoreInfo reduceDomains(CSP csp) { DomainRestoreInfo result = new DomainRestoreInfo(); FIFOQueue<Variable> queue = new FIFOQueue<Variable>(); foreach (Variable var in csp.getVariables()) queue.Add(var); reduceDomains(queue, csp, result); return result.compactify(); }
private Assignment generateRandomAssignment(CSP csp) { Assignment assignment = new Assignment(); foreach (Variable var in csp.getVariables()) { Object randomValue = Util.selectRandomlyFromList(csp.getDomain(var) .asList()); assignment.setAssignment(var, randomValue); } return assignment; }
private List<Variable> getConflictedVariables(Assignment assignment, CSP csp) { List<Variable> result = new List<Variable>(); foreach (Constraint constraint in csp.getConstraints()) { if (!constraint.isSatisfiedWith(assignment)) foreach (Variable var in constraint.getScope()) if (!result.contains(var)) result.Add(var); } return result; }
/** * Starts with a constraint propagation if AC-3 is enabled and then calls * the super class implementation. */ public Assignment solve(CSP csp) { if (inferenceStrategy == Inference.AC3) { DomainRestoreInfo info = new AC3Strategy().reduceDomains(csp); if (!info.isEmpty()) { fireStateChanged(csp); if (info.isEmptyDomainFound()) return null; } } return super.solve(csp); }
private bool revise(Variable var, Constraint constraint, Assignment assignment, CSP csp, DomainRestoreInfo info) { bool revised = false; foreach (Object value in csp.getDomain(var)) { assignment.setAssignment(var, value); if (!constraint.isSatisfiedWith(assignment)) { info.storeDomainFor(var, csp.getDomain(var)); csp.removeValueFromDomain(var, value); revised = true; } assignment.removeAssignment(var); } return(revised); }
/** * Primitive operation, selecting a not yet assigned variable. */ protected override Variable selectUnassignedVariable(Assignment assignment, CSP csp) { switch (selectionStrategy) { case MRV: return applyMRVHeuristic(csp, assignment).get(0); case MRV_DEG: List<Variable> vars = applyMRVHeuristic(csp, assignment); return applyDegreeHeuristic(vars, assignment, csp).get(0); default: foreach (Variable var in csp.getVariables()) { if (!(assignment.hasAssignmentFor(var))) return var; } } return null; }
private List <Variable> getConflictedVariables(Assignment assignment, CSP csp) { List <Variable> result = new List <Variable>(); foreach (Constraint constraint in csp.getConstraints()) { if (!constraint.isSatisfiedWith(assignment)) { foreach (Variable var in constraint.getScope()) { if (!result.contains(var)) { result.Add(var); } } } } return(result); }
private int countLostValues(Variable var, Object value, CSP csp) { int result = 0; Assignment assignment = new Assignment(); assignment.setAssignment(var, value); foreach (Constraint constraint in csp.getConstraints(var)) { Variable neighbor = csp.getNeighbor(var, constraint); foreach (Object nValue in csp.getDomain(neighbor)) { assignment.setAssignment(neighbor, nValue); if (!constraint.isSatisfiedWith(assignment)) { ++result; } } } return(result); }
/** * Reduces the domain of the specified variable to the specified * value and reestablishes arc-consistency. It is assumed that the * provided CSP is arc-consistent before the call. * @return An object which indicates success/failure and contains * data to undo the operation. */ public DomainRestoreInfo reduceDomains(Variable var, Object value, CSP csp) { DomainRestoreInfo result = new DomainRestoreInfo(); Domain domain = csp.getDomain(var); if (domain.contains(value)) { if (domain.Count > 1) { FIFOQueue<Variable> queue = new FIFOQueue<Variable>(); queue.Add(var); result.storeDomainFor(var, domain); csp.setDomain(var, new Domain(new Object[] { value })); reduceDomains(queue, csp, result); } } else { result.setEmptyDomainFound(true); } return result.compactify(); }
public Assignment solve(CSP csp) { Assignment assignment = generateRandomAssignment(csp); fireStateChanged(assignment, csp); for (int i = 0; i < maxSteps; i++) { if (assignment.isSolution(csp)) { return assignment; } else { List<Variable> vars = getConflictedVariables(assignment, csp); Variable var = Util.selectRandomlyFromList(vars); Object value = getMinConflictValueFor(var, assignment, csp); assignment.setAssignment(var, value); fireStateChanged(assignment, csp); } } return null; }
/** * Primitive operation, selecting a not yet assigned variable. */ protected override Variable selectUnassignedVariable(Assignment assignment, CSP csp) { switch (selectionStrategy) { case MRV: return(applyMRVHeuristic(csp, assignment).get(0)); case MRV_DEG: List <Variable> vars = applyMRVHeuristic(csp, assignment); return(applyDegreeHeuristic(vars, assignment, csp).get(0)); default: foreach (Variable var in csp.getVariables()) { if (!(assignment.hasAssignmentFor(var))) { return(var); } } } return(null); }
public Assignment solve(CSP csp) { Assignment assignment = generateRandomAssignment(csp); fireStateChanged(assignment, csp); for (int i = 0; i < maxSteps; i++) { if (assignment.isSolution(csp)) { return(assignment); } else { List <Variable> vars = getConflictedVariables(assignment, csp); Variable var = Util.selectRandomlyFromList(vars); Object value = getMinConflictValueFor(var, assignment, csp); assignment.setAssignment(var, value); fireStateChanged(assignment, csp); } } return(null); }
/** * Reduces the domain of the specified variable to the specified * value and reestablishes arc-consistency. It is assumed that the * provided CSP is arc-consistent before the call. * @return An object which indicates success/failure and contains * data to undo the operation. */ public DomainRestoreInfo reduceDomains(Variable var, Object value, CSP csp) { DomainRestoreInfo result = new DomainRestoreInfo(); Domain domain = csp.getDomain(var); if (domain.contains(value)) { if (domain.Count > 1) { FIFOQueue <Variable> queue = new FIFOQueue <Variable>(); queue.Add(var); result.storeDomainFor(var, domain); csp.setDomain(var, new Domain(new Object[] { value })); reduceDomains(queue, csp, result); } } else { result.setEmptyDomainFound(true); } return(result.compactify()); }
/** * Template method, which can be configured by overriding the three * primitive operations below. */ private Assignment recursiveBackTrackingSearch(CSP csp, Assignment assignment) { Assignment result = null; if (assignment.isComplete(csp.getVariables())) { result = assignment; } else { Variable var = selectUnassignedVariable(assignment, csp); foreach (Object value in orderDomainValues(var, assignment, csp)) { assignment.setAssignment(var, value); fireStateChanged(assignment, csp); if (assignment.isConsistent(csp.getConstraints(var))) { DomainRestoreInfo info = inference(var, assignment, csp); if (!info.isEmpty()) { fireStateChanged(csp); } if (!info.isEmptyDomainFound()) { result = recursiveBackTrackingSearch(csp, assignment); if (result != null) { break; } } info.restoreDomains(csp); } assignment.removeAssignment(var); } } return(result); }
// ////////////////////////////////////////////////////////////// // heuristics for selecting the next unassigned variable and domain ordering /** : the minimum-remaining-values heuristic. */ private List <Variable> applyMRVHeuristic(CSP csp, Assignment assignment) { List <Variable> result = new List <Variable>(); int mrv = int.MAX_VALUE; foreach (Variable var in csp.getVariables()) { if (!assignment.hasAssignmentFor(var)) { int num = csp.getDomain(var).Count; if (num <= mrv) { if (num < mrv) { result.clear(); mrv = num; } result.Add(var); } } } return(result); }
private void reduceDomains(FIFOQueue <Variable> queue, CSP csp, DomainRestoreInfo info) { while (!queue.isEmpty()) { Variable var = queue.pop(); foreach (Constraint constraint in csp.getConstraints(var)) { if (constraint.getScope().Count == 2) { Variable neighbor = csp.getNeighbor(var, constraint); if (revise(neighbor, var, constraint, csp, info)) { if (csp.getDomain(neighbor).isEmpty()) { info.setEmptyDomainFound(true); return; } queue.push(neighbor); } } } } }
public void restoreDomains(CSP csp) { foreach (Pair<Variable, Domain> pair in getSavedDomains()) csp.setDomain(pair.getFirst(), pair.getSecond()); }
public abstract Assignment solve(CSP csp);
protected void fireStateChanged(Assignment assignment, CSP csp) { foreach (CSPStateListener listener in listeners) listener.stateChanged(assignment.copy(), csp.copyDomains()); }
protected void fireStateChanged(CSP csp) { foreach (CSPStateListener listener in listeners) listener.stateChanged(csp.copyDomains()); }
/** * Returns true if this assignment is consistent as well as complete with * respect to the given CSP. */ public bool isSolution(CSP csp) { return isConsistent(csp.getConstraints()) && isComplete(csp.getVariables()); }
/** : the degree heuristic. */ private List<Variable> applyDegreeHeuristic(List<Variable> vars, Assignment assignment, CSP csp) { List<Variable> result = new List<Variable>(); int maxDegree = int.MIN_VALUE; foreach (Variable var in vars) { int degree = 0; foreach (Constraint constraint in csp.getConstraints(var)) { Variable neighbor = csp.getNeighbor(var, constraint); if (!assignment.hasAssignmentFor(neighbor) && csp.getDomain(neighbor).Count > 1) ++degree; } if (degree >= maxDegree) { if (degree > maxDegree) { result.clear(); maxDegree = degree; } result.Add(var); } } return result; }
private Object getMinConflictValueFor(Variable var, Assignment assignment, CSP csp) { List<Constraint> constraints = csp.getConstraints(var); Assignment duplicate = assignment.copy(); int minConflict = int.MAX_VALUE; List<Object> resultCandidates = new List<Object>(); foreach (Object value in csp.getDomain(var)) { duplicate.setAssignment(var, value); int currConflict = countConflicts(duplicate, constraints); if (currConflict <= minConflict) { if (currConflict < minConflict) { resultCandidates.clear(); minConflict = currConflict; } resultCandidates.Add(value); } } if (!resultCandidates.isEmpty()) return Util.selectRandomlyFromList(resultCandidates); else return null; }
/** * Primitive operation, ordering the domain values of the specified * variable. This default implementation just takes the default order * provided by the CSP. */ protected Iterable? orderDomainValues(Variable var, Assignment assignment, CSP csp) { return csp.getDomain(var); }
/** * Returns true if this assignment is consistent as well as complete with * respect to the given CSP. */ public bool isSolution(CSP csp) { return(isConsistent(csp.getConstraints()) && isComplete(csp.getVariables())); }
/** * Primitive operation, ordering the domain values of the specified * variable. This default implementation just takes the default order * provided by the CSP. */ protected Iterable?orderDomainValues(Variable var, Assignment assignment, CSP csp) { return(csp.getDomain(var)); }
/** * Primitive operation, selecting a not yet assigned variable. This default * implementation just selects the first in the ordered list of variables * provided by the CSP. */ protected Variable selectUnassignedVariable(Assignment assignment, CSP csp) { foreach (Variable var in csp.getVariables()) { if (!(assignment.hasAssignmentFor(var))) return var; } return null; }
private bool revise(Variable var, Constraint constraint, Assignment assignment, CSP csp, DomainRestoreInfo info) { bool revised = false; foreach (Object value in csp.getDomain(var)) { assignment.setAssignment(var, value); if (!constraint.isSatisfiedWith(assignment)) { info.storeDomainFor(var, csp.getDomain(var)); csp.removeValueFromDomain(var, value); revised = true; } assignment.removeAssignment(var); } return revised; }
public Assignment solve(CSP csp) { return recursiveBackTrackingSearch(csp, new Assignment()); }
/** * Primitive operation, which tries to prune out values from the CSP which * are not possible anymore when extending the given assignment to a * solution. This default implementation just leaves the original CSP as it * is. * * @return An object which provides informations about (1) whether changes * have been performed, (2) possibly inferred empty domains , and * (3) how to restore the domains. */ protected DomainRestoreInfo inference(Variable var, Assignment assignment, CSP csp) { return new DomainRestoreInfo().compactify(); }
/** : the least constraining value heuristic. */ private List<Object> applyLeastConstrainingValueHeuristic(Variable var, CSP csp) { List<Pair<Object, int>> pairs = new List<Pair<Object, int>>(); foreach (Object value in csp.getDomain(var)) { int num = countLostValues(var, value, csp); pairs.Add(new Pair<Object, int>(value, num)); } // TODO //Collections.sort(pairs, new Comparator<Pair<Object, int>>() { // public int compare(Pair<Object, int> o1, // Pair<Object, int> o2) { // return o1.getSecond() < o2.getSecond() ? -1 // : o1.getSecond() > o2.getSecond() ? 1 : 0; // } //}); List<Object> result = new List<Object>(); foreach (Pair<Object, int> pair in pairs) result.Add(pair.getFirst()); return result; }
private bool revise(Variable xi, Variable xj, Constraint constraint, CSP csp, DomainRestoreInfo info) { bool revised = false; Assignment assignment = new Assignment(); foreach (Object iValue in csp.getDomain(xi)) { assignment.setAssignment(xi, iValue); bool consistentExtensionFound = false; foreach (Object jValue in csp.getDomain(xj)) { assignment.setAssignment(xj, jValue); if (constraint.isSatisfiedWith(assignment)) { consistentExtensionFound = true; break; } } if (!consistentExtensionFound) { info.storeDomainFor(xi, csp.getDomain(xi)); csp.removeValueFromDomain(xi, iValue); revised = true; } } return revised; }
// ////////////////////////////////////////////////////////////// // heuristics for selecting the next unassigned variable and domain ordering /** : the minimum-remaining-values heuristic. */ private List<Variable> applyMRVHeuristic(CSP csp, Assignment assignment) { List<Variable> result = new List<Variable>(); int mrv = int.MAX_VALUE; foreach (Variable var in csp.getVariables()) { if (!assignment.hasAssignmentFor(var)) { int num = csp.getDomain(var).Count; if (num <= mrv) { if (num < mrv) { result.clear(); mrv = num; } result.Add(var); } } } return result; }
// ////////////////////////////////////////////////////////////// // inference algorithms /** : forward checking. */ private DomainRestoreInfo doForwardChecking(Variable var, Assignment assignment, CSP csp) { DomainRestoreInfo result = new DomainRestoreInfo(); foreach (Constraint constraint in csp.getConstraints(var)) { List<Variable> scope = constraint.getScope(); if (scope.Count == 2) { foreach (Variable neighbor in constraint.getScope()) { if (!assignment.hasAssignmentFor(neighbor)) { if (revise(neighbor, constraint, assignment, csp, result)) { if (csp.getDomain(neighbor).isEmpty()) { result.setEmptyDomainFound(true); return result; } } } } } } return result; }
/** * Returns a copy which contains a copy of the domains list and is in all * other aspects a flat copy of this. */ public CSP copyDomains() { CSP result = new CSP(); result.variables = variables; result.domains = new List<Domain>(domains.Count); result.domains.AddRange(domains); result.constraints = constraints; result.varIndexHash = varIndexHash; result.cnet = cnet; return result; }
private int countLostValues(Variable var, Object value, CSP csp) { int result = 0; Assignment assignment = new Assignment(); assignment.setAssignment(var, value); foreach (Constraint constraint in csp.getConstraints(var)) { Variable neighbor = csp.getNeighbor(var, constraint); foreach (Object nValue in csp.getDomain(neighbor)) { assignment.setAssignment(neighbor, nValue); if (!constraint.isSatisfiedWith(assignment)) { ++result; } } } return result; }
/** * Primitive operation, which tries to prune out values from the CSP which * are not possible anymore when extending the given assignment to a * solution. * * @return An object which provides informations about (1) whether changes * have been performed, (2) possibly inferred empty domains , and * (3) how to restore the domains. */ protected override DomainRestoreInfo inference(Variable var, Assignment assignment, CSP csp) { switch (inferenceStrategy) { case FORWARD_CHECKING: return doForwardChecking(var, assignment, csp); case AC3: return new AC3Strategy().reduceDomains(var, assignment .getAssignment(var), csp); default: return new DomainRestoreInfo().compactify(); } }
private void reduceDomains(FIFOQueue<Variable> queue, CSP csp, DomainRestoreInfo info) { while (!queue.isEmpty()) { Variable var = queue.pop(); foreach (Constraint constraint in csp.getConstraints(var)) { if (constraint.getScope().Count == 2) { Variable neighbor = csp.getNeighbor(var, constraint); if (revise(neighbor, var, constraint, csp, info)) { if (csp.getDomain(neighbor).isEmpty()) { info.setEmptyDomainFound(true); return; } queue.push(neighbor); } } } } }
/** * Primitive operation, which tries to prune out values from the CSP which * are not possible anymore when extending the given assignment to a * solution. This default implementation just leaves the original CSP as it * is. * * @return An object which provides informations about (1) whether changes * have been performed, (2) possibly inferred empty domains , and * (3) how to restore the domains. */ protected DomainRestoreInfo inference(Variable var, Assignment assignment, CSP csp) { return(new DomainRestoreInfo().compactify()); }
/** * Primitive operation, ordering the domain values of the specified * variable. */ protected override Iterable? orderDomainValues(Variable var, Assignment assignment, CSP csp) { if (!isLCVHeuristicEnabled) { return csp.getDomain(var); } else { return applyLeastConstrainingValueHeuristic(var, csp); } }
public Assignment solve(CSP csp) { return(recursiveBackTrackingSearch(csp, new Assignment())); }