Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Interesting mate test for hashing

Author: Dave Gomboc

Date: 19:50:17 09/10/99

Go up one level in this thread


On September 10, 1999 at 17:40:45, Robert Hyatt wrote:

>On September 10, 1999 at 17:01:58, jonathon smith wrote:
>
>>On September 10, 1999 at 16:45:59, Robert Hyatt wrote:
>>
>>>On September 10, 1999 at 16:21:48, Alessandro Damiani wrote:
>>>
>>>>On September 10, 1999 at 15:58:45, Ed Schröder wrote:
>>>>
>>>>>On September 10, 1999 at 13:17:57, Robert Hyatt wrote:
>>>>>
>>>>>>On September 10, 1999 at 11:29:04, Alessandro Damiani wrote:
>>>>>>
>>>>>>>On September 10, 1999 at 09:36:51, Robert Hyatt wrote:
>>>>>>>
>>>>>>>>On September 10, 1999 at 08:01:35, Alessandro Damiani wrote:
>>>>>>>>
>>>>>>>>>On September 10, 1999 at 07:48:44, Ed Schröder wrote:
>>>>>>>>>
>>>>>>>>>>On September 10, 1999 at 00:19:37, Robert Hyatt wrote:
>>>>>>>>>>
>>>>>>>>>>>Here is an interesting position given to me by Steffen Jakob:
>>>>>>>>>>>
>>>>>>>>>>> /p/P5p/7p/7P/4kpK/// w
>>>>>>>>>>>
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    8  |   |   |   |   |   |   |   |   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    7  | *P|   |   |   |   |   |   |   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    6  | P |   |   |   |   |   | *P|   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    5  |   |   |   |   |   |   |   | *P|
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    4  |   |   |   |   |   |   |   | P |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    3  |   |   |   |   | *K| *P| K |   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    2  |   |   |   |   |   |   |   |   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>    1  |   |   |   |   |   |   |   |   |
>>>>>>>>>>>       +---+---+---+---+---+---+---+---+
>>>>>>>>>>>         a   b   c   d   e   f   g   h
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>Obviously black is getting crushed.  He has one move, Kh3, which leads to a
>>>>>>>>>>>mate in 6.  Steffen asked me to try this and Crafty found a mate in 4, which
>>>>>>>>>>>doesn't exist.  I spent the entire day debugging this thing and here is what
>>>>>>>>>>>I found:
>>>>>>>>>>>
>>>>>>>>>>>If you recall the discussion here a couple of weeks ago, I reported that I store
>>>>>>>>>>>absolute mate scores (EXACT scores) in the hash table, and that I adjust them
>>>>>>>>>>>so that they are always stored as "mate in N from the current position".  This
>>>>>>>>>>>has always worked flawlessly for me, and still does.
>>>>>>>>>>>
>>>>>>>>>>>For bounds, I once tried adjusting the bounds as well, but found quirks, and
>>>>>>>>>>>left them alone.  Wrong answer.  To fix this mate in 4 problem, I decided to
>>>>>>>>>>>adjust the bounds as well, but I now set any bound value that is larger than
>>>>>>>>>>>MATE-300, by reducing it to exactly MATE-300, but still using the "LOWER"
>>>>>>>>>>>flag to say that this is the lowest value this position could have.  For bound
>>>>>>>>>>>values < -MATE+300, I set them to exactly -MATE+300 and leave the flag as is.
>>>>>>>>>>>
>>>>>>>>>>>This position is cute.  Because not only is it a mate in 6, but there are
>>>>>>>>>>>transpositions that lead to mate in 7, mate in 8, and there are shorter (but
>>>>>>>>>>>non-forced) mates in 4 and 5.  And there are stalemates, and positions with
>>>>>>>>>>>1 legal move, and so forth.
>>>>>>>>>>>
>>>>>>>>>>>You ought to find the following variation as one mate in 6:
>>>>>>>>>>>
>>>>>>>>>>>Kh3, f2, Kg2, Ke2, Kg3, f1=Q, Kh2, g5, hg, Kf3, g6, Qg2#
>>>>>>>>>>>
>>>>>>>>>>>If you find a shorter mate, it is wrong.  If you find a longer mate, you
>>>>>>>>>>>are probably just extending like mad on checks (crafty finds a mate in 8 at
>>>>>>>>>>>shallow depths (9 plies, 2 secs on my PII/300 notebook), and doesn't find the
>>>>>>>>>>>mate in 6 until depth 10, 3 seconds.
>>>>>>>>>>>
>>>>>>>>>>>It is a good test as the transpositions are real cute with white's king caught
>>>>>>>>>>>in a tiny box, but with several different moves that triangulate and transpose
>>>>>>>>>>>into other variations...
>>>>>>>>>>>
>>>>>>>>>>>If you get it right, you have either handled the bounds right, or else you are
>>>>>>>>>>>very lucky.  IE Crafty 16.17 gets this dead right.  But if I disable the eval,
>>>>>>>>>>>it goes bananas, yet the eval is not important when mate is possible.
>>>>>>>>>>>
>>>>>>>>>>>Have fun...
>>>>>>>>>>>
>>>>>>>>>>>I did... :)
>>>>>>>>>>
>>>>>>>>>>A simple solution: do not store a position in the hash table if there is
>>>>>>>>>>no best-move. It solves the mate-cases and also repetition cases. Also
>>>>>>>>>>there is no speed loss of the search.
>>>>>>>>>>
>>>>>>>>>>Ed
>>>>>>>>>
>>>>>>>>>Do you mean by "no best-move"
>>>>>>>>>  bestmove == 0
>>>>>>>>>or
>>>>>>>>>  best<=alpha, after having searched all moves (best: minimax score)?
>>>>>>>>>
>>>>>>>>>What I do:
>>>>>>>>>  if bestmove == 0 then don't store anything, just return the score (mate or
>>>>>>>>>  stalemate).
>>>>>>>>>
>>>>>>>>>Alessandro
>>>>>>>>
>>>>>>>>
>>>>>>>>that doesn't make sense to me.  If _every_ move at one node in the tree returns
>>>>>>>>alpha for the score, which is the best move?  And since you don't have one, you
>>>>>>>>don't store anything?  That hurts performance, because the next time you
>>>>>>>>encounter this position, you get to search it again, while I discover that the
>>>>>>>>last time I searched it I returned alpha, so I can just do that now and not
>>>>>>>>search anything...
>>>>>>>
>>>>>>>No, no. My answer was misleading. What I mean is explained by the following code
>>>>>>>(the code is simpilied!). I have marked the important things by an "****". It is
>>>>>>>assumed that
>>>>>>>  - when the king is removed from board its position is -1 ( < 0)
>>>>>>>  - alpha, beta < INF
>>>>>>>
>>>>>>>Alessandro
>>>>>>>
>>>>>>>int AlphaBeta (int alpha, int beta, int depth) {
>>>>>>>
>>>>>>>//**************************************
>>>>>>>// legality check:
>>>>>>>
>>>>>>>  if (myKingSquare<0) return -INF;
>>>>>>>
>>>>>>>//**************************************
>>>>>>>
>>>>>>>  if (depth==0) return Quiescence(alpha,beta);
>>>>>>>
>>>>>>>  // here use info from the transposition table
>>>>>>>
>>>>>>>  best= -INF; bestmove= 0; startalpha= alpha;
>>>>>>>  i= 0; n= GenMoves();
>>>>>>>  while (i!=n && best<beta) {
>>>>>>>    // m[i] is the current move
>>>>>>>
>>>>>>>    make(m[i]);
>>>>>>>    value= -AlphaBeta(-beta,-alpha,depth-1);
>>>>>>>    unmake(m[i]);
>>>>>>>
>>>>>>>    if (value>best) {
>>>>>>>      best= value; bestmove= m[i];
>>>>>>>      if (best>alpha) alpha= best;
>>>>>>>    };
>>>>>>>    i++;
>>>>>>>  };
>>>>>>>
>>>>>>>//**********************************************
>>>>>>>// no best move => mate or stalemate
>>>>>>>
>>>>>>>  if (bestmove==0) {
>>>>>>>    if InCheck(Me) return -MATE+ply;
>>>>>>>    return STALEMATE;
>>>>>>>  };
>>>>>>>
>>>>>>>//**********************************************
>>>>>>>
>>>>>>>  // here update the transposition table
>>>>>>>
>>>>>>>  return best;
>>>>>>>}
>>>>>>
>>>>>>
>>>>>>Same question as before.  The above simply doesn't work as you think it
>>>>>>does.  Here is why.
>>>>>>
>>>>>>at ply=N you set best to -inf, and then step thru each move and do a search
>>>>>>after making it.  And you pass that search a value for alpha and beta that is
>>>>>>used to terminate the search when it can prove that the score below that move
>>>>>>is >= beta (which at our ply=N node means the move we tried is <= alpha.)
>>>>>>
>>>>>>So lets assume that after we search the first move, we get a score back that
>>>>>>is obviously > -infinity, but < alpha.  You remember that move as "best".  But
>>>>>>the problem here is that the 'proof' search stopped as soon as it found a score
>>>>>>> beta.  It didn't try _all_ moves to get the largest score > beta, just the
>>>>>>first score > beta... which is why we refer to the search as returning a bound.
>>>>>>At least as low, but maybe even lower.
>>>>>>
>>>>>>So you end up with a bunch of random bounds that are all <= alpha, and you take
>>>>>>the largest one and assume that is the best move and store that move in the hash
>>>>>>table?  I will run some tests as this is easy to do, but when I tried this a few
>>>>>>years ago, my tree got _bigger_.  And when I looked into why, I found myself
>>>>>>searching nonsense moves from the hash table _before_ I got to the winning
>>>>>>captures (the first of which was a move that would refute the move at the
>>>>>>previous ply.)
>>>>>>
>>>>>>Easy to test.  I'll supply some data in a bit, just for fun...
>>>>>
>>>>>For one moment forget about alpha and beta, you are on the wrong track as
>>>>>alpha and beta are not a part at all of the code. You need an extra stack
>>>>>that is set to -INF at each ply. Then before you do A/B you do the bestmove
>>>>>calculation for that ply. Involved variables: SCORE and STACK, no alpha beta.
>>>>>
>>>>>Ed
>>>>
>>>>I think the best way to explain is to write a small piece of code in pseudo C,
>>>>else we talk around the point.
>>>>
>>>>Alessandro
>>>
>>>
>>>OK... here is what I did:
>>
>>Drunken code adjustment inserted ................
>>
>>
>>>
>>>Normal alpha/beta first:
>>
>>Drunken code added:
>>
>>>
>>>int Search(int alpha, int beta, etc...) {
>>>  best=-infinity;
>>   roughbest = -INFINITY;
>>>  bestmove=0;
>>   roughbestmove = 0;
>>>  foreach (move in movelist) {
>>>    MakeMove();
>>     roughvalue = StaticEvaluate(-whatever,etc);
>>>    value=-Search(-beta,-alpha,etc.)
>>>    if (value > best) {
>>>      best=value;
>>>      bestmove=current.move;
>>>    }
>>>    if (value > alpha) {
>>>      if (value >= beta) {
>>>        return(value);
>>>      }
>>>      alpha=value;
>>>    }
>>     if (roughvalue > roughbest)
>>     {
>>       roughvalue = roughbest;
>>       roughbestmove = current.move;
>>     }
>>>  }
>>   if (THEREWASNTANEWALPHA)
>>     HastStore(roughbestmove, etc...)
>>   else
>>>    HashStore(bestmove,alpha, etc...)
>>>}
>>>
>>>
>>>
>>>So what I did was to simply take the score for each search made after trying
>>>one of the moves at this ply, and remember the 'best' score and associated move.
>>
>>So what you needed to do was think about having an semi-accurate evaluation
>>function at each internal node, rather than a search based quiesence score.
>>
>>
>>>
>>>All I am saying is "this does not work".  It is a characteristic of the alpha/
>>>beta search.  It isn't a "it might work if ..."  it simply won't work.  Because
>>>the searches below this node (again, assuming this is a fail-low node where _no_
>>>move produces a score > alpha, which is the case where I claim there is never a
>>>best move to try here) return a bound on the value for that move.  And I have no
>>>idea how to choose between a move with a bound <=200 and another move with a
>>>bound <= 150.  Because the first could have a score well below 200.  I simply
>>>don't know as I told the search below this node to stop whenever you find a
>>>score > X, where X is my negated alpha bound.
>>>
>>>Now, we have code.  Did I misunderstand what you are saying?  If not, then I
>>>can certainly explain further why that 'best' and 'bestmove' above are no good
>>>in this context.  You can think of "best" as a random number that is <= alpha,
>>>nothing more.  Which means "bestmove" is a random move chosen from the moves
>>>searched at this ply.  And that is _not_ the move we want to try first when we
>>>get back to this position and it is suddenly not a fail-low position where all
>>>moves have to be tried, but rather it is a fail high position where the best
>>>move will let us cut off quickly...
>
>
>That is worthless.  You are saying that you would try the best move suggested
>by your static evaluation there?  I say you are wasting a bunch of time.  And
>I don't think Ed uses his static eval as you suggest, although I could be wrong.
>
>I would _much_ prefer my simpler captures-first approach when I come back here,
>as that is much less expensive to compute than the static eval.  And in most
>cases it would be more accurate, since most moves are refuted directly by a
>simple capture...

Would the substitution of
    roughvalue = StaticEvaluate(-whatever,etc);
with
    roughvalue = Quiesce(-whatever, etc);
appease?

Dave



This page took 0.01 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.