Repository navigation
NewtonBisection: correct the Newton step at multiple roots - #1375
ChrisRackauckas wants to merge 11 commits into
Conversation
NewtonBisection is Newton's method safeguarded by bisection, for interval problems that give the derivative of `f` as the `jac` of their IntervalNonlinearFunction. It bisects when a Newton step leaves the bracket or does not shrink fast enough (the rule of `rtsafe`). Once the Newton step is within the tolerance, it evaluates just beyond the Newton point on the other side of the root, doubling the distance until the sign changes, so that both ends converge and a zero tolerance ends with adjacent floats. With a cheap derivative it needs fewer evaluations of `f` than ModAB, for example when locating the events of continuous callbacks. The ForwardDiff extension handles NewtonBisection like the other methods, and keeps the derivative when it strips Duals from the endpoints. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It has the `jac` field that NewtonBisection reads. Also bump to 1.13.0 for the new exported method. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It doubles at every step of the end game, and as an `Int` it could overflow and change sign after 63 doublings. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…osed NewtonBisection now evaluates the derivative at every point right after `f`, also at the two ends of the bracket, so a cache of the last point lets them share work. It also skips the derivative at the last point, which no step uses. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
It evaluates the derivative about as often as `f`, so it needs a derivative that costs a small fraction of `f`, as when `f` is an integral and the derivative its integrand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test gives all methods the derivative, which only NewtonBisection uses, and checks it is also evaluated inside the bracket. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Near a root of multiplicity m Newton's method converges linearly: each step shrinks by (m - 1)/m, which rtsafe's acceptance rule (step at most half the step before the previous one) lets through for m >= 3. So on (u - 1)^3 over (0, 3) at abstol = 0 NewtonBisection took 88 evaluations of f, against 55 for ModAB. When two successive Newton steps from the same end of the bracket shrink by a ratio rho > 1/2, the step is now multiplied by m = round(1/(1 - rho)) (at most 16), if that point stays inside the bracket. Evaluations of f at abstol = 0: 4 on (u - 1)^3, 5 on (u - 1)^5, 12 on sin(u - pi/4)^3, 15 on (exp(u) - 2)^3 (before: 88, 102, 89, 88). On the nine standard functions the total goes from 90 to 91. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Claude <noreply@anthropic.com> Agent-Harness: Claude Code cloud Agent-Model: withheld (the harness forbids model identifiers in commits) Agent-Session: https://claude.ai/code/session_01HJLdhiuK5ih88KyZciWTEH
|
(AI-generated, Claude Code cloud session: https://claude.ai/code/session_01HJLdhiuK5ih88KyZciWTEH) The red Downgrade / Downgrade Tests - Core check is not from this PR:
Generated by Claude Code |
|
(AI-generated, Claude Code cloud session: https://claude.ai/code/session_01HJLdhiuK5ih88KyZciWTEH) The red downgrade-sublibraries / test (lib/SCCNonlinearSolve) check is not from this PR either:
Generated by Claude Code |
|
Follow-up on the
The same failure shows on #1376 and #1377 for the same reason. AI-generated (Claude Code cloud harness, on behalf of @ChrisRackauckas). Session: https://claude.ai/code/session_01HJLdhiuK5ih88KyZciWTEH Generated by Claude Code |
…ltiplicity Picks up #1347 (PolyAlgorithm solve! retcode type assert for Julia 1.10 inference), fixing the lts Tests-Core and Downgrade-Tests-Core failures. Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Devin <noreply@cognition.ai> Agent-Harness: Devin CLI 3000.11.92 Agent-Model: swe-2-max Agent-Session: local Devin CLI session oss-fix/SciML-NonlinearSolve.jl-1375
Merged What was wrongThree red checks, two upstream causes, none in this PR's code:
Validation (run on the pushed merge
|
…iduals Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Codex <noreply@openai.com> Agent-Harness: Codex CLI 0.163.0 Agent-Model: gpt-6.1-sol Agent-Session: local job 1377-codex (no session URL)
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Codex <noreply@openai.com> Agent-Harness: Codex CLI 0.163.0 Agent-Model: gpt-6.1-sol Agent-Session: local job 1377-codex (no session URL)
Co-Authored-By: Chris Rackauckas <accounts@chrisrackauckas.com> Co-Authored-By: Codex <noreply@openai.com> Agent-Harness: Codex CLI 0.163.0 Agent-Model: gpt-6.1-sol Agent-Session: local job 1377-codex (no session URL)
NewtonBisection corrects the Newton step at multiple roots, rejects undefined residuals before changing the bracket, uses an overflow-safe bisection safeguard, and normalizes integer brackets to floating point before initialization. Existing derivative-free Dual solves with a supplied jacobian use a plain-function wrapper and allocate zero bytes. The concrete Newton derivative wrapper and AD backend validation remain in the AD layer.
The original NewtonBisection branch belongs to the fork behind #1330, so this PR targets master; its dependents target the owned stack branches. Please ignore until reviewed by @ChrisRackauckas. Part of #1377 (#1377).
Failing before / passing after
The same committed safeguard tests ran through a runner that imports Test and includes
newton_safeguard_tests.jlinside@testset "Newton safeguards":The derivative-free wrapper test uses the same 48 assertions before and after the guard. The runner imports Test and includes
interval_wrapper_tests.jl; four zero-allocation assertions discriminate the bug.Integer endpoint normalization is covered with positive, negative and reversed brackets, both default and zero absolute tolerance. The reference is signed
sqrt(big(2)), computed independently of the solver. The same test file produces eight initialization errors before the fix and 32 passing assertions after it.Verification
Current source and test files were checked byte-for-byte against the isolated snapshot used for the official groups below. The snapshot includes the repository project and documentation so QA performs its normal public API checks. Julia 1.10 environments add SciMLBase 3.58 first and develop the local sublibraries and root.
Core passed 21,327 assertions on each Julia version. Runic, staged
git diff --check, andtypos --config .typos.tomlon the staged diff exited zero. No docstrings, docs entries, dependencies, or tolerances changed in these focused guard fixes. Integer brackets now reach the same floating-point iteration as floating brackets.Not verified
GPU, downstream, prerelease, other platforms, and a complete downgrade matrix were not rerun locally. The SCC downgrade issue remains dependent on the open prerequisite fix; no tests were weakened or silenced. Full study wall-time benchmarks were not rerun.
Reviewer decisions
Chris retains the public API decision, acceptance of the two MIT dependencies in the AD layer, the value of adding ModABNewton, and how the original NewtonBisection branch should integrate master. No changes are pushed to that original author's branch.
Independent review
Fresh Codex CLI 0.163.0 / gpt-6.1-sol review at 9e93e479 returned CHANGES, medium risk (M1). It independently reproduced Core 21,327 on each version, sub QA 20/root QA 26, root Core LTS 1,572 passes with 91 existing broken assertions, both safeguard/allocation negative controls, 824 additional analytic assertions at this head, and 96 identical existing solution/trace comparisons.
The remaining compatibility blocker is SCC: the review runs the selected SciMLBase 3.57 configuration and observes 11 passes/1 failure at
isconcretetype(eltype(scc_sol_debug.original)); the base with 3.46 passes 12/12. Passing root Core and QA does not clear this separate failure. The compatible prerequisite and a refreshed downgrade check are required.The review also found that the dependent revisions fetched at its start (
b91696f3/1eb61948) lacked the integer fix. That integration has since landed through normal merges at 695446ab and 377e506d, with AD 64 and combined 128 integer assertions passing locally. The fresh AD review independently tested both final heads, including Core 24,719 on each version at ModABNewton, and confirms the integer and cache-handoff defects are resolved; its only blocker is SCC. Review summary. This is not presented as a clean stack verdict. Its stale-body concern is addressed with the current output and count above.A non-blocking shared follow-up remains: the sensitivity secant for a function capturing Dual state can sample outside a very narrow original bracket. The reviewer reproduces it for NewtonBisection and existing ModAB. It is tracked in the handoff and is not claimed fixed here.
Downstream CI classification
All three current heads fail ModelingToolkit InterfaceI at the same causal-connection equation orientation assertion,
lib/ModelingToolkitBase/test/components.jl:446: multiplicity, AD, ModABNewton. Each actual log selects 207f39e2, the merge of SciML/ModelingToolkit.jl#5295. ModelingToolkit's own master CI fails the identical assertion without this stack. The older passing NonlinearSolve base integration uses an earlier downstream revision and Symbolics/SymbolicUtils versions. All comparison logs were read.CI rechecked 2026-10-21 22:40 UTC: ModABNewton and its actual AD base each have 56 successful checks and the same single ModelingToolkit failure; multiplicity has 80 successes, the ModelingToolkit and SCC failures, and three skips. No checks remain pending. The latest ModelingToolkit master InterfaceI run at fe189a7e still fails the identical assertion (1,590 passed, one failed, three broken); its actual log was read. The routed CHANGES verdict remains blocked on the separate, unmerged SCC prerequisite. No new source commit or push is claimed for this audit. AD Ubuntu LTS Core reports success on the current AD head. No causal-connection test is changed. This upstream failure is separate from the SCC downgrade compatibility regression exposed by the raised SciMLBase minimum; neither is claimed fixed.
Links
Original NewtonBisection: Add NewtonBisection, a bracketing Newton method that uses the derivative #1330
Multiplicity and safeguards: NewtonBisection: correct the Newton step at multiple roots #1375
Opt-in AD: NewtonBisection: opt-in automatic differentiation #1376
ModABNewton: Add ModABNewton: ModAB's bisection phase, then NewtonBisection's steps #1377
SCC prerequisite: Keep spelled NonlinearSolution element type concrete across SciMLBase layouts #1332
Study: https://github.com/SciML/NonlinearSolve.jl/blob/interval-derivative-study/study/REPORT.md
Original author discussion: https://claude.ai/code/session_01HJLdhiuK5ih88KyZciWTEH
Failing SCC check with 3.57: https://github.com/SciML/NonlinearSolve.jl/actions/runs/39550827583/job/119059420114
Passing base SCC check with 3.46: https://github.com/SciML/NonlinearSolve.jl/actions/runs/39042199035/job/117433525410
Upstream connector change: Change comparison to 0 instead of to nothing ModelingToolkit.jl#5295
Matching upstream master failure: https://github.com/SciML/ModelingToolkit.jl/actions/runs/39509027344/job/118925364789
Earlier passing base integration: https://github.com/SciML/NonlinearSolve.jl/actions/runs/39047077630/job/117444557421
Risk assessment
🤖 Posted by an AI agent — harness: Codex CLI 0.163.0 · model: gpt-6.1-sol
Conversation: local job 1377-codex (no session URL)