Skip to content

Commit df44983

Browse files
committed
Modify Muller to be an IntervalNonlinearProblem
1 parent 013e7be commit df44983

File tree

6 files changed

+32
-193
lines changed

6 files changed

+32
-193
lines changed

lib/BracketingNonlinearSolve/src/BracketingNonlinearSolve.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,6 @@ end
4545

4646
@reexport using SciMLBase, NonlinearSolveBase
4747

48-
export Alefeld, Bisection, Brent, Falsi, ITP, Muller, Ridder
48+
export Alefeld, Bisection, Brent, Falsi, Muller, ITP, Ridder
4949

5050
end
Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,55 @@
11
"""
2-
Muller(; middle = nothing)
2+
Muller()
33
44
Muller's method for determining a root of a univariate, scalar function. The
55
algorithm, described in Sec. 9.5.2 of
66
[Press et al. (2007)](https://numerical.recipes/book.html), requires three
7-
initial guesses `(left, middle, right)` for the root.
8-
9-
### Keyword Arguments
10-
11-
- `middle`: the initial guess for the middle point. If not provided, the
12-
midpoint of the interval `(left, right)` is used.
7+
initial guesses `(xᵢ₋₂, xᵢ₋₁, xᵢ)` for the root.
138
"""
14-
struct Muller{T} <: AbstractBracketingAlgorithm
15-
middle::T
16-
end
17-
18-
Muller() = Muller(nothing)
9+
struct Muller <: AbstractBracketingAlgorithm end
1910

2011
function CommonSolve.solve(prob::IntervalNonlinearProblem, alg::Muller, args...;
21-
abstol = nothing, maxiters = 1000, kwargs...)
12+
abstol = nothing, maxiters = 1000, kwargs...)
2213
@assert !SciMLBase.isinplace(prob) "`Muller` only supports out-of-place problems."
2314
xᵢ₋₂, xᵢ = prob.tspan
24-
xᵢ₋₁ = isnothing(alg.middle) ? (xᵢ₋₂ + xᵢ) / 2 : alg.middle
15+
xᵢ₋₁ = (xᵢ₋₂ + xᵢ) / 2 # Use midpoint for middle guess
2516
xᵢ₋₂, xᵢ₋₁, xᵢ = promote(xᵢ₋₂, xᵢ₋₁, xᵢ)
2617
@assert xᵢ₋₂ xᵢ₋₁ xᵢ xᵢ₋₂
2718
f = Base.Fix2(prob.f, prob.p)
2819
fxᵢ₋₂, fxᵢ₋₁, fxᵢ = f(xᵢ₋₂), f(xᵢ₋₁), f(xᵢ)
2920

3021
xᵢ₊₁, fxᵢ₊₁ = xᵢ₋₂, fxᵢ₋₂
3122

32-
abstol = abs(NonlinearSolveBase.get_tolerance(
33-
xᵢ₋₂, abstol, promote_type(eltype(xᵢ₋₂), eltype(xᵢ))))
23+
abstol = NonlinearSolveBase.get_tolerance(
24+
xᵢ₋₂, abstol, promote_type(eltype(xᵢ₋₂), eltype(xᵢ)))
3425

35-
for _ in 1:maxiters
36-
q = (xᵢ - xᵢ₋₁) / (xᵢ₋₁ - xᵢ₋₂)
37-
A = q * fxᵢ - q * (1 + q) * fxᵢ₋₁ + q^2 * fxᵢ₋₂
38-
B = (2 * q + 1) * fxᵢ - (1 + q)^2 * fxᵢ₋₁ + q^2 * fxᵢ₋₂
39-
C = (1 + q) * fxᵢ
26+
for _ 1:maxiters
27+
q = (xᵢ - xᵢ₋₁)/(xᵢ₋₁ - xᵢ₋₂)
28+
A = q*fxᵢ - q*(1 + q)*fxᵢ₋₁ + q^2*fxᵢ₋₂
29+
B = (2*q + 1)*fxᵢ - (1 + q)^2*fxᵢ₋₁ + q^2*fxᵢ₋₂
30+
C = (1 + q)*fxᵢ
4031

41-
denom₊ = B + (B^2 - 4 * A * C)
42-
denom₋ = B - (B^2 - 4 * A * C)
32+
denom₊ = B + (B^2 - 4*A*C)
33+
denom₋ = B - (B^2 - 4*A*C)
4334

4435
if abs(denom₊) abs(denom₋)
45-
xᵢ₊₁ = xᵢ - (xᵢ - xᵢ₋₁) * 2 * C / denom₊
36+
xᵢ₊₁ = xᵢ - (xᵢ - xᵢ₋₁)*2*C/denom₊
4637
else
47-
xᵢ₊₁ = xᵢ - (xᵢ - xᵢ₋₁) * 2 * C / denom₋
38+
xᵢ₊₁ = xᵢ - (xᵢ - xᵢ₋₁)*2*C/denom₋
4839
end
4940

5041
fxᵢ₊₁ = f(xᵢ₊₁)
5142

5243
# Termination Check
5344
if abstol abs(fxᵢ₊₁)
5445
return SciMLBase.build_solution(prob, alg, xᵢ₊₁, fxᵢ₊₁;
55-
retcode = ReturnCode.Success,
56-
left = xᵢ₊₁, right = xᵢ₊₁)
46+
retcode = ReturnCode.Success)
5747
end
5848

5949
xᵢ₋₂, xᵢ₋₁, xᵢ = xᵢ₋₁, xᵢ, xᵢ₊₁
6050
fxᵢ₋₂, fxᵢ₋₁, fxᵢ = fxᵢ₋₁, fxᵢ, fxᵢ₊₁
6151
end
6252

6353
return SciMLBase.build_solution(prob, alg, xᵢ₊₁, fxᵢ₊₁;
64-
retcode = ReturnCode.MaxIters,
65-
left = xᵢ₊₁, right = xᵢ₊₁)
54+
retcode = ReturnCode.MaxIters)
6655
end
Lines changed: 13 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
@testitem "Muller" begin
2-
f(u, p) = u^2 - p
3-
g(u, p) = sin(u)
4-
h(u, p) = exp(-u) * sin(u)
5-
i(u, p) = u^3 - 1
6-
72
@testset "Quadratic function" begin
3+
f(u, p) = u^2 - p
4+
85
tspan = (10.0, 30.0)
96
p = 612.0
107
prob = IntervalNonlinearProblem{false}(f, tspan, p)
@@ -20,77 +17,40 @@
2017
end
2118

2219
@testset "Sine function" begin
20+
f(u, p) = sin(u)
21+
2322
tspan = (1.0, 3.0)
24-
prob = IntervalNonlinearProblem{false}(g, tspan)
23+
prob = IntervalNonlinearProblem{false}(f, tspan)
2524
sol = solve(prob, Muller())
2625

2726
@test sol.u π
2827

2928
tspan = (2.0, 6.0)
30-
prob = IntervalNonlinearProblem{false}(g, tspan)
29+
prob = IntervalNonlinearProblem{false}(f, tspan)
3130
sol = solve(prob, Muller())
3231

33-
@test sol.u 2 * π
32+
@test sol.u 2*π
3433
end
3534

3635
@testset "Exponential-sine function" begin
36+
f(u, p) = exp(-u)*sin(u)
37+
3738
tspan = (-2.0, -4.0)
38-
prob = IntervalNonlinearProblem{false}(h, tspan)
39+
prob = IntervalNonlinearProblem{false}(f, tspan)
3940
sol = solve(prob, Muller())
4041

4142
@test sol.u -π
4243

4344
tspan = (-3.0, 1.0)
44-
prob = IntervalNonlinearProblem{false}(h, tspan)
45+
prob = IntervalNonlinearProblem{false}(f, tspan)
4546
sol = solve(prob, Muller())
4647

47-
@test sol.u0 atol=1e-15
48+
@test sol.u 0 atol = 1e-15
4849

4950
tspan = (-1.0, 1.0)
50-
prob = IntervalNonlinearProblem{false}(h, tspan)
51-
sol = solve(prob, Muller())
52-
53-
@test sol.u π
54-
end
55-
56-
@testset "Complex roots" begin
57-
tspan = (-1.0, 1.0 * im)
58-
prob = IntervalNonlinearProblem{false}(i, tspan)
51+
prob = IntervalNonlinearProblem{false}(f, tspan)
5952
sol = solve(prob, Muller())
6053

61-
@test sol.u (-1 + 3 * im) / 2
62-
63-
tspan = (-1.0, -1.0 * im)
64-
prob = IntervalNonlinearProblem{false}(i, tspan)
65-
sol = solve(prob, Muller())
66-
67-
@test sol.u (-1 - 3 * im) / 2
68-
end
69-
70-
@testset "Middle" begin
71-
tspan = (10.0, 30.0)
72-
p = 612.0
73-
prob = IntervalNonlinearProblem{false}(f, tspan, p)
74-
sol = solve(prob, Muller(20.0))
75-
76-
@test sol.u 612
77-
78-
tspan = (1.0, 3.0)
79-
prob = IntervalNonlinearProblem{false}(g, tspan)
80-
sol = solve(prob, Muller(2.0))
81-
8254
@test sol.u π
83-
84-
tspan = (-2.0, -4.0)
85-
prob = IntervalNonlinearProblem{false}(h, tspan)
86-
sol = solve(prob, Muller(-3.0))
87-
88-
@test sol.u -π
89-
90-
tspan = (-1.0, 1.0 * im)
91-
prob = IntervalNonlinearProblem{false}(i, tspan)
92-
sol = solve(prob, Muller(0.0))
93-
94-
@test sol.u (-1 + 3 * im) / 2
9555
end
9656
end

lib/SimpleNonlinearSolve/src/SimpleNonlinearSolve.jl

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,6 @@ include("klement.jl")
5454
include("lbroyden.jl")
5555
include("raphson.jl")
5656
include("trust_region.jl")
57-
include("muller.jl")
5857

5958
# By Pass the highlevel checks for NonlinearProblem for Simple Algorithms
6059
function CommonSolve.solve(
@@ -167,7 +166,6 @@ export SimpleBroyden, SimpleKlement, SimpleLimitedMemoryBroyden
167166
export SimpleDFSane
168167
export SimpleGaussNewton, SimpleNewtonRaphson, SimpleTrustRegion
169168
export SimpleHalley
170-
export SimpleMuller
171169

172170
export solve
173171

lib/SimpleNonlinearSolve/src/muller.jl

Lines changed: 0 additions & 52 deletions
This file was deleted.

lib/SimpleNonlinearSolve/test/core/muller_tests.jl

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)