Skip to content
This repository was archived by the owner on May 15, 2025. It is now read-only.

Commit 58f41f7

Browse files
committed
Bug fixes
1 parent 22bb58b commit 58f41f7

File tree

9 files changed

+47
-44
lines changed

9 files changed

+47
-44
lines changed

src/nlsolve/broyden.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ and static array problems.
77
struct SimpleBroyden <: AbstractSimpleNonlinearSolveAlgorithm end
88

99
function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleBroyden, args...;
10-
abstol = nothing, reltol = nothing, maxiters = 1000,
10+
abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
1111
termination_condition = nothing, kwargs...)
12-
@bb x = copy(float(prob.u0))
12+
x = __maybe_unaliased(prob.u0, alias_u0)
1313
fx = _get_fx(prob, x)
1414

1515
@bb xo = copy(x)

src/nlsolve/dfsane.jl

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,9 @@ Computation, 75, 1429-1448.](https://www.researchgate.net/publication/220576479_
5151
end
5252

5353
function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleDFSane, args...;
54-
abstol = nothing, reltol = nothing, maxiters = 1000,
54+
abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
5555
termination_condition = nothing, kwargs...)
56-
x = float(copy(prob.u0))
56+
x = __maybe_unaliased(prob.u0, alias_u0)
5757
fx = _get_fx(prob, x)
5858
T = eltype(x)
5959

@@ -76,6 +76,7 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleDFSane, args...;
7676
history_f_k = fill(fx_norm, M)
7777

7878
# Generate the cache
79+
@bb x_cache = similar(x)
7980
@bb d = copy(x)
8081
@bb xo = copy(x)
8182
@bb δx = copy(x)
@@ -89,38 +90,40 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleDFSane, args...;
8990
# Line search direction
9091
@bb @. d = -σ_k * fx
9192

92-
η = η_strategy(f_1, k, x, fx)
93+
η = η_strategy(f_1, k + 1, x, fx)
9394
f_bar = maximum(history_f_k)
9495
α_p = α_1
9596
α_m = α_1
9697

97-
@bb @. x += α_p * d
98+
@bb @. x_cache = x + α_p * d
9899

99-
fx = __eval_f(prob, fx, x)
100+
fx = __eval_f(prob, fx, x_cache)
100101
fx_norm_new = NONLINEARSOLVE_DEFAULT_NORM(fx)^nexp
101102

102103
while k < maxiters
103104
Bool(fx_norm_new (f_bar + η - γ * α_p^2 * fx_norm)) && break
104105

105-
α_p = α_p^2 * fx_norm / (fx_norm_new + (T(2) * α_p - T(1)) * fx_norm)
106-
@bb @. x -= α_m * d
106+
α_tp = α_p^2 * fx_norm / (fx_norm_new + (T(2) * α_p - T(1)) * fx_norm)
107+
@bb @. x_cache = x - α_m * d
107108

108-
fx = __eval_f(prob, fx, x)
109+
fx = __eval_f(prob, fx, x_cache)
109110
fx_norm_new = NONLINEARSOLVE_DEFAULT_NORM(fx)^nexp
110111

111112
Bool(fx_norm_new (f_bar + η - γ * α_m^2 * fx_norm)) && break
112113

113114
α_tm = α_m^2 * fx_norm / (fx_norm_new + (T(2) * α_m - T(1)) * fx_norm)
114-
α_p = clamp(α_p, τ_min * α_p, τ_max * α_p)
115+
α_p = clamp(α_tp, τ_min * α_p, τ_max * α_p)
115116
α_m = clamp(α_tm, τ_min * α_m, τ_max * α_m)
116-
@bb @. x += α_p * d
117+
@bb @. x_cache = x + α_p * d
117118

118-
fx = __eval_f(prob, fx, x)
119+
fx = __eval_f(prob, fx, x_cache)
119120
fx_norm_new = NONLINEARSOLVE_DEFAULT_NORM(fx)^nexp
120121

121122
k += 1
122123
end
123124

125+
@bb copyto!(x, x_cache)
126+
124127
tc_sol = check_termination(tc_cache, fx, x, xo, prob, alg)
125128
tc_sol !== nothing && return tc_sol
126129

src/nlsolve/halley.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ A low-overhead implementation of Halley's Method.
2424
end
2525

2626
function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleHalley, args...;
27-
abstol = nothing, reltol = nothing, maxiters = 1000,
27+
abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
2828
termination_condition = nothing, kwargs...)
2929
isinplace(prob) &&
3030
error("SimpleHalley currently only supports out-of-place nonlinear problems")
3131

32-
x = copy(float(prob.u0))
32+
x = __maybe_unaliased(prob.u0, alias_u0)
3333
fx = _get_fx(prob, x)
3434
T = eltype(x)
3535

src/nlsolve/klement.jl

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@ method is non-allocating on scalar and static array problems.
77
struct SimpleKlement <: AbstractSimpleNonlinearSolveAlgorithm end
88

99
function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleKlement, args...;
10-
abstol = nothing, reltol = nothing, maxiters = 1000,
10+
abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
1111
termination_condition = nothing, kwargs...)
12-
@bb x = copy(float(prob.u0))
12+
x = __maybe_unaliased(prob.u0, alias_u0)
1313
T = eltype(x)
1414
fx = _get_fx(prob, x)
1515

@@ -21,13 +21,12 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleKlement, args...;
2121
@bb δx = copy(x)
2222
@bb fprev = copy(fx)
2323
@bb xo = copy(x)
24-
@bb δf = copy(fx)
2524
@bb d = copy(x)
2625

2726
J = __init_identity_jacobian(fx, x)
28-
@bb J_cache = copy(J)
29-
@bb δx² = copy(x)
30-
@bb J_cache2 = copy(J)
27+
@bb J_cache = similar(J)
28+
@bb δx² = similar(x)
29+
@bb J_cache2 = similar(J)
3130
@bb F = copy(J)
3231

3332
for _ in 1:maxiters
@@ -67,23 +66,18 @@ function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleKlement, args...;
6766
tc_sol !== nothing && return tc_sol
6867

6968
@bb δx .*= -1
70-
@bb @. δf = fx - fprev
71-
72-
# Prevent division by 0
69+
@bb J_cache .= J' .^ 2
7370
@bb @. δx² = δx^2
74-
@bb @. J_cache = J^2
75-
@bb d = transpose(J_cache) × vec(δx²)
76-
@bb @. d = max(d, singular_tol)
77-
71+
@bb d = J_cache × vec(δx²)
7872
@bb δx² = J × vec(δx)
79-
@bb @. δf = (δf - δx²) / d
80-
81-
_vδf, _vδx = _vec(δf), _vec(δx)
82-
@bb J_cache = _vδf × transpose(_vδx)
73+
@bb @. fprev = (fx - fprev - δx²) / ifelse(iszero(d), singular_tol, d)
74+
@bb J_cache = vec(fprev) × transpose(_vec(δx))
8375
@bb @. J_cache *= J
8476
@bb J_cache2 = J_cache × J
85-
8677
@bb @. J += J_cache2
78+
79+
@bb copyto!(fprev, fx)
80+
@bb copyto!(xo, x)
8781
end
8882

8983
return build_solution(prob, alg, x, fx; retcode = ReturnCode.MaxIters)

src/nlsolve/lbroyden.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ function SimpleLimitedMemoryBroyden(; threshold::Union{Val, Int} = Val(27))
2222
end
2323

2424
@views function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleLimitedMemoryBroyden,
25-
args...; abstol = nothing, reltol = nothing, maxiters = 1000,
25+
args...; abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
2626
termination_condition = nothing, kwargs...)
27-
@bb x = copy(float(prob.u0))
27+
x = __maybe_unaliased(prob.u0, alias_u0)
2828
threshold = __get_threshold(alg)
2929
η = min(SciMLBase._unwrap_val(threshold), maxiters)
3030

src/nlsolve/raphson.jl

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ const SimpleGaussNewton = SimpleNewtonRaphson
2424

2525
function SciMLBase.__solve(prob::Union{NonlinearProblem, NonlinearLeastSquaresProblem},
2626
alg::SimpleNewtonRaphson, args...; abstol = nothing, reltol = nothing,
27-
maxiters = 1000, termination_condition = nothing, kwargs...)
28-
@bb x = copy(float(prob.u0))
27+
maxiters = 1000, termination_condition = nothing, alias_u0 = false, kwargs...)
28+
x = __maybe_unaliased(prob.u0, alias_u0)
2929
fx = _get_fx(prob, x)
3030
@bb xo = copy(x)
3131
J, jac_cache = jacobian_cache(alg.autodiff, prob.f, fx, x, prob.p)
@@ -37,9 +37,7 @@ function SciMLBase.__solve(prob::Union{NonlinearProblem, NonlinearLeastSquaresPr
3737
fx, dfx = value_and_jacobian(alg.autodiff, prob.f, fx, x, prob.p, jac_cache; J)
3838

3939
if i == 1
40-
if iszero(fx)
41-
return build_solution(prob, alg, x, fx; retcode = ReturnCode.Success)
42-
end
40+
iszero(fx) && build_solution(prob, alg, x, fx; retcode = ReturnCode.Success)
4341
else
4442
# Termination Checks
4543
tc_sol = check_termination(tc_cache, fx, x, xo, prob, alg)

src/nlsolve/trustRegion.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ scalar and static array problems.
4949
end
5050

5151
function SciMLBase.__solve(prob::NonlinearProblem, alg::SimpleTrustRegion, args...;
52-
abstol = nothing, reltol = nothing, maxiters = 1000,
52+
abstol = nothing, reltol = nothing, maxiters = 1000, alias_u0 = false,
5353
termination_condition = nothing, kwargs...)
54-
@bb x = copy(float(prob.u0))
54+
x = __maybe_unaliased(prob.u0, alias_u0)
5555
T = eltype(real(x))
5656
Δₘₐₓ = T(alg.max_trust_radius)
5757
Δ = T(alg.initial_trust_radius)

src/utils.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,3 +335,11 @@ end
335335

336336
@inline __eval_f(prob, fx, x) = isinplace(prob) ? (prob.f(fx, x, prob.p); fx) :
337337
prob.f(x, prob.p)
338+
339+
# Unalias
340+
@inline __maybe_unaliased(x::Union{Number, SArray}, ::Bool) = x
341+
@inline function __maybe_unaliased(x::AbstractArray, alias::Bool)
342+
# Spend time coping iff we will mutate the array
343+
(alias || !ArrayInterface.can_setindex(typeof(x))) && return x
344+
return deepcopy(x)
345+
end

test/23_test_problems.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ end
6161
alg_ops = (SimpleDFSane(),)
6262

6363
broken_tests = Dict(alg => Int[] for alg in alg_ops)
64-
broken_tests[alg_ops[1]] = [1, 2, 3, 4, 5, 6, 7, 9, 11, 12, 13, 15, 16, 17, 21, 22]
64+
broken_tests[alg_ops[1]] = [1, 2, 3, 4, 5, 6, 11, 21]
6565

6666
test_on_library(problems, dicts, alg_ops, broken_tests)
6767
end
@@ -82,7 +82,7 @@ end
8282
alg_ops = (SimpleKlement(),)
8383

8484
broken_tests = Dict(alg => Int[] for alg in alg_ops)
85-
broken_tests[alg_ops[1]] = [1, 2, 4, 5, 6, 7, 9, 10, 11, 12, 13, 19, 21, 22]
85+
broken_tests[alg_ops[1]] = [1, 2, 4, 5, 6, 7, 11, 13, 22]
8686

8787
test_on_library(problems, dicts, alg_ops, broken_tests)
8888
end

0 commit comments

Comments
 (0)