Skip to content

Over the complex numbers, an equation in and out of a modulus is left unsolved - #2307

Merged
Rafael-SOWNet merged 1 commit into
masterfrom
an-equation-in-and-out-of-a-modulus-is-left-unsolved-over-the-complex-numbers
Nov 1, 2026
Merged

Rafael-SOWNet merged 1 commit into
masterfrom
an-equation-in-and-out-of-a-modulus-is-left-unsolved-over-the-complex-numbers

Conversation

@Rafael-SOWNet

Copy link
Copy Markdown
Member

Over the complex numbers, the default codomain, an equation with x inside abs, sgn, conj, Re, Im or arg and outside it as well is now left unsolved. This is option 1 from #2139, and |x - 2| = |x - 3| was already left unsolved the same way (#1573).

Solve("x") master and 2.6.0 now
x^2/abs(1-x^2) = x { 0, 0.618…, 1.618…, 1.618… + 1.7E-9i, 1.618… + 9.9E-8i } { x : x ^ 2 / abs(1 - x ^ 2) = x }
abs(x^2 - 4) = 3x { 1, 4, 4.0000000000000062… + 1.6E-7i } { x : abs(x ^ 2 - 4) = 3 * x }
x * abs(x) = 4 { 2 } { x : x * abs(x) = 4 }
  • Why the search can't answer these. Newton's method assumes a holomorphic function, and over the complex numbers |u| = ±u holds only where u is real, which a root needn't make it. So neither the search nor a split by sign can say it found every root, and the search's near-copies of a root came back as roots.
  • The cost. The search's right answers go with the wrong ones, x * abs(x) = 4 among them.
  • Over the reals each is still solved exactly, by cases, since Over the reals, a modulus of a polynomial is split at the polynomial's real roots #2178.
  • Four of the six new cases fail on master. The suite, the trio, F#, AOT and the eight harnesses pass.

Fixes #2139.

🤖 Generated with Claude Code

… unsolved

x^2/abs(1 - x^2) = x was answered by a numerical search in the
complex codomain, the default, with two non-real entries beside 1.618
that solve nothing: Newton's method assumes a holomorphic function,
and its near-copies of a root came back as roots. abs(x^2 - 4) = 3x had
4.0000000000000062 + 1.6e-7 i beside { 1, 4 }. Over the complex
numbers |u| = +-u only where u is real, which a root need not make it
(x^2 + 1 = |x| has roots at +-0.618 i), so a split by the sign cannot
say it found every root either.

An equation with x inside abs, sgn, conj, Re, Im or arg and outside it
as well is now left unsolved in the complex codomain, at the point
where only the search is left, as |x - 2| = |x - 3| already was
(#1573). That gives up the cases the search happened to answer right,
x * abs(x) = 4 among them; over the reals each is solved by cases,
exactly, since #2178.

ModulusEquationTest takes six such equations left unsolved, four of
which master answered, and two that are still answered. The suite, the
trio, F#, AOT and the eight harnesses pass.

Fixes #2139.

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

codecov Bot commented Oct 31, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 86.77%. Comparing base (5d973db) to head (8ac2297).

Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #2307      +/-   ##
==========================================
- Coverage   86.77%   86.77%   -0.01%     
==========================================
  Files         311      311              
  Lines       68025    68030       +5     
  Branches    19758    19762       +4     
==========================================
+ Hits        59028    59032       +4     
- Misses       4875     4876       +1     
  Partials     4122     4122              
Flag Coverage Δ
cpp 37.77% <ø> (ø)
csharp 87.32% <100.00%> (-0.01%) ⬇️
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 Δ
...Solvers/EquationSolver/AnalyticalEquationSolver.cs 96.29% <100.00%> (+0.05%) ⬆️
...Continuous/Solvers/EquationSolver/ModulusSolver.cs 74.68% <100.00%> (+0.99%) ⬆️

... and 2 files with indirect coverage changes

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

@Rafael-SOWNet
Rafael-SOWNet merged commit b9171c0 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 an-equation-in-and-out-of-a-modulus-is-left-unsolved-over-the-complex-numbers branch November 1, 2026 00:06
@Happypig375

Copy link
Copy Markdown
Member

Merely wrapping the source equation inside a conditional set isn't solving though.

@Rafael-SOWNet

Copy link
Copy Markdown
Member Author

Agreed. #2309 solves them. With x = a + b i and each |u| a real t ≥ 0, the equation is a polynomial system in a, b and the ts. The Gröbner solver solves it exactly, and its real solutions are the roots. x^2/|1 - x^2| = x is { 0, (1 + sqrt(5))/2, (sqrt(5) - 1)/2 }, x |x| = 4 and x + sgn(x) = 3 are { 2 } again, and x^2 + 1 = |x| is ±i (sqrt(5) - 1)/2, which Newton didn't find.

Still left as a condition: infinitely many solutions (|x| = Re x is a ray), roots with no exact form (x^5 = |x| + 1), and arg.

Rafael-SOWNet added a commit that referenced this pull request Nov 1, 2026
…ed in the parts of x (#2309)

* Over the complex numbers, an equation in and out of a modulus is solved in the parts of x

#2307 left an equation with x inside abs, sgn, conj, Re, Im or arg and outside it too
unsolved over the complex numbers, since Newton's method assumes a holomorphic function
and its near-copies of a root came back as roots. Leaving it unsolved is not solving it.

With x = a + b i and each |u| a real t >= 0 with t^2 = (Re u)^2 + (Im u)^2, the real and
imaginary parts of the equation and one equation per modulus are a polynomial system in
as many unknowns, which the Groebner solver answers exactly and completely or not at
all. The roots are its solutions with a, b and every t real and no t negative, each put
back into the equation as written, since clearing the denominators can add a pole.
conj, Re and Im split directly. sgn(u) is u/|u| where u is not zero, and the case where
it is zero is solved on its own.

x^2/|1 - x^2| = x is { 0, (1 + sqrt(5))/2, (sqrt(5) - 1)/2 }, x |x| = 4 is { 2 },
x + sgn(x) = 3 is { 2 } again, and x^2 + 1 = |x| is +-i (sqrt(5) - 1)/2, which neither
the search nor a split by the sign found. Left unsolved: infinitely many solutions
(|x| = Re x), roots with no exact form (x^5 = |x| + 1), arg, and a system above 32
solutions by Bezout's bound, past which x^7 = |x| + 1 spent over 20 s declining.

The route runs once, on the equation as asked and ahead of the spelling loop, whose
spellings would each be the same system: asked of every one, x^5 = |x^3 + 1| + 1 ran
it dozens of times.


* Walk the tree by hand for the test that picks out these equations

It is asked of every equation the solver is given, ahead of the spelling loop. Enumerating
Nodes allocates an iterator at each level, and that was 4.5 MB of the kernel benchmark's
SolveHard, 45% of it, which has no modulus in it. The walk allocates nothing: SolveHard
allocates 187,558,968 bytes per solve on master and on the branch.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
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.

An equation through abs is answered in decimals, with two non-real entries that are not roots

2 participants