Blunder option

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Ajedrecista wrote: Wed Dec 30, 2020 1:01 pm
What is j in

Code: Select all

F(i) = Prob(i) + SUM[Prob(j)], with j < i
SF12 from startpos at 5s, K=1.0.

Code: Select all

moves: ['e2e4', 'd2d4', 'c2c4', 'g1f3', 'e2e3', 'g2g3', 'b1c3', 'c2c3', 'h2h3', 'a2a3', 'a2a4', 'd2d3', 'b2b3', 'f2f4', 'b2b4', 'h2h4', 'g1h3', 'f2f3', 'b1a3', 'g2g4']
scores: [0.33, 0.27, 0.24, 0.13, 0.09, 0.06, 0.01, 0.01, 0.0, -0.08, -0.1, -0.1, -0.13, -0.25, -0.3, -0.43, -0.5, -0.52, -0.6, -1.25]
d: [0.0, -0.06, -0.09, -0.2, -0.24, -0.27, -0.32, -0.32, -0.33, -0.41, -0.43, -0.43, -0.46, -0.58, -0.63, -0.76, -0.83, -0.85, -0.93, -1.58]
prob: [0.11855, 0.10325, 0.09636, 0.0748, 0.06822, 0.06367, 0.05674, 0.05674, 0.05545, 0.04612, 0.04405, 0.04405, 0.04111, 0.03118, 0.02779, 0.0206, 0.01753, 0.01675, 0.01393, 0.00312]
Sesse
Posts: 300
Joined: Mon Apr 30, 2018 11:51 pm

Re: Blunder option.

Post by Sesse »

Ferdy wrote: Wed Dec 30, 2020 8:48 pm
Ajedrecista wrote: Wed Dec 30, 2020 1:01 pm
What is j in

Code: Select all

F(i) = Prob(i) + SUM[Prob(j)], with j < i
j is all integers from 0 to i-1, inclusive. So F(i) is cumulative probability.

So F(3) = Prob(3) + SUM[Prob(j)] = Prob(3) + (Prob(0) + Prob(1) + Prob(2)) = Prob(3) + F(2).
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Sesse wrote: Wed Dec 30, 2020 11:39 pm
Ferdy wrote: Wed Dec 30, 2020 8:48 pm
Ajedrecista wrote: Wed Dec 30, 2020 1:01 pm
What is j in

Code: Select all

F(i) = Prob(i) + SUM[Prob(j)], with j < i
j is all integers from 0 to i-1, inclusive. So F(i) is cumulative probability.

So F(3) = Prob(3) + SUM[Prob(j)] = Prob(3) + (Prob(0) + Prob(1) + Prob(2)) = Prob(3) + F(2).
Thanks I will try that.
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Ajedrecista wrote: Wed Dec 30, 2020 1:01 pm Hello Ferdinand:
Ferdy wrote: Wed Dec 30, 2020 6:14 amI am looking at this:

Code: Select all

Imagine a position where the evals of all the possible moves from the side to move are:

(In pawns): d(i) = eval(i) - eval(best move) = {0, -0.1, -0.2, -0.2, -0.6, -2.9, -4, -4, -4, -9}

Prob(i) = 10^[d(i)/K]/SUM{10^[d(i)/K]}, with K > 0

// i = 1, 2, ..., moves - 1, moves; with moves = perft(1) of the position

F(0) = 0
F(i) = Prob(i) + SUM[Prob(j)], with j < i
// Of course: F(moves) = 1

Get r = a random number from a PRNG.

if [F(i-1) < r =< F(i)] then
  pick move i
end if

/*
Choose wisely. If I am right:
0 < r =< 1 ==> condition: F(i-1) < r =< F(i)
0 =< r < 1 ==> condition: F(i-1) =< r < F(i)
*/
and this.

Code: Select all

Rounding up to 1e-4:

-----------------------------

K = 1, basis 10:

Move   d(i)    P(i)     F(i)
  1     0.0   0.3276   0.3276
  2    -0.1   0.2457   0.5732
  3    -0.2   0.1842   0.7574
  4    -0.2   0.1842   0.9417
  5    -0.6   0.0583   0.9999
  6    -2.9   0.0001   1.0000
  7    -4.0   0.0000   1.0000
  8    -4.0   0.0000   1.0000
  9    -4.0   0.0000   1.0000
 10    -9.0   0.0000   1.0000

-----------------------------

K = 4, basis 10:

Move   d(i)    P(i)     F(i)
  1     0.0   0.2029   0.2029
  2    -0.1   0.1916   0.3945
  3    -0.2   0.1808   0.5753
  4    -0.2   0.1808   0.7561
  5    -0.6   0.1436   0.8998
  6    -2.9   0.0382   0.9380
  7    -4.0   0.0203   0.9583
  8    -4.0   0.0203   0.9786
  9    -4.0   0.0203   0.9989
 10    -9.0   0.0011   1.0000

-----------------------------

K = 0.5, basis 10:

Move   d(i)    P(i)     F(i)
  1     0.0   0.4016   0.4016
  2    -0.1   0.2534   0.6549
  3    -0.2   0.1599   0.8148
  4    -0.2   0.1599   0.9747
  5    -0.6   0.0253   1.0000
  6    -2.9   0.0000   1.0000
  7    -4.0   0.0000   1.0000
  8    -4.0   0.0000   1.0000
  9    -4.0   0.0000   1.0000
 10    -9.0   0.0000   1.0000
And this:

Code: Select all

Get r = a random number from a PRNG.

if [F(i-1) < r =< F(i)] then
  pick move i
end if
So ultimately the move is picked based on random number? Could you explain more about this method?
I am trying to reproduce you example calculation.

Code: Select all

(In pawns): d(i) = eval(i) - eval(best move) = {0, -0.1, -0.2, -0.2, -0.6, -2.9, -4, -4, -4, -9}

Prob(i) = 10^[d(i)/K]/SUM{10^[d(i)/K]}, with K > 0

K = 1, basis 10:

Move   d(i)    P(i)     F(i)
  1     0.0   0.3276   0.3276
  2    -0.1   0.2457   0.5732
  3    -0.2   0.1842   0.7574
  4    -0.2   0.1842   0.9417
  5    -0.6   0.0583   0.9999
  6    -2.9   0.0001   1.0000
  7    -4.0   0.0000   1.0000
  8    -4.0   0.0000   1.0000
  9    -4.0   0.0000   1.0000
 10    -9.0   0.0000   1.0000
What I get is this.

Code: Select all

   Move  d(i)    P(i)
0     1   0.0  0.3022
1     2  -0.1  0.2401
2     3  -0.2  0.1907
3     4  -0.2  0.1907
4     5  -0.6  0.0759
5     6  -2.9  0.0004
6     7  -4.0  0.0000
7     8  -4.0  0.0000
8     9  -4.0  0.0000
9    10  -9.0  0.0000
There is something wrong with my formula in python or I failed to interpret your formula. I pre-calculated the SUM.

Code: Select all

10 ^ x is just equal to 10**x

Code: Select all

d = [0.0, -0.1, -0.2, -0.2, -0.6, -2.9, -4.0, -4.0, -4.0, -9.0]

Code: Select all

def proba(d, K=1.0):
    """
    d is a list of float.

    Prob(i) = 10^[d(i)/K] / SUM{10^[d(i)/K]}
    """
    prob = []

    sumv = 0
    for i in d:
        sumv += 10 ** (i / K)

    for i in d:
        value = (10 ** (i / K)) / sumv
        prob.append(round(value, 4))

    return prob

Code: Select all

import pandas as pd
def main():
    d = [0.0, -0.1, -0.2, -0.2, -0.6, -2.9, -4.0, -4.0, -4.0, -9.0]
    p = proba(d)
    moves = [i for i in range(1, len(d)+1)]
    data = {'Move': moves, 'd(i)': d, 'P(i)': p}
    df = pd.DataFrame(data)
    print(df)
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

From previous example, now with F, using cummulative sum see F(p).

Code: Select all

   Move  d(i)    P(i)    F(i)
0     1   0.0  0.3022  0.3022
1     2  -0.1  0.2401  0.4802
2     3  -0.2  0.1907  0.6215
3     4  -0.2  0.1907  0.8122
4     5  -0.6  0.0759  0.7733
5     6  -2.9  0.0004  0.6982
6     7  -4.0  0.0000  0.6978
7     8  -4.0  0.0000  0.6978
8     9  -4.0  0.0000  0.6978
9    10  -9.0  0.0000  0.6978

Code: Select all

def proba(d, K=1.0):
    """
    d is a list of float.

    Prob(i) = 10^[d(i)/K] / SUM{10^[d(i)/K]}
    """
    prob = []

    sumv = 0
    for i in d:
        sumv += 10 ** (i / K)

    for i in d:
        value = (10 ** (i / K)) / sumv
        prob.append(round(value, 4))

    return prob

Code: Select all

def F(p):
    """
    p is a list of float.

    F(i) = Prob(i) + SUM[Prob(j)], with j < i
    """
    res = []

    cumsum = 0

    for i, v in enumerate(p):
        cumsum += v if i > 0 else 0
        value = v + cumsum
        res.append(round(value, 4))

    return res

Code: Select all

import pandas as pd

def main():
    d = [0.0, -0.1, -0.2, -0.2, -0.6, -2.9, -4.0, -4.0, -4.0, -9.0]
    p = proba(d)
    f = F(p)

    moves = [i for i in range(1, len(d)+1)]
    data = {'Move': moves, 'd(i)': d, 'P(i)': p, 'F(i)': f}
    df = pd.DataFrame(data)
    print(df)
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Generate random number and search the move number.

Move Selector

Code: Select all

if [F(i-1) < r =< F(i)] then
  pick move i
end if

Sample given

Code: Select all

d = [0.0, -0.1, -0.2, -0.2, -0.6, -2.9, -4.0, -4.0, -4.0, -9.0]

Code: Select all

   Move  d(i)    P(i)    F(i)
0     1   0.0  0.3022  0.3022
1     2  -0.1  0.2401  0.4802
2     3  -0.2  0.1907  0.6215
3     4  -0.2  0.1907  0.8122
4     5  -0.6  0.0759  0.7733
5     6  -2.9  0.0004  0.6982
6     7  -4.0  0.0000  0.6978
7     8  -4.0  0.0000  0.6978
8     9  -4.0  0.0000  0.6978
9    10  -9.0  0.0000  0.6978

Result

Code: Select all

min: 0.3022, max: 0.8122
random number: 0.6446
low: 0.6215, r: 0.6446, high: 0.8122
move num: 4

Code

Code: Select all

def search_move_num(d, f):
    """
    Search the move number based on generated random number.
    """
    move_num = None

    # Don't return unless we get the move number.
    while True:
        # Generate random number between the min and max of f.
        print(f'min: {min(f)}, max: {max(f)}')
        r = random.uniform(min(f), max(f))
        r = round(r, 4)
        print(f'random number: {r}')

        found = False
        for i in range(len(d)):
            if i == 0:
                continue

            low = f[i-1]
            high = f[i]

            if low < r <= high:
                move_num = i
                print(f'low: {low}, r: {r}, high: {high}')
                found = True
                break

        if found:
            break

        print('Failed to get move num.\n')

    return move_num + 1

Code: Select all

import random
import pandas as pd

def main():
    d = [0.0, -0.1, -0.2, -0.2, -0.6, -2.9, -4.0, -4.0, -4.0, -9.0]
    p = proba(d)
    f = F(p)

    moves = [i for i in range(1, len(d)+1)]
    data = {'Move': moves, 'd(i)': d, 'P(i)': p, 'F(i)': f}
    df = pd.DataFrame(data)
    print(df)

    move_num = search_move_num(d, f)
    print(f'move num: {move_num}')
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Actual example from sf12 at K=1.0

>> setoption name multipv value 500
>> isready

info string Hash table allocation: Windows large pages not used.
readyok

>> ucinewgame
>> isready

readyok

>> go depth 16

Code: Select all

 num move  scores  d(i)   P(i)   F(i)
   1 e2e4    0.49  0.00 0.1549 0.1549
   2 d2d4    0.29 -0.20 0.0977 0.1954
   3 g1f3    0.29 -0.20 0.0977 0.2931
   4 c2c4    0.21 -0.28 0.0813 0.3580
   5 e2e3    0.13 -0.36 0.0676 0.4119
   6 a2a3    0.04 -0.45 0.0549 0.4541
   7 b1c3    0.02 -0.47 0.0525 0.5042
   8 g2g3    0.01 -0.48 0.0513 0.5543
   9 c2c3   -0.01 -0.50 0.0490 0.6010
  10 a2a4   -0.08 -0.57 0.0417 0.6354
  11 b2b4   -0.09 -0.58 0.0407 0.6751
  12 h2h3   -0.10 -0.59 0.0398 0.7140
  13 d2d3   -0.16 -0.65 0.0347 0.7436
  14 b2b3   -0.16 -0.65 0.0347 0.7783
  15 h2h4   -0.32 -0.81 0.0240 0.7916
  16 f2f4   -0.33 -0.82 0.0234 0.8144
  17 b1a3   -0.45 -0.94 0.0178 0.8266
  18 g1h3   -0.45 -0.94 0.0178 0.8444
  19 f2f3   -0.50 -0.99 0.0158 0.8582
  20 g2g4   -1.25 -1.74 0.0028 0.8480
info string move number 10 random number 0.6027
bestmove a2a4
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

[d]rnbQkbnr/ppp3pp/5p2/4p3/4P3/5N2/PPP2PPP/RNB1KB1R b KQkq - 0 5

position fen rnbQkbnr/ppp3pp/5p2/4p3/4P3/5N2/PPP2PPP/RNB1KB1R b KQkq - 0 5
go movetime 10000

Code: Select all

 num move  scores   d(i)  P(i)  F(i)
   1 e8d8   -0.14   0.00   1.0   1.0
   2 e8f7  -23.43 -23.29   0.0   0.0
User avatar
Ajedrecista
Posts: 1968
Joined: Wed Jul 13, 2011 9:04 pm
Location: Madrid, Spain.

Re: Blunder option.

Post by Ajedrecista »

Hello Ferdinand:

Steinar is right, F is a cumulative function. Regarding my example calculation, you are right: those individual probabilities are correct. My example gives the other values with K = 0.8, but for some reason there is a typo and K = 1 was written instead.

I think the cumulative part and pseudorandom number is not well implemented. Once you get P(d = 0.0) ~ 0.3022, P(d = -0.1) ~ 0.2401... my intention is to pick the move with d = 0.0 if the pseudorandom number is between 0 and 0.3022, the move with d = -0.1 if the pseudorandom number is between 0.3022 and 0.4802... and the worst move if the pseudorandom number is between 0.999999999697793 (the cumulative function at that point according to Excel) and 1. The pseudorandom number range and the cumulative function range is the same: [0, 1].

Other than that, the idea should be to play whole games and see if the moves are realistic. An opening book could be used just like in normal testing in order to avoid 1.- a4, Na6; 2.- Na3, f6 or things like that.

With the moves and evals of the opening position, the F(i) column would be:

Code: Select all

 num move  scores  d(i)   P(i)   F(i)  Pseudorandom number
   1 e2e4    0.49  0.00 0.1549 0.1549   0.0000 to 0.1549
   2 d2d4    0.29 -0.20 0.0977 0.2526   0.1549 to 0.2526
   3 g1f3    0.29 -0.20 0.0977 0.3503   0.2526 to 0.3503
   4 c2c4    0.21 -0.28 0.0813 0.4315   0.3503 to 0.4315
   5 e2e3    0.13 -0.36 0.0676 0.4991   0.4315 to 0.4991
   6 a2a3    0.04 -0.45 0.0549 0.5541   0.4991 to 0.5541
   7 b1c3    0.02 -0.47 0.0525 0.6066   0.5541 to 0.6066
   8 g2g3    0.01 -0.48 0.0513 0.6578   0.6066 to 0.6578
   9 c2c3   -0.01 -0.50 0.0490 0.7068   0.6578 to 0.7068
  10 a2a4   -0.08 -0.57 0.0417 0.7485   0.7068 to 0.7485
  11 b2b4   -0.09 -0.58 0.0407 0.7892   0.7485 to 0.7892
  12 h2h3   -0.10 -0.59 0.0398 0.8290   0.7892 to 0.8290
  13 d2d3   -0.16 -0.65 0.0347 0.8637   0.8290 to 0.8637
  14 b2b3   -0.16 -0.65 0.0347 0.8984   0.8637 to 0.8984
  15 h2h4   -0.32 -0.81 0.0240 0.9223   0.8984 to 0.9223
  16 f2f4   -0.33 -0.82 0.0234 0.9458   0.9223 to 0.9458
  17 b1a3   -0.45 -0.94 0.0178 0.9636   0.9458 to 0.9636
  18 g1h3   -0.45 -0.94 0.0178 0.9813   0.9636 to 0.9813
  19 f2f3   -0.50 -0.99 0.0158 0.9972   0.9813 to 0.9972
  20 g2g4   -1.25 -1.74 0.0028 1.0000   0.9972 to 1.0000
I have added the bounds of the pseudorandom numbers to pick each move in a try to clarify my proposal (just be careful with the bounds: < or =<, but never making a pseudorandom number able to pick more than a move). Then, if your pseudorandom number is 0.6027, the move to be played is Nc3 (0.5541 < 0.6027 < 0.6066). In this example, there are more less the same odds of playing the top-5 moves than the other 15.

Thanks again for your time. I do not exactly know how a chess engine works. Would be fair and correct that the evaluations of all the moves are from the same depth or it does not matter if some evals are from a certain depth and the rest from depth - 1 if the full depth search has not been completed yet?

Regards from Spain.

Ajedrecista.
Ferdy
Posts: 4833
Joined: Sun Aug 10, 2008 3:15 pm
Location: Philippines

Re: Blunder option.

Post by Ferdy »

Ajedrecista wrote: Thu Dec 31, 2020 1:22 pm Hello Ferdinand:

Steinar is right, F is a cumulative function. Regarding my example calculation, you are right: those individual probabilities are correct. My example gives the other values with K = 0.8, but for some reason there is a typo and K = 1 was written instead.

I think the cumulative part and pseudorandom number is not well implemented. Once you get P(d = 0.0) ~ 0.3022, P(d = -0.1) ~ 0.2401... my intention is to pick the move with d = 0.0 if the pseudorandom number is between 0 and 0.3022, the move with d = -0.1 if the pseudorandom number is between 0.3022 and 0.4802... and the worst move if the pseudorandom number is between 0.999999999697793 (the cumulative function at that point according to Excel) and 1. The pseudorandom number range and the cumulative function range is the same: [0, 1].

Other than that, the idea should be to play whole games and see if the moves are realistic. An opening book could be used just like in normal testing in order to avoid 1.- a4, Na6; 2.- Na3, f6 or things like that.

With the moves and evals of the opening position, the F(i) column would be:

Code: Select all

 num move  scores  d(i)   P(i)   F(i)  Pseudorandom number
   1 e2e4    0.49  0.00 0.1549 0.1549   0.0000 to 0.1549
   2 d2d4    0.29 -0.20 0.0977 0.2526   0.1549 to 0.2526
   3 g1f3    0.29 -0.20 0.0977 0.3503   0.2526 to 0.3503
   4 c2c4    0.21 -0.28 0.0813 0.4315   0.3503 to 0.4315
   5 e2e3    0.13 -0.36 0.0676 0.4991   0.4315 to 0.4991
   6 a2a3    0.04 -0.45 0.0549 0.5541   0.4991 to 0.5541
   7 b1c3    0.02 -0.47 0.0525 0.6066   0.5541 to 0.6066
   8 g2g3    0.01 -0.48 0.0513 0.6578   0.6066 to 0.6578
   9 c2c3   -0.01 -0.50 0.0490 0.7068   0.6578 to 0.7068
  10 a2a4   -0.08 -0.57 0.0417 0.7485   0.7068 to 0.7485
  11 b2b4   -0.09 -0.58 0.0407 0.7892   0.7485 to 0.7892
  12 h2h3   -0.10 -0.59 0.0398 0.8290   0.7892 to 0.8290
  13 d2d3   -0.16 -0.65 0.0347 0.8637   0.8290 to 0.8637
  14 b2b3   -0.16 -0.65 0.0347 0.8984   0.8637 to 0.8984
  15 h2h4   -0.32 -0.81 0.0240 0.9223   0.8984 to 0.9223
  16 f2f4   -0.33 -0.82 0.0234 0.9458   0.9223 to 0.9458
  17 b1a3   -0.45 -0.94 0.0178 0.9636   0.9458 to 0.9636
  18 g1h3   -0.45 -0.94 0.0178 0.9813   0.9636 to 0.9813
  19 f2f3   -0.50 -0.99 0.0158 0.9972   0.9813 to 0.9972
  20 g2g4   -1.25 -1.74 0.0028 1.0000   0.9972 to 1.0000
I have added the bounds of the pseudorandom numbers to pick each move in a try to clarify my proposal (just be careful with the bounds: < or =<, but never making a pseudorandom number able to pick more than a move). Then, if your pseudorandom number is 0.6027, the move to be played is Nc3 (0.5541 < 0.6027 < 0.6066). In this example, there are more less the same odds of playing the top-5 moves than the other 15.

Thanks again for your time. I do not exactly know how a chess engine works. Would be fair and correct that the evaluations of all the moves are from the same depth or it does not matter if some evals are from a certain depth and the rest from depth - 1 if the full depth search has not been completed yet?

Regards from Spain.

Ajedrecista.
So my P(i) and F(i) is ok now.

Now my issue is how to pick a move?
Do you have a replacement for this general formula?

Code: Select all

if [F(i-1) < r =< F(i)] then
  pick move i
end if
In the column "Pseudorandom number" is this fixed no matter what position?
Thanks again for your time. I do not exactly know how a chess engine works. Would be fair and correct that the evaluations of all the moves are from the same depth or it does not matter if some evals are from a certain depth and the rest from depth - 1 if the full depth search has not been completed yet?
when I send go depth 16 to sf12, every move and score are from depth 16. So they are fair.

Here is an example from startpos with sf 12, go depth 16.
go depth 16

Code: Select all

 num move  scores  d(i)   P(i)   F(i)
   1 e2e4    0.49  0.00 0.1549 0.1549
   2 d2d4    0.29 -0.20 0.0977 0.1954
   3 g1f3    0.29 -0.20 0.0977 0.2931
   4 c2c4    0.21 -0.28 0.0813 0.3580
   5 e2e3    0.13 -0.36 0.0676 0.4119
   6 a2a3    0.04 -0.45 0.0549 0.4541
   7 b1c3    0.02 -0.47 0.0525 0.5042
   8 g2g3    0.01 -0.48 0.0513 0.5543
   9 c2c3   -0.01 -0.50 0.0490 0.6010
  10 a2a4   -0.08 -0.57 0.0417 0.6354
  11 b2b4   -0.09 -0.58 0.0407 0.6751
  12 h2h3   -0.10 -0.59 0.0398 0.7140
  13 d2d3   -0.16 -0.65 0.0347 0.7436
  14 b2b3   -0.16 -0.65 0.0347 0.7783
  15 h2h4   -0.32 -0.81 0.0240 0.7916
  16 f2f4   -0.33 -0.82 0.0234 0.8144
  17 b1a3   -0.45 -0.94 0.0178 0.8266
  18 g1h3   -0.45 -0.94 0.0178 0.8444
  19 f2f3   -0.50 -0.99 0.0158 0.8582
  20 g2g4   -1.25 -1.74 0.0028 0.8480
info string random number 0.7107
info string move number 11 random number 0.7107
bestmove b2b4

The random number generated is between.

Code: Select all

  11 b2b4   -0.09 -0.58 0.0407 0.6751
  12 h2h3   -0.10 -0.59 0.0398 0.7140
I selected the top move 11.