mirror of
https://github.com/HChaZZY/Stockfish.git
synced 2025-12-20 17:16:33 +08:00
Remove Tempo
The Tempo variable was introduced 10 years ago in our search because the
classical evaluation function was antisymmetrical in White and Black by design
to gain speed:
Eval(White to play) = -Eval(Black to play)
Nowadays our neural networks know which side is to play in a position when
they evaluate a position and are trained on real games, so the neural network
encodes the advantage of moving as an output of search. This patch shows that
the Tempo variable is not necessary anymore.
STC:
LLR: 2.94 (-2.94,2.94) <-2.50,0.50>
Total: 33512 W: 2805 L: 2709 D: 27998
Ptnml(0-2): 80, 2209, 12095, 2279, 93
https://tests.stockfishchess.org/tests/view/60a44ceace8ea25a3ef03d30
LTC:
LLR: 2.95 (-2.94,2.94) <-2.50,0.50>
Total: 53920 W: 1807 L: 1760 D: 50353
Ptnml(0-2): 16, 1617, 23650, 1658, 19
https://tests.stockfishchess.org/tests/view/60a477f0ce8ea25a3ef03d49
We also tried a match (20000 games) at STC using purely classical, result was neutral:
https://tests.stockfishchess.org/tests/view/60a4eebcce8ea25a3ef03db5
Note: there are two locations left in search.cpp where we assume antisymmetry
of evaluation (in relation with a speed optimization for null moves in lines
770 and 1439), but as the values are just used for heuristic pruning this
approximation should not hurt too much because the order of magnitude is still
true most of the time.
closes https://github.com/official-stockfish/Stockfish/pull/3481
Bench: 4015864
This commit is contained in:
@@ -1058,7 +1058,7 @@ make_v:
|
|||||||
v = (v / 16) * 16;
|
v = (v / 16) * 16;
|
||||||
|
|
||||||
// Side to move point of view
|
// Side to move point of view
|
||||||
v = (pos.side_to_move() == WHITE ? v : -v) + Tempo;
|
v = (pos.side_to_move() == WHITE ? v : -v);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
@@ -1119,7 +1119,7 @@ Value Eval::evaluate(const Position& pos) {
|
|||||||
|
|
||||||
int scale = 903 + 28 * pos.count<PAWN>() + 28 * pos.non_pawn_material() / 1024;
|
int scale = 903 + 28 * pos.count<PAWN>() + 28 * pos.non_pawn_material() / 1024;
|
||||||
|
|
||||||
Value nnue = NNUE::evaluate(pos) * scale / 1024 + Time.tempoNNUE;
|
Value nnue = NNUE::evaluate(pos) * scale / 1024;
|
||||||
|
|
||||||
if (pos.is_chess960())
|
if (pos.is_chess960())
|
||||||
nnue += fix_FRC(pos);
|
nnue += fix_FRC(pos);
|
||||||
|
|||||||
@@ -767,7 +767,7 @@ namespace {
|
|||||||
if ((ss-1)->currentMove != MOVE_NULL)
|
if ((ss-1)->currentMove != MOVE_NULL)
|
||||||
ss->staticEval = eval = evaluate(pos);
|
ss->staticEval = eval = evaluate(pos);
|
||||||
else
|
else
|
||||||
ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
|
ss->staticEval = eval = -(ss-1)->staticEval;
|
||||||
|
|
||||||
// Save static evaluation into transposition table
|
// Save static evaluation into transposition table
|
||||||
tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
|
tte->save(posKey, VALUE_NONE, ss->ttPv, BOUND_NONE, DEPTH_NONE, MOVE_NONE, eval);
|
||||||
@@ -776,7 +776,7 @@ namespace {
|
|||||||
// Use static evaluation difference to improve quiet move ordering
|
// Use static evaluation difference to improve quiet move ordering
|
||||||
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
|
if (is_ok((ss-1)->currentMove) && !(ss-1)->inCheck && !priorCapture)
|
||||||
{
|
{
|
||||||
int bonus = std::clamp(-depth * 4 * int((ss-1)->staticEval + ss->staticEval - 2 * Tempo), -1000, 1000);
|
int bonus = std::clamp(-depth * 4 * int((ss-1)->staticEval + ss->staticEval), -1000, 1000);
|
||||||
thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus;
|
thisThread->mainHistory[~us][from_to((ss-1)->currentMove)] << bonus;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1436,7 +1436,7 @@ moves_loop: // When in check, search starts from here
|
|||||||
// and addition of two tempos
|
// and addition of two tempos
|
||||||
ss->staticEval = bestValue =
|
ss->staticEval = bestValue =
|
||||||
(ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
|
(ss-1)->currentMove != MOVE_NULL ? evaluate(pos)
|
||||||
: -(ss-1)->staticEval + 2 * Tempo;
|
: -(ss-1)->staticEval;
|
||||||
|
|
||||||
// Stand pat. Return immediately if static value is at least beta
|
// Stand pat. Return immediately if static value is at least beta
|
||||||
if (bestValue >= beta)
|
if (bestValue >= beta)
|
||||||
|
|||||||
@@ -94,14 +94,6 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
|
|||||||
optimumTime = TimePoint(optScale * timeLeft);
|
optimumTime = TimePoint(optScale * timeLeft);
|
||||||
maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, maxScale * optimumTime));
|
maximumTime = TimePoint(std::min(0.8 * limits.time[us] - moveOverhead, maxScale * optimumTime));
|
||||||
|
|
||||||
if (Stockfish::Search::Limits.use_time_management())
|
|
||||||
{
|
|
||||||
int strength = std::log( std::max(1, int(optimumTime * Threads.size() / 10))) * 60;
|
|
||||||
tempoNNUE = std::clamp( (strength + 264) / 24, 18, 30);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
tempoNNUE = 28; // default for no time given
|
|
||||||
|
|
||||||
if (Options["Ponder"])
|
if (Options["Ponder"])
|
||||||
optimumTime += optimumTime / 4;
|
optimumTime += optimumTime / 4;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,6 @@ public:
|
|||||||
TimePoint(Threads.nodes_searched()) : now() - startTime; }
|
TimePoint(Threads.nodes_searched()) : now() - startTime; }
|
||||||
|
|
||||||
int64_t availableNodes; // When in 'nodes as time' mode
|
int64_t availableNodes; // When in 'nodes as time' mode
|
||||||
int tempoNNUE;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TimePoint startTime;
|
TimePoint startTime;
|
||||||
|
|||||||
@@ -191,7 +191,6 @@ enum Value : int {
|
|||||||
BishopValueMg = 825, BishopValueEg = 915,
|
BishopValueMg = 825, BishopValueEg = 915,
|
||||||
RookValueMg = 1276, RookValueEg = 1380,
|
RookValueMg = 1276, RookValueEg = 1380,
|
||||||
QueenValueMg = 2538, QueenValueEg = 2682,
|
QueenValueMg = 2538, QueenValueEg = 2682,
|
||||||
Tempo = 28,
|
|
||||||
|
|
||||||
MidgameLimit = 15258, EndgameLimit = 3915
|
MidgameLimit = 15258, EndgameLimit = 3915
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user