Exemplo n.º 1
0
def solve_schedules(schedule_problem,
                    algo,
                    allsolns,
                    variableHeuristic='mrv',
                    silent=False,
                    trace=False):
    #If the silent parameter is set to True
    #you must ensure that you do not execute any print statements
    #in this function.

    #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
    csp = schedules_csp(schedule_problem)

    #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.

    solutionList = []
    if len(solutions) == 0:
        # print("No solutions to {} found".format(csp.name()))
        return []
    else:
        for s in solutions:
            sList = []
            for (var, val) in s:
                if val.split('-')[0] == NOCLASS:
                    val = NOCLASS
                sList.append(val)
            if sList not in solutionList:
                solutionList.append(sList)
    return solutionList
Exemplo n.º 2
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
    # util.raiseNotDefined()
    csp = schedules(schedule_problem)
    #invoke search with the passed parameters
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns, trace)

    solns = []

    for s in solutions:
        #s = sorted(s, key=lambda x: x[0].name())
        soln = []
        for (var,val) in s:
            soln.append(val)
        solns.append(soln)
    print(solns)
    return solns
Exemplo n.º 3
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

    planes = planes_problem.planes  # the actual planes: 'AC-1', 'AC-2', etc
    flights = planes_problem.flights  # flight codes 'AC001', 'AC002', etc
    maintenanceFlights = planes_problem.maintenance_flights
    maintFreq = planes_problem.min_maintenance_frequency
    planeVars = []  # list of planeVariables, DIFFERENT FROM PLANES
    constraint_list = []  # list of constraints
    '''
    create a variable for each plane "stop"
    format: actualplanename.#
    need to count how many flights each plane is able to fly to create each variable
    for each "start" plane variable, the domain is the initial flight list
    for other plane variables, the domain is the flightlist
    '''
    noneCount = 1  # keep track of unique "none" flights

    # 1. Assigned flights only 2. Initial flight
    # both enforced through domains
    # cycle through the planes
    for p in planes:
        # get number of flights this plane can fly
        flightCount = len(planes_problem.can_fly(p))
        # then create variables and domains
        for i in range(flightCount):
            name = "{}.{}".format(p, noneCount)
            if i == 0:  # if it's the first plane var
                dom = list(planes_problem.can_start(
                    p))  # domain is only the "can_start" flights
            else:
                dom = list(planes_problem.can_fly(
                    p))  # otherwise domain is the "can_fly" flights
            # add unique "none" flight values to domain
            dom.append("none.{}".format(noneCount))
            planeVar = Variable(name, dom)
            planeVars.append(planeVar)
            noneCount += 1  # increment nonecounter

    # 5. Everything must be scheduled once and only once - AllDiff + NValues
    # AllDiff: everything is only scheduled once
    # NValues: all flights have been scheduled
    a = 1
    constraint_list.extend([AllDiffConstraint("C{}".format(a), planeVars)])
    a += 1
    constraint_list.extend([
        NValuesConstraint("C{}".format(a), planeVars, flights, len(flights),
                          999999)
    ])
    a += 1

    # 4. Maintenance every K flights. If numflights = J < K, its satisfied
    # NValues Constraint
    # cycle through unique plane names
    for plane in planes:
        # from the planeVars, grab the variables that correspond to the unique plane chosen
        match = [v for v in planeVars if plane in v.name()]
        # we now need to iterate through match list by grabbing maintFreq amount of subsequent planeVars
        subSequences = map(list, zip(*(match[i:] for i in range(maintFreq))))
        if len(match) < maintFreq:
            continue  # if the max length of this plane's flight plan is < maintFreq
            # it doesn't need a constraint
        # cycle through each subsequence
        for sub in subSequences:
            noneNames = []
            # figure out the unique none names
            for v in sub:
                noneNames += ["none.{}".format(v.name().split('.')[1])]
            # combine maintenanceFlights and none names into one list, required
            required = maintenanceFlights + noneNames
            # enforce NValues on the required values, lowerbound is 1
            constraint_list.extend(
                [NValuesConstraint("C{}".format(a), sub, required, 1, 99999)])
            a += 1

    # 3. Sequence - Table Constraints
    for plane in planes:
        match = [v for v in planeVars if plane in v.name()
                 ]  # match is a collection of variables whose name starts with
        # the current plane were looking at
        for i in range(len(match) - 1):
            first = match[i]
            second = match[i + 1]
            constraintTuples = []
            firstnone = "none." + first.name().split('.')[1]
            secondnone = "none." + second.name().split('.')[1]

            narrowlist = []
            if i == 0:  # if it's the starting flight, then match[i] needs to start with one of the can_start flights
                firstdomain = planes_problem.can_start(plane)
            else:  # otherwise, just get the domain of the first ones
                firstdomain = first.domain()
            for flight in firstdomain:
                # from the list of can_follow, narrow the list down using can_follow tuple[0] = flight
                narrowlist += [
                    x for x in planes_problem.can_follow if x[0] == flight
                ]
            # at this point, we have narrowlist,
            # work through the narrowlist, check the second flight domain with the second item in each tuple
            # insert if domain holds
            for n in narrowlist:
                dest = n[1]
                if dest in second.domain():
                    constraintTuples += [[n[0], n[1]]]
            # insert none flights as necessary
            for flight in firstdomain:
                constraintTuples += [[flight, secondnone]]
            if i == 0: constraintTuples += [[firstnone, secondnone]]
            scope = [first, second]
            constraint_list.extend(
                [TableConstraint("C{}".format(a), scope, constraintTuples)])
        # if the plane can only ever fly one flight, then the table constraint is the domain itself, not necessary tbh
        if len(match) == 1:
            constraintTuples = []
            first = match[0]
            for flight in first.domain():
                constraintTuples += [[flight]]
            scope = [first]
            constraint_list.extend(
                [TableConstraint("C{}".format(a), scope, constraintTuples)])
        a += 1

    csp = CSP("Planes", planeVars, 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.
    #then return a list containing all converted solutions
    #(i.e., a list of lists of lists)
    returnList = []
    for sol in solutions:
        subList = []
        finalList = []
        for plane in planes:
            match = [x for x in sol if x[0].name().split('.')[0] == plane]
            further = [x[1] for x in match]
            subList.extend([plane])
            subList.extend(further)
            subList = [s for s in subList if "none" not in s]
            finalList.extend([list(subList)])
            del subList[:]
        returnList += [list(finalList)]
        #print returnList
    return returnList
Exemplo n.º 4
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
    #Initialize all the parameters, constrains contains all constrains that we need
    #to follow. all_planes contain all planes information as list of list of list of
    #variables. (Triple list)

    #list of  constraint
    all_constraint = []
    #List of all planes
    all_planes = []
    #All elements
    all_info = []

    # each planes can have multiple stop.
    for planes in range(len(planes_problem.planes)):
        all_planes.append([])

    planes_counter = 0
    for plane in planes_problem.planes:
        plane_dom = planes_problem._can_fly[plane]
        # setting domain for each stop according to plane
        for each_des in range(len(plane_dom)):
            # first time setting
            if each_des == 0:
                des_can_start = planes_problem.can_start(plane)
                des_can_start.extend(["Stop"])
                each_des_var = Variable(str(each_des),des_can_start)
                all_planes[planes_counter].append(each_des_var)
                all_info.append(each_des_var)
            #using can_fly destination as domain
            if each_des != 0:
                des_can_start = [item for item in plane_dom]
                des_can_start.extend(["Stop"])
                each_des_var = Variable(str(each_des), des_can_start)
                all_planes[planes_counter].append(each_des_var)
                all_info.append(each_des_var)
        planes_counter += 1


    # constrain each flight must take maintenance within minimum maintenance frequency.
    for each_plane in range(len(all_planes)):
        max_start_index = len(all_planes[each_plane])-planes_problem.min_maintenance_frequency+1
        if max_start_index > 0:
            this_sequence = 0
            while (this_sequence != max_start_index):
                scope = []
                lower = this_sequence
                upper = this_sequence + planes_problem.min_maintenance_frequency
                for this_des in range(lower,upper):
                    scope.append(all_planes[each_plane][this_des])
                required_values = [item for item in planes_problem.maintenance_flights]
                required_values.extend(["Stop"])
                lower_bound = 1
                upper_bound = planes_problem.min_maintenance_frequency
                con = NValuesConstraint(str(each_plane), scope,required_values ,lower_bound,upper_bound)
                all_constraint.append(con)
                this_sequence += 1


    # each flight can only be taken once
    for this_flight in planes_problem.flights:
        #name, scope, required_values, lower_bound, upper_bound
        name = str(this_flight)
        scope = all_info
        required_values = [this_flight]
        lower_bound = upper_bound = 1
        new_con =  NValuesConstraint(name,scope,required_values,lower_bound,upper_bound)
        all_constraint.append(new_con)


    #each plane can stop after flight, or continue waiting(stop)
    for each_flight in planes_problem.flights:
        planes_problem.can_follow.append((each_flight,"Stop"))
    planes_problem.can_follow.append(("Stop","Stop"))

    # make sure each plane/flight can follow
    for each_plane in range(len(all_planes)):
        max_start_index = len(all_planes[each_plane])-2+1
        for this_des in range(max_start_index):
            scope = [all_planes[each_plane][this_des],all_planes[each_plane][this_des+1]]
            con = TableConstraint(str(this_des), scope,planes_problem.can_follow)
            all_constraint.append(con)

    #Output result.
    csp = CSP("plane scheduling",all_info,all_constraint)
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, allsolns, trace)
    result = []
    for ans in solutions:
        current = 0
        this_plane = []
        for plane in range(len(all_planes)):
            schedule = [planes_problem.planes[plane]]
            for each_des in range(len(all_planes[plane])):
                if ans[current][1]!="Stop":
                    schedule.append(ans[current][1])
                current+=1
            this_plane.append(schedule)
        result.append(this_plane)
    return result
Exemplo n.º 5
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) + ['']

        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) + ['']
        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)): # i is the index of plane in planes
        sequence = []

        # construct the possible can fly sequences for each plane
        curr_can_fly = planes_problem.can_fly(planes[i])
        num_slots = len(curr_can_fly)

        empty_assign = []
        for _ in range(num_slots):
            empty_assign.append('')
        sequence.append(empty_assign)

        for first_flight in planes_problem.can_start(planes[i]):
            sequence_same_start = [[first_flight]]
            curr_step_sequence = sequence_same_start
            while True:
                flag = 0

                for subsequence in curr_step_sequence:
                    tail = subsequence[-1]
                    new_sub = []
                    for nxt in curr_can_fly:
                        if (tail, nxt) in can_follow and nxt not in subsequence:
                            new_sub.append(subsequence + [nxt])
                    if len(new_sub) > 0:
                        sequence_same_start.extend(new_sub)
                        curr_step_sequence = new_sub
                    else:
                        flag = 1

                if flag == 1:
                    break

            for sub in sequence_same_start:
                if len(sub) < num_slots:
                    sub += [''] * (num_slots - len(sub))

            sequence.extend(sequence_same_start)
        constraint_list.append(TableConstraint('can follow', var_array[i], sequence))

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

    # 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:  # solution is list of tuple of assignment
        assigned = []
        for var, val in solution:   # check all assigned
            if val not in assigned and val != '':
                assigned.append(val)
        if len(assigned) == len(flights):
            curr_solution = []
            pivot = 0
            for plane in planes:
                plane_sol = [plane]
                flight_sol = solution[pivot:pivot + len(planes_problem.can_fly(plane))]
                pivot += len(planes_problem.can_fly(plane))
                # remove ''
                remove_empty = []
                for var, val in flight_sol:
                    if val != '':
                        remove_empty.append(val)

                # check maintenance
                maintenance_list = []
                for flight in remove_empty:
                    if flight in maintenance_flights:
                        maintenance_list.append(1)
                    else:
                        maintenance_list.append(0)
                if maintenance_check(maintenance_list, frequency):
                    plane_sol.extend(remove_empty)
                    curr_solution.append(plane_sol)
            if curr_solution:
                allSolution.append(curr_solution)

    # then return a list containing all converted solutions
    # (i.e., a list of lists of lists)
    return allSolution
Exemplo n.º 6
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.
    '''

    # class CSP:
    # def __init__(self, name, variables, constraints):

    #BUILD your CSP here and store it in the varable csp
    # util.raiseNotDefined()

    # use time slots as variables
    event_in_time = {}
    for class_info in schedule_problem.classes:
        info = class_info.split('-')
        time = int(info[2])
        if time not in event_in_time:
            event_in_time[time] = [class_info]
        else:
            event_in_time[time].append(class_info)

    variables = []
    v_domain = []
    # for i in range(schedule_problem.num_time_slots):
    #     v_domain.append(NOCLASS)
    v_domain.append(NOCLASS)

    # create variables
    for i in range(schedule_problem.num_time_slots):
        new_slot_name = "{}".format(i + 1)
        if (i + 1) in event_in_time:
            # change
            variables.append(
                Variable(
                    new_slot_name,
                    v_domain + event_in_time[i + 1] + event_in_time[i + 1]))
        else:
            variables.append(Variable(new_slot_name, v_domain))

    # There are 4 contstrings, 3 new and 1 alredy been implemented
    constraints = []

    # 1
    # use NValuesConstraint for student should take all courses on the list
    # print("c1")

    c_type = {}
    for c in schedule_problem.classes:
        info = c.split('-')
        cur_type = info[0] + '-' + info[3]
        # print(cur_type)
        if cur_type in c_type:  #already in
            c_type[cur_type].append(c)
        else:
            c_type[cur_type] = [c]
    # print(c_type)
    for key_type in c_type:
        constraints.append(
            NValuesConstraint("c1_{}".format(key_type), variables,
                              c_type[key_type], 1, 1))

    # 2, sep for sepcific class
    # print("c2")

    sep_class = {}
    for key_type in c_type:
        info = key_type.split('-')
        cur_class = info[0]
        lt = info[1]
        if cur_class in sep_class:  #already in
            sep_class[cur_class][lt] = c_type[
                key_type]  # since there are no  duplicates in c_types
        else:
            sep_class[cur_class] = {lt: c_type[key_type]}
    # print(sep_class)
    for cur_class in sep_class:
        if TUT in sep_class[cur_class]:  # have both lec and tut
            constraints.append(
                taftercConstraint("c2_{}".format(cur_class), variables,
                                  sep_class[cur_class][LEC],
                                  sep_class[cur_class][TUT]))

    # 3
    # print("c3")

    close_distance_buildings = {}
    for building in schedule_problem.buildings:
        close_distance_buildings[
            building] = schedule_problem.connected_buildings(building)
    constraints.append(cdbConstraint("c3", variables,
                                     close_distance_buildings))

    # 4
    # print("c4")

    constraints.append(
        rfConstraint("c4", variables, schedule_problem.min_rest_frequency))

    csp = CSP("Class_Sheduling_Problem", 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 student in the format described above.
    final_solution = []
    for s in solutions:
        cur_soluction = []
        for (var, val) in s:
            cur_soluction.append(val)
        if cur_soluction not in final_solution:
            final_solution.append(cur_soluction)
    return final_solution
def solve_planes(planes_problem,
                 algo,
                 allsolns,
                 variableHeuristic='mrv',
                 silent=False,
                 trace=True):
    # 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

    planes = planes_problem.planes
    flights = planes_problem.flights
    can_follow = planes_problem.can_follow
    maintenance_flights = planes_problem.maintenance_flights
    min_maintenance = planes_problem.min_maintenance_frequency
    flights_of_planes = []
    variables = []
    constraints_list = []
    max_flights = 0

    for p in planes:
        if len(planes_problem.can_fly(p)) > max_flights:
            max_flights = len(planes_problem.can_fly(p))
        if max_flights == len(flights):
            break

    for plane in planes:
        for i in range(max_flights):
            if i == 0:
                # Constraint 2
                var = Variable(plane + ' flight' + str(i),
                               planes_problem.can_start(plane) + [''])
            else:
                # Constraint 1
                var = Variable(plane + ' flight' + str(i),
                               planes_problem.can_fly(plane) + [''])
            variables.append(var)

    for i in range(len(planes)):
        lst = []
        for j in range(max_flights):
            lst.append(variables[j + i * max_flights])
        flights_of_planes.append(lst)

    # Constraint 3
    can_follow_lists = [list(c)
                        for c in can_follow] + [[f, '']
                                                for f in flights] + [['', '']]
    for i in range(len(flights_of_planes)):
        for j in range(1, len(flights_of_planes[i])):
            constraints_list.append(
                TableConstraint(
                    "Can follow ",
                    [flights_of_planes[i][j - 1], flights_of_planes[i][j]],
                    can_follow_lists))

    # Constraint 4
    for i in range(len(flights_of_planes)):
        for j in range(len(flights_of_planes[i]) - min_maintenance + 1):
            constraints_list.append(
                NValuesConstraint("Maintenance",
                                  flights_of_planes[i][j:j + min_maintenance],
                                  maintenance_flights, 1, min_maintenance))

    # Constraint 5
    non_empty_variables = []
    for v in variables:
        if v.getValue() != '':
            non_empty_variables.append(v)
    constraints_list.append(
        AllDiffConstraint("All Flights", non_empty_variables))
    constraints_list.append(
        NValuesConstraint("Every flight flown", non_empty_variables, flights,
                          len(flights), len(flights)))

    csp = CSP('plane scheduling', variables, constraints_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.
    formatted_sol = []
    for s in solutions:
        total_sol = []
        for i in range(len(planes)):
            for j in range(max_flights):
                curr_sol = [planes[i]]
                for k in range(len(s)):
                    if s[k][0].name().split(
                    )[0] == planes[i] and s[k][1] != '':
                        curr_sol.append(s[k][1])
                if curr_sol not in total_sol:
                    total_sol.append(curr_sol)
        formatted_sol.append(total_sol)

    # then return a list containing all converted solutions
    # (i.e., a list of lists of lists)
    return formatted_sol
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
    # util.raiseNotDefined()

    # csp = None #set to to your CSP
    #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)

    def initPlaneCSP(planes_problem):

        planes = planes_problem.planes.copy()
        flights = planes_problem.flights.copy()
        planes_can_fly_flights = planes_problem._can_fly.copy()
        valid_first_flights = planes_problem._flights_at_start.copy()
        valid_flight_prev_next_pairs = planes_problem.can_follow.copy()
        maintenance_flights = planes_problem.maintenance_flights.copy()
        min_maintenance_frequency = planes_problem.min_maintenance_frequency

        #First define the variables:
        # 构建Variables
        # Variable的设定是plane + 这个plane可以飞的航班flight
        # 假设有n个plane, 每个plane能飞m个航班flight, 那么我们就会有nm个variable在variable_arr里
        variable_arr = []
        for planeIndex in range(len(planes)):
            variable_arr.append([])
            domain = [0]
            domain.extend(planes_can_fly_flights[planes[planeIndex]])
            for flyableFlightIndex in range(
                    len(planes_can_fly_flights[planes[planeIndex]])):
                newVar = Variable(
                    "{},{}".format(
                        planes[planeIndex], planes_can_fly_flights[
                            planes[planeIndex]][flyableFlightIndex]), domain)
                variable_arr[planeIndex].append(newVar)

        #Set up the constraints
        constraint_list = []

        # Flight Maintenance constraints
        # 用 NValuesConstraint 因为对这个航班的数量有要求
        # lowerBound is 1
        # upperBound is min_maintenance_frequency
        required_values = [0]
        required_values.extend(maintenance_flights)
        for sub_arr in variable_arr:
            for index in range(len(sub_arr) - min_maintenance_frequency + 1):
                # scope 的长度是最多是min_maintenance_frequency
                scope = sub_arr[index:index + min_maintenance_frequency]
                # required_values 这里是maintenance的航班
                # 至少有一个航班要是maintenance 航班, 最多是min_maintenance_frequency个
                constraint_list.extend([
                    NValuesConstraint(
                        "[{}] maintenance flight".format(sub_arr), scope,
                        required_values, 1, min_maintenance_frequency)
                ])

        # Consecutive flight constraints
        # allConsecutiveFlights 放所有的可以连接起来的flights
        allConsecutiveFlights = [[0, 0]]
        for pair in valid_flight_prev_next_pairs:
            allConsecutiveFlights.append(list(pair))
        for flight in flights:
            allConsecutiveFlights.append([flight, 0])

        # Construct constraints for possible consecutive two flights
        for sub_arr in variable_arr:
            for index in range(len(sub_arr) - 1):
                [prevFlight, nextFlight] = [sub_arr[index], sub_arr[index + 1]]
                # [prevFlight, nextFlight] 可以从allConsecutiveFlights里面挑选合适的pair
                new_constraint = TableConstraint(
                    "[{}] consecutive flights".format(sub_arr),
                    [prevFlight, nextFlight], allConsecutiveFlights)
                constraint_list.extend([new_constraint])

        # First flight constraints
        for index in range(len(variable_arr)):
            initialFlight = variable_arr[index][0]
            initialFlightDomain = [[0]]  # 0 for having no flight
            for possibleFirstFlight in valid_first_flights[planes[index]]:
                initialFlightDomain.append([possibleFirstFlight])
            # initialFlight 是从 initialFlightDomain 里面挑选
            constraint_list.extend([
                TableConstraint("[{}] first flight".format(initialFlight),
                                [initialFlight], initialFlightDomain)
            ])

        # Cover all flights and no more than once
        variables = [var for row in variable_arr for var in row]
        constraint_list.extend(
            [coverAndNoDuplicate("all flights", variables, flights)])

        return CSP("Plane Scheduling Problem", variables, constraint_list)

    csp = initPlaneCSP(planes_problem)

    #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)
    allSolutions = []
    if len(solutions) == 0:
        if not silent:
            print("No solution found")

    for solution in solutions:
        currentSolution = []
        flightArrangement = dict()
        for (planeVar, flight) in solution:
            plane = planeVar.name().split(',')[0]
            if plane in flightArrangement:
                flightArrangement[plane].append([flight])
            else:
                flightArrangement[plane] = [[flight]]
        planes = list(flightArrangement.keys())
        for plane in planes:
            planeSchedule = [plane]
            for [flight] in flightArrangement[plane]:
                if flight != 0:
                    planeSchedule.append(flight)
            currentSolution.append(planeSchedule)
        allSolutions.append(currentSolution)
    return allSolutions
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.
    '''

    # Initialization:
    k = schedule_problem.num_time_slots
    scopeList = [['NOCLASS'] for i in range(k)]

    # Looping through classes:
    for classItem in schedule_problem.classes:
        scopeList[int(classItem.split('-')[2]) - 1].append(classItem)

    # Initializing constraints list, schedule solution list, and defining variableList:
    variableList = [Variable(j, scopeList[j]) for j in range(k)]
    courseList = list(product(*scopeList))
    courseList = [list(item) for item in courseList]
    constraints = []
    scheduleSolutionList = []

    # Iterating through course list for potential solutions:
    for solutionItem in courseList:
        if check_schedule_solution(schedule_problem, solutionItem):
            constraints.append(solutionItem)

    # Defining additional constraints and calling the CSP solver:
    constraints = TableConstraint('all_constraints', variableList, constraints)
    csp = CSP('Solver', variableList, [constraints])

    # Calling bt_search:
    solutions, num_nodes = bt_search(algo, csp, variableHeuristic, True, trace)

    # Appending solutions to schedule list:
    for solution in solutions:
        solutionClassList = [j[1] for j in solution]
        scheduleSolutionList.append(solutionClassList)

    return scheduleSolutionList
Exemplo n.º 10
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
    list_of_planes = planes_problem.planes
    list_of_flights = planes_problem.flights
    # valid_flights = planes_problem.can_fly(list_of_planes[0])
    # can_start = planes_problem.can_start(list_of_planes[0])
    can_follow_list = planes_problem.can_follow

    constraint = []
    variables = []

    for plane in list_of_planes:
        valid_flights = planes_problem.can_fly(plane)
        for f in valid_flights:
            variable_to_add = Variable(plane, planes_problem.can_fly(plane))
            variables.append(variable_to_add)

    for flight in list_of_flights:
        constraint_to_add = NValuesConstraint(flight, variables, [flight], 1,
                                              1)
        constraint.append(constraint_to_add)

    for i in range(len(variables)):
        if i < len(variables) - 1:
            table_constraint = TableConstraint(
                "table", [variables[i], variables[i + 1]],
                planes_problem.can_follow)
            constraint.append(table_constraint)

    csp = CSP("Plane Problem", variables, constraint)

    #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)
    answer = []
    for i in range(len(solutions)):
        f = []
        f.append(solutions[i][0][0].name())
        for var in solutions[i]:
            f.append(var[1])
        solution = []
        solution.append(f)
        answer.append(solution)
    return answer
Exemplo n.º 11
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
    # util.raiseNotDefined()

    list_of_can_follow = [list(elem) for elem in planes_problem.can_follow]
    for flight in planes_problem.flights:
        list_of_can_follow.append([flight, "NOFLIGHT"])
    list_of_can_follow.append(["NOFLIGHT", "NOFLIGHT"])

    required_maintenance_flights = ["NOFLIGHT"]
    required_maintenance_flights.extend(planes_problem.maintenance_flights)
    min_maintenance_frequency = planes_problem.min_maintenance_frequency

    var_array = []
    constraint_list = []

    for plane in planes_problem.planes:
        legal_flights = planes_problem.can_fly(plane)
        legal_flights.append("NOFLIGHT")
        plane_scope = []
        for i in range(len(legal_flights) - 1):
            newVar = Variable('{}-{}'.format(plane, i + 1), legal_flights)
            var_array.append(newVar)
            if i == 0:
                list_of_can_start = [
                    [elem] for elem in planes_problem.can_start(plane)
                ]
                list_of_can_start.append(["NOFLIGHT"])
                constraint_list.append(
                    TableConstraint('plane_start', [newVar],
                                    list_of_can_start))
            else:
                constraint_list.append(
                    TableConstraint('plane_can_follow', [oldVar, newVar],
                                    list_of_can_follow))
            oldVar = newVar
            plane_scope.append(newVar)
        for i in range(len(plane_scope) - min_maintenance_frequency + 1):
            scope = plane_scope[i:i + min_maintenance_frequency]
            constraint_list.append(
                NValuesConstraint('plane_min_freq', scope,
                                  required_maintenance_flights, 1,
                                  min_maintenance_frequency))

    constraint_list.append(
        checkAllFlights("plane_all_diff", var_array, planes_problem.flights))

    csp = CSP("PlaneScheduling", var_array,
              constraint_list)  #set to to your CSP
    #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.

    res = []
    plane = {}

    for s in solutions:
        temp = []
        plane = {}
        for (var, val) in s:
            plane_name = var.name()[:-2]
            flight_no = var.name()[-1]
            if val != "NOFLIGHT":
                if plane_name in plane:
                    plane[plane_name].append((flight_no, val))
                else:
                    plane[plane_name] = [(flight_no, val)]

        for k, v in plane.items():
            v = sorted(v, key=lambda x: x[0])
            v = [x[1] for x in v]
            v.insert(0, k)
            temp.append(v)

        res.append(temp)

    return res