protected void FireStateChanged(CSProblem csp) { foreach (ICSPStateListener listener in listeners) { listener.StateChanged(csp.CopyDomains()); } }
private bool Revise(Variable xi, Variable xj, IConstraint constraint, CSProblem csp, DomainRestoreInfo info) { bool revised = false; var assignment = new Assignment(); foreach (object vValue in csp.GetDomain(xi)) { assignment.SetAssignment(xi, vValue); bool vValueOk = false; foreach (var nValue in csp.GetDomain(xj)) { assignment.SetAssignment(xj, nValue); if (constraint.IsSatisfiedWith(assignment)) { vValueOk = true; break; } } if (!vValueOk) { info.StoreDomainFor(xi, csp.GetDomain(xi)); csp.RemoveValueFromDomain(xi, vValue); revised = true; } } return(revised); }
// ////////////////////////////////////////////////////////////// // inference algorithms /// <summary> /// Implements forward checking. /// </summary> /// <param name="var"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> private DomainRestoreInfo DoForwardChecking(Variable var, Assignment assignment, CSProblem csp) { DomainRestoreInfo result = new DomainRestoreInfo(); foreach (IConstraint constraint in csp.GetConstraints(var)) { IList <Variable> scope = constraint.GetScope(); if (scope.Count == 2) { foreach (Variable neighbor in constraint.GetScope()) { if (!assignment.HasAssignmentFor(neighbor)) { if (this.Revise(neighbor, constraint, assignment, csp, result)) { if (csp.GetDomain(neighbor).IsEmpty()) { result.SetEmptyDomainFound(true); return(result); } } } } } } return(result); }
/// <summary> /// Implements the degree heuristic. /// </summary> /// <param name="vars"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> private IList <Variable> applyDegreeHeuristic(IList <Variable> vars, Assignment assignment, CSProblem csp) { IList <Variable> result = new List <Variable>(); int maxDegree = int.MinValue; foreach (Variable var in vars) { int degree = 0; foreach (IConstraint constraint in csp.GetConstraints(var)) { Variable neighbor = csp.GetNeighbor(var, constraint); if (!assignment.HasAssignmentFor(neighbor) && csp.GetDomain(neighbor).Size() > 1) { ++degree; } } if (degree >= maxDegree) { if (degree > maxDegree) { result.Clear(); maxDegree = degree; } result.Add(var); } } return(result); }
protected void FireStateChanged(Assignment assignment, CSProblem csp) { foreach (ICSPStateListener listener in listeners) { listener.StateChanged(assignment.Copy(), csp.CopyDomains()); } }
private Assignment GenerateRandomAssignment(CSProblem csp) { Assignment assignment = new Assignment(); foreach (Variable var in csp.Variables) { object randomValue = Util.Util.SelectRandomlyFromList(csp.GetDomain(var).ToList()); assignment.SetAssignment(var, randomValue); } return(assignment); }
public DomainRestoreInfo ReduceDomains(CSProblem csp) { var result = new DomainRestoreInfo(); var queue = new FIFOQueue <Variable>(); foreach (Variable var in csp.Variables) { queue.Push(var); } this.ReduceDomains(queue, csp, result); return(result.Compactify()); }
/// <summary> /// Returns a copy which contains a copy of the domains list and is in all /// other aspects a flat copy of this. /// </summary> /// <returns></returns> public CSProblem CopyDomains() { CSProblem result = new CSProblem(); result.variables = variables; result.domains = new List <Domain>(domains.Count); result.domains = domains.ToList(); result.constraints = constraints; result.varIndexHash = varIndexHash; result.cnet = cnet; return(result); }
/// <summary> /// Primitive operation, which tries to prune out values from the CSProblem which /// are not possible anymore when extending the given assignment to a /// solution. /// </summary> /// <param name="var"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns>An object which provides informations about (1) whether changes /// have been performed, (2) possibly inferred empty domains , and /// (3) how to restore the domains.</returns> protected override DomainRestoreInfo Inference(Variable var, Assignment assignment, CSProblem csp) { switch (this.InferenceStrategy) { case InferenceType.ForwardChecking: return(this.DoForwardChecking(var, assignment, csp)); case InferenceType.AC3: return(new AC3Strategy().ReduceDomains(var, assignment.GetAssignment(var), csp)); default: return(new DomainRestoreInfo().Compactify()); } }
/// <summary> /// Implements the least constraining value heuristic. /// </summary> /// <param name="var"></param> /// <param name="csp"></param> /// <returns></returns> private IList <object> ApplyLeastConstrainingValueHeuristic(Variable var, CSProblem csp) { var pairs = (from value in csp.GetDomain(var) let num = this.CountLostValues(var, value, csp) select new Pair <object, int>(value, num)).ToList(); pairs.Sort((o1, o2) => o1.GetSecond() < o2.GetSecond() ? -1 : o1.GetSecond() > o2.GetSecond() ? 1 : 0); IList <object> result = new List <object>(); foreach (Pair <object, int> pair in pairs) { result.Add(pair.GetFirst()); } return(result); }
/// <summary> /// Starts with a constraint propagation if AC-3 is enabled and then calls /// the super class implementation. /// </summary> /// <param name="csp"></param> /// <returns></returns> public override Assignment Solve(CSProblem csp) { if (this.InferenceStrategy == InferenceType.AC3) { DomainRestoreInfo info = new AC3Strategy().ReduceDomains(csp); if (!info.IsEmpty()) { FireStateChanged(csp); if (info.IsEmptyDomainFound()) { return(null); } } } return(base.Solve(csp)); }
private bool Revise(Variable var, IConstraint constraint, Assignment assignment, CSProblem 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 override Assignment Solve(CSProblem csp) { Assignment assignment = this.GenerateRandomAssignment(csp); FireStateChanged(assignment, csp); for (int i = 0; i < maxSteps; i++) { if (assignment.IsSolution(csp)) { return(assignment); } IList <Variable> vars = this.GetConflictedVariables(assignment, csp); Variable var = Util.Util.SelectRandomlyFromList(vars); object value = this.GetMinConflictValueFor(var, assignment, csp); assignment.SetAssignment(var, value); FireStateChanged(assignment, csp); } return(null); }
private IList <Variable> GetConflictedVariables(Assignment assignment, CSProblem csp) { IList <Variable> result = new List <Variable>(); foreach (IConstraint 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, CSProblem csp) { int result = 0; Assignment assignment = new Assignment(); assignment.SetAssignment(var, value); foreach (IConstraint 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); }
public DomainRestoreInfo ReduceDomains(Variable var, object value, CSProblem 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.Push(var); result.StoreDomainFor(var, domain); csp.SetDomain(var, new Domain(new object[] { value })); this.ReduceDomains(queue, csp, result); } } else { result.SetEmptyDomainFound(true); } return(result.Compactify()); }
/// <summary> /// Template method, which can be configured by overriding the three /// primitive operations below. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <returns></returns> private Assignment RecursiveBackTrackingSearch(CSProblem csp, Assignment assignment) { Assignment result = null; if (assignment.IsComplete(csp.Variables)) { result = assignment; } else { Variable var = this.SelectUnassignedVariable(assignment, csp); foreach (object value in this.OrderDomainValues(var, assignment, csp)) { assignment.SetAssignment(var, value); this.FireStateChanged(assignment, csp); if (assignment.IsConsistent(csp.GetConstraints(var))) { DomainRestoreInfo info = this.Inference(var, assignment, csp); if (!info.IsEmpty()) { this.FireStateChanged(csp); } if (!info.IsEmptyDomainFound()) { result = this.RecursiveBackTrackingSearch(csp, assignment); if (result != null) { break; } } csp.RestoreDomains(info); } assignment.RemoveAssignment(var); } } return(result); }
/// <summary> /// Primitive operation, selecting a not yet assigned variable. /// </summary> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> protected override Variable SelectUnassignedVariable(Assignment assignment, CSProblem csp) { switch (this.SelectionStrategy) { case Selection.MRV: return(this.ApplyMrvHeuristic(csp, assignment)[0]); case Selection.MRVDeg: IList <Variable> vars = this.ApplyMrvHeuristic(csp, assignment); return(applyDegreeHeuristic(vars, assignment, csp)[0]); default: foreach (Variable var in csp.Variables) { if (!(assignment.HasAssignmentFor(var))) { return(var); } } break; } return(null); }
// ////////////////////////////////////////////////////////////// // heuristics for selecting the next unassigned variable and domain ordering /// <summary> /// Implements the minimum-remaining-values heuristic. /// </summary> /// <param name="csp"></param> /// <param name="assignment"></param> /// <returns></returns> private IList <Variable> ApplyMrvHeuristic(CSProblem csp, Assignment assignment) { IList <Variable> result = new List <Variable>(); int mrv = int.MaxValue; foreach (Variable var in csp.Variables) { if (!assignment.HasAssignmentFor(var)) { int num = csp.GetDomain(var).Size(); if (num <= mrv) { if (num < mrv) { result.Clear(); mrv = num; } result.Add(var); } } } return(result); }
private object GetMinConflictValueFor(Variable var, Assignment assignment, CSProblem csp) { IList <IConstraint> constraints = csp.GetConstraints(var); Assignment duplicate = assignment.Copy(); int minConflict = int.MaxValue; IList <object> resultCandidates = new List <object>(); foreach (object value in csp.GetDomain(var)) { duplicate.SetAssignment(var, value); int currConflict = this.CountConflicts(duplicate, constraints); if (currConflict <= minConflict) { if (currConflict < minConflict) { resultCandidates.Clear(); minConflict = currConflict; } resultCandidates.Add(value); } } return(resultCandidates.Count != 0 ? Util.Util.SelectRandomlyFromList(resultCandidates) : null); }
protected void ReduceDomains(FIFOQueue <Variable> queue, CSProblem csp, DomainRestoreInfo info) { while (!(queue.Count == 0)) { Variable var = queue.Pop(); foreach (IConstraint constraint in csp.GetConstraints(var)) { if (constraint.GetScope().Count == 2) { Variable neighbor = csp.GetNeighbor(var, constraint); if (this.Revise(neighbor, var, constraint, csp, info)) { if (csp.GetDomain(neighbor).IsEmpty()) { info.SetEmptyDomainFound(true); return; } queue.Push(neighbor); } } } } }
/// <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(CSProblem csp) { return(this.IsConsistent(csp.GetConstraints()) && this.IsComplete(csp.Variables)); }
/// <summary> /// Primitive operation, ordering the domain values of the specified /// variable. /// </summary> /// <param name="var"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> protected override IEnumerable <object> OrderDomainValues(Variable var, Assignment assignment, CSProblem csp) { if (!this.IsLcvHeuristicEnabled) { return(csp.GetDomain(var)); } else { return(this.ApplyLeastConstrainingValueHeuristic(var, csp)); } }
public abstract Assignment Solve(CSProblem csp);
/// <summary> /// Primitive operation, selecting a not yet assigned variable. This default /// implementation just selects the first in the ordered list of variables /// provided by the CSProblem. /// </summary> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> protected virtual Variable SelectUnassignedVariable(Assignment assignment, CSProblem csp) { return(csp.Variables.FirstOrDefault(var => !(assignment.HasAssignmentFor(var)))); }
public override Assignment Solve(CSProblem csp) { return(this.RecursiveBackTrackingSearch(csp, new Assignment())); }
/// <summary> /// Primitive operation, which tries to prune out values from the CSProblem which /// are not possible anymore when extending the given assignment to a /// solution. This default implementation just leaves the original CSProblem as it /// is. /// </summary> /// <param name="var"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns>An object which provides informations about (1) whether changes /// have been performed, (2) possibly inferred empty domains , and /// (3) how to restore the domains.</returns> protected virtual DomainRestoreInfo Inference(Variable var, Assignment assignment, CSProblem csp) { return(new DomainRestoreInfo().Compactify()); }
/// <summary> /// Primitive operation, ordering the domain values of the specified /// variable. This default implementation just takes the default order /// provided by the CSProblem. /// </summary> /// <param name="var"></param> /// <param name="assignment"></param> /// <param name="csp"></param> /// <returns></returns> protected virtual IEnumerable <object> OrderDomainValues(Variable var, Assignment assignment, CSProblem csp) { return(csp.GetDomain(var)); }