def clues_3_4(Stdnts):
    """
    Combine clues 3 and 4 into a single clue.
    The Stdnt who studies CS has a $5,000 larger scholarship than Lynn.
    Marie has a $10,000 bigger scholarship than Lynn.
    """
    yield from Solver_FD.is_contiguous_in(
        [Const_Stdnt(name='Lynn'), Const_Stdnt(major='CS'), Const_Stdnt(name='Marie')], Stdnts)
示例#2
0
 def complete_col(self, col_index):
     if self.col_is_ok(col_index):
         if self.summands_sum_upper_bound(col_index) == self.summands_sum_lower_bound(col_index):
             (carry_out_var, sum_dig_var) = (self.carry_out_var(col_index), self.cols[col_index][-1])
             (carry_out, sum_dig) = divmod(self.summands_sum_upper_bound(col_index), 10)
             (carry_out_cvar, sum_dig_cvar) = (Const_FD({carry_out}), Const_FD({sum_dig}))
             yield from Solver_FD.unify_pairs_FD([(carry_out_var, carry_out_cvar), (sum_dig_var, sum_dig_cvar)])
         else: yield
示例#3
0
def set_up(board_size, trace=False):
    """ Set up the solver and All_Different for the transversals problem. """
    Solver_FD.set_up()
    # Solver_FD.propagate = True
    # Solver_FD.smallest_first = True

    # Create a Queen_FD for each column. Each has an initial range of {c+1 for c in range(board_size)}.
    vars = {Queen_FD(board_size=board_size) for _ in range(board_size)}
    All_Different(vars)

    # Keep a record of the vars in Queen_FD so that we can propagate diagonals.
    Queen_FD.vars = vars

    # Don't need constraints since every time a var is instantiated it is
    # propagated, which ensures that the constraints are always satisfied.
    solver_fd = Queens_Solver_FD(vars, constraints=set())
    solver_fd.trace = trace
    return solver_fd
示例#4
0
def set_up(sets, propagate, smallest_first):
    """ Set up the solver and All_Different for the transversals problem. """
    Solver_FD.set_up()

    # Create a Var_FD for each set. Its initial range is the entire set.
    vars = {Var_FD(s.domain) for s in sets}
    All_Different(vars)

    trace = propagate and smallest_first
    solver_fd = Solver_FD(vars,
                          propagate=propagate,
                          smallest_first=smallest_first,
                          trace=trace)
    if solver_fd.trace:
        print(f'{"~" * 90}\n')
        print('Following is the trace of the final search.')
        print(Solver_FD.to_str(sets))
        print(f'propagate: {propagate}; smallest_first: {smallest_first};\n')
    return solver_fd
示例#5
0
The search is a standard depth-first search with two heuristics: propagate
and smallest_first.
           
The search is done four time with different settings of propagate and smallest-first.
           
When propagate is true, once an element is selected as the representative of one set,
it is removed from consideration as a posible representative of other sets.

When smallest-first is true, the search selectes an element for an unrepresented set
by chosing the smallest unrepresented set to find a representative for.
           
When both propagate and smallest_first are true, a trace of the search is shown.
""")

    print('The sets for which to find a traversal are:\n',
          Solver_FD.to_str(sets), '\n')
    print('The (alphabetized) traversals are:')

    for propagate in [False, True]:
        for smallest_first in [False, True]:
            solver_fd = set_up(sets,
                               propagate=propagate,
                               smallest_first=smallest_first)
            sol_str_set = set()

            if solver_fd.trace:
                print(
                    '*: Var was directly instantiated--and propagated if propagation is on.\n'
                    '-: Var was indirectly instantiated but not propagated.\n')
            assert solver_fd.propagate == propagate and solver_fd.smallest_first == smallest_first
            for _ in solver_fd.solve():
def clue_d(Stdnts):
    """ A derived clue.  From the other clues can exclude some values at the start and end."""
    yield from Solver_FD.is_a_subsequence_of(
        [Const_Stdnt(name=Stdnt.names-{'Ada', 'Marie', 'Emmy'}, major=Stdnt.majors-{'CS'}),
         Const_Stdnt(), Const_Stdnt(),
         Const_Stdnt(name=Stdnt.names-{'Lynn'}, major=Stdnt.majors-{'Bio', 'CS', 'Phys'})], Stdnts)
def clue_5(Stdnts):
    """ Ada has a larger scholarship than the Stdnt who studies Bio. """
    yield from Solver_FD.is_a_subsequence_of(
        [Const_Stdnt(major='Bio'), Const_Stdnt(name='Ada')], Stdnts)
def clue_1(Stdnts):
    """ The student who studies Phys gets a smaller scholarship than Emmy. """
    yield from Solver_FD.is_a_subsequence_of(
        [Const_Stdnt(major='Phys'), Const_Stdnt(name='Emmy')], Stdnts)
def clue_d(Stdnts):
    """ A derived clue.  From the other clues can exclude some values at the start and end."""
    yield from Solver_FD.is_a_subsequence_of(
        [Const_Stdnt(name=Stdnt.names-{'Ada', 'Marie', 'Emmy'}, major=Stdnt.majors-{'CS'}),
         Const_Stdnt(), Const_Stdnt(),
         Const_Stdnt(name=Stdnt.names-{'Lynn'}, major=Stdnt.majors-{'Bio', 'CS', 'Phys'})], Stdnts)


if __name__ == '__main__':

    students = [Stdnt(name=Stdnt.names, major=Stdnt.majors) for _ in range(4)]
    name_vars = {std.name for std in students}
    major_vars = {std.major for std in students}

    Solver_FD.set_up()
    All_Different(name_vars)
    All_Different(major_vars)

    # Do the derived clue first since it sets 3 things and has no alternatives.
    # Do clue_3_4 next since it sets 3 things and after the derived clue has no alternatives.
    # Then clue_2 since it now has no alternatives.
    # Clue_5 finishes the job, again with no alternatives.
    # Can drop clue_1 since it is satisfied after clue 2.
    clues = [clue_d, clues_3_4, clue_2, clue_5]  #, clue_1]

    print('\nStudents:', ', '.join(sorted(Stdnt.names)))
    print('Majors:', ', '.join(sorted(Stdnt.majors)))
    print(""" The original clues
    1. The student who studies Phys gets a smaller scholarship than Emmy.
    2. Emmy studies either Bio or Math.