Пример #1
0
 def DefaultGame(self):
     self.height = 7
     self.width = 7
     self.game = PegGameInstance(height=7, width=7)
     self.game.boards = [
         PegBoardState(height=7, width=7, time=t) for t in range(31)
     ]
     self.literalAllocator = LiteralAllocator()
     # Start state
     for i in range(7):
         for j in range(7):
             if i in range(2, 5) or j in range(2, 5):
                 if i == j and i == 3:
                     self.game[0][i][j].state = PegState.DEAD
                 else:
                     self.game[0][i][j].state = PegState.ALIVE
     # Intermediate states
     for t in range(1, 30):
         for i in range(7):
             for j in range(7):
                 if i in range(2, 5) or j in range(2, 5):
                     self.game[t][i][j].state = PegState.DONTCARE
     # Final state
     for i in range(7):
         for j in range(7):
             if i in range(2, 5) or j in range(2, 5):
                 if i == j and i == 3:
                     self.game[30][i][j].state = PegState.ALIVE
                 else:
                     self.game[30][i][j].state = PegState.DEAD
Пример #2
0
 def __init__(self, n, symbols):
     self.n = n
     self.symbols = symbols
     self.board = None
     self.la = LiteralAllocator()
     self.literal2board = dict()
     self.board2literal = dict()
     self.cnf = CNF()
     self.InitSquare()
     self.Assert()
Пример #3
0
 def Test1D(self):
     self.height = 1
     self.width = 7
     numGen = 3
     self.game = PegGameInstance(height=self.height, width=self.width)
     self.game.boards = [
         PegBoardState(height=self.height, width=self.width, time=t)
         for t in range(numGen)
     ]
     self.literalAllocator = LiteralAllocator()
     # Start state
     for i in range(self.width):
         if i != 3:
             self.game[0][0][i].state = PegState.ALIVE
         else:
             self.game[0][0][i].state = PegState.DEAD
     # Intermediate states
     for t in range(1, numGen):
         for i in range(self.width):
             self.game[t][0][i].state = PegState.DONTCARE
Пример #4
0
 def BasicTest(self):
     self.height = 5
     self.width = 5
     numGen = 3
     self.game = PegGameInstance(height=self.height, width=self.width)
     self.game.boards = [
         PegBoardState(height=self.height, width=self.width, time=t)
         for t in range(numGen)
     ]
     self.literalAllocator = LiteralAllocator()
     # Start state
     for i in range(self.height):
         for j in range(self.width):
             if i == j and i == 2:
                 self.game[0][i][j].state = PegState.DEAD
             else:
                 self.game[0][i][j].state = PegState.ALIVE
     # Intermediate states
     for t in range(1, numGen):
         for i in range(self.height):
             for j in range(self.width):
                 self.game[t][i][j].state = PegState.DONTCARE
Пример #5
0
class EulerSquare:
    def __init__(self, n, symbols):
        self.n = n
        self.symbols = symbols
        self.board = None
        self.la = LiteralAllocator()
        self.literal2board = dict()
        self.board2literal = dict()
        self.cnf = CNF()
        self.InitSquare()
        self.Assert()

    def InitSquare(self):
        self.board = []
        for row in range(self.n):
            cols = []
            for col in range(self.n):
                symbols = []
                for symbol in range(self.symbols):
                    symbolVals = []
                    for symbolVal in range(self.n):
                        literal = self.la.getLiteral()
                        self.board2literal[(row, col, symbol,
                                            symbolVal)] = literal
                        symbolVals.append(literal)
                    symbols.append(symbolVals)
                cols.append(symbols)
            self.board.append(cols)

        #                                     number of possible symbol values    | how many symbol types |  columns           |            rows
        # self.board = [[[[self.la.getLiteral() for _ in range(self.n)] for _ in range(self.symbols)] for _ in range(self.n)] for _ in range(self.n)]
        # pp.pprint(self.board)

    def Assert(self):
        # Asserts that for each symbol, it doesn't share a row or column with the same symbol
        for symbol in range(self.symbols):
            for row in range(self.n):
                for col in range(self.n):
                    for i in range(self.n):
                        for j in range(self.n):
                            if (row == i) ^ (col == j):
                                for symbolVal in range(self.n):
                                    self.cnf.addClause([
                                        -self.board[row][col][symbol]
                                        [symbolVal],
                                        -self.board[i][j][symbol][symbolVal]
                                    ])

        # Assert that each symbol has a single value assigned
        for symbol in range(self.symbols):
            for row in range(self.n):
                for col in range(self.n):
                    self.cnf.mergeWithRaw(
                        SATUtils.exactlyOne(self.board[row][col][symbol],
                                            forceInefficient=True)[0])

        # For each pair of symbols, they never appear twice
        for symbolA, symbolB in itertools.combinations(range(self.symbols), 2):
            for symbolValA in range(self.n):
                for symbolValB in range(self.n):
                    # get pairs of literals and AND them together. That value must be
                    # true exactly 1 time for each pairing of symbol types.
                    impliedLiterals = []
                    for row in range(self.n):
                        for col in range(self.n):
                            clauses, C = Tseytin.AND(
                                self.board[row][col][symbolA][symbolValA],
                                self.board[row][col][symbolB][symbolValB],
                                self.la.getLiteral())
                            impliedLiterals.append(C)
                            self.cnf.mergeWithRaw(clauses)
                    self.cnf.mergeWithRaw(
                        SATUtils.atLeast(impliedLiterals, 1)[0])

        # pp.pprint(sorted(self.cnf.rawCNF(), key=lambda x: [abs(_) for _ in x]))

    def Solve(self):
        finalVals = pycosat.solve(self.cnf.rawCNF())
        if finalVals == 'UNSAT':
            print(finalVals)
            return
        rows = []
        for row in range(self.n):
            cols = []
            for col in range(self.n):
                symbols = []
                for symbol in range(self.symbols):
                    for symbolVal in range(self.n):
                        val = self.board2literal[(row, col, symbol, symbolVal)]
                        if val in finalVals:
                            symbols.append(symbolVal)
                            break
                cols.append(symbols)
            rows.append(cols)
        pp.pprint(rows)
Пример #6
0
 def __init__(self, height=0, width=0):
     self.height = height
     self.width = width
     self.game = None
     self.literalAllocator = LiteralAllocator()
     self.cnf = CNF()
Пример #7
0
class PegSolitaire:
    def __init__(self, height=0, width=0):
        self.height = height
        self.width = width
        self.game = None
        self.literalAllocator = LiteralAllocator()
        self.cnf = CNF()

    def Test1D(self):
        self.height = 1
        self.width = 7
        numGen = 3
        self.game = PegGameInstance(height=self.height, width=self.width)
        self.game.boards = [
            PegBoardState(height=self.height, width=self.width, time=t)
            for t in range(numGen)
        ]
        self.literalAllocator = LiteralAllocator()
        # Start state
        for i in range(self.width):
            if i != 3:
                self.game[0][0][i].state = PegState.ALIVE
            else:
                self.game[0][0][i].state = PegState.DEAD
        # Intermediate states
        for t in range(1, numGen):
            for i in range(self.width):
                self.game[t][0][i].state = PegState.DONTCARE

    def DefaultGame(self):
        self.height = 7
        self.width = 7
        self.game = PegGameInstance(height=7, width=7)
        self.game.boards = [
            PegBoardState(height=7, width=7, time=t) for t in range(31)
        ]
        self.literalAllocator = LiteralAllocator()
        # Start state
        for i in range(7):
            for j in range(7):
                if i in range(2, 5) or j in range(2, 5):
                    if i == j and i == 3:
                        self.game[0][i][j].state = PegState.DEAD
                    else:
                        self.game[0][i][j].state = PegState.ALIVE
        # Intermediate states
        for t in range(1, 30):
            for i in range(7):
                for j in range(7):
                    if i in range(2, 5) or j in range(2, 5):
                        self.game[t][i][j].state = PegState.DONTCARE
        # Final state
        for i in range(7):
            for j in range(7):
                if i in range(2, 5) or j in range(2, 5):
                    if i == j and i == 3:
                        self.game[30][i][j].state = PegState.ALIVE
                    else:
                        self.game[30][i][j].state = PegState.DEAD

    def BasicTest(self):
        self.height = 5
        self.width = 5
        numGen = 3
        self.game = PegGameInstance(height=self.height, width=self.width)
        self.game.boards = [
            PegBoardState(height=self.height, width=self.width, time=t)
            for t in range(numGen)
        ]
        self.literalAllocator = LiteralAllocator()
        # Start state
        for i in range(self.height):
            for j in range(self.width):
                if i == j and i == 2:
                    self.game[0][i][j].state = PegState.DEAD
                else:
                    self.game[0][i][j].state = PegState.ALIVE
        # Intermediate states
        for t in range(1, numGen):
            for i in range(self.height):
                for j in range(self.width):
                    self.game[t][i][j].state = PegState.DONTCARE

    def assignLiterals(self):
        for t in range(len(self.game.boards)):
            for i in range(self.height):
                for j in range(self.width):
                    if self.game[t][i][j].state != PegState.DNE:
                        self.game[t][i][
                            j].variable = self.literalAllocator.getLiteral()
        print(self.game)

    def FillInSequence(self):
        sequence = self.game.boards
        if len(sequence) <= 1:
            raise Exception('A sequence needs at least 2 elements!')
        for board in sequence:
            assert isinstance(board, PegBoardState)
            assert board.height == sequence[0].height and board.width == sequence[0].width, \
                'Cannot compare boards with different dimensions.'
        self.assignLiterals()
        height = sequence[0].height
        width = sequence[0].width

        self.assertTransitions()
        self.assertOneMovePerTurn()
        self.assertFixedStates()

        for solution in pycosat.itersolve(self.cnf.rawCNF()):
            updatedSequence = []
            for tiling in sequence:
                newTilingA = PegBoardState(tiling.height, tiling.width,
                                           tiling.time)

                for row in range(tiling.height):
                    for col in range(tiling.width):
                        if tiling[row][col].state != PegState.DNE:
                            if tiling[row][col].variable in solution:
                                if tiling[row][
                                        col].state == PegState.ALIVE or tiling[
                                            row][
                                                col].state == PegState.DONTCARE:
                                    # This means that we either forced the cell to be alive or we derived a possible value
                                    newTilingA[row][col].state = PegState.ALIVE
                                else:
                                    # raise Exception("Computed state is incompatible with original state")
                                    pass
                            elif -tiling[row][col].variable in solution:
                                if tiling[row][
                                        col].state == PegState.DEAD or tiling[
                                            row][
                                                col].state == PegState.DONTCARE:
                                    # This means that we either forced the cell to be dead or we derived a possible value
                                    newTilingA[row][col].state = PegState.DEAD
                                    pass
                                else:
                                    # raise Exception("Computed state is incompatible with original state")
                                    pass
                            else:
                                raise Exception(
                                    "Input wasn't even in the solution! Something is clearly wrong here."
                                )
                updatedSequence.append(newTilingA)
            gameSolution = PegGameInstance()
            gameSolution.SetFrames(updatedSequence)
            print(gameSolution)
            break

    def assertTransitions(self):
        self.assertAllTriplets()

    def assertFixedStates(self):
        fixedVals = []
        for t in range(1):  #len(self.game.boards)):
            for row in range(self.height):
                for col in range(self.width):
                    if self.game.boards[t][row][col].state == PegState.ALIVE:
                        fixedVals.append(
                            self.game.boards[t][row][col].variable)
                    if self.game.boards[t][row][col].state == PegState.DEAD:
                        fixedVals.append(
                            -self.game.boards[t][row][col].variable)
        self.cnf.mergeWithRaw([[x] for x in fixedVals])

    def assertTriplet(self, jumper, skipped, endpoint, time):
        a = self.game.boards[time][jumper[0]][jumper[1]].variable
        b = self.game.boards[time][skipped[0]][skipped[1]].variable
        c = self.game.boards[time][endpoint[0]][endpoint[1]].variable
        x = self.game.boards[time + 1][jumper[0]][jumper[1]].variable
        y = self.game.boards[time + 1][skipped[0]][skipped[1]].variable
        z = self.game.boards[time + 1][endpoint[0]][endpoint[1]].variable
        clauses = [[-a, -b, c, -x, y], [-a, -b, c, -x, -z], [-a, -b, c, x, -y],
                   [-a, -b, c, -y, -z], [-a, -b, c, x, z], [-a, -b, c, y, z]]
        self.cnf.mergeWithRaw(clauses)

    def assertAllTriplets(self):
        for t in range(len(self.game.boards) - 1):
            for row in range(self.height):
                for col in range(self.width):
                    for direction in [[-1, 0], [1, 0], [0, -1], [0, 1]]:
                        xDir = direction[0]
                        yDir = direction[1]
                        jumper = [row, col]
                        skipped = [row + xDir, col + yDir]
                        endpoint = [row + 2 * xDir, col + 2 * yDir]
                        if self.isValidTriple(jumper, skipped, endpoint):
                            self.assertTriplet(jumper, skipped, endpoint, t)

    def assertOneMovePerTurn(self):
        initPop = 0
        for row in range(self.height):
            for col in range(self.width):
                if self.game.boards[0][row][col].state == PegState.ALIVE:
                    initPop += 1

        for t in range(len(self.game.boards)):
            boardLiterals = []
            for row in range(self.height):
                for col in range(self.width):
                    if self.game.boards[t][row][col].state != PegState.DNE:
                        boardLiterals.append(
                            self.game.boards[t][row][col].variable)
            # Try swapping for SATUtils.atLeast to check for faster speeds
            newClauses, highestLiteral = SATUtils.exactlyR(
                boardLiterals,
                initPop - t,
                startLiteral=self.literalAllocator.getCurrLiteral())
            if highestLiteral >= self.literalAllocator.getCurrLiteral():
                self.literalAllocator.getLiterals(
                    highestLiteral - self.literalAllocator.getCurrLiteral() +
                    1)
            self.cnf.mergeWithRaw(newClauses)

    def isValidTriple(self, jumper, skipped, endpoint):
        if endpoint[0] not in range(self.width) or endpoint[1] not in range(
                self.height):
            return False
        if skipped[0] not in range(self.width) or skipped[1] not in range(
                self.height):
            return False
        if self.game.boards[0][jumper[0]][jumper[1]].state == PegState.DNE:
            return False
        if self.game.boards[0][skipped[0]][skipped[1]].state == PegState.DNE:
            return False
        if self.game.boards[0][endpoint[0]][endpoint[1]].state == PegState.DNE:
            return False
        return True