Move the polynomial kernel out of Functions/Simplification - #868
Open
Rafael-SOWNet wants to merge 7 commits into
Open
Move the polynomial kernel out of Functions/Simplification#868Rafael-SOWNet wants to merge 7 commits into
Rafael-SOWNet wants to merge 7 commits into
Conversation
Towards #860. EquationSystem.Solve eliminated one variable at a time by calling SolveEquation, which applies the closed-form radical formulas. With numeric coefficients those are cheap; with symbolic ones they are not, and since each elimination turns the next one's coefficients into nested radicals the size compounds -- the same quartic is 5 nodes with numeric coefficients and 5661 with symbolic ones. Four coupled variables did not finish in 300s while four uncoupled ones with 256 solutions took 17ms, so the cost was never the size of the system. 4 coupled variables no answer in 300 s -> 24 solutions, 23 ms 5 coupled variables over 60 s -> 120 solutions, 129 ms A Groebner basis eliminates without radicals: the lexicographic basis is triangular and leaves the last variable a univariate with rational coefficients, which PolynomialSolver already handles. The basis is computed under degree-reverse-lexicographic, which is the order that can be computed at all -- lexicographic dies at five variables on dense input from coefficient swell -- and converted by FGLM. Bounded, because Buchberger is doubly exponential in the worst case. Two of the four ceilings exist because measurement put them there rather than theory: coefficient width, after a system was seen to run away with 53 pairs and 64 terms and 188-digit rationals, which no count of pairs or terms would have caught; and quotient dimension, checked before FGLM starts rather than discovered inside it, because a system can have a basis that computes in milliseconds and a conversion that never finishes. The path is deliberately narrow: it answers only where every solution is rational. The first cut verified candidates with a full Simplify, which is unbounded work outside every budget -- on a degree-nine univariate it spent longer failing to prove a nested radical satisfied the system than the old solver takes to solve the whole thing, and hung the suite. With rational coordinates the check is exact arithmetic and immediate. So this takes the systems that were hanging and leaves the rest exactly as they were, including the equation-count refusal. Over-determined systems are solved rather than refused, and an inconsistent one reports itself as having no solutions instead of throwing. Both are breaking and recorded. Fewer equations than unknowns still throws: that ideal is not zero-dimensional. MultivariatePolynomial becomes partial so the operations only this needs live in Functions/Algebra/Groebner beside their consumer. Moving the rest of the polynomial kernel out of Functions/Simplification is a separate, mechanical change. Verified: 6079 C# tests and 130 F# tests pass, with the suite at its usual runtime. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…stem-solver # Conflicts: # BREAKING-CHANGES.md # Sources/.editorconfig
… search
The restriction to rational solutions was the right fix for the wrong reason. What hung
the suite was verifying candidates with Simplify, which searches -- it generates
candidate forms and picks between them, so how long it takes to settle a nested radical
is not bounded by anything. Restricting the input was one way to avoid that. Bounding the
check is a better one.
InnerSimplified is a single structural pass, and it is enough:
sqrt(2)^2 - 2 zero in 13 ms
(3^(1/3))^3 - 3 zero in 13 ms
((1+sqrt(5))/2)^2 - (1+sqrt(5))/2-1 zero in 3 ms
sqrt(3 + 2*sqrt(2)) - 1 - sqrt(2) zero in 3 ms
a Cardano cube root of unity zero in 15 ms
So the rational-only gate is gone and radical solutions are in reach:
x^2 - 2, y - x -> (sqrt(2), sqrt(2)), (-sqrt(2), -sqrt(2)) 57 ms
x^2 - 2, y^2 - 3 -> 4 solutions, all exact 11 ms
x^3 - 2, y - x -> 3 solutions, including complex cube roots 104 ms
It reads as one pass proving what it can rather than as a narrower input class, which is
also what it actually is: InnerSimplified only ever proves zero and never disproves it, so
a candidate it cannot settle is declined and the system falls back. That costs coverage,
never correctness, and no tolerance is involved at any point.
One existing test moves from the fallback into this path and gets faster and exact with
it: the system with a 0.1 coefficient went from 629 ms of numeric answers to 22 ms of
radicals. The degree-nine system stays out, since decimal roots leave nothing to prove an
identity with, and now costs 941 ms rather than 282 -- bounded, and worth the rest.
Verified: 6102 C# tests and 130 F# tests pass.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
MultivariatePolynomial, PolynomialGcd and PolynomialFactoring sat under Functions/Simplification because simplification was the first thing to need them. They are kernel algebra: the solvers, the evaluator and the simplifier all depend on them and they depend on none of those. PolynomialGcd is reached from simplification, from Core/Transformations and from evaluation -- three separate layers -- so filing it under one of the three said something untrue about the other two. They now live in Functions/Algebra/Polynomials, beside Functions/Algebra/Groebner, which was put there for the same reason and would otherwise have entrenched the confusion by sitting next to nothing. Nothing but the location changes. Namespaces are left alone: all three were already `AngouriMath.Functions` rather than matching their folder, which is how this codebase works, so moving the files needs no `using` edits anywhere and no consumer is touched. Two of the three are byte-identical to what they were; the third gains a remark saying which way the dependencies run, so the next person to look for a home for a polynomial routine has one. Verified: 6102 C# tests and 130 F# tests pass, the same counts as before the move, and git records all three as renames rather than as deletions and additions. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…stem-solver # Conflicts: # BREAKING-CHANGES.md
…l-kernel-placement
…-kernel-placement # Conflicts: # Sources/AngouriMath/Functions/Algebra/Polynomials/MultivariatePolynomial.cs
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.
Depends on #865 — branched from it, because it touches
MultivariatePolynomialtoo and a rename plus an edit to the same file is a conflict nobody needs. Merge #865 first and this becomes a three-file move.MultivariatePolynomial,PolynomialGcdandPolynomialFactoringsat underFunctions/Simplificationbecause simplification was the first thing that needed them. They are kernel algebra: the solvers, the evaluator and the simplifier all depend on them, and they depend on none of those.PolynomialGcdmakes the point. It is reached from:Functions/SimplificationSimplificator,PatternsCore/TransformationsRewriteRulesFunctions/EvaluationEvaluation.Continuous.Arithmetics.ClassesCore/EntityEntity.Continuous.Rounding.ClassesFiling it under one of those said something untrue about the other three.
They now live in
Functions/Algebra/Polynomials, beside theFunctions/Algebra/Groebneradded by #865 — which was put there for exactly this reason and would otherwise have entrenched the confusion by sitting next to nothing.Nothing but the location changes
Namespaces are deliberately left alone. All three were already
namespace AngouriMath.Functionsrather than matching their folder, which is how this codebase works — so moving the files needs nousingedits and no consumer is touched at all. Changing the namespaces too would have turned a zero-risk move into a churn across a dozen files for no gain.PolynomialGcd.csandPolynomialFactoring.csare byte-identical to what they were (verified by diffing againstHEAD).MultivariatePolynomial.csgains a remark saying which way the dependencies run, so the next person looking for a home for a polynomial routine has one.git diff -M --statrecords 3 renames, 0 insertions, 0 deletions — history follows the files..csprojglobs sources, so no project file changes. No.editorconfigsection was keyed on the old path.Verification
A relocation that changed a test count would be a relocation that changed behaviour.
🤖 Generated with Claude Code