def get_moves_black_increasing_incorrect(probfile): mtp = MoveTreeParser(probfile) ss = mtp.getAllPaths() move = mtp.start.clone() #print_move('start ({}x{})'.format(move.x, move.y), move) isBtL = (mtp.problemType == 1 or mtp.problemType==3) pt = 1 if isBtL else 2 sw = len(determineLife(move, False)) sb = len(determineLife(move, True)) if sb>0: print('{}: Black is already alive!'.format(probfile)) problems = [] # prob type, solution, terminal, # living black groups, # living white groups #tpl= (pt, 1, 0, sb, sw) for spath in ss: move = mtp.start.clone() for step in spath: fm = mtp.formatMove(mtp.moveID[step]) move.place_stone(fm['x'], fm['y'], fm['isBlack']) w = len(determineLife(move, False)) b = len(determineLife(move, True)) sol = 1 if step in mtp.getSolutionNodes() else 0 term = 1 if step in mtp.getTerminalStates() else 0 bdiff = b-sb wdiff = w-sw if bdiff>0 and sol==0: problems.append([step, fm['x'], fm['y'], fm['isBlack']]) return problems
def print_move(label, move): liveWGr = determineLife(move, False) liveBGr = determineLife(move, True) w = len(liveWGr) b = len(liveBGr) wa = 0 wb = 0 print('{}: w={}, b={}, wa={}, wb={}, nw={}, nb={}'.format(label,w,b,wa,wb,len(move.white_stones),len(move.black_stones)))
def calculate_feature(self): first = len(determineLife(self.start, self.isblack)) firstTotal = float(self.getNumGroups(self.start, self.isblack)) second = len(determineLife(self.move, self.isblack)) secondTotal = float(self.getNumGroups(self.start, self.isblack)) return [ second / (secondTotal + 0.0001), (second / (secondTotal + 0.0001)) - (first / (firstTotal + 0.0001)), second, second - first ]
def terminal_test(self, move, i, j, isblack): # Use cache for black-is-alive test #black_is_alive = self.cache.get(move) black_is_alive=None if black_is_alive is None: if self.sb is None: self.sb =len(determineLife(self.board, True)) b = len(determineLife(move, True)) black_is_alive= (b-self.sb)>0 #self.cache.put(move, black_is_alive) result = 2 if black_is_alive else 0 return [result, b] result = 2 if black_is_alive else 0 return [result, None]
def terminal_test(self, move, i, j, isblack): # Use cache for black-is-alive test #black_is_alive = self.cache.get(move) black_is_alive = None if black_is_alive is None: if self.sb is None: self.sb = len(determineLife(self.board, True)) b = len(determineLife(move, True)) black_is_alive = (b - self.sb) > 0 #self.cache.put(move, black_is_alive) result = 2 if black_is_alive else 0 return [result, b] result = 2 if black_is_alive else 0 return [result, None]
def load_problem_paths(f): mtp = MoveTreeParser(f) #print('{} := {}'.format(f.split('/')[-1].split('\\')[-1], mtp.problemType)) sn = mtp.getSolutionNodes() inc = mtp.getIncorrectNodes() probtyp = mtp.getProblemType() if probtyp == 1 or probtyp == 3: #Black to live probtyp = 1 elif probtyp == 2 or probtyp == 4: #White to kill probtyp = 2 else: #Error should be thrown, but just in case it isn't probtyp = 0 paths = mtp.getAllPaths() boards = [] for path in paths: start = mtp.start if (len(path) > 100): print('START NEW PATH (len={}; {})'.format(len(path), f.split('/')[-1])) move = None outcome = 0 liveWGr = determineLife(start, False) liveBGr = determineLife(start, True) w = len(liveWGr) b = len(liveBGr) boards.append(start) print('START: w={}, b={}, nw={}, nb={}'.format( w, b, len(start.white_stones), len(start.black_stones))) for mid in path: move_dict = mtp.formatMove(mtp.moveID[mid]) saysblack = move_dict['isBlack'] #move_str[0:1]=='B' #print('{}''s turn'.format('black' if saysblack else 'white')) move_y = move_dict['y'] #ord(move_str[2]) - ord('a') move_x = move_dict['x'] #ord(move_str[3]) - ord('a') move = start.clone() try: move.place_stone(move_x, move_y, saysblack) boards.append(move) color = 'B' if saysblack else 'W' print('{}({},{}): w={}, b={}, nw={}, nb={}'.format( color, move_x, move_y, w, b, len(move.white_stones), len(move.black_stones))) except IllegalMove as e: print('{}: ({},{})'.format(e, move_x, move_y)) start = move if outcome == 1: return move return boards
def load_problem_paths(f): mtp = MoveTreeParser(f) #print('{} := {}'.format(f.split('/')[-1].split('\\')[-1], mtp.problemType)) sn = mtp.getSolutionNodes() inc = mtp.getIncorrectNodes() probtyp = mtp.getProblemType() if probtyp == 1 or probtyp == 3: #Black to live probtyp = 1 elif probtyp == 2 or probtyp == 4: #White to kill probtyp = 2 else: #Error should be thrown, but just in case it isn't probtyp = 0 paths = mtp.getAllPaths() boards = [] for path in paths: start = mtp.start if( len(path)>100 ): print('START NEW PATH (len={}; {})'.format(len(path),f.split('/')[-1])) move = None outcome = 0 liveWGr = determineLife(start, False) liveBGr = determineLife(start, True) w = len(liveWGr) b = len(liveBGr) boards.append(start) print('START: w={}, b={}, nw={}, nb={}'.format(w,b,len(start.white_stones),len(start.black_stones))) for mid in path: move_dict = mtp.formatMove(mtp.moveID[mid]) saysblack = move_dict['isBlack'] #move_str[0:1]=='B' #print('{}''s turn'.format('black' if saysblack else 'white')) move_y = move_dict['y'] #ord(move_str[2]) - ord('a') move_x = move_dict['x'] #ord(move_str[3]) - ord('a') move = start.clone() try: move.place_stone(move_x, move_y, saysblack) boards.append(move) color = 'B' if saysblack else 'W' print('{}({},{}): w={}, b={}, nw={}, nb={}'.format(color,move_x,move_y,w,b,len(move.white_stones),len(move.black_stones))) except IllegalMove as e: print('{}: ({},{})'.format(e, move_x, move_y)) start = move if outcome==1: return move return boards
def get_terminal_states(mtp): ss = mtp.getSolutionPaths() #isblack = mtp.blackFirst != mtp.flipColors move = mtp.start.clone() solutionStates = set() terminalIncorrectStates = set() print_move('start ({}x{})'.format(move.x, move.y), move) longestPath = 0 isBtL = (mtp.problemType == 1 or mtp.problemType == 3) ptdesc = mtp.getProblemTypeDesc() if mtp.flipColors: ptdesc += ' => ' if isBtL: ptdesc += 'Black to Live' else: ptdesc += 'White to Kill' print(ptdesc) print('SOLUTIONS:') for spath in ss: pathLength = 0 move = mtp.start.clone() sb = len(determineLife(mtp.start, True)) sw = len(determineLife(mtp.start, False)) for step in spath: pathLength += 1 if pathLength > longestPath: longestPath = pathLength fm = mtp.formatMove(mtp.moveID[step]) move.place_stone(fm['x'], fm['y'], fm['isBlack']) color = 'B' if fm['isBlack'] else 'W' print_move('{}({},{})'.format(color, fm['x'], fm['y']), move, sw=sw, sb=sb) if step in mtp.getTerminalStates(): if step in mtp.getSolutionStates(): solutionStates.add(move.clone()) else: terminalIncorrectStates.add(move.clone()) print('------------') return [solutionStates, terminalIncorrectStates, longestPath]
def drawBoard(self): #board, dim_x, dim_y, diam, margin, spaces): #i = 0 for c in self.C.children: c.destroy() for [color,stones] in [['white', self.board.white_stones], ['black', self.board.black_stones]]: living_groups = determineLife(self.board, color) self.C.delete(color) for stone in stones: alive = False for group in living_groups: if not alive and stone in group: alive = True self.drawStone(stone[0],stone[1],color,alive)
def probfile_move_to_board_state(probfile, moveid): mtp= MoveTreeParser(probfile) ss = mtp.getAllPaths() move = mtp.start.clone() #print_move('start ({}x{})'.format(move.x, move.y), move) isBtL = (mtp.problemType == 1 or mtp.problemType==3) pt = 1 if isBtL else 2 sw = len(determineLife(move, False)) sb = len(determineLife(move, True)) if sb>0: print('{}: Black is already alive!'.format(probfile)) # prob type, solution, terminal, # living black groups, # living white groups #tpl= (pt, 1, 0, sb, sw) for spath in ss: move = mtp.start.clone() if moveid in spath: for step in spath: fm = mtp.formatMove(mtp.moveID[step]) move.place_stone(fm['x'], fm['y'], fm['isBlack']) if step==moveid: return move raise Exception('{}: Move id {} not found in problem file.'.format(probfile, moveid))
def print_move(label, move, sw=None, sb=None, w=None, b=None, moves=None, prob=None, etime=None, nodecount=None): if w is None: liveWGr = determineLife(move, False) w = len(liveWGr) if b is None: liveBGr = determineLife(move, True) b = len(liveBGr) if prob is None: probS = '' elif prob >= 5.0: probS = ' T' else: probS = ' {:.3f}'.format(prob) if etime is None: timeS = '' else: timeS = ' ({:.1f} seconds).'.format(etime) if nodecount is not None: timeS = ' ({} moves, {:.1f} seconds, {} nodes).'.format( moves, etime, nodecount) if sw is None or sb is None: print('{}: w={}, b={}, nw={}, nb={}{}{}'.format( label, w, b, len(move.white_stones), len(move.black_stones), probS, timeS)) else: print('{}: w={}, b={}, sw={}, sb={}, nw={}, nb={}{}{}'.format( label, w, b, sw, sb, len(move.white_stones), len(move.black_stones), probS, timeS))
def drawBoard(self): #board, dim_x, dim_y, diam, margin, spaces): #i = 0 for c in self.C.children: c.destroy() for [color, stones] in [['white', self.board.white_stones], ['black', self.board.black_stones]]: living_groups = determineLife(self.board, color) self.C.delete(color) for stone in stones: alive = False for group in living_groups: if not alive and stone in group: alive = True self.drawStone(stone[0], stone[1], color, alive)
def calculate_feature(self): first = len(determineLife(self.start, self.isblack)) firstTotal = float(self.getNumGroups(self.start,self.isblack)) second = len(determineLife(self.move, self.isblack)) secondTotal = float(self.getNumGroups(self.start,self.isblack)) return [second/(secondTotal+0.0001), (second/(secondTotal+0.0001)) - (first/(firstTotal+0.0001)), second, second - first]
def load_problem_solution(f): mtp = MoveTreeParser(f) #print('{} := {}'.format(f.split('/')[-1].split('\\')[-1], mtp.problemType)) sn = mtp.getSolutionNodes() inc = mtp.getIncorrectNodes() probtyp = mtp.getProblemType() if probtyp == 1 or probtyp == 3: #Black to live probtyp = 1 elif probtyp == 2 or probtyp == 4: #White to kill probtyp = 2 else: #Error should be thrown, but just in case it isn't probtyp = 0 isBTL = (probtyp==1) or (probtyp==0) # and mtp.blackFirst) if not sn.isdisjoint(inc): print('NOT DISJOINT') paths = mtp.getAllPaths() movesConsidered = set() for path in paths: parent = 0 start = mtp.start if( len(path)>100 ): print('START NEW PATH (len={}; {})'.format(len(path),f.split('/')[-1])) move = None outcome = 0 liveWGr = determineLife(start, False) liveBGr = determineLife(start, True) w = len(liveWGr) b = len(liveBGr) print('START: w={}, b={}, nw={}, nb={}'.format(w,b,len(start.white_stones),len(start.black_stones))) for mid in path: move_dict = mtp.formatMove(mtp.moveID[mid]) saysblack = move_dict['isBlack'] #move_str[0:1]=='B' #print('{}''s turn'.format('black' if saysblack else 'white')) move_y = move_dict['y'] #ord(move_str[2]) - ord('a') move_x = move_dict['x'] #ord(move_str[3]) - ord('a') move = start.clone() try: move.place_stone(move_x, move_y, saysblack) color = 'B' if saysblack else 'W' print('{}({},{}): w={}, b={}, nw={}, nb={}'.format(color,move_x,move_y,w,b,len(move.white_stones),len(move.black_stones))) if (parent, mid) not in movesConsidered: #features = [probtyp] outcome = 0 if isBTL == saysblack: #CHECK THIS LOGIC if mid in sn: outcome = 1 elif mid in inc: outcome = 0 else: raise Exception('Unknown outcome!') else: ''' Assume only moves on incorrect path are correct for the "antagonist" ''' if mid in inc: outcome = 1 ''' Assume all moves for the "antagonist" are correct ''' # outcome = 1 movesConsidered.add((parent, mid)) #vectors.append(features) # Only train on the first wrong move for the protagonist if outcome==0 and isBTL==saysblack: break; except IllegalMove as e: print('{}: ({},{})'.format(e, move_x, move_y)) parent = mid start = move if outcome==1: return move return None
def test_problem(mtp, modelBtL, modelWtK, maxdepth=10): [solutionStates, terminalIncorrectStates, longestPath] = get_terminal_states(mtp) move = mtp.start.clone() isBtL = (mtp.problemType == 1 or mtp.problemType == 3) if not isBtL: raise UnspecifiedProblemType( 'Only configured to test black-to-live problems') sb = len(determineLife(mtp.start, True)) sw = len(determineLife(mtp.start, False)) pathLength = 0 isblack = mtp.blackFirst != mtp.flipColors path = [move.clone()] print('GOLD:') start = time.clock() mmt = MinMaxTree(move, isblack, not isblack, blackModel=modelBtL, whiteModel=modelWtK) mmt.extend_tree() passed = False maxpathlength = 2 * longestPath + 3 maxnodecount = 0 while (move not in solutionStates and pathLength < maxpathlength): color = 'B' if isblack else 'W' moves = len(mmt.children) validMove = False illegalMoves = set() while not validMove: nextMove = mmt.decideNextMove() if nextMove is None: print('Pass.') if passed: if mmt.terminal: print('Two passes and Black lives. You win!!') return [path, maxnodecount] raise YouLoseException('Two passes in a row. You Lose!', path, maxnodecount) passed = True continue elif passed: passed = False try: move.place_stone(nextMove.i, nextMove.j, mmt.isblack) validMove = True except IllegalMove as im: # Rebuild that part of the tree # and prune away the illegal moves print('({},{}): {}'.format(nextMove.i, nextMove.j, im)) [i, j] = [nextMove.i, nextMove.j] mmt.prune((i, j)) illegalMoves.add((i, j)) mmt.promote(extendIfSame=True) for p, q in illegalMoves: mmt.prune((p, q)) nextMove = None if nextMove.value is None: if nextMove.terminal: prob = 5.0 else: prob = nextMove.value + 10.0 else: prob = nextMove.value nodecount = mmt.node_count() if nodecount > maxnodecount: maxnodecount = nodecount print_move('{}({},{})'.format(color, nextMove.i, nextMove.j), move, sb=sb, sw=sw, moves=moves, prob=prob, etime=time.clock() - start, nodecount=nodecount) start = time.clock() mmt = nextMove path.append(move.clone()) if move in terminalIncorrectStates: raise YouLoseException('Haha! You lose!', path, maxnodecount) if move in solutionStates: print('Solution matched!! You Win!! ') return [path, maxnodecount] if mmt.sb is None: mmt.sb = len(determineLife(mmt.board, isblack)) if mmt.sb > sb: print( 'You win!!! Black has groups that are unconditionally alive!') return [path, maxnodecount] pathLength = pathLength + 1 if pathLength < maxpathlength: mmt.promote() isblack = not isblack raise YouLoseException('Too many moves, you lose!!', path, maxnodecount)
def load_problem_solution(f): mtp = MoveTreeParser(f) #print('{} := {}'.format(f.split('/')[-1].split('\\')[-1], mtp.problemType)) sn = mtp.getSolutionNodes() inc = mtp.getIncorrectNodes() probtyp = mtp.getProblemType() if probtyp == 1 or probtyp == 3: #Black to live probtyp = 1 elif probtyp == 2 or probtyp == 4: #White to kill probtyp = 2 else: #Error should be thrown, but just in case it isn't probtyp = 0 isBTL = (probtyp == 1) or (probtyp == 0) # and mtp.blackFirst) if not sn.isdisjoint(inc): print('NOT DISJOINT') paths = mtp.getAllPaths() movesConsidered = set() for path in paths: parent = 0 start = mtp.start if (len(path) > 100): print('START NEW PATH (len={}; {})'.format(len(path), f.split('/')[-1])) move = None outcome = 0 liveWGr = determineLife(start, False) liveBGr = determineLife(start, True) w = len(liveWGr) b = len(liveBGr) print('START: w={}, b={}, nw={}, nb={}'.format( w, b, len(start.white_stones), len(start.black_stones))) for mid in path: move_dict = mtp.formatMove(mtp.moveID[mid]) saysblack = move_dict['isBlack'] #move_str[0:1]=='B' #print('{}''s turn'.format('black' if saysblack else 'white')) move_y = move_dict['y'] #ord(move_str[2]) - ord('a') move_x = move_dict['x'] #ord(move_str[3]) - ord('a') move = start.clone() try: move.place_stone(move_x, move_y, saysblack) color = 'B' if saysblack else 'W' print('{}({},{}): w={}, b={}, nw={}, nb={}'.format( color, move_x, move_y, w, b, len(move.white_stones), len(move.black_stones))) if (parent, mid) not in movesConsidered: #features = [probtyp] outcome = 0 if isBTL == saysblack: #CHECK THIS LOGIC if mid in sn: outcome = 1 elif mid in inc: outcome = 0 else: raise Exception('Unknown outcome!') else: ''' Assume only moves on incorrect path are correct for the "antagonist" ''' if mid in inc: outcome = 1 ''' Assume all moves for the "antagonist" are correct ''' # outcome = 1 movesConsidered.add((parent, mid)) #vectors.append(features) # Only train on the first wrong move for the protagonist if outcome == 0 and isBTL == saysblack: break except IllegalMove as e: print('{}: ({},{})'.format(e, move_x, move_y)) parent = mid start = move if outcome == 1: return move return None