def naive_cycle_cutset(constraint_problem: ConstraintProblem, with_history: bool = False) \ -> Optional[Deque[Tuple[Variable, Any]]]: actions_history = None if with_history: actions_history = deque() variables = constraint_problem.get_variables() read_only_variables = constraint_problem.get_assigned_variables() constraints = list(constraint_problem.get_constraints()) constraints.sort(key=lambda constraint: len(constraint.variables), reverse=True) constraint_graph = constraint_problem.get_constraint_graph_as_adjacency_list() for i in range(1, len(constraints)): cutset_constraints = constraints[:i] cutset_variables = set() for cutset_const in cutset_constraints: cutset_variables.update(cutset_const.variables) reduced_graph = {var: neighbors for var, neighbors in constraint_graph.items() if var not in cutset_variables} for var in reduced_graph: reduced_graph[var] -= cutset_variables if __is_tree(reduced_graph): consistent_assignments_list = __get_consistent_assignments(cutset_variables, cutset_constraints, read_only_variables) non_cutset_variables = variables - cutset_variables non_cutset_vars_to_original_domains_map = {var: var.domain for var in non_cutset_variables} for consist_assignment in consistent_assignments_list: for var, value in zip(cutset_variables, consist_assignment): if var not in read_only_variables: var.assign(value) if with_history: actions_history.append((var, value)) for non_cutset_var in non_cutset_variables: if non_cutset_var not in read_only_variables: non_cutset_var.domain = list(constraint_problem.get_consistent_domain(non_cutset_var)) tree_csp_action_history = tree_csp_solver(constraint_problem, with_history) if with_history: actions_history.extend(tree_csp_action_history) if constraint_problem.is_completely_consistently_assigned(): return actions_history for var in variables: if var not in read_only_variables: var.unassign() if with_history: actions_history.append((var, None)) for var in non_cutset_vars_to_original_domains_map: if var not in read_only_variables: var.domain = non_cutset_vars_to_original_domains_map[var] return actions_history
def __reduce_assignment_constraints_domains(constraint_problem: ConstraintProblem, i_subsets_consistent_assignments: Dict[Tuple[Tuple[Variable, ...], Variable], set]) -> None: constraints = constraint_problem.get_constraints() for subset, ith_variable in i_subsets_consistent_assignments: i_variables = frozenset(subset + (ith_variable,)) found = False for constraint in constraints: if i_variables.issubset(constraint.variables): found = True constraint.update_i_consistent_assignments(i_subsets_consistent_assignments[(subset, ith_variable)]) if not found: i_constraint = OnlyiConsistentAssignment((i_subsets_consistent_assignments[(subset, ith_variable)])) new_constraint = Constraint(i_variables, i_constraint) constraint_problem.add_constraint(new_constraint)
def ac4(constraint_problem: ConstraintProblem) -> bool: support_counter = collections.Counter() variable_value_pairs_supported_by = collections.defaultdict(set) unsupported_variable_value_pairs = collections.deque() __initialize_ac4(constraint_problem.get_constraints(), support_counter, variable_value_pairs_supported_by, unsupported_variable_value_pairs) while unsupported_variable_value_pairs: second_variable, second_value = unsupported_variable_value_pairs.popleft() for first_variable, first_value in variable_value_pairs_supported_by[(second_variable, second_value)]: if first_value in first_variable.domain: support_counter[(first_variable, first_value, second_variable)] -= 1 if support_counter[(first_variable, first_value, second_variable)] == 0: first_variable.remove_from_domain(first_value) unsupported_variable_value_pairs.append((first_variable, first_value)) for var in constraint_problem.get_variables(): if not var.domain or not constraint_problem.get_consistent_domain(var): return False return True
def constraints_weighting(constraint_problem: ConstraintProblem, max_tries: int, with_history: bool = False) \ -> Optional[Deque[Tuple[Variable, Any]]]: actions_history = None if with_history: actions_history = deque() constraints_weights = { constraint: 1 for constraint in constraint_problem.get_constraints() } read_only_variables = constraint_problem.get_assigned_variables() for i in range(max_tries): constraint_problem.assign_variables_with_random_values( read_only_variables) last_reduction = float("inf") while 0 < last_reduction: if constraint_problem.is_completely_consistently_assigned(): return actions_history reduction, variable, value = __get_best_reduction_variable_value( constraint_problem, constraints_weights, read_only_variables) variable.unassign() if with_history: actions_history.append((variable, None)) variable.assign(value) if with_history: actions_history.append((variable, value)) last_reduction = reduction for unsatisfied_constraint in constraint_problem.get_unsatisfied_constraints( ): constraints_weights[unsatisfied_constraint] += 1 if i != max_tries - 1: constraint_problem.unassign_all_variables(read_only_variables) return actions_history