示例#1
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging
    #trace = True
    if unAssignedVars.empty():
        if trace: print "{} Solution Found".format(csp.name())
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))
            #if allSolutions:
        return [soln]
            #else:
                #exit
    bt_search.nodesExplored += 1
    solns = []
    nxtvar = unAssignedVars.extract()
    if trace: print "==>Trying {}".format(nxtvar.name())
    for val in nxtvar.curDomain(): #curDomain for FC!!
        if trace: print "==> {} = {}".format(nxtvar.name(), val)
        nxtvar.setValue(val)
        noDWO = True
        for constraint in csp.constraintsOf(nxtvar):
            #print "fc constr,", constraint
            if constraint.numUnassigned() == 1:
                if FCCheck(constraint, nxtvar, val) == "DWO":
                    noDWO = False
                    if trace: print "<==falsified constraint\n"
                    break
        if noDWO:
            new_solns = FC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            Variable.restoreValues(nxtvar, val)

            if len(solns)> 0 and not allSolutions:
                break
        Variable.restoreValues(nxtvar, val)

    nxtvar.unAssign() #same as set Vlue none
    #nxtvar.setValue(None)
    unAssignedVars.insert(nxtvar)

    return solns
示例#2
0
def my_csp_problem_1():
    # Defined in notebook

    constraints = []

    variables = []
    variables.append(Variable("1", ['R', 'G', 'B', 'Y']))
    variables.append(Variable("2", ['R', 'G', 'B', 'Y']))
    variables.append(Variable("3", ['R', 'G', 'B', 'Y']))
    variables.append(Variable("4", ['R', 'G', 'B', 'Y']))
    variables.append(Variable("5", ['R', 'G', 'B', 'Y']))

    # these are all variable pairing of adjacent slots
    adjacent_pairs = [
        ("1", "2"), ("1", "5"), ("2", "1"), ("2", "3"), ("2", "5"), ("3", "2"),
        ("3", "4"), ("3", "5"), ("4", "3"), ("4", "5"), ("5", "1"), ("5", "2"),
        ("5", "3"), ("5", "4")
    ]

    # No same neighbor colors
    def base_rule(val_a, val_b, name_a, name_b):
        if val_a == val_b:
            return False
        return True

    for pair in adjacent_pairs:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], base_rule,
                             "No same color neighbors"))

    return CSP(constraints, variables)
示例#3
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging
    if unAssignedVars.empty():
        if trace: print "{} Solution Found".format(csp.name())
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  #each call returns a list of solutions found
    bt_search.nodesExplored += 1
    solns = []  #so far we have no solutions recursive calls
    nxtvar = unAssignedVars.extract()
    if trace: print "==>Trying {}".format(nxtvar.name())

    for val in nxtvar.curDomain():
        if trace: print "==> {} = {}".format(nxtvar.name(), val)
        nxtvar.setValue(val)
        constraintsOK = True
        lastVar = None
        pruned_var = []
        for cnstr in csp.constraintsOf(nxtvar):
            if cnstr.numUnassigned() == 1:
                lastVar = cnstr.unAssignedVars()[0]
                pruned_var.append(lastVar)
                if FCCheck(cnstr, nxtvar, val) == "DWO":
                    constraintsOK = False
                    if trace: print "<==falsified constraint\n"
                    break
        if constraintsOK:
            new_solns = FC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break  #don't bother with other values of nxtvar
                #as we found a soln.
        # FCCheck failed or search rest solns, need to restore
        Variable.restoreValues(nxtvar, val)
    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging

    if unAssignedVars.empty():
        if trace: print("{} Solution Found".format(csp.name()))
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  #each call returns a list of solutions found
    
    solns = []         #so far we have no solutions recursive calls
    nxtvar = unAssignedVars.extract()
    if trace: print("==>Trying {}".format(nxtvar.name()))

    for val in nxtvar.curDomain():
        if trace: print("==> {} = {}".format(nxtvar.name(), val))
        nxtvar.setValue(val)
        # Prune all values of V ≠ d from CurDom[V]
        for p in nxtvar.curDomain():
            if val != p:
                nxtvar.pruneValue(p, nxtvar, val)
        # for each constraint C whose scope contains V 
 Put C on GACQueue

        GACQueue = []
        for c in csp.constraints():
            if nxtvar in c.scope():
                GACQueue.append(c)
        if GacEnforce(GACQueue, csp, nxtvar, val) != "DWO":
            new_solns = GAC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break
        Variable.restoreValues(nxtvar, val)

    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns        
示例#5
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging

    if unAssignedVars.empty():
        if trace: print("{} Solution Found".format(csp.name()))
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  #each call returns a list of solutions found
    bt_search.nodesExplored += 1
    solns = []  #so far we have no solutions recursive calls

    "Choos a value from the unassigned ones"
    nxtvar = unAssignedVars.extract()
    if trace: print("==>Trying {}".format(nxtvar.name()))

    "Assign every value to the next variable from its domain -- Note that curDomain is used instead of domain because cur is pruned"
    for val in nxtvar.curDomain():
        if trace: print("==> {} = {}".format(nxtvar.name(), val))

        nxtvar.setValue(val)

        "For every constraint that the next variable has to satisfy -- "
        if GacEnforce(csp.constraintsOf(nxtvar), csp, nxtvar, val) == "OK":
            new_solns = GAC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break  #don't bother with other values of nxtvar
                #as we found a soln.

        "Restore all the values that have been pruned away"
        Variable.restoreValues(nxtvar, val)

    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns
示例#6
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging
    # util.raiseNotDefined()
    # print unAssignedVars
    if unAssignedVars.empty():
        if trace: print "{} Solution Found".format(csp.name())
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))
        return [soln]

    bt_search.nodesExplored += 1
    solns = []
    nextVar = unAssignedVars.extract()
    if trace: print "{} Solution Found".format(csp.name())

    for value in nextVar.curDomain():
        nextVar.setValue(value)
        noDWO = True
        constraints = csp.constraintsOf(nextVar)
        if GacEnforce(constraints, csp, nextVar, value) == "DWO":
            if trace: print "<==falsified constraint\n"
            noDWO = False
        if noDWO:
            newSolns = GAC(unAssignedVars, csp, allSolutions, trace)
            if newSolns:
                solns.extend(newSolns)
            if len(solns) > 0 and not allSolutions:
                # restore pruned values even if FC is terminating after one solution found; if keep finding other
                # solutions, the second restoreValues gonna be executed
                Variable.restoreValues(nextVar, value)
                break
        Variable.restoreValues(nextVar, value)

    nextVar.unAssign()
    unAssignedVars.insert(nextVar)
    return solns
示例#7
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of unassigned variables.  
       csp is the csp problem, 
       allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging

    #Forward checking, pass unassigned variables
    if unAssignedVars.empty():  #no more unassigned variables
        # print "{} Solution Found".format(csp.name())
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))
            if not allSolutions:
                Variable.restoreValues(var, var.getValue())
        return [soln]  #terminate after one solution found.
    var = unAssignedVars.extract()  #select next variable to assign
    # print "==>Trying {}".format(var.name())
    bt_search.nodesExplored += 1
    solns = []
    for val in var.curDomain():
        # print "==> {} = {}".format(var.name(), val)
        var.setValue(val)
        noDWO = True
        for constraint in csp.constraintsOf(var):
            if constraint.numUnassigned() == 1:
                if FCCheck(constraint, var,
                           val) == "DWO":  #prune future variables
                    noDWO = False  #pass var/val as reason
                    # print "<==falsified constraint\n"
                    break
        if noDWO:
            solns.extend(FC(unAssignedVars, csp, allSolutions, trace))
        if len(solns) > 0 and not allSolutions:
            break  #don't bother with other values of var
            #as we found a soln.
        Variable.restoreValues(var,
                               val)  #restore values pruned by this assignment
    var.setValue(None)  #undo assignemnt to var
    unAssignedVars.insert(var)  #restore var to unAssignedVars
    return solns
示例#8
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging
    if unAssignedVars.empty():
        if trace: print "{} Solution Found".format(csp.name())
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  #each call returns a list of solutions found
    bt_search.nodesExplored += 1
    solns = []  #so far we have no solutions recursive calls
    nxtvar = unAssignedVars.extract()
    if trace: print "==>Trying {}".format(nxtvar.name())

    for val in nxtvar.curDomain():
        if trace: print "==> {} = {}".format(nxtvar.name(), val)
        nxtvar.setValue(val)
        constraintsOK = True
        constraints = csp.constraintsOf(nxtvar)
        subResult = GacEnforce(constraints, csp, nxtvar, val)
        if subResult == "DWO":
            constraintsOK = False
            if trace: print "<==falsified constraint\n"
        if constraintsOK:

            new_solns = GAC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break  #don't bother with other values of nxtvar
                #as we found a soln.

        Variable.restoreValues(nxtvar, val)
    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns
示例#9
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging
    if unAssignedVars.empty():
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))

        return [soln]

    bt_search.nodesExplored += 1
    solns = []  #so far we have no solutions recursive calls
    var = unAssignedVars.extract()

    for val in var.curDomain():
        var.setValue(val)
        noDwo = True
        for cnstr in csp.constraintsOf(var):
            if cnstr.numUnassigned() == 1:
                if FCCheck(cnstr, var, val) == "DWO":
                    noDwo = False
                    break

        if noDwo:
            new_solns = FC(unAssignedVars, csp, allSolutions, trace)
            Variable.restoreValues(var, val)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                break  #don't bother with other values of nxtvar
                #as we found a soln.
        Variable.restoreValues(var, val)

    var.unAssign()
    unAssignedVars.insert(var)
    return solns
示例#10
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.
       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging

    # util.raiseNotDefined()
    if unAssignedVars.empty():
        if trace:
            print("{} Solution Found".format(csp.name()))
        solution = []
        for var in csp.variables():
            if trace:
                print(var.name(), ",", var.getValue())
            solution.append((var, var.getValue()))
        return [solution]
    all_solutions = []
    var = unAssignedVars.extract()
    bt_search.nodesExplored += 1
    if trace:
        print(" Trying {}".format(var.name()))
    for val in var.curDomain():
        if trace:
            print(" {} = {}".format(var.name(), val))
        var.setValue(val)
        noDWO = True
        if GacEnforce(csp.constraintsOf(var), csp, var, val) == "DWO":
            noDWO = False
        if noDWO:
            currentSolution = GAC(unAssignedVars, csp, allSolutions, trace)
            all_solutions.extend(currentSolution)

            if (not allSolutions) and len(all_solutions) >= 1:
                Variable.restoreValues(var, val)
                break
        Variable.restoreValues(var, val)
    var.unAssign()
    unAssignedVars.insert(var)
    return all_solutions
示例#11
0
def planeCSP(planes_problem):
    planes = planes_problem.planes
    flights = planes_problem.flights
    flights_can_follow = planes_problem.can_follow
    maintenance_flights = planes_problem.maintenance_flights
    min_maintenance_frequency = planes_problem.min_maintenance_frequency

    # first define the variables
    var_array = []
    for i, plane in enumerate(planes):
        can_fly = planes_problem.can_fly(plane)
        var_array.append([])
        for j in range(len(can_fly)):
            # -1 indicates no flight assigned
            if j == 0:
                dom = [
                    x for x in planes_problem.can_start(plane) if x in can_fly
                ] + [-1]
                var = Variable("V{},{}".format(plane, j), dom)
            else:
                var = Variable("V{},{}".format(plane, j), can_fly + [-1])
            var_array[i].append(var)
    # Set up the constraints
    constraint_list = []
    # can_follow constraint
    for flight in flights:
        flights_can_follow.append((flight, -1))
    flights_can_follow.append((-1, -1))
    for i in range(len(var_array)):
        for j in range(len(var_array[i]) - 1):
            scope = [var_array[i][j], var_array[i][j + 1]]
            constraint_list.append(
                TableConstraint("Follow {}{}".format(i, j), scope,
                                flights_can_follow))
    # maintenance
    for i in range(len(var_array)):
        for j in range(len(var_array[i]) - min_maintenance_frequency + 1):
            scope = []
            for k in range(j, j + min_maintenance_frequency):
                scope.append(var_array[i][k])
            constraint_list.append(
                NValuesConstraint("Maintenance {}{}".format(i, j), scope,
                                  maintenance_flights + [-1], 1,
                                  min_maintenance_frequency))
    # Exactly one flight
    vars = [var for row in var_array for var in row]
    for flight in flights:
        constraint_list.append(
            NValuesConstraint("Exactly One {}".format(flight), vars, [flight],
                              1, 1))
    return CSP("Plane Schedule", vars, constraint_list), var_array
示例#12
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
    #TODO: q4
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging
    # TODO: q4 in CSP pseudo code

    if unAssignedVars.empty():
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))
        #if allSolutions:
        return [soln]
    var = unAssignedVars.extract()
    bt_search.nodesExplored += 1

    solns = []
    for val in var.curDomain():
        var.setValue(val)
        noDWO = True
        if GacEnforce(csp.constraintsOf(var), csp, var, val) == "DWO":
            noDWO = False
        if noDWO:
            new_solns = GAC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            Variable.restoreValues(var, val)

            if len(solns)> 0 and not allSolutions:
                break
        Variable.restoreValues(var, val)
    var.setValue(None)
    unAssignedVars.insert(var)
    return solns
示例#13
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging

    if unAssignedVars.empty():
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  # each call returns a list of solutions found
    bt_search.nodesExplored += 1
    solns = []  # so far we have no solutions recursive calls
    nxtvar = unAssignedVars.extract()
    for val in nxtvar.curDomain():
        nxtvar.setValue(val)
        status = "none"
        DWO = "DWO"
        nDWO = "nDWO"
        if GacEnforce(csp.constraintsOf(nxtvar), csp, nxtvar, val) == DWO:
            status = DWO
        else:
            status = nDWO
        if status == nDWO:
            new_solns = GAC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break
        Variable.restoreValues(nxtvar, val)
    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns
示例#14
0
def PlaneCSP(planes_problem):
    constraint_list = []
    result = []
    can_follow = planes_problem.can_follow
    variables = []
    min_main_freq = planes_problem.min_maintenance_frequency
    maintenance_flights = planes_problem.maintenance_flights
    planes_list = []
    for x in range(len(planes_problem.planes)):
        planes_list.append([])
    for ind, plane in enumerate(planes_problem.planes):
        can_fly = planes_problem.can_fly(plane)
        planes_list[ind] = []
        for y in range(len(can_fly)):
            if y!=0:
                variable = Variable("{}{}".format(plane,str(y)),can_fly+["NULL"])
            else:
                can_start = planes_problem.can_start(plane) 
                variable = Variable("{}{}".format(plane,str(y)),can_start+["NULL"])
            planes_list[ind].append(variable)
            variables.append(variable)
    #----constraints-----
    #terminate at a maintenance location
    for x in range(len(planes_list)):
        k = len(planes_list[x]) - min_main_freq + 1
        if k > 0:
            for y in range(k):
                scope = []
                for z in range(y,y+min_main_freq):
                    scope.append(planes_list[x][z])
                constraint = NValuesConstraint("Maintenance {}{}".format(x,z), scope, maintenance_flights + ["NULL"], 1, min_main_freq)
                constraint_list.append(constraint)
    #constraint to schedule each flight only once
    for flight in planes_problem.flights:
        constraint = NValuesConstraint("Flight {}".format(flight), variables, [flight], 1, 1)
        constraint_list.append(constraint)
    #can_follow constraint
    for flight in planes_problem.flights:
        can_follow.append((flight,"NULL"))
    can_follow.append(("NULL","NULL"))
    for x in range(len(planes_list)):
        for y in range(len(planes_list[x]) - 1):
            scope = [planes_list[x][y], planes_list[x][y+1]]
            constraint = TableConstraint("Can_follow {}{}".format(x,y), scope, can_follow)
            constraint_list.append(constraint)
    result.append(CSP("PlaneProblem",variables,constraint_list))
    result.append(planes_list)
    return result
示例#15
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    if unAssignedVars.empty():
        if trace: print "{} Solution Found".format(csp.name())
        soln = []
        for v in csp.variables():
            soln.append((v, v.getValue()))
        return [soln]  # each call returns a list of solutions found
    bt_search.nodesExplored += 1
    solns = []  # so far we have no solutions recursive calls
    nxtvar = unAssignedVars.extract()
    if trace: print "==>Trying {}".format(nxtvar.name())
    for val in nxtvar.curDomain():
        if trace: print "==> {} = {}".format(nxtvar.name(), val)
        nxtvar.setValue(val)
        noDWO = True
        for cnstr in csp.constraintsOf(nxtvar):
            if cnstr.numUnassigned() == 1:
                if FCCheck(cnstr, nxtvar, val) == "DWO":
                    noDWO = False
                    if trace: print "<==Domain Wipe Out\n"
                    break
        if noDWO:
            new_solns = FC(unAssignedVars, csp, allSolutions, trace)
            if new_solns:
                solns.extend(new_solns)
            if len(solns) > 0 and not allSolutions:
                Variable.restoreValues(nxtvar, val)
                break  # don't bother with other values of nxtvar
                # as we found a soln.
        Variable.restoreValues(nxtvar, val)
    nxtvar.unAssign()
    unAssignedVars.insert(nxtvar)
    return solns
示例#16
0
def schedules(schedule_problem):
    '''Return an n-queens CSP, optionally use tableContraints'''
    #your implementation for Question 4 changes this function
    #implement handling of model == 'alldiff'
    t_dom = defaultdict(list)
    course_classes_dict = defaultdict(list)

    for class_info in schedule_problem.classes:

        info = class_info.split('-')
        time_slot = int(info[2])
        # Domain for each possible timeslot
        t_dom[time_slot].append(class_info)
        # A dictionary of course-class mappings
        course_classes_dict[info[0]].append(class_info)

    vars = []
    for t in range(1,schedule_problem.num_time_slots + 1):

        t_dom[t].append(NOCLASS)
        vars.append(Variable('T_{}'.format(t), t_dom[t]))

    cnstrs = []

    for course in schedule_problem.courses:

        lectures = [c for c in course_classes_dict[course] if c.split('-')[3] == LEC]
        tuts = [c for c in course_classes_dict[course] if c.split('-')[3] == TUT]
        one_lec_cnstr = NValuesConstraint('One_lecture', vars, lectures, 1, 1)
        one_tut_cnstr = NValuesConstraint('One_tutorial', vars, tuts, 1, 1)
        cnstrs.append(one_lec_cnstr)
        cnstrs.append(one_tut_cnstr)

    for ti in range(schedule_problem.num_time_slots):

        for tj in range(ti + 1, schedule_problem.num_time_slots):

            scope = [vars[ti], vars[tj]]
            sat_assignments = lecture_tut_sat_assignments(scope)
            tut_after_lec_cnstr = TableConstraint("C(T{},T{})".format(ti+1,tj+1), scope, sat_assignments)
            cnstrs.append(tut_after_lec_cnstr)

    for ti in range(schedule_problem.num_time_slots - 1):

        scope = [vars[ti], vars[ti + 1]]
        sat_assignments = building_sat_assignments(scope, schedule_problem.connected_buildings)
        close_buildings_cnstr = TableConstraint("C(B{})".format(ti+1), scope, sat_assignments)
        cnstrs.append(close_buildings_cnstr)

    min_rest = schedule_problem.min_rest_frequency

    for ti in range(schedule_problem.num_time_slots - (min_rest -1)):

        scope = vars[ti:ti + min_rest]
        rest_cnstr = NValuesConstraint("Min_rest{}".format(min_rest),
                                       scope, [NOCLASS], 1, min_rest)
        cnstrs.append(rest_cnstr)

    csp = CSP("{}-Schedule".format(schedule_problem.num_time_slots), vars, cnstrs)
    return csp
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
示例#18
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':
        cons.append(AllDiffConstraint("nQueens_alldiff", vars))
        for i in range(n):
          for j in range(i+1, n):
            cons.append(NeqConstraint("nQueens_neq", [vars[i], vars[j]], i+1, j+1))
    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
示例#19
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging

    if unAssignedVars.empty():
        soln = []
        for var in csp.variables():
            soln.append((var, var.getValue()))
            if not allSolutions:
                Variable.restoreValues(var, var.getValue())
        return [soln]
    var = unAssignedVars.extract()  #select next variable to assign
    bt_search.nodesExplored += 1
    solns = []
    for val in var.curDomain():  #current domain!
        var.setValue(val)
        noDWO = True
        if GacEnforce(csp.constraintsOf(var), csp, var, val) == "DWO":
            #only var's domain changed-constraints with var have to be checked
            noDWO = False
        if noDWO:
            solns.extend(GAC(unAssignedVars, csp, allSolutions, trace))
        if len(solns) > 0 and not allSolutions:
            break  #don't bother with other values of var
            #as we found a soln.
        Variable.restoreValues(
            var, val)  #restore values pruned by var = val assignment
    var.setValue(None)  #set var to be unassigned and return to list
    unAssignedVars.insert(var)
    return solns
示例#20
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging
    solutions = []
    if unAssignedVars.empty():
        solution = [(var,var.getValue()) for var in csp.variables()]
        solutions.append(solution)
        return solutions
    var = unAssignedVars.extract()
    for val in var.curDomain():
        var.setValue(val)
        noDWO = True
        for constraint in csp.constraintsOf(var):
            if constraint.numUnassigned()==1:
                if FCCheck(constraint,var,val)=="DWO":
                    noDWO = False
                    break
        if noDWO:
            new = FC(unAssignedVars,csp,allSolutions,trace)
            if new:
                solutions.extend(new)
            if not(len(solutions)==0 or allSolutions):
                Variable.restoreValues(var,val)
                break
        Variable.restoreValues(var,val)
    var.unAssign()
    unAssignedVars.insert(var)
    return solutions

    util.raiseNotDefined()
示例#21
0
def GAC(unAssignedVars, csp, allSolutions, trace):
    '''GAC search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 3 goes in this function body
    #You must not change the function parameters.
    #implementing support for "trace" is optional, but it might
    #help you in debugging
    solutions = []
    if unAssignedVars.empty():
        if trace:
            for var in csp.variables():
                print var.name(), " = ", var.getValue()
        solution = [(var,var.getValue()) for var in csp.variables()]
        solutions.append(solution)
        return solutions
    var = unAssignedVars.extract()
    for val in var.curDomain():
        var.setValue(val)
        noDWO = True
        if GacEnforce(csp.constraintsOf(var),csp,var,val)=="DWO":
            noDWO = False
        if noDWO:
            new = GAC(unAssignedVars,csp,allSolutions,trace)
            if new:
                solutions.extend(new)
            if not(len(solutions)==0 or allSolutions):
                Variable.restoreValues(var,val)
                break
        Variable.restoreValues(var,val)
    var.unAssign()
    unAssignedVars.insert(var)
    return solutions
示例#22
0
def time_traveling_csp_problem():
    constraints = []

    variables = []
    # order of the variables here is the order given in the problem
    variables.append(Variable("T", ["1"]))
    variables.append(Variable("L", ["1", "2", "3", "4"]))
    variables.append(Variable("B", ["1", "2", "3", "4"]))
    variables.append(Variable("C", ["1", "2", "3", "4"]))
    variables.append(Variable("S", ["1", "2", "3", "4"]))
    variables.append(Variable("P", ["1", "2", "3", "4"]))
    variables.append(Variable("N", ["1", "2", "3", "4"]))

    # these are all variable pairing of adjacent seats
    edges = [("C", "P"), ("C", "L"), ("C", "N"), ("C", "B"), ("B", "C"),
             ("B", "N"), ("N", "B"), ("N", "C"), ("N", "P"), ("N", "L"),
             ("N", "T"), ("T", "N"), ("T", "L"), ("L", "T"), ("L", "N"),
             ("L", "P"), ("P", "L"), ("P", "N"), ("P", "C"), ("P", "S"),
             ("S", "P")]

    # not allowed constraints:
    def conflict(val_a, val_b, var_a, var_b):
        if val_a == val_b:
            return False
        return True

    for pair in edges:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], conflict, "Time conflict"))
    return CSP(constraints, variables)
示例#23
0
def bt_search(algo, csp, variableHeuristic, allSolutions, trace):
    '''Main interface routine for calling different forms of backtracking search
       algorithm is one of ['BT', 'FC', 'GAC']
       csp is a CSP object specifying the csp problem to solve
       variableHeuristic is one of ['random', 'fixed', 'mrv']
       allSolutions True or False. True means we want to find all solutions.
       trace True of False. True means turn on tracing of the algorithm

       bt_search returns a list of solutions. Each solution is itself a list
       of pairs (var, value). Where var is a Variable object, and value is
       a value from its domain.
    '''
    varHeuristics = ['random', 'fixed', 'mrv']
    algorithms = ['BT', 'FC', 'GAC']

    #statistics
    bt_search.nodesExplored = 0

    if variableHeuristic not in varHeuristics:
        print(
            "Error. Unknown variable heursitics {}. Must be one of {}.".format(
                variableHeuristic, varHeuristics))
    if algo not in algorithms:
        print("Error. Unknown algorithm heursitics {}. Must be one of {}.".
              format(algo, algorithms))

    uv = UnassignedVars(variableHeuristic, csp)
    Variable.clearUndoDict()
    for v in csp.variables():
        v.reset()
    if algo == 'BT':
        solutions = BT(uv, csp, allSolutions, trace)
    elif algo == 'FC':
        for cnstr in csp.constraints():
            if cnstr.arity() == 1:
                FCCheck(cnstr, None,
                        None)  #FC with unary constraints at the root
        solutions = FC(uv, csp, allSolutions, trace)
    elif algo == 'GAC':
        GacEnforce(csp.constraints(), csp, None, None)  #GAC at the root
        solutions = GAC(uv, csp, allSolutions, trace)

    return solutions, bt_search.nodesExplored
示例#24
0
def FC(unAssignedVars, csp, allSolutions, trace):
    '''Forward checking search.
       unAssignedVars is the current set of
       unassigned variables.  csp is the csp
       problem, allSolutions is True if you want all solutionsl trace
       if you want some tracing of variable assignments tried and
       constraints failed.

       RETURNS LIST OF ALL SOLUTIONS FOUND.

       Finding allSolutions is handled just as it was in BT.  Except
       that when we are not looking for all solutions and we stop
       early because one of the recursive calls found a solution we
       must make sure that we restore all pruned values before
       returning.
    '''
    #your implementation for Question 2 goes in this function body.
    #you must not change the function parameters.
    #Implementing handling of the trace parameter is optional
    #but it can be useful for debugging

    if unAssignedVars.empty():
        return [[(v, v.getValue()) for v in csp.variables()]]
    sol_a = []
    v = unAssignedVars.extract()
    bt_search.nodesExplored += 1
    for val in v.curDomain():
        v.setValue(val)
        DWO = False
        for c in csp.constraintsOf(v):
            if c.numUnassigned() == 1:
                if FCCheck(c, v, val) == 'DWO':
                    DWO = True
                    break
        if not DWO:
            sol_a += FC(unAssignedVars, csp, allSolutions, trace)
            if not allSolutions and len(sol_a):
                Variable.restoreValues(v, val)
                break
        Variable.restoreValues(v, val)
    v.unAssign()
    unAssignedVars.insert(v)
    return sol_a
示例#25
0
def my_csp_problem_2():
    # Defined in notebook

    constraints = []

    variables = []
    colors = ['R', 'O', 'Y', 'G', 'B']
    variables.append(Variable("1", colors.copy()))
    variables.append(Variable("2", colors.copy()))
    variables.append(Variable("3", colors.copy()))
    variables.append(Variable("4", colors.copy()))
    variables.append(Variable("5", colors.copy()))
    variables.append(Variable("6", colors.copy()))
    variables.append(Variable("7", colors.copy()))
    variables.append(Variable("8", colors.copy()))
    variables.append(Variable("9", colors.copy()))
    variables.append(Variable("10", colors.copy()))

    # these are all variable pairing of adjacent slots
    adjacent_pairs = [("1", "2"), ("1", "10"), ("10", "9"), ("10", "1")]

    for i in range(1, 9):
        adjacent_pairs.append(
            (variables[i].get_name(), variables[i - 1].get_name()))
        adjacent_pairs.append(
            (variables[i].get_name(), variables[i + 1].get_name()))

    # No same neighbor colors
    def base_rule(val_a, val_b, name_a, name_b):
        if val_a == val_b:
            return False
        return True

    for pair in adjacent_pairs:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], base_rule,
                             "No same color neighbors"))

    return CSP(constraints, variables)
示例#26
0
def schedules_csp(sp):
    '''
    sp.courses = courses
    sp.classes = classes
    sp.buildings = buildings
    sp.num_time_slots = num_time_slots
    sp._connected_buildings = dict()
    sp.min_rest_frequency = min_rest_frequency
    '''

    "Define the domain and variables"
    classDom = []  # class in form of 'CSC108-BA-1-LEC-01'
    courses_sessions = []
    for class_info in sp.classes:
        classDom.append(class_info)
        courses_session = class_info.split('-')[0] + class_info.split('-')[3]
        if courses_session not in courses_sessions:
            courses_sessions.append(courses_session)

    "Add a number of none classes to ones that have classes"
    num_noclass = sp.num_time_slots - len(courses_sessions)
    for i in range(num_noclass):
        classDom.append(NOCLASS + '-' + str(i))

    timeVars = []
    for i in range(sp.num_time_slots):
        timeVars.append(Variable('Time-{}'.format(i + 1), classDom))

    "Construct the constraints"
    cons = []

    con = AllDiffConstraint("Alldiff", timeVars)
    cons.append(con)

    for slot in range(sp.num_time_slots - sp.min_rest_frequency):
        con = NoclassConstraint(
            "C(Time{} to Time{})".format(slot + 1,
                                         slot + sp.min_rest_frequency + 1),
            timeVars[slot + 1:slot + sp.min_rest_frequency + 1], 1,
            sp.min_rest_frequency)
        cons.append(con)

    timeslot_pairs = combinations(list(range(sp.num_time_slots)), 2)
    for (slot1, slot2) in timeslot_pairs:
        con = BinaryClassConstraint("C(Time{},Time{})".format(slot1, slot2),
                                    [timeVars[slot1], timeVars[slot2]], sp)
        cons.append(con)

    csp = CSP("{}-ClassScheduling".format(sp.num_time_slots), timeVars, cons)
    return csp
示例#27
0
def planeCSP(planes_problem):
    """My code start"""
    p, f, mp, mf = planes_problem.planes[:], planes_problem.flights[:], \
                   planes_problem.maintenance_flights[:], planes_problem.min_maintenance_frequency
    var_array = [[
        Variable("{},{}".format(p[i], j), [0] + planes_problem._can_fly[p[i]])
        for j in range(len(planes_problem._can_fly[p[i]]))
    ] for i in range(len(p))]
    valid_connect = [[0, 0]] + [
        list(pair) for pair in planes_problem.can_follow[:]
    ] + [[fl, 0] for fl in f]
    vars = [var for row in var_array for var in row]
    constraint_list = [NValuesConstraint("[{}] maintenance".format(var_array[i]),var_array[i][j:j + mf], [0] + mp, 1, mf)
                         for i in range(len(var_array)) for j in range(len(var_array[i]) - mf + 1)] + \
                      [TableConstraint("[{}] follow".format(var_array[i]),[var_array[i][j], var_array[i][j + 1]], valid_connect)
                       for i in range(len(var_array)) for j in range(len(var_array[i]) - 1)] +\
                      [TableConstraint("[{}] initial".format(var_array[i][0]),[var_array[i][0]],[[0]] +
                                       [[start] for start in planes_problem._flights_at_start[p[i]]])
                       for i in range(len(var_array))] \
                      + [allOnce("all once", vars, f)]
    return CSP("planeSchedule", vars, constraint_list)
示例#28
0
def ta_scheduling_csp_problem():
    constraints = []

    variables = []
    # order of the variables here is the order given in the problem
    # the domains are those pre-reduced in part A.
    # constraints
    variables.append(Variable("C", ["Mark", "Rob", "Sam"]))
    # optimal search
    variables.append(Variable("O", ["Mark", "Mike", "Sam"]))
    # games
    variables.append(Variable("G", ["Mark"]))
    # rules
    variables.append(Variable("R", ["Mark", "Mike", "Sam"]))
    # id-trees
    variables.append(Variable("I", ["Mark", "Rob", "Sam"]))
    # neural nets
    variables.append(Variable("N", ["Mike", "Sam"]))
    # svms
    variables.append(Variable("S", ["Rob"]))
    # boosting
    variables.append(Variable("B", ["Mike"]))

    # these are all variable pairing of adjacent seats
    edges = [("C", "R"), ("B", "I"), ("B", "S"), ("S", "O"), ("S", "G"),
             ("S", "R"), ("S", "N"), ("N", "G")]

    # not allowed constraints:
    def conflict(val_a, val_b, var_a, var_b):
        if val_a == val_b:
            return False
        return True

    for pair in edges:
        constraints.append(
            BinaryConstraint(pair[0], pair[1], conflict,
                             "TA(subject_a) != TA(subject_b) constraint"))
    return CSP(constraints, variables)
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]
def question_1():
    print_title(0)
    tested[0] = True
    ntests = 3
    fails = [False] * ntests
    #test1 constraint.check()
    q2 = Variable("Q2", [1, 2, 3, 4, 5])
    q5 = Variable("Q5", [1, 2, 3, 4, 5])
    c = QueensTableConstraint("Q2/Q5", q2, q5, 2, 5)
    q2.setValue(2)
    for val in q5.domain():
        q5.setValue(val)
        if c.check():
            if val in [2, 5]:
                print "Queens table constraint check routine failed"
                print "Q2={}, Q5={} not detected as falsifying constraint".format(
                    q2.getValue(), q5.getValue())
                fails[0] = True
        else:
            if val in [1, 3, 4]:
                print "Queens table constraint check routine failed"
                print "Q2={}, Q5={} not detected as satisfying constraint".format(
                    q2.getValue(), q5.getValue())
                fails[0] = True
    if fails[0]:
        print "Fail Q1 test 1"
    else:
        print "Pass Q1 test 1"
    print_sep()

    #test2 constraint.hasSupport()
    q2.reset()
    q3 = Variable("Q3", [1, 2, 3, 4, 5])
    q2.pruneValue(1, None, None)
    q2.pruneValue(4, None, None)
    q2.pruneValue(5, None, None)
    c = QueensTableConstraint("Q2/Q5", q2, q3, 2, 3)
    for val in q3.domain():
        if c.hasSupport(q3, val):
            if val not in [1, 4, 5]:
                print "Queens table constraint hasSupport routine failed"
                print "Q2 current domain = {}, Q3 = {} detected to have support (doesn't)".format(
                    q2.curDomain(), val)
                fails[1] = True
        else:
            if val not in [2, 3]:
                print "Queens table constraint hasSupport routine failed"
                print "Q2 current domain = {}, Q3 = {} detected to not have support (does)".format(
                    q2.curDomain(), val)
                fails[1] = True
    if fails[1]:
        print "Fail Q1 test 2"
    else:
        print "Pass Q1 test 2"
    print_sep()

    #test3 within backtracking search
    csp = nQueens(8, True)
    solutions, num_nodes = bt_search('BT', csp, 'fixed', True, False)
    if num_nodes != 1965:
        print "Queens table constraint not working correctly. BT should explore 1965 nodes."
        print "With your implementation it explores {}".format(num_nodes)
        fails[2] = True
    if len(solutions) != 92:
        print "Queens table constraint not working correctly. BT should return 92 solutions"
        print "With your implementation it returns {}".format(len(solutions))
        fails[2] = True

    if fails[2]:
        print "Fail Q1 test 3"
    else:
        print "Pass Q1 test 3"

    if any(fails):
        grades[0] = 0
    else:
        grades[0] = outof[0]