Skip to content

Commit 472e726

Browse files
Vizvezdenecvondele
authored andcommitted
Search tuning at very long time control
This patch is a result of tuning session of approximately 100k games at 120+1.2. Biggest changes are in extensions, stat bonus and depth reduction for nodes without a tt move. Failed STC: https://tests.stockfishchess.org/tests/view/63f72c72e74a12625bcd7938 LLR: -2.94 (-2.94,2.94) <0.00,2.00> Total: 13872 W: 3535 L: 3769 D: 6568 Ptnml(0-2): 56, 1621, 3800, 1419, 40 Close to neutral at LTC: https://tests.stockfishchess.org/tests/view/63f738f5e74a12625bcd7b8a Elo: 0.80 +-1.2 (95%) LOS: 90.0% Total: 60000 W: 16213 L: 16074 D: 27713 Ptnml(0-2): 24, 5718, 18379, 5853, 26 nElo: 1.82 +-2.8 (95%) PairsRatio: 1.02 Passed 180+1.8 VLTC: https://tests.stockfishchess.org/tests/view/63f868f3e74a12625bcdb33e LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 15864 W: 4449 L: 4202 D: 7213 Ptnml(0-2): 1, 1301, 5083, 1544, 3 Passed 60+0.6 8 threads SMP VLTC: https://tests.stockfishchess.org/tests/view/63f8a5d6e74a12625bcdbdb3 LLR: 2.94 (-2.94,2.94) <0.50,2.50> Total: 6288 W: 1821 L: 1604 D: 2863 Ptnml(0-2): 0, 402, 2123, 619, 0 closes #4406 bench 4705194
1 parent 29b5ad5 commit 472e726

File tree

1 file changed

+51
-51
lines changed

1 file changed

+51
-51
lines changed

src/search.cpp

Lines changed: 51 additions & 51 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(158 * (d - improving));
66+
return Value(154 * (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 + 1460 - int(delta) * 1024 / int(rootDelta)) / 1024 + (!i && r > 937);
74+
return (r + 1449 - int(delta) * 1032 / int(rootDelta)) / 1024 + (!i && r > 941);
7575
}
7676

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

8282
// History and stats update bonus, based on depth
8383
int stat_bonus(Depth d) {
84-
return std::min(350 * d - 400, 1650);
84+
return std::min(340 * d - 470, 1855);
8585
}
8686

8787
// Add a small random component to draw evaluations to avoid 3-fold blindness
@@ -161,7 +161,7 @@ namespace {
161161
void Search::init() {
162162

163163
for (int i = 1; i < MAX_MOVES; ++i)
164-
Reductions[i] = int((20.26 + std::log(Threads.size()) / 2) * std::log(i));
164+
Reductions[i] = int((19.47 + std::log(Threads.size()) / 2) * std::log(i));
165165
}
166166

167167

@@ -354,12 +354,12 @@ void Thread::search() {
354354
if (rootDepth >= 4)
355355
{
356356
Value prev = rootMoves[pvIdx].averageScore;
357-
delta = Value(10) + int(prev) * prev / 15400;
357+
delta = Value(10) + int(prev) * prev / 16502;
358358
alpha = std::max(prev - delta,-VALUE_INFINITE);
359359
beta = std::min(prev + delta, VALUE_INFINITE);
360360

361361
// Adjust optimism based on root move's previousScore
362-
int opt = 116 * prev / (std::abs(prev) + 170);
362+
int opt = 120 * prev / (std::abs(prev) + 161);
363363
optimism[ us] = Value(opt);
364364
optimism[~us] = -optimism[us];
365365
}
@@ -462,16 +462,16 @@ void Thread::search() {
462462
&& !Threads.stop
463463
&& !mainThread->stopOnPonderhit)
464464
{
465-
double fallingEval = (71 + 12 * (mainThread->bestPreviousAverageScore - bestValue)
466-
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 656.7;
465+
double fallingEval = (69 + 13 * (mainThread->bestPreviousAverageScore - bestValue)
466+
+ 6 * (mainThread->iterValue[iterIdx] - bestValue)) / 619.6;
467467
fallingEval = std::clamp(fallingEval, 0.5, 1.5);
468468

469469
// If the bestMove is stable over several iterations, reduce time accordingly
470-
timeReduction = lastBestMoveDepth + 9 < completedDepth ? 1.37 : 0.65;
471-
double reduction = (1.4 + mainThread->previousTimeReduction) / (2.15 * timeReduction);
472-
double bestMoveInstability = 1 + 1.7 * totBestMoveChanges / Threads.size();
470+
timeReduction = lastBestMoveDepth + 8 < completedDepth ? 1.57 : 0.65;
471+
double reduction = (1.4 + mainThread->previousTimeReduction) / (2.08 * timeReduction);
472+
double bestMoveInstability = 1 + 1.8 * totBestMoveChanges / Threads.size();
473473
int complexity = mainThread->complexityAverage.value();
474-
double complexPosition = std::min(1.0 + (complexity - 261) / 1738.7, 1.5);
474+
double complexPosition = std::min(1.03 + (complexity - 241) / 1552.0, 1.45);
475475

476476
double totalTime = Time.optimum() * fallingEval * reduction * bestMoveInstability * complexPosition;
477477

@@ -491,7 +491,7 @@ void Thread::search() {
491491
Threads.stop = true;
492492
}
493493
else if ( !mainThread->ponder
494-
&& Time.elapsed() > totalTime * 0.53)
494+
&& Time.elapsed() > totalTime * 0.50)
495495
Threads.increaseDepth = false;
496496
else
497497
Threads.increaseDepth = true;
@@ -760,7 +760,7 @@ namespace {
760760
// Use static evaluation difference to improve quiet move ordering (~4 Elo)
761761
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
762762
{
763-
int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1940, 1940);
763+
int bonus = std::clamp(-19 * int((ss-1)->staticEval + ss->staticEval), -1920, 1920);
764764
thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus;
765765
}
766766

@@ -770,13 +770,13 @@ namespace {
770770
// margin and the improving flag are used in various pruning heuristics.
771771
improvement = (ss-2)->staticEval != VALUE_NONE ? ss->staticEval - (ss-2)->staticEval
772772
: (ss-4)->staticEval != VALUE_NONE ? ss->staticEval - (ss-4)->staticEval
773-
: 172;
773+
: 156;
774774
improving = improvement > 0;
775775

776776
// Step 7. Razoring (~1 Elo).
777777
// If eval is really low check with qsearch if it can exceed alpha, if it can't,
778778
// return a fail low.
779-
if (eval < alpha - 394 - 255 * depth * depth)
779+
if (eval < alpha - 426 - 252 * depth * depth)
780780
{
781781
value = qsearch<NonPV>(pos, ss, alpha - 1, alpha);
782782
if (value < alpha)
@@ -786,27 +786,27 @@ namespace {
786786
// Step 8. Futility pruning: child node (~40 Elo).
787787
// The depth condition is important for mate finding.
788788
if ( !ss->ttPv
789-
&& depth < 8
790-
&& eval - futility_margin(depth, improving) - (ss-1)->statScore / 304 >= beta
789+
&& depth < 9
790+
&& eval - futility_margin(depth, improving) - (ss-1)->statScore / 280 >= beta
791791
&& eval >= beta
792-
&& eval < 28580) // larger than VALUE_KNOWN_WIN, but smaller than TB wins
792+
&& eval < 25128) // larger than VALUE_KNOWN_WIN, but smaller than TB wins
793793
return eval;
794794

795795
// Step 9. Null move search with verification search (~35 Elo)
796796
if ( !PvNode
797797
&& (ss-1)->currentMove != MOVE_NULL
798-
&& (ss-1)->statScore < 18200
798+
&& (ss-1)->statScore < 18755
799799
&& eval >= beta
800800
&& eval >= ss->staticEval
801-
&& ss->staticEval >= beta - 20 * depth - improvement / 14 + 235 + complexity / 24
801+
&& ss->staticEval >= beta - 19 * depth - improvement / 13 + 253 + complexity / 25
802802
&& !excludedMove
803803
&& pos.non_pawn_material(us)
804804
&& (ss->ply >= thisThread->nmpMinPly || us != thisThread->nmpColor))
805805
{
806806
assert(eval - beta >= 0);
807807

808808
// Null move dynamic reduction based on depth, eval and complexity of position
809-
Depth R = std::min(int(eval - beta) / 165, 6) + depth / 3 + 4 - (complexity > 800);
809+
Depth R = std::min(int(eval - beta) / 168, 6) + depth / 3 + 4 - (complexity > 825);
810810

811811
ss->currentMove = MOVE_NULL;
812812
ss->continuationHistory = &thisThread->continuationHistory[0][0][NO_PIECE][0];
@@ -842,7 +842,7 @@ namespace {
842842
}
843843
}
844844

845-
probCutBeta = beta + 180 - 54 * improving;
845+
probCutBeta = beta + 186 - 54 * improving;
846846

847847
// Step 10. ProbCut (~10 Elo)
848848
// If we have a good enough capture and a reduced search returns a value
@@ -904,14 +904,14 @@ namespace {
904904
return qsearch<PV>(pos, ss, alpha, beta);
905905

906906
if ( cutNode
907-
&& depth >= 9
907+
&& depth >= 7
908908
&& !ttMove)
909909
depth -= 2;
910910

911911
moves_loop: // When in check, search starts here
912912

913913
// Step 12. A small Probcut idea, when we are in check (~4 Elo)
914-
probCutBeta = beta + 402;
914+
probCutBeta = beta + 391;
915915
if ( ss->inCheck
916916
&& !PvNode
917917
&& depth >= 2
@@ -1006,14 +1006,14 @@ namespace {
10061006
// Futility pruning for captures (~2 Elo)
10071007
if ( !givesCheck
10081008
&& !PvNode
1009-
&& lmrDepth < 7
1009+
&& lmrDepth < 6
10101010
&& !ss->inCheck
1011-
&& ss->staticEval + 185 + 203 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
1012-
+ captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 6 < alpha)
1011+
&& ss->staticEval + 182 + 230 * lmrDepth + PieceValue[EG][pos.piece_on(to_sq(move))]
1012+
+ captureHistory[movedPiece][to_sq(move)][type_of(pos.piece_on(to_sq(move)))] / 7 < alpha)
10131013
continue;
10141014

10151015
// SEE based pruning (~11 Elo)
1016-
if (!pos.see_ge(move, Value(-220) * depth))
1016+
if (!pos.see_ge(move, Value(-206) * depth))
10171017
continue;
10181018
}
10191019
else
@@ -1024,24 +1024,24 @@ namespace {
10241024

10251025
// Continuation history based pruning (~2 Elo)
10261026
if ( lmrDepth < 5
1027-
&& history < -4180 * (depth - 1))
1027+
&& history < -4405 * (depth - 1))
10281028
continue;
10291029

10301030
history += 2 * thisThread->mainHistory[us][from_to(move)];
10311031

1032-
lmrDepth += history / 7208;
1032+
lmrDepth += history / 7278;
10331033
lmrDepth = std::max(lmrDepth, -2);
10341034

10351035
// Futility pruning: parent node (~13 Elo)
10361036
if ( !ss->inCheck
10371037
&& lmrDepth < 13
1038-
&& ss->staticEval + 103 + 136 * lmrDepth <= alpha)
1038+
&& ss->staticEval + 103 + 138 * lmrDepth <= alpha)
10391039
continue;
10401040

10411041
lmrDepth = std::max(lmrDepth, 0);
10421042

10431043
// Prune moves with negative SEE (~4 Elo)
1044-
if (!pos.see_ge(move, Value(-25 * lmrDepth * lmrDepth - 16 * lmrDepth)))
1044+
if (!pos.see_ge(move, Value(-24 * lmrDepth * lmrDepth - 15 * lmrDepth)))
10451045
continue;
10461046
}
10471047
}
@@ -1056,15 +1056,15 @@ namespace {
10561056
// a reduced search on all the other moves but the ttMove and if the
10571057
// result is lower than ttValue minus a margin, then we will extend the ttMove.
10581058
if ( !rootNode
1059-
&& depth >= 4 - (thisThread->completedDepth > 22) + 2 * (PvNode && tte->is_pv())
1059+
&& depth >= 4 - (thisThread->completedDepth > 21) + 2 * (PvNode && tte->is_pv())
10601060
&& move == ttMove
10611061
&& !excludedMove // Avoid recursive singular search
10621062
/* && ttValue != VALUE_NONE Already implicit in the next condition */
10631063
&& abs(ttValue) < VALUE_KNOWN_WIN
10641064
&& (tte->bound() & BOUND_LOWER)
10651065
&& tte->depth() >= depth - 3)
10661066
{
1067-
Value singularBeta = ttValue - (3 + (ss->ttPv && !PvNode)) * depth;
1067+
Value singularBeta = ttValue - (2 + (ss->ttPv && !PvNode)) * depth;
10681068
Depth singularDepth = (depth - 1) / 2;
10691069

10701070
ss->excludedMove = move;
@@ -1083,7 +1083,7 @@ namespace {
10831083
&& ss->doubleExtensions <= 10)
10841084
{
10851085
extension = 2;
1086-
depth += depth < 12;
1086+
depth += depth < 13;
10871087
}
10881088
}
10891089

@@ -1106,15 +1106,15 @@ namespace {
11061106

11071107
// Check extensions (~1 Elo)
11081108
else if ( givesCheck
1109-
&& depth > 9
1110-
&& abs(ss->staticEval) > 78)
1109+
&& depth > 10
1110+
&& abs(ss->staticEval) > 88)
11111111
extension = 1;
11121112

11131113
// Quiet ttMove extensions (~1 Elo)
11141114
else if ( PvNode
11151115
&& move == ttMove
11161116
&& move == ss->killers[0]
1117-
&& (*contHist[0])[movedPiece][to_sq(move)] >= 5600)
1117+
&& (*contHist[0])[movedPiece][to_sq(move)] >= 5705)
11181118
extension = 1;
11191119
}
11201120

@@ -1155,7 +1155,7 @@ namespace {
11551155

11561156
// Decrease reduction for PvNodes based on depth
11571157
if (PvNode)
1158-
r -= 1 + 11 / (3 + depth);
1158+
r -= 1 + 12 / (3 + depth);
11591159

11601160
// Decrease reduction if ttMove has been singularly extended (~1 Elo)
11611161
if (singularQuietLMR)
@@ -1172,17 +1172,17 @@ namespace {
11721172

11731173
// Decrease reduction if move is a killer and we have a good history
11741174
if (move == ss->killers[0]
1175-
&& (*contHist[0])[movedPiece][to_sq(move)] >= 3600)
1175+
&& (*contHist[0])[movedPiece][to_sq(move)] >= 3722)
11761176
r--;
11771177

11781178
ss->statScore = 2 * thisThread->mainHistory[us][from_to(move)]
11791179
+ (*contHist[0])[movedPiece][to_sq(move)]
11801180
+ (*contHist[1])[movedPiece][to_sq(move)]
11811181
+ (*contHist[3])[movedPiece][to_sq(move)]
1182-
- 4467;
1182+
- 4182;
11831183

11841184
// Decrease/increase reduction for moves with a good/bad history (~30 Elo)
1185-
r -= ss->statScore / (12800 + 4410 * (depth > 7 && depth < 19));
1185+
r -= ss->statScore / (11791 + 3992 * (depth > 6 && depth < 19));
11861186

11871187
// Step 17. Late moves reduction / extension (LMR, ~117 Elo)
11881188
// We use various heuristics for the sons of a node after the first son has
@@ -1206,8 +1206,8 @@ namespace {
12061206
{
12071207
// Adjust full depth search based on LMR results - if result
12081208
// was good enough search deeper, if it was bad enough search shallower
1209-
const bool doDeeperSearch = value > (alpha + 66 + 11 * (newDepth - d));
1210-
const bool doEvenDeeperSearch = value > alpha + 582 && ss->doubleExtensions <= 5;
1209+
const bool doDeeperSearch = value > (alpha + 58 + 12 * (newDepth - d));
1210+
const bool doEvenDeeperSearch = value > alpha + 588 && ss->doubleExtensions <= 5;
12111211
const bool doShallowerSearch = value < bestValue + newDepth;
12121212

12131213
ss->doubleExtensions = ss->doubleExtensions + doEvenDeeperSearch;
@@ -1318,8 +1318,8 @@ namespace {
13181318
// Reduce other moves if we have found at least one score improvement
13191319
if ( depth > 1
13201320
&& depth < 6
1321-
&& beta < VALUE_KNOWN_WIN
1322-
&& alpha > -VALUE_KNOWN_WIN)
1321+
&& beta < 10534
1322+
&& alpha > -10534)
13231323
depth -= 1;
13241324

13251325
assert(depth > 0);
@@ -1374,7 +1374,7 @@ namespace {
13741374
else if (!priorCapture)
13751375
{
13761376
// Extra bonuses for PV/Cut nodes or bad fail lows
1377-
int bonus = (depth > 4) + (PvNode || cutNode) + (bestValue < alpha - 88 * depth);
1377+
int bonus = (depth > 5) + (PvNode || cutNode) + (bestValue < alpha - 97 * depth);
13781378
update_continuation_histories(ss-1, pos.piece_on(prevSq), prevSq, stat_bonus(depth) * bonus);
13791379
}
13801380

@@ -1502,7 +1502,7 @@ namespace {
15021502
if (PvNode && bestValue > alpha)
15031503
alpha = bestValue;
15041504

1505-
futilityBase = bestValue + 158;
1505+
futilityBase = bestValue + 168;
15061506
}
15071507

15081508
const PieceToHistory* contHist[] = { (ss-1)->continuationHistory, (ss-2)->continuationHistory,
@@ -1575,7 +1575,7 @@ namespace {
15751575
continue;
15761576

15771577
// Do not search moves with bad enough SEE values (~5 Elo)
1578-
if (!pos.see_ge(move, Value(-108)))
1578+
if (!pos.see_ge(move, Value(-110)))
15791579
continue;
15801580

15811581
}
@@ -1708,7 +1708,7 @@ namespace {
17081708

17091709
if (!pos.capture(bestMove))
17101710
{
1711-
int bonus2 = bestValue > beta + 146 ? bonus1 // larger bonus
1711+
int bonus2 = bestValue > beta + 153 ? bonus1 // larger bonus
17121712
: stat_bonus(depth); // smaller bonus
17131713

17141714
// Increase stats for the best move in case it was a quiet move

0 commit comments

Comments
 (0)