Collecting the principal Variation

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

OK, finally I think I got it, touch wood.

OK I rejigged my use of the term ply a bit, this way seems more intuitive to me. It'll do for now anyway.

in alphaBeta search, ply goes from 1 to maxPly, when ply > maxPly evaluate() or qSearch() is called.

ok, so for PV all I have is a 2D array maxPly x maxPly, and my alpha updates look like this...

Code: Select all

if( eval > alpha ) {
    alpha = eval;
    PV[ply][ply] = m;
    for&#40; int j=ply+1; j<=maxPly; j++ ) &#123;
        PV&#91;ply&#93;&#91;j&#93; = PV&#91;ply+1&#93;&#91;j&#93;;
    &#125;
&#125;
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Collecting the principal Variation

Post by hgm »

That would do it. To save some time, you might not want to copy every time upto maxPly, but hide a marker indicating the end of the PV, and stop there:

Code: Select all

if&#40; eval > alpha ) &#123; 
    alpha = eval; 
    PV&#91;ply&#93;&#91;ply&#93; = m; 
    int j=ply+1; 
    while&#40; PV&#91;ply&#93;&#91;j&#93; = PV&#91;ply+1&#93;&#91;j&#93; ) j++; 
&#125; 
This assuming the PV ends with m == 0, which you put there on stand pat (when you have no best move).
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

hgm wrote:That would do it. To save some time, you might not want to copy every time upto maxPly, but hide a marker indicating the end of the PV, and stop there:

Code: Select all

if&#40; eval > alpha ) &#123; 
    alpha = eval; 
    PV&#91;ply&#93;&#91;ply&#93; = m; 
    int j=ply+1; 
    while&#40; PV&#91;ply&#93;&#91;j&#93; = PV&#91;ply+1&#93;&#91;j&#93; ) j++; 
&#125; 
This assuming the PV ends with m == 0, which you put there on stand pat (when you have no best move).
Yeah, I have noticed a few issues with the final move of a PV, I assumed it would be something easy to deal with and didn't give it a lot of thought.

Anyways, thanks for the help. Next step is to use PV with iterative deepening. Onwards and upwards.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Collecting the principal Variation

Post by Sven »

Fguy64 wrote:OK, finally I think I got it, touch wood.

OK I rejigged my use of the term ply a bit, this way seems more intuitive to me. It'll do for now anyway.

in alphaBeta search, ply goes from 1 to maxPly, when ply > maxPly evaluate() or qSearch() is called.

ok, so for PV all I have is a 2D array maxPly x maxPly, and my alpha updates look like this...

Code: Select all

if&#40; eval > alpha ) &#123;
    alpha = eval;
    PV&#91;ply&#93;&#91;ply&#93; = m;
    for&#40; int j=ply+1; j<=maxPly; j++ ) &#123;
        PV&#91;ply&#93;&#91;j&#93; = PV&#91;ply+1&#93;&#91;j&#93;;
    &#125;
&#125;
If your 'ply' goes from 1 to maxPly then with this code you are off by one, since your PV array has dimensions [maxPly][maxPly] so legal indices for both dimensions are 0..maxPly-1. Therefore your loop termination implies that you will get an illegal access to PV[whatever][maxPly].

A possible fix would be to define that your 'ply' starts at 0, and that your loop condition becomes 'j<maxPly'. You should check carefully the implications for your program of letting 'ply' start at 0, though. In your case 'ply==0' would mean 'root node'.

Sven
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

Sven Schüle wrote:
Fguy64 wrote:OK, finally I think I got it, touch wood.

OK I rejigged my use of the term ply a bit, this way seems more intuitive to me. It'll do for now anyway.

in alphaBeta search, ply goes from 1 to maxPly, when ply > maxPly evaluate() or qSearch() is called.

ok, so for PV all I have is a 2D array maxPly x maxPly, and my alpha updates look like this...

Code: Select all

if&#40; eval > alpha ) &#123;
    alpha = eval;
    PV&#91;ply&#93;&#91;ply&#93; = m;
    for&#40; int j=ply+1; j<=maxPly; j++ ) &#123;
        PV&#91;ply&#93;&#91;j&#93; = PV&#91;ply+1&#93;&#91;j&#93;;
    &#125;
&#125;
If your 'ply' goes from 1 to maxPly then with this code you are off by one, since your PV array has dimensions [maxPly][maxPly] so legal indices for both dimensions are 0..maxPly-1. Therefore your loop termination implies that you will get an illegal access to PV[whatever][maxPly].

A possible fix would be to define that your 'ply' starts at 0, and that your loop condition becomes 'j<maxPly'. You should check carefully the implications for your program of letting 'ply' start at 0, though. In your case 'ply==0' would mean 'root node'.

Sven
right, I was a little careless with my post. in fact my array is defined with dimension maxPly+1. Else I get stopped pretty quick by ArrayIndexOutOfBounds runtime errors.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Collecting the principal Variation

Post by Sven »

O.k., so in this case, what does "ply == 0" mean in your program? It seems either that your root node has "ply == 1", or that you are doing full-width search always one ply deeper than you think you do. You wrote that you call (evaluate or) qsearch if "ply > maxPly", so with "ply == maxPly" you do full-width search, right?

Sven
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

ply==0 means nothing at all at the moment, that space in the array is unused, because my iterative deepening loop goes from 1 to maxPly inclusive.

In my iterative deepening scheme, iPly is my iteration variable, and is defined as a class variable as opposed to a local variable. So from within my ID loop, with each iteration 1 gets passed to alphaBeta, then in alphaBeta ply goes from 1 to iPly inclusive, and evaluate or qSearch is called when ply > iPly.

I find this numbering scheme requires less mental gymnastics for me. Once I am convinced that evrything works ok, I may or may not tighten things up a bit and eliminate unneeded array space.

p.s. I should add that all this will be revised a bit when it comes time to implement time control, which as i see it is one of the big advantages of ID.
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

OK so I am playing with iterative deepening, and searching the principal variation first. I am still searching to a fix depth, and am testing without qSearch.

So far in my test positions, the same "best move" is found for a given search depth, and so far the eval and the final PV are the same, most of the time. But I have found an occasional position in which the same initial "best move" was found, but with a different eval and PV, which came as a surprise. The give PV was reasonable, no obvious mistakes, but just different.

So, does this mean something is wrong? I would have expected that since I was still searching fixed depth without Q, that the PV and evals should be identical to those for my tests without Iterative deepening.

regards.
User avatar
hgm
Posts: 27808
Joined: Fri Mar 10, 2006 10:06 am
Location: Amsterdam
Full name: H G Muller

Re: Collecting the principal Variation

Post by hgm »

If you have no hash table, or move-order-dependent reductions, scores shoud be exactly the same. So yes, something must be wrong. The PV could be different if you end up in the same node, or in nodes that accidentally have exactly the same score.
Fguy64
Posts: 814
Joined: Sat May 09, 2009 4:51 pm
Location: Toronto

Re: Collecting the principal Variation

Post by Fguy64 »

hmm, something is not quite right with the way i am dealing with mate scores i suspect. Or maybe it is a beta cutoff issue. Things were fine without playing Playing PV first, but using PV introduces the occasional problem.

I just found a position which returned a PV with the same initial move, but a reply which leads to mate in 3, where in fact there was a reply which led to mate in 4, a reply which involved a subsequent useless dummy check away from the action to delay the inevitable by one move.

The only other obvious problem was a position whereby in the non-ID scheme the engine offered up a dummy sac in one line to delay the inevitable by one move. There are mates in here too, although not forced.

But this is 2 out of 20 positions where there was as problem. The others are fine.