def ac3(constraint_problem: ConstraintProblem,
        assigned_variable: Variable = None) -> bool:
    if assigned_variable is not None:  # usage of ac3 as part of Maintaining Arc Consistency (MAC) algorithm
        unassigned_neighbors = constraint_problem.get_unassigned_neighbors(
            assigned_variable)
        arcs = {(unassigned_neighbor, assigned_variable)
                for unassigned_neighbor in unassigned_neighbors}
    else:
        arcs = {(variable, neighbor)
                for variable in constraint_problem.get_unassigned_variables()
                for neighbor in constraint_problem.get_neighbors(variable)}

    while arcs:
        variable, neighbor = arcs.pop()
        if __revise(constraint_problem, variable, neighbor):
            if not constraint_problem.get_consistent_domain(variable):
                return False
            rest_of_neighbors = constraint_problem.get_neighbors(variable) - {
                neighbor
            }
            if rest_of_neighbors:
                for other_neighbor in rest_of_neighbors:
                    arcs.add((other_neighbor, variable))

    for var in constraint_problem.get_variables():
        if not var.domain or not constraint_problem.get_consistent_domain(var):
            return False
    return True
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
Exemplo n.º 3
0
def i_consistency(constraint_problem: ConstraintProblem, i: int) -> bool:
    variables = constraint_problem.get_variables()

    assert 0 < i <= len(variables), "for i = {0}: i <= 0 or (number of variables in constraint_problem) < i.".format(i)

    i_minus_one_sized_subsets = combinations(variables, i - 1)
    i_subsets_consistent_assignments = __initialize_i_consistency(variables, i_minus_one_sized_subsets)

    reducing_domains = True
    while reducing_domains:
        reducing_domains = False
        for subset, ith_variable in i_subsets_consistent_assignments:
            if __revise_i(constraint_problem, subset, ith_variable, i_subsets_consistent_assignments):
                reducing_domains = True

    for var in constraint_problem.get_variables():
        if not var.domain or not constraint_problem.get_consistent_domain(var):
            return False
    return True
def __calculate_weight(constraint_problem: ConstraintProblem,
                       constraints_weights: Dict[Constraint, int]) -> int:
    weight = 0
    for variable in constraint_problem.get_variables():
        unsatisfied_constraints = filterfalse(
            None,
            constraint_problem.get_constraints_containing_variable(variable))
        for unsatisfied_const in unsatisfied_constraints:
            weight += constraints_weights[unsatisfied_const]
    return weight
Exemplo n.º 5
0
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
Exemplo n.º 6
0
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 __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 generate_start_state_randomly(
        constraint_problem: ConstraintProblem) -> None:
    constraint_problem.unassign_all_variables()
    for var in constraint_problem.get_variables():
        var.assign(choice(var.domain))