Skip to content

Initial version - #1

Closed
roed314 wants to merge 3 commits into
DiophantineLibrary:mainfrom
roed-math:main
Closed

Initial version#1
roed314 wants to merge 3 commits into
DiophantineLibrary:mainfrom
roed-math:main

Conversation

@roed314

@roed314 roed314 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Implemented by Claude, with feedback from @roed314 and GPT.

roed314 and others added 3 commits August 2, 2026 18:03
- docs/FAMILIES.md: prioritized enumeration of ~60 families of Diophantine
  equations (forms, status, methods, software, references, specialization
  DAG, undecidability boundary), per the LuCaNT 2 vision talk
- diophantine_classifier/: Sage-based package
  - data/families.yaml: machine-readable registry (DAG, priorities, status,
    software pointers, fillable code templates)
  - parsing: term model with parameters, variable exponents (2^n, y^q),
    unit fractions, denominator-clearing with tracked conditions
  - matchers: ~45 structural recognizers + genus-based routing for plane
    curves; reducible equations split into components
  - classify: DAG-ranked classification with explain() and JSON as_dict()
  - solvers: linear, Pell (continued fractions), generalized Pell and Thue
    (PARI), quadratic-form isotropy with local obstructions, 2/3/4 squares,
    BinaryQF, Weierstrass integral points, plus literature-complete answers
    (Catalan, Fermat, Ramanujan-Nagell)
  - cli: dioclassify entry point (text and JSON)
- tests: 86 tests incl. a 54-equation corpus of famous examples
- docs/DESIGN.md: architecture + transformation-ladder roadmap (waves 2-4)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…stry files

Responding to review:
1. Sage-convention docstrings (INPUT/OUTPUT/EXAMPLES) on every function and
   dataclass, private helpers included; 410 doctests pass under 'sage -t';
   'sage --coverage' reports 100% on all seven modules (make doctest/coverage).
2. SolutionSet is now iterable with true enumeration of infinite solution
   sets: Pell by powers of the fundamental unit, generalized Pell by walking
   automorph orbits, linear equations by lattice-coset shells, primitive
   Pythagorean triples, and the Markov/Hurwitz Vieta tree (heap order).
   Finite representation problems are enumerated completely instead of
   witnessed (2/3/4 squares, definite BinaryQF, unit fractions), with
   explicit complete/kind semantics.
3. All dataclasses (Family, Term, ParsedEquation, Match, Classification,
   SolutionSet) document every attribute.
4. References upgraded: data/references.bib (122 entries; DOIs where
   verified, urls only to legally free copies), families cite by BibTeX key
   with per-use 'why' annotations, and tools/check_references.py validates
   structure, resolves DOIs/URLs (--online), and checks locally downloaded
   PDFs (references/pdf/<key>.pdf) against their entries; report at
   references/REPORT.md.
5. Registry split into data/families/<slug>.yaml (one file per family,
   merge-friendly; loader enforces slug == filename).

105 unit tests + 410 doctests green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- tools/check_references.py now records successes (PDF verified, DOI/URL
  resolved) write-once in the committed ledger references/status.yaml:
  a run on a machine without a file reports 'missing locally' but never
  downgrades a recorded verification, and a local mismatch warns without
  erasing the ledger (your copy may simply be the wrong file). Ledger
  verifications also drop entries from the download TODO list. Tests cover
  upgrade-only, mismatch-keeps-verification, and recording.
- All 115 docstrings reformatted to the Sage convention: the summary starts
  on the line after the opening triple quote. Doctests (410) and coverage
  (100% on all modules) unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This was referenced Aug 8, 2026
roed-math pushed a commit that referenced this pull request Aug 8, 2026
The parser: equation string to `ParsedEquation`.

Recognizes the term model the rest of the classifier works with: polynomial
terms, `2^n`-style exponential terms and `y^q` power terms, with parameters
living in the coefficient ring.  Denominators are cleared and the resulting
nonvanishing conditions are recorded in `conditions`, so the original problem
is never silently replaced by a cleared one.

No family data is involved: the parser is exercised entirely by its own
doctests (`make doctest`).

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 pushed a commit that referenced this pull request Aug 8, 2026
The family registry: `data/families/<slug>.yaml`, one file per family.

- `registry.py` loads the directory, validates it (parents resolve, priorities
  and statuses come from fixed vocabularies, the DAG is acyclic, every
  reference key resolves in `references.bib` with a nonempty `why`), and
  exposes `depth`/`ancestors` — the specificity order used to rank matches.
- `tools/check_references.py` plus `references/`: the reference pipeline and
  its monotone verification ledger.  `make references` regenerates
  `references/REPORT.md`; that generated file is committed by the last PR of
  the series, when the registry is complete.
- `docs/FAMILIES.md`: the prose enumeration.  Its section headings are all
  here; the per-family entries arrive with their families.

Three seed families are included so that the layers that follow have something
to classify: `general-polynomial` (the root of the DAG), `linear` and
`univariate`.  Every other family gets its own PR later in the series.

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 pushed a commit that referenced this pull request Aug 8, 2026
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;
any normalization is described in `Match.transform`.

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 pushed a commit that referenced this pull request Aug 8, 2026
The classification pipeline.

`classify()` parses, splits reducible equations into components, runs the
matchers, and ranks the results by depth in the family DAG, so the most
specific family wins.  `Classification.explain()` is the human report and
`as_dict()` is the JSON contract for the future website backend.

`tests/test_classify.py` starts the classification corpus (famous equation to
expected family); each family PR adds its own rows.

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 pushed a commit that referenced this pull request Aug 8, 2026
The solver layer.

`SolutionSet` is the result type: a finite complete list, an empty set with a
reason, or an infinite family that streams (`iter(S)`, `S.first(n)`).  When no
solver is wired up, `SolverUnavailable` carries the registry's software
pointers and filled code templates, so an equation page can always offer
runnable code.

`solve()` dispatches on the primary family and then walks up the lineage.  The
two seed solvers (linear, univariate) are here; every other solver arrives with
its family, which is what makes those PRs independent.  The module-level
enumeration bounds and the Sage imports are the union used by those solvers.

`cli.py` (`dioclassify 'x^2 - 61*y^2 = 1' --solve`) also lands here, since it
needs both halves: classification for `--json`, solving for `--solve`.

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 pushed a commit that referenced this pull request Aug 8, 2026
The first layer of the family DAG: the root families and their immediate
specializations.

These are the parents that the individual family PRs hang off, so they land
first as a group.  Each entry is a YAML file, its `docs/FAMILIES.md` section,
its classification-corpus rows and, where standard software is definitive, its
solver.

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 pushed a commit that referenced this pull request Aug 8, 2026
The second layer of the family DAG.

Same shape as the previous PR: parent families only, so that the 38 one-family
PRs at the end of the series can be reviewed and merged in any order.

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 pushed a commit that referenced this pull request Aug 8, 2026
The last layer of parent families: the deepest interior nodes of the DAG.

After this PR every remaining family is a leaf, and each one gets its own PR
that touches nothing but its own data, prose, tests and (where applicable)
solver.

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 pushed a commit that referenced this pull request Aug 9, 2026
Packaging and documentation skeleton plus the bibliography layer.

- `pyproject.toml`, `Makefile`, `.gitignore`: the project runs under Sage's
  Python (`make test`, `make doctest`, `make coverage`, `make references`).
- `.github/workflows/ci.yml`: those same four checks on every pull request,
  inside the official `sagemath/sagemath` container (that image has no `make`,
  so the steps spell the commands out and name the target they mirror).
- `CLAUDE.md`, `docs/DESIGN.md`: how the classifier is put together.  They
  describe the finished system, i.e. the state at the end of this series.
  `README.md` waits for `03-registry`, the PR that brings the files it links
  to.
- `references.py` and `data/references.bib`: the annotated bibliography and
  the BibTeX parser/formatter that renders entries for display.  Every family
  in this series cites into that file by key.

Reviewing the bibliography: entries are checked mechanically (required fields,
DOI/arXiv/URL syntax) by the tool that arrives in `03-registry`; `url` fields
point at legally free copies only.  What each reference is *for* is recorded
per family, in the family's own PR.

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 pushed a commit that referenced this pull request Aug 9, 2026
The parser: equation string to `ParsedEquation`.

Recognizes the term model the rest of the classifier works with: polynomial
terms, `2^n`-style exponential terms and `y^q` power terms, with parameters
living in the coefficient ring.  Denominators are cleared and the resulting
nonvanishing conditions are recorded in `conditions`, so the original problem
is never silently replaced by a cleared one.

No family data is involved: the parser is exercised entirely by its own
doctests (`make doctest`).

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 pushed a commit that referenced this pull request Aug 9, 2026
The family registry: `data/families/<slug>.yaml`, one file per family.

- `registry.py` loads the directory, validates it (parents resolve, priorities
  and statuses come from fixed vocabularies, the DAG is acyclic, every
  reference key resolves in `references.bib` with a nonempty `why`), and
  exposes `depth`/`ancestors` — the specificity order used to rank matches.
- `tools/check_references.py` plus `references/`: the reference pipeline and
  its monotone verification ledger.  The committed `references/REPORT.md` is
  the output of `make references` against the registry as it stands here; the
  closing PR regenerates it once every family has landed (regenerating it in
  each family PR would collide in every one of them).
- `README.md`, which links to the family enumeration, the registry directory
  and the reference report — all of them present as of this PR.
- `docs/FAMILIES.md`: the prose enumeration.  Its section headings are all
  here; the per-family entries arrive with their families.

Three seed families are included so that the layers that follow have something
to classify: `general-polynomial` (the root of the DAG), `linear` and
`univariate`.  Every other family gets its own PR later in the series.

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 pushed a commit that referenced this pull request Aug 9, 2026
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;
any normalization is described in `Match.transform`.

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 pushed a commit that referenced this pull request Aug 9, 2026
The classification pipeline.

`classify()` parses, splits reducible equations into components, runs the
matchers, and ranks the results by depth in the family DAG, so the most
specific family wins.  `Classification.explain()` is the human report and
`as_dict()` is the JSON contract for the future website backend.

`tests/test_classify.py` starts the classification corpus (famous equation to
expected family); each family PR adds its own rows.

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 pushed a commit that referenced this pull request Aug 9, 2026
The solver layer.

`SolutionSet` is the result type: a finite complete list, an empty set with a
reason, or an infinite family that streams (`iter(S)`, `S.first(n)`).  When no
solver is wired up, `SolverUnavailable` carries the registry's software
pointers and filled code templates, so an equation page can always offer
runnable code.

`solve()` dispatches on the primary family and then walks up the lineage.  The
two seed solvers (linear, univariate) are here; every other solver arrives with
its family, which is what makes those PRs independent.  The module-level
enumeration bounds and the Sage imports are the union used by those solvers.

`cli.py` (`dioclassify 'x^2 - 61*y^2 = 1' --solve`) also lands here, since it
needs both halves: classification for `--json`, solving for `--solve`.

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 pushed a commit that referenced this pull request Aug 9, 2026
The first layer of the family DAG: the root families and their immediate
specializations.

These are the parents that the individual family PRs hang off, so they land
first as a group.  Each entry is a YAML file, its `docs/FAMILIES.md` section,
its classification-corpus rows and, where standard software is definitive, its
solver.

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 pushed a commit that referenced this pull request Aug 9, 2026
The second layer of the family DAG.

Same shape as the previous PR: parent families only, so that the 38 one-family
PRs at the end of the series can be reviewed and merged in any order.

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 pushed a commit that referenced this pull request Aug 9, 2026
The last layer of parent families: the deepest interior nodes of the DAG.

After this PR every remaining family is a leaf, and each one gets its own PR
that touches nothing but its own data, prose, tests and (where applicable)
solver.

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 pushed a commit that referenced this pull request Aug 9, 2026
Packaging and documentation skeleton plus the bibliography layer.

- `pyproject.toml`, `Makefile`, `.gitignore`: the project runs under Sage's
  Python (`make test`, `make doctest`, `make coverage`, `make references`).
- `.github/workflows/ci.yml`: those same four checks on every pull request,
  inside the official `sagemath/sagemath` container (that image has no `make`,
  so the steps spell the commands out and name the target they mirror).
- `CLAUDE.md`, `docs/DESIGN.md`: how the classifier is put together.  They
  describe the finished system, i.e. the state at the end of this series.
  `README.md` waits for `03-registry`, the PR that brings the files it links
  to.
- `references.py` and `data/references.bib`: the annotated bibliography and
  the BibTeX parser/formatter that renders entries for display.  Every family
  in this series cites into that file by key.

Reviewing the bibliography: entries are checked mechanically (required fields,
DOI/arXiv/URL syntax) by the tool that arrives in `03-registry`; `url` fields
point at legally free copies only.  What each reference is *for* is recorded
per family, in the family's own PR.

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 pushed a commit that referenced this pull request Aug 9, 2026
The parser: equation string to `ParsedEquation`.

Recognizes the term model the rest of the classifier works with: polynomial
terms, `2^n`-style exponential terms and `y^q` power terms, with parameters
living in the coefficient ring.  Denominators are cleared and the resulting
nonvanishing conditions are recorded in `conditions`, so the original problem
is never silently replaced by a cleared one.

No family data is involved: the parser is exercised entirely by its own
doctests (`make doctest`).

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 pushed a commit that referenced this pull request Aug 9, 2026
The family registry: `data/families/<slug>.yaml`, one file per family.

- `registry.py` loads the directory, validates it (parents resolve, priorities
  and statuses come from fixed vocabularies, the DAG is acyclic, every
  reference key resolves in `references.bib` with a nonempty `why`), and
  exposes `depth`/`ancestors` — the specificity order used to rank matches.
- `tools/check_references.py` plus `references/`: the reference pipeline and
  its monotone verification ledger.  The committed `references/REPORT.md` is
  the output of `make references` against the registry as it stands here; the
  closing PR regenerates it once every family has landed (regenerating it in
  each family PR would collide in every one of them).
- `README.md`, which links to the family enumeration, the registry directory
  and the reference report — all of them present as of this PR.
- `docs/FAMILIES.md`: the prose enumeration.  Its section headings are all
  here; the per-family entries arrive with their families.

Three seed families are included so that the layers that follow have something
to classify: `general-polynomial` (the root of the DAG), `linear` and
`univariate`.  Every other family gets its own PR later in the series.

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 pushed a commit that referenced this pull request Aug 9, 2026
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;
any normalization is described in `Match.transform`.

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 pushed a commit that referenced this pull request Aug 9, 2026
The classification pipeline.

`classify()` parses, splits reducible equations into components, runs the
matchers, and ranks the results by depth in the family DAG, so the most
specific family wins.  `Classification.explain()` is the human report and
`as_dict()` is the JSON contract for the future website backend.

`tests/test_classify.py` starts the classification corpus (famous equation to
expected family); each family PR adds its own rows.

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 pushed a commit that referenced this pull request Aug 9, 2026
The solver layer.

`SolutionSet` is the result type: a finite complete list, an empty set with a
reason, or an infinite family that streams (`iter(S)`, `S.first(n)`).  When no
solver is wired up, `SolverUnavailable` carries the registry's software
pointers and filled code templates, so an equation page can always offer
runnable code.

`solve()` dispatches on the primary family and then walks up the lineage.  The
two seed solvers (linear, univariate) are here; every other solver arrives with
its family, which is what makes those PRs independent.  The module-level
enumeration bounds and the Sage imports are the union used by those solvers.

`cli.py` (`dioclassify 'x^2 - 61*y^2 = 1' --solve`) also lands here, since it
needs both halves: classification for `--json`, solving for `--solve`.

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 pushed a commit that referenced this pull request Aug 9, 2026
The first layer of the family DAG: the root families and their immediate
specializations.

These are the parents that the individual family PRs hang off, so they land
first as a group.  Each entry is a YAML file, its `docs/FAMILIES.md` section,
its classification-corpus rows and, where standard software is definitive, its
solver.

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 pushed a commit that referenced this pull request Aug 9, 2026
The second layer of the family DAG.

Same shape as the previous PR: parent families only, so that the 38 one-family
PRs at the end of the series can be reviewed and merged in any order.

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 pushed a commit that referenced this pull request Aug 9, 2026
The last layer of parent families: the deepest interior nodes of the DAG.

After this PR every remaining family is a leaf, and each one gets its own PR
that touches nothing but its own data, prose, tests and (where applicable)
solver.

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 pushed a commit that referenced this pull request Aug 9, 2026
Packaging and documentation skeleton plus the bibliography layer.

- `pyproject.toml`, `Makefile`, `.gitignore`: the project runs under Sage's
  Python (`make test`, `make doctest`, `make coverage`, `make references`).
- `.github/workflows/ci.yml`: those same four checks on every pull request,
  inside the official `sagemath/sagemath` container (that image has no `make`,
  so the steps spell the commands out and name the target they mirror).
- `CLAUDE.md`, `docs/DESIGN.md`: how the classifier is put together.  They
  describe the finished system, i.e. the state at the end of this series.
  `README.md` waits for `03-registry`, the PR that brings the files it links
  to.
- `references.py` and `data/references.bib`: the annotated bibliography and
  the BibTeX parser/formatter that renders entries for display.  Every family
  in this series cites into that file by key.

Reviewing the bibliography: entries are checked mechanically (required fields,
DOI/arXiv/URL syntax) by the tool that arrives in `03-registry`; `url` fields
point at legally free copies only.  What each reference is *for* is recorded
per family, in the family's own PR.

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 pushed a commit that referenced this pull request Aug 9, 2026
The parser: equation string to `ParsedEquation`.

Recognizes the term model the rest of the classifier works with: polynomial
terms, `2^n`-style exponential terms and `y^q` power terms, with parameters
living in the coefficient ring.  Denominators are cleared and the resulting
nonvanishing conditions are recorded in `conditions`, so the original problem
is never silently replaced by a cleared one.

No family data is involved: the parser is exercised entirely by its own
doctests (`make doctest`).

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 pushed a commit that referenced this pull request Aug 9, 2026
The family registry: `data/families/<slug>.yaml`, one file per family.

- `registry.py` loads the directory, validates it (parents resolve, priorities
  and statuses come from fixed vocabularies, the DAG is acyclic, every
  reference key resolves in `references.bib` with a nonempty `why`), and
  exposes `depth`/`ancestors` — the specificity order used to rank matches.
- `tools/check_references.py` plus `references/`: the reference pipeline and
  its monotone verification ledger.  The committed `references/REPORT.md` is
  the output of `make references` against the registry as it stands here; the
  closing PR regenerates it once every family has landed (regenerating it in
  each family PR would collide in every one of them).
- `README.md`, which links to the family enumeration, the registry directory
  and the reference report — all of them present as of this PR.
- `docs/FAMILIES.md`: the prose enumeration.  Its section headings are all
  here; the per-family entries arrive with their families.

Three seed families are included so that the layers that follow have something
to classify: `general-polynomial` (the root of the DAG), `linear` and
`univariate`.  Every other family gets its own PR later in the series.

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 pushed a commit that referenced this pull request Aug 9, 2026
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;
any normalization is described in `Match.transform`.

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
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