@@ -8,8 +8,7 @@ A low-overhead implementation of a
88[trust-region](https://optimization.mccormick.northwestern.edu/index.php/Trust-region_methods)
99solver
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"""
3152struct 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
3978end
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)
0 commit comments