Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
Centipawns and Millipawns
Moderators: hgm, Rebel, chrisw
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Centipawns and Millipawns
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Centipawns and Millipawns
I think the conclusion for that is that your values are probably reasonably tuned. I have seen some programs where every score is an even number, for example, so that the rightmost bit is never 1. They are using 1/50th of a pawn without thinking about it....BubbaTough wrote:I tried variations of that, and for me...even with a scale of 1/1000...it hurt performance.Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
-Sam
I switched from millipawns to centipawns way back in Crafty. I started with millipawns because that is what we used in Blitz/CrayBlitz since the early days. I found centipawns resulted in less arbitrary scores (is this a .01, or a .011 or a .009 score)? My tests with .1 were worse, but now I can quantify exactly how much worse on the cluster and am going to run this test hopefully tomorrow.
-
- Posts: 803
- Joined: Mon Jul 17, 2006 5:53 am
- Full name: Edsel Apostol
Re: Centipawns and Millipawns
I can't edit my post anymore. In my last sentence I mean too fine instead of too coarse for the search.BubbaTough wrote:I tried variations of that, and for me...even with a scale of 1/1000...it hurt performance.Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
-Sam
I think the best value for the basic unit is somewhere between 0.01 and 0.05. Stockfish uses 0.03125.
There are some exceptions though. Take for example Strelka that uses 3399 as Pawn Value. Its basic uinit is 0.0003.
In the end, it all boils down to who's eval function is well tuned may it be using 1/1000 or 1/100.
Edsel Apostol
https://github.com/ed-apostol/InvictusChess
https://github.com/ed-apostol/InvictusChess
-
- Posts: 803
- Joined: Mon Jul 17, 2006 5:53 am
- Full name: Edsel Apostol
Re: Centipawns and Millipawns
I am not sure if zero is a legitimate shift, I don't have much exposure to hardware other than the PC. I assume that since it's zero the hardware will be intelligent enough not to shift anything. Thanks for pointing it out.bob wrote:Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
Edsel Apostol
https://github.com/ed-apostol/InvictusChess
https://github.com/ed-apostol/InvictusChess
-
- Posts: 12541
- Joined: Wed Mar 08, 2006 8:57 pm
- Location: Redmond, WA USA
Re: Centipawns and Millipawns
Shifts of zero bits are defined. Here is what the current C standard says:Edsel Apostol wrote:I am not sure if zero is a legitimate shift, I don't have much exposure to hardware other than the PC. I assume that since it's zero the hardware will be intelligent enough not to shift anything. Thanks for pointing it out.bob wrote:Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
6.5.7 Bitwise shift operators
Syntax
1 shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
-
- Posts: 803
- Joined: Mon Jul 17, 2006 5:53 am
- Full name: Edsel Apostol
Re: Centipawns and Millipawns
Based on this:Dann Corbit wrote:Shifts of zero bits are defined. Here is what the current C standard says:Edsel Apostol wrote:I am not sure if zero is a legitimate shift, I don't have much exposure to hardware other than the PC. I assume that since it's zero the hardware will be intelligent enough not to shift anything. Thanks for pointing it out.bob wrote:Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
6.5.7 Bitwise shift operators
Syntax
1 shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
When E2 = 0 then:If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
Code: Select all
E1 * 2^0 = E1 * 1 = E1
Edsel Apostol
https://github.com/ed-apostol/InvictusChess
https://github.com/ed-apostol/InvictusChess
-
- Posts: 10296
- Joined: Thu Mar 09, 2006 12:37 am
- Location: Tel-Aviv Israel
Re: Centipawns and Millipawns
You do not need values that are smaller than 0.01 to have millipawns evaluation.bob wrote:Having done all three, my take on the issue is this:rjgibert wrote:I can't imagine what a centipawn means. What is the reason for using such a fine grained evaluation unit? Is there really any benefit? I understand mate-in-N evaluations and maybe what a decipawn means, but that is as far as I can go with my 2234 rating.
The only other thing I can relate to is a judgement call that position X appears to be better than position Y even though I might quantify them as having the same evaluation.
So my question is, do centipawns evaluations really help chess engines and why? What would you lose by using say 1/20th of a pawn as the finest grain for your evaluations as opposed to the finer grained evaluations? It appears to me that chess programmers are doing something akin to measuring something to the nearest hundredths, while having a standard deviation of as much as a quarter of a pawn.
In engineering, 1.234 +/- 0.1 is just silly. Why isn't it just as silly in computer chess?
And then there even are engines that use millipawns. What's that about?
(1) decipawns (0.1) is too coarse. Not every positional consideration is worth 0.1 pawns, so you either have to round the score up to 0.1, or else throw it out since it would be zero.
(2) millipawns (0.001) is too fine. I do not believe that my evaluation has any .001 accuracy ideas in it. As you spread the evaluation scores out, your tree search becomes less efficient (for example, compare a program with no positional scoring to one with, with respect to tree size).
(3) centipawns (0.01) is reasonable. One could make the argument that maybe .05 is better (1/20th of a pawn). Or some other number. But my intuition after trying all three during the development of Crafty is that the right value lies in the interval {0.01, 0.1}. Whether it is on one end or the other, or somewhere in the middle, is a point for conjecture. It is too hard to test the idea, although I suppose I could just do a normal eval and then at the end, reduce it to the accuracy needed. But it is not easy to test for smaller than .01 increments since no increments in crafty would be smaller than .01...
If you do an average between opening evaluation and endgame evaluation when the weight of the opening evaluation is based on the stage of the game then the difference between evaluations can be less than 0.01 pawns.
Uri
-
- Posts: 20943
- Joined: Mon Feb 27, 2006 7:30 pm
- Location: Birmingham, AL
Re: Centipawns and Millipawns
anything^0 = 1.Edsel Apostol wrote:Based on this:Dann Corbit wrote:Shifts of zero bits are defined. Here is what the current C standard says:Edsel Apostol wrote:I am not sure if zero is a legitimate shift, I don't have much exposure to hardware other than the PC. I assume that since it's zero the hardware will be intelligent enough not to shift anything. Thanks for pointing it out.bob wrote:Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
6.5.7 Bitwise shift operators
Syntax
1 shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.When E2 = 0 then:If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.Is the above assumption correct? Is 2^0 undefined also?Code: Select all
E1 * 2^0 = E1 * 1 = E1
-
- Posts: 803
- Joined: Mon Jul 17, 2006 5:53 am
- Full name: Edsel Apostol
Re: Centipawns and Millipawns
What I mean if that is still undefined in the C standard. I already knew that anything^0 = 1 in my algebra class since I'm 13 years old.bob wrote:anything^0 = 1.Edsel Apostol wrote:Based on this:Dann Corbit wrote:Shifts of zero bits are defined. Here is what the current C standard says:Edsel Apostol wrote:I am not sure if zero is a legitimate shift, I don't have much exposure to hardware other than the PC. I assume that since it's zero the hardware will be intelligent enough not to shift anything. Thanks for pointing it out.bob wrote:Is zero a legit shift amount? lots of hardware will handle that in unexpected ways. Some will not shift at all, some will shift as if that were the word size, which means a value of zero will result...Edsel Apostol wrote:I have tried this idea just recently. I'm still using my old scoring of centipawns but at the end of the eval I use something like:
where grain is a number 0 to 4.Code: Select all
return score &= ~((1<<grain)-1);
Grain with 0 value means no change in the score, 1 will make it round to 2, 2 to 4 and 3 to 8, and 4 to 16.
I only have tried grain values 0, 2, 3. 0 still gives the best result, though my number of games is only 1200 each and the difference in elo between 0 and 2,3 is only 10. I will test with 1 to see if it performs better.
Using eval grain in Stockfish works because it uses 256 as Pawn value and it is too coarse for the search so it scales it by 4, meaning the finest unit for its search is 1/64. I think this is the optimal value.
6.5.7 Bitwise shift operators
Syntax
1 shift-expression:
additive-expression
shift-expression << additive-expression
shift-expression >> additive-expression
Constraints
2 Each of the operands shall have integer type.
Semantics
3 The integer promotions are performed on each of the operands. The type of the result is that of the promoted left operand. If the value of the right operand is negative or is greater than or equal to the width of the promoted left operand, the behavior is undefined.
4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.When E2 = 0 then:If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.Is the above assumption correct? Is 2^0 undefined also?Code: Select all
E1 * 2^0 = E1 * 1 = E1
If one we're to base on this deductions, if anything^0=1 is defined in the C standard, therefore a shift by 0 will still produce the same number being shifted. So there is no undefined behavior in it. If there will be problems with other hardware concerning this, it must be the problem of the hardware itself and not in the code.
Edsel Apostol
https://github.com/ed-apostol/InvictusChess
https://github.com/ed-apostol/InvictusChess
-
- Posts: 838
- Joined: Thu Jul 05, 2007 5:03 pm
- Location: British Columbia, Canada
Re: Centipawns and Millipawns
Edsel Apostol wrote: What I mean if that is still undefined in the C standard. I already knew that anything^0 = 1 in my algebra class since I'm 13 years old.
If one we're to base on this deductions, if anything^0=1 is defined in the C standard, therefore a shift by 0 will still produce the same number being shifted. So there is no undefined behavior in it. If there will be problems with other hardware concerning this, it must be the problem of the hardware itself and not in the code.
They were pretty careful with the definitions. They standardized everything that was predictable across real hardware (of that era) and avoided specifying behaviours for things that have different behaviour on different hardware (shifting by greater or equal to the number of bits in a word, 1s- and 2s-complement machines, etc.)The authors of the C standard wrote: 4 The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 * 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 * 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
5 The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
"The result of E1 << E2 is E1 left-shifted E2 bit positions". If E2 is zero, it is left-shifted by zero bit positions, and there are no vacated bits to fill.
"The result of E1 >> E2 is E1 right-shifted E2 bit positions." Same thing, except that it is implementation-defined if E1 has a signed type and a negative value. Which means it has to do something consistent for your implementation, but the standard does not specify what. In practice, every implementation you'll ever come across leaves the value of E1 unchanged if E2 is zero (because it is what the underlying shift and rotate instructions do, at least on every platform I've ever heard of).
When this standard was written, they had to contend with 1s-complement math and byte- and word-sizes that were not multiples of 8 bits. We are spoiled nowadays: Every machine made in at least the last 20 years has IEEE floats, 2's complement integers, 8-bits to a byte, and 16 or 32 or 64 bits to a word.