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

Remove mate score display from basic certainty propagation #4

Open
wants to merge 2 commits into
base: basic-certainty-propagation
Choose a base branch
from
Open
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
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
build/
testdata/
LC0VSProj/
CUDA_NN/
.DS_Store
xcuserdata
subprojects/*
!subprojects/*.wrap
lc0.xcodeproj/
*.swp
2 changes: 0 additions & 2 deletions src/chess/callbacks.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,6 @@ struct ThinkingInfo {
int hashfull = -1;
// Win in centipawns.
optional<int> score;
// Distance to mate.
optional<int> mate;
// Number of successful TB probes (not the same as playouts ending in TB hit).
int tb_hits = -1;
// Best line found. Moves are from perspective of white player.
Expand Down
8 changes: 1 addition & 7 deletions src/chess/uciloop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,7 @@ void UciLoop::SendInfo(const std::vector<ThinkingInfo>& infos) {
if (info.seldepth >= 0) res += " seldepth " + std::to_string(info.seldepth);
if (info.time >= 0) res += " time " + std::to_string(info.time);
if (info.nodes >= 0) res += " nodes " + std::to_string(info.nodes);

// If mate display mate, otherwise if score display score.
if (info.mate) {
res += " score mate " + std::to_string(*info.mate);
} else if (info.score) {
res += " score cp " + std::to_string(*info.score);
}
if (info.score) res += " score cp " + std::to_string(*info.score);
if (info.hashfull >= 0) res += " hashfull " + std::to_string(info.hashfull);
if (info.nps >= 0) res += " nps " + std::to_string(info.nps);
if (info.tb_hits >= 0) res += " tbhits " + std::to_string(info.tb_hits);
Expand Down
1 change: 0 additions & 1 deletion src/engine.cc
Original file line number Diff line number Diff line change
Expand Up @@ -349,7 +349,6 @@ void EngineController::Go(const GoParams& params) {
if (info.multipv <= 1) {
ponder_info = info;
if (ponder_info.score) ponder_info.score = -*ponder_info.score;
if (ponder_info.mate) ponder_info.mate = -*ponder_info.mate;
if (ponder_info.depth > 1) ponder_info.depth--;
if (ponder_info.seldepth > 1) ponder_info.seldepth--;
ponder_info.pv.clear();
Expand Down
3 changes: 1 addition & 2 deletions src/mcts/params.cc
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ const OptionId SearchParams::kHistoryFillId{
"synthesize them (always, never, or only at non-standard fen position)."};
const OptionId SearchParams::kCertaintyPropagationId{
"certainty-propagation", "CertaintyPropagation",
"Propagates certain scores more efficiently in the search tree, "
"proves and displays mates."};
"Propagates certain scores more efficiently in the search tree."};
const OptionId SearchParams::kTwoFoldDrawScoringId{
"two-fold-draw-scoring", "TwoFoldDrawScoring",
"Scores two-folds as draws (0.00) in search to use visits more "
Expand Down
45 changes: 10 additions & 35 deletions src/mcts/search.cc
Original file line number Diff line number Diff line change
Expand Up @@ -142,22 +142,6 @@ void Search::SendUciInfo() REQUIRES(nodes_mutex_) {
uci_info.pv.push_back(iter.GetMove(flip));
if (!iter.node()) break; // Last edge was dangling, cannot continue.
}

// Mate display if certain win (or loss) with distance to mate set to
// length of pv (average mate).
// If win is based on propagated TB bit, length of mate is
// adjusted by +1000; For root filtered TB moves +500.
if (params_.GetCertaintyPropagation()) {
if (edge.IsCertain() && edge.GetEQ() != 0)
uci_info.mate = edge.GetEQ() * ((uci_info.pv.size() + 1) / 2 +
(edge.IsPropagatedTBHit() ? 1000 : 0));
else if (root_syzygy_rank_) {
int sign = (root_syzygy_rank_ - 1 > 0) - (root_syzygy_rank_ - 1 < 0);
if (sign) {
uci_info.mate = sign * (-500 + abs(root_syzygy_rank_));
} else uci_info.score = 0;
}
}
}

if (!uci_infos.empty()) last_outputted_uci_info_ = uci_infos.front();
Expand Down Expand Up @@ -463,28 +447,22 @@ std::int64_t Search::GetTotalPlayouts() const {
return total_playouts_;
}

int Search::PopulateRootMoveLimit(MoveList* root_moves) const {
bool Search::PopulateRootMoveLimit(MoveList* root_moves) const {
// Search moves overrides tablebase.
if (!limits_.searchmoves.empty()) {
*root_moves = limits_.searchmoves;
return 0;
return false;
}

// Syzygy root_probe returns best_rank for proper eval if
// moves are syzygy root filtered.
auto board = played_history_.Last().GetBoard();
if (!syzygy_tb_ || !board.castlings().no_legal_castle() ||
(board.ours() | board.theirs()).count() > syzygy_tb_->max_cardinality()) {
return 0;
return false;
}

int best_rank = syzygy_tb_->root_probe(
played_history_.Last(), params_.GetSyzygyFastPlay() ||
played_history_.DidRepeatSinceLastZeroingMove(),
root_moves);
if (!best_rank)
best_rank = syzygy_tb_->root_probe_wdl(played_history_.Last(), root_moves);
return best_rank;
return syzygy_tb_->root_probe(played_history_.Last(),
params_.GetSyzygyFastPlay() ||
played_history_.DidRepeatSinceLastZeroingMove(),
root_moves) ||
syzygy_tb_->root_probe_wdl(played_history_.Last(), root_moves);
}

// Computes the best move, maybe with temperature (according to the settings).
Expand Down Expand Up @@ -773,10 +751,8 @@ void SearchWorker::InitializeIteration(

if (!root_move_filter_populated_) {
root_move_filter_populated_ = true;
int best_rank = search_->PopulateRootMoveLimit(&root_move_filter_);
if (best_rank) {
if (search_->PopulateRootMoveLimit(&root_move_filter_)) {
search_->tb_hits_.fetch_add(1, std::memory_order_acq_rel);
search_->root_syzygy_rank_ = best_rank;
}
}
}
Expand Down Expand Up @@ -1068,8 +1044,7 @@ void SearchWorker::EvalPosition(Node* node, MoveList& legal_moves,
}

// Neither by-position or by-rule termination, but maybe it's a TB position.
if (!search_->root_syzygy_rank_ && search_->syzygy_tb_ &&
board.castlings().no_legal_castle() &&
if (search_->syzygy_tb_ && board.castlings().no_legal_castle() &&
history_.Last().GetNoCaptureNoPawnPly() == 0 &&
(board.ours() | board.theirs()).count() <=
search_->syzygy_tb_->max_cardinality()) {
Expand Down
3 changes: 1 addition & 2 deletions src/mcts/search.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ class Search {
// Populates the given list with allowed root moves.
// Returns best_rank != 0 if the population came from tablebase.
// 1 for draw, > 1 for win and < 1 for loss
int PopulateRootMoveLimit(MoveList* root_moves) const;
bool PopulateRootMoveLimit(MoveList* root_moves) const;

// Returns verbose information about given node, as vector of strings.
std::vector<std::string> GetVerboseStats(Node* node,
Expand Down Expand Up @@ -179,7 +179,6 @@ class Search {
// Cummulative depth of all paths taken in PickNodetoExtend.
uint64_t cum_depth_ GUARDED_BY(nodes_mutex_) = 0;
std::atomic<int> tb_hits_{0};
std::atomic<int> root_syzygy_rank_{0};

BestMoveInfo::Callback best_move_callback_;
ThinkingInfo::Callback info_callback_;
Expand Down
23 changes: 11 additions & 12 deletions src/syzygy/syzygy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1623,9 +1623,9 @@ int SyzygyTablebase::probe_dtz(const Position& pos, ProbeState* result) {
}

// Use the DTZ tables to rank root moves.
// A return value 0 indicates that not all probes were successful.
// Otherwise best rank is returned, with rank 1 = draw.
int SyzygyTablebase::root_probe(const Position& pos, bool has_repeated,
//
// A return value false indicates that not all probes were successful.
bool SyzygyTablebase::root_probe(const Position& pos, bool has_repeated,
std::vector<Move>* safe_moves) {
ProbeState result;
auto root_moves = pos.GetBoard().GenerateLegalMoves();
Expand Down Expand Up @@ -1655,14 +1655,14 @@ int SyzygyTablebase::root_probe(const Position& pos, bool has_repeated,
next_pos.GetBoard().GenerateLegalMoves().size() == 0) {
dtz = 1;
}
if (result == FAIL) return 0;
if (result == FAIL) return false;
// Better moves are ranked higher. Certain wins are ranked equally.
// Losing moves are ranked equally unless a 50-move draw is in sight.
int r = dtz > 0
? (dtz + cnt50 <= 99 && !rep ? 1000 : 1000 - (dtz + cnt50))
: dtz < 0 ? (-dtz * 2 + cnt50 < 100 ? -1000
: -1000 + (-dtz + cnt50))
: 1;
: 0;
if (r > best_rank) best_rank = r;
ranks.push_back(r);
}
Expand All @@ -1674,17 +1674,16 @@ int SyzygyTablebase::root_probe(const Position& pos, bool has_repeated,
}
counter++;
}
return best_rank;
return true;
}

// Use the WDL tables to rank root moves.
// This is a fallback for the case that some or all DTZ tables are missing.
//
// A return value 0 indicates that not all probes were successful.
// Otherwise best rank is returned with rank 1 = draw.
int SyzygyTablebase::root_probe_wdl(const Position& pos,
// A return value false indicates that not all probes were successful.
bool SyzygyTablebase::root_probe_wdl(const Position& pos,
std::vector<Move>* safe_moves) {
static const int WDL_to_rank[] = {-1000, -899, 1, 899, 1000};
static const int WDL_to_rank[] = {-1000, -899, 0, 899, 1000};
auto root_moves = pos.GetBoard().GenerateLegalMoves();
ProbeState result;
std::vector<int> ranks;
Expand All @@ -1694,7 +1693,7 @@ int SyzygyTablebase::root_probe_wdl(const Position& pos,
for (auto& m : root_moves) {
Position nextPos = Position(pos, m);
WDLScore wdl = static_cast<WDLScore>(-probe_wdl(nextPos, &result));
if (result == FAIL) return 0;
if (result == FAIL) return false;
ranks.push_back(WDL_to_rank[wdl + 2]);
if (ranks.back() > best_rank) best_rank = ranks.back();
}
Expand All @@ -1706,6 +1705,6 @@ int SyzygyTablebase::root_probe_wdl(const Position& pos,
}
counter++;
}
return best_rank;
return true;
}
} // namespace lczero
7 changes: 3 additions & 4 deletions src/syzygy/syzygy.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,16 @@ class SyzygyTablebase {
// has_repeated should be whether there are any repeats since last 50 move
// counter reset.
// Thread safe.
// Returns 0 if the position is not in the tablebase, and best rank
// if found (1 = draw, > 1 for wins, < 1 for losses)
// Returns false if the position is not in the tablebase.
// Safe moves are added to the safe_moves output paramater.
int root_probe(const Position& pos, bool has_repeated,
bool root_probe(const Position& pos, bool has_repeated,
std::vector<Move>* safe_moves);
// Probes WDL tables to determine which moves might be on the optimal play
// path. If 50 move ply counter is non-zero some (or maybe even all) of the
// returned safe moves in a 'winning' position, may actually be draws.
// Returns false if the position is not in the tablebase.
// Safe moves are added to the safe_moves output paramater.
int root_probe_wdl(const Position& pos, std::vector<Move>* safe_moves);
bool root_probe_wdl(const Position& pos, std::vector<Move>* safe_moves);

private:
template <bool CheckZeroingMoves = false>
Expand Down