Shape matchers: recognizing families in a parsed equation - #5
Open
roed-math wants to merge 1 commit into
Open
Conversation
Closed
roed-math
force-pushed
the
split/03-registry
branch
from
August 8, 2026 16:12
80a8831 to
127bd1b
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 8, 2026 16:12
7082747 to
9b81d40
Compare
roed-math
force-pushed
the
split/03-registry
branch
from
August 9, 2026 02:43
127bd1b to
52cb94e
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 9, 2026 02:43
9b81d40 to
7ebfa9d
Compare
roed-math
force-pushed
the
split/03-registry
branch
from
August 9, 2026 05:01
52cb94e to
fe35513
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 9, 2026 05:01
7ebfa9d to
006dca5
Compare
roed-math
force-pushed
the
split/03-registry
branch
from
August 9, 2026 05:21
fe35513 to
369a5e2
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 9, 2026 05:21
006dca5 to
51c029f
Compare
roed-math
force-pushed
the
split/03-registry
branch
from
August 9, 2026 08:23
369a5e2 to
03c0a82
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 9, 2026 08:23
51c029f to
c442b80
Compare
The shape matchers: `matchers.run(parsed)` returns `Match(slug, data)` records. This is the file where a human eye is most useful on the mathematics: the degree/genus tests, the reductions to standard forms, and the data each match extracts (`D` for Pell, a-invariants for Weierstrass, the regime of a generalized Fermat equation, ...). Matchers never mutate the parsed equation. **API note:** `Match.transform` is a `CoordinateTransform` (`transforms.py`), not a prose string. It holds both directions of the map between the user's variables and the family's standard coordinates, `push_forward`/`pull_back`, and the structural roles a family assigns — which have moved out of `Match.data["roles"]`, since a solver needs them together with the map that consumes them. A string cannot transport a solution: `5*x^2 - y^2 = 1` is a Pell equation only after reading the user's `y` as the standard `x`, and the answer has to come back. Operations that change the equation but no coordinate (multiplying through by `-1`) are recorded separately, in `.operations`. Two recognition fixes worth a look: a parameter in a coefficient is no longer dropped (a `Term` keeps its parameter factors apart from `coeff`, so `A*2^n` and `2^n` shared `coeff == 1` and Pillai matched both), and orienting `D*x^2 - y^2 = N` as a Pell equation swaps the variables, which negates the right-hand side too — without that, `5*x^2 - y^2 = 1` was matched as the different equation `x^2 - 5*y^2 = 1`. The recognizers cover 44 families, most of which are not registered yet. That is deliberate and safe: a recognizer whose family has not landed is inert, because the classifier (next PR) ranks matches through the registry and drops slugs it does not know. `tests/test_registry.py` checks the flags of the registered ones; `99-polish` tightens that to *every* emitted slug once the registry is complete. Part of the series that splits #1 into reviewable pieces: 1. `01-bibliography` — packaging, docs, annotated bibliography 2. `02-parsing` — equation strings to a term model 3. `03-registry` — the YAML family registry (3 seed families) 4. `04-matchers` — shape recognizers 5. `05-classify` — the classification pipeline 6. `06-solvers` — solver framework, two seed solvers, and the CLI 7. `07..09-backbone` — the 23 parent families of the DAG, by depth 8. one PR per remaining family (38 of them, mutually independent) 9. `99-polish` — restore the full doctests and tighten the invariants
roed-math
force-pushed
the
split/03-registry
branch
from
August 9, 2026 20:35
03c0a82 to
67d4419
Compare
roed-math
force-pushed
the
split/04-matchers
branch
from
August 9, 2026 20:35
c442b80 to
b6219b9
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The shape matchers:
matchers.run(parsed)returnsMatch(slug, data)records.This is the file where a human eye is most useful on the mathematics: the
degree/genus tests, the reductions to standard forms, and the data each match
extracts (
Dfor Pell, a-invariants for Weierstrass, the regime of ageneralized Fermat equation, ...). Matchers never mutate the parsed equation.
API note:
Match.transformis aCoordinateTransform(transforms.py),not a prose string. It holds both directions of the map between the user's
variables and the family's standard coordinates,
push_forward/pull_back,and the structural roles a family assigns — which have moved out of
Match.data["roles"], since a solver needs them together with the map thatconsumes them. A string cannot transport a solution:
5*x^2 - y^2 = 1is aPell equation only after reading the user's
yas the standardx, and theanswer has to come back. Operations that change the equation but no
coordinate (multiplying through by
-1) are recorded separately, in.operations.Two recognition fixes worth a look: a parameter in a coefficient is no longer
dropped (a
Termkeeps its parameter factors apart fromcoeff, soA*2^nand
2^nsharedcoeff == 1and Pillai matched both), and orientingD*x^2 - y^2 = Nas a Pell equation swaps the variables, which negates theright-hand side too — without that,
5*x^2 - y^2 = 1was matched as thedifferent equation
x^2 - 5*y^2 = 1.The recognizers cover 44 families, most of which are not registered yet. That
is deliberate and safe: a recognizer whose family has not landed is inert,
because the classifier (next PR) ranks matches through the registry and drops
slugs it does not know.
tests/test_registry.pychecks the flags of theregistered ones;
99-polishtightens that to every emitted slug once theregistry is complete.
Part of the series that splits #1 into reviewable pieces:
01-bibliography— packaging, docs, annotated bibliography02-parsing— equation strings to a term model03-registry— the YAML family registry (3 seed families)04-matchers— shape recognizers05-classify— the classification pipeline06-solvers— solver framework, two seed solvers, and the CLI07..09-backbone— the 23 parent families of the DAG, by depth99-polish— restore the full doctests and tighten the invariants