Skip to content

Normalize book weights #1109

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

Merged
merged 8 commits into from
May 29, 2025

Conversation

AttackingOrDefending
Copy link
Member

Type of pull request:

  • Bug fix
  • Feature
  • Other

Description:

Adds the ability to normalize the weights of an opening book, so that min_weight can be used more easily across different books.

Related Issues:

#1107

Checklist:

  • I have read and followed the contribution guidelines.
  • I have added necessary documentation (if applicable).
  • The changes pass all existing tests.

Screenshots/logs (if applicable):

@MarkZH
Copy link
Collaborator

MarkZH commented May 16, 2025

I don't understand how this PR changes anything. Scaling the weights shouldn't matter, since all that matters is their relative sizes. Multiplying every weight by the same number should result in the same probability.

Also, it looks like the new random choices in the get_move_from_entries() function behave the same as the find() (best_move), choice() (uniform_random), and weighted_choice() (weighted_random) methods of the python-chess polyglot reader.

After reading the linked issue, are these changes about making min_weight have a consistent meaning? In that case, it would be easier to scale min_weight. Something like this:

min_weight = polyglot_cfg.min_weight
normalization = polyglot_cfg.normalization
entries = reader.find_all(board)
scalar = (100 if normalization == "none"
          else sum(entry.weight for entry in entries) if normalization == "sum"
          else max(entry.weight for entry in entries) if normalization == "max")
min_weight = min_weight*scalar/100
# I think this is equivalent to the change in the PR.

# The rest of the function is unchanged.

if selection == "weighted_random":
    move = reader.weighted_choice(board).move
elif selection == "uniform_random":
    move = reader.choice(board, minimum_weight=min_weight).move
elif selection == "best_move":
    move = reader.find(board, minimum_weight=min_weight).move

@AttackingOrDefending
Copy link
Member Author

The goal was to normalize the weights of an opening book, as they can be in the range of 0-65535, and even in the same opening book some positions may have a sum of weights <= 10 and others > 100000. This makes min_weight hard to use as a value of 20 wouldn't leave any move in the first position but would leave all the moves in the second. Indeed, scaling min_weight instead of the weights of the entries seems to be an easier way to accomplish the same goal.

@MarkZH
Copy link
Collaborator

MarkZH commented May 20, 2025

Is it possible that the maximum score will be negative? If so, the scalar should be calculated with the absolute value. Otherwise, it would change the sign of the min_weight.

The documentation for min_weight should have a reference to the normalization section.

How are checkmates handled in books? If they have an infinite score, then do the book functions correctly handle that?

@AttackingOrDefending
Copy link
Member Author

The weights in polyglot opening books are unsigned 16-bit integers so they take values from 0 to 65535.

@MarkZH MarkZH merged commit f358074 into lichess-bot-devs:master May 29, 2025
23 checks passed
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.

2 participants