Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math, random, pickle, numpy as np
- class boardFunctions:
- def __init__(self, boardState):
- # Current state of the board
- self.boardState = boardState
- # Return 1/-1 if player has won, return 0 if draw, return 2 if game ongoing
- def checkWin(self, board) :
- winIndices = [[0,3,6], [1,4,7], [2,5,8], [0,1,2], [3,4,5], [6,7,8], [0,4,8], [2,4,6]]
- for element in winIndices :
- winCheckSum = (board[element[0]] + board[element[1]] + board[element[2]]) / 3
- if abs(winCheckSum) == 1 :
- return winCheckSum
- if 0 in board :
- return 2
- else :
- return 0
- # Prints a certain boardstate
- def print(self, board) :
- boardDisp = [' '] * 9
- for i in range(len(board)):
- if board[i] == 1 :
- boardDisp[i] = 'X'
- elif board[i] == -1 :
- boardDisp[i] = 'O'
- i += 1
- print('-----')
- print(boardDisp[0], boardDisp[1], boardDisp[2])
- print(boardDisp[3], boardDisp[4], boardDisp[5])
- print(boardDisp[6], boardDisp[7], boardDisp[8])
- print('-----')
- # Helper func for imputting indices as a row and column
- def rowColumn(self, row, column) :
- i = (3 * row) + column
- return i
- # Prompts the user to imput a move and updates the specified board
- def playerInput(self, board, player) :
- column = int(input('Column? '))
- row = int(input('Row? '))
- space = self.rowColumn(row, column)
- if board[space] == 0 :
- board[space] = player
- else:
- if self.checkWin(board) == 0 :
- print('Square already filled. Try again')
- self.playerInput(player)
- else :
- return
- # Plays a move on the specified board in a random empty square
- def randomMove(self, board, player) :
- board[random.choice([idx for idx, val in enumerate(board) if 0 == val])] = player
- bfunc = boardFunctions([0] * 9)
- class minimax :
- def __init__(self) :
- self.minimaxSeed = 4
- def moveSearch(self, board, player, depth) :
- winState = bfunc.checkWin(bfunc.boardState)
- if abs(winState) == 1 :
- if depth == 0 :
- return
- else :
- return winState * player * -1
- elif winState == 0:
- if depth == 0 :
- return
- else :
- return 0
- elif winState == 2 :
- moveList = []
- i = 0
- while i < 9 :
- if board[i] == 0 :
- moveList.append(i)
- i += 1
- j = 0
- valueList = [0] * len(moveList)
- while j < len(moveList) :
- board[moveList[j]] = player
- valueList[j] = self.moveSearch(board, -1 * player, depth + 1)
- board[moveList[j]] = 0
- j += 1
- if depth == 0 :
- maxValue = max(valueList)
- maxIndices = [idx for idx, val in enumerate(valueList) if maxValue == val]
- boardStateInt = sum([(2**j)*abs(bfunc.boardState[j]) + 1 + self.minimaxSeed for j in range(len(valueList))])
- boardStateSeed = int(((100*abs(math.cos(boardStateInt)))%1)*100) % len(maxIndices)
- return moveList[maxIndices[boardStateSeed]]
- else :
- return max(valueList) * -1
- def minimaxMove(self, board, player) :
- board[self.moveSearch(board, player, 0)] = player
- def minimaxGame(self, startingPlayer) :
- i = 0
- while bfunc.checkWin(bfunc.boardState) == 2 :
- self.minimaxMove(bfunc.boardState, startingPlayer * ((-1) ** i))
- bfunc.print(bfunc.boardState)
- i += 1
- mmx = minimax()
- class pickler:
- def __init__(self, path) :
- self.picklePath = path
- def encode(self, data, fileName):
- with open(self.picklePath + '/' + fileName + '.pickle', 'wb') as f:
- pickle.dump(data, f)
- def decode(self, fileName) :
- with open(self.picklePath + '/' + fileName + '.pickle', 'rb') as f :
- return pickle.load(f)
- pkl = pickler('C:/Users/riley/Documents/PythonProjects/Neural/pickles/')
- class neuralNetwork:
- def __init__(self) :
- pass # eventually will put all neural network related functions inside this class
- def sigmoid(x) :
- return 1/(1 + np.exp(-x))
- def derivativeSigmoid(x) :
- return sigmoid(x) * (1 - sigmoid(x))
- def inverseSigmoid(x) :
- return np.log(x / (1 - x))
- def sigmoidArray(array) :
- arr = np.copy(array)
- arr = [[sigmoid(j) for j in i] for i in arr]
- arr = np.reshape(arr,array.shape)
- return arr
- layerSizes = [10,20,9]
- neuralPlayer = 1
- weightMatrices = pkl.decode('weights')
- biasMatrices = pkl.decode('biases')
- def neuralValuePass(board, player) :
- layers = [np.concatenate(([player], board)).reshape((layerSizes[0],1))]
- for i in range(len(weightMatrices)) :
- layers.append(sigmoidArray(np.matmul(weightMatrices[i], layers[i]) + biasMatrices[i]))
- return layers
- def neuralMoveSelect(board, player) :
- moveSelection = np.argmax(neuralValuePass(board,player)[-1])
- return moveSelection
- def neuralMove(board, player) :
- move = neuralMoveSelect(board, player)
- if board[move] == 0 :
- board[move] = player
- else :
- return
- def cost(board, player) :
- nnwValues = neuralValuePass(board, player)[-1].reshape(9)
- mmxValues = np.zeros(9)
- mmxValues[mmx.moveSearch(board, player, 0)] = 1
- costValues = [(mmxValues[i] - nnwValues[i]) ** 2 for i in range(9)]
- return sum(costValues)
- layers = [i.reshape((i.shape)[0]) for i in neuralValuePass(bfunc.boardState, 1)]
- mmxValues = np.zeros(9)
- mmxValues[mmx.moveSearch(bfunc.boardState, neuralPlayer, 0)] = 1
- def layerGradients(layers) :
- layerGradients = [0] * len(weightMatrices)
- layerGradients[-1] = [2 * (layers[-1][i] - mmxValues[i]) for i in range(len(layers[-1]))]
- layerGradients[-2] = [sum([(weightMatrices[-1][j][i]) * (derivativeSigmoid(inverseSigmoid(layers[-1][j]))) * (2 * (layers[-1][j] - mmxValues[j])) for j in range(len(layers[-1]))]) for i in range(len(layers[-2]))]
- return layerGradients
- def weightGradients(weights) :
- weightGradients = [0] * len(weights)
- weightGradients[-1] = np.copy(weights[-1])
- weightGradients[-1] = [[(layers[-2][j]) * (derivativeSigmoid(inverseSigmoid(layers[-1][i]))) * (2 * (layers[-1][i] - mmxValues[i])) for j in range(len(weightGradients[-1][i]))] for i in range(len(weightGradients[-1]))]
- weightGradients[-1] = np.reshape(weightGradients[-1],weights[-1].shape)
- weightGradients[-2] = np.copy(weights[-2])
- weightGradients[-2] = [[(layers[-3][j]) * (derivativeSigmoid(inverseSigmoid(layers[-2][i]))) * (layerGradients(layers)[-2][j]) for j in range(len(weightGradients[-2][i]))] for i in range(len(weightGradients[-2]))]
- weightGradients[-2] = np.reshape(weightGradients[-2],weights[-2].shape)
- return weightGradients
- def biasGradients(biases) :
- biasGradients = [0] * len(biases)
- biasGradients[-1] = np.copy(biases[-1])
- biasGradients[-1] = [[(1) * (derivativeSigmoid(inverseSigmoid(layers[-1][i]))) * (2 * (layers[-1][i] - mmxValues[i])) for j in range(len(biasGradients[-1][i]))] for i in range(len(biasGradients[-1]))]
- biasGradients[-1] = np.reshape(biasGradients[-1],biases[-1].shape)
- biasGradients[-2] = np.copy(biases[-2])
- biasGradients[-2] = [[(1) * (derivativeSigmoid(inverseSigmoid(layers[-2][i]))) * (layerGradients(layers)[-2][j]) for j in range(len(biasGradients[-2][i]))] for i in range(len(biasGradients[-2]))]
- biasGradients[-2] = np.reshape(biasGradients[-2],biases[-2].shape)
- return biasGradients
- layerGradients(layers)
- weightGradients(weightMatrices)
- biasGradients(biasMatrices)
- '''
- To-Do List:
- - Weight/bias shape check
- - Gradient Descent
- - Training
- - Major clean up/refactor
- - GUI???'''
Advertisement
Add Comment
Please, Sign In to add comment