diff --git a/src/statebag.py b/src/statebag.py --- a/src/statebag.py +++ b/src/statebag.py @@ -16,19 +16,29 @@ So we try to find the correct crossover - remember the better variant - linearize the fork back by discarding s'_j-s preceding the crossover and s_j-s following the crossover """ +import random from util import EMPTY -from go.core import transitionSequence +from go.engine import transitionSequence + +rand=random.Random() +rand.seed(361) +zobristNums=tuple( + tuple( + tuple(rand.getrandbits(32) for i in range(3)) for c in range(19) + ) for r in range(19) +) ## Crude lower bound on edit distance between states. def estimateDistance(diff): + # lot of room for improvements additions=sum(1 for d in diff if d[2]=="+") deletions=sum(1 for d in diff if d[2]=="-") replacements=len(diff)-additions-deletions if additions>0: return additions+replacements elif replacements==0 and deletions>0: return 2 # take n, return 1 - return replacements # ??? + return replacements+1 # ??? class BoardState: @@ -40,6 +50,13 @@ class BoardState: self.weight=0 self.diff2Prev=None + def hash(self): + res=0 + for (r,row) in enumerate(self._board): + for (c,item) in enumerate(row): + res^=zobristNums[r][c][item+1] + return res + def __iter__(self): return iter(self._board) def __getitem__(self,key): return self._board[key] @@ -52,9 +69,13 @@ class BoardState: if item1==item2: continue elif item2==EMPTY: res.append((r,c,"+",item1)) elif item1==EMPTY: res.append((r,c,"-",item2)) - else: res.append((r,c,item2,item1)) # from->to + else: res.append((r,c,"*",item1)) # ->to return res + def __eq__(self,x): + # might want to use hash + return self._board==x._board + class StateBag: def __init__(self): @@ -62,6 +83,8 @@ class StateBag: def pushState(self,board): sn=BoardState(board) + if self._states and sn==self._states[-1]: return # no change + for s in reversed(self._states): diff=sn-s distEst=estimateDistance(diff)