Skip to content

A union of solves solves each equation once - #2310

Merged
Rafael-SOWNet merged 2 commits into
masterfrom
a-union-of-solves-solves-each-once
Nov 1, 2026
Merged

Rafael-SOWNet merged 2 commits into
masterfrom
a-union-of-solves-solves-each-once

Conversation

@Rafael-SOWNet

@Rafael-SOWNet Rafael-SOWNet commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

Unite and Intersect were sets.Any() ? sets.Aggregate(...) : Empty, which enumerates the sequence twice. The solvers pass Unite a lazy Select of solves, one per root of a substitution or per factor, so Any() solved the first equation to see there was one, and Aggregate solved it again. Each sequence is now enumerated once into an array and folded.

Bytes allocated per Solve, after a warm-up, same answers:

Solve("x") master now
x^5 = abs(x^3 + 1) + 1 733 MB, 721 ms 140 MB, 362 ms
e^(2x) - 3 e^x + 2 = 0 668 KB 403 KB
sqrt(x + 1) = x - 1 1205 KB 829 KB
sin(x)^2 = 1/4 809 KB 735 KB
x^4 - 5x^2 + 4 = 0 317 KB 317 KB
  • Why it went unseen. A Select over a list or a range knows its count, so Any() computes nothing. Over a plain iterator it computes the first element. The new test counts through a yield iterator, and master computes the first set twice (4 against 3).
  • The kernel baseline is updated. The gate reported SolveHard 4.7% and SolveMediumHard 3.1% below the baseline, and it fails on a gain so that the gain gets recorded. performance-baseline.json is now the file this PR's own Benchmark job wrote. Every other gated row is within its band.
  • No answer changes. The suite, the trio, F#, AOT and the eight harnesses pass, and the chain's corpus runs have 0 moves.

Found while tracing why the route in #2309 ran twice per spelling. No issue was filed.

🤖 Generated with Claude Code

Unite and Intersect asked Any() of their sequence and then folded it with Aggregate, which
enumerates it a second time. The solvers hand Unite a lazy Select of solves, one per root
of a substitution or per factor, so the first of them was solved twice. A Select over a
list or a range knows its count without computing anything, which is why it went unseen;
over a plain iterator Any() computes the first element. Each is now enumerated once into
an array and folded.

Measured per Solve after a warm-up, the answers unchanged: x^5 = |x^3 + 1| + 1 allocates
140 MB where it allocated 733 MB, and takes 362 ms where it took 721; e^(2x) - 3e^x + 2 = 0
403 KB where 668 KB, sqrt(x + 1) = x - 1 829 KB where 1205 KB.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Rafael-SOWNet Rafael-SOWNet added this to the 2.7.0 milestone Nov 1, 2026
@Rafael-SOWNet Rafael-SOWNet moved this from Todo to In review in AngouriMath Nov 1, 2026
@codecov

codecov Bot commented Nov 1, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.77%. Comparing base (df991d3) to head (dcbf619).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2310      +/-   ##
==========================================
- Coverage   86.78%   86.77%   -0.02%     
==========================================
  Files         311      311              
  Lines       68032    68032              
  Branches    19763    19763              
==========================================
- Hits        59039    59032       -7     
- Misses       4872     4877       +5     
- Partials     4121     4123       +2     
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.31% <100.00%> (-0.02%) ⬇️
fsharp 32.97% <ø> (ø)
interactive 40.72% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...s/AngouriMath/Convenience/AngouriMathExtensions.cs 100.00% <100.00%> (ø)

... and 5 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

…el performance baseline

The gate reported IMPROVED: SolveHard allocates 9,526,556 B/op, 4.7% below the 9,996,973
recorded at 5edd6a1 on 2026-10-21, and SolveMediumHard 1,366,964, 3.1% below 1,410,754.
The file is the one this pull request's own Benchmark job wrote,
measured-CommonFunctionsInterVersion.json from its artifact, copied over the baseline as
version_performance_control.md describes. Every other gated row is within its band:
SimplifyHard +2.4%, SolveEasy -2.0%.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@Rafael-SOWNet
Rafael-SOWNet merged commit eb19a31 into master Nov 1, 2026
35 checks passed
@github-project-automation github-project-automation Bot moved this from In review to Done in AngouriMath Nov 1, 2026
@Rafael-SOWNet
Rafael-SOWNet deleted the a-union-of-solves-solves-each-once branch November 1, 2026 14:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant