Stockfish can't evaluate the KP vs K endgame?

Discussion of anything and everything relating to chess playing software and machines.

Moderators: hgm, Rebel, chrisw

User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Stockfish can't evaluate the KP vs K endgame?

Post by lucasart »

lucasart wrote:
Michel wrote:GNU Chess uses the single repetion rule only for repetions occurring within the search. For repetitions involving the games history it uses the threefold repetition rule. So it analyzes this position correctly.
This is interesting. I was just reading that thread, and realizing that DiscoCheck would have the same problem as SF -- if only it had a KPK bitbase.

And the good news is that it can be implemented without any measurable cost in the general case.
I commited the bugfix in DiscoCheck
https://github.com/lucasart/chess/commi ... 23ac5ac811
What's very important is that there is no (measurable) speed penalty, so it wouldn't hurt elo in anyway.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: Stockfish can't evaluate the KP vs K endgame?

Post by rvida »

lucasart wrote: I commited the bugfix in DiscoCheck
https://github.com/lucasart/chess/commi ... 23ac5ac811
What's very important is that there is no (measurable) speed penalty, so it wouldn't hurt elo in anyway.
This is a dangerous assumption. This patch makes the search space a bit larger when playing real games. No way to tell it won't hurt elo until you test with games. It may very well be a regression.

off-topic: Looking at this particular loop, it seems you are making the life quite hard for the gcc optimizer ;)
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Stockfish can't evaluate the KP vs K endgame?

Post by lucasart »

rvida wrote:
lucasart wrote: I commited the bugfix in DiscoCheck
https://github.com/lucasart/chess/commi ... 23ac5ac811
What's very important is that there is no (measurable) speed penalty, so it wouldn't hurt elo in anyway.
This is a dangerous assumption. This patch makes the search space a bit larger when playing real games. No way to tell it won't hurt elo until you test with games. It may very well be a regression.

off-topic: Looking at this particular loop, it seems you are making the life quite hard for the gcc optimizer ;)
You make a valid point. My speed measure was done with an initially empty search stack. In real games, this means often looking back at the stack all the way down to the initial position. I am running a non regression test to be on the safe side.

Regargind the GCC optimization, I'm not sure what you mean. Here is the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		rep += sp&#91;-i&#93;.key == st&#40;).key;
		if &#40;rep >= 2 + &#40;sp-i < sp0&#41;)
			return true;
	&#125;
where sp is the current stack pointer and sp0 the stack pointer value at the root position.

How would you rewrite that to make life easier for the optimizer ? And why ?
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Stockfish can't evaluate the KP vs K endgame?

Post by Sven »

lucasart wrote:
rvida wrote:off-topic: Looking at this particular loop, it seems you are making the life quite hard for the gcc optimizer ;)
Regargind the GCC optimization, I'm not sure what you mean. Here is the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		rep += sp&#91;-i&#93;.key == st&#40;).key;
		if &#40;rep >= 2 + &#40;sp-i < sp0&#41;)
			return true;
	&#125;
where sp is the current stack pointer and sp0 the stack pointer value at the root position.

How would you rewrite that to make life easier for the optimizer ? And why ?
Maybe Richard meant that gcc won't find much more to optimize in that particular loop ....
bob
Posts: 20943
Joined: Mon Feb 27, 2006 7:30 pm
Location: Birmingham, AL

Re: Stockfish can't evaluate the KP vs K endgame?

Post by bob »

Uri Blass wrote:
bob wrote:
JVMerlino wrote:
JVMerlino wrote: Unless I'm mistaken, I think you might have missed the initial point of the thread, with all of the other stuff that has been discussed. The point is that in the initial position the move Kf6 was forced and that SF THEN scored the position as draw, because the only way to win is to go back to the initial position, which most engines score as a draw because they have seen one repetition.

And I just confirmed this same behavior in Crafty 23.5. Setting the position, using "analyze" and then forcing Kf6 produces a -0.01 score up through depth 60, which it reaches in 1.42 seconds. Changing Crafty so that, if in analysis mode, it requires two reps to declare draw, will fix the problem.

jm
Ok, I think I have to retract the above because if you make that change then the behavior of the engine between analysis and "normal search" modes can be drastically different. Fine 70 is an obvious example. Since I use analysis mode for various test positions, making this change to the code would defeat the purpose of analysis mode.

So the other solution presented in this thread by Michel Van den Bergh is indeed correct.

Sorry for the confusion,
jm
BTW, didn't you mean "change crafty so that analysis requires THREE reps for a draw"?? It already does the 2-reps == draw everywhere in the search, analysis mode or not.
I think that it already evaluates first repetition as a draw.
The word repetition means that the position happened at least twice.
Then what is "three-fold repetition"? :)
Michel
Posts: 2272
Joined: Mon Sep 29, 2008 1:50 am

Re: Stockfish can't evaluate the KP vs K endgame?

Post by Michel »

, this means often looking back at the stack all the way down to the initial position.
More precisely to the last irreversible move. You will have to do that often anyway even with the two fold repetition rule (in case there is no repetition).

For positions in the game history you could in principle xor 1 with the hash key on the stack to indicate a two fold repetition. This avoids having to go all the way down to the base of the stack. I suspect this optimization is not worth it however.
Sven
Posts: 4052
Joined: Thu May 15, 2008 9:57 pm
Location: Berlin, Germany
Full name: Sven Schüle

Re: Stockfish can't evaluate the KP vs K endgame?

Post by Sven »

Sven Schüle wrote:
lucasart wrote:
rvida wrote:off-topic: Looking at this particular loop, it seems you are making the life quite hard for the gcc optimizer ;)
Regargind the GCC optimization, I'm not sure what you mean. Here is the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		rep += sp&#91;-i&#93;.key == st&#40;).key;
		if &#40;rep >= 2 + &#40;sp-i < sp0&#41;)
			return true;
	&#125;
where sp is the current stack pointer and sp0 the stack pointer value at the root position.

How would you rewrite that to make life easier for the optimizer ? And why ?
Maybe Richard meant that gcc won't find much more to optimize in that particular loop ....
The code above may run into trouble when starting search from a position given by FEN with "rule50" set to a value >= 4. As long as only reversible moves were made on the current path, "sp[-i].key" may be an illegal access since the stack size is actually smaller than "rule50". So it would be safer to calculate the loop termination condition from the minimum of "rule50" and the total length of the game from its starting position.

Sven
User avatar
Don
Posts: 5106
Joined: Tue Apr 29, 2008 4:27 pm

Re: Stockfish can't evaluate the KP vs K endgame?

Post by Don »

Uri Blass wrote:Nothing to do with evaluation of pawn endgames.

It is obvious that it is about evaluating first repetition and many engines evaluate first repetition as a draw because they are designed to play and not to analyze correctly and the programmers did not want to add code that is probably not productive for playing strength.

It is a disadvantage of the program but
I do not think that it is a bug because a bug is a behaviour that is different than the intention of the programmer.
Program authors have struggled with this for years - i.e. what to do with respect to repetition. There is pretty much a consensus to evaluate the first repetition as a draw as it does contribute to the strength. If you do not do it that way and you NEED a draw you may take several more ply to see it or you may allow the opponent to get a draw when you could win.

The 3-fold repetition rule is arbitrary anyway. Why 3? Why not 2 or 4? In principle if you are the one to repeat you are offering a draw - although you can change your mind or use it as a tactic with the 3-fold rule.
Capital punishment would be more effective as a preventive measure if it were administered prior to the crime.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Stockfish can't evaluate the KP vs K endgame?

Post by lucasart »

Sven Schüle wrote:
Sven Schüle wrote:
lucasart wrote:
rvida wrote:off-topic: Looking at this particular loop, it seems you are making the life quite hard for the gcc optimizer ;)
Regargind the GCC optimization, I'm not sure what you mean. Here is the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		rep += sp&#91;-i&#93;.key == st&#40;).key;
		if &#40;rep >= 2 + &#40;sp-i < sp0&#41;)
			return true;
	&#125;
where sp is the current stack pointer and sp0 the stack pointer value at the root position.

How would you rewrite that to make life easier for the optimizer ? And why ?
Maybe Richard meant that gcc won't find much more to optimize in that particular loop ....
The code above may run into trouble when starting search from a position given by FEN with "rule50" set to a value >= 4. As long as only reversible moves were made on the current path, "sp[-i].key" may be an illegal access since the stack size is actually smaller than "rule50". So it would be safer to calculate the loop termination condition from the minimum of "rule50" and the total length of the game from its starting position.

Sven
Thanks! You just spotted a nasty bug. Actually DiscoCheck has had this bug all along :wink:
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
User avatar
rvida
Posts: 481
Joined: Thu Apr 16, 2009 12:00 pm
Location: Slovakia, EU

Re: Stockfish can't evaluate the KP vs K endgame?

Post by rvida »

lucasart wrote: Regargind the GCC optimization, I'm not sure what you mean. Here is the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		rep += sp&#91;-i&#93;.key == st&#40;).key;
		if &#40;rep >= 2 + &#40;sp-i < sp0&#41;)
			return true;
	&#125;
where sp is the current stack pointer and sp0 the stack pointer value at the root position.

How would you rewrite that to make life easier for the optimizer ? And why ?
1. In tight loops don't do more calculations than absolutely necessary. Here the "rep >= 2 + (sp-i < sp0)" condition is evaluated even when the keys don't match. I'm not sure the optimizer is smart enough to optimize this. I would rather rearrange the code:

Code: Select all

	for &#40;int i = 4, rep = 1; i <= st&#40;).rule50; i += 2&#41; &#123;
		if &#40;sp&#91;-i&#93;.key == st&#40;).key&#41; &#123;
			if (++rep >= 2 + &#40;sp-i < sp0&#41;)
				return true;
		&#125;
	&#125;
2. Problematic pointer arithmetic in 64bit environment: Compiler must insert an extra int => ptrdiff_t conversion at each loop iteration. Declaring i as ptrdiff_t might produce better 64bit code.