private ISet <VAR> getConflictedVariables(Assignment <VAR, VAL> assignment, CSP <VAR, VAL> csp) { ISet <VAR> result = CollectionFactory.CreateSet <VAR>(); foreach (IConstraint <VAR, VAL> constraint in csp.getConstraints()) { if (!constraint.isSatisfiedWith(assignment)) { foreach (VAR var in constraint.getScope()) { if (!result.Contains(var)) { result.Add(var); } } } } return(result); }
/** Returns the values of Dom(var) in a special order. The least constraining value comes first. */ public ICollection <VAL> apply(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment, VAR var) { ICollection <Pair <VAL, int> > pairs = CollectionFactory.CreateQueue <Pair <VAL, int> >(); foreach (VAL value in csp.getDomain(var)) { int num = countLostValues(csp, assignment, var, value); pairs.Add(new Pair <VAL, int>(value, num)); } pairs.Sort(new PairComparer <VAL>()); ICollection <VAL> obj = CollectionFactory.CreateQueue <VAL>(); foreach (Pair <VAL, int> val in pairs) { obj.Add(val.GetFirst()); } return(obj); }
/** Returns variables from <code>vars</code> which are the best with respect to DEG. */ public ICollection <VAR> apply(CSP <VAR, VAL> csp, ICollection <VAR> vars) { ICollection <VAR> result = CollectionFactory.CreateQueue <VAR>(); int maxDegree = -1; foreach (VAR var in vars) { int degree = csp.getConstraints(var).Size(); if (degree >= maxDegree) { if (degree > maxDegree) { result.Clear(); maxDegree = degree; } result.Add(var); } } return(result); }
/** Returns variables from <code>vars</code> which are the best with respect to MRV. */ public ICollection <VAR> apply(CSP <VAR, VAL> csp, ICollection <VAR> vars) { ICollection <VAR> result = CollectionFactory.CreateQueue <VAR>(); int mrv = int.MaxValue; foreach (VAR var in vars) { int rv = csp.getDomain(var).size(); if (rv <= mrv) { if (rv < mrv) { result.Clear(); mrv = rv; } result.Add(var); } } return(result); }
/** * Computes an explicit representation of the tree structure and a total order which is consistent with the * parent-child relations. If the provided CSP has not the required properties (CSP contains only binary * constraints, constraint graph is tree-structured and connected), an exception is thrown. * * @param csp A CSP * @param root A root variable * @param orderedVars The computed total order (initially empty) * @param parentConstraints The tree structure, maps a variable to the constraint representing the arc to the parent * variable (initially empty) */ private void topologicalSort(CSP <VAR, VAL> csp, VAR root, ICollection <VAR> orderedVars, IMap <VAR, IConstraint <VAR, VAL> > parentConstraints) { orderedVars.Add(root); parentConstraints.Put(root, null); int currParentIdx = -1; while (currParentIdx < orderedVars.Size() - 1) { currParentIdx++; VAR currParent = orderedVars.Get(currParentIdx); int arcsPointingUpwards = 0; foreach (IConstraint <VAR, VAL> constraint in csp.getConstraints(currParent)) { VAR neighbor = csp.getNeighbor(currParent, constraint); if (neighbor == null) { throw new IllegalArgumentException("Constraint " + constraint + " is not binary."); } if (parentConstraints.ContainsKey(neighbor)) { // faster than orderedVars.contains(neighbor)! arcsPointingUpwards++; if (arcsPointingUpwards > 1) { throw new IllegalArgumentException("CSP is not tree-structured."); } } else { orderedVars.Add(neighbor); parentConstraints.Put(neighbor, constraint); } } } if (orderedVars.Size() < csp.getVariables().Size()) { throw new IllegalArgumentException("Constraint graph is not connected."); } }
public override Assignment <VAR, VAL> solve(CSP <VAR, VAL> csp) { Assignment <VAR, VAL> current = generateRandomAssignment(csp); fireStateChanged(csp, current, null); for (int i = 0; i < maxSteps && !currIsCancelled; ++i) { if (current.isSolution(csp)) { return(current); } else { ISet <VAR> vars = getConflictedVariables(current, csp); VAR var = Util.selectRandomlyFromSet(vars); VAL value = getMinConflictValueFor(var, current, csp); current.add(var, value); fireStateChanged(csp, current, var); } } return(null); }
/// <summary> /// Template method, which can be configured by overriding the three primitive operations below. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <returns>An assignment (possibly incomplete if task was cancelled) or null if no solution was found.</returns> private Assignment <VAR, VAL> backtrack(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment) { Assignment <VAR, VAL> result = null; if (assignment.isComplete(csp.getVariables()) || currIsCancelled) { result = assignment; } else { VAR var = selectUnassignedVariable(csp, assignment); foreach (VAL value in orderDomainValues(csp, assignment, var)) { assignment.add(var, value); fireStateChanged(csp, assignment, var); if (assignment.isConsistent(csp.getConstraints(var))) { IInferenceLog <VAR, VAL> log = inference(csp, assignment, var); if (!log.isEmpty()) { fireStateChanged(csp, null, null); } if (!log.inconsistencyFound()) { result = backtrack(csp, assignment); if (result != null) { break; } } log.undo(csp); } assignment.remove(var); } } return(result); }
/** * Computes a solution to the given CSP, which specifies values for all * variables of the CSP such that all constraints are satisfied. * * @param csp a CSP to be solved. * @return the computed solution or empty if no solution was found. */ public abstract Assignment <VAR, VAL> solve(CSP <VAR, VAL> csp);
/// <summary> /// Applies a recursive backtracking search to solve the CSP. /// </summary> /// <param name="csp"></param> /// <returns></returns> public override Assignment <VAR, VAL> solve(CSP <VAR, VAL> csp) { Assignment <VAR, VAL> result = backtrack(csp, new Assignment <VAR, VAL>()); return(result); }
/// <summary> /// Primitive operation, which tries to optimize the CSP representation with respect to a new assignment. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <param name="var">The variable which just got a new value in the assignment.</param> /// <returns> /// An object which provides information about /// (1) whether changes have been performed, /// (2) possibly inferred empty domains, and /// (3) how to restore the original CSP. /// </returns> protected abstract IInferenceLog <VAR, VAL> inference(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment, VAR var);
/// <summary> /// Primitive operation, ordering the domain values of the specified variable. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <param name="var"></param> /// <returns></returns> protected abstract IEnumerable <VAL> orderDomainValues(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment, VAR var);
/// <summary> /// Primitive operation, selecting a not yet assigned variable. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <returns></returns> protected abstract VAR selectUnassignedVariable(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment);
public ICollection <VAR> apply(CSP <VAR, VAL> csp, ICollection <VAR> vars) { return(new DegHeuristic <VAR, VAL>().apply(csp, new MrvHeuristic <VAR, VAL>().apply(csp, vars))); }
/** * Establishes arc-consistency for (xi, xj). * @return value true if the domain of xi was reduced. */ private bool makeArcConsistent(VAR xi, VAR xj, IConstraint <VAR, VAL> constraint, CSP <VAR, VAL> csp) { 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()) { csp.setDomain(xi, new Domain <VAL>(newValues)); return(true); } return(false); }
/// <summary> /// Returns true if this assignment is consistent as well as complete with /// respect to the given CSP. /// </summary> /// <param name="csp"></param> /// <returns></returns> public bool isSolution(CSP <VAR, VAL> csp) { return(isConsistent(csp.getConstraints()) && isComplete(csp.getVariables())); }
private VAL getMinConflictValueFor(VAR var, Assignment <VAR, VAL> assignment, CSP <VAR, VAL> csp) { ICollection <IConstraint <VAR, VAL> > constraints = csp.getConstraints(var); Assignment <VAR, VAL> testAssignment = assignment.Clone(); int minConflict = int.MaxValue; ICollection <VAL> resultCandidates = CollectionFactory.CreateQueue <VAL>(); foreach (VAL value in csp.getDomain(var)) { testAssignment.add(var, value); int currConflict = countConflicts(testAssignment, constraints); if (currConflict <= minConflict) { if (currConflict < minConflict) { resultCandidates.Clear(); minConflict = currConflict; } resultCandidates.Add(value); } } return((!resultCandidates.IsEmpty()) ? Util.selectRandomlyFromList <VAL>(resultCandidates) : default(VAL)); }