(Have you got it yet?)
Matthew:out
Moderator: Ras
The fail low case is nonsense. Think about both alpha and beta beingZirconiumX wrote:I have examined my implementation, and hope this pseudo code may clear things up:
Code: Select all
void search() { InitEverything(); for (int depth = 1;;depth++) { if (depth <= 3) { alpha = -ValueInf; beta = +ValueInf; } else { alpha = last_search_value - 32; beta = last_search_value + 32; } alphabetaroot(); if (search_is_fail_high) { // This limits it to depth 4 depth -= 3; // This may well be the culprit } if (search_is_fail_low) { alpha *= 2; // /= 2??? beta *= 2; } } }
Code: Select all
void search() {
InitEverything();
low_aspiration_delta = 32;
high_aspiration_delta = 32;
for (int depth = 1;;depth++) {
if (depth <= 3) {
alpha = -ValueInf;
beta = +ValueInf;
} else {
alpha = last_search_value - low_aspiration_delta;
beta = last_search_value + high_aspiration_delta;
}
alphabetaroot();
if (search_is_fail_high) {
high_aspiration_delta *= 4;
depth--;
}
else if (search_is_fail_low) {
low_aspiration_delta *= 4;
depth--;
}
else {
low_aspiration_delta = 32;
high_aspiration_delta = 32;
}
}
}
Hi Matthew,ZirconiumX wrote:I have examined my implementation, and hope this pseudo code may clear things up:
So, the depth 4 search fails high, and the depth is reduced by three, giving me...a depth 1 search; maybe Robert Houdart has a minimum depth condition of >= 10. Since the depth 4 search finishes quickly, I only *just* see the depth 1 search, which sticks in my mind.Code: Select all
void search() { InitEverything(); for (int depth = 1;;depth++) { if (depth <= 3) { alpha = -ValueInf; beta = +ValueInf; } else { alpha = last_search_value - 32; beta = last_search_value + 32; } alphabetaroot(); if (search_is_fail_high) { // This limits it to depth 4 depth -= 3; // This may well be the culprit } if (search_is_fail_low) { alpha *= 2; // /= 2??? beta *= 2; } } }
Yes, I know, you cannot work with information you aren't given, but really Lucas and Vincent, what you said was unkind.
Matthew:out
Matthew:out
Code: Select all
1. Inside the rootsearch for the first move.
alphaBetaRoot()
{
...
while(moves)
{
if(moveNb == 1)
{
"INSERT HERE"
}
else
{
//handle all other moves
}
}
...
}
"INSERT HERE":
X: repeat
* set aspiration window
* search with Aspiration window
* Repeat search
- on fail lo (open window to lower bound)
- on fail hi (open window to upper bound)
* (refinement: the research must not open into the failed direction
completly, so you can jump to "X" and try it with a wider
window, 2,3 or 4 times before open the window completly)
HINT: for the first trials you should open the window for
the research completly (at least in the direction it failed)
HINT: i am not sure, but i think that is the classical approach of
using aspiration window technique. Get it to work, play around with it.
Code: Select all
iterationLoop()
{
aspirationLoop( exit when pv value (within alpha and beta) has been found)
{
setAlpha;
setBeta;
alphaBetaRoot(alpha,beta)
}
}
*
ok, you set the starting window to lastvalue +- 32.
ok, you TRY to widen something somehow (alpha *=2)
- how it should continue to handle the window ? when
- you would have such an "aspirationloop", how do you control that
the loop isnt infinite, and the computation for the bounds doesnt produce
ähhhmmm ;-) (pls check out how alpha and beta will change with your formular with each loop,
maybe it works somehow, but this must be figured out by yourself)
*
Why do you want to repeat the complete movelist (alphaBetaRoot()), unlike in
the classic concept only the first move ?? Do you know it ? Well, it is not intuitive !
- can it be better, then why ? (think about it a while...)
Code: Select all
void iterate()
{
//...
//ITERAION LOOP
for(ctl->iteration = onePly;!stopSearch(canStop);ctl->iteration += onePly)
{
// ... robbo, aspiration search...
if( ctl->iteration >= 14 && absN(lastValue)<OPENWINDOW)
{
// aspirationWindow
delta = 8;
aspiLo = guess - delta;
aspiHi = guess + delta;
// make sure technical bounds do not crash
// or simply decide to open fully a direction
// from a certain value on.
if( aspiLo < -OPENWINDOW ) aspiLo = lbound;
if( aspiHi > OPENWINDOW ) aspiHi = ubound;
// ASPIRATION LOOP
do
{
value = nodeRoot(pos,mliRoot,aspiLo,aspiHi,ctl->iteration,plyRoot);
// pv hit
if( value > aspiLo && value < aspiHi ) break;// goto END;
// handle fail lo
if( value <= aspiLo )
{
aspiLo -= delta;
delta += delta / 2;
guess = aspiLo;
}
// handle fail hi
else
{
aspiHi += delta;
delta += delta / 2;
guess = aspiHi;
}
}while(1);
}
else value = nodeRoot(pos,mliRoot,lbound,ubound,ctl->iteration,plyRoot);
//...
}
What I wanted to say is that the latter is not true. Because alpha won't stay -INF for the duration of the node. After the first move is search, you doasanjuan wrote:What I wanted to say is that if you do a search like this:The root node will be a PV node and a frontier node at the same time.Code: Select all
depth=1, alpha = -INF, beta= +INF
and imagine you have a condition before make a move like this:This contidion won't affect to anything, because you'll never enter inside the 'if'. Your alpha is -INF, so nothing is lower than this.Code: Select all
if (depth ==1 && board_eval + material_gain(move) + FUTILE_MARGIN < alpha) continue;
Code: Select all
if(score > alpha) alpha = score;
I think he mixed by accident 2 cases:hgm wrote:What I wanted to say is that the latter is not true. Because alpha won't stay -INF for the duration of the node. After the first move is search, you doasanjuan wrote:What I wanted to say is that if you do a search like this:The root node will be a PV node and a frontier node at the same time.Code: Select all
depth=1, alpha = -INF, beta= +INF
and imagine you have a condition before make a move like this:This contidion won't affect to anything, because you'll never enter inside the 'if'. Your alpha is -INF, so nothing is lower than this.Code: Select all
if (depth ==1 && board_eval + material_gain(move) + FUTILE_MARGIN < alpha) continue;
And if alpha starts as -INF you will certainly get into that if, and score will certainly be larger than -INF. In fact it could be board_eval + 950, and 950 is probably larger than FUTILE_MARGIN...Code: Select all
if(score > alpha) alpha = score;
Code: Select all
void iterate()
{
//...
//ITERAION LOOP
for(ctl->iteration = onePly;!stopSearch(canStop);ctl->iteration += onePly)
{
// ... robbo, aspiration search...
if( ctl->iteration >= 14 && absN(lastValue)<OPENWINDOW)
{
// aspirationWindow
delta = 8;
aspiLo = guess - delta;
aspiHi = guess + delta;
// ASPIRATION LOOP
do
{
// make sure technical bounds do not crash
// or simply decide to open fully a direction
// from a certain value on.
if( aspiLo < -OPENWINDOW ) aspiLo = lbound;
if( aspiHi > OPENWINDOW ) aspiHi = ubound;
value = nodeRoot(pos,mliRoot,aspiLo,aspiHi,ctl->iteration,plyRoot);
// pv hit
if( value > aspiLo && value < aspiHi ) break;
// handle fail lo
if( value <= aspiLo )
{
aspiLo -= delta;
delta += delta / 2;
guess = aspiLo;
}
// handle fail hi
else
{
aspiHi += delta;
delta += delta / 2;
guess = aspiHi;
}
}while(1);
}
//full window
else value = nodeRoot(pos,mliRoot,lbound,ubound,ctl->iteration,plyRoot);
//...
}
Code: Select all
void iterate()
{
//...
//ITERAION LOOP
for(ctl->iteration = onePly;!stopSearch(canStop);ctl->iteration += onePly)
{
// ... robbo, aspiration search...
if( ctl->iteration >= 14 && absN(guess)<OPENWINDOW)
{
// aspirationWindow
delta = 8;
aspiLo = guess - delta;
aspiHi = guess + delta;
// ASPIRATION LOOP
do
{
// make sure technical bounds do not crash
// or simply decide to open fully a direction
// from a certain value on.
if( aspiLo < -OPENWINDOW ) aspiLo = lbound;
if( aspiHi > OPENWINDOW ) aspiHi = ubound;
value = nodeRoot(pos,mliRoot,aspiLo,aspiHi,ctl->iteration,plyRoot);
// pv hit
if( value > aspiLo && value < aspiHi ) break;
// handle fail lo
if( value <= aspiLo )
{
aspiLo -= delta;
delta += delta / 2;
guess = aspiLo;
}
// handle fail hi
else
{
aspiHi += delta;
delta += delta / 2;
guess = aspiHi;
}
}while(1);
}
//full window
else value = nodeRoot(pos,mliRoot,lbound,ubound,ctl->iteration,plyRoot);
//...
}
well, at least one understood me1: first case is exactly what you describe
2: second case, if this node is started with aspiration bounds
and there might be no "score > alpha", or no other condition
that leads to a real value. (so the complete move loop may
be pruned ??!) and additionally no bestValue update in a
failsoft framework, then there might be an undefined phantom
score returned...
But bestValue starts at -INF, in a fail-soft framework, right? If you let it start as an uninitialized variable, it would almost always return phantom scores, because it will often start above alpha, or even beta, end thus never get updated.Desperado wrote:2: second case, if this node is started with aspiration bounds
and there might be no "score > alpha", or no other condition
that leads to a real value. (so the complete move loop may
be pruned ??!) and additionally no bestValue update in a
failsoft framework, then there might be an undefined phantom
score returned...![]()
Code: Select all
int search_full_root(list_t * list, board_t * board, int depth, int search_type) {
int value;
int alpha, beta;
int alpha_delta, beta_delta;
ASSERT(list_is_ok(list));
ASSERT(board_is_ok(board));
ASSERT(depth_is_ok(depth));
ASSERT(search_type==SearchNormal||search_type==SearchShort);
ASSERT(list==SearchRoot->list);
ASSERT(!LIST_IS_EMPTY(list));
ASSERT(board==SearchCurrent->board);
ASSERT(board_is_legal(board));
ASSERT(depth>=1);
alpha_delta = 32;
beta_delta = 32;
if (depth <= 3) {
value = full_root(list,board,-ValueInf,+ValueInf,depth,0,search_type);
} else {
do {
alpha = SearchRoot->last_value - alpha_delta;
beta = SearchRoot->last_value + beta_delta;
value = full_root(list,board,alpha,beta,depth,0,search_type);
if (false) {
} else if (value <= alpha) {
alpha_delta *= 4;
depth--;
} else if (value >= beta) {
beta_delta *= 4;
depth--;
} else break;
} while (true);
}
ASSERT(value_is_ok(value));
ASSERT(LIST_VALUE(list,0)==value);
return value;
}