From 2dcf885d91c3fac4914a87d5d2aa82e71911793c Mon Sep 17 00:00:00 2001 From: Rafael Vuijk Date: Tue, 27 Oct 2026 11:17:26 +0000 Subject: [PATCH] A root check says what it tolerates: zero to about fifty digits GroebnerSystemSolver.Satisfies said that "no tolerance is involved anywhere, which is what would turn a root that is merely close into one that gets reported". It decides with InnerSimplified, and with downcasting on, the default, a residual that evaluates below DowncastingTolerance (half the hundred working digits) times the scale that cancelled comes out as 0. Measured on 583338efe: 8y^3 + 4y^2 - 4y - 1 at the Cardano root for cos(2pi/7), with one 7 made 7 + 10^(-50), is 0 to InnerSimplified, while mpmath at 200 digits gives 2.48e-52 - 3.26e-52 i. With 10^(-40) it is left unsimplified, and evaluates to 2.48e-42 - 3.26e-42 i. So a candidate right to about fifty digits is accepted. The comment says so, and "proves" becomes "settles" where the same paragraph names what it reduces to zero. No behaviour changes. Found answering https://github.com/asc-community/AngouriMath/issues/2143 Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura --- .../Algebra/Groebner/GroebnerSystemSolver.cs | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/Sources/AngouriMath/Functions/Algebra/Groebner/GroebnerSystemSolver.cs b/Sources/AngouriMath/Functions/Algebra/Groebner/GroebnerSystemSolver.cs index a836c2d45..df1e1aa92 100644 --- a/Sources/AngouriMath/Functions/Algebra/Groebner/GroebnerSystemSolver.cs +++ b/Sources/AngouriMath/Functions/Algebra/Groebner/GroebnerSystemSolver.cs @@ -249,15 +249,21 @@ static Entity Canonical(Entity substituted, IReadOnlyDictionary r /// radical is not bounded by anything, and an early version of this spent longer /// failing to prove a degree-nine root satisfied its system than the old solver takes /// to solve the whole thing. `InnerSimplified` is one structural pass, which is - /// cheap enough to be safe here and still proves what is needed: + /// cheap enough to be safe here and still settles what is needed: /// sqrt(2)^2 - 2, (3^(1/3))^3 - 3 and a Cardano cube root all reduce to /// zero in single-digit milliseconds. /// /// - /// It only ever proves zero, never disproves it, so a candidate it cannot settle is - /// declined and the system falls back. That costs coverage and never costs - /// correctness — and no tolerance is involved anywhere, which is what would turn a - /// root that is merely close into one that gets reported. + /// It only ever answers zero, never disproves it, so a candidate it cannot settle is + /// declined and the system falls back, which costs coverage. The zero is decided to + /// about fifty digits, though, not exactly. With downcasting on, the default, a + /// residual that evaluates below DowncastingTolerance, half the hundred digits + /// of , times the scale that + /// cancelled is taken as 0. So a candidate that is close enough passes as + /// well: 8y^3 + 4y^2 - 4y - 1 at the Cardano root for cos(2pi/7), with + /// one 7 made 7 + 10^(-50), comes out 0, where its value is + /// 2.48e-52 - 3.26e-52 i. + /// #2143 /// /// static bool Satisfies(