Пример #1
0
def test_min_conflicts_solver():
    problem = Problem(MinConflictsSolver())
    problem.addVariable("x", [0, 1])
    problem.addVariable("y", [0, 1])
    solution = problem.getSolution()

    possible_solutions = [
        {
            "x": 0,
            "y": 0
        },
        {
            "x": 0,
            "y": 1
        },
        {
            "x": 1,
            "y": 0
        },
        {
            "x": 1,
            "y": 1
        },
    ]

    assert solution in possible_solutions
Пример #2
0
 def _generate_solutions(cls, period, doms):
     """
     Each child gets as domain a set of ShiftAssignables, 
     which is generated by their shift preferences;
     each solution selects for each child a ShiftAssignable
     so that all assignments are compatible.
     Here we configure a problem from the constraint library,
     then call the solver.
     The problem takes a mapping, doms, from child_pk to a set of assignables for that child, plus a specification, across children, of which assignables are pairwise consistent
     The solver yields all compatible sets of assignables
     """
     problem = Problem()
     prefs = (ShiftPreference.objects.filter(
         period=period).select_related('shift').select_related('child'))
     for pref in prefs:
         for assignable in pref.assignables():
             if assignable.is_active:
                 doms[assignable.child.pk].append(assignable)
     for k, dom in doms.items():
         try:
             problem.addVariable(k, dom)
         except ValueError:
             return {}
     cached_compatibility = functools.lru_cache()(
         lambda a1, a2: a1.is_compatible_with(a2))
     for k1, k2 in itertools.combinations(doms.keys(), 2):
         problem.addConstraint(cached_compatibility, (k1, k2))
     # call the solver
     return problem.getSolutionIter()
Пример #3
0
def find_mapping(signal_patterns: Set[FrozenSet[str]]) -> Dict[str, str]:

    # Let’s express this as a constraint satisfaction problem
    problem = Problem()
    for signal in "abcdefg":
        problem.addVariable(signal, "abcdefg")

    # Each signal wire goes to a different segment
    problem.addConstraint(AllDifferentConstraint())

    # Unambiguous digits based on count of lit segments
    for digit in {1, 4, 7, 8}:
        for wire in find_possible_signals_for(signal_patterns, digit):
            segments = DIGIT_TO_SEGMENTS[digit]
            problem.addConstraint(InSetConstraint(segments), wire)

    # Unambiguous segments based on how many times they appear in patterns
    for signal_wire in {"a", "b", "c", "d", "e", "f", "g"}:
        count = sum(1 for pattern in signal_patterns if signal_wire in pattern)
        if count == 4:
            problem.addConstraint(InSetConstraint(["e"]), signal_wire)
        elif count == 6:
            problem.addConstraint(InSetConstraint(["b"]), signal_wire)
        elif count == 7:
            problem.addConstraint(InSetConstraint(["d", "g"]), signal_wire)
        elif count == 8:
            problem.addConstraint(InSetConstraint(["a", "c"]), signal_wire)
        elif count == 9:
            problem.addConstraint(InSetConstraint(["f"]), signal_wire)
        else:
            raise ValueError

    return problem.getSolution()
Пример #4
0
def queens(n):
    problem = Problem()
    domain = range(n + 1)[1:]
    variables = LinkedList(list("X%d" % i for i in range(n + 1)[1:]))
    for name in variables:
        problem.addVariable(name, domain)
    constr_all(problem, variables)
    return problem
Пример #5
0
    def _cp_step(self, state, prob):
        """ The constraint programming step.

            This is one of the more complicated steps; it divides the boundary into
            components that don't influence each other first, then divides each of those into areas that are equally
            constrained and must therefore have the same probabilities. The combinations of the number of mines in those
            components is computed with constraint programming. Those solutions are then combined to count the number of
            models in which each area has the given number of mines, from which we can calculate the average expected
            number of mines per square in a component if it has M mines, i.e. per component we have a mapping of
            {num_mines: (num_models, avg_prob)}. This information is then passed on to the combining step to form the
            final probabilities.

            :param state: The reduced state.
            :param prob: The already computed probabilities.
            :returns: The exact probability for every unknown square.
        """
        components, num_components = self._components(state)
        c_counts = []   # List of model_count_by_m instances from inside the 'for c' loop.
        c_probs = []    # List of model_count_by_m instances from inside the 'for c' loop.
        m_known = self.known_mine_count()
        # Solve each component individually
        for c in range(1, num_components+1):
            areas, constraints = self._get_areas(state, components == c)
            # Create a CP problem to determine which combination of mines per area is possible.
            problem = Problem()
            # Add all variables, each one having a domain [0, num_squares].
            for v in areas.values():
                problem.addVariable(v, range(len(v)+1))
            # Now constrain how many mines areas can have combined.
            for constraint in constraints:
                problem.addConstraint(constraint, [v for k, v in areas.items() if constraint in k])
            # Add a constraint so that the maximum number of mines never exceeds the number of mines left.
            problem.addConstraint(MaxSumConstraint(self._total_mines - m_known), list(areas.values()))
            solutions = problem.getSolutions()
            model_count_by_m = {}       # {m: #models}
            model_prob_by_m = {}        # {m: prob of the average component model}
            # Now count the number of models that exist for each number of mines in that component.
            for solution in solutions:
                m = sum(solution.values())
                # Number of models that match this solution.
                model_count = self._count_models(solution)
                # Increase counter for the number of models that have m mines.
                model_count_by_m[m] = model_count_by_m.get(m, 0) + model_count
                # Calculate the probability of each square in the component having a mines.
                model_prob = np.zeros(prob.shape)
                for area, m_area in solution.items():
                    # The area has `m_area` mines in it, evenly distributed.
                    model_prob[tuple(zip(*area))] = m_area/len(area)
                # Sum up all the models, giving the expected number of mines of all models combined
                model_prob_by_m[m] = model_prob_by_m.get(m, np.zeros(prob.shape)) + model_count*model_prob
            # We've summed the probabilities of each solution, weighted by the number of models with those
            # probabilities, now divide out the total number of models to obtain the probability of each square of a
            # model with m mines having a mine.
            model_prob_by_m = {m: model_prob/model_count_by_m[m] for m, model_prob in model_prob_by_m.items()}
            c_probs.append(model_prob_by_m)
            c_counts.append(model_count_by_m)
        prob = self._combine_components(state, prob, c_probs, c_counts)
        return prob
def solver(domain, appointments):
    problem = Problem()
    ConstraintGraphCost = nx.Graph()
    variablesName = []
    # for each appointment (iterate on the numerical key of the appointments)
    for x in appointments:
        dom = []
        # check which elements of the generic domain are necessary for this appointment
        for y in domain:
            hour, minutes = y[1].split(".")
            hour = int(hour)
            #print(appointments[x])
            #print(appointments[x]["Day"])

            for a in appointments[x]["Day"]:
                if "Morning" == a[1] and hour < 12 and y[0] in a[0] and y[
                        2] in appointments[x]["House"]:
                    dom.append(y)

                if "Afternoon" == a[1] and hour > 12 and y[0] in a[0] and y[
                        2] in appointments[x]["House"]:
                    dom.append(y)

        #Aggiungo la variabile corrente con il domain aggiustato
    #    print(dom)
        variablesName.append(x)
        ConstraintGraphCost.add_node(x, domain=dom)
        problem.addVariable(x, dom)

    a = itertools.combinations(variablesName, 2)

    for i in a:
        #print("Considero ", i)
        stop = False
        for domItem1 in ConstraintGraphCost.nodes[i[0]]['domain']:
            if (stop):
                break
            else:
                for domItem2 in ConstraintGraphCost.nodes[i[1]]['domain']:
                    if domItem1[0] == domItem2[0] and domItem1[1] == domItem2[
                            1] and domItem1 != "notScheduled":
                        #print("creo edge")
                        ConstraintGraphCost.add_edge(i[0], i[1])
                        problem.addConstraint(constraintFunction(),
                                              (i[0], i[1]))
                        stop = True
                        break

    start = current_milli_time()
    solution = problem.getSolution()
    end = current_milli_time()
    print("\n\n###########Time spent to find the first solution = ",
          end - start, " ms.\n\n")

    # pp.pprint(solution)

    return solution
Пример #7
0
def test_toy_python_constraint():
    def func1(a):
        return a < 0

    p = Problem()
    p.addVariable("a", [-1, -2, 0, 1, 2])
    p.addConstraint(func1, ["a"])
    result = p.getSolutions()
    print(result)
Пример #8
0
def solve_board(overlays, verify_just_one=False):
    problem = Problem()
    spot_constraints = defaultdict(list)
    overlay_constraints = []
    for overlay in overlays:
        # the simplest case is a fully 3x3 grid
        if len(overlay) == 3 and len(overlay[0]) == 3:
            for x in range(3):
                for y in range(3):
                    if overlay[x][y] is None:
                        continue
                    spot_constraints[(x, y)].extend(
                        get_constraints(overlay[x][y]))
        else:
            # dealing with a grid that is smaller than 3x3 so we
            # need to make relative constraints - we add those
            # after the all different constraint so it only needs
            # to look at possible boards
            overlay_constraints.append(
                (FunctionConstraint(floating_overlay(overlay)),
                 locations))

    # the unspecified spots could be any piece
    for x in range(3):
        for y in range(3):
                if (x, y) not in spot_constraints:
                    spot_constraints[(x, y)] = pieces

    for spot, values in spot_constraints.iteritems():
        problem.addVariable(spot, values)

    problem.addConstraint(AllDifferentConstraint())

    for overlay_constraint in overlay_constraints:
        problem.addConstraint(*overlay_constraint)

    solution = None

    if verify_just_one:
        solutions = problem.getSolutions()
        assert len(solutions) == 1, ('%d solutions but there should be 1' %
                                     len(solutions))
        solution = solutions[0]
    else:
        solution = problem.getSolution()

    answer = [[None] * 3 for x in range(3)]
    for x in range(3):
        for y in range(3):
            answer[x][y] = solution[(x, y)]

    print('\n'.join(' '.join(_) for _ in answer))
    print('')

    return answer
Пример #9
0
class SudokuProblem(object):
    def __init__(self):
        self._problem = Problem()

    def _each_once_per_line(self):
        for line_index in range(9):
            variable_names = [self._variable_name(line_index, column_index) for column_index in range(9)]
            self._problem.addConstraint(AllDifferentConstraint(), variable_names)

    def _each_once_per_column(self):
        for column_index in range(9):
            variable_names = [self._variable_name(line_index, column_index) for line_index in range(9)]
            self._problem.addConstraint(AllDifferentConstraint(), variable_names)

    def _each_once_per_square(self):
        for line_square_index in range(3):
            for column_square_index in range(3):
                variable_names = []
                line_index_start = line_square_index * 3
                for line_index in range(line_index_start, line_index_start + 3):
                    column_index_start = column_square_index * 3
                    for column_index in range(column_index_start, column_index_start + 3):
                        variable_names.append(self._variable_name(line_index, column_index))
                self._problem.addConstraint(AllDifferentConstraint(), variable_names)

    def generate_constraints(self):
        self._each_once_per_line()
        self._each_once_per_column()
        self._each_once_per_square()

    def _variable_name(self, line_index, column_index):
        return '(l%d,c%d)' % (line_index, column_index)

    def feed_puzzle(self, values_of_colum_of_line):
        for line_index, values_of_column in values_of_colum_of_line.items():
            for column_index, values in values_of_column.items():
                variable_name = self._variable_name(line_index, column_index)
                self._problem.addVariable(variable_name, values)

    def iterate_solutions(self):
        return self._problem.getSolutionIter()

    def format_solution(self, solution_dict, indent_text):
        chunks = []
        for line_index in range(9):
            values = []
            for column_index in range(9):
                value = solution_dict[self._variable_name(line_index, column_index)]
                values.append(value)
            chunks.append(indent_text + '%d %d %d | %d %d %d | %d %d %d' % tuple(values))

            if line_index % 3 == 2 and line_index < 8:
                chunks.append(indent_text + '------+-------+------')

        return '\n'.join(chunks)
Пример #10
0
def solve():
    problem = Problem()
    total = 3.00
    variables = ("0.02", "0.09", "0.13", "1.50", "2.00")
    values = [float(x) for x in variables]
    for variable, value in zip(variables, values):
        problem.addVariable(variable, range(int(total / value)))
    problem.addConstraint(ExactSumConstraint(total, values), variables)
    problem.addConstraint(ExactSumConstraint(100))
    solutions = problem.getSolutionIter()
    return solutions, variables
Пример #11
0
def solve():
    problem = Problem()
    total = 5.00
    variables = ("0.01", "0.05", "0.10", "0.50", "1.00")
    values = [float(x) for x in variables]
    for variable, value in zip(variables, values):
        problem.addVariable(variable, range(int(total / value)))
    problem.addConstraint(ExactSumConstraint(total, values), variables)
    problem.addConstraint(ExactSumConstraint(100))
    solutions = problem.getSolutionIter()
    return solutions, variables
def test_constraint():
    c = Problem()
    c.addVariable("i", range(-100, 10))
    c.addVariable("j", range(-10, 10))
    c.addVariable("k", range(-10, 10))
    c.addConstraint(lambda i, j, k: i <= 0 or j <= 0 or k <= 0, ("i", "j", "k"))
    C = CustomConstraint(c)
    values1 = [-1, -1, -1]
    values2 = [9, 8, 2]
    assert C.to_fitness(values1) == 9963.0
    assert C.to_fitness(values2) == 12349.0
Пример #13
0
def processResults(all_data):

    prob = Problem()
    for i, d in enumerate(all_data):
        prob.addVariable(i, d["logic"])

    prob.addConstraint(MaxSumConstraint(234720))

    solutions = prob.getSolutionIter()

    for i, s in enumerate(solutions):
        if i % 1000 == 0:
            print(i)
Пример #14
0
def buildproblem(terms, total):
    problem = Problem()

    letters = sorted(list(set("".join(terms) + total)))
    initial = set([word[0] for word in terms + [total]])

    for letter in letters:
        if letter in initial:
            problem.addVariable(letter, list(range(1, 10)))
        else:
            problem.addVariable(letter, list(range(10)))
    problem.addConstraint(AllDifferentConstraint())
    digit_checks(problem, terms, total, letters)
    return problem
Пример #15
0
def buildproblem(terms, total):
    problem = Problem()

    letters = sorted(list(set("".join(terms) + total)))
    initial = set([word[0] for word in terms + [total]])

    for letter in letters:
        if letter in initial:
            problem.addVariable(letter, list(range(1,10)))
        else:
            problem.addVariable(letter, list(range(10)))
    problem.addConstraint(AllDifferentConstraint())
    digit_checks(problem, terms, total, letters)
    return problem
Пример #16
0
def team_solver(all_players, max_overall):

    problem = Problem()
    for position in all_players:
        problem.addVariable(position, all_players[position])

    def constraint(pg, sg, sf, pf, c):
        team_overall = pg['player']['overall'] + sg['player']['overall'] + \
                       sf['player']['overall'] + pf['player']['overall'] + \
                       c['player']['overall']
        return team_overall <= max_overall

    problem.addConstraint(constraint)

    return problem.getSolutions()
Пример #17
0
def test_least_conflicts_solver():
    # another test for LeastConflictsSolver

    problem = Problem(LeastConflictsSolver())

    result = [[('a', 1), ('b', 2), ('c', 1)], [('a', 2), ('b', 1), ('c', 1)],
              [('a', 2), ('b', 2), ('c', 1)]]

    problem.addVariables(["a", "b"], [1, 2])
    problem.addVariable("c", [1])
    problem.addConstraint(lambda a, b: b != a, ["a", "b"])
    problem.addConstraint(lambda a, b: b != a, ["a", "c"])
    problem.addConstraint(lambda a, b: b != a, ["b", "c"])

    solution = problem.getSolution()
    assert sorted(solution.items()) in result
Пример #18
0
def solver(domain, appointments):
    problem = Problem()

    # for each appointment (iterate on the numerical key of the appointments)
    for x in appointments:
        dom = []

        # check which elements of the generic domain are necessary for this appointment
        for y in domain:
            hour, minutes = y[1].split(".")
            hour = int(hour)

            if "Morning" in appointments[x]["Pref"] and hour < 12 and y[
                    0] in appointments[x]["Day"] and y[2] in appointments[x][
                        "House"]:
                dom.append(y)

            if "Afternoon" in appointments[x]["Pref"] and hour > 12 and y[
                    0] in appointments[x]["Day"] and y[2] in appointments[x][
                        "House"]:
                dom.append(y)

        # print("FOR APPOINTMENT:\n")
        # pp.pprint(x)
        # print("The domain is:\n")
        # pp.pprint(dom)

        # add a variable to the CSP problem with the appointment *x* and the just computed domain *dom*
        problem.addVariable(x, dom)

    # add constraints
    for x in appointments:
        for y in appointments:
            if (x != y):
                problem.addConstraint(constraintFunction(), (x, y))

    start = current_milli_time()
    solution = problem.getSolution()
    end = current_milli_time()
    print("\n\n###########Time spent to find the first solution = ",
          end - start, " ms.\n\n")

    # pp.pprint(solution)

    return solution
Пример #19
0
def solve_puzzles(puzzles, solver):
    """
    Solves an array of sudoku puzzles, recording runtime.

    :param puzzles: an array of 2D array boards
    :param solver: the CSP solver to be used
    :return: none
    """
    fail_count = 0
    start_time = datetime.now()     # start timer (for runtime)

    for puzzle in puzzles:
        # initialize Board
        b = Board(puzzle)

        sudoku = Problem(solver)      # initialize CSP with custom solver

        # add variables for each square, indexed 1...size^2
        for index in range(b.board_size ** 2):
            value = b.get_value(index)

            if value == 0:
                sudoku.addVariable(index, range(1, b.board_size + 1))
            else:
                sudoku.addVariable(index, [value])

        # add uniqueness constraints to each row, column, and subsquare
        for i in range(b.board_size):
            sudoku.addConstraint(AllDifferentConstraint(), [el[0] for el in b.row(i)])
            sudoku.addConstraint(AllDifferentConstraint(), [el[0] for el in b.col(i)])
            sudoku.addConstraint(AllDifferentConstraint(), [el[0] for el in b.subsquare(i)])

        sln = sudoku.getSolution()      # solve CSP

        if sln:
            # assign solved values
            for index, value in sln.items():
                b.set_value(index, value)
        else:
            fail_count += 1

    # perform/display runtime calculation
    runtime = datetime.now() - start_time
    print("Runtime: {} seconds ({} failed)".format(runtime.total_seconds(), fail_count))
Пример #20
0
def compute_using_external_solver(predicate, env, varList):
    # TODO: import at module level
    # external software:
    # install http://labix.org/python-constraint
    # download and unzip python-constraint-1.1.tar.bz2
    # python setup.py build
    # python setup.py install
    #from pretty_printer import pretty_print
    #print "predicate:", pretty_print(predicate)
    from constraint import Problem
    assert isinstance(predicate, Predicate)
    var_and_domain_lst = []
    # get domain 
    for idNode in varList:
        assert isinstance(idNode, AIdentifierExpression)
        atype = env.get_type_by_node(idNode)
        #if USE_RPYTHON_CODE:
        #    domain = all_values_by_type_RPYTHON(atype, env, idNode)
        #else:
        #    domain = all_values_by_type(atype, env, idNode)
        domain = all_values_by_type(atype, env, idNode)
        tup = (idNode.idName, domain)
        var_and_domain_lst.append(tup)
    problem = Problem() # import from "constraint"
    for tup in var_and_domain_lst:
        name = tup[0]
        lst  = tup[1]
        if isinstance(lst, frozenset):
            lst = set_to_list(lst) 
        problem.addVariable(name, lst)
    qme_nodes = []
    constraint_string = pretty_print_python_style(env, varList, predicate, qme_nodes)
    names = [x.idName for x in varList]
    expr = "lambda "
    for n in names[0:-1]:
        expr += n+","
    expr += varList[-1].idName+":"+constraint_string
    #print expr
    my_globales = {"qme_nodes":qme_nodes, "quick_member_eval":quick_member_eval, "env":env}
    lambda_func = eval(expr, my_globales)  # TODO:(#ISSUE 16) not Rpython
    problem.addConstraint(lambda_func, names)
    return problem.getSolutionIter()
Пример #21
0
        def try_assignment():
            problem = Problem()

            for variable in self.variables:
                candidates = [assignment[variable.name]] if variable.name in assignment else groups
                domain = list([g for g in candidates if any(st in variable.types for st in
                                                            (Typing.as_legacy_type(gt) for gt in g.vector_types))])
                if len(domain) == 0:
                    return variable.name in assignment, []
                problem.addVariable(variable.name, domain)

            for f in filters:
                variables = list([v.name for v in f.variables])

                def c_j(ff, vv):
                    return lambda *args: ff.test_relaxed({vv[i]: args[i] for i in range(len(args))}, solutions)

                problem.addConstraint(c_j(f, variables), variables)

            return True, list(problem.getSolutions())
Пример #22
0
def gen_disjunct_intervals_CSP(ints):
    p = Problem()
    size = len(ints)
    sizeL = range(size)
    for intnum, key in enumerate(ints):
        values = [[]]
        for i in sizeL:
            values += [
                item for item in it.combinations(ints, i + 1) if key in item
            ]
        p.addVariable(intnum, values)

    for i in sizeL:
        p.addConstraint(check_continuity, (i, ))
    for i1, i2 in it.product(sizeL, sizeL):
        if i1 < i2:
            p.addConstraint(check_all, (i1, i2))
    p.addConstraint(all_interval, sizeL)

    return p.getSolution()
Пример #23
0
def problem_2():
    """Function for performing the work of problem 2."""
    # Initialize the problem.
    problem = Problem()

    # Add the variables.
    problem.addVariable('case', CASES)
    problem.addVariable('motherboard', MOTHERBOARDS)
    problem.addVariable('memory', MEMORY)
    problem.addVariable('GPU', GPUS)
    problem.addVariable('SSD', SSDS)
    problem.addVariable('CPU', CPUS)

    # Add constraints.
    problem.addConstraint(motherboard_case, ['motherboard', 'case'])
    problem.addConstraint(motherboard_memory, ['motherboard', 'memory'])
    problem.addConstraint(motherboard_ssd, ['motherboard', 'SSD'])
    problem.addConstraint(motherboard_cpu, ['motherboard', 'CPU'])
    problem.addConstraint(case_gpu, ['case', 'GPU'])

    return problem
Пример #24
0
def gen_disjunct_intervals_CSP(ints):
    p = Problem()
    size = len(ints)
    sizeL = range(size)
    for intnum, key in enumerate(ints):
        values = [[]]
        for i in sizeL:
            values += [
                item
                for item in it.combinations(ints, i + 1) if key in item
            ]
        p.addVariable(intnum, values)

    for i in sizeL:
        p.addConstraint(check_continuity, (i,))
    for i1, i2 in it.product(sizeL, sizeL):
        if i1 < i2:
            p.addConstraint(check_all, (i1, i2))
    p.addConstraint(all_interval, sizeL)

    return p.getSolution()
Пример #25
0
def player_solver(players, attribute_bounds):
    def create_constraint(attribute, bounds):
        min_value, max_value = bounds

        def constraint(player):
            return min_value <= player[attribute]

        return constraint

        # def constraint(player):
        #     return min_value <= player[attribute] <= max_value
        # return constraint

    problem = Problem()
    problem.addVariable("player", players)

    for attribute, bounds in attribute_bounds.items():
        constraint = create_constraint(attribute, bounds)
        problem.addConstraint(constraint, ["player"])

    return problem.getSolutions()
Пример #26
0
def test_addVariable_support_domain_subclasses():
    class MyCustomDomain(Domain):
        pass

    class MyConstraint(Constraint):
        def __call__(self,
                     variables,
                     domains,
                     assignments,
                     forwardcheck=False):
            assert isinstance(domains['x'], Domain)
            assert isinstance(domains['y'], MyCustomDomain)
            return True

    problem = Problem()
    problem.addVariable("x", [0, 1])
    problem.addVariable("y", MyCustomDomain([0, 1]))
    problem.addConstraint(MyConstraint())
    solution = problem.getSolution()

    possible_solutions = [
        {
            "x": 0,
            "y": 0
        },
        {
            "x": 0,
            "y": 1
        },
        {
            "x": 1,
            "y": 0
        },
        {
            "x": 1,
            "y": 1
        },
    ]

    assert solution in possible_solutions
Пример #27
0
def solve_board(board, cages):
    problem = Problem()
    height = len(board)
    width = len(board[0])
    assert width == height, 'Grid must be a square'

    cage_name_to_locations = defaultdict(list)

    for x in range(height):
        row_variables = [(x, ry) for ry in range(width)]
        column_variables = [(cx, x) for cx in range(height)]
        problem.addConstraint(AllDifferentConstraint(), row_variables)
        problem.addConstraint(AllDifferentConstraint(), column_variables)
        for y in range(width):
            if isinstance(board[x][y], basestring):
                # we are dealing with a function
                cage_name_to_locations[board[x][y]].append((x, y))
            else:
                # we are dealing with a pre-assigned number
                problem.addVariable((x, y), [board[x][y]])

    for cage_name, cage_locations in cage_name_to_locations.iteritems():
        cage_function = cages[cage_name]
        all_values = product(range(1, width + 1),
                             repeat=len(cage_locations))
        possible_values = set(chain(*[values for values in all_values
                                      if cage_function(*values)]))
        for location in cage_locations:
            problem.addVariable(location, list(possible_values))
        problem.addConstraint(FunctionConstraint(cage_function),
                              cage_locations)

    solution = problem.getSolution()

    answer = [row[:] for row in board]
    for x in range(height):
        for y in range(width):
            answer[x][y] = solution[(x, y)]

    return answer
Пример #28
0
def kakuroCSP():

  # Pre: variables and equations have been computed by sanityCheck
  # Will be run in a background thread

  global solutions, variables       # will be accessed by main thread
  global solverDone

  problem = Problem()

  # Restrict the value of each white square as much as possible

  domains = defaultdict(set)
  univ = list(range(1,10))
  for n in univ:
    for c in combinations(univ, n):
      domains[sum(c), n] |= set(c)

  candidates = {v: set(univ) for v in variables}
  for eq in equations:
    for v in eq.variables:
      candidates[v] &= domains[eq.clue, len(eq.variables)]

  # one variable for each white square, with values in range computed above

  for v in variables:
    problem.addVariable(v, tuple(candidates[v]))

  for eq in equations:
    # All the numbers in a single sum are distinct

    problem.addConstraint(AllDifferentConstraint(), eq.variables)

    # The numbers must sum to the clue

    problem.addConstraint(ExactSumConstraint(eq.clue), eq.variables)

  solutions = problem.getSolutions()
  solverDone = True
Пример #29
0
def Balanceo(trabajadores):
    global TAREA
    problema = Problem()
    variables = list()
    for objTrabajador in trabajadores:
        dominio = range(0, objTrabajador.capacidad + 1)
        variable = str(objTrabajador.id)
        variables.append(problema.addVariable(variable, dominio))

    while (TAREA > 0):
        promedioActual = Trabajar(trabajadores)
        TAREA -= 1

    ImprimirSalida(promedioActual, trabajadores)
Пример #30
0
def solve(sudoku_data):
    """ Solves the sudoku using simple constraints programming.
    Returns a list of solutions. Multiple solutions may be found if
    the sudoku wasn't parsed correctly.
    """
    problem = Problem()
    # add known numbers
    for i in range(0, 81):
        problem.addVariable(i, [int(sudoku_data[i])]
                                   if sudoku_data[i]
                                   else range(1, 10))
    for i in range(0, 9):
        # row constraint
        problem.addConstraint(AllDifferentConstraint(),
                              range(i * 9, i * 9 + 9))
        # column constraint
        problem.addConstraint(AllDifferentConstraint(),
                              [(i + 9 * c) for c in range(0, 9)])
        # box constraint
        problem.addConstraint(AllDifferentConstraint(),
                              [(i * 3) + (i / 3 * 18) + (9 * j) + k
                                  for j in range(0, 3)
                                    for k in range(0, 3)])
    return problem.getSolutions()
Пример #31
0
    def determine(state):
        card_played_this_round = [
            card is not None and 1 or 0
            for card in state.cards_played_by_player
        ]
        remaining_hand_size = 5 - sum(state.tricks_won_by_team)
        hand_size_by_player = [
            remaining_hand_size - played for played in card_played_this_round
        ]
        cards = list(
            set(deal()) - set(list(chain(*state.hands))) -
            set(state.cards_played))
        shuffle(cards)

        problem = Problem()
        for player in range(4):
            if state.hands[player]:
                for card_index, card in enumerate(state.hands[player]):
                    problem.addVariable((player, card_index), [card])
            else:
                voids_by_player = state.voids_by_player[player]
                for card_index in range(hand_size_by_player[player]):
                    if voids_by_player:
                        potential_cards = potential_cards_given_voids(
                            state.trump, voids_by_player, cards)
                        shuffle(potential_cards)
                        problem.addVariable((player, card_index),
                                            potential_cards)
                    else:
                        problem.addVariable((player, card_index), cards)
        problem.addConstraint(AllDifferentConstraint())

        cards = sorted(iteritems(problem.getSolution()))
        hands = [[], [], [], []]
        for player in range(4):
            hands[player] = [c[1] for c in cards[:hand_size_by_player[player]]]
            del cards[:hand_size_by_player[player]]

        state = state._replace(hands=hands)
        return state
Пример #32
0
    def determine(state):
        card_played_this_round = [card is not None and 1 or 0
                                  for card in state.cards_played_by_player]
        remaining_hand_size = 5 - sum(state.tricks_won_by_team)
        hand_size_by_player = [remaining_hand_size - played
                               for played in card_played_this_round]
        cards = list(set(deal()) -
                     set(list(chain(*state.hands))) -
                     set(state.cards_played))
        shuffle(cards)

        problem = Problem()
        for player in range(4):
            if state.hands[player]:
                for card_index, card in enumerate(state.hands[player]):
                    problem.addVariable((player, card_index),
                                        [card])
            else:
                voids_by_player = state.voids_by_player[player]
                for card_index in range(hand_size_by_player[player]):
                    if voids_by_player:
                        potential_cards = potential_cards_given_voids(
                            state.trump, voids_by_player, cards)
                        shuffle(potential_cards)
                        problem.addVariable((player, card_index),
                                            potential_cards)
                    else:
                        problem.addVariable((player, card_index), cards)
        problem.addConstraint(AllDifferentConstraint())

        cards = sorted(iteritems(problem.getSolution()))
        hands = [[], [], [], []]
        for player in range(4):
            hands[player] = [c[1] for c in cards[:hand_size_by_player[player]]]
            del cards[:hand_size_by_player[player]]

        state = state._replace(hands=hands)
        return state
Пример #33
0
class CSPSolver(Solver):
    """Solver reducing the task to a Constraint Satisfaction Problem.

    Solving this done with the python-constraint module.

    The variables are the quantum numbers of particles/edges, but also some
    composite quantum numbers which are attributed to the interaction nodes
    (such as angular momentum :math:`L`). The conservation rules serve as the
    constraints and a special wrapper class serves as an adapter.
    """

    # pylint: disable=too-many-instance-attributes
    def __init__(self,
                 allowed_intermediate_particles: List[GraphEdgePropertyMap]):
        self.__variables: Set[Union[_EdgeVariableInfo,
                                    _NodeVariableInfo]] = set()
        self.__var_string_to_data: Dict[str, Union[_EdgeVariableInfo,
                                                   _NodeVariableInfo]] = {}
        self.__node_rules: Dict[int, Set[Rule]] = defaultdict(set)
        self.__non_executable_node_rules: Dict[int,
                                               Set[Rule]] = defaultdict(set)
        self.__edge_rules: Dict[int, Set[GraphElementRule]] = defaultdict(set)
        self.__non_executable_edge_rules: Dict[
            int, Set[GraphElementRule]] = defaultdict(set)
        self.__problem = Problem(BacktrackingSolver(True))
        self.__allowed_intermediate_particles = allowed_intermediate_particles
        self.__scoresheet = Scoresheet()

    def find_solutions(self, problem_set: QNProblemSet) -> QNResult:
        # pylint: disable=too-many-locals
        self.__initialize_constraints(problem_set)
        solutions = self.__problem.getSolutions()

        node_not_executed_rules = self.__non_executable_node_rules
        node_not_satisfied_rules: Dict[int, Set[Rule]] = defaultdict(set)
        edge_not_executed_rules = self.__non_executable_edge_rules
        edge_not_satisfied_rules: Dict[
            int, Set[GraphElementRule]] = defaultdict(set)
        for node_id, rules in self.__node_rules.items():
            for rule in rules:
                if self.__scoresheet.rule_calls[(node_id, rule)] == 0:
                    node_not_executed_rules[node_id].add(rule)
                elif self.__scoresheet.rule_passes[(node_id, rule)] == 0:
                    node_not_satisfied_rules[node_id].add(rule)

        for edge_id, edge_rules in self.__edge_rules.items():
            for rule in edge_rules:
                if self.__scoresheet.rule_calls[(edge_id, rule)] == 0:
                    edge_not_executed_rules[edge_id].add(rule)
                elif self.__scoresheet.rule_passes[(edge_id, rule)] == 0:
                    edge_not_satisfied_rules[edge_id].add(rule)

        solutions = self.__convert_solution_keys(solutions)

        # insert particle instances
        if self.__node_rules or self.__edge_rules:
            full_particle_solutions = (
                _merge_particle_candidates_with_solutions(
                    solutions,
                    problem_set.topology,
                    self.__allowed_intermediate_particles,
                ))
        else:
            full_particle_solutions = [
                QuantumNumberSolution(
                    node_quantum_numbers=problem_set.initial_facts.node_props,
                    edge_quantum_numbers=problem_set.initial_facts.edge_props,
                )
            ]

        if full_particle_solutions and (node_not_executed_rules
                                        or edge_not_executed_rules):
            # rerun solver on these graphs using not executed rules
            # and combine results
            result = QNResult()
            for full_particle_solution in full_particle_solutions:
                node_props = full_particle_solution.node_quantum_numbers
                edge_props = full_particle_solution.edge_quantum_numbers
                node_props.update(problem_set.initial_facts.node_props)
                edge_props.update(problem_set.initial_facts.edge_props)
                result.extend(
                    validate_full_solution(
                        QNProblemSet(
                            topology=problem_set.topology,
                            initial_facts=GraphElementProperties(
                                node_props=node_props,
                                edge_props=edge_props,
                            ),
                            solving_settings=GraphSettings(
                                node_settings={
                                    i: NodeSettings(conservation_rules=rules)
                                    for i, rules in
                                    node_not_executed_rules.items()
                                },
                                edge_settings={
                                    i: EdgeSettings(conservation_rules=rules)
                                    for i, rules in
                                    edge_not_executed_rules.items()
                                },
                            ),
                        )))
            return result

        return QNResult(
            full_particle_solutions,
            _convert_non_executed_rules_to_names(node_not_executed_rules),
            _convert_violated_rules_to_names(node_not_satisfied_rules),
            _convert_non_executed_rules_to_names(edge_not_executed_rules),
            _convert_violated_rules_to_names(edge_not_satisfied_rules),
        )

    def __clear(self) -> None:
        self.__variables = set()
        self.__var_string_to_data = {}
        self.__node_rules = defaultdict(set)
        self.__edge_rules = defaultdict(set)
        self.__problem = Problem(BacktrackingSolver(True))
        self.__scoresheet = Scoresheet()

    def __initialize_constraints(self, problem_set: QNProblemSet) -> None:
        """Initialize all of the constraints for this graph.

        For each interaction node a set of independent constraints/conservation
        laws are created. For each conservation law a new CSP wrapper is
        created. This wrapper needs all of the qn numbers/variables which enter
        or exit the node and play a role for this conservation law. Hence
        variables are also created within this method.
        """
        # pylint: disable=too-many-locals

        self.__clear()

        def get_rules_by_priority(
            graph_element_settings: Union[NodeSettings, EdgeSettings, ]
        ) -> List[Rule]:
            # first add priorities to the entries
            priority_list = [
                (x, graph_element_settings.rule_priorities[type(x)]) if type(x)
                in graph_element_settings.rule_priorities else (x, 1)
                for x in graph_element_settings.conservation_rules
            ]
            # then sort according to priority
            sorted_list = sorted(priority_list,
                                 key=lambda x: x[1],
                                 reverse=True)
            # and strip away the priorities again
            return [x[0] for x in sorted_list]

        arg_handler = RuleArgumentHandler()

        for edge_id in problem_set.topology.edges:
            edge_settings = problem_set.solving_settings.edge_settings[edge_id]
            for rule in get_rules_by_priority(edge_settings):
                variable_mapping = _VariableContainer()
                # from cons law and graph determine needed var lists
                edge_qns, node_qns = get_required_qns(rule)

                edge_vars, fixed_edge_vars = self.__create_edge_variables(
                    [
                        edge_id,
                    ],
                    edge_qns,
                    problem_set,
                )

                score_callback = self.__scoresheet.register_rule(edge_id, rule)
                constraint = _GraphElementConstraint[EdgeQuantumNumber](
                    rule,  # type: ignore
                    edge_vars,
                    fixed_edge_vars,
                    arg_handler,
                    score_callback,
                )

                if edge_vars:
                    var_strings = [
                        _create_variable_string(*x) for x in edge_vars
                    ]
                    self.__edge_rules[edge_id].add(rule)  # type: ignore
                    self.__problem.addConstraint(constraint, var_strings)
                else:
                    self.__non_executable_edge_rules[edge_id].add(
                        rule  # type: ignore
                    )

        for node_id in problem_set.topology.nodes:
            for rule in get_rules_by_priority(
                    problem_set.solving_settings.node_settings[node_id]):
                variable_mapping = _VariableContainer()
                # from cons law and graph determine needed var lists
                edge_qns, node_qns = get_required_qns(rule)

                in_edges = problem_set.topology.get_edge_ids_ingoing_to_node(
                    node_id)
                in_edge_vars = self.__create_edge_variables(
                    in_edges, edge_qns, problem_set)
                variable_mapping.ingoing_edge_variables = in_edge_vars[0]
                variable_mapping.fixed_ingoing_edge_variables = in_edge_vars[1]
                var_list: List[Union[
                    _EdgeVariableInfo, _NodeVariableInfo]] = list(
                        variable_mapping.ingoing_edge_variables)

                out_edges = (problem_set.topology.
                             get_edge_ids_outgoing_from_node(node_id))
                out_edge_vars = self.__create_edge_variables(
                    out_edges, edge_qns, problem_set)
                variable_mapping.outgoing_edge_variables = out_edge_vars[0]
                variable_mapping.fixed_outgoing_edge_variables = out_edge_vars[
                    1]
                var_list.extend(list(variable_mapping.outgoing_edge_variables))

                # now create variables for node/interaction qns
                int_node_vars = self.__create_node_variables(
                    node_id,
                    node_qns,
                    problem_set,
                )
                variable_mapping.node_variables = int_node_vars[0]
                variable_mapping.fixed_node_variables = int_node_vars[1]
                var_list.extend(list(variable_mapping.node_variables))

                score_callback = self.__scoresheet.register_rule(node_id, rule)
                if len(inspect.signature(rule).parameters) == 1:
                    constraint = _GraphElementConstraint[NodeQuantumNumber](
                        rule,  # type: ignore
                        int_node_vars[0],
                        {
                            node_id: int_node_vars[1]
                        },
                        arg_handler,
                        score_callback,
                    )
                else:
                    constraint = _ConservationRuleConstraintWrapper(
                        rule, variable_mapping, arg_handler, score_callback)
                if var_list:
                    var_strings = [
                        _create_variable_string(*x) for x in var_list
                    ]
                    self.__node_rules[node_id].add(rule)
                    self.__problem.addConstraint(constraint, var_strings)
                else:
                    self.__non_executable_node_rules[node_id].add(rule)

    def __create_node_variables(
        self,
        node_id: int,
        qn_list: Set[Type[NodeQuantumNumber]],
        problem_set: QNProblemSet,
    ) -> Tuple[Set[_NodeVariableInfo], GraphNodePropertyMap]:
        """Create variables for the quantum numbers of the specified node.

        If a quantum number is already defined for a node, then a fixed
        variable is created, which cannot be changed by the csp solver.
        Otherwise the node is initialized with the specified domain of that
        quantum number.
        """
        variables: Tuple[Set[_NodeVariableInfo], GraphNodePropertyMap] = (
            set(),
            dict(),
        )

        if node_id in problem_set.initial_facts.node_props:
            node_props = problem_set.initial_facts.node_props[node_id]
            for qn_type in qn_list:
                if qn_type in node_props:
                    variables[1].update({qn_type: node_props[qn_type]})
        else:
            node_settings = problem_set.solving_settings.node_settings[node_id]
            for qn_type in qn_list:
                var_info = (node_id, qn_type)
                if qn_type in node_settings.qn_domains:
                    qn_domain = node_settings.qn_domains[qn_type]
                    self.__add_variable(var_info, qn_domain)
                    variables[0].add(var_info)
        return variables

    def __create_edge_variables(
        self,
        edge_ids: Sequence[int],
        qn_list: Set[Type[EdgeQuantumNumber]],
        problem_set: QNProblemSet,
    ) -> Tuple[Set[_EdgeVariableInfo], Dict[int, GraphEdgePropertyMap]]:
        """Create variables for the quantum numbers of the specified edges.

        If a quantum number is already defined for an edge, then a fixed
        variable is created, which cannot be changed by the csp solver. This is
        the case for initial and final state edges. Otherwise the edges are
        initialized with the specified domains of that quantum number.
        """
        variables: Tuple[Set[_EdgeVariableInfo],
                         Dict[int, GraphEdgePropertyMap], ] = (
                             set(),
                             dict(),
                         )

        for edge_id in edge_ids:
            variables[1][edge_id] = {}
            if edge_id in problem_set.initial_facts.edge_props:
                edge_props = problem_set.initial_facts.edge_props[edge_id]
                for qn_type in qn_list:
                    if qn_type in edge_props:
                        variables[1][edge_id].update(
                            {qn_type: edge_props[qn_type]})
            else:
                edge_settings = problem_set.solving_settings.edge_settings[
                    edge_id]
                for qn_type in qn_list:
                    var_info = (edge_id, qn_type)
                    if qn_type in edge_settings.qn_domains:
                        qn_domain = edge_settings.qn_domains[qn_type]
                        self.__add_variable(var_info, qn_domain)
                        variables[0].add(var_info)
        return variables

    def __add_variable(
        self,
        var_info: Union[_EdgeVariableInfo, _NodeVariableInfo],
        domain: List[Any],
    ) -> None:
        if var_info not in self.__variables:
            self.__variables.add(var_info)
            var_string = _create_variable_string(*var_info)
            self.__var_string_to_data[var_string] = var_info
            self.__problem.addVariable(var_string, domain)

    def __convert_solution_keys(
        self,
        solutions: List[Dict[str, Scalar]],
    ) -> List[QuantumNumberSolution]:
        """Convert keys of CSP solutions from string to quantum number types."""
        converted_solutions = list()
        for solution in solutions:
            edge_quantum_numbers: Dict[
                int, GraphEdgePropertyMap] = defaultdict(dict)
            node_quantum_numbers: Dict[
                int, GraphNodePropertyMap] = defaultdict(dict)
            for var_string, value in solution.items():
                ele_id, qn_type = self.__var_string_to_data[var_string]

                if qn_type in getattr(  # noqa: B009
                        EdgeQuantumNumber, "__args__"):
                    edge_quantum_numbers[ele_id].update({qn_type:
                                                         value}  # type: ignore
                                                        )
                else:
                    node_quantum_numbers[ele_id].update({qn_type:
                                                         value}  # type: ignore
                                                        )
            converted_solutions.append(
                QuantumNumberSolution(node_quantum_numbers,
                                      edge_quantum_numbers))

        return converted_solutions
Пример #34
0
def main(puzzle, lines):
    puzzle = puzzle.rstrip().splitlines()
    while puzzle and not puzzle[0]:
        del puzzle[0]

    # Extract horizontal words
    horizontal = []
    word = []
    predefined = {}
    for row in range(len(puzzle)):
        for col in range(len(puzzle[row])):
            char = puzzle[row][col]
            if not char.isspace():
                word.append((row, col))
                if char != "#":
                    predefined[row, col] = char
            elif word:
                if len(word) > MINLEN:
                    horizontal.append(word[:])
                del word[:]
        if word:
            if len(word) > MINLEN:
                horizontal.append(word[:])
            del word[:]

    # Extract vertical words
    vertical = []
    validcol = True
    col = 0
    while validcol:
        validcol = False
        for row in range(len(puzzle)):
            if col >= len(puzzle[row]):
                if word:
                    if len(word) > MINLEN:
                        vertical.append(word[:])
                    del word[:]
            else:
                validcol = True
                char = puzzle[row][col]
                if not char.isspace():
                    word.append((row, col))
                    if char != "#":
                        predefined[row, col] = char
                elif word:
                    if len(word) > MINLEN:
                        vertical.append(word[:])
                    del word[:]
        if word:
            if len(word) > MINLEN:
                vertical.append(word[:])
            del word[:]
        col += 1

    # hnames = ["h%d" % i for i in range(len(horizontal))]
    # vnames = ["v%d" % i for i in range(len(vertical))]

    # problem = Problem(MinConflictsSolver())
    problem = Problem()

    for hi, hword in enumerate(horizontal):
        for vi, vword in enumerate(vertical):
            for hchar in hword:
                if hchar in vword:
                    hci = hword.index(hchar)
                    vci = vword.index(hchar)
                    problem.addConstraint(
                        lambda hw, vw, hci=hci, vci=vci: hw[hci] == vw[vci],
                        ("h%d" % hi, "v%d" % vi))

    for char, letter in predefined.items():
        for hi, hword in enumerate(horizontal):
            if char in hword:
                hci = hword.index(char)
                problem.addConstraint(
                    lambda hw, hci=hci, letter=letter: hw[hci] == letter,
                    ("h%d" % hi, ))
        for vi, vword in enumerate(vertical):
            if char in vword:
                vci = vword.index(char)
                problem.addConstraint(
                    lambda vw, vci=vci, letter=letter: vw[vci] == letter,
                    ("v%d" % vi, ))

    wordsbylen = {}
    for hword in horizontal:
        wordsbylen[len(hword)] = []
    for vword in vertical:
        wordsbylen[len(vword)] = []

    for line in lines:
        line = line.strip()
        l = len(line)
        if l in wordsbylen:
            wordsbylen[l].append(line.upper())

    for hi, hword in enumerate(horizontal):
        words = wordsbylen[len(hword)]
        random.shuffle(words)
        problem.addVariable("h%d" % hi, words)
    for vi, vword in enumerate(vertical):
        words = wordsbylen[len(vword)]
        random.shuffle(words)
        problem.addVariable("v%d" % vi, words)

    problem.addConstraint(AllDifferentConstraint())

    solution = problem.getSolution()
    if not solution:
        print("No solution found!")

    maxcol = 0
    maxrow = 0
    for hword in horizontal:
        for row, col in hword:
            if row > maxrow:
                maxrow = row
            if col > maxcol:
                maxcol = col
    for vword in vertical:
        for row, col in vword:
            if row > maxrow:
                maxrow = row
            if col > maxcol:
                maxcol = col

    matrix = []
    for row in range(maxrow + 1):
        matrix.append([" "] * (maxcol + 1))

    for variable in solution:
        if variable[0] == "v":
            word = vertical[int(variable[1:])]
        else:
            word = horizontal[int(variable[1:])]
        for (row, col), char in zip(word, solution[variable]):
            matrix[row][col] = char

    for row in range(maxrow + 1):
        for col in range(maxcol + 1):
            sys.stdout.write(matrix[row][col])
        sys.stdout.write("\n")
Пример #35
0
def main(puzzle, lines):
    puzzle = puzzle.rstrip().splitlines()
    while puzzle and not puzzle[0]:
        del puzzle[0]

    # Extract horizontal words
    horizontal = []
    word = []
    predefined = {}
    for row in range(len(puzzle)):
        for col in range(len(puzzle[row])):
            char = puzzle[row][col]
            if not char.isspace():
                word.append((row, col))
                if char != "#":
                    predefined[row, col] = char
            elif word:
                if len(word) > MINLEN:
                    horizontal.append(word[:])
                del word[:]
        if word:
            if len(word) > MINLEN:
                horizontal.append(word[:])
            del word[:]

    # Extract vertical words
    vertical = []
    validcol = True
    col = 0
    while validcol:
        validcol = False
        for row in range(len(puzzle)):
            if col >= len(puzzle[row]):
                if word:
                    if len(word) > MINLEN:
                        vertical.append(word[:])
                    del word[:]
            else:
                validcol = True
                char = puzzle[row][col]
                if not char.isspace():
                    word.append((row, col))
                    if char != "#":
                        predefined[row, col] = char
                elif word:
                    if len(word) > MINLEN:
                        vertical.append(word[:])
                    del word[:]
        if word:
            if len(word) > MINLEN:
                vertical.append(word[:])
            del word[:]
        col += 1

    # hnames = ["h%d" % i for i in range(len(horizontal))]
    # vnames = ["v%d" % i for i in range(len(vertical))]

    # problem = Problem(MinConflictsSolver())
    problem = Problem()

    for hi, hword in enumerate(horizontal):
        for vi, vword in enumerate(vertical):
            for hchar in hword:
                if hchar in vword:
                    hci = hword.index(hchar)
                    vci = vword.index(hchar)
                    problem.addConstraint(lambda hw, vw, hci=hci, vci=vci:
                                          hw[hci] == vw[vci],
                                          ("h%d" % hi, "v%d" % vi))

    for char, letter in predefined.items():
        for hi, hword in enumerate(horizontal):
            if char in hword:
                hci = hword.index(char)
                problem.addConstraint(lambda hw, hci=hci, letter=letter:
                                      hw[hci] == letter, ("h%d" % hi,))
        for vi, vword in enumerate(vertical):
            if char in vword:
                vci = vword.index(char)
                problem.addConstraint(lambda vw, vci=vci, letter=letter:
                                      vw[vci] == letter, ("v%d" % vi,))

    wordsbylen = {}
    for hword in horizontal:
        wordsbylen[len(hword)] = []
    for vword in vertical:
        wordsbylen[len(vword)] = []

    for line in lines:
        line = line.strip()
        l = len(line)
        if l in wordsbylen:
            wordsbylen[l].append(line.upper())

    for hi, hword in enumerate(horizontal):
        words = wordsbylen[len(hword)]
        random.shuffle(words)
        problem.addVariable("h%d" % hi, words)
    for vi, vword in enumerate(vertical):
        words = wordsbylen[len(vword)]
        random.shuffle(words)
        problem.addVariable("v%d" % vi, words)

    problem.addConstraint(AllDifferentConstraint())

    solution = problem.getSolution()
    if not solution:
        print("No solution found!")

    maxcol = 0
    maxrow = 0
    for hword in horizontal:
        for row, col in hword:
            if row > maxrow:
                maxrow = row
            if col > maxcol:
                maxcol = col
    for vword in vertical:
        for row, col in vword:
            if row > maxrow:
                maxrow = row
            if col > maxcol:
                maxcol = col

    matrix = []
    for row in range(maxrow + 1):
        matrix.append([" "] * (maxcol + 1))

    for variable in solution:
        if variable[0] == "v":
            word = vertical[int(variable[1:])]
        else:
            word = horizontal[int(variable[1:])]
        for (row, col), char in zip(word, solution[variable]):
            matrix[row][col] = char

    for row in range(maxrow + 1):
        for col in range(maxcol + 1):
            sys.stdout.write(matrix[row][col])
        sys.stdout.write("\n")
Пример #36
0
        print("|%10s| %12s | %12s | %12s | %12s | %12s | %12s | %12s |" %
              (horas[i], horario[7 * i], horario[7 * i + 1],
               horario[7 * i + 2], horario[7 * i + 3], horario[7 * i + 4],
               horario[7 * i + 5], horario[7 * i + 6]))

        print("|__________|" + "______________|" * 7)


#---------------------------------------------------------------------------

from constraint import Problem, AllDifferentConstraint

problema = Problem()

#Primer semestre
problema.addVariable("calc_1", [7])
problema.addVariable("geom", [14])
problema.addVariable("alg_sup", [21])
problema.addVariable("apren", [28])
problema.addVariable("intro_cc", [35, 39, 40])
problema.addVariable("diseño_algo", [42, 46, 47])

#Tercer semestre
problema.addVariable("calc_3", [43, 44])
problema.addVariable("ec_difs", [15, 22, 29])
problema.addVariable("fluidos", [22, 15, 29])
problema.addVariable("progra_avan", [33, 40, 47])
problema.addVariable("análi_num1", [39, 32, 46])
problema.addVariable("expre_oe", [8])

#Quinto semestre
Пример #37
0
def derive_depths(original_markers, additional_constraints=[]):
    """Use constraint programming to derive the paragraph depths associated
    with a list of paragraph markers. Additional constraints (e.g. expected
    marker types, etc.) can also be added. Such constraints are functions of
    two parameters, the constraint function (problem.addConstraint) and a
    list of all variables"""
    if not original_markers:
        return []
    problem = Problem()
    marker_list = _compress_markerless(original_markers)

    # Depth in the tree, with an arbitrary limit of 10
    problem.addVariables(["depth" + str(i) for i in range(len(marker_list))],
                         range(10))

    # Always start at depth 0
    problem.addConstraint(rules.must_be(0), ("depth0",))

    all_vars = []
    for idx, marker in enumerate(marker_list):
        type_var = "type{}".format(idx)
        depth_var = "depth{}".format(idx)
        # Index within the marker list. Though this variable is redundant, it
        # makes the code easier to understand and doesn't have a significant
        # performance penalty
        idx_var = "idx{}".format(idx)

        typ_opts = [t for t in markers.types if marker in t]
        idx_opts = [i for t in typ_opts for i in range(len(t))
                    if t[i] == marker]
        problem.addVariable(type_var, typ_opts)
        problem.addVariable(idx_var, idx_opts)

        problem.addConstraint(rules.type_match(marker), [type_var, idx_var])
        all_vars.extend([type_var, idx_var, depth_var])

        if idx > 0:
            pairs = all_vars[3*(idx-1):]
            problem.addConstraint(rules.depth_check, pairs)

        if idx > 1:
            pairs = all_vars[3*(idx-2):]
            problem.addConstraint(rules.markerless_sandwich, pairs)
            problem.addConstraint(rules.star_sandwich, pairs)

    # separate loop so that the simpler checks run first
    for idx in range(1, len(marker_list)):
        # start with the current idx
        params = all_vars[3*idx:3*(idx+1)]
        # then add on all previous
        params += all_vars[:3*idx]
        problem.addConstraint(rules.sequence, params)

    # @todo: There's probably efficiency gains to making these rules over
    # prefixes (see above) rather than over the whole collection at once
    problem.addConstraint(rules.same_parent_same_type, all_vars)
    problem.addConstraint(rules.stars_occupy_space, all_vars)

    for constraint in additional_constraints:
        constraint(problem.addConstraint, all_vars)

    solutions = []
    for assignment in problem.getSolutionIter():
        assignment = _decompress_markerless(assignment, original_markers)
        solutions.append(Solution(assignment))
    return solutions
Пример #38
0
section_type_one = [
    make_section(course_sections[0]),
    make_section(course_sections[1])
]

section_type_two = [
    make_section(course_sections[2]),
    make_section(course_sections[6]),
    make_section(course_sections[7])
]

course_one = Course(section_type_one)
course_two = Course(section_type_two)

problem.addVariable('a', course_one.sections)
problem.addVariable('b', course_two.sections)

total_solutions = problem.getSolutions()
print('Total Pairs: {}'.format(get_number_of_pairs(total_solutions)))


# TODO: fix so it works when the a.end_time matches b.start_time or vice versa
def no_time_conflicts(a: CourseSection, b: CourseSection) -> bool:
    return (a.end_time < b.start_time or b.end_time < a.start_time) and \
           (a.end_time != b.end_time or a.start_time != b.start_time)


problem.addConstraint(no_time_conflicts, ['a', 'b'])

solution_set = problem.getSolutions()
Пример #39
0
class Scheduler(object):
    """
	This class provides the constraint-based Scheduler.
	"""
    def __init__(self, plant, orderList):
        """
		plant is a Plant instance to run the Scheduler on.
		orderList is the OrderList instance of incoming orders to the Plant.
		problem is a python-constraint Problem instance where solver is used as 
		the constraint solver.
		"""
        assert plant != None
        assert orderList != None

        self.printing = True

        self.plant = plant
        self.orderList = orderList
        self.problem = Problem()
        self.endMargin = 1
        self.machineMargin = 1

    def createMachineQuantityVarName(self, machine):
        """
		Creates and returns a python-constraint Variable name from a Machine 
		instance.
		"""
        assert type(machine) != str or type(machine) != unicode
        return str(machine.name) + "-quantity"

    def createEnterTimeVarName(self, order, machine):
        """
		Creates and returns a python-constraint Variable name from an Order 
		instance and a Machine instance.
		"""
        if type(machine) == str or type(machine) == unicode:
            machineName = machine
        else:
            machineName = machine.name
        return str(str(order.id) + "-enter-" + machineName)

    def createTimeAtMachineVarName(self, order, machine):
        """
		Creates and returns a python-constraint Variable name from an Order 
		instance and a Machine instance.
		"""
        if type(machine) == str or type(machine) == unicode:
            machineName = machine
        else:
            machineName = machine.name
        return str(str(order.id) + "-spend-" + machineName)

    def addPrecedenceConstraint(self, enterVar, order, machineIndex):
        """
		Adds a python-constraint Variable and Constraint to an order for the 
		precedence of Machine instances. Meaning that an order cannot get into 
		Machine 2 before getting into Machine 1. The sequence is determined by 
		the Plant instance. 
		"""
        prevMachine = self.plant.machines[machineIndex - 1]
        enterVar2 = self.createEnterTimeVarName(order, prevMachine)
        spendVar2 = self.createTimeAtMachineVarName(order, prevMachine)
        if order.recipe[prevMachine.name] != 0:
            if prevMachine.quantity <= \
               self.plant.machines[machineIndex].quantity \
               and prevMachine.canUnhook == False:
                self.problem.addConstraint(lambda x, y, yt: x == y + yt + \
                 self.plant.craneMoveTime, [enterVar, enterVar2, spendVar2])
            else:
                self.problem.addConstraint(lambda x, y, yt: x >= y + yt + \
                 self.plant.craneMoveTime, [enterVar, enterVar2, spendVar2])

    def addFinishTimeVar(self, order):
        """
		Adds a python-constraint Variable and Constraint to an order for the 
		finish time on the Plant.
		"""
        var = str(order.id) + "-finish"
        lastMachine = self.plant.machines[-1]
        self.problem.addVariable(
            var,
            range(order.deadline - self.endMargin,
                  order.deadline + self.endMargin))
        self.problem.addConstraint(lambda x, y, yt: x == y + yt, [
            var,
            self.createEnterTimeVarName(order, lastMachine),
            self.createTimeAtMachineVarName(order, lastMachine)
        ])

    def addOrderEnterTimeAtMachineVar(self, order, machineName, machineIndex):
        """
		Adds a python-constraint Variable and Constraint to an order for the 
		entrance time at a Machine instance.
		"""
        var = self.createEnterTimeVarName(order, machineName)
        if order.recipe[machineName] != 0:
            machineStart = (order.deadline + self.endMargin) - \
             order.recipe.calcMinProcTime(self.plant, machineName) - \
             self.machineMargin
            machineEnd = machineStart + self.machineMargin + \
             min(self.endMargin, self.machineMargin)
            variableRange = range(max(machineStart, 0), machineEnd)
        else:
            variableRange = range(0, 1)

        self.problem.addVariable(var, variableRange)
        if machineIndex != 0:
            self.addPrecedenceConstraint(var, order, machineIndex)

    def machineQuantityConstraintFunc(self, *args):
        quantity = args[0]
        argsMiddle = (len(args) - 1) / 2
        enterTimes = args[1:argsMiddle + 1]
        spendTimes = args[argsMiddle + 1:]

        assert len(enterTimes) == len(spendTimes)

        numberOfCommons = 0

        for i, et in enumerate(enterTimes):
            range1 = range(et, et + spendTimes[i])
            numberOfCommons = 0
            for j, et2 in enumerate(enterTimes):
                if i != j:
                    range2 = range(et2, et2 + spendTimes[j])
                    for v1 in range1:
                        if v1 in range2:
                            numberOfCommons += 1
                            break
        return not (numberOfCommons >= quantity)

    def addMachineQuantityConstraint(self, machine):
        enterVars = []
        spendVars = []

        for order in self.orderList.orders:
            enterVars.append(self.createEnterTimeVarName(order, machine))
            spendVars.append(self.createTimeAtMachineVarName(order, machine))

        vars = [self.createMachineQuantityVarName(machine)] + \
         enterVars + spendVars
        self.problem.addConstraint(self.machineQuantityConstraintFunc, vars)

    def machineCapacityConstraintFunc(self, *args):
        argsMiddle = len(args) / 2
        enterTimes = args[0:argsMiddle]
        nextEnterTimes = args[argsMiddle:]

        for i, et in enumerate(enterTimes):
            for j, et2 in enumerate(enterTimes):
                if i != j:
                    if et > et2 and nextEnterTimes[i] < nextEnterTimes[j]:
                        return False
        return True

    def addCapacityConstraint(self, machine, machineIndex):
        enterVars = []
        nextEnterVars = []

        nextMachine = self.plant.machines[machineIndex + 1]

        for order in self.orderList.orders:
            enterVars.append(self.createEnterTimeVarName(order, machine))
            nextEnterVars.append(
                self.createEnterTimeVarName(order, nextMachine))

        self.problem.addConstraint(self.machineCapacityConstraintFunc,
                                   enterVars + nextEnterVars)

    def run(self):
        """
		Runs the main Scheduler logic.
		"""
        for machine in self.plant.machines:
            var = self.createMachineQuantityVarName(machine)
            self.problem.addVariable(var, [machine.quantity])

        for machine in self.plant.machines:
            for order in self.orderList.orders:
                var = self.createTimeAtMachineVarName(order, machine)
                self.problem.addVariable(var, [order.recipe[machine.name]])

        for machineIndex, machine in enumerate(self.plant.machines):
            for order in self.orderList.orders:
                self.addOrderEnterTimeAtMachineVar(order, machine.name,
                                                   machineIndex)

        for machineIndex, machine in enumerate(self.plant.machines):
            if machine.precedence == True and \
               machineIndex != len(self.plant.machines) - 1:
                self.addCapacityConstraint(machine, machineIndex)
            self.addMachineQuantityConstraint(machine)

        for machineIndex, machine in enumerate(self.plant.machines):
            if len(machine.setOfBreaks()) != 0:
                for order in self.orderList.orders:
                    enterVar = self.createEnterTimeVarName(order, machine)
                    self.problem.addConstraint(
                        MachineBreaksConstraint(order, machine), [enterVar])

        for order in self.orderList.orders:
            self.addFinishTimeVar(order)

        pprint("SCHED Computing solutions...", BLUE, self.printing)
        solutions = self.problem.getSolutions()
        return solutions, len(solutions)

    def start(self, endMarginLimit=10, machineMarginLimit=10):
        pprint("SCHED Started...", BLUE, self.printing)
        self.endMargin = 1
        while self.endMargin <= endMarginLimit:
            self.machineMargin = 1
            while self.machineMargin <= machineMarginLimit:
                try:
                    pprint("SCHED End Margin: %d, Machine Margin: %d" % \
                     (self.endMargin, self.machineMargin), YELLOW, self.printing)
                    self.problem.reset()
                    solutions, numberOfSolutions = self.run()
                    if numberOfSolutions > 0:
                        return solutions
                except Exception as e:
                    pprint("SCHED Exception " + str(e), RED)
                    pprint("SCHED Trying new value for End Margin.", RED)
                    endMarginLimit += 1

                self.machineMargin += 1
            self.endMargin += 1
        pprint("SCHED No solutions found.", RED, self.printing)
        return None
Пример #40
0
from constraint import Problem

# Define variables for the CSP problem
problem = Problem()
problem.addVariable("f", [1])
problem.addVariable("t", [1, 2, 3, 4, 5, 6, 7, 8, 9])
problem.addVariable("u", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
problem.addVariable("w", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
problem.addVariable("r", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
problem.addVariable("o", [0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
problem.addVariable("c10", [0, 1])
problem.addVariable("c100", [0, 1])
problem.addVariable("c1000", [0, 1])

# Define the constraints for the CSP problem
problem.addConstraint(lambda o, r, c10: o + o == r + (10 * c10),
                      ("o", "r", "c10"))
problem.addConstraint(lambda w, u, c10, c100: c10 + w + w == u + (10 * c100),
                      ("w", "u", "c10", "c100"))
problem.addConstraint(
    lambda o, t, c100, c1000: c100 + t + t == o + (10 * c1000),
    ("o", "t", "c100", "c1000"))
problem.addConstraint(lambda f, c1000: f == c1000, ("f", "c1000"))
# All diff
problem.addConstraint(
    lambda f, t, u, w, r, o: len(set([f, t, u, w, r, o])) == 6,
    ("f", "t", "u", "w", "r", "o"))

# Solve the CSP problem
solutions = problem.getSolutions()
#!/usr/bin/env python
# encoding=utf-8 (pep 0263)

# je zapotrebi nainstaloval balicek python-constraint
# <https://github.com/python-constraint/python-constraint>
from constraint import Problem, AllDifferentConstraint

problem = Problem()
domain = range(10)
variables = ("S", "E", "N", "D", "M", "O", "R", "Y")
for name in variables:
    problem.addVariable(name, domain)
problem.addConstraint(lambda s: s > 0, ("S"))
problem.addConstraint(lambda m: m > 0, ("M"))
problem.addConstraint(AllDifferentConstraint())
problem.addConstraint(lambda s, e, n, d, m, o, r, y: \
                      1000 * s + 100 * e + 10 * n + d +
                      1000 * m + 100 * o + 10 * r + e ==
                      10000 * m + 1000 * o + 100 * n + 10 * e + y, variables)

# demonstracni vypis
if __name__ == "__main__":
    print("CLP - Algebrogram\n")

    print("  S E N D")
    print("+ M O R E")
    print("---------")
    print("M O N E Y\n")

    print("Vysledek volani problem.getSolutions():")
    solution = problem.getSolutions()[0]
Пример #42
0
def solve():
    problem = Problem()
    for i in range(1, 6):
        problem.addVariable("color%d" % i,
                            ["red", "white", "green", "yellow", "blue"])
        problem.addVariable("nationality%d" % i,
                            ["brit", "swede", "dane", "norwegian", "german"])
        problem.addVariable("drink%d" % i,
                            ["tea", "coffee", "milk", "beer", "water"])
        problem.addVariable("smoke%d" % i,
                            ["pallmall", "dunhill", "blends",
                             "bluemaster", "prince"])
        problem.addVariable("pet%d" % i,
                            ["dogs", "birds", "cats", "horses", "fish"])

    problem.addConstraint(AllDifferentConstraint(),
                          ["color%d" % i for i in range(1, 6)])
    problem.addConstraint(AllDifferentConstraint(),
                          ["nationality%d" % i for i in range(1, 6)])
    problem.addConstraint(AllDifferentConstraint(),
                          ["drink%d" % i for i in range(1, 6)])
    problem.addConstraint(AllDifferentConstraint(),
                          ["smoke%d" % i for i in range(1, 6)])
    problem.addConstraint(AllDifferentConstraint(),
                          ["pet%d" % i for i in range(1, 6)])

    for i in range(1, 6):

        # Hint 1
        problem.addConstraint(lambda nationality, color:
                              nationality != "brit" or color == "red",
                              ("nationality%d" % i, "color%d" % i))

        # Hint 2
        problem.addConstraint(lambda nationality, pet:
                              nationality != "swede" or pet == "dogs",
                              ("nationality%d" % i, "pet%d" % i))

        # Hint 3
        problem.addConstraint(lambda nationality, drink:
                              nationality != "dane" or drink == "tea",
                              ("nationality%d" % i, "drink%d" % i))

        # Hint 4
        if i < 5:
            problem.addConstraint(lambda colora, colorb:
                                  colora != "green" or colorb == "white",
                                  ("color%d" % i, "color%d" % (i + 1)))
        else:
            problem.addConstraint(lambda color: color != "green",
                                  ("color%d" % i,))

        # Hint 5
        problem.addConstraint(lambda color, drink:
                              color != "green" or drink == "coffee",
                              ("color%d" % i, "drink%d" % i))

        # Hint 6
        problem.addConstraint(lambda smoke, pet:
                              smoke != "pallmall" or pet == "birds",
                              ("smoke%d" % i, "pet%d" % i))

        # Hint 7
        problem.addConstraint(lambda color, smoke:
                              color != "yellow" or smoke == "dunhill",
                              ("color%d" % i, "smoke%d" % i))

        # Hint 8
        if i == 3:
            problem.addConstraint(lambda drink: drink == "milk",
                                  ("drink%d" % i,))

        # Hint 9
        if i == 1:
            problem.addConstraint(lambda nationality:
                                  nationality == "norwegian",
                                  ("nationality%d" % i,))

        # Hint 10
        if 1 < i < 5:
            problem.addConstraint(lambda smoke, peta, petb:
                                  smoke != "blends" or peta == "cats" or
                                  petb == "cats",
                                  ("smoke%d" % i, "pet%d" % (i - 1),
                                                  "pet%d" % (i + 1)))
        else:
            problem.addConstraint(lambda smoke, pet:
                                  smoke != "blends" or pet == "cats",
                                  ("smoke%d" % i,
                                   "pet%d" % (i == 1 and 2 or 4)))

        # Hint 11
        if 1 < i < 5:
            problem.addConstraint(lambda pet, smokea, smokeb:
                                  pet != "horses" or smokea == "dunhill" or
                                  smokeb == "dunhill",
                                  ("pet%d" % i, "smoke%d" % (i - 1),
                                                "smoke%d" % (i + 1)))
        else:
            problem.addConstraint(lambda pet, smoke:
                                  pet != "horses" or smoke == "dunhill",
                                  ("pet%d" % i,
                                   "smoke%d" % (i == 1 and 2 or 4)))

        # Hint 12
        problem.addConstraint(lambda smoke, drink:
                              smoke != "bluemaster" or drink == "beer",
                              ("smoke%d" % i, "drink%d" % i))

        # Hint 13
        problem.addConstraint(lambda nationality, smoke:
                              nationality != "german" or smoke == "prince",
                              ("nationality%d" % i, "smoke%d" % i))

        # Hint 14
        if 1 < i < 5:
            problem.addConstraint(lambda nationality, colora, colorb:
                                  nationality != "norwegian" or
                                  colora == "blue" or colorb == "blue",
                                  ("nationality%d" % i, "color%d" % (i - 1),
                                                        "color%d" % (i + 1)))
        else:
            problem.addConstraint(lambda nationality, color:
                                  nationality != "norwegian" or
                                  color == "blue",
                                  ("nationality%d" % i,
                                   "color%d" % (i == 1 and 2 or 4)))

        # Hint 15
        if 1 < i < 5:
            problem.addConstraint(lambda smoke, drinka, drinkb:
                                  smoke != "blends" or
                                  drinka == "water" or drinkb == "water",
                                  ("smoke%d" % i, "drink%d" % (i - 1),
                                                  "drink%d" % (i + 1)))
        else:
            problem.addConstraint(lambda smoke, drink:
                                  smoke != "blends" or drink == "water",
                                  ("smoke%d" % i,
                                   "drink%d" % (i == 1 and 2 or 4)))

    solutions = problem.getSolutions()
    return solutions