Seed the numerical search from the real axis, not the grid alone (#115) - #729
Merged
Merged
Conversation
`arcsin(x) - x*pi/3 = 0` answered `{ 0 }`. Its roots are -1/2, 0 and 1/2,
and all three were already inside the region being searched, so this was
not a matter of iterating harder.
The search starts from a grid over the complex plane, which is
two-dimensional: a step count of N costs N^2 Newton runs but lays real
starting points only (To - From) / N apart. At the default that is 2, so
the reporter's three roots -- spanning one unit in total -- shared a
single starting point.
Whether both of two close roots get reached is then left to where the
iteration happens to go. A polynomial usually survives it, its basins
being interleaved across the whole plane; `x*(x - 1/2)*(x + 1/2)` gives
all three. An expression real only on a small interval does not: outside
[-1, 1] every starting point hands arcsin a complex value and the
iteration wanders off.
A sign change is a much cheaper witness of a root than a Newton run is --
one evaluation against the sixty an iteration to precision 30 costs. So
the real axis is now scanned at StepCount.Re * StepCount.Im points, as
many as the grid has starting points, and Newton runs from the brackets
that scan finds. The spacing that matters for a real root becomes
(To - From) / N^2 rather than (To - From) / N: 0.2 at the default rather
than 2.
Additive, and the grid is unchanged. A sign change witnesses a root of
odd multiplicity on an interval where the expression is real, so repeated
roots and roots off the real axis stay the grid's to find; a test pins
both. Intervals where the value is not real are skipped, the intermediate
value theorem having nothing to say there.
Measured: `arcsin(x) - x*pi/3` 1 root -> 3, and `SolveEquation` now
answers the reporter's `{ -1/2, 0, 1/2 }`. Ten other equations covering
polynomial, trigonometric and complex-rooted cases are unchanged in both
roots and timing (the scan is ~2% of what the grid already spends). Full
suite 4861 passed / 0 failed, F# 130/130, corpus 112/117 with 0 wrong,
0 error, 0 timeout.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.
Closes #115.
arcsin(x) - x*pi/3 = 0answered{ 0 }. Its roots are -1/2, 0 and 1/2, and all three were already inside the region being searched, so this was not a matter of iterating harder.What was wrong
The search starts from a grid over the complex plane, which is two-dimensional: a step count of N costs N² Newton runs but lays real starting points only
(To - From) / Napart. At the default 10 over [-10, 10] that is 2, so the reporter’s three roots — spanning one unit in total — shared a single starting point.Whether both of two close roots then get reached is left to where the iteration happens to go. A polynomial usually survives it, its basins being interleaved across the whole plane:
x*(x - 1/2)*(x + 1/2)has roots the same 0.5 apart and gives all three. An expression that is real only on a small interval does not — outside[-1, 1]every starting point handsarcsina complex value and the iteration wanders off. That is why this looked like a hard limit of the method and was not.The fix
A sign change is a much cheaper witness of a root than a Newton run is: one evaluation against the sixty an iteration to precision 30 costs. So the real axis is now scanned at
StepCount.Re * StepCount.Impoints — as many as the grid has starting points — and Newton runs only from the brackets that scan finds.The spacing that matters for a real root becomes
(To - From) / N²rather than(To - From) / N: 0.2 at the default rather than 2, for about 2% of what the grid already spends.It is additive and the grid is untouched. A sign change witnesses a root of odd multiplicity on an interval where the expression is real, so repeated roots (
x^2 + 2x + 1) and roots off the real axis (x^2 + 1) stay the grid’s to find — a test pins both. Intervals where the value is not real are skipped, the intermediate value theorem having nothing to say there.Measured
arcsin(x) - x*pi/3viaSolveNt{0}arcsin(x) - x*pi/3viaSolveEquation{ 0 }{ -1/2, 0, 1/2 }Ten other equations covering polynomial, trigonometric and complex-rooted cases are unchanged in both roots and timing.
Full suite 4861 passed / 0 failed, F# 130/130, 117-problem corpus 112/117 with 0 wrong, 0 error, 0 timeout — all unchanged from master.
🤖 Generated with Claude Code