def min_conflicts( constraint_problem: ConstraintProblem, max_steps: int, tabu_size: int = -1, with_history: bool = False) -> Optional[Deque[Tuple[Variable, Any]]]: __tabu_queue.clear() read_only_variables = constraint_problem.get_assigned_variables() if tabu_size == -1: tabu_size = 0 assert tabu_size + len(read_only_variables) < len(constraint_problem.get_variables()), \ "tabu_size + len(read_only_variables) is equal or bigger than constraint_problem's variables amount." if tabu_size == 0: tabu_size = -1 actions_history = None if with_history: actions_history = deque() rand_assignmt_history = constraint_problem.assign_variables_with_random_values( read_only_variables, actions_history) if with_history: actions_history.extend(rand_assignmt_history) best_min_conflicts = len(constraint_problem.get_unsatisfied_constraints()) best_min_conflicts_assignment = constraint_problem.get_current_assignment() for i in range(max_steps): if constraint_problem.is_completely_consistently_assigned(): return actions_history conflicted_variable = __get_random_conflicted_variable( constraint_problem, read_only_variables, tabu_size) conflicted_variable.unassign() if with_history: actions_history.append((conflicted_variable, None)) min_conflicts_value = __get_min_conflicts_value( constraint_problem, conflicted_variable) conflicted_variable.assign(min_conflicts_value) if with_history: actions_history.append((conflicted_variable, min_conflicts_value)) if len(__tabu_queue) == tabu_size: __tabu_queue.popleft() if __tabu_queue: __tabu_queue.append(conflicted_variable) curr_conflicts_count = len( constraint_problem.get_unsatisfied_constraints()) if curr_conflicts_count < best_min_conflicts: best_min_conflicts = curr_conflicts_count best_min_conflicts_assignment = constraint_problem.get_current_assignment( ) constraint_problem.unassign_all_variables() constraint_problem.assign_variables_from_assignment( best_min_conflicts_assignment) return actions_history
def __heuristic_backtrack( constraint_problem: ConstraintProblem, primary_select_unassigned_vars: SelectUnassignedVariables = minimum_remaining_values, secondary_select_unassigned_vars: SelectUnassignedVariables = degree_heuristic, sort_domain: SortDomain = least_constraining_value, inference: Optional[Inference] = None, find_all_solutions: bool = False, with_history: bool = False) -> Optional[Dict[Variable, Any]]: selected_unassigned_vars = primary_select_unassigned_vars( constraint_problem, None) if secondary_select_unassigned_vars is not None and len( selected_unassigned_vars) > 1: selected_unassigned_vars = secondary_select_unassigned_vars( constraint_problem, selected_unassigned_vars) selected_variable, *_ = selected_unassigned_vars sorted_domain = sort_domain(constraint_problem, selected_variable) for value in sorted_domain: selected_variable.assign(value) if with_history: __actions_history.append((selected_variable, value)) if inference is not None and not inference(constraint_problem, selected_variable): selected_variable.unassign() if with_history: __actions_history.append((selected_variable, None)) continue if constraint_problem.is_completely_assigned(): if constraint_problem.is_consistently_assigned(): if find_all_solutions: yield constraint_problem.get_current_assignment() else: yield None selected_variable.unassign() if with_history: __actions_history.append((selected_variable, None)) continue if constraint_problem.is_consistently_assigned(): for solution_assignment in __heuristic_backtrack( constraint_problem, primary_select_unassigned_vars, secondary_select_unassigned_vars, sort_domain, inference, find_all_solutions, with_history): yield solution_assignment selected_variable.unassign() if with_history: __actions_history.append((selected_variable, None))
def __forward_checking_backtrack( constraint_problem: ConstraintProblem, find_all_solutions: bool = False, with_history: bool = False) -> Optional[Dict[Variable, Any]]: variable, *_ = constraint_problem.get_unassigned_variables() for value in variable.domain: variable.assign(value) if with_history: __actions_history.append((variable, value)) unassigned_neighbors_frozenset = constraint_problem.get_unassigned_neighbors( variable) unsatisfiable_neighbors = filter( lambda unassigned_neighbor: not constraint_problem. get_consistent_domain(unassigned_neighbor), unassigned_neighbors_frozenset) if any(unsatisfiable_neighbors): variable.unassign() if with_history: __actions_history.append((variable, None)) continue if constraint_problem.is_completely_assigned(): if constraint_problem.is_consistently_assigned(): if find_all_solutions: yield constraint_problem.get_current_assignment() else: yield None variable.unassign() if with_history: __actions_history.append((variable, None)) continue if constraint_problem.is_consistently_assigned(): for solution_assignment in __forward_checking_backtrack( constraint_problem, find_all_solutions, with_history): yield solution_assignment variable.unassign() if with_history: __actions_history.append((variable, None))
def __backtrack(constraint_problem: ConstraintProblem, inference: Optional[Inference] = None, find_all_solutions: bool = False, with_history: bool = False) -> Optional[Dict[Variable, Any]]: variable, *_ = constraint_problem.get_unassigned_variables() for value in variable.domain: variable.assign(value) if with_history: __actions_history.append((variable, value)) if inference is not None and not inference(constraint_problem, variable): variable.unassign() if with_history: __actions_history.append((variable, None)) continue if constraint_problem.is_completely_assigned(): if constraint_problem.is_consistently_assigned(): if find_all_solutions: yield constraint_problem.get_current_assignment() else: yield None variable.unassign() if with_history: __actions_history.append((variable, None)) continue if constraint_problem.is_consistently_assigned(): for solution_assignment in __backtrack(constraint_problem, inference, find_all_solutions, with_history): yield solution_assignment variable.unassign() if with_history: __actions_history.append((variable, None))
def __get_best_reduction_variable_value( constraint_problem: ConstraintProblem, constraints_weights: Dict[Constraint, int], read_only_variables: FrozenSet[Variable]) -> Tuple[int, Variable, Any]: pairs_to_weight_reduction = dict() weight = __calculate_weight(constraint_problem, constraints_weights) original_assignment = constraint_problem.get_current_assignment() constraint_problem.unassign_all_variables() for variable in constraint_problem.get_variables() - read_only_variables: for value in variable.domain: variable.assign(value) curr_weight = __calculate_weight(constraint_problem, constraints_weights) pairs_to_weight_reduction[(variable, value)] = weight - curr_weight variable.unassign() constraint_problem.unassign_all_variables() constraint_problem.assign_variables_from_assignment(original_assignment) max_variable, max_value = max(pairs_to_weight_reduction, key=pairs_to_weight_reduction.get) return pairs_to_weight_reduction[(max_variable, max_value)], max_variable, max_value
def __optimized_heuristic_backtrack(constraint_problem: ConstraintProblem, find_all_solutions: bool = False, with_history: bool = False): unassigned_variables = constraint_problem.get_unassigned_variables() min_variable = min( unassigned_variables, key=lambda var: len(constraint_problem.get_consistent_domain(var))) min_remaining_values = len( constraint_problem.get_consistent_domain(min_variable)) min_variables = filter( lambda var: len(constraint_problem.get_consistent_domain(var)) == min_remaining_values, unassigned_variables) selected_unassigned_vars = frozenset(min_variables) if len(selected_unassigned_vars) > 1: selected_variable = max( selected_unassigned_vars, key=lambda var: len( constraint_problem.get_unassigned_neighbors(var))) else: selected_variable, *_ = selected_unassigned_vars unassigned_neighbors = constraint_problem.get_unassigned_neighbors( selected_variable) def neighbors_consistent_domain_lengths(val) -> int: selected_variable.assign(val) consistent_domain_lengths = map( lambda neighbor: len( (constraint_problem.get_consistent_domain(neighbor))), unassigned_neighbors) selected_variable.unassign() return sum(consistent_domain_lengths) sorted_domain = sorted( constraint_problem.get_consistent_domain(selected_variable), key=neighbors_consistent_domain_lengths, reverse=True) for value in sorted_domain: selected_variable.assign(value) if with_history: __actions_history.append((selected_variable, value)) if constraint_problem.is_completely_assigned(): if constraint_problem.is_consistently_assigned(): if find_all_solutions: yield constraint_problem.get_current_assignment() else: yield None selected_variable.unassign() if with_history: __actions_history.append((selected_variable, None)) continue if constraint_problem.is_consistently_assigned(): for solution_assignment in __optimized_heuristic_backtrack( constraint_problem, find_all_solutions, with_history): yield solution_assignment selected_variable.unassign() if with_history: __actions_history.append((selected_variable, None))