Razoring / Lazy eval question

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

jd1
Posts: 269
Joined: Wed Oct 24, 2012 2:07 am

Razoring / Lazy eval question

Post by jd1 »

Hi,

I have a question:

When Razoring, I understand some programs (such as Toga II) call the evaluation and check whether it is less than (beta - RazorMargin) as one condition.

Lazy Evaluation is done (as in Toga) by passing alpha & beta to the evaluation and checking whether lazy value > beta + margin or < alpha + margin.

When calling eval() for razoring, should (alpha, beta) be passed into the eval() function as normal, or does it make sense to pass (beta - RazorMargin, beta - RazorMargin+1)?

It seems that the evaluation value found here is not used again, and if we are only using the evaluation to decide whether or not to use razoring, I would have thought that if

lazy value > beta - RazorMargin + margin
or
lazy value < beta - RazorMargin - margin

it should be safe to return from eval() here as we already know what the decision will be. Am I right or horribly mistaken?

Thanks for all your help.

Jerry
syzygy
Posts: 5566
Joined: Tue Feb 28, 2012 11:56 pm

Re: Razoring / Lazy eval question

Post by syzygy »

jd1 wrote:it should be safe to return from eval() here as we already know what the decision will be. Am I right or horribly mistaken?
Sounds right to me, as long as the value returned by eval() is used only for the razoring check and for nothing else.
User avatar
Eelco de Groot
Posts: 4567
Joined: Sun Mar 12, 2006 2:40 am
Full name:   

Re: Razoring / Lazy eval question

Post by Eelco de Groot »

Too lazy to look up the code so what I am saying can be totally nonsensical :oops: From general principle if in razoring the quiescense is called with those parameters (beta - RazorMargin, beta - RazorMargin+1) these can also be used for Lazy Eval. If I understand right that was more or less the idea Jerry?

But I do not really like lazy eval I think; if preliminary eval is way above beta it is okay because you will stand pat (in this case though in Stockfish it would fall under static null move pruning, not sure how this is done in Toga), but if if is below, quiescence search might still go up enough to cross beta so I think you would need a pretty large margin to safely stop evaluating early? It does not make much sense to me to have these, theoretically, very asymmetrical margins, I may be very wrong but in the case of Toga, and your example code, it does not sound as if there are two asymmetrical margins?

Sorry Jerry but I can't remember anything at all about ever having seen a lazy eval in Toga, who invented that :P

Regards, Eelco
Debugging is twice as hard as writing the code in the first
place. Therefore, if you write the code as cleverly as possible, you
are, by definition, not smart enough to debug it.
-- Brian W. Kernighan
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Razoring / Lazy eval question

Post by lucasart »

jd1 wrote: When Razoring, I understand some programs (such as Toga II) call the evaluation and check whether it is less than (beta - RazorMargin) as one condition.
Maybe Toga does it, but it's pretty dumb idea. I suggest you use the qsearch instead, and the eval only as a precondition for speedup.

Here's my razoring code in DiscoCheck to give you an idea:

Code: Select all

	// Razoring
	if &#40;UseRazoring && depth <= RazorDepth
		&& !is_pv && !is_mate_score&#40;beta&#41; && !in_check&#41;
	&#123;
		const int threshold = beta - RazorMargin&#40;depth&#41;;
		if &#40;current_eval < threshold&#41; &#123;
			const int score = qsearch&#40;B, threshold-1, threshold, 0, ply+1, is_pv, si+1&#41;;
			if &#40;score < threshold&#41;
				return score;
		&#125;
	&#125;
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
syzygy
Posts: 5566
Joined: Tue Feb 28, 2012 11:56 pm

Re: Razoring / Lazy eval question

Post by syzygy »

lucasart wrote:Maybe Toga does it, but it's pretty dumb idea.
Funny that you immediately call it dumb, because your program does the same as Toga:

Code: Select all

if&#40;node_type != NodePV && depth <= RazorDepth &&  eval&#40;board,alpha, beta, ThreadId&#41; < beta - RazorMargin&#41;&#123;
		value = full_quiescence&#40;board,alpha,beta,0,height,pv,ThreadId&#41;;
      if&#40;value < beta&#41;
        return value;
   &#125;
As "one condition", the static eval is compared to beta - RazorMargin.
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Razoring / Lazy eval question

Post by lucasart »

syzygy wrote:
lucasart wrote:Maybe Toga does it, but it's pretty dumb idea.
Funny that you immediately call it dumb, because your program does the same as Toga:

Code: Select all

if&#40;node_type != NodePV && depth <= RazorDepth &&  eval&#40;board,alpha, beta, ThreadId&#41; < beta - RazorMargin&#41;&#123;
		value = full_quiescence&#40;board,alpha,beta,0,height,pv,ThreadId&#41;;
      if&#40;value < beta&#41;
        return value;
   &#125;
As "one condition", the static eval is compared to beta - RazorMargin.
I didn't look at Toga's source code, just read the post, which talked about razoring based on the eval only. My point is that:
- pruning if eval < beta - razor_margin is not a good idea
- better to use at least a qsearch, rather than an eval
- however, qsearch is a costly calcualtion, so the eval as a *pre*condition is probably best
It seems to be what everyone does nowadays, no ?

Regarding Toga, I would point two important differences with DiscoCheck:
- Toga uses (alpha, beta) as bounds for the full_quiescence(). Not sure it's a good idea. We just want to test if the qsearch is <= beta-RazorMargin.
- Toga RazorMargin which is a constant independant of depth. IMO RazorMargin should be an increasing function of depth.

Anyway, razoring is not an exact science, but a heuristic with a gain/pain ratio to optimize.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
jd1
Posts: 269
Joined: Wed Oct 24, 2012 2:07 am

Re: Razoring / Lazy eval question

Post by jd1 »

Thanks to everyone for their informative and helpful replies.

Lucas, the eval is only a pre-condition for razoring. Sorry if that wasn't clear in the original post.
Jerry
User avatar
lucasart
Posts: 3232
Joined: Mon May 31, 2010 1:29 pm
Full name: lucasart

Re: Razoring / Lazy eval question

Post by lucasart »

jd1 wrote:Thanks to everyone for their informative and helpful replies.

Lucas, the eval is only a pre-condition for razoring. Sorry if that wasn't clear in the original post.
Jerry
No worries. But to answer your question, I think you're right, Toga does it wrong:
- let threshold = beta - RazorMargin
- the lazy eval should use the bounds (threshold-1,threshold). I don't use lazy eval, and haven't looked at Toga's lazy eval, but if it does what it should, it means that the eval(alpha, beta) is *potentially* capped by beta and floored by alpha.
- and, as I pointed out in my previous post, the same applies to the qsearch call. This is a far more serious mistake (I did it before, and when I fixed it, there was an elo gain comparable to the elo gain of razoring itself).

So I would recommend:
- use the correct bounds, both for the lazy eval and the qsearch
- use a RazorMargin which is an increasing function of depth, not a constant.
Theory and practice sometimes clash. And when that happens, theory loses. Every single time.
jd1
Posts: 269
Joined: Wed Oct 24, 2012 2:07 am

Re: Razoring / Lazy eval question

Post by jd1 »

Hi Lucas,

Yes, I totally agree with you. I will change it as you say and test. Thanks for your help -it's great to get advice from experienced programmers :D

Jerry
diep
Posts: 1822
Joined: Thu Mar 09, 2006 11:54 pm
Location: The Netherlands

Re: Razoring / Lazy eval question

Post by diep »

jd1 wrote:Hi,

I have a question:

When Razoring, I understand some programs (such as Toga II) call the evaluation and check whether it is less than (beta - RazorMargin) as one condition.

Lazy Evaluation is done (as in Toga) by passing alpha & beta to the evaluation and checking whether lazy value > beta + margin or < alpha + margin.

When calling eval() for razoring, should (alpha, beta) be passed into the eval() function as normal, or does it make sense to pass (beta - RazorMargin, beta - RazorMargin+1)?

It seems that the evaluation value found here is not used again, and if we are only using the evaluation to decide whether or not to use razoring, I would have thought that if

lazy value > beta - RazorMargin + margin
or
lazy value < beta - RazorMargin - margin

it should be safe to return from eval() here as we already know what the decision will be. Am I right or horribly mistaken?

Thanks for all your help.

Jerry
In any pruning decision at the leaves - lazy evaluation doesn't work for Diep.

Suppose that you search 30 plies deep. then the entire decision after that 30 plies is based upon lazy evaluation. That means that a few generic rules overrule a huge sophisticated evaluation function - which is not acceptable.