Skip to content

Use normalized centipawn conversion formula#2398

Open
Menkib64 wants to merge 6 commits intoLeelaChessZero:masterfrom
Menkib64:normalized_centipawn
Open

Use normalized centipawn conversion formula#2398
Menkib64 wants to merge 6 commits intoLeelaChessZero:masterfrom
Menkib64:normalized_centipawn

Conversation

@Menkib64
Copy link
Copy Markdown
Contributor

This centipawn conversion formula has been fitted trought 3 fixed points. 75% expected score is 1.00 centipawns. 100% expected score is 128.0 centipawns. 50% expected score is 0.0 centipawns.

Default score type is changed to centipawn because WDL_mu doesn't match how search ranks moves.

This centipawn conversion formula has been fitted trought 3 fixed
points. 75% expected score is 1.00 centipawns. 100% expected score is
128.0 centipawns. 50% expected score is 0.0 centipawns.

Default score type is changed to centipawn because WDL_mu doesn't
match how search ranks moves.
Copilot AI review requested due to automatic review settings March 13, 2026 20:28
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adjusts how the engine reports evaluation scores over UCI by retuning the “centipawn” conversion and switching the default score display type to standard centipawns.

Changes:

  • Updated the score-type=centipawn WL→centipawn conversion constants in both classic and dag_classic search output.
  • Changed the default ScoreType option from WDL_mu to centipawn.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
src/search/dag_classic/search.cc Updates centipawn score conversion used in UCI info score output for dag_classic search.
src/search/classic/search.cc Updates centipawn score conversion used in UCI info score output for classic search.
src/search/classic/params.cc Changes the default ScoreType option value to centipawn.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

You can also share your feedback on Copilot code review. Take the survey.

Comment on lines 319 to 323
} else if (score_type == "centipawn_with_drawscore") {
uci_info.score = 90 * tan(1.5637541897 * q);
} else if (score_type == "centipawn") {
uci_info.score = 90 * tan(1.5637541897 * wl);
uci_info.score = 100.79055 * tan(1.56292199291664 * wl);
} else if (score_type == "centipawn_2019") {
Comment on lines 367 to 371
} else if (score_type == "centipawn_with_drawscore") {
uci_info.score = 90 * tan(1.5637541897 * q);
} else if (score_type == "centipawn") {
uci_info.score = 90 * tan(1.5637541897 * wl);
uci_info.score = 100.79055 * tan(1.56292199291664 * wl);
} else if (score_type == "centipawn_2019") {
Comment thread src/search/classic/params.cc Outdated
Comment on lines +591 to +595
@@ -592,7 +592,7 @@ void BaseSearchParams::Populate(OptionsParser* options) {
"Q",
"W-L",
"WDL_mu"};
options->Add<ChoiceOption>(kScoreTypeId, score_type) = "WDL_mu";
options->Add<ChoiceOption>(kScoreTypeId, score_type) = "centipawn";
uci_info.score = 90 * tan(1.5637541897 * q);
} else if (score_type == "centipawn") {
uci_info.score = 90 * tan(1.5637541897 * wl);
uci_info.score = 100.79055 * tan(1.56292199291664 * wl);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Usually when we update centipawn formula, we keep previous as centipawn_<year> (where year is when it was introduced)

@mooskagh mooskagh requested a review from Naphthalin March 21, 2026 07:16
@Naphthalin
Copy link
Copy Markdown
Contributor

I'm strongly against changing the default centipawn formula back to being Q based for several reasons:

  • Q (as derived from WDL) is inherently dependent on the playing conditions (specified through WDLCalibrationElo), which means Q values for the same position aren't comparable
  • the primary objective of an eval is to communicate something about a position, and the absolute meaning is in 95% of use cases more important than multiPV moves being in the "right" order
  • to add on that, ordering of moves isn't something universal either, and again depends on the playing conditions -- if you have e.g. a +2.5 position, there might be a riskier move which (when played through precisely) maintains the +2.5 eval, and a safe alternative which is only +2.2 but has no counterplay. I personally fail to see the downside of Leela recommending the +2.2 line over the +2.5 line, and trust the user to not get confused by this.
  • and ultimately, the several mathematical properties of WDL_mu mean it can 1:1 be translated to SF evals (assuming they're perfectly normalized) in the range of [-2.5, +2.5] which wasn't the case for any Q based eval we tried so far, nor will it be the case for this formula. The fallback behavior (which is unfortunately necessary) isn't ideal, but only rarely relevant for TCEC conditions which shouldn't be our primary development target.

Furthermore, search doesn't order moves by Q anyway, but by nodes -- which is of course closely correlated with Q, but so is the WDL_mu eval.

In total, reverting back to a Q based centipawn formula would put a significant burden in interpreting and translating Leela's eval, including suffering from old issues where different nets give vastly different evals at default settings because of having different inherent draw rates. I'm not generally against adding a new centipawn_2026 score type option, but definitely don't want to see it as the default.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants