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

Commit 95b2f40

Browse files
committed
Made kwargs of parameters
1 parent dbe614b commit 95b2f40

File tree

2 files changed

+110
-19
lines changed

2 files changed

+110
-19
lines changed

src/trustRegion.jl

Lines changed: 56 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@ A low-overhead implementation of a
88
[trust-region](https://optimization.mccormick.northwestern.edu/index.php/Trust-region_methods)
99
solver
1010
11-
12-
### Keyword Arguments
11+
### Arguments
1312
- `max_trust_radius`: the maximum radius of the trust region. The step size in the algorithm
1413
will change dynamically. However, it will never be greater than the `max_trust_radius`.
1514
@@ -27,14 +26,54 @@ solver
2726
- `diff_type`: the type of finite differencing used if `autodiff = false`. Defaults to
2827
`Val{:forward}` for forward finite differences. For more details on the choices, see the
2928
[FiniteDiff.jl](https://github.com/JuliaDiff/FiniteDiff.jl) documentation.
29+
- `initial_trust_radius`: the initial trust region radius. Defaults to
30+
`max_trust_radius / 11`.
31+
- `step_threshold`: the threshold for taking a step. In every iteration, the threshold is
32+
compared with a value `r`, which is the actual reduction in the objective function divided
33+
by the predicted reduction. If `step_threshold > r` the model is not a good approximation,
34+
and the step is rejected. Defaults to `0.1`. For more details, see
35+
[Trust-region methods](https://optimization.mccormick.northwestern.edu/index.php/Trust-region_methods)
36+
- `shrink_threshold`: the threshold for shrinking the trust region radius. In every
37+
iteration, the threshold is compared with a value `r` which is the actual reduction in the
38+
objective function divided by the predicted reduction. If `shrink_threshold > r` the trust
39+
region radius is shrunk by `shrink_factor`. Defaults to `0.25`. For more details, see
40+
[Trust-region methods](https://optimization.mccormick.northwestern.edu/index.php/Trust-region_methods)
41+
- `expand_threshold`: the threshold for expanding the trust region radius. If a step is
42+
taken, i.e `step_threshold < r` (with `r` defined in `shrink_threshold`), a check is also
43+
made to see if `expand_threshold < r`. If that is true, the trust region radius is
44+
expanded by `expand_factor`. Defaults to `0.75`.
45+
- `shrink_factor`: the factor to shrink the trust region radius with if
46+
`shrink_threshold > r` (with `r` defined in `shrink_threshold`). Defaults to `0.25`.
47+
- `expand_factor`: the factor to expand the trust region radius with if
48+
`expand_threshold < r` (with `r` defined in `shrink_threshold`). Defaults to `2.0`.
49+
- `max_shrink_times`: the maximum number of times to shrink the trust region radius in a
50+
row, `max_shrink_times` is exceeded, the algorithm returns. Defaults to `32`.
3051
"""
3152
struct TrustRegion{CS, AD, FDT} <: AbstractNewtonAlgorithm{CS, AD, FDT}
3253
max_trust_radius::Number
54+
initial_trust_radius::Number
55+
step_threshold::Number
56+
shrink_threshold::Number
57+
expand_threshold::Number
58+
shrink_factor::Number
59+
expand_factor::Number
60+
max_shrink_times::Int
3361
function TrustRegion(max_trust_radius::Number; chunk_size = Val{0}(),
3462
autodiff = Val{true}(),
35-
diff_type = Val{:forward})
63+
diff_type = Val{:forward},
64+
initial_trust_radius::Number = max_trust_radius / 11,
65+
step_threshold::Number = 0.1,
66+
shrink_threshold::Number = 0.25,
67+
expand_threshold::Number = 0.75,
68+
shrink_factor::Number = 0.25,
69+
expand_factor::Number = 2.0,
70+
max_shrink_times::Int = 32)
3671
new{SciMLBase._unwrap_val(chunk_size), SciMLBase._unwrap_val(autodiff),
37-
SciMLBase._unwrap_val(diff_type)}(max_trust_radius)
72+
SciMLBase._unwrap_val(diff_type)}(max_trust_radius, initial_trust_radius,
73+
step_threshold,
74+
shrink_threshold, expand_threshold,
75+
shrink_factor,
76+
expand_factor, max_shrink_times)
3877
end
3978
end
4079

@@ -45,13 +84,14 @@ function SciMLBase.solve(prob::NonlinearProblem,
4584
f = Base.Fix2(prob.f, prob.p)
4685
x = float(prob.u0)
4786
T = typeof(x)
48-
Δₘₐₓ = float(alg.max_trust_radius) # The maximum trust region radius.
49-
Δ = Δₘₐₓ / 11 # Initial trust region radius.
50-
η₁ = 0.1 # Threshold for taking a step.
51-
η₂ = 0.25 # Threshold for shrinking the trust region.
52-
η₃ = 0.75 # Threshold for expanding the trust region.
53-
t₁ = 0.25 # Factor to shrink the trust region with.
54-
t₂ = 2.0 # Factor to expand the trust region with.
87+
Δₘₐₓ = float(alg.max_trust_radius)
88+
Δ = float(alg.initial_trust_radius)
89+
η₁ = float(alg.step_threshold)
90+
η₂ = float(alg.shrink_threshold)
91+
η₃ = float(alg.expand_threshold)
92+
t₁ = float(alg.shrink_factor)
93+
t₂ = float(alg.expand_factor)
94+
max_shrink_times = alg.max_shrink_times
5595

5696
if SciMLBase.isinplace(prob)
5797
error("TrustRegion currently only supports out-of-place nonlinear problems")
@@ -74,7 +114,7 @@ function SciMLBase.solve(prob::NonlinearProblem,
74114
fₖ = 0.5 * norm(F)^2
75115
H = ∇f * ∇f
76116
g = ∇f * F
77-
counter = 0
117+
shrink_counter = 0
78118

79119
for k in 1:maxiters
80120
# Solve the trust region subproblem.
@@ -85,18 +125,18 @@ function SciMLBase.solve(prob::NonlinearProblem,
85125

86126
# Compute the ratio of the actual to predicted reduction.
87127
model = -' * g + 0.5 * δ' * H * δ)
88-
r = (fₖ - fₖ₊₁) / model
128+
r = model \ (fₖ - fₖ₊₁)
89129

90130
# Update the trust region radius.
91131
if r < η₂
92132
Δ = t₁ * Δ
93-
counter += 1
94-
if counter > 32
133+
shrink_counter += 1
134+
if shrink_counter > max_shrink_times
95135
return SciMLBase.build_solution(prob, alg, x, F;
96136
retcode = ReturnCode.Success)
97137
end
98138
else
99-
counter = 0
139+
shrink_counter = 0
100140
end
101141
if r > η₁
102142
if isapprox(xₖ₊₁, x, atol = atol, rtol = rtol)

test/basictests.jl

Lines changed: 54 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ using ForwardDiff
6363
f, u0 = (u, p) -> u .* u .- p, @SVector[1.0, 1.0]
6464

6565
for alg in [SimpleNewtonRaphson(), Broyden(), Klement(),
66-
TrustRegion(10.0)]
66+
TrustRegion(10.0)]
6767
g = function (p)
6868
probN = NonlinearProblem{false}(f, csu0, p)
6969
sol = solve(probN, alg, tol = 1e-9)
@@ -79,7 +79,7 @@ end
7979
# Scalar
8080
f, u0 = (u, p) -> u * u - p, 1.0
8181
for alg in [SimpleNewtonRaphson(), Broyden(), Klement(),
82-
TrustRegion(10.0)]
82+
TrustRegion(10.0)]
8383
g = function (p)
8484
probN = NonlinearProblem{false}(f, oftype(p, u0), p)
8585
sol = solve(probN, alg)
@@ -121,7 +121,7 @@ for alg in [Bisection(), Falsi()]
121121
end
122122

123123
for alg in [SimpleNewtonRaphson(), Broyden(), Klement(),
124-
TrustRegion(10.0)]
124+
TrustRegion(10.0)]
125125
global g, p
126126
g = function (p)
127127
probN = NonlinearProblem{false}(f, 0.5, p)
@@ -207,3 +207,54 @@ sol = solve(probB, Bisection(; exact_left = true, exact_right = true); immutable
207207
@test f(nextfloat(sol.left), nothing) >= 0.0
208208
@test f(sol.right, nothing) >= 0.0
209209
@test f(prevfloat(sol.right), nothing) <= 0.0
210+
211+
# Test that `TrustRegion` passes a test that `SimpleNewtonRaphson` fails on.
212+
u0 = [-10.0, -1.0, 1.0, 2.0, 3.0, 4.0, 10.0]
213+
global g, f
214+
f = (u, p) -> 0.010000000000000002 .+
215+
10.000000000000002 ./ (1 .+
216+
(0.21640425613334457 .+
217+
216.40425613334457 ./ (1 .+
218+
(0.21640425613334457 .+
219+
216.40425613334457 ./
220+
(1 .+ 0.0006250000000000001(u .^ 2.0))) .^ 2.0)) .^ 2.0) .-
221+
0.0011552453009332421u
222+
.-p
223+
g = function (p)
224+
probN = NonlinearProblem{false}(f, u0, p)
225+
sol = solve(probN, TrustRegion(100.0))
226+
return sol.u
227+
end
228+
p = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
229+
u = g(p)
230+
f(u, p)
231+
@test all(f(u, p) .< 1e-10)
232+
233+
# Test kwars in `TrustRegion`
234+
max_trust_radius = [10.0, 100.0, 1000.0]
235+
initial_trust_radius = [10.0, 1.0, 0.1]
236+
step_threshold = [0.0, 0.01, 0.25]
237+
shrink_threshold = [0.25, 0.3, 0.5]
238+
expand_threshold = [0.5, 0.8, 0.9]
239+
shrink_factor = [0.1, 0.3, 0.5]
240+
expand_factor = [1.5, 2.0, 3.0]
241+
max_shrink_times = [10, 20, 30]
242+
243+
list_of_options = zip(max_trust_radius, initial_trust_radius, step_threshold,
244+
shrink_threshold, expand_threshold, shrink_factor,
245+
expand_factor, max_shrink_times)
246+
for options in list_of_options
247+
local probN, sol, alg
248+
alg = TrustRegion(options[1];
249+
initial_trust_radius = options[2],
250+
step_threshold = options[3],
251+
shrink_threshold = options[4],
252+
expand_threshold = options[5],
253+
shrink_factor = options[6],
254+
expand_factor = options[7],
255+
max_shrink_times = options[8])
256+
257+
probN = NonlinearProblem(f, u0, p)
258+
sol = solve(probN, alg)
259+
@test all(f(u, p) .< 1e-10)
260+
end

0 commit comments

Comments
 (0)