Пример #1
0
def main(argv: List[str]) -> None:
    size: int = 0
    try:
        opts: List[Tuple[str, str]]
        args: List[str]
        opts, args = getopt.getopt(argv, 'hs:', ['size='])
    except getopt.GetoptError:
        print('queens.py -s <size>')
        sys.exit(2)

    opt: str
    arg: str
    for opt, arg in opts:
        if opt == '-h':
            print('queens.py -s <size>')
            sys.exit(2)
        elif opt in ('-s', '--size'):
            try:
                size = int(arg)
            except ValueError:
                print('Error: size must be int. queens.py -s <size>')
                sys.exit(2)
    columns: List[int] = list(range(size))
    rows: Dict[int, List[int]] = {}
    for column in columns:
        rows[column] = list(range(size))
    csp: CSP[int, int] = CSP(columns, rows)
    for i in range(len(columns) - 1):
        for j in range(i + 1, len(columns)):
            csp.add_constraint(QueenArcConstraint(i, j))
    min_conflict: MinConflict[int, int] = MinConflict(
        csp, State[int, int]({i: 0
                              for i in range(size)}), 1000)
    solution, steps = min_conflict.solve()
    if solution is None:
        print("No solution found!")
    else:
        print(solution.assignment)
Пример #2
0
def create_n_queens_csp(n=8):
    """Create an N-Queen problem on the board of size n * n.

    You should call csp.add_variable() and csp.add_binary_factor().

    Args:
        n: int, number of queens, or the size of one dimension of the board.

    Returns
        csp: A CSP problem with correctly configured factor tables
        such that it can be solved by a weighted CSP solver
    """
    csp = CSP()
    # TODO: Problem a
    # TODO: BEGIN_YOUR_CODE
    for i in range(n):
        csp.add_variable('Q' + str(i), list(range(n)))    # the position of a queen in each row (from 0 to n-1)
    for i in range(n-1):
        for j in range(i+1, n):
            csp.add_binary_factor('Q' + str(i), 'Q' + str(j), lambda x, y: x != y)
            csp.add_binary_factor('Q' + str(i), 'Q' + str(j), lambda x, y: abs(x-y) != abs(j-i))
    # TODO: END_YOUR_CODE
    return csp
Пример #3
0
def nQueens(n, tableCnstr):
    '''Return an n-queens CSP, optionally use tableContraints'''
    i = 0
    dom = []
    for i in range(n):
        dom.append(i+1)

    vars = []
    for i in dom:
        vars.append(Variable('Q{}'.format(i), dom))

    cons = []
    for qi in range(len(dom)):
        for qj in range(qi+1, len(dom)):
            if tableCnstr:
                con = QueensTableConstraint("C(Q{},Q{})".format(qi+1,qj+1),
                                            vars[qi], vars[qj], qi+1, qj+1)
            else: con = QueensConstraint("C(Q{},Q{})".format(qi+1,qj+1),
                                        vars[qi], vars[qj], qi+1, qj+1)
            cons.append(con)

    csp = CSP("{}-Queens".format(n), vars, cons)
    return csp
Пример #4
0
def scheduling(courses, faculties, times, rooms, assigned_faculty):
    domains = {}
    # to append all possible courses' cases to domains
    for course in courses:
        domains[course] = list()
        for faculty in faculties:
            for time in times:
                for room in rooms:
                    domains[course].append([faculty, time, room])

    # Pairing two courses each.
    neighbors = parse_neighbors(
        """cs108: cs112;
                cs112: cs212; cs212: cs214; cs214: cs384;
                cs384: cs232; cs232: cs344; cs344: cs108""", courses)
    for type in [courses]:
        for A in type:
            for B in type:
                if A != B:
                    if B not in neighbors[A]:
                        neighbors[A].append(B)
                    if A not in neighbors[B]:
                        neighbors[B].append(A)

    def scheduling_constraint(A, a, B, b, recurse=0):
        # each course should be offered exactly once by the assigned faculty member.
        if assigned_faculty[A] != a[0] and assigned_faculty[B] != b[0]:
            return False
        # a faculty member can only teach one thing at a time.
        if a[0] == b[0] and a[1] == b[1]:
            return False
        # a room can only have one class at each time.
        if a[1] == b[1] and a[2] == b[2]:
            return False
        return True

    return CSP(courses, domains, neighbors, scheduling_constraint)
Пример #5
0
def main():
    GRID_SIZE = 9
    CB = CircuitBoard(GRID_SIZE)
    boxes = (
        # From Book
        "44",
        "33",
        "22",
        "61",
        "25",
        # More Squares
        "31",
        "17",
        "23",
        "11",
        "41",
        "32",
        "51",
        "14",
        # 9x9 area is full
    )
    locations = {}
    for box in boxes:
        locations[box] = CB.generate_domain(int(box[0]), int(box[1]))
    csp = CSP(boxes, locations)
    csp.add_constraint(CircuitBoardConstraint(boxes))
    solution = csp.backtracking_search()
    if solution is None:
        print("No Solution Found")
    else:
        for box, grid_locations in solution.items():
            print(
                f"Box: {box},"
                f"Grid Location: {[gl.__str__() for gl in grid_locations]},"
                f"Area: {len(grid_locations)}\n"
            )
    print_grid(solution, GRID_SIZE)
def create_n_queens_csp(n=8):
    """Create an N-Queen problem on the board of size n * n.

    You should call csp.add_variable() and csp.add_binary_factor().

    Args:
        n: int, number of queens, or the size of one dimension of the board.

    Returns
        csp: A CSP problem with correctly configured factor tables
        such that it can be solved by a weighted CSP solver
    """
    csp = CSP()
    # TODO: Problem a
    # TODO: BEGIN_YOUR_CODE
    vars = []
    for i in range(1, n + 1):
        # we suppose that on a board, we put in queens with order.
        # In other words, Xi is fixed for each queen,
        # we only have to consider Yi for each queen
        varName = 'Y' + str(i)
        csp.add_variable(varName, range(1, n + 1))
        vars.append(varName)

    rule1 = lambda x, y: x != y
    for var in vars:
        for anotherVar in vars:
            if var != anotherVar:
                # csp.add_binary_factor(var, anotherVar, lambda y1, y2: y1 != y2)
                dist = abs(vars.index(anotherVar) - vars.index(var))
                csp.add_binary_factor(
                    var, anotherVar,
                    lambda y1, y2: y1 != y2 and abs(y1 - y2) != dist)

    # raise NotImplementedError
    # TODO: END_YOUR_CODE
    return csp
Пример #7
0
def nQueens(n, model):
    '''Return an n-queens CSP, optionally use tableContraints'''
    #your implementation for Question 4 changes this function
    #implement handling of model == 'alldiff'
    if not model in ['table', 'alldiff', 'row']:
        print("Error wrong sudoku model specified {}. Must be one of {}").format(
            model, ['table', 'alldiff', 'row'])

    i = 0
    dom = []
    for i in range(n):
        dom.append(i+1)

    vars = []
    for i in dom:
        vars.append(Variable('Q{}'.format(i), dom))

    cons = []

    if model == 'alldiff':
        for qi in range(len(dom)):
            for qj in range(qi+1, len(dom)):
                con = NeqConstraint("C(Q{},Q{})".format(qi+1,qj+1),
                                            [vars[qi], vars[qj]], qi+1, qj+1)
                cons.append(con)
        cons.append(AllDiffConstraint("C(Q{})".format(n),vars))
    else:
        constructor = QueensTableConstraint if model == 'table' else QueensConstraint
        for qi in range(len(dom)):
            for qj in range(qi+1, len(dom)):
                con = constructor("C(Q{},Q{})".format(qi+1,qj+1),
                                            vars[qi], vars[qj], qi+1, qj+1)
                cons.append(con)

    csp = CSP("{}-Queens".format(n), vars, cons)
    return csp
Пример #8
0
def ClassSchedulingCSP():
    """Queens problem for the class scheduling problem. I've used the classes as the variables
    and combinations of time, professor, and classroom as the domains for each variable. The
    constraints are that no prof can teach two classes at the same time, no class can be in the
    same room at the same time as another class, and each course should be offered exactly once.
    """
    """Initialize data structures for the class scheduling problem."""
    classes = ['CS108', 'CS112', 'CS214', 'CS212', 'CS232', 'CS344']
    faculty = ['dschuurman', 'kvlinden', 'adams', 'norman']
    time_slots = ['mwf900', 'mwf1030', 'tth900', 'tth1030']
    classrooms = ['nh253', 'sb382']
    combination = [faculty, time_slots, classrooms]

    variables = classes
    domain = list(itertools.product(*combination))
    domains = {}
    neighbors = {}
    for var in variables:
        domains[var] = domain
        neighbors[var] = [x for x in variables if x != var]

    def constraints(A, a, B, b):
        # check if it's the same time
        if a[1] == b[1]:
            # check if profs are the same
            if a[0] == b[0]:
                return False
            # check if rooms are the same
            elif a[2] == b[2]:
                return False
            else:
                return True
        else:
            return True

    return CSP(variables, domains, neighbors, constraints)
Пример #9
0
def min_conflict_solve():
    req_data = request.get_json()
    k: int = req_data['k']
    init_state: List[int] = req_data['initState']
    iteration: int = req_data['iteration']
    columns: List[int] = list(range(k))
    rows: Dict[int, List[int]] = {}
    for column in columns:
        rows[column] = list(range(k))
    csp: CSP[int, int] = CSP(columns, rows)
    for i in range(len(columns) - 1):
        for j in range(i + 1, len(columns)):
            csp.add_constraint(QueenArcConstraint(i, j))
    min_conflict: MinConflict[int, int] = MinConflict(
        csp, State[int, int]({i: x
                              for i, x in enumerate(init_state)}), iteration)
    solution, steps, time = min_conflict.solve()
    response = app.response_class(response=json.dumps({
        "steps": steps,
        "time": time
    }),
                                  status=200,
                                  mimetype='application/json')
    return response
Пример #10
0
def run_experiment():
    kenken = KenKen(6, difficult)
    csp = CSP()
    csp.solve(kenken)
    print('RESULTS of AC3 Only')
    csp.print_solution()
    print('\nNow, try searching to reduce domains')
    A1domain = csp.variables['A1'].domain
    A2domain = csp.variables['A2'].domain
    A3domain = csp.variables['A3'].domain
    for i in A1domain:
        kenken.variables['A1'].domain = [i]
        kenken.variables['A2'].domain = A2domain
        kenken.variables['A3'].domain = A3domain
        answer = csp.solve(kenken)
        if answer == None:
            print('A1=', i, ' No Solution Found.')
            continue
        for j in A2domain:
            kenken.variables['A2'].domain = [j]
            kenken.variables['A3'].domain = A3domain
            answer = csp.solve(kenken)
            if answer == None:
                print('A1=', i, ' A2=', j, ' No Solution Found.')
                continue
            for k in A3domain:
                kenken.variables['A3'].domain = [k]
                answer = csp.solve(kenken)
                if answer == None:
                    print('A1=', i, ' A2=', j, ' A3=', k,
                          ' No Solution Found.')
                else:
                    # This is a viable combination
                    print('A1=', i, ' A2=', j, ' A3=', k)
                    csp.print_solution()
                    print("\n")
        # 모든 변수에 숫자를 할당해서 계싼이 맞는지 확인한다
        if len(assignment) == len(self.letters):
            s: int = assignment["S"]
            e: int = assignment["E"]
            n: int = assignment["N"]
            d: int = assignment["D"]
            m: int = assignment["M"]
            o: int = assignment["O"]
            r: int = assignment["R"]
            y: int = assignment["Y"]
            send: int = s * 1000 + e * 100 + n * 10 + d
            more: int = m * 1000 + o * 100 + r * 10 + e
            money: int = m * 10000 + o * 1000 + n * 100 + e * 10 + y
            return send + more == money
        return True


if __name__ == "__main__":
    letters: List[str] = ["S", "E", "N", "D", "M", "O", "R", "Y"]
    possible_digits: Dict[str, List[int]] = {}
    for letter in letters:
        possible_digits[letter] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    possible_digits["M"] = [1]  # 답은 0으로 시작하지 않는다
    csp: CSP[str, int] = CSP(letters, possible_digits)
    csp.add_constraint(SendMoreMoneyConstraint(letters))
    solution: Optional[Dict[str, int]] = csp.backtracking_search()
    if solution is None:
        print("답을 찾을 수 없습니다")
    else:
        print(solution)
Пример #12
0
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='mrv',
                 silent=False,
                 trace=False):
    # Your implementation for Question 6 goes here.
    #
    # Do not but do not change the functions signature
    # (the autograder will twig out if you do).

    # If the silent parameter is set to True
    # you must ensure that you do not execute any print statements
    # in this function.
    # (else the output of the autograder will become confusing).
    # So if you have any debugging print statements make sure you
    # only execute them "if not silent". (The autograder will call
    # this function with silent=True, plane_scheduling.py will call
    # this function with silent=False)

    # You can optionally ignore the trace parameter
    # If you implemented tracing in your FC and GAC implementations
    # you can set this argument to True for debugging.
    #
    # Once you have implemented this function you should be able to
    # run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    '''

    # BUILD your CSP here and store it in the varable csp
    variables = []
    constraints = []

    legal_order = [[f1, f2] for f1, f2 in planes_problem.can_follow]
    legal_order += [[f, 'None'] for f in planes_problem.flights]
    legal_order += [['None', 'None']]

    maintenance_flights = [f for f in planes_problem.maintenance_flights]
    maintenance_flights += ['None']

    for p in planes_problem.planes:
        legal_flights = planes_problem.can_fly(p)
        domain = [f for f in legal_flights] + ['None']
        flight_sequence = [
            Variable(p + '_%d' % i, domain)
            for i in range(1, len(legal_flights))
        ]
        flight_sequence = [
            Variable(p + '_0',
                     planes_problem.can_start(p) + ['None'])
        ] + flight_sequence
        variables += flight_sequence

        # Flight order
        for i in range(0, len(flight_sequence) - 1):
            f1, f2 = flight_sequence[i], flight_sequence[i + 1]
            constraints.append(
                TableConstraint(p + '_order%d' % i, [f1, f2], legal_order))

        # Flight maintenance
        if len(flight_sequence) >= planes_problem.min_maintenance_frequency:
            for i in range(
                    0,
                    len(flight_sequence) -
                    planes_problem.min_maintenance_frequency + 1):
                fs = flight_sequence[i:i +
                                     planes_problem.min_maintenance_frequency]
                constraints.append(
                    NValuesConstraint(p + '_maintenance%d' % i, fs,
                                      maintenance_flights, 1,
                                      len(flight_sequence)))

    # Every flight taken
    for f in planes_problem.flights:
        constraints.append(NValuesConstraint('flights', variables, [f], 1, 1))

    csp = CSP('plane_scheduling', variables, constraints)

    # invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns,
                                     trace)

    # Convert each solution into a list of lists specifying a schedule
    # for each plane in the format described above.

    # then return a list containing all converted solutions
    # (i.e., a list of lists of lists)
    all_solutions = []
    for s_raw in solutions:
        s = {p: [] for p in planes_problem.planes}
        for var, f in s_raw:
            if f == 'None':
                continue
            p, order = var.name().split('_')
            order = int(order)
            s[p].append((order, f))
        s = {p: sorted(s[p]) for p in s}
        s = [[p] + [f[1] for f in s[p]] for p in s]
        all_solutions.append(s)

    return all_solutions
Пример #13
0
    
    def satisfied(self, assignment: Dict[str, str]) -> bool:
        # If either place is not in the assignment, then it is not
        # yet possible for their colors to be conflicting
        if self.place1 not in assignment or self.place2 not in assignment:
            return True
        # check the color assigned to place1 is not the same as the # color assigned to place2
        return assignment[self.place1] != assignment[self.place2]

if __name__ == "__main__":
    variables: List[str] = ["MA", "PI", "CE", "RN", "PB", "PE", "AL", "SE", "BA"] 
    domains: Dict[str, List[str]] = {}
    for variable in variables:
        domains[variable] = ["red", "green", "blue"]
    
    csp: CSP[str, str] = CSP(variables, domains)
    csp.add_constraint(MapColoringConstraint("MA", "PI"))
    csp.add_constraint(MapColoringConstraint("PI", "CE"))
    csp.add_constraint(MapColoringConstraint("PI", "PE"))
    csp.add_constraint(MapColoringConstraint("PI", "BA"))
    csp.add_constraint(MapColoringConstraint("CE", "RN"))
    csp.add_constraint(MapColoringConstraint("CE", "PB"))
    csp.add_constraint(MapColoringConstraint("CE", "PE"))
    csp.add_constraint(MapColoringConstraint("RN", "PB"))
    csp.add_constraint(MapColoringConstraint("PB", "PE"))
    csp.add_constraint(MapColoringConstraint("PE", "AL"))
    csp.add_constraint(MapColoringConstraint("PE", "BA"))
    csp.add_constraint(MapColoringConstraint("AL", "SE"))
    csp.add_constraint(MapColoringConstraint("AL", "BA"))
    csp.add_constraint(MapColoringConstraint("SE", "BA"))
Пример #14
0
def question_3():
    print_title(2)
    tested[2] = True

    fails = [False, False, False, False, False, False, False, False]
    v1 = Variable('V1', [1, 2])
    v2 = Variable('V2', [1, 2])
    v3 = Variable('V3', [1, 2, 3, 4, 5])
    v4 = Variable('V4', [1, 2, 3, 4, 5])
    v5 = Variable('V5', [1, 2, 3, 4, 5])
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]
    ac = AllDiffConstraint('test9', vars)
    testcsp = CSP('test', vars, [ac])
    GacEnforce([ac], testcsp, None, None)

    #v1.pruneValue(1, None, None)

    test1 = "    v1 = Variable('V1', [1, 2])\n\
    v2 = Variable('V2', [1, 2])\n\
    v3 = Variable('V3', [1, 2, 3, 4, 5])\n\
    v4 = Variable('V4', [1, 2, 3, 4, 5])\n\
    v5 = Variable('V5', [1, 2, 3, 4, 5])\n\
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]\n\
    ac = AllDiffConstraint('test9', vars)\n\
    testcsp = CSP('test', vars, [ac])\n\
    GacEnforce([ac], testcsp, None, None)"

    soln_doms = [
        set([1, 2]),
        set([1, 2]),
        set([3, 4, 5]),
        set([3, 4, 5]),
        set([3, 4, 5]),
        set([6, 7, 8, 9]),
        set([6, 7, 8, 9]),
        set([6, 7, 8, 9]),
        set([6, 7, 8, 9])
    ]

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[0] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[0]:
        print "\nFail Q3 test 1\nErrors were generated on the following code:"
        print test1
    else:
        print "Pass Q3 test 1"
    print_sep()

    v1 = Variable('V1', [1, 2])
    v2 = Variable('V2', [1, 2])
    v3 = Variable('V3', [1, 2, 3, 4, 5])
    v4 = Variable('V4', [1, 2, 3, 4, 5])
    v5 = Variable('V5', [1, 2, 3, 4, 5])
    v6 = Variable('V6', [1, 3, 4, 5])
    v7 = Variable('V7', [1, 3, 4, 5])
    ac1 = AllDiffConstraint('1', [v1, v2, v3])
    ac2 = AllDiffConstraint('1', [v1, v2, v4])
    ac3 = AllDiffConstraint('1', [v1, v2, v5])
    ac4 = AllDiffConstraint('1', [v3, v4, v5, v6])
    ac5 = AllDiffConstraint('1', [v3, v4, v5, v7])
    vars = [v1, v2, v3, v4, v5, v6, v7]
    cnstrs = [ac1, ac2, ac3, ac4, ac5]
    testcsp = CSP('test2', vars, cnstrs)
    GacEnforce(cnstrs, testcsp, None, None)

    test2 = "    v1 = Variable('V1', [1, 2])\n\
    v2 = Variable('V2', [1, 2])\n\
    v3 = Variable('V3', [1, 2, 3, 4, 5])\n\
    v4 = Variable('V4', [1, 2, 3, 4, 5])\n\
    v5 = Variable('V5', [1, 2, 3, 4, 5])\n\
    v6 = Variable('V6', [1, 3, 4, 5])\n\
    v7 = Variable('V7', [1, 3, 4, 5])\n\
    ac1 = AllDiffConstraint('1', [v1,v2,v3])\n\
    ac2 = AllDiffConstraint('1', [v1,v2,v4])\n\
    ac3 = AllDiffConstraint('1', [v1,v2,v5])\n\
    ac4 = AllDiffConstraint('1', [v3,v4,v5,v6])\n\
    ac5 = AllDiffConstraint('1', [v3,v4,v5,v7])\n\
    vars = [v1, v2, v3, v4, v5, v6, v7]\n\
    cnstrs = [ac1,ac2,ac3,ac4,ac5]\n\
    testcsp = CSP('test2', vars, cnstrs)\n\
    GacEnforce(cnstrs, testcsp, None, None)"

    soln_doms = [
        set([1, 2]),
        set([1, 2]),
        set([3, 4, 5]),
        set([3, 4, 5]),
        set([3, 4, 5]),
        set([1]),
        set([1])
    ]

    #v1.pruneValue(1, None, None)

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[1] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[1]:
        print "\nFail Q3 test 2\nErrors were generated on the following code:"
        print test2
    else:
        print "Pass Q3 test 2"
    print_sep()

    csp = sudokuCSP(b1, 'neq')
    GacEnforce(csp.constraints(), csp, None, None)
    vars = csp.variables()
    vars.sort(key=lambda var: var.name())
    soln_doms = [
        set([3]),
        set([1]),
        set([2]),
        set([5]),
        set([9]),
        set([8]),
        set([7]),
        set([6]),
        set([4]),
        set([9]),
        set([4]),
        set([6]),
        set([7]),
        set([3]),
        set([1]),
        set([2]),
        set([5]),
        set([8]),
        set([8]),
        set([7]),
        set([5]),
        set([4]),
        set([2]),
        set([6]),
        set([9]),
        set([1]),
        set([3]),
        set([5]),
        set([6]),
        set([7]),
        set([8]),
        set([4]),
        set([2]),
        set([3]),
        set([9]),
        set([1]),
        set([4]),
        set([8]),
        set([1]),
        set([3]),
        set([6]),
        set([9]),
        set([5]),
        set([7]),
        set([2]),
        set([2]),
        set([9]),
        set([3]),
        set([1]),
        set([7]),
        set([5]),
        set([4]),
        set([8]),
        set([6]),
        set([1]),
        set([3]),
        set([8]),
        set([2]),
        set([5]),
        set([7]),
        set([6]),
        set([4]),
        set([9]),
        set([6]),
        set([5]),
        set([4]),
        set([9]),
        set([1]),
        set([3]),
        set([8]),
        set([2]),
        set([7]),
        set([7]),
        set([2]),
        set([9]),
        set([6]),
        set([8]),
        set([4]),
        set([1]),
        set([3]),
        set([5])
    ]

    #vars[0].pruneValue(3, None, None)

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[2] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[2]:
        print "\nFail Q3 test 3\nErrors were generated on the following code:"
        print "python2.7 sudoku.py -e -m neq 1"
    else:
        print "Pass Q3 test 3"
    print_sep()

    csp = sudokuCSP(b5, 'neq')
    GacEnforce(csp.constraints(), csp, None, None)
    vars = csp.variables()
    vars.sort(key=lambda var: var.name())
    soln_doms = [
        set([2, 4, 5, 8]),
        set([6]),
        set([2, 4, 5, 8]),
        set([1]),
        set([2, 5, 8]),
        set([3, 8]),
        set([7, 9]),
        set([3, 5, 7, 8]),
        set([3, 7, 8, 9]),
        set([1, 2, 5, 8]),
        set([1, 2, 5, 8]),
        set([7]),
        set([2, 3, 9]),
        set([2, 5, 6, 8]),
        set([3, 6, 8]),
        set([1, 6, 9]),
        set([3, 5, 6, 8]),
        set([4]),
        set([1, 5, 8]),
        set([9]),
        set([3]),
        set([4]),
        set([7]),
        set([6, 8]),
        set([1, 6]),
        set([5, 6, 8]),
        set([2]),
        set([2, 4, 8]),
        set([2, 4, 7, 8]),
        set([1]),
        set([6]),
        set([3]),
        set([9]),
        set([2, 4, 7]),
        set([2, 4, 7]),
        set([5]),
        set([5, 9]),
        set([5, 7]),
        set([5, 6, 9]),
        set([8]),
        set([4]),
        set([2]),
        set([1, 6, 7, 9]),
        set([3, 6, 7]),
        set([1, 3, 6, 7, 9]),
        set([3]),
        set([2, 4]),
        set([2, 4, 6, 9]),
        set([5]),
        set([1]),
        set([7]),
        set([8]),
        set([2, 4, 6]),
        set([6, 9]),
        set([6]),
        set([2, 4, 5, 8]),
        set([2, 4, 5, 8]),
        set([2, 7]),
        set([9]),
        set([4, 8]),
        set([3]),
        set([1]),
        set([7, 8]),
        set([7]),
        set([1, 2, 3, 4, 8]),
        set([2, 4, 8, 9]),
        set([2, 3]),
        set([2, 6, 8]),
        set([1, 3, 4, 6, 8]),
        set([5]),
        set([2, 4, 6, 8]),
        set([6, 8]),
        set([1, 2, 4, 8]),
        set([1, 2, 3, 4, 8]),
        set([2, 4, 8]),
        set([2, 3, 7]),
        set([2, 6, 8]),
        set([5]),
        set([2, 4, 6, 7]),
        set([9]),
        set([6, 7, 8])
    ]

    #vars[0].pruneValue(2, None, None)

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[3] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[3]:
        print "\nFail Q3 test 4\nErrors were generated on the following code:"
        print "python2.7 sudoku.py -e -m neq 5"
    else:
        print "Pass Q3 test 4"
    print_sep()

    v1 = Variable('V1', [1, 2])
    v2 = Variable('V2', [1, 2])
    v3 = Variable('V3', [1, 2, 3, 4, 5])
    v4 = Variable('V4', [1, 2, 3, 4, 5])
    v5 = Variable('V5', [1, 2, 3, 4, 5])
    v6 = Variable('V6', [1, 3, 4, 5])
    v7 = Variable('V7', [1, 3, 4, 5])
    ac1 = AllDiffConstraint('1', [v1, v2, v3])
    ac2 = AllDiffConstraint('1', [v1, v2, v4])
    ac3 = AllDiffConstraint('1', [v1, v2, v5])
    ac4 = AllDiffConstraint('1', [v3, v4, v5, v6])
    ac5 = AllDiffConstraint('1', [v3, v4, v5, v7])
    neq = NeqConstraint('2', [v6, v7])
    vars = [v1, v2, v3, v4, v5, v6, v7]
    cnstrs = [ac1, ac2, ac3, ac4, ac5, neq]
    testcsp = CSP('test2', vars, cnstrs)
    val = GacEnforce(cnstrs, testcsp, None, None)

    test5 = "    v1 = Variable('V1', [1, 2])\n\
    v2 = Variable('V2', [1, 2])\n\
    v3 = Variable('V3', [1, 2, 3, 4, 5])\n\
    v4 = Variable('V4', [1, 2, 3, 4, 5])\n\
    v5 = Variable('V5', [1, 2, 3, 4, 5])\n\
    v6 = Variable('V6', [1, 3, 4, 5])\n\
    v7 = Variable('V7', [1, 3, 4, 5])\n\
    ac1 = AllDiffConstraint('1', [v1,v2,v3])\n\
    ac2 = AllDiffConstraint('1', [v1,v2,v4])\n\
    ac3 = AllDiffConstraint('1', [v1,v2,v5])\n\
    ac4 = AllDiffConstraint('1', [v3,v4,v5,v6])\n\
    ac5 = AllDiffConstraint('1', [v3,v4,v5,v7])\n\
    neq = NeqConstraint('2', [v6,v7])\n\
    vars = [v1, v2, v3, v4, v5, v6, v7]\n\
    cnstrs = [ac1,ac2,ac3,ac4,ac5]\n\
    testcsp = CSP('test2', vars, cnstrs)\n\
    val = GacEnforce(cnstrs, testcsp, None, None)"

    #val = 'fo'

    if val != "DWO":
        fails[4] = True
        print "Error: GacEnforce failed to return \"DWO\" returned {} instead".format(
            val)

    if fails[4]:
        print "\nFail Q3 test 5\nErrors were generated on the following code:"
        print test5
    else:
        print "Pass Q3 test 5"
    print_sep()

    csp = nQueens(8, False)
    solutions, num_nodes = bt_search('GAC', csp, 'fixed', False, False)
    errors = csp.check(solutions)

    if len(errors) > 0:
        fails[5] = True
        print "Fail Q3 test 6: invalid solution(s) returned by GAC"
        for err in errors:
            print_soln(err[0])
            print "\n", err[1]

    if len(solutions) != 1:
        fails[5] = True
        print "Fail Q3 test 6: GAC failed to return only one solution"
        print "  returned: "
        for s in solutions:
            print_soln(s)
            print ""
    ok = True
    for v in csp.variables():
        if set(v.curDomain()) != set(v.domain()):
            fails[5] = True
            print "Fail Q3 test 6: GAC failed to restore domains of variables"

    if not fails[5]:
        print "Pass Q3 test 6"
    print_sep()

    csp = nQueens(8, False)
    solutions, num_nodes = bt_search('GAC', csp, 'fixed', True, False)
    errors = csp.check(solutions)

    if len(errors) > 0:
        fails[6] = True
        print "Fail Q3 test 7: invalid solution(s) returned by GAC"
        for err in errors:
            print_soln(err[0])
            print "\n", err[1]

    if len(solutions) != 92:
        fails[6] = True
        print "Fail Q3 test 7: GAC failed to return 92 solutions"
        print "  returned {} solutions".format(len(solutions))

    ok = True
    for v in csp.variables():
        if set(v.curDomain()) != set(v.domain()):
            fails[6] = True
            print "Fail Q3 test 7: GAC failed to restore domains of variables"

    if not fails[7]:
        print "Pass Q3 test 7"
    print_sep()

    grades[2] = 0
    if sum(fails[:4]) == 0:
        grades[2] += 3
        if not fails[4]:
            grades[2] += 1
        if grades[2] >= 3:
            if sum([fails[5], fails[6]]) == 0:
                grades[2] += 3
            m = assignment['M']
            o = assignment['O']
            r = assignment['R']
            y = assignment['Y']
            send = s * 1000 + e * 100 + n * 10 + d
            more = m * 1000 + o * 100 + r * 10 + e
            money = m * 10000 + o * 1000 + n * 100 + e * 10 + y

            return send + more == money

        # No conflict, ensures partial solution can continue to be worked on
        return True


if __name__ == '__main__':
    letters = list('SENDMORY')
    possible_digits = {}

    for letter in letters:
        possible_digits[letter] = list(range(10))

    possible_digits['M'] = [1]  # So we don't get answers starting with a 0
    csp = CSP(letters, possible_digits)
    csp.add_constraint(SendMoreMoneyConstraint(letters))
    solution = csp.backtracking_search()

    if solution is None:
        print('No solution found!')
    else:
        print(solution)
Пример #16
0
    def satisfied(self, assignment: Dict[str, List[GridLocation]]) -> bool:
        # if there are any duplicates grid locations then there is an overlap
        all_locations = [
            locs for values in assignment.values() for locs in values
        ]
        return len(set(all_locations)) == len(all_locations)


if __name__ == "__main__":
    grid: Grid = generate_grid(9, 9)
    words: List[str] = ["MATTHEW", "JOE", "MARY", "SARAH", "SALLY"]
    locations: Dict[str, List[List[GridLocation]]] = {}
    for word in words:
        locations[word] = generate_domain(word, grid)
    csp: CSP[str, List[GridLocation]] = CSP(words, locations)
    csp.add_constraint(WordSearchConstraint(words))
    solution: Optional[Dict[str,
                            List[GridLocation]]] = csp.backtracking_search()
    if solution is None:
        print("No solution found!")
    else:
        for word, grid_locations in solution.items():
            # random reverse half the time
            if choice([True, False]):
                grid_locations.reverse()
            for index, letter in enumerate(word):
                (row, col) = (grid_locations[index].row,
                              grid_locations[index].column)
                grid[row][col] = letter
        display_grid(grid)
Пример #17
0
def solve_schedules(schedule_problem, algo, allsolns,
                 variableHeuristic='mrv', silent=False, trace=False):
    #Your implementation for Question 6 goes here.
    #
    #Do not but do not change the functions signature
    #(the autograder will twig out if you do).

    #If the silent parameter is set to True
    #you must ensure that you do not execute any print statements
    #in this function.
    #(else the output of the autograder will become confusing).
    #So if you have any debugging print statements make sure you
    #only execute them "if not silent". (The autograder will call
    #this function with silent=True, class_scheduling.py will call
    #this function with silent=False)

    #You can optionally ignore the trace parameter
    #If you implemented tracing in your FC and GAC implementations
    #you can set this argument to True for debugging.
    #
    #Once you have implemented this function you should be able to
    #run class_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a schedule_problem (an instance of ScheduleProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solution(s) it constructs a list (of lists) specifying possible schedule(s)
       for the student and returns that list (of lists)

       The required format of the list is:
       L[0], ..., L[N] is the sequence of class (or NOCLASS) assigned to the student.

       In the case of all solutions, we will have a list of lists, where the inner
       element (a possible schedule) follows the format above.
    '''

    #BUILD your CSP here and store it in the varable csp
    slot_num = schedule_problem.num_time_slots
    course_num = len(schedule_problem.courses)
    min_rest_frequency = schedule_problem.min_rest_frequency
    connected_buildings = schedule_problem._connected_buildings

    # domain of each slot
    dom = [NOCLASS]
    for class_ in schedule_problem.classes:
        found = False
        for course in schedule_problem.courses:
            if course in class_:
                found = True
                break
        if found:
            dom.append(class_)

    # variables in csp
    vars = []
    for i in range(slot_num):
        vars.append(Variable('Slot{}'.format(i), dom))

    cons = []
    cons.append(NValuesConstraint("name", vars, [NOCLASS], max(0, slot_num-course_num*2), max(0, slot_num-course_num*2)))

    # for each course, one can only take one lec and one tut
    lec_candidates = {}
    tut_candidates = {}
    for i in range(1, len(dom)):
        c_info = dom[i].split("-")
        if c_info[3] == "LEC":
            if c_info[0] not in lec_candidates:
                lec_candidates[c_info[0]] = []
            lec_candidates[c_info[0]].append(dom[i])
        else:
            if c_info[0] not in tut_candidates:
                tut_candidates[c_info[0]] = []
            tut_candidates[c_info[0]].append(dom[i])

    for l in lec_candidates.values():
        cons.append(NValuesConstraint("name", vars, l, 1, 1))
    for l in tut_candidates.values():
        cons.append(NValuesConstraint("name", vars, l, 1, 1))

    # CSC108-SF-1-LEC-01 
    # 0 -> courses, 1 -> location, 2 -> timeslot, 3 -> LEC/TUT, 4 -> section num
    for i in range(slot_num):
        for j in range(i+1, slot_num):
            # for each pair of time slots, create all possible combinations of candidates
            # store them in a table constaint
            satisfying_assignments = []
            for c1 in dom:
                c1_info = c1.split("-")
                for c2 in dom:
                    c2_info = c2.split("-")
                    if c1 == NOCLASS or c2 == NOCLASS:
                        if c1 == NOCLASS and c2 != NOCLASS and (j+1) == int(c2_info[2]) or \
                           c1 != NOCLASS and c2 == NOCLASS and (i+1) == int(c1_info[2]) or \
                           c1 == NOCLASS and c2 == NOCLASS:
                            satisfying_assignments.append([c1, c2])
                        continue
                    
                    # 1. candidate needs to be at the right time slot
                    # 2. for same course, lec must comes before tut
                    # 3. for consective time slot, two buildings need to be connected
                    if c1 == c2 or \
                       (i+1) != int(c1_info[2]) or (j+1) != int(c2_info[2]) or \
                       c1_info[0] == c2_info[0] and c1_info[3] == "TUT" and c2_info[3] == "LEC" or \
                       j-i == 1 and c2_info[1] not in connected_buildings[c1_info[1]]:
                        continue
                    
                    # same course and same type, take either one of them and make the other as NOCLASS
                    if c1_info[0] == c2_info[0] and c1_info[3] == c2_info[3]:
                        satisfying_assignments.append([NOCLASS, c2])
                        satisfying_assignments.append([c1, NOCLASS])
                        continue

                    satisfying_assignments.append([c1, c2])
            # new table constraint
            cons.append(TableConstraint("name", [vars[i], vars[j]], satisfying_assignments))

    scope = []
    for i in range(min_rest_frequency-1):
        scope.append(vars[i])
    for i in range(min_rest_frequency, len(vars)):
        scope.append(vars[i])
        cons.append(NValuesConstraint("name", scope, [NOCLASS], 1, float('inf')))
        scope.pop(0)

    csp = CSP("solve_schedules", vars, cons)
    #invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns, trace)

    #Convert each solution into a list of lists specifying a schedule
    #for each student in the format described above.

    #then return a list containing all converted solutions
    ans = []
    for sol in solutions:
        l = []
        for (var, val) in sol:
            l.append(val)
        ans.append(l)
    return ans
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='mrv',
                 silent=False,
                 trace=False):
    #Your implementation for Question 6 goes here.
    #
    #Do not but do not change the functions signature
    #(the autograder will twig out if you do).

    #If the silent parameter is set to True
    #you must ensure that you do not execute any print statements
    #in this function.
    #(else the output of the autograder will become confusing).
    #So if you have any debugging print statements make sure you
    #only execute them "if not silent". (The autograder will call
    #this function with silent=True, plane_scheduling.py will call
    #this function with silent=False)

    #You can optionally ignore the trace parameter
    #If you implemented tracing in your FC and GAC implementations
    #you can set this argument to True for debugging.
    #
    #Once you have implemented this function you should be able to
    #run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    '''

    #BUILD your CSP here and store it in the varable csp
    dic = {}
    block = []
    cons = []

    for plane in planes_problem.planes:
        start_var = Variable(
            "Plane:{}_1".format(plane),
            planes_problem.can_start(plane) +
            ['Empty'])  # initialize the start variable with its location
        dic[plane] = [start_var]  # put the variable in the dictionary

        fly_plane = planes_problem.can_fly(plane) + ['Empty']
        for i in range(2, len(fly_plane)):
            new = Variable(
                "Plane:{}_{}".format(plane, i),
                fly_plane)  # initialize other variables that they can fly
            dic[plane].extend([new])
        block.extend(dic[plane])

        follow_plane = []
        for (
                f1, f2
        ) in planes_problem.can_follow:  # store all the flights that cna be followed
            if f1 in fly_plane and f2 in fly_plane:
                follow_plane.append([f1, f2])

        for flight in fly_plane:
            follow_plane.append([flight, "Empty"])
        cols = dic[plane]

        for i in range(len(cols) - 1):
            new_con = TableConstraint(
                "Plane_{}_({},{})".format(plane, i + 1, i + 2),
                [cols[i], cols[i + 1]], follow_plane)
            cons.append(new_con)  # add new constraint into our constraint list

        maintain_plane = []
        maintain_freq = planes_problem.min_maintenance_frequency
        for f in planes_problem.maintenance_flights:  # store all the flights that are maintain
            if f in fly_plane:
                maintain_plane.append(f)

        for i in range(len(cols) - maintain_freq + 1):
            name = "Plane_{}_Range({},{})".format(plane, i + 1,
                                                  i + maintain_freq)
            scope = []
            required_values = maintain_plane
            required_values.append("Empty")
            for x in range(i, i + maintain_freq):
                scope.append(cols[x])
            lb = 1
            maintenance_constraint = NValuesConstraint(name, scope,
                                                       required_values, lb,
                                                       maintain_freq)
            cons.append(maintenance_constraint
                        )  # add the constraints for maintain flights

    for flight in planes_problem.flights:
        name = "Flight_{}_assigned".format(flight)
        required_values = [flight]
        lb = 1
        ub = 1
        flight_constrain = NValuesConstraint(name, block, required_values, lb,
                                             ub)
        cons.append(flight_constrain)

    csp = CSP("Plane", block, cons)

    #invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns,
                                     trace)

    #Convert each solution into a list of lists specifying a schedule
    #for each plane in the format described above.

    #then return a list containing all converted solutions
    #(i.e., a list of lists of lists)

    acc = []
    for item in solutions:
        final_sol = {}
        for plane in planes_problem.planes:
            final_sol[plane] = []
        for (var, val) in item:
            var_name = var.name()
            row_num = int(var_name.split("_")[1])
            final_sol[var_name.split(":")[1].split("_")[0]].append(
                (row_num, val))
        ordered_sol = {}
        for plane in final_sol:
            final_sol[plane].sort()
            ordered_sol[plane] = []
            for tup in final_sol[plane]:
                if tup[1] != "Empty":
                    ordered_sol[plane].append(tup[1])
        sol = []
        for plane in ordered_sol:
            sol.append([plane] + ordered_sol[plane])
        acc.append(sol)
    return acc
Пример #19
0
def sudoku_csp_problem(partial_grid=grid):

    #Ensure board is 9x9.  This could easily be extended to n^2 by n^2
    if len(partial_grid) <> 9: 'Error: Board must be 9x9'

    for i in range(len(partial_grid)):
        if len(partial_grid[i]) <> 9:
            return 'Error: Board must be 9x9'

    # Initialize...
    constraints = []

    indices = [(i, j) for i in range(1, 10) for j in range(1, 10)]

    variables = []

    #Initialize variables with one variable for each square.
    for (i, j) in indices:
        if partial_grid[i - 1][j - 1] <> 0:
            theval = [partial_grid[i - 1][j - 1]]
        else:
            theval = range(1, 10)

        variables.append(Variable(str(i) + ',' + str(j), theval))

    #returns i coordinate of a variable
    def i(var):
        return var.get_name()[0]

    #returns j coordinate of a variable
    def j(var):
        return var.get_name()[2]

    #gives the 3x3 box a given square is in, they are numbered left to right, top to bottom.
    def getbox(stri, strj):
        i = int(stri)
        j = int(strj)
        if i <= 3:
            if j <= 3: return 1
            elif 4 <= j <= 6: return 2
            elif 7 <= j <= 9: return 3
        elif 4 <= i <= 6:
            if j <= 3: return 4
            elif 4 <= j <= 6: return 5
            elif 7 <= j <= 9: return 6
        elif 7 <= i <= 9:
            if j <= 3: return 7
            elif 4 <= j <= 6: return 8
            elif 7 <= j <= 9: return 9

        return 'Error: Please enter i,j in the correct range'

    # make list of all square sharing a row, column or box
    # no need to duplicate the other way around since this loops through all

    edges = []
    for v1 in variables:
        for v2 in variables:
            if v1 <> v2 and (i(v1) == i(v2) or j(v1) == j(v2)
                             or getbox(i(v1), j(v1)) == getbox(i(v2), j(v2))):
                edges.append((v1.get_name(), v2.get_name()))

    # not allowed to have same value for square:
    def nomatch_constraint(val_a, val_b, name_a, name_b):
        if val_a == val_b:
            return False
        return True

    for e in edges:
        constraints.append(
            BinaryConstraint(e[0], e[1], nomatch_constraint,
                             "Cant match squares in same row, column, or box"))

    return CSP(constraints, variables)
Пример #20
0
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='mrv',
                 silent=False,
                 trace=False):
    # Your implementation for Question 6 goes here.
    #
    # Do not change the functions signature
    # (the autograder will twig out if you do).

    # If the silent parameter is set to True
    # you must ensure that you do not execute any print statements
    # in this function.
    # (else the output of the autograder will become confusing).
    # So if you have any debugging print statements make sure you
    # only execute them "if not silent". (The autograder will call
    # this function with silent=True, plane_scheduling.py will call
    # this function with silent=False)

    # You can optionally ignore the trace parameter
    # If you implemented tracing in your FC and GAC implementations
    # you can set this argument to True for debugging.
    #
    # Once you have implemented this function you should be able to
    # run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    """This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    """
    # BUILD your CSP here and store it in the variable csp
    variables = []
    constraints = []

    all_planes = planes_problem.planes
    all_flights = planes_problem.flights

    NO_FLIGHT_VALUE = "__NO_FLIGHT__"

    # Helper functions, based on my choice of variables' names
    extract_plane = lambda var_name: var_name[var_name.find('~') + 1:var_name.
                                              rfind('~')]
    extract_slot = lambda var_name: int(var_name[var_name.rfind('~') + 1:])

    # Variables
    # One variable per plane and flight slot
    for plane in all_planes:
        dom = planes_problem.can_fly(plane)
        for i in range(len(dom)):
            if i == 0:  # if first plane, dom must be restricted to the ones that "can start"
                variables.append(
                    Variable(
                        "Var~{}~{}".format(plane, i + 1),
                        planes_problem.can_start(plane) + [NO_FLIGHT_VALUE]))
            else:
                variables.append(
                    Variable("Var~{}~{}".format(plane, i + 1),
                             dom + [NO_FLIGHT_VALUE]))

    # Sequence of flights must be feasible
    # Note: every flight can precede NO_FLIGHT_VALUE, including NO_FLIGHT_VALUE itself, but none can follow it
    idx = 0  # index of variables list
    while idx < len(variables) - 1:
        curr_plane = extract_plane(variables[idx].name())
        next_plane = extract_plane(variables[idx + 1].name())

        if curr_plane == next_plane:
            constr_name = "CanFollow~{}~{}".format(variables[idx].name(),
                                                   variables[idx + 1].name())
            constr_scope = [variables[idx], variables[idx + 1]]
            acceptable_pairs = planes_problem.can_follow + [
                (fl, NO_FLIGHT_VALUE) for fl in variables[idx].domain()
            ]

            constraints.append(
                TableConstraint(constr_name, constr_scope, acceptable_pairs))

        idx += 1

    # Mainteinance check
    min_freq = planes_problem.min_maintenance_frequency
    mant_flights = planes_problem.maintenance_flights + [NO_FLIGHT_VALUE]

    idx_first = 0  # index of first plane
    idx_last = 0  # index of last plane
    while idx_last < len(variables):
        curr_plane = extract_plane(variables[idx_first].name())
        next_plane = extract_plane(variables[idx_last].name())

        if curr_plane != next_plane:
            num_of_flights = idx_last - idx_first
            all_subsequences = [
                variables[idx_first:idx_last][i:i + min_freq]
                for i in range(num_of_flights - min_freq + 1)
            ]

            for subsequence in all_subsequences:
                constraints.append(
                    NValuesConstraint(
                        "MainteinanceCheckForPlane~{}".format(curr_plane),
                        subsequence, mant_flights, 1, min_freq))

            idx_first = idx_last

        idx_last += 1

    if idx_first == 0:  # if there was only one plane
        for subsequence in [
                variables[i:i + min_freq]
                for i in range(idx_last - min_freq + 1)
        ]:
            constraints.append(
                NValuesConstraint("MaintCheckForOnlyPlane", subsequence,
                                  mant_flights, 1, min_freq))

    # All flights must be scheduled exactly once
    for flight in all_flights:
        constraints.append(
            NValuesConstraint("Flight~{}~uniqueness".format(flight), variables,
                              [flight], 1, 1))

    csp = CSP("Plane scheduling CSP", variables, constraints)

    # invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns,
                                     trace)

    # Convert each solution into a list of lists specifying a schedule
    # for each plane in the format described above.
    to_return = []

    for solution in solutions:
        planes_to_routes = {
            plane: [None] * len(all_flights)
            for plane in all_planes
        }

        for var, val in solution:
            curr_plane = extract_plane(var.name())
            curr_slot = extract_slot(var.name()) - 1

            planes_to_routes[curr_plane][
                curr_slot] = val if val != NO_FLIGHT_VALUE else None

        converted_solutions = map(
            lambda plane: [plane] + planes_to_routes[plane],
            planes_to_routes.keys())

        # get rid of None's in a functional programming way
        to_return.append(
            map(lambda schedule: filter(lambda fl: fl is not None, schedule),
                converted_solutions))

    # then return a list containing all converted solutions
    # (i.e., a list of lists of lists)
    return to_return
Пример #21
0
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='fixed',
                 silent=False,
                 trace=False):
    #Your implementation for Question 6 goes here.
    #
    #Do not but do not change the functions signature
    #(the autograder will twig out if you do).

    #If the silent parameter is set to True
    #you must ensure that you do not execute any print statements
    #in this function.
    #(else the output of the autograder will become confusing).
    #So if you have any debugging print statements make sure you
    #only execute them "if not silent". (The autograder will call
    #this function with silent=True, plane_scheduling.py will call
    #this function with silent=False)

    #You can optionally ignore the trace parameter
    #If you implemented tracing in your FC and GAC implementations
    #you can set this argument to True for debugging.
    #
    #Once you have implemented this function you should be able to
    #run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    '''

    #BUILD your CSP here and store it in the varable csp

    allVariables = []
    allConstraints = []

    increment = 1

    answer = []
    noneFlights = 1
    flights = planes_problem.flights
    maintenanceFlights = planes_problem.maintenance_flights
    mFrequency = planes_problem.min_maintenance_frequency
    '''
    '''

    constraintNameString = "C"
    planes = planes_problem.planes

    for i in range(len(planes)):
        currPlane = planes[i]
        canFlyPlanes = planes_problem.can_fly(currPlane)
        numFlights = len(canFlyPlanes)

        for j in range(numFlights):
            name = str(currPlane) + "." + str(noneFlights)
            if j > 0:
                currDomain = list(canFlyPlanes)
            else:
                currDomain = list(planes_problem.can_start(
                    currPlane))  # domain is only the "can_start" flights
            valString = "none." + str(noneFlights)
            currDomain = currDomain + [valString]
            var = Variable(name, currDomain)
            allVariables.append(var)
            noneFlights = noneFlights + 1

    diffCounter = 1
    allConstraints.extend([
        AllDiffConstraint(constraintNameString + str(diffCounter),
                          allVariables)
    ])
    diffCounter = diffCounter + increment
    allConstraints.extend([
        NValuesConstraint(constraintNameString + str(diffCounter),
                          allVariables, flights, len(flights), np.inf)
    ])
    diffCounter = diffCounter + increment

    noneString = "none" + "."

    for i in range(len(planes)):
        foundVariables = []
        for var in allVariables:
            if planes[i] in var.name():
                foundVariables.append(var)

        for variable_index in range(len(foundVariables[:-1])):
            first = foundVariables[variable_index]
            second = foundVariables[variable_index + 1]
            cnstrBatch = []

            noneA = noneString + first.name().split('.')[1]
            noneB = noneString + second.name().split('.')[1]

            listOfCo = []
            if variable_index == 0:
                firstdomain = planes_problem.can_start(planes[i])
            else:
                firstdomain = first.domain()
            for flight in firstdomain:
                for follow in planes_problem.can_follow:
                    if flight == follow[0]:
                        listOfCo.append(follow)

            for k in range(len(listOfCo)):
                nextDomain = second.domain()
                if listOfCo[k][1] in nextDomain:
                    cnstrBatch.append([listOfCo[k][0], listOfCo[k][1]])

            for flight in firstdomain:
                cnstrBatch.append([flight, noneB])
            if variable_index == 0:
                cnstrBatch.append([noneA, noneB])

            scope = [first, second]
            allConstraints.extend([
                TableConstraint(constraintNameString + str(diffCounter), scope,
                                cnstrBatch)
            ])

        if len(foundVariables) == 1:
            cnstrBatch = []
            first = foundVariables[0]
            firstDomain = first.domain()
            for flight in firstDomain:
                cnstrBatch.append([flight])
            scope = [first]
            allConstraints.extend([
                TableConstraint(constraintNameString + str(diffCounter), scope,
                                cnstrBatch)
            ])
        diffCounter = diffCounter + increment

    for i in range(len(planes)):

        foundVariables = []
        for var_index in range(len(allVariables)):
            if planes[i] in allVariables[var_index].name():
                foundVariables.append(allVariables[var_index])

        subSequences = map(
            list, zip(*(foundVariables[i:] for i in range(mFrequency))))
        if len(foundVariables) < mFrequency:
            continue

        for index in subSequences:
            planesWithNone = []

            for var in index:
                intermediateLst = var.name().split(".")
                formattedString = "none." + str(intermediateLst[1])
                planesWithNone.append(formattedString)

            currSequence = index
            allConstraints = allConstraints + [
                NValuesConstraint(
                    constraintNameString + str(diffCounter), currSequence,
                    maintenanceFlights + planesWithNone, 1, np.inf)
            ]
            diffCounter = diffCounter + increment

    csp = CSP("Planes", allVariables, allConstraints)

    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns,
                                     trace)

    for i in range(len(solutions)):
        temp = []
        final = []

        for plane in planes:
            foundVariables = []
            for var in solutions[i]:
                if var[0].name().split(".")[0] == plane:
                    foundVariables.append(var)

            nextVal = [x[1] for x in foundVariables]
            temp += [plane]
            temp += nextVal
            temp = [y for y in temp if (not "none" in y)]
            final += [temp]
            temp = []
        answer += [final]

    #print("---------------------------")
    #for lst in answer:
    #print(lst)
    return answer
Пример #22
0
def solve_planes(planes_problem, algo, allsolns,
                 variableHeuristic='mrv', silent=False, trace=False):
    # Your implementation for Question 6 goes here.
    #
    # Do not but do not change the functions signature
    # (the autograder will twig out if you do).

    # If the silent parameter is set to True
    # you must ensure that you do not execute any print statements
    # in this function.
    # (else the output of the autograder will become confusing).
    # So if you have any debugging print statements make sure you
    # only execute them "if not silent". (The autograder will call
    # this function with silent=True, plane_scheduling.py will call
    # this function with silent=False)

    # You can optionally ignore the trace parameter
    # If you implemented tracing in your FC and GAC implementations
    # you can set this argument to True for debugging.
    #
    # Once you have implemented this function you should be able to
    # run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    '''
    # BUILD your CSP here and store it in the variable csp

    # get the data from the planes_problem object
    planes = planes_problem.planes  # list of planes
    flights = planes_problem.flights  # list of flights
    can_follow = planes_problem.can_follow
    maintenance_flights = planes_problem.maintenance_flights
    frequency = planes_problem.min_maintenance_frequency

    # first define the variables
    # construct the variable: each can be allocated slot is a variable, domain is can_fly flights + ''
    var_array = []  # each plane is in order
    for plane in planes:
        plane_slots = []
        # the first slot can only have can_start and ''
        first_dom = planes_problem.can_start ( plane ).append ( '' )
        first_var = Variable ( "{} slot1".format ( plane, 1 ), first_dom )
        plane_slots.append ( first_var )
        # remaining slot have can_fly and ''
        dom = planes_problem.can_fly ( plane ).append ( '' )
        for i in range ( 1, len ( planes_problem.can_fly ( plane ) ) ):
            var = Variable ( "{} slot{}".format ( plane, i + 1 ), dom )
            plane_slots.append ( var )
        var_array.append ( plane_slots )

    # Set up the constraints
    # row constraints
    constraint_list = []

    # table constraint for can follow
    for i in range ( len ( var_array ) ):
        sequence = [[]]

        # can_follow for current plane:
        curr_can_follow = []
        for f1, f2 in can_follow:
            if f1 in planes_problem.can_fly ( planes[i] ) and f2 in planes_problem.can_fly ( planes[i] ):
                curr_can_follow.append ( (f1, f2) )

        # construct the dictionary of the current can follow: {f1: [list of f2]}
        dict_curr_can_follow = {}
        for f1, f2 in curr_can_follow:
            if f1 not in curr_can_follow:
                dict_curr_can_follow[f1] = [f2]
            else:
                if f2 not in dict_curr_can_follow[f1]:
                    dict_curr_can_follow[f1].append ( f2 )

        # construct the possible can fly sequences for each plane
        potential = []  # list of 'flight' sequence

        for first_flight in planes_problem.can_start ( planes[i] ):
            sequence.append ( [first_flight] )

        for f1 in dict_curr_can_follow:
            #

            sequence.append ( potential )

        for first_flight in planes_problem.can_start ( planes[i] ):
            potential.append ( first_flight )
            # begin the chain
            curr_can_follow = can_follow  # need to guarantee flights in potential is unique
            for f1, f2 in curr_can_follow:
                if f1 == first_flight:  # also f2 need in this plane's can_fly

    # NValue constraint for maintenance
    for plane_slots in var_array:
        constraint_list.append (
            NValuesConstraint('maintenance', plane_slots, maintenance_flights + [''], 1, frequency))

    # all different
    all_var = []
    for plane_slots in var_array:
        all_var.extend ( plane_slots )
    constraint_list.append(AllDiffNoneConstraint ( 'different flights', all_var ) )

    # need to check all assigned in later print out

    # NValue constraint for maintenance

    # construct csp problem
    vars = [var for row in var_array for var in row]
    csp = CSP ( "solve_planes", vars, constraint_list )

    # invoke search with the passed parameters
    solutions, num_nodes = bt_search ( algo, csp, variableHeuristic, allsolns, trace )

    # Convert each solution into a list of lists specifying a schedule
    # for each plane in the format described above.
    allSolution = []
    for solution in solutions:
Пример #23
0
from csp import CSP

crossword_puzzle = CSP(
    var_domains={
        # read across:
        'a1': set("bus has".split()),
        'a3': set("lane year".split()),
        'a4': set("ant car ".split()),
        # read down:
        'd1': set("buys hold".split()),
        'd2': set("search syntax".split()),
    },
    constraints={
        lambda a1, d1: a1[0] == d1[0],
        lambda d1, a3: d1[2] == a3[0],
        lambda a1, d2: a1[2] == d2[0],
        lambda d2, a3: d2[2] == a3[2],
        lambda d2, a4: d2[4] == a4[0],
    })
Пример #24
0
def main():
    """ Parse the command line arguments. Make the CSP object. Do preprocessing
        if requested. Then call the search object.
        () -> None
    """
    args = parse_cmd_line_args()

    #Get the appropriate functions to be used by the search
    variable_selection_function = get_variable_selection_function(
        args.variable_heuristic)
    value_ordering_function = get_value_ordering_function(args.value_heuristic)
    inference_pre_function = get_inference_function(args.preprocessing)
    inference_search_function = get_inference_function(args.search_inference)

    print "Parsing CSP file:", args.input_file_name
    csp = CSP()
    if not csp.parse_csp_file(args.input_file_name):
        return
    print "Success."
    initial_assignment = dict([ (var, csp.domains[var][0])\
        for var in csp.variables if len(csp.domains[var]) == 1 ])
    #Apply preprocessing if requested
    if inference_pre_function is not None:
        print "Preprocessing..."
        result = inference_pre_function(None, initial_assignment, csp)

        if result is None:
            print "Error: inconsistency detected in preprocessing."
            return
        csp.notify_of_inference(None, initial_assignment, result[0], result[1])
        print "Preprocessing made", len(result[1]), "assignments."

    if args.output_file_name is not None:
        print "Writing grounded CSP to:", args.output_file_name
        try:
            with file(args.output_file_name, "w") as output_file:
                csp.write(output_file)
        except IOError as e:
            print "Error: cannot open output file:", args.output_file_name
        return

    print "Performing backtracking search..."
    assignment, explored, search_time = search(csp, initial_assignment,
                                               variable_selection_function,
                                               value_ordering_function,
                                               inference_search_function)

    if args.solution_file_name is None:
        solution_file = sys.stdout
    else:
        try:
            solution_file = file(args.solution_file_name, "w")
        except IOError as e:
            print "Error: could not open output file:", args.solution_file_name
            return

    #Display the result
    if assignment is None:
        print "There is no solution!"
        solution_file.write("UNSAT\n")
        solution_file.write("Explored: " + str(explored) + "\n")
        solution_file.write("Time: " + str(search_time) + "\n")
    else:
        print "Solution found."
        if args.sudoku_output:
            for y in xrange(1, 10):
                for x in xrange(1, 10):
                    solution_file.write(assignment[str(x) + str(y)] + " ")
                    if x % 3 == 0 and x < 9:
                        solution_file.write("| ")
                solution_file.write("\n")
                if y % 3 == 0 and y < 9:
                    solution_file.write("---------------------\n")
        else:
            solution_file.write("SAT\n")
            solution_file.write("Explored: " + str(explored) + "\n")
            solution_file.write("Time: " + str(search_time) + "\n")
            solution_file.write("Solution: " + " ".join([var+"="+val\
                for var,val in assignment.iteritems() ]) + "\n")
Пример #25
0
def sudokuCSP(initial_sudoku_board, model='neq'):
    '''The input board is specified as a list of 9 lists. Each of the
       9 lists represents a row of the board. If a 0 is in the list it
       represents an empty cell. Otherwise if a number between 1--9 is
       in the list then this represents a pre-set board
       position. E.g., the board

       -------------------
       | | |2| |9| | |6| |
       | |4| | | |1| | |8|
       | |7| |4|2| | | |3|
       |5| | | | | |3| | |
       | | |1| |6| |5| | |
       | | |3| | | | | |6|
       |1| | | |5|7| |4| |
       |6| | |9| | | |2| |
       | |2| | |8| |1| | |
       -------------------
       would be represented by the list of lists

       [[0,0,2,0,9,0,0,6,0],
       [0,4,0,0,0,1,0,0,8],
       [0,7,0,4,2,0,0,0,3],
       [5,0,0,0,0,0,3,0,0],
       [0,0,1,0,6,0,5,0,0],
       [0,0,3,0,0,0,0,0,6],
       [1,0,0,0,5,7,0,4,0],
       [6,0,0,9,0,0,0,2,0],
       [0,2,0,0,8,0,1,0,0]]


       Construct and return CSP for solving this sudoku board using
       binary not equals if model='neq' or using allDiff constraints
       if model='alldiff'

       The CSP contains a variable for each cell of the board with
       with domain equal to {1-9} if the board has a 0 at that position,
       and domain equal {i} if the board has a fixed number i at that
       cell.

       The CSP has a neq constraint between every relevant pair of
       varibles, or an alldiff constraint between every set of
       variables in a row, column, or sub-square

    '''
    #your implementation for Question 4 changes this function
    #implement handleing of model == 'alldiff'

    if not model in ['neq', 'alldiff']:
        print "Error wrong sudoku model specified {}. Must be one of {}".format(
            model, ['neq', 'alldiff'])

    #first define the variables
    i = 0
    var_array = []
    for row_list in initial_sudoku_board:
        var_array.append([])
        j = 0
        for col in row_list:
            cell = initial_sudoku_board[i][j]
            if cell == 0:
                dom = [1, 2, 3, 4, 5, 6, 7, 8, 9]
            else:
                dom = [cell]
            var = Variable("V{},{}".format(i + 1, j + 1), dom)
            var_array[i].append(var)
            j += 1
        i += 1

    #Set up the constraints
    #row constraints
    constraint_list = []

    for row in var_array:
        if model == 'neq':
            constraint_list.extend(post_all_pairs(row))
        elif model == 'alldiff':
            constraint_list += [SodukuAllDiff(row)]

    for col in range(len(var_array[0])):
        scope = map(lambda row: row[col], var_array)
        if model == 'neq':
            constraint_list.extend(post_all_pairs(scope))
        elif model == 'alldiff':
            constraint_list += [SodukuAllDiff(scope)]

    for i in [0, 3, 6]:
        for j in [0, 3, 6]:
            #initial upper left hand index of subsquare
            scope = []
            for k in [0, 1, 2]:
                for l in [0, 1, 2]:
                    scope.append(var_array[i + k][j + l])
            if model == 'neq':
                constraint_list.extend(post_all_pairs(scope))
            elif model == 'alldiff':
                constraint_list += [SodukuAllDiff(scope)]

    vars = [var for row in var_array for var in row]
    return CSP("Sudoku", vars, constraint_list)
Пример #26
0
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='mrv',
                 silent=False,
                 trace=False):
    #Your implementation for Question 6 goes here.
    #
    #Do not but do not change the functions signature
    #(the autograder will twig out if you do).

    #If the silent parameter is set to True
    #you must ensure that you do not execute any print statements
    #in this function.
    #(else the output of the autograder will become confusing).
    #So if you have any debugging print statements make sure you
    #only execute them "if not silent". (The autograder will call
    #this function with silent=True, plane_scheduling.py will call
    #this function with silent=False)

    #You can optionally ignore the trace parameter
    #If you implemented tracing in your FC and GAC implementations
    #you can set this argument to True for debugging.
    #
    #Once you have implemented this function you should be able to
    #run plane_scheduling.py to solve the test problems (or the autograder).
    #
    #
    '''This function takes a planes_problem (an instance of PlaneProblem
       class) as input. It constructs a CSP, solves the CSP with bt_search
       (using the options passed to it), and then from the set of CSP
       solutions it constructs a list of lists specifying a schedule
       for each plane and returns that list of lists
       The required format is the list of lists is:

       For each plane P the list of lists contains a list L.
       L[0] == P (i.e., the first item of the list is the plane)
       and L[1], ..., L[k] (i.e., L[1:]) is the sequence of flights
       assigned to P.

       The returned list of lists should contain a list for every
       plane.
    '''
    #BUILD your CSP here and store it in the variable csp

    # get the data from the planes_problem object
    planes = planes_problem.planes  # list of planes
    flights = planes_problem.flights  # list of flights
    can_follow = planes_problem.can_follow
    maintenance_flights = planes_problem.maintenance_flights
    frequency = planes_problem.min_maintenance_frequency
    constraint_list = []

    # variable1: 'flight' with domain [(can_follow, 1->maintenance)]
    variables_flights = []
    flight_obj_dict = {}  # {'flight': flight_obj}
    obj_flight_dict = {}  # {flight_obj: 'flight'}
    for flight in flights:
        name = flight
        domain = []
        for f1, f2 in can_follow:
            if f1 == name:
                if f2 in maintenance_flights:
                    domain.append((f2, 1))
                else:
                    domain.append((f2, 0))
        # deal with the flight in the last
        domain.append(('None', -1))
        flight_obj = Variable(name, domain)
        variables_flights.append(flight_obj)
        flight_obj_dict[name] = flight_obj
        obj_flight_dict[flight_obj] = name
    constraint_flight = AllDiffConstraint('constraintFlight',
                                          variables_flights)
    constraint_list.append(constraint_flight)

    # variable2: 'plane' with domain [start flight_obj - can be empty]
    variables_planes = []
    for plane in planes:
        name = plane
        domain = []
        for flight in planes_problem.can_start(name):
            domain.append(flight_obj_dict[flight])
        # deal with situation there is no flight for the plane
        domain.append(None)
        plane_obj = Variable(name, domain)
        variables_planes.append(plane_obj)
    # start flight all different except None object
    constraint_plane = AllDiffFilterConstraint('constraintPlane',
                                               variables_planes)
    constraint_list.append(constraint_plane)

    # construct csp problem
    csp = CSP("solve_planes", variables_flights + variables_planes,
              constraint_list)

    #invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns,
                                     trace)

    # Convert each solution into a list of lists specifying a schedule
    # for each plane in the format described above.
    allSolution = []  # list of each_solution
    for solution in solutions:
        flight_solution = solution[:len(
            flights)]  # [(flight_obj, ('nxt_flight', 1/0))]
        plane_solution = solution[
            -len(planes):]  # [(plane_obj, first_flight_obj)]

        # convert flight_solution to dictionary
        flight_solution_dic = {}  # dict {flight_obj: ('nxt_flight', 1/0)}
        for var, val in flight_solution:
            flight_solution_dic[var] = val

        # construct plane solution, connect the chain
        plane_sol_dic = {}  # {'plane': [sequence (flight, maintenance)]}
        for plane, first_flight in plane_solution:
            plane_sol_dic[plane.name()] = []
            if first_flight is not None:
                # this is just the first sequence
                maintenance = 0
                if first_flight.name() in maintenance_flights:
                    maintenance = 1
                plane_sol_dic[plane.name()].append(
                    (first_flight.name(), maintenance))

                if first_flight in flight_solution_dic:
                    nxt_flight, maintenance = flight_solution_dic.pop(
                        first_flight)
                    while nxt_flight != 'None':
                        plane_sol_dic[plane.name()].append(
                            (nxt_flight, maintenance))
                        constructed_path = []
                        for flight, maintenance in plane_sol_dic[plane.name()]:
                            constructed_path.append(flight)
                        if flight_obj_dict[nxt_flight] in flight_solution_dic:
                            check_nxt_flight, check_maintenance = flight_solution_dic.pop(
                                flight_obj_dict[nxt_flight])
                            if check_nxt_flight not in constructed_path:
                                nxt_flight, maintenance = check_nxt_flight, check_maintenance
                            else:
                                break
                        else:
                            break

        # check each flight has been allocated
        allocate_flight = sum(
            len(plane_sol_dic[plane]) for plane in plane_sol_dic)
        if allocate_flight != len(flights):
            continue

        each_solution = [
        ]  # list of solution to each plane ['plane', 'flight1', 'flight2', ...]
        for plane in plane_sol_dic:
            # case1: plane only assign < frequency # of flights
            if len(plane_sol_dic[plane]) < frequency:
                plane_sol = [plane]
                for flight, maintenance in plane_sol_dic[plane]:
                    plane_sol.append(flight)
                each_solution.append(plane_sol)

            else:  # case: assigned sequence length >= frequency
                # prune the case not satisfies maintenance
                maintenance_list = []
                for flight, maintenance in plane_sol_dic[plane]:
                    maintenance_list.append(maintenance)
                if maintenance_check(maintenance_list, frequency):
                    plane_sol = [plane]
                    for flight, maintenance in plane_sol_dic[plane]:
                        plane_sol.append(flight)
                    each_solution.append(plane_sol)
        if each_solution != [] and each_solution not in allSolution:
            allSolution.append(each_solution)

    #then return a list containing all converted solutions
    #(i.e., a list of lists of lists)
    return allSolution
Пример #27
0
def question_5():
    print_title(4)
    fails = [False] * 2

    test1 = "    v1 = Variable('V1', [1, 2])\n\
    v2 = Variable('V2', [1, 2])\n\
    v3 = Variable('V3', [1, 2, 3, 4, 5])\n\
    v4 = Variable('V4', [1, 2, 3, 4, 5])\n\
    v5 = Variable('V5', [1, 2, 3, 4, 5])\n\
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]\n\
    nv9 = NValuesConstraint('9', vars, [9], 4, 5)\n\
    testcsp = CSP('test', vars, [nv9])\n\
    GacEnforce([nv9], testcsp, None, None)"

    v1 = Variable('V1', [1, 2])
    v2 = Variable('V2', [1, 2])
    v3 = Variable('V3', [1, 2, 3, 4, 5])
    v4 = Variable('V4', [1, 2, 3, 4, 5])
    v5 = Variable('V5', [1, 2, 3, 4, 5])
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]
    nv9 = NValuesConstraint('9', vars, [9], 4, 5)
    testcsp = CSP('test', vars, [nv9])
    GacEnforce([nv9], testcsp, None, None)
    soln_doms = [
        set([1, 2]),
        set([1, 2]),
        set([1, 2, 3, 4, 5]),
        set([1, 2, 3, 4, 5]),
        set([1, 2, 3, 4, 5]),
        set([9]),
        set([9]),
        set([9]),
        set([9])
    ]

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[0] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[0]:
        print "\nFail Q5 test 1\nErrors were generated on the following code:"
        print test1
    else:
        print "Pass Q5 test 1"
        print_sep()

    test2 = "    v1 = Variable('V1', [1, 2])\n\
    v2 = Variable('V2', [1, 2])\n\
    v3 = Variable('V3', [1, 2, 3, 4, 5])\n\
    v4 = Variable('V4', [1, 2, 3, 4, 5])\n\
    v5 = Variable('V5', [1, 2, 3, 4, 5])\n\
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])\n\
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]\n\
    nv9 = NValuesConstraint('9', vars, [9], 4, 5)\n\
    nv1 = NValuesConstraint('1', vars, [1], 5, 5)\n\
    testcsp = CSP('test', vars, [nv1, nv9])\n\
    GacEnforce([nv1, nv9], testcsp, None, None)"

    v1 = Variable('V1', [1, 2])
    v2 = Variable('V2', [1, 2])
    v3 = Variable('V3', [1, 2, 3, 4, 5])
    v4 = Variable('V4', [1, 2, 3, 4, 5])
    v5 = Variable('V5', [1, 2, 3, 4, 5])
    v6 = Variable('V6', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v7 = Variable('V7', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v8 = Variable('V8', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    v9 = Variable('V9', [1, 2, 3, 4, 5, 6, 7, 8, 9])
    vars = [v1, v2, v3, v4, v5, v6, v7, v8, v9]
    nv9 = NValuesConstraint('9', vars, [9], 4, 5)
    nv1 = NValuesConstraint('1', vars, [1], 5, 5)
    testcsp = CSP('test', vars, [nv1, nv9])
    GacEnforce([nv1, nv9], testcsp, None, None)
    soln_doms = [
        set([1]),
        set([1]),
        set([1]),
        set([1]),
        set([1]),
        set([9]),
        set([9]),
        set([9]),
        set([9])
    ]

    #vars[0].pruneValue(1, None, None)

    for i, v in enumerate(vars):
        if set(v.curDomain()) != soln_doms[i]:
            fails[1] = True
            print "Error: {}.curDomain() == {}".format(v.name(), v.curDomain())
            print "Correct curDomin should be == {}".format(list(soln_doms[i]))

    if fails[1]:
        print "\nFail Q5 test 2\nErrors were generated on the following code:"
        print test3
    else:
        print "Pass Q5 test 2"
        print_sep()

    if not any(fails):
        grades[4] = outof[4]
Пример #28
0
def moose_csp_problem():
    constraints = []

    # We start with the reduced domain.
    # So the constraint that McCain must sit in seat 1 is already
    # covered.
    variables = []
    variables.append(Variable("1", ["Mc"]))
    variables.append(Variable("2", ["Y", "M", "P"]))
    variables.append(Variable("3", ["Y", "M", "O", "B"]))
    variables.append(Variable("4", ["Y", "M", "O", "B"]))
    variables.append(Variable("5", ["Y", "M", "O", "B"]))
    variables.append(Variable("6", ["Y", "M", "P"]))

    # these are all variable pairing of adjacent seats
    adjacent_pairs = [("1", "2"), ("2", "1"), ("2", "3"), ("3", "2"),
                      ("3", "4"), ("4", "3"), ("4", "5"), ("5", "4"),
                      ("5", "6"), ("6", "5"), ("6", "1"), ("1", "6")]
    # now we construct the set of non-adjacent seat pairs.
    nonadjacent_pairs = []
    variable_names = ["1", "2", "3", "4", "5", "6"]
    for x in range(len(variable_names)):
        for y in range(x, len(variable_names)):
            if x == y:
                continue
            tup = (variable_names[x], variable_names[y])
            rev = (variable_names[y], variable_names[x])
            if tup not in adjacent_pairs:
                nonadjacent_pairs.append(tup)
            if rev not in adjacent_pairs:
                nonadjacent_pairs.append(rev)

    # all pairs is the set of all distinct seating pairs
    # this list is useful for checking where
    # the two seat are assigned to the same person.
    all_pairs = adjacent_pairs + nonadjacent_pairs

    # 1. The Moose is afraid of Palin
    def M_not_next_to_P(val_a, val_b, name_a, name_b):
        if ((val_a == "M" and val_b == "P")
                or (val_a == "P" and val_b == "M")):
            return False
        return True

    for pair in adjacent_pairs:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], M_not_next_to_P,
                             "Moose can't be " + "next to Palin"))

    # 2. Obama and Biden must sit next to each other.
    # This constraint can be directly phrased as:
    #
    #   for all sets of adjacents seats
    #      there must exist one pair where O & B are assigned
    #
    #   C(1,2) or C(2,3) or C(3,4) or ... or C(6,1)
    #
    # where C is a binary constraint that checks
    # whether the value of the two variables have values O and B
    #
    # However the way our checker works, the constraint needs to be
    # expressed as a big AND.
    # So that when any one of the binary constraints
    # fails the entire assignment fails.
    #
    # To turn our original OR formulation to an AND:
    # We invert the constraint condition as:
    #
    #  for all sets of nonadjacent seats
    #     there must *not* exist a pair where O & B are assigned.
    #
    #  not C(1,3) and not C(1,4) and not C(1,5) ... not C(6,4)
    #
    # Here C checks whether the values assigned are O and B.
    #
    # Finally, this is an AND of all the binary constraints as required.

    def OB_not_next_to_each_other(val_a, val_b, name_a, name_b):
        if (val_a == "O" and val_b == "B") or \
                (val_a == "B" and val_b == "O"):
            return False
        return True

    for pair in nonadjacent_pairs:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], OB_not_next_to_each_other,
                             "Obama, Biden must be next to each-other"))

    # 3. McCain and Palin must sit next to each other
    def McP_not_next_to_each_other(val_a, val_b, name_a, name_b):
        if ((val_a == "P" and val_b == "Mc")
                or (val_a == "Mc" and val_b == "P")):
            return False
        return True

    for pair in nonadjacent_pairs:
        constraints.append(
            BinaryConstraint(
                pair[0], pair[1], McP_not_next_to_each_other,
                "McCain and Palin must be " + "next to each other"))

    # 4. Obama + Biden can't sit next to Palin or McCain
    def OB_not_next_to_McP(val_a, val_b, name_a, name_b):
        if ((val_a == "O" or val_a == "B") \
                and (val_b == "Mc" or val_b == "P")) or \
                ((val_b == "O" or val_b == "B") \
                     and (val_a == "Mc" or val_a == "P")):
            return False
        return True

    for pair in adjacent_pairs:
        constraints.append(
            BinaryConstraint(
                pair[0], pair[1], OB_not_next_to_McP,
                "McCain, Palin can't be next " + "to Obama, Biden"))

    # No two seats can be occupied by the same person
    def not_same_person(val_a, val_b, name_a, name_b):
        return val_a != val_b

    for pair in all_pairs:
        constraints.append(
            BinaryConstraint(
                pair[0], pair[1], not_same_person,
                "No two seats can be occupied " + "by the same person"))
    return CSP(constraints, variables)
Пример #29
0
class QueensConstraint(Constraint[int, int]):
    def __init__(self, columns: List[int]) -> None:
        super().__init__(columns)
        self.columns: List[int] = columns

    def satisfied(self, assignment: Dict[int, int]):
        # q1c = queen 1 column, q1r = queen 1 row
        for q1c, q1r in assignment.items():
            # q2c = queen 2 column
            for q2c in range(q1c + 1, len(self.columns) + 1):
                if q2c in assignment:
                    q2r: int = assignment[q2c]
                    if q1r == q2r:  # same row
                        return False
                    if abs(q1r - q2r) == abs(q1c - q2c):  # same diagonal
                        return False
        return True


if __name__ == "__main__":
    columns: List[int] = [1, 2, 3, 4, 5, 6, 7, 8]
    rows: Dict[int, List[int]] = {i: columns for i in range(1, 9)}
    csp: CSP[int, int] = CSP(columns, rows)
    csp.add_constraint(QueensConstraint(columns))
    solution: Optional[Dict[int, int]] = csp.backtracking_search()
    if solution is None:
        print("No solution found")
    else:
        print(solution)
Пример #30
0
from csp import CSP
canterbury_colouring = CSP(
    var_domains={
        'christchurch': {'red', 'green'},
        'selwyn': {'red', 'green'},
        'waimakariri': {'red', 'green'},
    },
    constraints={
        lambda christchurch, waimakariri: christchurch != waimakariri,
        lambda christchurch, selwyn: christchurch != selwyn,
        lambda selwyn, waimakariri: selwyn != waimakariri,
    })

#Unchanged since for every option in every domain there is an option in the
#corresponding domain that does not equal it