Skip to content

Monomial hashes again, so stored values are found through their index - #2104

Merged
rocky merged 3 commits into
masterfrom
monomial-hashable
Nov 4, 2026
Merged

rocky merged 3 commits into
masterfrom
monomial-hashable

Conversation

@tombouctou

Copy link
Copy Markdown
Collaborator

Stored values such as f[1] = a are meant to be found through an index (LiteralRuleIndex, #2013). The index keeps the sort keys (pattern_precedence) of the rules in a set.

Since #2073 those keys can contain a Monomial. Monomial defines __eq__, so Python dropped its default __hash__. As a result:

No test caught it, because #2013's tests did not come along with it.

Change: Monomial.__hash__ hashes the (variable, exponent) pairs that __eq__ compares, so equal monomials hash equally (1 and 1.0 included).

Measurements

  • 100 lookups among 400 stored values: 5050 SameQ calls on master, now 200.
  • Combinatorica's SetGraphOptions, rewritten to look options up in such a table (Mathics3-Package-Combinatorica, set-graph-options-index), becomes linear in the number of edges with this fix.

Tests: test/core/test_literal_rule_index.py. Both tests fail on master.

  • Monomials hash the way they compare.
  • The index is built for 400 stored values plus a pattern rule, and lookups through it cost a few comparisons each; results are checked, including the fallback to the pattern rule.

The full pytest run and the doctests pass.

🤖 Generated with Claude Code

tombouctou and others added 3 commits November 4, 2026 19:36
Stored values such as f[1] = a are found through an index
(LiteralRuleIndex, #2013), which keeps the sort keys of the rules in a
set. Since #2073 those keys can hold a Monomial, which defines __eq__
and so lost its default __hash__: building the index raised TypeError,
which it takes to mean "can not be indexed", and every lookup went
through all the rules again.

Monomial now hashes the pairs of variables and exponents it compares.

100 lookups among 400 stored values: 5050 SameQ on master, now 200.
Combinatorica's SetGraphOptions, with a table of the edges' option
groups, depends on this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@rocky

rocky commented Nov 4, 2026

Copy link
Copy Markdown
Member

LGTM. Very good catch in finding the subtle bug here.

@rocky
rocky merged commit a5ac187 into master Nov 4, 2026
15 checks passed
@rocky
rocky deleted the monomial-hashable branch November 4, 2026 17:27
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