def check_terminal(board: np.ndarray, _last_action: Optional[PlayerAction] = None) -> bool: ''' check if the board is a "terminal" board: a win or a draw''' board1 = board.copy() board2 = board.copy() board1[board1 == PLAYER1] = NO_PLAYER board1[board1 == PLAYER2] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board1, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == CONNECT_N): return True board2[board2 == PLAYER2] = NO_PLAYER board2[board2 == PLAYER1] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board2, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == CONNECT_N): return True if np.count_nonzero(board) == board.shape[0] * board.shape[1]: return True return False
def position_value(board: np.ndarray, player: BoardPiece, _last_action: Optional[PlayerAction] = None) -> bool: """ Returns the heuristic value to the given plaer of a complete board """ board1 = board.copy() board2 = board.copy() other_player = BoardPiece(player % 2 + 1) board1[board1 == other_player] = 5 board1[board1 == player] = BoardPiece(1) board2[board2 == player] = BoardPiece(5) board2[board2 == other_player] = BoardPiece(1) value = 0 # scoring central positions center = board[:, board.shape[1] // 2] value += (center == player).sum() * 10 value += (center == other_player).sum() * -5 # checking remainin positions for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board1, kernel, 1, 0, 0, BoardPiece(0)) for i in result: for sum in i: if sum == CONNECT_N: value += 200 if sum == CONNECT_N - 1: value += 50 if sum == CONNECT_N - 2: value += 10 for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board2, kernel, 1, 0, 0, 0) for i in result: for sum in i: if sum == CONNECT_N: value += -250 if sum == CONNECT_N - 1: value += -55 if sum == CONNECT_N - 2: value += -12 return int(value)
def conv2d(self, img, kern, mode="valid"): """ Basic slow python implementatation for DebugMode """ if not imported_scipy_signal: raise NotImplementedError( "AbstractConv perform requires the python package" " for scipy.signal to be installed.") if not (mode in ('valid', 'full')): raise ValueError( 'invalid mode {}, which must be either ' '"valid" or "full"'.format(mode)) out_shape = get_conv_output_shape(img.shape, kern.shape, mode, [1, 1]) out = numpy.zeros(out_shape, dtype=img.dtype) val = _valfrommode(mode) bval = _bvalfromboundary('fill') with warnings.catch_warnings(): warnings.simplefilter('ignore', numpy.ComplexWarning) for b in xrange(img.shape[0]): for n in xrange(kern.shape[0]): for im0 in xrange(img.shape[1]): # some cast generates a warning here out[b, n, ...] += _convolve2d(img[b, im0, ...], kern[n, im0, ...], 1, val, bval, 0) return out
def check_result(board: np.ndarray, player: BoardPiece, _last_action: Optional[PlayerAction] = None) -> bool: ''' check if the board is a "terminal" board: a win or a draw and assigns a value to each option that can be used by an evaluation function''' board1 = board.copy() board2 = board.copy() MinPiece = 3 - player MaxPiece = player board1[board1 == MinPiece] = NO_PLAYER board1[board1 == MaxPiece] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board1, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == CONNECT_N): # print(time) # print(MaxPiece) # print("won") return 1 #self wins board2[board2 == MaxPiece] = NO_PLAYER board2[board2 == MinPiece] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board2, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == CONNECT_N): # print(time) # print(MinPiece) # print("lost") return -0.1 #opponent wins if np.count_nonzero(board) == board.shape[0] * board.shape[1]: # print(board) # print("draw") return 0 #draw return False
def convolve2d(in1, in2, mode='full', boundary='fill', fillvalue=0): """ Convolve two 2-dimensional arrays. Convolve `in1` and `in2` with output size determined by `mode`, and boundary conditions determined by `boundary` and `fillvalue`. Parameters ---------- in1, in2 : array_like Two-dimensional input arrays to be convolved. mode : str {'full', 'valid', 'same'}, optional A string indicating the size of the output: ``full`` The output is the full discrete linear convolution of the inputs. (Default) ``valid`` The output consists only of those elements that do not rely on the zero-padding. ``same`` The output is the same size as `in1`, centered with respect to the 'full' output. boundary : str {'fill', 'wrap', 'symm'}, optional A flag indicating how to handle boundaries: ``fill`` pad input arrays with fillvalue. (default) ``wrap`` circular boundary conditions. ``symm`` symmetrical boundary conditions. fillvalue : scalar, optional Value to fill pad input arrays with. Default is 0. Returns ------- out : ndarray A 2-dimensional array containing a subset of the discrete linear convolution of `in1` with `in2`. """ in1 = asarray(in1) in2 = asarray(in2) if mode == 'valid': _check_valid_mode_shapes(in1.shape, in2.shape) val = _valfrommode(mode) bval = _bvalfromboundary(boundary) with warnings.catch_warnings(): warnings.simplefilter('ignore', np.ComplexWarning) # FIXME: some cast generates a warning here out = sigtools._convolve2d(in1, in2, 1, val, bval, fillvalue) return out
def connected_four(board: np.ndarray, player: BoardPiece, _last_action: Optional[PlayerAction] = None) -> bool: board = board.copy() other_player = BoardPiece(player % 2 + 1) board[board == other_player] = NO_PLAYER board[board == player] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == CONNECT_N): return True return False
def _conv2d(img, kern, mode="valid", dilation=(1, 1), groups=1): """Basic slow Python 2D or 3D convolution for DebugMode Copied and simplified from Theano (2020/11/08): https://github.com/Theano/Theano/blob/master/theano/tensor/nnet/abstract_conv.py """ convdim = 2 assert mode in ("valid", "full") out_shape = _get_conv_output_shape(img.shape, kern.shape, mode, [1] * convdim, dilation) dil_kern_shp = kern.shape[:-convdim] + tuple( (kern.shape[-convdim + i] - 1) * dilation[i] + 1 for i in range(convdim)) dilated_kern = np.zeros(dil_kern_shp, dtype=kern.dtype) dilated_kern[(slice(None), ) * (dilated_kern.ndim - convdim) + tuple(slice(None, None, dilation[i]) for i in range(convdim))] = kern out = np.zeros(out_shape, dtype=img.dtype) input_channel_offset = img.shape[1] // groups output_channel_offset = kern.shape[0] // groups val = _valfrommode(mode) bval = _bvalfromboundary("fill") with warnings.catch_warnings(): warnings.simplefilter("ignore", np.ComplexWarning) for b in range(img.shape[0]): for g in range(groups): for n in range(output_channel_offset): for im0 in range(input_channel_offset): # some cast generates a warning here out[b, g * output_channel_offset + n, ...] += _convolve2d( img[b, g * input_channel_offset + im0, ...], dilated_kern[g * output_channel_offset + n, im0, ...], 1, val, bval, 0, ) return out
def connected_four(board: np.ndarray, player: BoardPiece, _last_action: Optional[PlayerAction] = None) -> bool: """ Returns True if there are four adjacent pieces equal to `player` arranged in either a horizontal, vertical, or diagonal line. Returns False otherwise. If desired, the last action taken (i.e. last column played) can be provided for potential speed optimisation. """ board = board.copy() other_player = BoardPiece(player % 2 + 1) board[board == other_player] = NO_PLAYER board[board == player] = BoardPiece(1) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board, kernel, 1, 0, 0, BoardPiece(0)) if np.any(result == 4): return True return False
def negamax_heuristic(board: np.ndarray, player: BoardPiece) -> float: """ A heuristic for negamax -- the weighted sum of n-in-a-row for the current board. :param board: current board :param player: the player to play :return: selected move """ board = board.copy() other_player = BoardPiece(player % 2 + 1) board[board == other_player] = -1 board[board == player] = 1 score = 0 # if a move results in blocking a loss, return it for n in range(2, CONNECT_N+1): weight = weights[n-1] for _, kernel in enumerate(kernels[n]): result = _convolve2d(board, kernel, 1, 0, 0, BoardPiece(0)) score += weight * np.sum(result == (n - 1)) return score
def _own_correlate(self, Europa_map, Sandbox_data, mode='full', boundary='fill', fillvalue=0) -> Tuple[int, int]: in1 = np.asarray(Europa_map) in2 = np.asarray(Sandbox_data) if not in1.ndim == in2.ndim == 2: raise ValueError('_own_correlate inputs must both be 2D arrays') swapped_inputs = True #np._inputs_swap_needed(mode, in1.shape, in2.shape) if swapped_inputs: in1, in2 = in2, in1 #val = _valfrommode(mode) #bval = _bvalfromboundary(boundary) out = sigtools._convolve2d(in1, in2.conj(), 0) if swapped_inputs: out = out[::-1, ::-1] ascent = misc.ascent() fig, (ax_orig, ax_mag, ax_ang) = plt.subplots(3, 1, figsize=(6, 15)) ax_orig.imshow(ascent, cmap='gray') ax_orig.set_title('Original') ax_orig.set_axis_off() ax_mag.imshow(np.absolute(out), cmap='gray') ax_mag.set_title('Gradient magnitude') ax_mag.set_axis_off() ax_ang.imshow(np.angle(out), cmap='hsv') # hsv is cyclic, like angles ax_ang.set_title('Gradient orientation') ax_ang.set_axis_off() fig.show() return out
def connected_four( board: np.ndarray, player: BoardPiece, last_action: Optional[PlayerAction] = None, ) -> bool: """ Returns True if there are four adjacent pieces equal to `player` arranged in either a horizontal, vertical, or diagonal line. Returns False otherwise. If desired, the last action taken (i.e. last column played) can be provided for potential speed optimisation. """ # from Owen Mackwood's connected_four_convolve board = board.copy() # other_player = BoardPiece(player % 2 + 1) # flat = board.flatten() # to play nice with numba have to use 1d boolean indexing # flat[flat == other_player] = BoardPiece(0) # flat[flat == player] = BoardPiece(1) # board = flat.reshape(board.shape) other_player = BoardPiece(player % 2 + 1) board[board == other_player] = NO_PLAYER board[board == player] = BoardPiece(1) # TODO: add condition for if last_action provided # if last_action: # result = _convolve2d(board, kernel, 1 # , 0, 0, BoardPiece(0)) for kernel in (col_kernel, row_kernel, dia_l_kernel, dia_r_kernel): result = _convolve2d(board, kernel, 1, 0, 0, BoardPiece(0)) # result = np.convolve(board, kernel) if np.any(result == CONNECT_N): return True return False
def exec_multilayer_conv_nnet_old(conv_mode, ss, bsize, imshp, kshps, nkerns, unroll_batch=0, unroll_kern=0, img=T.dmatrix(), validate=True, conv_op_py=False, do_print=True, repeat=1, unroll_patch=False, unroll_patch_size=False, verbose=0): # build actual input images imgval = global_rng.rand(bsize, imshp[0], imshp[1], imshp[2]) a = T.dmatrix() kerns = [a for i in nkerns] inputs4 = dmatrix4() kerns4 = dmatrix4() # for each layer ntot = 0 tctot = 0 tpytot = 0 for kshp, kern, nkern, n_layer in zip(kshps, kerns, nkerns, range(len(nkerns))): if do_print: print '************* layer %i ***************' % n_layer print conv_mode, ss, n_layer, kshp, nkern # actual values w = global_rng.random_sample(N.r_[nkern, imshp[0], kshp]) w_flip = flip(w, kshp).reshape(w.shape) ## manual implementation # check first stage padimg = imgval if conv_mode == 'full': padimg_shp = N.array( imshp[1:]) + 2 * (N.array(kshp) - N.array([1, 1])) padimg = N.zeros(N.r_[bsize, imshp[0], padimg_shp]) padimg[:, :, kshp[0] - 1:-kshp[0] + 1, kshp[1] - 1:-kshp[1] + 1] = imgval outshp = N.hstack( (nkern, ConvOp.getOutputShape(imshp[1:], kshp, ss, conv_mode))) time1 = time.time() outval = N.zeros(N.r_[bsize, outshp]) if validate: # causes an atexit problem from scipy.signal.sigtools import _convolve2d from scipy.signal.signaltools import _valfrommode, _bvalfromboundary val = _valfrommode(conv_mode) bval = _bvalfromboundary('fill') for b in range(bsize): # loop over batches for n in range(nkern): # loop over filters for i in range(imshp[0]): # loop over input feature maps outval[b,n,...] += _convolve2d(\ imgval[b,i,...], w_flip[n,i,...],1,val, bval, 0)[0::ss[0],0::ss[1]] ntot += time.time() - time1 # ConvOp if unroll_patch and not unroll_patch_size: conv_op = ConvOp(dx=ss[0], dy=ss[1], output_mode=conv_mode, unroll_patch=unroll_patch, verbose=verbose)(inputs4, kerns4) else: conv_op = ConvOp(imshp, kshp, nkern, bsize, ss[0], ss[1], conv_mode, unroll_batch=unroll_batch, unroll_kern=unroll_kern, unroll_patch=unroll_patch, verbose=verbose)(inputs4, kerns4) l1shp = N.hstack( (nkern, ConvOp.getOutputShape(imshp[1:], kshp, ss, conv_mode))) propup2 = function([inputs4, kerns4], conv_op) propup3 = function([inputs4, kerns4], conv_op, mode=Mode(linker="py")) time1 = time.time() for i in range(repeat): hidval2_ = propup2(imgval, w_flip) hidval2 = hidval2_ #[:,:,0::ss[0],0::ss[1]] tctot += time.time() - time1 if conv_op_py: time1 = time.time() for i in range(repeat): hidval3_ = propup3(imgval, w_flip) hidval3 = hidval3_ #[:,:,0::ss[0],0::ss[1]] tpytot += time.time() - time1 assert (N.abs(hidval2 - hidval3) < 1e-5).all() else: tpytot += 0 if validate: temp = N.abs(outval - hidval2) assert (temp < 1e-5).all() if validate and conv_op_py: temp = N.abs(outval - hidval3) assert (temp < 1e-5).all() imshp = tuple(outshp) imgval = outval.reshape(bsize, outshp[0], outshp[1], outshp[2]) return tctot, tpytot, ntot
def exec_multilayer_conv_nnet_old( conv_mode, ss, bsize, imshp, kshps, nkerns, unroll_batch=0, unroll_kern=0, img=T.dmatrix(), validate=True, conv_op_py=False, do_print=True, repeat=1, unroll_patch=False, unroll_patch_size=False, verbose=0, ): # build actual input images imgval = global_rng.rand(bsize, imshp[0], imshp[1], imshp[2]) a = T.dmatrix() kerns = [a for i in nkerns] inputs4 = dmatrix4() kerns4 = dmatrix4() # for each layer ntot = 0 tctot = 0 tpytot = 0 for kshp, kern, nkern, n_layer in zip(kshps, kerns, nkerns, xrange(len(nkerns))): if do_print: print("************* layer %i ***************" % n_layer) print(conv_mode, ss, n_layer, kshp, nkern) # actual values w = global_rng.random_sample(N.r_[nkern, imshp[0], kshp]) w_flip = flip(w, kshp).reshape(w.shape) # manual implementation # check first stage padimg = imgval if conv_mode == "full": padimg_shp = N.array(imshp[1:]) + 2 * (N.array(kshp) - N.array([1, 1])) padimg = N.zeros(N.r_[bsize, imshp[0], padimg_shp]) padimg[:, :, kshp[0] - 1 : -kshp[0] + 1, kshp[1] - 1 : -kshp[1] + 1] = imgval outshp = N.hstack((nkern, ConvOp.getOutputShape(imshp[1:], kshp, ss, conv_mode))) time1 = time.time() outval = N.zeros(N.r_[bsize, outshp]) if validate: # causes an atexit problem from scipy.signal.sigtools import _convolve2d from scipy.signal.signaltools import _valfrommode, _bvalfromboundary val = _valfrommode(conv_mode) bval = _bvalfromboundary("fill") for b in xrange(bsize): # loop over batches for n in xrange(nkern): # loop over filters for i in xrange(imshp[0]): # loop over input feature maps outval[b, n, ...] += _convolve2d(imgval[b, i, ...], w_flip[n, i, ...], 1, val, bval, 0)[ 0 :: ss[0], 0 :: ss[1] ] ntot += time.time() - time1 # ConvOp if unroll_patch and not unroll_patch_size: conv_op = ConvOp(dx=ss[0], dy=ss[1], output_mode=conv_mode, unroll_patch=unroll_patch, verbose=verbose)( inputs4, kerns4 ) else: conv_op = ConvOp( imshp, kshp, nkern, bsize, ss[0], ss[1], conv_mode, unroll_batch=unroll_batch, unroll_kern=unroll_kern, unroll_patch=unroll_patch, verbose=verbose, )(inputs4, kerns4) # l1shp = N.hstack((nkern, # ConvOp.getOutputShape(imshp[1:], kshp, ss, conv_mode))) propup2 = function([inputs4, kerns4], conv_op) propup3 = function([inputs4, kerns4], conv_op, mode=Mode(linker="py")) time1 = time.time() for i in xrange(repeat): hidval2_ = propup2(imgval, w_flip) hidval2 = hidval2_ # [:,:,0::ss[0],0::ss[1]] tctot += time.time() - time1 if conv_op_py: time1 = time.time() for i in xrange(repeat): hidval3_ = propup3(imgval, w_flip) hidval3 = hidval3_ # [:,:,0::ss[0],0::ss[1]] tpytot += time.time() - time1 assert (N.abs(hidval2 - hidval3) < 1e-5).all() else: tpytot += 0 if validate: temp = N.abs(outval - hidval2) assert (temp < 1e-5).all() if validate and conv_op_py: temp = N.abs(outval - hidval3) assert (temp < 1e-5).all() imshp = tuple(outshp) imgval = outval.reshape(bsize, outshp[0], outshp[1], outshp[2]) return tctot, tpytot, ntot