Skip to content

Commit b0b3155

Browse files
Vizvezdenecvondele
authored andcommitted
Big search tuning
Most credits for this patch should go to @candirufish. Based on his big search tuning (1M games at 20+0.1s) https://tests.stockfishchess.org/tests/view/61fc7a6ed508ec6a1c9f4b7d with some hand polishing on top of it, which includes : a) correcting trend sigmoid - for some reason original tuning resulted in it being negative. This heuristic was proven to be worth some elo for years so reversing it sign is probably some random artefact; b) remove changes to continuation history based pruning - this heuristic historically was really good at providing green STCs and then failing at LTC miserably if we tried to make it more strict, original tuning was done at short time control and thus it became more strict - which doesn't scale to longer time controls; c) remove changes to improvement - not really indended :). passed STC https://tests.stockfishchess.org/tests/view/6203526e88ae2c84271c2ee2 LLR: 2.94 (-2.94,2.94) <0.00,2.50> Total: 16840 W: 4604 L: 4363 D: 7873 Ptnml(0-2): 82, 1780, 4449, 2033, 76 passed LTC https://tests.stockfishchess.org/tests/view/620376e888ae2c84271c35d4 LLR: 2.96 (-2.94,2.94) <0.50,3.00> Total: 17232 W: 4771 L: 4542 D: 7919 Ptnml(0-2): 14, 1655, 5048, 1886, 13 closes #3926 bench 5030992
1 parent 08ac4e9 commit b0b3155

File tree

1 file changed

+46
-47
lines changed

1 file changed

+46
-47
lines changed

src/search.cpp

Lines changed: 46 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,15 @@ namespace {
6363

6464
// Futility margin
6565
Value futility_margin(Depth d, bool improving) {
66-
return Value(214 * (d - improving));
66+
return Value(171 * (d - improving));
6767
}
6868

6969
// Reductions lookup table, initialized at startup
7070
int Reductions[MAX_MOVES]; // [depth or moveNumber]
7171

7272
Depth reduction(bool i, Depth d, int mn, Value delta, Value rootDelta) {
7373
int r = Reductions[d] * Reductions[mn];
74-
return (r + 1358 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 904);
74+
return (r + 1575 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 1011);
7575
}
7676

7777
constexpr int futility_move_count(bool improving, Depth depth) {
@@ -80,7 +80,7 @@ namespace {
8080

8181
// History and stats update bonus, based on depth
8282
int stat_bonus(Depth d) {
83-
return std::min((6 * d + 229) * d - 215 , 2000);
83+
return std::min((7 * d + 254) * d - 206 , 1990);
8484
}
8585

8686
// Add a small random component to draw evaluations to avoid 3-fold blindness
@@ -157,7 +157,7 @@ namespace {
157157
void Search::init() {
158158

159159
for (int i = 1; i < MAX_MOVES; ++i)
160-
Reductions[i] = int((21.9 + std::log(Threads.size()) / 2) * std::log(i));
160+
Reductions[i] = int((21.5 + std::log(Threads.size()) / 2) * std::log(i));
161161
}
162162

163163

@@ -303,10 +303,10 @@ void Thread::search() {
303303

304304
multiPV = std::min(multiPV, rootMoves.size());
305305

306-
complexityAverage.set(232, 1);
306+
complexityAverage.set(190, 1);
307307

308308
trend = SCORE_ZERO;
309-
optimism[ us] = Value(25);
309+
optimism[ us] = Value(34);
310310
optimism[~us] = -optimism[us];
311311

312312
int searchAgainCounter = 0;
@@ -349,16 +349,16 @@ void Thread::search() {
349349
if (rootDepth >= 4)
350350
{
351351
Value prev = rootMoves[pvIdx].averageScore;
352-
delta = Value(17) + int(prev) * prev / 16384;
352+
delta = Value(16) + int(prev) * prev / 16384;
353353
alpha = std::max(prev - delta,-VALUE_INFINITE);
354354
beta = std::min(prev + delta, VALUE_INFINITE);
355355

356356
// Adjust trend and optimism based on root move's previousScore
357-
int tr = sigmoid(prev, 0, 0, 147, 113, 1);
357+
int tr = sigmoid(prev, 6, 13, 96, 110, 1);
358358
trend = (us == WHITE ? make_score(tr, tr / 2)
359359
: -make_score(tr, tr / 2));
360360

361-
int opt = sigmoid(prev, 0, 25, 147, 14464, 256);
361+
int opt = sigmoid(prev, 7, 21, 94, 14786, 221);
362362
optimism[ us] = Value(opt);
363363
optimism[~us] = -optimism[us];
364364
}
@@ -413,7 +413,7 @@ void Thread::search() {
413413
else
414414
break;
415415

416-
delta += delta / 4 + 5;
416+
delta += delta / 4 + 3;
417417

418418
assert(alpha >= -VALUE_INFINITE && beta <= VALUE_INFINITE);
419419
}
@@ -459,17 +459,17 @@ void Thread::search() {
459459
&& !Threads.stop
460460
&& !mainThread->stopOnPonderhit)
461461
{
462-
double fallingEval = (142 + 12 * (mainThread->bestPreviousAverageScore - bestValue)
463-
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 825.0;
462+
double fallingEval = (87 + 12 * (mainThread->bestPreviousAverageScore - bestValue)
463+
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 777.20;
464464
fallingEval = std::clamp(fallingEval, 0.5, 1.5);
465465

466466
// If the bestMove is stable over several iterations, reduce time accordingly
467-
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.92 : 0.95;
468-
double reduction = (1.47 + mainThread->previousTimeReduction) / (2.32 * timeReduction);
467+
timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.70 : 0.91;
468+
double reduction = (1.59 + mainThread->previousTimeReduction) / (2.33 * timeReduction);
469469
double bestMoveInstability = 1.073 + std::max(1.0, 2.25 - 9.9 / rootDepth)
470470
* totBestMoveChanges / Threads.size();
471471
int complexity = mainThread->complexityAverage.value();
472-
double complexPosition = std::clamp(1.0 + (complexity - 232) / 1750.0, 0.5, 1.5);
472+
double complexPosition = std::clamp(1.0 + (complexity - 312) / 1750.0, 0.5, 1.5);
473473

474474
double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition;
475475

@@ -490,7 +490,7 @@ void Thread::search() {
490490
}
491491
else if ( Threads.increaseDepth
492492
&& !mainThread->ponder
493-
&& Time.elapsed() > totalTime * 0.58)
493+
&& Time.elapsed() > totalTime * 0.55)
494494
Threads.increaseDepth = false;
495495
else
496496
Threads.increaseDepth = true;
@@ -788,19 +788,19 @@ namespace {
788788
// Step 8. Futility pruning: child node (~25 Elo).
789789
// The depth condition is important for mate finding.
790790
if ( !ss->ttPv
791-
&& depth < 9
791+
&& depth < 8
792792
&& eval - futility_margin(depth, improving) - (ss-1)->statScore / 256 >= beta
793793
&& eval >= beta
794-
&& eval < 15000) // 50% larger than VALUE_KNOWN_WIN, but smaller than TB wins.
794+
&& eval < 17548) // 50% larger than VALUE_KNOWN_WIN, but smaller than TB wins.
795795
return eval;
796796

797797
// Step 9. Null move search with verification search (~22 Elo)
798798
if ( !PvNode
799799
&& (ss-1)->currentMove != MOVE_NULL
800-
&& (ss-1)->statScore < 23767
800+
&& (ss-1)->statScore < 13706
801801
&& eval >= beta
802802
&& eval >= ss->staticEval
803-
&& ss->staticEval >= beta - 20 * depth - improvement / 15 + 204 + complexity / 25
803+
&& ss->staticEval >= beta - 19 * depth - improvement / 15 + 200 + complexity / 25
804804
&& !excludedMove
805805
&& pos.non_pawn_material(us)
806806
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
@@ -844,13 +844,13 @@ namespace {
844844
}
845845
}
846846

847-
probCutBeta = beta + 209 - 44 * improving;
847+
probCutBeta = beta + 229 - 47 * improving;
848848

849849
// Step 10. ProbCut (~4 Elo)
850850
// If we have a good enough capture and a reduced search returns a value
851851
// much above beta, we can (almost) safely prune the previous move.
852852
if ( !PvNode
853-
&& depth > 4
853+
&& depth > 3
854854
&& abs(beta) < VALUE_TB_WIN_IN_MAX_PLY
855855
// if value from transposition table is lower than probCutBeta, don't attempt probCut
856856
// there and in further interactions with transposition table cutoff depth is set to depth - 3
@@ -871,7 +871,6 @@ namespace {
871871
if (move != excludedMove && pos.legal(move))
872872
{
873873
assert(pos.capture_or_promotion(move));
874-
assert(depth >= 5);
875874

876875
captureOrPromotion = true;
877876

@@ -909,19 +908,19 @@ namespace {
909908

910909
// Step 11. If the position is not in TT, decrease depth by 2 or 1 depending on node type (~3 Elo)
911910
if ( PvNode
912-
&& depth >= 6
911+
&& depth >= 4
913912
&& !ttMove)
914913
depth -= 2;
915914

916915
if ( cutNode
917-
&& depth >= 9
916+
&& depth >= 7
918917
&& !ttMove)
919918
depth--;
920919

921920
moves_loop: // When in check, search starts here
922921

923922
// Step 12. A small Probcut idea, when we are in check (~0 Elo)
924-
probCutBeta = beta + 409;
923+
probCutBeta = beta + 401;
925924
if ( ss->inCheck
926925
&& !PvNode
927926
&& depth >= 4
@@ -1017,12 +1016,12 @@ namespace {
10171016
&& !PvNode
10181017
&& lmrDepth < 6
10191018
&& !ss->inCheck
1020-
&& ss->staticEval + 342 + 238 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
1019+
&& ss->staticEval + 392 + 207 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
10211020
+ captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 8 < alpha)
10221021
continue;
10231022

10241023
// SEE based pruning (~9 Elo)
1025-
if (!pos.see_ge(move, Value(-217) * depth))
1024+
if (!pos.see_ge(move, Value(-200) * depth))
10261025
continue;
10271026
}
10281027
else
@@ -1040,12 +1039,12 @@ namespace {
10401039

10411040
// Futility pruning: parent node (~9 Elo)
10421041
if ( !ss->inCheck
1043-
&& lmrDepth < 8
1044-
&& ss->staticEval + 138 + 137 * lmrDepth + history / 64 <= alpha)
1042+
&& lmrDepth < 11
1043+
&& ss->staticEval + 131 + 137 * lmrDepth + history / 64 <= alpha)
10451044
continue;
10461045

10471046
// Prune moves with negative SEE (~3 Elo)
1048-
if (!pos.see_ge(move, Value(-21 * lmrDepth * lmrDepth - 21 * lmrDepth)))
1047+
if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 29 * lmrDepth)))
10491048
continue;
10501049
}
10511050
}
@@ -1081,7 +1080,7 @@ namespace {
10811080

10821081
// Avoid search explosion by limiting the number of double extensions
10831082
if ( !PvNode
1084-
&& value < singularBeta - 75
1083+
&& value < singularBeta - 71
10851084
&& ss->doubleExtensions <= 6)
10861085
extension = 2;
10871086
}
@@ -1101,15 +1100,15 @@ namespace {
11011100

11021101
// Check extensions (~1 Elo)
11031102
else if ( givesCheck
1104-
&& depth > 6
1105-
&& abs(ss->staticEval) > 100)
1103+
&& depth > 7
1104+
&& abs(ss->staticEval) > 128)
11061105
extension = 1;
11071106

11081107
// Quiet ttMove extensions (~0 Elo)
11091108
else if ( PvNode
11101109
&& move == ttMove
11111110
&& move == ss->killers[0]
1112-
&& (*contHist[0])[movedPiece][to_sq(move)] >= 10000)
1111+
&& (*contHist[0])[movedPiece][to_sq(move)] >= 8932)
11131112
extension = 1;
11141113
}
11151114

@@ -1136,8 +1135,8 @@ namespace {
11361135
// We use various heuristics for the sons of a node after the first son has
11371136
// been searched. In general we would like to reduce them, but there are many
11381137
// cases where we extend a son if it has good chances to be "interesting".
1139-
if ( depth >= 3
1140-
&& moveCount > 1 + 2 * rootNode
1138+
if ( depth >= 2
1139+
&& moveCount > 1 + rootNode
11411140
&& ( !ss->ttPv
11421141
|| !captureOrPromotion
11431142
|| (cutNode && (ss-1)->moveCount > 1)))
@@ -1146,7 +1145,7 @@ namespace {
11461145

11471146
// Decrease reduction at some PvNodes (~2 Elo)
11481147
if ( PvNode
1149-
&& bestMoveCount <= 3)
1148+
&& bestMoveCount <= 4)
11501149
r--;
11511150

11521151
// Decrease reduction if position is or has been on the PV
@@ -1156,7 +1155,7 @@ namespace {
11561155
r -= 2;
11571156

11581157
// Decrease reduction if opponent's move count is high (~1 Elo)
1159-
if ((ss-1)->moveCount > 13)
1158+
if ((ss-1)->moveCount > 7)
11601159
r--;
11611160

11621161
// Increase reduction for cut nodes (~3 Elo)
@@ -1171,18 +1170,18 @@ namespace {
11711170
+ (*contHist[0])[movedPiece][to_sq(move)]
11721171
+ (*contHist[1])[movedPiece][to_sq(move)]
11731172
+ (*contHist[3])[movedPiece][to_sq(move)]
1174-
- 4923;
1173+
- 4142;
11751174

11761175
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
1177-
r -= ss->statScore / 14721;
1176+
r -= ss->statScore / 15328;
11781177

11791178
// In general we want to cap the LMR depth search at newDepth. But if reductions
11801179
// are really negative and movecount is low, we allow this move to be searched
11811180
// deeper than the first move (this may lead to hidden double extensions).
11821181
int deeper = r >= -1 ? 0
11831182
: moveCount <= 5 ? 2
1184-
: PvNode && depth > 6 ? 1
1185-
: cutNode && moveCount <= 7 ? 1
1183+
: PvNode && depth > 4 ? 1
1184+
: cutNode && moveCount <= 5 ? 1
11861185
: 0;
11871186

11881187
Depth d = std::clamp(newDepth - r, 1, newDepth + deeper);
@@ -1191,7 +1190,7 @@ namespace {
11911190

11921191
// If the son is reduced and fails high it will be re-searched at full depth
11931192
doFullDepthSearch = value > alpha && d < newDepth;
1194-
doDeeperSearch = value > (alpha + 62 + 20 * (newDepth - d));
1193+
doDeeperSearch = value > (alpha + 80 + 20 * (newDepth - d));
11951194
didLMR = true;
11961195
}
11971196
else
@@ -1212,7 +1211,7 @@ namespace {
12121211
: -stat_bonus(newDepth);
12131212

12141213
if (captureOrPromotion)
1215-
bonus /= 4;
1214+
bonus /= 5;
12161215

12171216
update_continuation_histories(ss, movedPiece, to_sq(move), bonus);
12181217
}
@@ -1343,7 +1342,7 @@ namespace {
13431342
//or fail low was really bad
13441343
bool extraBonus = PvNode
13451344
|| cutNode
1346-
|| bestValue < alpha - 94 * depth;
1345+
|| bestValue < alpha - 99 * depth;
13471346

13481347
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * (1 + extraBonus));
13491348
}
@@ -1474,7 +1473,7 @@ namespace {
14741473
if (PvNode && bestValue > alpha)
14751474
alpha = bestValue;
14761475

1477-
futilityBase = bestValue + 155;
1476+
futilityBase = bestValue + 127;
14781477
}
14791478

14801479
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,

0 commit comments

Comments
 (0)