private IEnumerable <Dictionary <TK, TD> > Ac3Search(CspProblem <TK, TD> problem) { NodesVisited = 0L; SolutionCount = 0L; foreach (var assignment in Search()) { yield return(assignment); } IEnumerable <Dictionary <TK, TD> > Search() { if (problem.Complete) { SolutionCount++; yield return(problem.Assignment); } else { var variable = problem.NextUnassigned(SelectVariableHeuristic); foreach (var value in variable.OrderDomainValues(OrderDomainHeuristic)) { NodesVisited++; variable.Value = value; if (variable.Consistent) { var removals = Ac3(problem, out var isConsistent); if (isConsistent) { // try finding solution foreach (var solution in Search().Where(s => s is not null)) { yield return(solution); } } foreach (var(v, removalCount) in removals) { v.RestorePreviousDomain(removalCount - 1); } } variable.Assigned = false; } yield return(null); } } }
private IEnumerable <Dictionary <TK, TD> > ForwardCheckingSearch(CspProblem <TK, TD> problem) { NodesVisited = 0L; SolutionCount = 0L; foreach (var assignment in Search()) { yield return(assignment); } IEnumerable <Dictionary <TK, TD> > Search() { if (problem.Complete) { SolutionCount++; yield return(problem.Assignment); } else { var variable = problem.NextUnassigned(SelectVariableHeuristic); foreach (var value in variable.OrderDomainValues(OrderDomainHeuristic)) { NodesVisited++; variable.Value = value; if (variable.Consistent) { var emptyDomainFound = false; var removals = new List <Variable <TK, TD> >(); // forward checking -> // remove from Variables connected by constraints // the values that are inconsistent with selected value foreach (var v in variable.Constraints .Where(c => !c.VariableTwo.Assigned) .Select(c => c.VariableTwo)) { var toRemove = v.Domain.Where(d => !v.CheckConsistency(d)).ToArray(); if (!toRemove.Any()) { continue; } v.RemoveFromDomain(toRemove); removals.Add(v); if (v.Domain.Any()) { continue; } emptyDomainFound = true; break; } if (emptyDomainFound) { yield return(null); } else { // try finding solution foreach (var solution in Search().Where(s => s is not null)) { yield return(solution); } } // restore domains to previous state foreach (var v in removals) { v.RestorePreviousDomain(); } } variable.Assigned = false; } yield return(null); } } }