Skip to content

The solver tries the equation as written before asking for its alternatives: SolveHard -98.6% allocation - #1209

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
speed-solve
Sep 7, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
speed-solve

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Part of #746 — the standing condition on speed. Same method as #1205 and #1207: a temporary hook attributing allocated bytes to the stages of AnalyticalEquationSolver.Solve, per recursion depth, run on SolveHard.

What the attribution showed

stage bytes
Entity.Alternate(4) before the replacement loop, top level 268 MB a whole level-4 simplification of the equation; the loop solved the first spelling it produced and never looked past
the same, at depths 2 and 3 103 MB, 20 MB the recursion asks again at every level
TrySplitOffRationalRoots + IsWorthFactoringToSolve 268 MB each expands the whole equation — radical constants included — to learn that a sine is not a monomial; twice per equation visited, 18 visits at depth 2 alone
everything else ~200 MB the solving

What changes

  • The equation as written is tried first. SpellingsToSolveOver yields the equation, then the alternatives — and builds them only if the loop gets that far. A spelling that comes back as a condition rather than a finite set is kept as a fallback while the next spelling is tried; that is what keeps x^4 * x^y - 2 answered with a root (SolveOneEquation.ExpSimpl caught the first version).
  • TryGetRationalCoefficients reads the tree before it expands. x only under sums, products, quotients by something free of it, and whole non-negative powers; no symbol or constant in a coefficient. A necessary condition only — what passes it is still expanded and checked — so it can lose nothing but time.

Measured

Gate on one machine, both columns in one session:

baseline (e45413c2) this change allocation time
SolveHard 859,268,416 B, 700 ms 11,818,936 B, 109 ms −98.6% 0.16x
SolveMediumHard 94,415,256 B, 66.8 ms 1,435,934 B, 13.9 ms −98.5% 0.21x
SolveMedium 662,923 B, 456 µs 452,901 B, 387 µs −31.7% 0.85x
SolveEasyMedium 97,335 B, 29.7 µs 65,232 B, 19.2 µs −33.0% 0.64x
SimplifyHard 733,188,536 B, 371 ms 680,457,400 B, 339 ms −7.2% 0.92x
SimplifyEasy 116,291 B, 71.2 µs 110,051 B, 66.4 µs −5.4% 0.93x

Every other entry within 0.1%. The gate's baseline is updated in the same change. Since the 1930th column this morning: SolveHard −99.2%, SolveMediumHard −99.1%, SimplifyHard −81%.

Answers

Every solve in the suite answers as before but one: (x - b)/(x + a) + c/(x + a) keeps its root, and the condition on it is spelled not -(-b + c) + a = 0 where it was not a + -(-b + c) = 0 — the terms in the order the equation had, since it is solved as written rather than resimplified first. Re-pinned with the reason; recorded in BREAKING-CHANGES.md. The SolveHard and SolveMediumHard answers are the same size as before (149,153 and 37,073 nodes) and the corpus gate holds.

Checks

Full suite in two chunks: 9,661 passed, 0 failed (Calculus 1,322, the rest 8,339).

🤖 Generated with Claude Code

https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura

…atives: SolveHard -98.6% allocation

Attributing SolveHard's 859 MB to the stages of AnalyticalEquationSolver
with a temporary hook found two things done before any solving:

- The replacement machinery asked Entity.Alternate(4) -- a whole level-4
  simplification of the equation, the search Simplify runs -- for every
  spelling before trying any, at every depth of its own recursion, and in
  the ordinary case solved the first spelling it got, which was the
  equation itself. 268 MB of the top-level call and a third of each level
  below. SpellingsToSolveOver now yields the equation as it stands and
  builds the alternatives only if it is reached past that. A spelling that
  comes back as a condition rather than a finite set is kept as a fallback
  and the next spelling tried, which keeps x^4 * x^y - 2 answered with a
  root.
- TryGetRationalCoefficients expanded the whole equation -- huge radical
  constants included -- before discovering that a sine is not a monomial,
  twice per equation visited (the rational-root split and the factoring
  gate). It reads the tree first now: x only under sums, products,
  quotients by something free of it and whole powers, and no symbol or
  constant in a coefficient.

Measured by the gate on one machine: SolveHard 859,268,416 -> 11,818,936 B
and 700 -> 109 ms; SolveMediumHard 94,415,256 -> 1,435,934 B and
66.8 -> 13.9 ms; SolveMedium -32%, SolveEasyMedium -33%; SimplifyHard
-7.2% and SimplifyEasy -5.4% through the same pre-check. The baseline
moves with it. Every solve in the suite answers as before but one, whose
condition's terms come in the order the equation had; BREAKING-CHANGES.md
has the row.

Part of #746.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012sonx8iAspMiwRwokT1Ura
@Rafael-SOWNet
Rafael-SOWNet merged commit 574555b into master Sep 7, 2026
31 checks passed
@Rafael-SOWNet
Rafael-SOWNet deleted the speed-solve branch September 7, 2026 23:16
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.

1 participant