Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: Mobility in Chess Evaluation Function at terminal-nodes

Author: Dann Corbit

Date: 16:18:37 12/28/05

Go up one level in this thread


On December 28, 2005 at 19:02:54, David Dahlem wrote:

>On December 28, 2005 at 18:39:28, Dann Corbit wrote:
>
>>On December 28, 2005 at 17:11:30, David Dahlem wrote:
>>
>>>On December 28, 2005 at 16:24:53, Dann Corbit wrote:
>>>
>>>>On December 28, 2005 at 16:03:47, David Dahlem wrote:
>>>>
>>>>><snip>
>>>>>
>>>>>>If you have a bitboard program, there is a way to get really cheap mobility
>>>>>>scores.
>>>>>
>>>>>Could you elaborate on this method?
>>>>
>>>>Precalculate for every ray, based on the bit pattern on that ray.
>>>>
>>>>Move generation is also helped by this idea (both for capture/promotion and
>>>>non-capture).
>>>>
>>>>consider this epd string:
>>>>[D]4k3/1n6/8/pR5b/1P6/1n6/1N6/4K3 w - -
>>>>For the rook's row, we have 1x000001 ( the x is because we ignore the square he
>>>>sits on, he can never attack or defend that.)
>>>>For this simple case, the non-captures are the zero squares and the captures are
>>>>the non-zero squares anded with the opponent chessmen mask.
>>>>Regardless of what the chessmen are, there are 5 non-captures and 0,1,or 2
>>>>captures depending on whether the 1 bits are friend or foe.
>>>>
>>>>For the column we have 010x1110.
>>>>There is one non-capture and 0,1, or 2 captures depending on whether the nearest
>>>>one bits are friend or foe.
>>>>
>>>>You get the idea.
>>>
>>>Thanks Dann. Mobility should only be considered for bishops, knights, rooks, and
>>>queens, is this correct?
>>
>>I would test it in your eval for benefit.  Tord does not calculate queen
>>mobility, for instance.
>>
>>If you use bitboards, you can calculate the total pawn mobility in a couple
>>operations.  I think it is a lot more important in the endgame (e.g. down a
>>piece with +3 pawns and your pawns are rammed sounds like trouble).
>>
>
>I'm currently only using bitboards to calculate mobility for bishops and rooks.
>I haven't even considered doing mobility for pawns.
>
>>>And I'm thinking the bonus should be scaled according
>>>to piece values?
>>
>>I do a fitted curve using parabolic least squares fit from actual data.  At
>>least it gives you a good starting point.
>>YMMV.
>
>I'm not a math expert, so "fitted curve using parabolic least squares" leaves me
>mystified. :-)

It looks like this:
#include <math.h>
#include <float.h>

/***************************************************
*  Parabolic Least Squares Demonstration Program   *
* ------------------------------------------------ *
* Reference: BASIC Scientific Subroutines, Vol. II *
*   by F.R. Ruckdeschel, BYTE/McGRAWW-HILL, 1981.  *
*   ISBN 0-07-054202-3 (v. 2), Pages 24-31         *
*                                                  *
*              C++ version by J-P Moreau, Paris    *
* Subsequently translated to C and heavily altered *
* by Dann Corbit                                   *
* ------------------------------------------------ *
* This program calculates a parabolic least squares*
* fit to a given data set.                         *
*                                                  *
* INSTRUCTIONS                                     *
* ------------                                     *
* 1.  The number of data coordinates provided must *
*     be greater than three points.                *
* 2.  The data must not be a single point, which   *
*     is repeated.                                 *
* 3.  The data must not be perfectly colinear.     *
* If any of these 3 rules are violated, an error   *
* flag will be set.  The returned data will be     *
* invalid and must not be used.                    *
*                                                  *
* SAMPLE DATA:                                     *
*                                                  *
* Number of data points : 4                        *
*                                                  *
*   X[0]=1  Y[0]=1                                 *
*   X[1]=2  Y[1]=4                                 *
*   X[2]=3  Y[2]=9                                 *
*   X[3]=5  Y[3]=24.95                             *
*                                                  *
* Fitted equation is:                              *
*   Y = -0.017727 + 0.022045 X + 0.994318 X^2      *
*                                                  *
* Standard deviation of fit: 0.004767              *
***************************************************/
#define DATA_OK         0	// Everything is A-OK

#define NOT_ENOUGH_DATA 1	// Underdetermined system

#define SINGLE_POINT    2	// Degenerate data

#define STRAIGHT_LINE   3	// Degenerate data

 /****************************************************************
 *           Parabolic least squares estimation                  *
 * ------------------------------------------------------------- *
 * In:  unsigned n = number of points                            *
 *      n values xd[i], yd[i]                                    *
 * Out: coefficients a,b,c of fit (a+b*x+c*x^2)                  *
 *      coefs[0] = multiplier for x^0 {Constant term}            *
 *      coefs[1] = multiplier for x^1 {Linear term}              *
 *      coefs[2] = multiplier for x^2 {Quadratic term}           *
 *      coefs[3] = Standard deviation {How good is the fit?}     *
 *      coefs[4] = x location for the extrapolcated minimum      *
 * Returns: The location of the minimum of the parabola at x.    *
 ****************************************************************/

double          plsqf(double *xd, double *yd, unsigned n, double *coefs, int
*error)
{
    double          a0;
    double          a1;
    double          a2,
                    a3,
                    a4,
                    b0,
                    b1,
                    b2,
                    d1;
    unsigned        i;
    double          a,
                    b,
                    c,
                    d,
                    e;
    *error = DATA_OK;           // Assume that there are no problems

    // Check for not enough data...
    if (n < 3) {
        *error = NOT_ENOUGH_DATA;
        return 0;
    }
    a0 = 1;
    a1 = 0;
    a2 = 0;
    a3 = 0;
    a4 = 0;
    b0 = 0;
    b1 = 0;
    b2 = 0;
    for (i = 0; i < n; i++) {
        double          xi2 = xd[i] * xd[i];
        double          xi4 = xi2 * xi2;
        double          xy = xd[i] * yd[i];
        a1 += xd[i];
        a2 += xi2;
        a3 += xi2 * xd[i];
        a4 += xi4;
        b0 += yd[i];
        b1 += xy;
        b2 += xy * xd[i];
    }
    a1 /= n;
    a2 /= n;
    a3 /= n;
    a4 /= n;
    b0 /= n;
    b1 /= n;
    b2 /= n;
    d = a0 * (a2 * a4 - a3 * a3) - a1 * (a1 * a4 - a2 * a3) + a2 * (a1 * a3 - a2
* a2);

    // Check for {near} singularity (all data is the same point)
    if (fabs(d) < (DBL_EPSILON * 10.0)) {
        *error = SINGLE_POINT;
        return 0;
    }
    a = (b0 * (a2 * a4 - a3 * a3) + b1 * (a2 * a3 - a1 * a4) + b2 * (a1 * a3 -
a2 * a2)) / d;
    b = (b0 * (a2 * a3 - a1 * a4) + b1 * (a0 * a4 - a2 * a2) + b2 * (a1 * a2 -
a0 * a3)) / d;
    c = (b0 * (a1 * a3 - a2 * a2) + b1 * (a2 * a1 - a0 * a3) + b2 * (a0 * a2 -
a1 * a1)) / d;

    // Check for {near} singularity (the data is perfectly linear)
    if (fabs(c) < (DBL_EPSILON * 10.0)) {
        *error = STRAIGHT_LINE;
        return 0;
    }
    // Evaluation of standard deviation d
    d = 0;
    for (i = 0; i < n; i++) {
        d1 = yd[i] - a - b * xd[i] - c * xd[i] * xd[i];
        d += d1 * d1;
    }
    d = sqrt(d / (n - 3.0));

    // Calculation of the minimum/maximum for x
    e = -b / (c * 2.0);

    // Load the constants into the return array
    coefs[0] = a;
    coefs[1] = b;
    coefs[2] = c;
    coefs[3] = d;
    coefs[4] = e;
    return e;                   // Return the x location for the minimum/maximum
}

If there are no errors, and the standard deviation is good, then we hope for a
maximum.  If the x location is a minimum (the sign of 'a' tells you that) then
the data has gone insane and we cannot trust it.  (e.g. the closer you get to
the central value, the fewer solutions are found in the allotted time.)

The idea works like this:
Suppose that I evaluate a pawn as 100.0 centipawns.  How much should a knight be
worth?  Probably somewhere between 200 and 500 centipawns.  Now, if I choose a
bad value (like 200 centipawns) then I should solve less problems.  If I choose
a good value (probably fairly close to 300), then I will solve more problems.
So I iterate over 12,000 quiet chess positions with known solutions and see what
value of the parameter gives me the most solutions.

Now, the value found will NOT be optimal for play.  But it will be a good
starting point for experimentation.  And I will also have a pretty good idea
about what sort of range will produce reasonable results.

So...

Big_again:
Tell the program that a knight is worth 'start' (e.g. 200) centipawns.
Have it try to solve 12000 positions at depth k.
Count the solutions.

Little_again:
Tell the program that a knight is worth Current Knight value + Increment
centipawns.
Have it try to solve 12000 positions at depth k.
Count the solutions.

If current knight value is bigger than 'limit' (e.g 500) goto Little_again

Fit the curve and write the solution. (We are interested in the apex of a
parabola that has only a maximum and not a minimum.)

If depth is not at maximum desired depth, increment depth 'k' and goto Big_again





This page took 0 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.