Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tune Histories #5712

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/history.h
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ using LowPlyHistory = Stats<int16_t, 7183, LOW_PLY_HISTORY_SIZE, int(SQUARE_NB)
using CapturePieceToHistory = Stats<int16_t, 10692, PIECE_NB, SQUARE_NB, PIECE_TYPE_NB>;

// PieceToHistory is like ButterflyHistory but is addressed by a move's [piece][to]
using PieceToHistory = Stats<int16_t, 29952, PIECE_NB, SQUARE_NB>;
using PieceToHistory = Stats<int16_t, 30000, PIECE_NB, SQUARE_NB>;

// ContinuationHistory is the combined history of a given pair of moves, usually
// the current one given a previous one. The nested history table is based on
Expand Down
76 changes: 39 additions & 37 deletions src/search.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ void Search::Worker::iterative_deepening() {

int searchAgainCounter = 0;

lowPlyHistory.fill(0);
lowPlyHistory.fill(106);

// Iterative deepening loop until requested to stop or the target depth is reached
while (++rootDepth < MAX_PLY && !threads.stop
Expand Down Expand Up @@ -500,10 +500,10 @@ void Search::Worker::iterative_deepening() {

// Reset histories, usually before a new game
void Search::Worker::clear() {
mainHistory.fill(0);
lowPlyHistory.fill(0);
captureHistory.fill(-758);
pawnHistory.fill(-1158);
mainHistory.fill(61);
lowPlyHistory.fill(106);
captureHistory.fill(-598);
pawnHistory.fill(-1181);
pawnCorrectionHistory.fill(0);
majorPieceCorrectionHistory.fill(0);
minorPieceCorrectionHistory.fill(0);
Expand All @@ -518,7 +518,7 @@ void Search::Worker::clear() {
for (StatsType c : {NoCaptures, Captures})
for (auto& to : continuationHistory[inCheck][c])
for (auto& h : to)
h->fill(-645);
h->fill(-427);

for (size_t i = 1; i < reductions.size(); ++i)
reductions[i] = int((19.43 + std::log(size_t(options["Threads"])) / 2) * std::log(i));
Expand All @@ -538,7 +538,7 @@ Value Search::Worker::search(

// Dive into quiescence search when the depth reaches zero
if (depth <= 0)
return qsearch < PvNode ? PV : NonPV > (pos, ss, alpha, beta);
return qsearch<PvNode ? PV : NonPV>(pos, ss, alpha, beta);

// Limit the depth if extensions made it too large
depth = std::min(depth, MAX_PLY - 1);
Expand Down Expand Up @@ -644,13 +644,13 @@ Value Search::Worker::search(
{
// Bonus for a quiet ttMove that fails high (~2 Elo)
if (!ttCapture)
update_quiet_histories(pos, ss, *this, ttData.move, stat_bonus(depth));
update_quiet_histories(pos, ss, *this, ttData.move, stat_bonus(depth) * 747 / 1024);

// Extra penalty for early quiet moves of
// the previous ply (~1 Elo on STC, ~2 Elo on LTC)
if (prevSq != SQ_NONE && (ss - 1)->moveCount <= 2 && !priorCapture)
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
-stat_malus(depth + 1));
-stat_malus(depth + 1) * 1091 / 1024);
}

// Partial workaround for the graph history interaction problem
Expand Down Expand Up @@ -762,10 +762,10 @@ Value Search::Worker::search(
if (((ss - 1)->currentMove).is_ok() && !(ss - 1)->inCheck && !priorCapture)
{
int bonus = std::clamp(-10 * int((ss - 1)->staticEval + ss->staticEval), -1831, 1428) + 623;
thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus;
thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << bonus * 1340 / 1024;
if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION)
thisThread->pawnHistory[pawn_structure_index(pos)][pos.piece_on(prevSq)][prevSq]
<< bonus;
<< bonus * 1159 / 1024;
}

// Set up the improving flag, which is true if current static evaluation is
Expand Down Expand Up @@ -909,7 +909,7 @@ Value Search::Worker::search(

if (value >= probCutBeta)
{
thisThread->captureHistory[movedPiece][move.to_sq()][type_of(captured)] << 1300;
thisThread->captureHistory[movedPiece][move.to_sq()][type_of(captured)] << 1226;

// Save ProbCut data into transposition table
ttWriter.write(posKey, value_to_tt(value, ss->ply), ss->ttPv, BOUND_LOWER,
Expand Down Expand Up @@ -1216,8 +1216,8 @@ Value Search::Worker::search(
value = -search<NonPV>(pos, ss + 1, -(alpha + 1), -alpha, newDepth, !cutNode);

// Post LMR continuation history updates (~1 Elo)
int bonus = 2 * (value >= beta) * stat_bonus(newDepth);
update_continuation_histories(ss, movedPiece, move.to_sq(), bonus);
int bonus = (value >= beta) * stat_bonus(newDepth);
update_continuation_histories(ss, movedPiece, move.to_sq(), bonus * 1427 / 1024);
}
}

Expand Down Expand Up @@ -1379,24 +1379,25 @@ Value Search::Worker::search(
// Bonus for prior countermove that caused the fail low
else if (!priorCapture && prevSq != SQ_NONE)
{
int bonus = (117 * (depth > 5) + 39 * !allNode + 168 * ((ss - 1)->moveCount > 8)
+ 115 * (!ss->inCheck && bestValue <= ss->staticEval - 108)
+ 119 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 83));
int bonusScale = (117 * (depth > 5) + 39 * !allNode + 168 * ((ss - 1)->moveCount > 8)
+ 115 * (!ss->inCheck && bestValue <= ss->staticEval - 108)
+ 119 * (!(ss - 1)->inCheck && bestValue <= -(ss - 1)->staticEval - 83));

// Proportional to "how much damage we have to undo"
bonus += std::min(-(ss - 1)->statScore / 113, 300);
bonusScale += std::min(-(ss - 1)->statScore / 113, 300);

bonus = std::max(bonus, 0);
bonusScale = std::max(bonusScale, 0);

const int scaledBonus = stat_bonus(depth) * bonusScale / 32;

update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq,
stat_bonus(depth) * bonus / 93);
thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()]
<< stat_bonus(depth) * bonus / 179;
scaledBonus * 416 / 1024);

thisThread->mainHistory[~us][((ss - 1)->currentMove).from_to()] << scaledBonus * 212 / 1024;

if (type_of(pos.piece_on(prevSq)) != PAWN && ((ss - 1)->currentMove).type_of() != PROMOTION)
thisThread->pawnHistory[pawn_structure_index(pos)][pos.piece_on(prevSq)][prevSq]
<< stat_bonus(depth) * bonus / 24;
<< scaledBonus * 1073 / 1024;
}

else if (priorCapture && prevSq != SQ_NONE)
Expand All @@ -1410,7 +1411,7 @@ Value Search::Worker::search(

// Bonus when search fails low and there is a TT move
else if (ttData.move && !allNode)
thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) * 23 / 100;
thisThread->mainHistory[us][ttData.move.from_to()] << stat_bonus(depth) * 287 / 1024;

if (PvNode)
bestValue = std::min(bestValue, maxValue);
Expand Down Expand Up @@ -1808,47 +1809,47 @@ void update_all_stats(const Position& pos,

if (!pos.capture_stage(bestMove))
{
update_quiet_histories(pos, ss, workerThread, bestMove, bonus);
update_quiet_histories(pos, ss, workerThread, bestMove, bonus * 1131 / 1024);

// Decrease stats for all non-best quiet moves
for (Move move : quietsSearched)
update_quiet_histories(pos, ss, workerThread, move, -malus);
update_quiet_histories(pos, ss, workerThread, move, -malus * 1028 / 1024);
}
else
{
// Increase stats for the best move in case it was a capture move
captured = type_of(pos.piece_on(bestMove.to_sq()));
captureHistory[moved_piece][bestMove.to_sq()][captured] << bonus;
captureHistory[moved_piece][bestMove.to_sq()][captured] << bonus * 1291 / 1024;
}

// Extra penalty for a quiet early move that was not a TT move in
// previous ply when it gets refuted.
if (prevSq != SQ_NONE && ((ss - 1)->moveCount == 1 + (ss - 1)->ttHit) && !pos.captured_piece())
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus);
update_continuation_histories(ss - 1, pos.piece_on(prevSq), prevSq, -malus * 919 / 1024);

// Decrease stats for all non-best capture moves
for (Move move : capturesSearched)
{
moved_piece = pos.moved_piece(move);
captured = type_of(pos.piece_on(move.to_sq()));
captureHistory[moved_piece][move.to_sq()][captured] << -malus;
captureHistory[moved_piece][move.to_sq()][captured] << -malus * 1090 / 1024;
}
}


// Updates histories of the move pairs formed by moves
// at ply -1, -2, -3, -4, and -6 with current move.
void update_continuation_histories(Stack* ss, Piece pc, Square to, int bonus) {
static constexpr std::array<ConthistBonus, 5> conthist_bonuses = {
{{1, 1024}, {2, 571}, {3, 339}, {4, 500}, {6, 592}}};

bonus = bonus * 50 / 64;

for (int i : {1, 2, 3, 4, 6})
for (const auto [i, weight] : conthist_bonuses)
{
// Only update the first 2 continuation histories if we are in check
if (ss->inCheck && i > 2)
break;
if (((ss - i)->currentMove).is_ok())
(*(ss - i)->continuationHistory)[pc][to] << bonus / (1 + (i == 3));
(*(ss - i)->continuationHistory)[pc][to] << bonus * weight / 1024;
}
}

Expand All @@ -1858,14 +1859,15 @@ void update_quiet_histories(
const Position& pos, Stack* ss, Search::Worker& workerThread, Move move, int bonus) {

Color us = pos.side_to_move();
workerThread.mainHistory[us][move.from_to()] << bonus;
workerThread.mainHistory[us][move.from_to()] << bonus; // Untuned to prevent duplicate effort

if (ss->ply < LOW_PLY_HISTORY_SIZE)
workerThread.lowPlyHistory[ss->ply][move.from_to()] << bonus;
workerThread.lowPlyHistory[ss->ply][move.from_to()] << bonus * 874 / 1024;

update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus);
update_continuation_histories(ss, pos.moved_piece(move), move.to_sq(), bonus * 853 / 1024);

int pIndex = pawn_structure_index(pos);
workerThread.pawnHistory[pIndex][pos.moved_piece(move)][move.to_sq()] << bonus / 2;
workerThread.pawnHistory[pIndex][pos.moved_piece(move)][move.to_sq()] << bonus * 628 / 1024;
}

}
Expand Down
5 changes: 5 additions & 0 deletions src/search.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ class Worker {
friend class SearchManager;
};

struct ConthistBonus {
int index;
int weight;
};


} // namespace Search

Expand Down
Loading