From e7e78aa09e190ea0fd7fed6fcff97d98c0cf5b5f Mon Sep 17 00:00:00 2001 From: Shawn Xu Date: Sat, 14 Dec 2024 15:13:32 -0800 Subject: [PATCH] Adjust LMR with correction history A positive constant increase in base reduction is applied to counter the decrease in average reduction from this tweak. Passed STC: LLR: 2.98 (-2.94,2.94) <0.00,2.00> Total: 109216 W: 28415 L: 27989 D: 52812 Ptnml(0-2): 310, 12848, 27911, 13184, 355 https://tests.stockfishchess.org/tests/view/6760bb0e86d5ee47d9542f26 Passed LTC: LLR: 2.95 (-2.94,2.94) <0.50,2.50> Total: 66918 W: 17073 L: 16694 D: 33151 Ptnml(0-2): 33, 7175, 18666, 7550, 35 https://tests.stockfishchess.org/tests/view/6761e10f86d5ee47d95431fa closes https://github.com/official-stockfish/Stockfish/pull/5727 Bench: 1294909 --- src/search.cpp | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index 02d7b677707..f184a353942 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -77,9 +77,7 @@ constexpr int futility_move_count(bool improving, Depth depth) { return (3 + depth * depth) / (2 - improving); } -// Add correctionHistory value to raw staticEval and guarantee evaluation -// does not hit the tablebase range. -Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos, Stack* ss) { +int correction_value(const Worker& w, const Position& pos, Stack* ss) { const Color us = pos.side_to_move(); const auto m = (ss - 1)->currentMove; const auto pcv = w.pawnCorrectionHistory[us][pawn_structure_index(pos)]; @@ -87,15 +85,17 @@ Value to_corrected_static_eval(Value v, const Worker& w, const Position& pos, St const auto micv = w.minorPieceCorrectionHistory[us][minor_piece_index(pos)]; const auto wnpcv = w.nonPawnCorrectionHistory[WHITE][us][non_pawn_index(pos)]; const auto bnpcv = w.nonPawnCorrectionHistory[BLACK][us][non_pawn_index(pos)]; - int cntcv = 1; + const auto cntcv = + m.is_ok() ? (*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()] + : 0; - if (m.is_ok()) - cntcv = int((*(ss - 2)->continuationCorrectionHistory)[pos.piece_on(m.to_sq())][m.to_sq()]); + return (6384 * pcv + 3583 * macv + 6492 * micv + 6725 * (wnpcv + bnpcv) + 5880 * cntcv); +} - const auto cv = - (6384 * pcv + 3583 * macv + 6492 * micv + 6725 * (wnpcv + bnpcv) + cntcv * 5880) / 131072; - v += cv; - return std::clamp(v, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); +// Add correctionHistory value to raw staticEval and guarantee evaluation +// does not hit the tablebase range. +Value to_corrected_static_eval(Value v, const int cv) { + return std::clamp(v + cv / 131072, VALUE_TB_LOSS_IN_MAX_PLY + 1, VALUE_TB_WIN_IN_MAX_PLY - 1); } // History and stats update bonus, based on depth @@ -709,7 +709,8 @@ Value Search::Worker::search( } // Step 6. Static evaluation of the position - Value unadjustedStaticEval = VALUE_NONE; + Value unadjustedStaticEval = VALUE_NONE; + const auto correctionValue = correction_value(*thisThread, pos, ss); if (ss->inCheck) { // Skip early pruning when in check @@ -733,8 +734,7 @@ Value Search::Worker::search( else if (PvNode) Eval::NNUE::hint_common_parent_position(pos, networks[numaAccessToken], refreshTable); - ss->staticEval = eval = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, correctionValue); // ttValue can be used as a better position evaluation (~7 Elo) if (is_valid(ttData.value) @@ -744,8 +744,7 @@ Value Search::Worker::search( else { unadjustedStaticEval = evaluate(pos); - ss->staticEval = eval = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + ss->staticEval = eval = to_corrected_static_eval(unadjustedStaticEval, correctionValue); // Static evaluation is saved as it was before adjustment by correction history ttWriter.write(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_UNSEARCHED, Move::none(), @@ -1155,6 +1154,10 @@ Value Search::Worker::search( // These reduction adjustments have no proven non-linear scaling + r += 330; + + r -= std::min(std::abs(correctionValue) / 32768, 2048); + // Increase reduction for cut nodes (~4 Elo) if (cutNode) r += 2518 - (ttData.depth >= depth && ss->ttPv) * 991; @@ -1525,7 +1528,8 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) return ttData.value; // Step 4. Static evaluation of the position - Value unadjustedStaticEval = VALUE_NONE; + Value unadjustedStaticEval = VALUE_NONE; + const auto correctionValue = correction_value(*thisThread, pos, ss); if (ss->inCheck) bestValue = futilityBase = -VALUE_INFINITE; else @@ -1537,7 +1541,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) if (!is_valid(unadjustedStaticEval)) unadjustedStaticEval = evaluate(pos); ss->staticEval = bestValue = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + to_corrected_static_eval(unadjustedStaticEval, correctionValue); // ttValue can be used as a better position evaluation (~13 Elo) if (is_valid(ttData.value) && !is_decisive(ttData.value) @@ -1550,7 +1554,7 @@ Value Search::Worker::qsearch(Position& pos, Stack* ss, Value alpha, Value beta) unadjustedStaticEval = (ss - 1)->currentMove != Move::null() ? evaluate(pos) : -(ss - 1)->staticEval; ss->staticEval = bestValue = - to_corrected_static_eval(unadjustedStaticEval, *thisThread, pos, ss); + to_corrected_static_eval(unadjustedStaticEval, correctionValue); } // Stand pat. Return immediately if static value is at least beta