def _backtracking(problem, assignment, domains, variable_chooser, values_sorter, inference=True): ''' Internal recursive backtracking algorithm. ''' from simpleai.search.arc import arc_consistency_3 if len(assignment) == len(problem.variables): return assignment pending = [v for v in problem.variables if v not in assignment] variable = variable_chooser(problem, pending, domains) values = values_sorter(problem, assignment, variable, domains) for value in values: new_assignment = deepcopy(assignment) new_assignment[variable] = value if not _count_conflicts(problem, new_assignment): # TODO on aima also checks if using fc new_domains = deepcopy(domains) new_domains[variable] = [value] if not inference or arc_consistency_3(new_domains, problem.constraints): result = _backtracking(problem, new_assignment, new_domains, variable_chooser, values_sorter, inference=inference) if result: return result return None
def test_chained_revise_calls_remove_non_obvious_problems(self): # if A, B, C must be all different, with domains [1, 1], [1, 2], [2, 2] you # can't find a solution, but it requires several chained calls to # revise: # revise(A, B) -> ok! [1, 1] [1, 2] [2, 2] # revise(A, C) -> ok! [1, 1] [1, 2] [2, 2] # revise(B, C) -> fail, remove 2 from B [1, 1] [1] [2, 2] # and re-revise A, B and C, B # revise(A, B) -> fail, remove 1 from A [] [1] [2, 2] # and re-revise ... # here A has no more values, ac3 returns a failure domains = {'A': [1, 1], 'B': [1, 2], 'C': [2, 2]} different = lambda variables, values: len(set(values)) == len(variables ) constraints = [(('A', 'B'), different), (('A', 'C'), different), (('B', 'C'), different)] result = arc_consistency_3(domains, constraints) self.assertFalse(result)
def _backtracking(problem, assignment, domains, variable_chooser, values_sorter, inference=True): ''' Internal recursive backtracking algorithm. ''' from simpleai.search.arc import arc_consistency_3 if len(assignment) == len(problem.variables): return assignment pending = [v for v in problem.variables if v not in assignment] variable = variable_chooser(problem, pending, domains) values = values_sorter(problem, assignment, variable, domains) for value in values: new_assignment = deepcopy(assignment) new_assignment[variable] = value if not _count_conflicts( problem, new_assignment): # TODO on aima also checks if using fc new_domains = deepcopy(domains) new_domains[variable] = [value] if not inference or arc_consistency_3(new_domains, problem.constraints): result = _backtracking(problem, new_assignment, new_domains, variable_chooser, values_sorter, inference=inference) if result: return result return None
def test_chained_revise_calls_remove_non_obvious_problems(self): # if A, B, C must be all different, with domains [1, 1], [1, 2], [2, 2] you # can't find a solution, but it requires several chained calls to # revise: # revise(A, B) -> ok! [1, 1] [1, 2] [2, 2] # revise(A, C) -> ok! [1, 1] [1, 2] [2, 2] # revise(B, C) -> fail, remove 2 from B [1, 1] [1] [2, 2] # and re-revise A, B and C, B # revise(A, B) -> fail, remove 1 from A [] [1] [2, 2] # and re-revise ... # here A has no more values, ac3 returns a failure domains = {'A': [1, 1], 'B': [1, 2], 'C': [2, 2]} different = lambda variables, values: len(set(values)) == len(variables) constraints = [(('A', 'B'), different), (('A', 'C'), different), (('B', 'C'), different)] result = arc_consistency_3(domains, constraints) self.assertFalse(result)
def ac3(self, domain_a, domain_b): domains = {'A': domain_a, 'B': domain_b} constraints = [(('A', 'B'), is_square)] return arc_consistency_3(domains, constraints), domains
def test_ac3(self): self.assertTrue(arc_consistency_3(self.domains, self.constraints)) self.assertEqual(self.domains, {'X': [1, 2, 3, 4], 'Y': [1, 4, 9, 16]})