private Assignment <VAR, VAL> generateRandomAssignment(CSP <VAR, VAL> csp) { Assignment <VAR, VAL> result = new Assignment <VAR, VAL>(); foreach (VAR var in csp.getVariables()) { VAL randomValue = Util.selectRandomlyFromList(csp.getDomain(var).asList()); result.add(var, randomValue); } return(result); }
public override Assignment <VAR, VAL> solve(CSP <VAR, VAL> csp) { Assignment <VAR, VAL> assignment = new Assignment <VAR, VAL>(); // Select a root from the List of Variables VAR root = _useRandom ? Util.selectRandomlyFromList(csp.getVariables()) : csp.getVariables().Get(0); // Sort the variables in topological order ICollection <VAR> orderedVars = CollectionFactory.CreateQueue <VAR>(); IMap <VAR, IConstraint <VAR, VAL> > parentConstraints = CollectionFactory.CreateInsertionOrderedMap <VAR, IConstraint <VAR, VAL> >(); topologicalSort(csp, root, orderedVars, parentConstraints); if (csp.getDomain(root).isEmpty()) { return(null); // CSP has no solution! (needed if orderedVars.size() == 1) } // Establish arc consistency from top to bottom (starting at the bottom). csp = csp.copyDomains(); // do not change the original CSP! for (int i = orderedVars.Size() - 1; i > 0; i--) { VAR var = orderedVars.Get(i); IConstraint <VAR, VAL> constraint = parentConstraints.Get(var); VAR parent = csp.getNeighbor(var, constraint); if (makeArcConsistent(parent, var, constraint, csp)) { fireStateChanged(csp, null, parent); if (csp.getDomain(parent).isEmpty()) { return(null); // CSP has no solution! } } } // Assign values to variables from top to bottom. for (int i = 0; i < orderedVars.Size(); ++i) { VAR var = orderedVars.Get(i); foreach (VAL value in csp.getDomain(var)) { assignment.add(var, value); if (assignment.isConsistent(csp.getConstraints(var))) { fireStateChanged(csp, assignment, var); break; } } } return(assignment); }
/** * Primitive operation, selecting a not yet assigned variable. */ protected override VAR selectUnassignedVariable(CSP <VAR, VAL> csp, Assignment <VAR, VAL> assignment) { ICollection <VAR> vars = CollectionFactory.CreateQueue <VAR>(); foreach (var v in csp.getVariables()) { if (!assignment.contains(v)) { vars.Add(v); } } if (varSelectionStrategy != null) { vars = varSelectionStrategy.apply(csp, vars); } return(vars.Get(0)); }
/** * 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."); } }
/// <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); }
/// <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())); }