]> git.sesse.net Git - stockfish/commitdiff
Remove Tempo
authorStéphane Nicolet <cassio@free.fr>
Tue, 18 May 2021 23:24:51 +0000 (01:24 +0200)
committerStéphane Nicolet <cassio@free.fr>
Wed, 19 May 2021 18:34:37 +0000 (20:34 +0200)
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

src/evaluate.cpp
src/search.cpp
src/timeman.cpp
src/timeman.h
src/types.h

index 256bd9944f3a6e9a4bb6a0c3a186117af56dcc93..543644ee96b201e49f31ec87f35cc17ff312d199 100644 (file)
@@ -1058,7 +1058,7 @@ make_v:
     v = (v / 16) * 16;
 
     // 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;
   }
@@ -1119,7 +1119,7 @@ Value Eval::evaluate(const Position& pos) {
 
          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())
              nnue += fix_FRC(pos);
index 6e1d2b5321a96e4332fa0cc689fe5921703414ae..359a774fd706cb4f7341b81c86e3675a85dad6c8 100644 (file)
@@ -767,7 +767,7 @@ namespace {
         if ((ss-1)->currentMove != MOVE_NULL)
             ss->staticEval = eval = evaluate(pos);
         else
-            ss->staticEval = eval = -(ss-1)->staticEval + 2 * Tempo;
+            ss->staticEval = eval = -(ss-1)->staticEval;
 
         // Save static evaluation into transposition table
         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
     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;
     }
 
@@ -1436,7 +1436,7 @@ moves_loop: // When in check, search starts from here
             // and addition of two tempos
             ss->staticEval = bestValue =
             (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
         if (bestValue >= beta)
index 3236b6e9bbb46ec15ad353607cba1a1a4dc8835c..f742d1e44221cd831022774a1163211812a81c56 100644 (file)
@@ -94,14 +94,6 @@ void TimeManagement::init(Search::LimitsType& limits, Color us, int ply) {
   optimumTime = TimePoint(optScale * timeLeft);
   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"])
       optimumTime += optimumTime / 4;
 }
index 4ac0b4be8a4178aaad72acff0ee15b0144dc9461..b1878d65f25fca5e77fade3c3765966296ac4e81 100644 (file)
@@ -37,7 +37,6 @@ public:
                                      TimePoint(Threads.nodes_searched()) : now() - startTime; }
 
   int64_t availableNodes; // When in 'nodes as time' mode
-  int tempoNNUE;
 
 private:
   TimePoint startTime;
index efebce1a7b6f730f2b77c111bb66c6efed73fc79..0bd4a1c4090c0044940f7128dca99f09e49d244e 100644 (file)
@@ -191,7 +191,6 @@ enum Value : int {
   BishopValueMg = 825,   BishopValueEg = 915,
   RookValueMg   = 1276,  RookValueEg   = 1380,
   QueenValueMg  = 2538,  QueenValueEg  = 2682,
-  Tempo = 28,
 
   MidgameLimit  = 15258, EndgameLimit  = 3915
 };