package aima.core.search.csp; import java.util.ArrayList; import java.util.List; import aima.core.util.Util; /** * Artificial Intelligence A Modern Approach (3rd Ed.): Figure 6.8, Page 221.
*
* *
 * 
 * function MIN-CONFLICTS(csp, max-steps) returns a solution or failure
 *    inputs: csp, a constraint satisfaction problem
 *            max-steps, the number of steps allowed before giving up
 *    current = an initial complete assignment for csp
 *    for i = 1 to max steps do
 *       if current is a solution for csp then return current
 *       var = a randomly chosen conflicted variable from csp.VARIABLES
 *       value = the value v for var that minimizes CONFLICTS(var, v, current, csp)
 *       set var = value in current
 *    return failure
 * 
 * 
* * Figure 6.8 The MIN-CONFLICTS algorithm for solving CSPs by local search. The * initial state may be chosen randomly or by a greedy assignment process that * chooses a minimal-conflict value for each variable in turn. The CONFLICTS * function counts the number of constraints violated by a particular value, * given the rest of the current assignment. * * @author Ruediger Lunde * @author Mike Stampone */ public class MinConflictsStrategy extends SolutionStrategy { private int maxSteps; /** * Constructs a min-conflicts strategy with a given number of steps allowed * before giving up. * * @param maxSteps * the number of steps allowed before giving up */ public MinConflictsStrategy(int maxSteps) { this.maxSteps = maxSteps; } 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 vars = getConflictedVariables(assignment, csp); Variable var = Util.selectRandomlyFromList(vars); Object value = getMinConflictValueFor(var, assignment, csp); assignment.setAssignment(var, value); fireStateChanged(assignment, csp); } } return null; } private Assignment generateRandomAssignment(CSP csp) { Assignment assignment = new Assignment(); for (Variable var : csp.getVariables()) { Object randomValue = Util.selectRandomlyFromList(csp.getDomain(var) .asList()); assignment.setAssignment(var, randomValue); } return assignment; } private List getConflictedVariables(Assignment assignment, CSP csp) { List result = new ArrayList(); for (Constraint constraint : csp.getConstraints()) { if (!constraint.isSatisfiedWith(assignment)) for (Variable var : constraint.getScope()) if (!result.contains(var)) result.add(var); } return result; } private Object getMinConflictValueFor(Variable var, Assignment assignment, CSP csp) { List constraints = csp.getConstraints(var); Assignment duplicate = assignment.copy(); int minConflict = Integer.MAX_VALUE; List resultCandidates = new ArrayList(); for (Object value : 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; } private int countConflicts(Assignment assignment, List constraints) { int result = 0; for (Constraint constraint : constraints) if (!constraint.isSatisfiedWith(assignment)) result++; return result; } }