From f5a31b7e576e2e56825fcfdff75c739ed545e852 Mon Sep 17 00:00:00 2001 From: Guenther Demetz Date: Tue, 22 Nov 2022 11:07:18 +0100 Subject: [PATCH] Correctly output lowerbound/upperbound in threaded searches fixes the lowerbound/upperbound output by taking the alpha,beta bracket into account also if a bestThread is selected that is different from the master thread. Instead of keeping track which bounds where used in the specific search, in this version we simply store the quality (exact, upperbound, lowerbound) of the score along with the actual score as information on rootMove. closes https://github.com/official-stockfish/Stockfish/pull/4239 No functional change --- src/search.cpp | 14 ++++++++------ src/search.h | 2 ++ src/uci.h | 2 +- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/search.cpp b/src/search.cpp index e73f68ff..b3f60f3d 100644 --- a/src/search.cpp +++ b/src/search.cpp @@ -244,7 +244,7 @@ void MainThread::search() { // Send again PV info if we have a new best thread if (bestThread != this) - sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth, -VALUE_INFINITE, VALUE_INFINITE) << sync_endl; + sync_cout << UCI::pv(bestThread->rootPos, bestThread->completedDepth) << sync_endl; sync_cout << "bestmove " << UCI::move(bestThread->rootMoves[0].pv[0], rootPos.is_chess960()); @@ -392,7 +392,7 @@ void Thread::search() { && multiPV == 1 && (bestValue <= alpha || bestValue >= beta) && Time.elapsed() > 3000) - sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; + sync_cout << UCI::pv(rootPos, rootDepth) << sync_endl; // In case of failing low/high increase aspiration window and // re-search, otherwise exit the loop. @@ -423,7 +423,7 @@ void Thread::search() { if ( mainThread && (Threads.stop || pvIdx + 1 == multiPV || Time.elapsed() > 3000)) - sync_cout << UCI::pv(rootPos, rootDepth, alpha, beta) << sync_endl; + sync_cout << UCI::pv(rootPos, rootDepth) << sync_endl; } if (!Threads.stop) @@ -1246,6 +1246,8 @@ moves_loop: // When in check, search starts here { rm.score = value; rm.selDepth = thisThread->selDepth; + rm.scoreLowerbound = value >= beta; + rm.scoreUpperbound = value <= alpha; rm.pv.resize(1); assert((ss+1)->pv); @@ -1820,7 +1822,7 @@ void MainThread::check_time() { /// UCI::pv() formats PV information according to the UCI protocol. UCI requires /// that all (if any) unsearched PV lines are sent using a previous search score. -string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { +string UCI::pv(const Position& pos, Depth depth) { std::stringstream ss; TimePoint elapsed = Time.elapsed() + 1; @@ -1858,8 +1860,8 @@ string UCI::pv(const Position& pos, Depth depth, Value alpha, Value beta) { if (Options["UCI_ShowWDL"]) ss << UCI::wdl(v, pos.game_ply()); - if (!tb && i == pvIdx) - ss << (v >= beta ? " lowerbound" : v <= alpha ? " upperbound" : ""); + if (i == pvIdx && !tb && updated) // tablebase- and previous-scores are exact + ss << (rootMoves[i].scoreLowerbound ? " lowerbound" : (rootMoves[i].scoreUpperbound ? " upperbound" : "")); ss << " nodes " << nodesSearched << " nps " << nodesSearched * 1000 / elapsed diff --git a/src/search.h b/src/search.h index f264bcae..60f2762a 100644 --- a/src/search.h +++ b/src/search.h @@ -71,6 +71,8 @@ struct RootMove { Value score = -VALUE_INFINITE; Value previousScore = -VALUE_INFINITE; Value averageScore = -VALUE_INFINITE; + bool scoreLowerbound = false; + bool scoreUpperbound = false; int selDepth = 0; int tbRank = 0; Value tbScore; diff --git a/src/uci.h b/src/uci.h index 7a2ef255..3b5a6764 100644 --- a/src/uci.h +++ b/src/uci.h @@ -79,7 +79,7 @@ void loop(int argc, char* argv[]); std::string value(Value v); std::string square(Square s); std::string move(Move m, bool chess960); -std::string pv(const Position& pos, Depth depth, Value alpha, Value beta); +std::string pv(const Position& pos, Depth depth); std::string wdl(Value v, int ply); Move to_move(const Position& pos, std::string& str); -- 2.39.2