Skip to content

Commit cf7bea5

Browse files
Use allowsbounds trait and lb/ub fields from NonlinearLeastSquaresProblem
Updated NonlinearSolveSciPy and NonlinearSolveBase to use the new lb/ub fields added to NonlinearLeastSquaresProblem in SciMLBase.jl PR #1169: NonlinearSolveSciPy: - Import and use SciMLBase.allowsbounds trait - Implement allowsbounds trait methods: - allowsbounds(::SciPyLeastSquares) = true - allowsbounds(::SciPyRoot) = false - allowsbounds(::SciPyRootScalar) = false - Update __solve to get bounds from prob.lb and prob.ub instead of hasproperty NonlinearSolveBase: - Add bounds checking in solve_call for NonlinearLeastSquaresProblem - Error if algorithm doesn't support bounds but problem has them This properly separates concerns: - SciMLBase defines the problem interface with lb/ub fields - allowsbounds trait indicates algorithm support - NonlinearSolveBase validates compatibility - NonlinearSolveSciPy uses the fields directly Depends on: SciMLBase.jl #1169 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]>
1 parent e2aa7b7 commit cf7bea5

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

lib/NonlinearSolveBase/src/solve.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,14 @@ function solve_call(_prob, args...; merge_callbacks = true, kwargshandle = nothi
136136
end
137137

138138
checkkwargs(kwargshandle; kwargs...)
139+
140+
# Check bounds support for NonlinearLeastSquaresProblem
141+
if _prob isa SciMLBase.NonlinearLeastSquaresProblem &&
142+
(_prob.lb !== nothing || _prob.ub !== nothing) &&
143+
length(args) > 0 && !SciMLBase.allowsbounds(args[1])
144+
error("Algorithm $(args[1]) does not support bounds. Use an algorithm with allowsbounds(alg) == true.")
145+
end
146+
139147
if isdefined(_prob, :u0)
140148
if _prob.u0 isa Array
141149
if !isconcretetype(RecursiveArrayTools.recursive_unitless_eltype(_prob.u0))

lib/NonlinearSolveSciPy/src/NonlinearSolveSciPy.jl

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ end
2121

2222
using CommonSolve
2323
using SciMLBase
24+
using SciMLBase: allowsbounds
2425
using NonlinearSolveBase: AbstractNonlinearSolveAlgorithm,
2526
construct_extension_function_wrapper
2627

@@ -123,12 +124,10 @@ function SciMLBase.__solve(
123124
# Construct Python residual
124125
py_f = _make_py_residual(prob.f, prob.p)
125126

126-
# Bounds handling (lb/ub may be missing)
127-
has_lb = hasproperty(prob, :lb)
128-
has_ub = hasproperty(prob, :ub)
129-
if has_lb || has_ub
130-
lb = has_lb ? getproperty(prob, :lb) : fill(-Inf, length(prob.u0))
131-
ub = has_ub ? getproperty(prob, :ub) : fill(Inf, length(prob.u0))
127+
# Bounds handling from problem fields
128+
if prob.lb !== nothing || prob.ub !== nothing
129+
lb = prob.lb !== nothing ? prob.lb : fill(-Inf, length(prob.u0))
130+
ub = prob.ub !== nothing ? prob.ub : fill(Inf, length(prob.u0))
132131
bounds = (lb, ub)
133132
else
134133
bounds = nothing
@@ -257,6 +256,11 @@ function CommonSolve.solve(prob::SciMLBase.IntervalNonlinearProblem, alg::SciPyR
257256
original = res, stats = stats)
258257
end
259258

259+
# Trait declarations
260+
SciMLBase.allowsbounds(::SciPyLeastSquares) = true
261+
SciMLBase.allowsbounds(::SciPyRoot) = false
262+
SciMLBase.allowsbounds(::SciPyRootScalar) = false
263+
260264
@reexport using SciMLBase, NonlinearSolveBase
261265

262266
export SciPyLeastSquares, SciPyLeastSquaresTRF, SciPyLeastSquaresDogbox,

0 commit comments

Comments
 (0)