obvious/easy move

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: obvious/easy move

Post by bob »

JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: obvious/easy move - final results

Post by bob »

JBNielsen wrote:
bob wrote:
OK, this is one of those GOOD exampls of why you should not draw conclusions after even 8500 games. Here is the 30K game final results:

Code: Select all


   2 Crafty-23.6-1        2652    4    4 30000   62%  2557   25%
   3 Crafty-23.6R02-1     2651    4    4 30000   62%  2557   25%
In short, no measurable difference with ponder = off.
Perhaps it is a good example of that 30K is not enough :wink:
Or an error has occured - are the programs different?

It could be interesting to change an engine so it gave these informations:

How much time is saved by playing easy moves fast?
How often would it play the same move with a normal use of time?
When the moves differs, what is the difference in the scores (how many centipawns are lost)?

I once did this, but not on a cluster test. But all I was interested in was "if a move was flagged as easy, did it (a) meet the criteria to remain easy (no fail lows up to 1/3 of the target time) and (b) did it remain best if the search was carried through to the normal target time.

When I tested what I do right now, the answer was "yes" to both for every case where "easy-move" was triggered. Earlier versions had a more relaxed method of flagging moves as "easy" and they had some problems...



And then evt. try to open up for more timesavings if there are only 2 or 3 good moves...


- - -

Another issue about timedisposition.
I have always avoided to start a new iteration, if it probably will stop the search after examining only one move. It takes a long time to examine the first move, and it is the same move as we found in the previous iteration.
But it gives the option to extend the search if the move turns out to be bad, though.
Is it right to do it this way?!
The error bar is down to +/- 4. The only thing that changed was that version 23.6R02 had the "easy-move" code disabled. Trivial change.

I don't like the idea of stopping a search if there appears to be insufficient time to do another iteration. Why? A fail-low is FAR faster than a normal search, so you can quickly discover that your "best move" is not so good, and then allocate more time to solve the problem. I have seen quite a few positions over the years where this helps. Not starting the next iteration doesn't save anything except for a little clock time, the search effort is saved through the trans table so when the search stops at time-out, you pick back up at almost the same place after making the move and starting the ponder search.
JBNielsen
Posts: 267
Joined: Thu Jul 07, 2011 10:31 pm
Location: Denmark

Re: obvious/easy move

Post by JBNielsen »

bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: obvious/easy move

Post by bob »

JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Here's the problem.

If you disable alpha/beta at the root, you incur HUGE cost.

What I do is that I order the root moves (before I start the first iteration) by making each move, one at a time, and then calling Quiesce() to get a rough approximation of the resulting position's material balance. Does the move outright hang a piece (not just the moving piece either, since if the moving piece is lost, Quiesce() will instantly see it, but also if your queen is attacked, and you move something else, Quiesce() will instantly see that the queen can be captured)? For the initial ordering, I have basically zero-ply searches for each move (quiesce() is always called with {-inf,+inf} as the window so that I get a real score.

I then order based on these scores. Cost is trivial. From this point forward, my only question is, "is there one move that is better than all the rest by a 2 pawn margin?" If so, it is flagged as easy. If, at any point in the ensuing search another best move is found, or this "easy move" fails low, I turn "easy" off and do a normal search, because in either case, it suddenly doesn't seem to be such an obvious move that I can save some time by a shorter search.

But beyond that initial ordering, and the resulting easy_move flag being set (or not) I do not look at the scores, because I only get a score for the best move, which hopefully remains the "easy move". If not, The search just reverts to a normal search as if "easy" was never set at all.

This is all done before iteration #1 (depth = 1) search is started. Once the first iteration is started, the only thing that can happen (assuming "easy" is set) is that the "easy" flag can be reset, and it will stay reset until the next opportunity (not on this search or any iteration remaining on this same position).
jd1
Posts: 269
Joined: Wed Oct 24, 2012 2:07 am

Re: obvious/easy move

Post by jd1 »

JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Another idea might be to run the first few iterations (e.g. until depth 4) with a -ValueInf, +ValueInf window for each root move. That probably won't slow the engine down much as it is very quick to get to depth 4, and we now have the "real" score for each move at depth 4.

Jerry
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: obvious/easy move

Post by bob »

jd1 wrote:
JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Another idea might be to run the first few iterations (e.g. until depth 4) with a -ValueInf, +ValueInf window for each root move. That probably won't slow the engine down much as it is very quick to get to depth 4, and we now have the "real" score for each move at depth 4.

Jerry
You would have to be VERY careful there. A normal search, today, is on the order of 25+ plies. How much correlation is there between a 4 ply search and the final 25 ply value? VERY low I would imagine. Which is why caution on this "easy move" logic is the key. If you do a shallow search and find a single move is much better, and it NEVER fails low over some fixed amount of time, your confidence that it is not going to fail low increases, iteration by iteration. Until such point as you feel comfortable that additional iterations are NOT going to change the best move. I chose 1/3 of the target time for my "easy move search time". I did NOT try to tune this, and that might actually be an interesting cluster test.
JBNielsen
Posts: 267
Joined: Thu Jul 07, 2011 10:31 pm
Location: Denmark

Re: obvious/easy move

Post by JBNielsen »

bob wrote:
JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Here's the problem.

If you disable alpha/beta at the root, you incur HUGE cost.

What I do is that I order the root moves (before I start the first iteration) by making each move, one at a time, and then calling Quiesce() to get a rough approximation of the resulting position's material balance. Does the move outright hang a piece (not just the moving piece either, since if the moving piece is lost, Quiesce() will instantly see it, but also if your queen is attacked, and you move something else, Quiesce() will instantly see that the queen can be captured)? For the initial ordering, I have basically zero-ply searches for each move (quiesce() is always called with {-inf,+inf} as the window so that I get a real score.

I then order based on these scores. Cost is trivial. From this point forward, my only question is, "is there one move that is better than all the rest by a 2 pawn margin?" If so, it is flagged as easy. If, at any point in the ensuing search another best move is found, or this "easy move" fails low, I turn "easy" off and do a normal search, because in either case, it suddenly doesn't seem to be such an obvious move that I can save some time by a shorter search.

But beyond that initial ordering, and the resulting easy_move flag being set (or not) I do not look at the scores, because I only get a score for the best move, which hopefully remains the "easy move". If not, The search just reverts to a normal search as if "easy" was never set at all.

This is all done before iteration #1 (depth = 1) search is started. Once the first iteration is started, the only thing that can happen (assuming "easy" is set) is that the "easy" flag can be reset, and it will stay reset until the next opportunity (not on this search or any iteration remaining on this same position).
I will not disable cutoff at the root. Only in one of the runs of testpositions. Perhaps you misunderstood me.

I saw in your other post that you go for 1/3 of the movetime. I think 1/12 would be a good start to try to gain a little elo :)

I will try to allow my engine to do the next iteration no matter it is likely to just examine one move. Thanks for the input.

And thanks for the explanation about your search. I could try something similar by suspending cutoffs at the root in iteration 1... Isn't it much the same?!
Do you keep this moveorder in the next iterations no matter the scores that has rejected the following moves or how many nodes have been spent on the moves?
Of course the order changes if there comes another best move.
If fx iteration 5 gives that both move 1, 5 and 12 are the new best moves - then iteration 6 will start with move 12.
But what is the order of the remaining moves?
User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 4:27 pm

Re: obvious/easy move - final results

Post by Don »

AlvaroBegue wrote:
bob wrote:OK, this is one of those GOOD exampls of why you should not draw conclusions after even 8500 games. Here is the 30K game final results:

Code: Select all


   2 Crafty-23.6-1        2652    4    4 30000   62%  2557   25%
   3 Crafty-23.6R02-1     2651    4    4 30000   62%  2557   25%
In short, no measurable difference with ponder = off.
That's exactly what I suspected. This type of thing doesn't happen very often, and when it does it just saves a bit of time, so the improvement would be similar to a very minor speed up (say, 1%), which I don't expect to be measurable in ELO.

Thanks for running this!
The ELO gain from doing this in Komodo is surprisingly large, so large we don't need thousands of games to see it clearly. It is on the order of 25 ELO.

It's not done in any way described here.
Capital punishment would be more effective as a preventive measure if it were administered prior to the crime.
jd1
Posts: 269
Joined: Wed Oct 24, 2012 2:07 am

Re: obvious/easy move

Post by jd1 »

bob wrote:
jd1 wrote:
JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Another idea might be to run the first few iterations (e.g. until depth 4) with a -ValueInf, +ValueInf window for each root move. That probably won't slow the engine down much as it is very quick to get to depth 4, and we now have the "real" score for each move at depth 4.

Jerry
You would have to be VERY careful there. A normal search, today, is on the order of 25+ plies. How much correlation is there between a 4 ply search and the final 25 ply value? VERY low I would imagine. Which is why caution on this "easy move" logic is the key. If you do a shallow search and find a single move is much better, and it NEVER fails low over some fixed amount of time, your confidence that it is not going to fail low increases, iteration by iteration. Until such point as you feel comfortable that additional iterations are NOT going to change the best move. I chose 1/3 of the target time for my "easy move search time". I did NOT try to tune this, and that might actually be an interesting cluster test.
Apologies for the confusion, of course any fail-low of the easy move will disqualify the easy move candidate. Fruit/Toga have 1/5 of the target for the "easy move search time" with a threshold of 150. Would be interesting to see what optimal settings in Crafty are.

Jerry
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: obvious/easy move

Post by bob »

JBNielsen wrote:
bob wrote:
JBNielsen wrote:
bob wrote:
JBNielsen wrote:
lucasart wrote:
JBNielsen wrote: y = the number of moves (max 3) that are z centipawns better than the rest.
z is the biggest gap among the 4 best moves. z is max 3.00.
And how do you calculate that ?
Once you search the first move alpha is raised!
"My engine is probably not written the standard way. I started it 18 years ago based on what I had read and my intuition and logic.
When a white move at the root is refused by a given black move, I store the score for the move that gave the cuf-off."

It is copied from this thread
http://www.talkchess.com/forum/viewtopi ... =&start=10
How do you know the score? You really only get a bound back when a move is refuted. NOTHING says the refutation move is "the best move". It is just one good enough to refute the preceding move.
I know.

Perhaps the relation between the score and the real score is too far away to be usefull.
I might try it to examine that in a number of testpositions (someone has probably done that before...).
My engine already has an option to turn cuf-offs off at the root.
So I can simply run the positions with the option on and off and then compare the results.

This might also help to find rules for guessing the next best move based on the scores/nodes to get a better move ordering.
Here's the problem.

If you disable alpha/beta at the root, you incur HUGE cost.

What I do is that I order the root moves (before I start the first iteration) by making each move, one at a time, and then calling Quiesce() to get a rough approximation of the resulting position's material balance. Does the move outright hang a piece (not just the moving piece either, since if the moving piece is lost, Quiesce() will instantly see it, but also if your queen is attacked, and you move something else, Quiesce() will instantly see that the queen can be captured)? For the initial ordering, I have basically zero-ply searches for each move (quiesce() is always called with {-inf,+inf} as the window so that I get a real score.

I then order based on these scores. Cost is trivial. From this point forward, my only question is, "is there one move that is better than all the rest by a 2 pawn margin?" If so, it is flagged as easy. If, at any point in the ensuing search another best move is found, or this "easy move" fails low, I turn "easy" off and do a normal search, because in either case, it suddenly doesn't seem to be such an obvious move that I can save some time by a shorter search.

But beyond that initial ordering, and the resulting easy_move flag being set (or not) I do not look at the scores, because I only get a score for the best move, which hopefully remains the "easy move". If not, The search just reverts to a normal search as if "easy" was never set at all.

This is all done before iteration #1 (depth = 1) search is started. Once the first iteration is started, the only thing that can happen (assuming "easy" is set) is that the "easy" flag can be reset, and it will stay reset until the next opportunity (not on this search or any iteration remaining on this same position).
I will not disable cutoff at the root. Only in one of the runs of testpositions. Perhaps you misunderstood me.

I saw in your other post that you go for 1/3 of the movetime. I think 1/12 would be a good start to try to gain a little elo :)

I will try to allow my engine to do the next iteration no matter it is likely to just examine one move. Thanks for the input.

And thanks for the explanation about your search. I could try something similar by suspending cutoffs at the root in iteration 1... Isn't it much the same?!
Do you keep this moveorder in the next iterations no matter the scores that has rejected the following moves or how many nodes have been spent on the moves?
Of course the order changes if there comes another best move.
If fx iteration 5 gives that both move 1, 5 and 12 are the new best moves - then iteration 6 will start with move 12.
But what is the order of the remaining moves?
no. I order the moves before iteration #1 by using the actual scores returned from a q-search for each move. But after that, I simply make sure the "best move" is first, the rest are ordered by the per-move node counts obtained as the search is completed...