예제 #1
0
def Theory():
  E = Encoding()
  E = onePerSquare(E)
  E = checkWin(E)
  E.add_constraint(winRow[2])

  return E
예제 #2
0
def finalEncoding():
    final = Encoding()
    # Combines all the encoding and their respective constraints
    for E in [orientation(), sizes(), allFinalPositions(), noOverlap()]:
        for constraint in E.constraints:
            final.add_constraint(constraint)
    return final
예제 #3
0
def Theory():
  E = Encoding()

  E = addConstraints(E, BK_Potential_Moves())

  E = addConstraints(E, spaceOccupied())

  E = addConstraints(E, outerBound())

  E = addConstraints(E, White_Potential_Movement([WQ_Space_Occupied,WP_Space_Occupied, WR_Space_Occupied, WB_Space_Occupied, WH_Space_Occupied, WK_Space_Occupied]))

  E = addConstraints(E, Kings_Adjacent())

  E = addConstraints(E, limitNumberPieces(BK_Space_Occupied, BK_Count, BK_Total_Count, 1, True))

  #There must be at least one black king, so that is always limited. The lines below will restrict each piece so some
  #Amount. They are useful for exploring the board in a very controlled way, so uncomment them and change them if you have an idea
  # of what you are doing.

  # E = addConstraints(E, limitNumberPieces(WQ_Space_Occupied, WQ_Count, WQ_Total_Count, 0, True)) #For Queen, 1 is min for stalemate, 2 is min for checkmate, and 43 is max for neither

  # E = addConstraints(E, limitNumberPieces(WP_Space_Occupied, WP_Count, WP_Total_Count, 0, True)) #For Pawn 3 is min for stalemate, 4 is min for checkmate, and 63 is max for neither

  # E = addConstraints(E, limitNumberPieces(WR_Space_Occupied, WR_Count, WR_Total_Count, 2, True)) #For Rook 2 is min for stalemate, 2 is min for checkmate, and 50 is max for neither

  # E = addConstraints(E, limitNumberPieces(WB_Space_Occupied, WB_Count, WB_Total_Count, 0, True)) #For Bishop 3 is min for stalemate, 3 is min for checkmate, and 57 is max for neither

  # E = addConstraints(E, limitNumberPieces(WH_Space_Occupied, WH_Count, WH_Total_Count, 0, True)) #For Knight 2 is min for stalemate, 3 is min for checkmate, and 61 is max for neither

  # E = addConstraints(E, limitNumberPieces(WK_Space_Occupied, WK_Count, WK_Total_Count, 0, True)) #For King 2 is min for stalemate, NaN is min for checkmate, and 58 is max for neither

  # Can't be in both checkmate and stalemate
  E.add_constraint(~Checkmate | ~Stalemate)

  #comment these out as needed to force the game to be stalemate, checkmate, or neither (if not using one of the exploring functions)
  #E.add_constraint(Stalemate)
  #E.add_constraint(Checkmate)
  #E.add_constraint(~Checkmate & ~Stalemate)

  # iff BK_No_Moves (ie the king has no valid moves), the game is either in checkmate or stalemate. pretty obvious
  # this will change if we add other pieces to the black side that are able to move, where we will also have to check
  # if the other peices are unable to move
  E.add_constraint(iff(BK_No_Moves, Checkmate | Stalemate))

  # if the king is in check, and doesn't have moves, then it is in checkmate. This will narrow the models down from the
  # previous constraint, which only simplified it to either checkmate or stalemate. now we know which one.
  # might be a more efficient way to do this, but this makes more sense in my head, so it's the way I'm doing it.
  E.add_constraint(iff(Check & BK_No_Moves, Checkmate))

  #Seeing if the king is in check
  allPotential = true.negate()
  for i in range(BOARD_SIZE):
    for j in range(BOARD_SIZE):
      allPotential |= (BK_Space_Occupied[i][j] & White_Potential_Moves[i][j])
  #if allPotential is FALSE, that means that the king certainly is not in check
  #if allPotential is TRUE, that means the king is in check
  E.add_constraint(iff(allPotential, Check))

  return E
예제 #4
0
def generate_path(E: Encoding, sq: tuple, visited: list):
    """Recursively generate a path from sq to the ending square."""
    i = coords.index(sq)
    x = grid_vars[i]
    y = path_vars[i]

    row = sq[0]
    col = sq[1]

    # Base case
    # If the end has been reached, add it as a constraint
    if x == end and not x in inaccessible:
        E.add_constraint(y)
        return True, y
    if visited == None:
        return True, y

    # Recursive case
    visited.append(sq)
    if not x in inaccessible:
        # Calculate each possible next square and the corresponding visited list
        left = (row-1, col)
        v_left = visited.copy().append(left)
        right = (row+1, col)
        v_right = visited.copy().append(right)
        up = (row, col-1)
        v_up = visited.copy().append(up)
        down = (row, col+1)
        v_down = visited.copy().append(down)

        # Look for a path to the end by moving in a valid direction and adding that
        # square to the path, or move back a square and look for a path to the end.
        if is_valid(left) and not left in visited and generate_path(E, left, visited)[0]:
            E.add_constraint(
                (generate_path(E, sq, v_left)[1] | y) & (y | ~y))
            return True, y

        if is_valid(right) and not right in visited and generate_path(E, right, visited)[0]:
            E.add_constraint(
                (generate_path(E, sq, v_right)[1] | y) & (y | ~y))
            return True, y

        if is_valid(up) and not up in visited and generate_path(E, up, visited)[0]:
            E.add_constraint(
                (generate_path(E, sq, v_up)[1] | y) & (y | ~y))
            return True, y

        if is_valid(down) and not down in visited and generate_path(E, down, visited)[0]:
            E.add_constraint(
                (generate_path(E, sq, v_down)[1] | y) & (y | ~y))
            return True, y

    return False, ~y
예제 #5
0
def example_theory():
    E = Encoding()
    #Making Constraints based on board condition
    board_Condition_To_Constraints(givenBoardCondition)
    E.add_constraint(a | b)
    E.add_constraint(~a | ~x)
    E.add_constraint(c | y | z)
    return E
예제 #6
0
def maxBasedOnShipPlacement():
    e = Encoding()
    """
    based on ships placement,The goal is to sink the ship (which has already been hit once) with a minimal number of misses.
    ship S is given and can only be translated in grid then know, the coordinates of one grid cell of the ship.
    in decision tree,  the set of possible positions at the root is P = S and P gets smaller at each new shot until
    it is reduced to a singleton at the leaves of the tree.
    If x is a hit, then the set of possible positions for the child becomes P ← P ∩ (S − x).
    If x is a miss, then the set of possible positions for the child becomes P ← P \ (S − x).


    Here are some examples of ways possible ship locations can be eliminated:
    A 'miss' square disqualifies a bunch of intersecting locations.
    A square where a ship has been marked 'sunk' disqualifies any other ships from crossing that square.
    A ship that's been sunk has to cross the square where it was sunk.
    Sunk ships cannot cross any square that is not a 'hit'.
    Ships that are not sunk can't be located entirely on 'hit' squares.
    If a certain spot on the board could only hold one certain ship, no other ships can cross any of those squares.
    If a 'hit' square is surrounded by misses in 3 directions, there must be a ship pointing in the fourth direction.

    optimized:
    A list of 'hit' squares is used to check the configurations against, rather than going through all 100 squares each time.
    saves the 5 ship locations for that configuration. Then, the ship location frequencies are used to calculate the squares' hit frequencies all in one go.
    If any ship's location can be deduced, it gets removed from process

    e.add_constraint()
    """
    return e
예제 #7
0
def noOverlap():
    """
    Encoding that makes sure sees that the starting positions do not overlap. However, unfortunately, the ships may still overlap for all of positions,
    with given more time to implement and compute these constraints, as an extension, to have no overlap between the ships as well as the ability to judge
    spacing may be implemented as well.
    """
    e = Encoding()
    # Following loops through all start positions to make sure that one one start position occupies a single coordinate.
    for i in range(1,size + 1):
        for j in range(1,size + 1):
            e.add_constraint((s1.startPosition[(i,j)] & ~s2.startPosition[(i,j)] & ~s3.startPosition[(i,j)])
                             | (~s1.startPosition[(i,j)] & s2.startPosition[(i,j)] & ~s3.startPosition[(i,j)])
                             | (~s1.startPosition[(i,j)] & ~s2.startPosition[(i,j)] & s3.startPosition[(i,j)])
                             | (~s1.startPosition[(i,j)] & ~s2.startPosition[(i,j)] & ~s3.startPosition[(i,j)]))

    return e
예제 #8
0
def example_theory():
    variables = createVariables(givenBoardCondition, k)

    #overall variables for overall node types and winning condition
    Wh = Var("Wh")
    Wo = Var("Wo")
    Sh = Var("Sh")
    Br = Var("Br")
    W = Var("W")

    #create variable arrays
    wood, wheat, sheep, brick = createVariableLists(variables)
    tree = buildTree(variables, createImplicationList(givenBoardCondition, k))
    rowVariables = variablesToRows(variables)

    E = Encoding()
    #Making Constraints based on board condition
    E = createBoardConstraints(givenBoardCondition, variables, E, k)
    #Adding constraint for winning condition
    E.add_constraint(W.negate() | (Wh & Wo & Sh & Br))
    #Setting W to always true so that the solver tries to find a winning model
    E.add_constraint(W)

    E = setOverallVariablesTrueOrFalse(Wh, Wo, Br, Sh, variables, wood, wheat,
                                       sheep, brick, E, S)
    E = leaf_constraints(
        findLeaves(
            tree,
            findAllParents(tree, createImplicationList(givenBoardCondition,
                                                       k))), E, variables)
    E = implementRequiredNodes(S, E, Wo, Wh, Sh, Br)
    E = rowVariablesToConstraints(rowVariables, E)
    #print(findLeaves(tree,findAllParents(tree,createImplicationList(givenBoardCondition,k))))
    print(E.constraints)
    return E
예제 #9
0
def all_paths_theory():
    """Creates a model for the grid and possible paths."""
    E = Encoding()
    E.add_constraint(assign_accessibility([x for x in grid_vars]))
    all_paths([], start_coords)
    E.add_constraint(constrain_paths([path for path in paths]))

    # Negate any path variables that are never used in a path
    for y in path_vars:
        if not y in list(set(sum(paths, []))):
            E.add_constraint(~y)

    # Return the model and the path list with duplicate squares in each path
    # filtered out
    return E, [list(set(path)) for path in paths]
예제 #10
0
def token_theory():
    S = Encoding()
    #Constraint to check if the tokens played where a success or fail
    for missions in post_models:
        for tokens in missions:
            if tokens in SpyTokensVariable:
                S.add_constraint(tokens.negate())
            else:
                S.add_constraint(tokens)
    return S
예제 #11
0
def connectFour():
  E = Encoding()
  E = validBoard(E)
  E = rowWin(E, blackRow, blackBoard)
  E = rowWin(E, redRow, redBoard)
  E = columnWin(E, blackColumn, blackBoard)
  E = columnWin(E, redColumn, redBoard)
  E = leftDiagonalWin(E, leftBlackDiagonal, blackBoard)
  E = leftDiagonalWin(E, leftRedDiagonal, redBoard)
  E = rightDiagonalWin(E, rightBlackDiagonal, blackBoard)
  E = rightDiagonalWin(E, rightRedDiagonal, redBoard)
  E = columnRules(E, blackColumn, blackRow, leftBlackDiagonal, rightBlackDiagonal)
  E = columnRules(E, redColumn, redRow, leftRedDiagonal, rightRedDiagonal)
  E = sameCount(E, blackPartialCount, blackBoard)
  E = sameCount(E, redPartialCount, redBoard)
  return E
예제 #12
0
def winCondition():
    """
    Simple encoding to see if all ship coordinates are hit
    """
    e = Encoding()
    # List to hold conjunctions
    win = []
    # Checks to see if all ship parts are hit, win_con is true if all are hit, false otherwise
    for i in range(1,size + 1):
        for j in range(1,size + 1):
            win.append((s1.position[(i,j)] & player_board.hit_board[(i,j)]))
    e.add_constraint(nnf.And(win).negate() | win_con)
    e.add_constraint(nnf.And(win) | ~win_con)
    return e
    def __init__(self, size=(5,5)):
        self.num_rows = size[0]
        self.num_cols = size[1]
        assert self.num_cols == 5 and self.num_rows == 5, "Code doesn't support sizes other than 5x5"
        # The maximum number of tents per row/column is equal to the
        # number of columns/rows in the puzzle, divided by 2 and rounded up.
        # Example:
        #                                                _ _ _ _ _
        #   # of col = 5 -> ceil(5/2) = ceil(2.5) = 3 : |T| |T| |T|
        #
        #                                             _ _ _ _ _ _           _ _ _ _ _ _
        #   # of col = 6 -> ceil(6/2) = ceil(3) = 3: |T| |T| |T| |  --or-- | |T| |T| |T|
        #
        # Doing ((n+1) // 2) is equivalent to doing ceil(n/2).
        self.max_tents_per_row = (self.num_cols + 1) // 2
        self.max_tents_per_col = (self.num_rows + 1) // 2

        self.theory = Encoding()
        self.build_propositions()
        self.build_general_constraints()
예제 #14
0
def example_theory():
    E = Encoding()

    # Final index
    E.add_constraint(iff(x_post[-1], ~x_pre[-1]))

    # Rest of the indices
    for i in range(len(x_pre)-1):
        # Set for everything to the right
        needs_to_flip = true
        for j in range(i+1, len(x_pre)):
            needs_to_flip &= x_pre[j]
        E.add_constraint(iff(x_post[i], (needs_to_flip & ~x_pre[i]) | (x_pre[i] & needs_to_flip.negate())))

    return E
예제 #15
0
def sizes():
    e = Encoding()
    # Makes sure that there is on 1 size for each ship
    for ship in fleet:
        e.add_constraint((ship.size2 & ~ship.size3 & ~ship.size4)
                         | (~ship.size2 & ship.size3 & ~ship.size4)
                         | (~ship.size2 & ~ship.size3 & ship.size4))
    # Makes sure that for each size, only one ship may have it (i.e only 1 ship may be of size 2, one ship of size 3, and one ship of size 4)
    e.add_constraint(((s1.size2 & ~s2.size2 & ~s3.size2)
                      | (~s1.size2 & s2.size2 & ~s3.size2)
                      | (~s1.size2 & ~s2.size2 & s3.size2))
                     & ((s1.size3 & ~s2.size3 & ~s3.size3)
                        | (~s1.size3 & s2.size3 & ~s3.size3)
                        | (~s1.size3 & ~s2.size3 & s3.size3))
                     & ((s1.size4 & ~s2.size4 & ~s3.size4)
                        | (~s1.size4 & s2.size4 & ~s3.size4)
                        | (~s1.size4 & ~s2.size4 & s3.size4)))
    return e
예제 #16
0
def example_theory():
    E = Encoding()
    
    # if a11 is scheduled before a21 then it cant be the case
    #that a21 is scheduled before a11, not possible
    E.add_constraint(~q12 | ~q21)
    E.add_constraint(~q13 | ~q31)
    E.add_constraint(~q14 | ~q41)
    E.add_constraint(~q23 | ~q32)
    E.add_constraint(~q24 | ~q42)
    E.add_constraint(~q34 | ~q43)

    #same for resource 2
    E.add_constraint(~p12 | ~p21)
    E.add_constraint(~p13 | ~p31)
    E.add_constraint(~p14 | ~p41)
    E.add_constraint(~p23 | ~p32)
    E.add_constraint(~p24 | ~p42)
    E.add_constraint(~p34 | ~p43)

    #and implication constraints for the resources
    E.add_constraint( (~a11 | ~a21) | (q12 | q21) )
    E.add_constraint( (~a11 | ~b11) | (q13 | q31) )
    E.add_constraint( (~a11 | ~b21) | (q14 | q41) )
    E.add_constraint( (~a21 | ~b11) | (q23 | q32) )
    E.add_constraint( (~a21 | ~b21) | (q24 | q42) )
    E.add_constraint( (~b11 | ~b21) | (q34 | q43) )

    E.add_constraint( (~a12  | ~a22) | (p12 | p21) )
    E.add_constraint( (~a12  | ~b12) | (p13 | p31) )
    E.add_constraint( (~a12  | ~b22) | (p14 | p41) )
    E.add_constraint( (~a22  | ~b12) | (p23 | p32) )
    E.add_constraint( (~a22  | ~b22) | (p24 | p42) )
    E.add_constraint( (~b12  | ~b22) | (p34 | p43) )


    return E
예제 #17
0
def example_theory():
    E = Encoding()

    set_up_props()

    #loop through each stop and set appropriate constraints
    #note: we don't necessarily set it that proposition to true unless we know 100%
    #it is true because it could still be set false by other constraints.
    #(just because something is false in one scenario, doesn't mean it's true in the
    # opposite).
    for entry in stop_info:
        location = entry["location"]
        #if a given mode of transportation is not feasible for that trip, set the
        #constraint that it can't be true
        if "drive" not in entry["travel"].keys():
            E.add_constraint(~drive[location])
        #if it would take more than 3 hours to drive to/from this trip/the trip is international, tolls
        #will be there
        else:
            if (entry["travel"]["drive"] > 3):
                E.add_constraint(toll[location])
                #cannot cross a toll if you have no toll money
                E.add_constraint(((toll[location] & ~toll_money)
                                  & drive[location]).negate())
        if "transit" not in entry["travel"].keys():
            E.add_constraint(~transit[location])
        if "plane" not in entry["travel"].keys():
            E.add_constraint(~plane[location])
        E.add_constraint(~international | toll[location])
        #at least one weather mode has to be true
        E.add_constraint(sunny[location] | rainy[location]
                         | snowstorm[location])

        #only one form of weather can be true at once
        E.add_constraint(~sunny[location]
                         | (~snowstorm[location] & ~rainy[location]))
        E.add_constraint(~rainy[location]
                         | (~snowstorm[location] & ~sunny[location]))
        E.add_constraint(~snowstorm[location]
                         | (~sunny[location] & ~rainy[location]))

        #good weather and holiday implies tickets will be sold out and you have to drive
        E.add_constraint((sunny[location] & holiday).negate()
                         | (transit[location] | plane[location]).negate())

        #rainy or snowstorm increases the likelihood of accidents
        E.add_constraint((rainy[location] | snowstorm[location]).negate()
                         | accident[location])
        #snowstorm implies that transit and planes will be shut down
        E.add_constraint(~snowstorm[location]
                         | (transit[location] | plane[location]).negate())
        #driving constraints (come into play if they are driving):
        #bad weather and roadwork implies unfeasible trip
        E.add_constraint(
            (((rainy[location] | snowstorm[location]) & roadwork[location])
             & drive[location]).negate())
        #bad weather and holiday implies unfeasible trip
        E.add_constraint((((rainy[location] | snowstorm[location]) & holiday)
                          & drive[location]).negate())
        #roadwork and holiday implies unfeasible trip
        E.add_constraint(
            ((roadwork[location] & holiday) & drive[location]).negate())
        #roadwork and accident implies unfeasible trip
        E.add_constraint(((roadwork[location] & accident[location])
                          & drive[location]).negate())
        #holiday and accident implies unfeasible trip
        E.add_constraint(
            ((holiday & accident[location]) & drive[location]).negate())
        #you must have at least one form of travel
        E.add_constraint(plane[location] | transit[location] | drive[location])
        #only one form of travel can be true at once
        E.add_constraint(~drive[location]
                         | (~transit[location] & ~plane[location]))
        E.add_constraint(~transit[location]
                         | (~drive[location] & ~plane[location]))
        E.add_constraint(~plane[location]
                         | (~transit[location] & ~drive[location]))

        #you cannot drive anywhere if you have more than 5 people
        E.add_constraint(~more_than_five | ~drive[location])

        #you cannot take a plane if you don't have money for a ticket
        E.add_constraint(afford_plane | ~plane[location])

        #if you are taking an urgent trip, only the fastest trip (determined earlier) is possible
        if "drive" in entry["urgent"].keys():
            E.add_constraint(~urgent_trip
                             | (~transit[location] & ~plane[location]))
        elif "transit" in entry["urgent"].keys():
            E.add_constraint(~urgent_trip
                             | (~drive[location] & ~plane[location]))
        elif "plane" in entry["urgent"].keys():
            E.add_constraint(~urgent_trip
                             | (~transit[location] & ~drive[location]))

        #if you have the virus, you ain't flying nowhere
        E.add_constraint(~plane[location] | (~virus & documents))
        #if you don't have documents, you ain't flying nowhere
        E.add_constraint(documents | ~plane[location])

    #only relevant if travel is international
    #if you have tested positive for the virus/been in contact, you can't cross the border
    E.add_constraint(~international | (~virus & documents))
    #no documents means you can't cross the border
    E.add_constraint((international & documents) | ~international)

    return E
예제 #18
0
def single_path_theory():
    """Creates a model for the grid and path."""
    E = Encoding()
    E.add_constraint(assign_accessibility([x for x in grid_vars]))
    generate_path(E, (coords[start_index][0], coords[start_index][1]), [])
    return E
def example_theory(restaurant, customer):

    # Shorter variables for the objects
    r = restaurant
    c = customer

    # Defining encoding variable
    E = Encoding()

    # Add distance constraint
    E.add_constraint(distanceConstraint(r, c))
    E.add_constraint(price_constraint(r, c))

    # Add dining constraints
    if len(user.userdine_opt) == 1:
        E.add_constraint(one_dining_constraints(r, c))
    elif len(user.userdine_opt) == 2:
        E.add_constraint(two_dining_constraints(r, c))
    elif len(user.userdine_opt) == 3:
        E.add_constraint(all_dining_constraints(r, c))

    # Add Diet constraints
    if len(user.userdiet) == 1:
        if 5 in user.userdiet:
            pass
        else:
            E.add_constraint(single_diet_constraint(r, c))
    elif len(user.userdiet) == 2:
        E.add_constraint(two_diet_constraint(r, c))
    elif len(user.userdiet) == 3:
        E.add_constraint(three_diet_constraint(r, c))
    elif len(user.userdiet) == 4:
        E.add_constraint(all_diet_constraint(r, c))

    # return the Encoding variable
    return E
예제 #20
0
def example_theory():
    E = Encoding()

    E.add_constraint(T)
    E.add_constraint(~F)

    # holding is exclusive
    for j in range(num_resources):
        constraint = F
        for i in range(num_processes):
            constraint = constraint | ~h[i][j]
        print('holding is exclusive', constraint)
        E.add_constraint(constraint)

    for i in range(num_processes):
        for j in range(num_resources):
            # holding implies max
            constraint = ~h[i][j] | m[i][j]
            print('holding implies max', constraint)
            E.add_constraint(constraint)

        # hard code 2 processes and 2 resources for now:
        # These constraints ensure that the system is in a safe state
        E.add_constraint(~m[0][0] | ~h[1][0] | ~m[1][1] | ~h[0][1])
        E.add_constraint(~m[0][1] | ~h[1][1] | ~m[1][0] | ~h[0][0])

    return E
예제 #21
0
def example_theory():
    E = Encoding()

    # Final index
    E.add_constraint(iff(x_post[-1], ~x_pre[-1]))

    # Rest of the indices
    for i in range(len(x_pre)-1):
        # Set for everything to the right
        needs_to_flip = true
        for j in range(i+1, len(x_pre)):
            needs_to_flip &= x_pre[j]
        E.add_constraint(iff(x_post[i], (needs_to_flip & ~x_pre[i]) | (x_pre[i] & needs_to_flip.negate())))

    # Final partial counts should be equal to the full count
    for c in range(BITS+1):
        E.add_constraint(iff(count_post[c], partial_count_vars[BITS-1][c]))
        print(partial_counts[BITS-1][c])
    # You can't have more true bits than you've already seen
    for i in range(BITS):
        for c in range(i+2, BITS+1):
            E.add_constraint(~partial_count_vars[i][c])

    # First index: only 0 or 1 could possibly be true
    E.add_constraint(iff(partial_count_vars[0][0], ~x_post[0]))
    E.add_constraint(iff(partial_count_vars[0][1], x_post[0]))

    # General pattern: look at the smaller sequence of bits to decide the current one
    for i in range(1, BITS):
        E.add_constraint(iff(partial_count_vars[i][0], partial_count_vars[i-1][0] & ~x_post[i]))
        for c in range(1,i+2):
            increased = partial_count_vars[i-1][c-1] & x_post[i]
            stay_same = partial_count_vars[i-1][c] & ~x_post[i]
            E.add_constraint(iff(partial_count_vars[i][c], increased | stay_same))
            # print("Define the constraint for index %d = %d" % (i,c))

    return E
예제 #22
0
def example_theory():
    E = Encoding()

    # Let's make sure that T is always true and F is always false :)
    E.add_constraint(T)
    E.add_constraint(~F)

    # Let's add constraints so that each process needs to run at least once:
    for process in range(num_processes):
        # We can build up a formula which is each variable that indicates that the process is runs at some time on some processor, all "or"ed together
        occurs = F
        for time in range(num_time_slots):
            for processor in range(num_processors):
                occurs = occurs | s.get(time, processor, process)
        # and now add that constraint
        E.add_constraint(occurs)

    # Let's add constraints so that each process cannot be run more than once:
    for process in range(num_processes):
        # We can keep track of each of the slots that a process could run on.
        # (A slot is time slot on a specific processor.)
        process_slots = []
        for time in range(num_time_slots):
            for processor in range(num_processors):
                process_slots.append(s.get(time, processor, process))
        # okay, we shoul have them all now...

        # So, for each slot the process could run in...
        for process_slot in process_slots:
            # We will build up a formula from each of the other process slots
            other_process_slots = filter(lambda x: x is not process_slot,
                                         process_slots)
            no_others = T
            for p in other_process_slots:
                no_others = no_others & ~p
            # The formula says that if the process is running in this slot, it is not running in any of the others.
            E.add_constraint(~process_slot | no_others)

    # Let's add constraints so that no 2 processes can run at the same time on the same processor:
    for p1 in range(num_processes):
        for p2 in range(p1 + 1, num_processes):
            for time in range(num_time_slots):
                for processor in range(num_processors):
                    E.add_constraint(~s.get(time, processor, p1)
                                     | ~s.get(time, processor, p2))

    # Let's add constratints so that no 2 processes can use the same resource at the same time:
    for p1 in range(num_processes):
        for p2 in range(p1 + 1, num_processes):
            for resource in range(num_resources):
                for time in range(num_time_slots):
                    # Build a formula that is true iff p1 is using the resource at this time:
                    p1_running_at_this_time = F
                    for processor in range(num_processors):
                        p1_running_at_this_time = p1_running_at_this_time | s.get(
                            time, processor, p1)
                    p1_using_resource = r.get(
                        p1, resource) & p1_running_at_this_time
                    # Build a formula that is true iff p2 is using the resource at this time:
                    p2_running_at_this_time = F
                    for processor in range(num_processors):
                        p2_running_at_this_time = p2_running_at_this_time | s.get(
                            time, processor, p2)
                    p2_using_resource = r.get(
                        p2, resource) & p2_running_at_this_time

                    E.add_constraint(~p1_using_resource | ~p2_using_resource)

    # Finally, we can add constraints to tell the system which processes use which resources:
    # For example:
    # process 0 uses resource:
    E.add_constraint(r.get(0, 0))
    # process 1 also uses resource
    E.add_constraint(r.get(1, 0))
    # process 2 also uses resource
    E.add_constraint(r.get(2, 0))
    # (So, processes 0, 1, and 2, cannot be run concurrently)
    return E
예제 #23
0
def example_theory():
    E = Encoding()

    ###########################################################################
    ### First determine the the valid starting points for each pilot.
    # Based on the number of pilots, which airports should be filled?
    # There are r objects to fill from find_n_maxes()
    fill = find_n_maxes(Pilot.count, demand[:])

    # There are (n+r-1)C(r-1) ways to assign n objects to m things where order matters and repetition is not allowed.
    # Equivalent to n!/(n-r)!*r!
    starting = pilot_permute(pilots, fill)

    starting_constraint = ''
    for scenario in starting:
        first = True

        for i in range(len(scenario)):
            if scenario[i] == None:
                # This was a padded object, do nothing
                continue

            # Find out which pilot is chosen for a given airport
            for p in range(len(pilots)):
                if pilots[p].pilot_id == scenario[i].pilot_id:
                    if first:
                        starting_constraint += '(pilots[%d].location[0][%d]' % (
                            p, fill[i])
                        first = False
                    else:
                        starting_constraint += ' & pilots[%d].location[0][%d]' % (
                            p, fill[i])

        starting_constraint += ') | '

    starting_constraint = starting_constraint[:-3]
    E.add_constraint(eval(starting_constraint))

    # Extra Information: Uncomment to display all the permutations fo starting positions for the pilots.
    """
    print(starting_constraint)
    count = 0
    my = pilot_permute(pilots, fill)
    for i in range(len(my)):
        for j in range(len(my[i])):
            count += 1
    print("There are: " + str(count) + " different initial positions for the pilots")
    """
    ###########################################################################

    ###########################################################################
    ### Every pilot can only make one flight per timestep.
    for pilot in range(Pilot.count):
        only_one_airport = '('
        for timestep in range(N_TIMESTEPS):
            for airport in range(N_AIRPORTS):
                # Current airport in loop is true.
                only_one_airport += '(pilots[%d].location[%d][%d] &' % (
                    pilot, timestep, airport)

                # All airports below airport are false, count up
                for count_up in range(0, airport):
                    only_one_airport += ' ~pilots[%d].location[%d][%d] &' % (
                        pilot, timestep, count_up)

                # All airports above airport are false, count up
                for count_up in range(airport + 1, N_AIRPORTS):
                    only_one_airport += ' ~pilots[%d].location[%d][%d] &' % (
                        pilot, timestep, count_up)

                # Remove the last & from the string
                only_one_airport = only_one_airport[:-2]
                only_one_airport += ') | '

            # Remove the last | from the string, use &'s to seperate timesteps
            only_one_airport = only_one_airport[:-3]
            only_one_airport += ') & ('

        # Remove the last & from the string.
        only_one_airport = only_one_airport[:-4]

        # Evaluate the string to turn it into NNF type
        E.add_constraint(eval(only_one_airport))
    ###########################################################################

    ###########################################################################
    ### Any two pilots cannot be at the same airport at the same timestep.
    for pilot in range(Pilot.count):
        for timestep in range(N_TIMESTEPS):
            for airport in range(N_AIRPORTS):
                only_one_pilot = ''

                # Current pilot is true
                only_one_pilot += '(pilots[%d].location[%d][%d] &' % (
                    pilot, timestep, airport)

                # Negate all the pilots below
                for count_up in range(0, pilot):
                    only_one_pilot += ' ~pilots[%d].location[%d][%d] &' % (
                        count_up, timestep, airport)

                # Negate all the pilots above
                for count_up in range(pilot + 1, Pilot.count):
                    only_one_pilot += ' ~pilots[%d].location[%d][%d] &' % (
                        count_up, timestep, airport)

                # Remove the last & and space
                only_one_pilot = only_one_pilot[:-2]
                only_one_pilot += ') | '

            # Remove the last | from the string.
            only_one_pilot = only_one_pilot[:-3]
            only_one_pilot += ' & '

        # Remove the last | from the string.
        only_one_pilot = only_one_pilot[:-3]
        only_one_pilot += ' & '

    only_one_pilot = only_one_pilot[:-3]

    E.add_constraint(eval(only_one_pilot))
    ###########################################################################

    ###########################################################################
    ### Each pilot cannot remain at the same airport in two adjacent timesteps.
    for pilot in range(Pilot.count):
        for timestep in range(N_TIMESTEPS - 1):
            for airport in range(N_AIRPORTS):
                # Pilot cannot be at the same location at an incremented timestep.
                E.add_constraint(
                    ~pilots[pilot].location[timestep][airport]
                    | ~pilots[pilot].location[timestep + 1][airport])
    ###########################################################################

    ###########################################################################
    ### Pilot should only fly to an airport that has demand.
    for pilot in range(Pilot.count):
        for timestep in range(N_TIMESTEPS - 1):
            for airport in range(N_AIRPORTS):
                # For all pilots and every timestep and every airport,
                # if the airport has 0 demand, the pilot should not fly there.
                if demand[airport] == 0:
                    # UNLESS - Every other airport also has 0 demand.
                    for inner_airport in range(N_AIRPORTS):
                        if demand[inner_airport] != 0:
                            E.add_constraint(
                                ~pilots[pilot].location[timestep][airport])
                            break
    ###########################################################################

    return E
예제 #24
0
def allFinalPositions():
    """
    This encoding see where to place the remaining ship parts given the propositions size, orientation, and starting position
    There are two "boards" per ship. One to place the remaining squares horizontally, and one for vertical placement. With
    these boards completed, the final board can be obtained by "superimposing" all the ships' boards on one another, or in the
    case of propositional logic, this would be equivalent to checking the disjunction between all boards for a specific position
    to see if any of them are true; if so, there is a ship piece of some ship in that position and the "final board" position will
    return true as well.
    """
    e = Encoding()
    # List for placement conjunctions
    placements = []
    # Utilizes the startingSquare helper function in order to limit the starting location to one square
    e.add_constraint(nnf.Or(startingSquareHelper(s1)))
    # Iterates through the three ships checking to see if a square would have a ship part on it
    for ship in fleet:
        # As the minimum to starting square may be is at the first row or column, there cannot be any intermediate spaces in the first row or column for vInterPosition and hInterPosition respectively.
        for i in range(1, size + 1):
            e.add_constraint(~ship.vInterPosition[(i,1)])
            e.add_constraint(~ship.hInterPosition[(1,i)])
        # Used to check if the second column has a ship part that belongs to a ship of size 2
        for i in range(2, 3):
            for j in range(1, size + 1):
                e.add_constraint(((ship.horizontal & ship.startPosition[(i-1,j)]) | ~ship.hInterPosition[(i,j)]))
                e.add_constraint(((ship.horizontal & ship.startPosition[(i - 1,j)]).negate() | ship.hInterPosition[(i,j)]))
        # Used to check if the third column has a ship part that belongs to a ship of size 2 or size 3
        for i in range(3, 4):
            for j in range(1, size + 1):
                e.add_constraint((((ship.horizontal & ship.startPosition[(i - 2,j)] & ~ship.size2) | (ship.horizontal & ship.startPosition[(i - 1,j)])) | ~ship.hInterPosition[(i,j)]))
                e.add_constraint((((ship.horizontal & ship.startPosition[(i - 2,j)] & ~ship.size2) | (ship.horizontal & ship.startPosition[(i - 1,j)])).negate() | ship.hInterPosition[(i,j)]))
        # Used to check if the third column has a ship part that belongs to a ship of size 2 or size 3 or size 4
        for i in range(4, size + 1):
            for j in range(1, size + 1):
                e.add_constraint((((ship.horizontal & ship.startPosition[(i-3,j)] & ship.size4) | (ship.horizontal & ship.startPosition[(i-2,j)] & ~ship.size2) | (ship.horizontal &
                ship.startPosition[(i-1, j)])) | ~ship.hInterPosition[(i, j)]))
                e.add_constraint((((ship.horizontal & ship.startPosition[(i - 3,j)] & ship.size4) | (ship.horizontal & ship.startPosition[(i - 2,j)] & ~ship.size2) | (ship.horizontal &
                ship.startPosition[(i - 1,j)])).negate() | ship.hInterPosition[(i,j)]))
        # Used to check if the second row has a ship part that belongs to a ship of size 2
        for i in range(1, size + 1):
            for j in range(2, 3):
                e.add_constraint(((ship.vertical & ship.startPosition[(i,j-1)]) | ~ship.vInterPosition[(i,j)]))
                e.add_constraint(((ship.vertical & ship.startPosition[(i,j - 1)]).negate() | ship.vInterPosition[(i,j)]))
        # Used to check if the second row has a ship part that belongs to a ship of size 2 or size 3
        for i in range(1, size + 1):
            for j in range(3, 4):
                e.add_constraint((((ship.vertical & ship.startPosition[(i,j-2)] & ~ship.size2) | (ship.vertical & ship.startPosition[(i,j-1)])) | ~ship.vInterPosition[(i,j)]))
                e.add_constraint((((ship.vertical & ship.startPosition[(i,j - 2)] & ~ship.size2) | (ship.vertical & ship.startPosition[(i,j - 1)])).negate() | ship.vInterPosition[(i,j)]))
        # Used to check if the second row has a ship part that belongs to a ship of size 2 or size 3 or size 4
        for i in range(1, size + 1):
            for j in range(4, size + 1):
                e.add_constraint((((ship.vertical & ship.startPosition[(i,j-3)] & ship.size4) | (ship.vertical & ship.startPosition[(i,j-2)] & ~ship.size2) | (ship.vertical &
                ship.startPosition[(i, j-1)])) | ~ship.vInterPosition[(i, j)]))
                e.add_constraint((((ship.vertical & ship.startPosition[(i,j - 3)] & ship.size4) | (ship.vertical & ship.startPosition[(i,j - 2)] & ~ship.size2) | (ship.vertical &
                ship.startPosition[(i,j - 1)])).negate() | ship.vInterPosition[(i,j)]))
        # Generation of the final board
        for i in range(1,size + 1):
            for j in range(1,size + 1):
                # Appends the Var of all boards for this specific position
                for ship in fleet:
                    placements.append(ship.startPosition[(i,j)])
                    placements.append(ship.hInterPosition[(i,j)])
                    placements.append(ship.vInterPosition[(i,j)])
                # If none of the Var for the specific position on the board is true, then the position of the final board will be false.
                e.add_constraint((nnf.Or(placements)) | ~s1.position[(i,j)])
                placements = []
        # Loops through the same
        for i in range(1,size + 1):
            for j in range(1,size + 1):
                for ship in fleet:
                    placements.append(ship.startPosition[(i,j)])
                    placements.append(ship.hInterPosition[(i,j)])
                    placements.append(ship.vInterPosition[(i,j)])
                # If any one of the Var for the specific position on the board is true, then the position of the final board will be true as well.
                e.add_constraint((nnf.Or(placements)).negate() | s1.position[(i,j)])
                placements = []


    return e
def example_theory():
    E = Encoding()

    #if two critical sections make use of the same constraints then they need to be scheduled

    E.add_constraint((~a11 | ~a21) | q12)  #(a11 & a21) >> q12
    #if p1_crit_sect1 uses r1 (a11) and p1_crit_sect2 uses r1 (a21)
    #then they must be scheduled (q12)
    #however, this leaves room for uncertainty if both a11 and a21 are false due to laws of implication
    #that is, if a11 and a21 are false then q12 could be true, which is against our model, therefore have to add
    #another implication constraint the other way around, essentially a biimplications
    #(a11 &* a21) <> q12
    E.add_constraint(~q12 | (a11 & a21))  #q12 >> (a11 & a21)

    E.add_constraint((~a11 | ~b11) | q13)  #(a11 & b11) >> q13
    E.add_constraint(~q13 | (a11 & b11))  #q13 >> (a11 & b11)

    E.add_constraint((~a11 | ~b21) | q14)  #(a11 & b21) >> q14
    E.add_constraint(~q14 | (a11 & b21))  #q14 >> (a11 & b21)

    E.add_constraint((~a21 | ~b11) | q23)  #(a21 & b11) >> q23
    E.add_constraint(~q23 | (a21 & b11))  #q23 >> (a21 & b11)

    E.add_constraint((~a21 | ~b21) | q24)  #(a21 & b21) >> q24
    E.add_constraint(~q24 | (a21 & b21))  #q24 >> (a21 & b21)

    E.add_constraint((~b11 | ~b21) | q34)  #(b11 & b21) >> q34
    E.add_constraint(~q34 | (b11 & b21))  #q34 >> (b11 & b21)

    #-------------------------RESOURCE 2 CONSTRAINTS------------------------------

    E.add_constraint((~a12 | ~a22) | p12)  #(a12 & a22) >> p12
    #if p1_crit_sect1 uses r2 (a12) and p1_crit_sect2 uses r2 (a22)
    #then they must be scheduled (p12)
    E.add_constraint(~p12 | (a12 & a22))  #p12 >> (a12 & a22)

    E.add_constraint((~a12 | ~b12) | p13)  #(a12 & b12) >> p13
    E.add_constraint(~p13 | (a12 & b12))  #p13 >> (a12 & b12)

    E.add_constraint((~a12 | ~b22) | p14)  #(a12 & b22) >> p14
    E.add_constraint(~p14 | (a12 & b22))  #p14 >> (a12 & b22)

    E.add_constraint((~a22 | ~b12) | p23)  #(a22 & b12) >> p23
    E.add_constraint(~p23 | (a22 & b12))  #p23 >> (a22 & b12)

    E.add_constraint((~a22 | ~b22) | p24)  #(a22 & b22) >> p24
    E.add_constraint(~p24 | (a22 & b22))  #p24 >> (a22 & b22)

    E.add_constraint((~b12 | ~b22) | p34)  #(b12 & b22) >> p34
    E.add_constraint(~p34 | (b12 & b22))  #p34 >> (b12 & b22)

    return E
예제 #26
0
파일: run.py 프로젝트: 18ML51/CISC204
def example_theory():
    E = Encoding()
    E.add_constraint(a | b)
    E.add_constraint(~a | ~x)
    E.add_constraint(c | y | z)
    return E
예제 #27
0
def game_theory():
    E = Encoding()
    #Constraint is to check if a mission is won or lost based upon if NO spy tokens are played in the current mission or the current mission's vote tracker didn't reach z5
    for x in range(len(post_models)):
        if post_models[x]:
            if len(post_models[x]) == 2:
                if FinalVotes[x] == VoteTracking[4]:
                    E.add_constraint(MissionVariables[x].negate())
                elif ((post_models[x][0] not in SpyTokensVariable)
                      and (post_models[x][1] not in SpyTokensVariable)):
                    E.add_constraint(MissionVariables[x])
                else:
                    E.add_constraint(MissionVariables[x].negate())
            elif len(post_models[x]) == 3:
                if FinalVotes[x] == VoteTracking[4]:
                    E.add_constraint(MissionVariables[x].negate())
                elif ((post_models[x][0] not in SpyTokensVariable)
                      and (post_models[x][1] not in SpyTokensVariable)
                      and (post_models[x][2] not in SpyTokensVariable)):
                    E.add_constraint(MissionVariables[x])
                else:
                    E.add_constraint(MissionVariables[x].negate())
            elif len(post_models[x]) == 4:
                if FinalVotes[x] == VoteTracking[4]:
                    E.add_constraint(MissionVariables[x].negate())
                elif ((post_models[x][0] not in SpyTokensVariable)
                      and (post_models[x][1] not in SpyTokensVariable)
                      and (post_models[x][2] not in SpyTokensVariable)
                      and (post_models[x][3] not in SpyTokensVariable)):
                    E.add_constraint(MissionVariables[x])
                else:
                    E.add_constraint(MissionVariables[x].negate())

    return E
예제 #28
0
def orientation():
    """
    This encoding constrains the possible starting positions and orientations based on the sizes as this makes sure that
    that they are valid, constraining the ships to the board for once the rest of the pieces are "placed". The orientations
    are horizontal or vertical. The remainder of the ship parts will be places to the right if the orientation is horizontal
    and downwards if the orientation is vertical.
    """
    e = Encoding()
    for ship in fleet:
        # Each ship is assigned a random orientation
        e.add_constraint((ship.vertical & ~ship.horizontal) | (ship.horizontal & ~ship.vertical))
        # Loop constrains the ship to not be vertical when starting position is against the bottom side of the board
        for i in range(1,size + 1):
            for j in range(size,size + 1):
                e.add_constraint(ship.horizontal | ~ship.startPosition[(i,j)])
        # Loop constrains the ship to not be horizontal when starting position is against the right side of the board
        for i in range(size,size + 1):
            for j in range(1,size + 1):
                e.add_constraint(ship.vertical | ~ship.startPosition[(i,j)])
        # Loop constrains ship to not be vertical when starting position of size 3 or 4 is at the second column from the bottom
        for i in range(1,size + 1):
            for j in range(size - 1,size):
                e.add_constraint((~ship.horizontal & (ship.size3 | ship.size4)).negate() | ~ship.startPosition[(i,j)])
        # Loop constrains ship to not be horizontal when starting position of size 3 or 4 is at the second column from the right
        for i in range(size - 1,size):
            for j in range(1,size + 1):
                e.add_constraint((~ship.vertical & (ship.size3 | ship.size4)).negate() | ~ship.startPosition[(i,j)])
        # Loop constrains ship to not be vertical when starting position of size 4 is at the third column from the bottom
        for i in range(1,size + 1):
            for j in range(size - 2,size - 1):
                e.add_constraint((~ship.horizontal & ship.size4).negate() | ~ship.startPosition[(i,j)])
        # Loop constrains ship to not be horizontal when starting position of size 4 is at the third column from the right
        for i in range(size - 2,size - 1):
            for j in range(1,size + 1):
                e.add_constraint((~ship.vertical & ship.size4).negate() | ~ship.startPosition[(i,j)])
        # Adds the constraint to only select one coordinate from the valid positions to be the starting position
        e.add_constraint(nnf.Or(startingSquareHelper(ship)))
    return e
예제 #29
0
def test_kenken(N):
    #scope of project constrained to 3x3 and 4x4 boards
    if ((N > 4) | (N < 3)):
        return -1

    E = Encoding()
    '''Create row and column propositions'''
    row = []
    col = []
    for i in range(N):
        row.append(Var(f'row_{i}'))
        col.append(Var(f'col_{i}'))
    '''Create board squares'''
    board = []
    for i in range(N):
        for j in range(N):
            # Create boolean corresponding to if the value at the square is valid or not
            charOffset = chr(ord('a') + i)
            is_valid = Var(f'{charOffset}{j}')
            values = []
            for x in range(1, N + 1):
                charOffset = chr(ord('a') + i)
                # Create booleans in each list corresponding to if the square is 1,2,3
                values.append(Var(f'{charOffset}{j}_{x}'))
            board.append(Square(is_valid, values))

    try:
        '''
        Create Regions, o is a list of Regions
        Uncomment the desired configuration, DO NOT uncomment more than one configuration or else it will just solve the most recent one.
        Board configurations are also listed along with the number of solutions they have and their classified difficulty.
        If you are switching between a 3x3 and 4x4 configuration, set the kenken_size variable to the proper dimensions at the top of the main function.
        '''
        """
        # 3x3 ADDITION ONLY BOARD (1 solution - easy)
        o = []
        o.append(Region([board[0],board[3]],3,'+'))
        o.append(Region([board[1],board[4]],5,'+'))
        o.append(Region([board[2]],1,'!'))
        o.append(Region([board[5],board[8]],5,'+'))
        o.append(Region([board[6],board[7]],4,'+'))
        """

        # 3x3 BOARD WITH MULTIPLICATION, ADDITION, SUBTRACTION (2 solutions - easy)
        o = []
        o.append(Region([board[0]], 3, '!'))
        o.append(Region([board[1], board[2]], 1, '-'))
        o.append(Region([board[3], board[4]], 3, '+'))
        o.append(Region([board[5]], 3, '!'))
        o.append(Region([board[6], board[7], board[8]], 6, '*'))
        """
        # 3x3 BOARD WITH DIVISION, ADDITION, SUBTRACTION (2 solutions - medium)
        o = []
        o.append(Region([board[0],board[3]],3,'/'))
        o.append(Region([board[1],board[2],board[4],board[5]],8,'+'))
        o.append(Region([board[6],board[7]],1,'-'))
        o.append(Region([board[8]],1,'!'))
        """
        """
        # 4x4 BOARD WITH ADDITION, SUBTRACTION, DIVISION, MULTIPLICATION (3 solutions - very hard)
        o = []
        o.append(Region([board[0],board[1],board[4],board[8]],12,'*'))
        o.append(Region([board[2],board[3]],2,'/'))
        o.append(Region([board[5],board[9]],1,'-'))
        o.append(Region([board[6],board[7],board[10]],8,'+'))
        o.append(Region([board[11],board[14],board[15]],6,'+'))
        o.append(Region([board[12],board[13]],2,'-'))
        """
        """
        # 4x4 BOARD WITH ADDITION, MULTIPLICATION, SUBTRACTION (3 solutions - easy/medium)
        o = []
        o.append(Region([board[0],board[1],board[4]],8,'*'))
        o.append(Region([board[2],board[3],board[7]],8,'+'))
        o.append(Region([board[5],board[6]],6,'*'))
        o.append(Region([board[8],board[12]],4,'+'))
        o.append(Region([board[9],board[10],board[13]],9,'+'))
        o.append(Region([board[14]],1,'!'))
        o.append(Region([board[11],board[15]],2,'-'))
        """

    except:
        print(
            "Incorrect specified board size or invalid board configuration! Please the kenken_size paramter at the top of the main function."
        )
        quit()

    print("Board layout defined:")
    ''' Constraint: Numbers on board must be from 1-N, sets the constraint for the proposition is_valid in each Square'''
    for i in range(len(board)):
        # At each square, access the list for squares_values
        # True if the square value is equal to the specified val
        sq = board[i]

        if N == 3:
            is_one = (sq.value[0] & ~sq.value[1] & ~sq.value[2])
            is_two = (~sq.value[0] & sq.value[1] & ~sq.value[2])
            is_three = (~sq.value[0] & ~sq.value[1] & sq.value[2])
            E.add_constraint(iff(sq.is_valid, (is_one | is_two | is_three)))
        elif N == 4:
            is_one = (sq.value[0] & ~sq.value[1] & ~sq.value[2] & ~sq.value[3])
            is_two = (~sq.value[0] & sq.value[1] & ~sq.value[2] & ~sq.value[3])
            is_three = (~sq.value[0] & ~sq.value[1] & sq.value[2]
                        & ~sq.value[3])
            is_four = (~sq.value[0] & ~sq.value[1] & ~sq.value[2]
                       & sq.value[3])
            E.add_constraint(
                iff(sq.is_valid, (is_one | is_two | is_three | is_four)))

        # Square is valid iff the square holds one of these values
        E.add_constraint(sq.is_valid)
    print("Valid square constraints added.")
    ''' Constraint: Row must contain EVERY number from 1-N, with no repeats'''
    for i in range(0, len(board), N):
        if N == 3:
            one_exists = (
                (board[i].value[0] & ~board[i].value[1] & ~board[i].value[2]) |
                (board[i + 1].value[0] & ~board[i + 1].value[1]
                 & ~board[i + 1].value[2]) |
                (board[i + 2].value[0] & ~board[i + 2].value[1]
                 & ~board[i + 2].value[2]))
            two_exists = (
                (~board[i].value[0] & board[i].value[1] & ~board[i].value[2]) |
                (~board[i + 1].value[0] & board[i + 1].value[1]
                 & ~board[i + 1].value[2]) |
                (~board[i + 2].value[0] & board[i + 2].value[1]
                 & ~board[i + 2].value[2]))
            three_exists = (
                (~board[i].value[0] & ~board[i].value[1] & board[i].value[2]) |
                (~board[i + 1].value[0] & ~board[i + 1].value[1]
                 & board[i + 1].value[2]) |
                (~board[i + 2].value[0] & ~board[i + 2].value[1]
                 & board[i + 2].value[2]))

            E.add_constraint(
                iff(row[int(i / N)], one_exists & two_exists & three_exists))

        elif N == 4:
            one_exists = ((board[i].value[0] & ~board[i].value[1]
                           & ~board[i].value[2] & ~board[i].value[3]) |
                          (board[i + 1].value[0] & ~board[i + 1].value[1]
                           & ~board[i + 1].value[2] & ~board[i + 1].value[3]) |
                          (board[i + 2].value[0] & ~board[i + 2].value[1]
                           & ~board[i + 2].value[2] & ~board[i + 2].value[3]) |
                          (board[i + 3].value[0] & ~board[i + 3].value[1]
                           & ~board[i + 3].value[2] & ~board[i + 3].value[3]))

            two_exists = ((~board[i].value[0] & board[i].value[1]
                           & ~board[i].value[2] & ~board[i].value[3]) |
                          (~board[i + 1].value[0] & board[i + 1].value[1]
                           & ~board[i + 1].value[2] & ~board[i + 1].value[3]) |
                          (~board[i + 2].value[0] & board[i + 2].value[1]
                           & ~board[i + 2].value[2] & ~board[i + 2].value[3]) |
                          (~board[i + 3].value[0] & board[i + 3].value[1]
                           & ~board[i + 3].value[2] & ~board[i + 3].value[3]))

            three_exists = ((~board[i].value[0] & ~board[i].value[1]
                             & board[i].value[2] & ~board[i].value[3]) |
                            (~board[i + 1].value[0] & ~board[i + 1].value[1]
                             & board[i + 1].value[2] & ~board[i + 1].value[3])
                            |
                            (~board[i + 2].value[0] & ~board[i + 2].value[1]
                             & board[i + 2].value[2] & ~board[i + 2].value[3])
                            |
                            (~board[i + 3].value[0] & ~board[i + 3].value[1]
                             & board[i + 3].value[2] & ~board[i + 3].value[3]))

            four_exists = ((~board[i].value[0] & ~board[i].value[1]
                            & ~board[i].value[2] & board[i].value[3]) |
                           (~board[i + 1].value[0] & ~board[i + 1].value[1]
                            & ~board[i + 1].value[2] & board[i + 1].value[3]) |
                           (~board[i + 2].value[0] & ~board[i + 2].value[1]
                            & ~board[i + 2].value[2] & board[i + 2].value[3]) |
                           (~board[i + 3].value[0] & ~board[i + 3].value[1]
                            & ~board[i + 3].value[2] & board[i + 3].value[3]))

            E.add_constraint(
                iff(row[int(i / N)],
                    one_exists & two_exists & three_exists & four_exists))

        E.add_constraint(row[int(i / N)])
    print("Row constraints added.")
    ''' Constraint: Col must contain EVERY number from 1-N, with no repeats'''
    for i in range(N):
        if N == 3:
            one_exists = (
                (board[i].value[0] & ~board[i].value[1] & ~board[i].value[2]) |
                (board[i + N].value[0] & ~board[i + N].value[1]
                 & ~board[i + N].value[2]) |
                (board[i + N * 2].value[0] & ~board[i + N * 2].value[1]
                 & ~board[i + N * 2].value[2]))
            two_exists = (
                (~board[i].value[0] & board[i].value[1] & ~board[i].value[2]) |
                (~board[i + N].value[0] & board[i + N].value[1]
                 & ~board[i + N].value[2]) |
                (~board[i + N * 2].value[0] & board[i + N * 2].value[1]
                 & ~board[i + N * 2].value[2]))
            three_exists = (
                (~board[i].value[0] & ~board[i].value[1] & board[i].value[2]) |
                (~board[i + N].value[0] & ~board[i + N].value[1]
                 & board[i + N].value[2]) |
                (~board[i + N * 2].value[0] & ~board[i + N * 2].value[1]
                 & board[i + N * 2].value[2]))

            E.add_constraint(
                iff(col[i], one_exists & two_exists & three_exists))

        elif N == 4:
            one_exists = (
                (board[i].value[0] & ~board[i].value[1] & ~board[i].value[2]
                 & ~board[i].value[3]) |
                (board[i + N].value[0] & ~board[i + N].value[1]
                 & ~board[i + N].value[2] & ~board[i + N].value[3]) |
                (board[i + N * 2].value[0] & ~board[i + N * 2].value[1]
                 & ~board[i + N * 2].value[2] & ~board[i + N * 2].value[3]) |
                (board[i + N * 3].value[0] & ~board[i + N * 3].value[1]
                 & ~board[i + N * 3].value[2] & ~board[i + N * 3].value[3]))

            two_exists = (
                (~board[i].value[0] & board[i].value[1] & ~board[i].value[2]
                 & ~board[i].value[3]) |
                (~board[i + N].value[0] & board[i + N].value[1]
                 & ~board[i + N].value[2] & ~board[i + N].value[3]) |
                (~board[i + N * 2].value[0] & board[i + N * 2].value[1]
                 & ~board[i + N * 2].value[2] & ~board[i + N * 2].value[3]) |
                (~board[i + N * 3].value[0] & board[i + N * 3].value[1]
                 & ~board[i + N * 3].value[2] & ~board[i + N * 3].value[3]))

            three_exists = (
                (~board[i].value[0] & ~board[i].value[1] & board[i].value[2]
                 & ~board[i].value[3]) |
                (~board[i + N].value[0] & ~board[i + N].value[1]
                 & board[i + N].value[2] & ~board[i + N].value[3]) |
                (~board[i + N * 2].value[0] & ~board[i + N * 2].value[1]
                 & board[i + N * 2].value[2] & ~board[i + N * 2].value[3]) |
                (~board[i + N * 3].value[0] & ~board[i + N * 3].value[1]
                 & board[i + N * 3].value[2] & ~board[i + N * 3].value[3]))

            four_exists = (
                (~board[i].value[0] & ~board[i].value[1] & ~board[i].value[2]
                 & board[i].value[3]) |
                (~board[i + N].value[0] & ~board[i + N].value[1]
                 & ~board[i + N].value[2] & board[i + N].value[3]) |
                (~board[i + N * 2].value[0] & ~board[i + N * 2].value[1]
                 & ~board[i + N * 2].value[2] & board[i + N * 2].value[3]) |
                (~board[i + N * 3].value[0] & ~board[i + N * 3].value[1]
                 & ~board[i + N * 3].value[2] & board[i + N * 3].value[3]))

            E.add_constraint(
                iff(col[i],
                    one_exists & two_exists & three_exists & four_exists))

        E.add_constraint(col[i])
    print("Column constraints added.")
    ''' Constraint: Each region must have squares that provide an arithmetic result as defined by the region's result and operator,
        accessed as region.rslt and region.operator'''
    operationList = []
    for idx, region in enumerate(o):
        varList = []
        sq = region.get_members()
        if region.get_len() == 1:
            varList.append(Var(f'{sq[0].is_valid}_{region.rslt}'))

        elif region.get_len() == 2:
            for i in range(1, N + 1):
                for j in range(1, N + 1):
                    if region.operator != "/":
                        condition = f'{i}{region.operator}{j}'
                        if (
                                abs(eval(condition)) == region.rslt
                        ):  # this line supports subtraction, multiplication, addition
                            # AND the two squares that make up the sum/difference/product
                            varList.append(
                                Var(f'{sq[0].is_valid}_{i}')
                                & Var(f'{sq[1].is_valid}_{j}'))

                    elif region.operator == "/":
                        # support for division is different: order matters
                        if i % j == 0:
                            # j divides i
                            condition = f'{i}{region.operator}{j}'
                            if (abs(eval(condition)) == region.rslt):
                                # AND the two squares that make up the sum/difference/product
                                varList.append(
                                    Var(f'{sq[0].is_valid}_{i}')
                                    & Var(f'{sq[1].is_valid}_{j}'))

                        elif j % i == 0:
                            # i divides j
                            condition = f'{j}{region.operator}{i}'
                            if (abs(eval(condition)) == region.rslt):
                                # AND the two squares that make up the sum/difference/product
                                varList.append(
                                    Var(f'{sq[0].is_valid}_{i}')
                                    & Var(f'{sq[1].is_valid}_{j}'))

        elif region.get_len() == 3:
            for i in range(1, N + 1):
                for j in range(1, N + 1):
                    for k in range(1, N + 1):
                        if region.operator != "/":
                            condition = f'{i}{region.operator}{j}{region.operator}{k}'
                            if (
                                    abs(eval(condition)) == region.rslt
                            ):  # this line supports subtraction, multiplication, addition (no division requried for regions of 3+ squares)
                                # AND the two squares that make up the sum/difference/product

                                varList.append(
                                    Var(f'{sq[0].is_valid}_{i}')
                                    & Var(f'{sq[1].is_valid}_{j}')
                                    & Var(f'{sq[2].is_valid}_{k}'))
                                #print(len(varList))

        elif region.get_len() == 4:
            for i in range(1, N + 1):
                for j in range(1, N + 1):
                    for k in range(1, N + 1):
                        for l in range(1, N + 1):
                            if region.operator != "/":
                                condition = f'{i}{region.operator}{j}{region.operator}{k}{region.operator}{l}'
                                if (
                                        abs(eval(condition)) == region.rslt
                                ):  # this line supports subtraction, multiplication, addition (no division requried for regions of 3+ squares)
                                    # AND the two squares that make up the sum/difference/product
                                    varList.append(
                                        Var(f'{sq[0].is_valid}_{i}')
                                        & Var(f'{sq[1].is_valid}_{j}')
                                        & Var(f'{sq[2].is_valid}_{k}')
                                        & Var(f'{sq[3].is_valid}_{l}'))

        operationList.append(Var(f'group{idx}result_{region.rslt}'))

        # Add constraint of the group's result
        E.add_constraint(operationList[idx])

        if len(
                varList
        ) == 1:  # Only one possible option for the region's configuration
            previous = varList[0]
        else:
            # Create combined XOR statement (for all the possible square combinations)
            for jdx in range(1, len(varList)):
                previous = xor(varList[jdx - 1], varList[jdx])
                varList[jdx] = previous

        # Add constraint that the group's result implies ONE OF the combinations of squares
        E.add_constraint(implies(operationList[idx], previous))

    print("Arithmetic constraints added. Finished definition.")

    return E
예제 #30
0
import pickle

# CISC 204 Libraries
from lib204 import Encoding

if __name__ == "__main__":
    # This is a default team. your_team is strong, while oppo_team is weak.
    # Acts as a test of model
    T = Encoding()
    team_vars = []
    pokemon_team = []

    with open('classes/theory.pyclass', 'rb') as input:
        T = pickle.load(input)

    with open('classes/team.pyclass', 'rb') as input:
        team_vars = pickle.load(input)

    with open('classes/pokemons.pyclass', 'rb') as input:
        pokemon_team = pickle.load(input)

    print("Possibility of Winning?: %s" % T.is_satisfiable())

    chance = (T.count_solutions(team_vars) / T.count_solutions())
    print("Estimated chance of winning:  %.2f" % chance)
    if chance < 0.6:
        print("You will probably lose.")
    elif chance < 0.7:
        print("It can go either way.")
    else:
        print("You will probably win!")