203
203
shrink_counter:: Int
204
204
du
205
205
u_tmp
206
+ u_gauss_newton
206
207
u_cauchy
207
208
fu_new
208
209
make_new_J:: Bool
@@ -229,6 +230,7 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg::TrustRegion,
229
230
linsolve_kwargs)
230
231
u_tmp = zero (u)
231
232
u_cauchy = zero (u)
233
+ u_gauss_newton = zero (u)
232
234
233
235
loss_new = loss
234
236
H = zero (J)
@@ -265,7 +267,6 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg::TrustRegion,
265
267
expand_factor = convert (trustType, alg. expand_factor)
266
268
267
269
# Parameters for the Schemes
268
- floatType = typeof (r)
269
270
p1 = convert (floatType, 0.0 )
270
271
p2 = convert (floatType, 0.0 )
271
272
p3 = convert (floatType, 0.0 )
@@ -321,28 +322,30 @@ function SciMLBase.__init(prob::NonlinearProblem{uType, iip}, alg::TrustRegion,
321
322
jac_cache, false , maxiters, internalnorm, ReturnCode. Default, abstol, prob,
322
323
radius_update_scheme, initial_trust_radius, max_trust_radius, step_threshold,
323
324
shrink_threshold, expand_threshold, shrink_factor, expand_factor, loss, loss_new,
324
- H, g, shrink_counter, du, u_tmp, u_cauchy, fu_new, make_new_J, r, p1, p2, p3, p4, ϵ,
325
+ H, g, shrink_counter, du, u_tmp, u_gauss_newton, u_cauchy, fu_new, make_new_J, r, p1, p2, p3, p4, ϵ,
325
326
NLStats (1 , 0 , 0 , 0 , 0 ))
326
327
end
327
328
328
329
isinplace (:: TrustRegionCache{iip} ) where {iip} = iip
329
330
330
331
function perform_step! (cache:: TrustRegionCache{true} )
331
- @unpack make_new_J, J, fu, f, u, p, u_tmp , alg, linsolve = cache
332
+ @unpack make_new_J, J, fu, f, u, p, u_gauss_newton , alg, linsolve = cache
332
333
if cache. make_new_J
333
334
jacobian!! (J, cache)
334
335
mul! (cache. H, J' , J)
335
336
mul! (cache. g, J' , fu)
336
337
cache. stats. njacs += 1
337
- end
338
338
339
- # do not use A = cache.H, b = _vec(cache.g) since it is equivalent
340
- # to A = cache.J, b = _vec(fu) as long as the Jacobian is non-singular
341
- linres = dolinsolve (alg. precs, linsolve, A = J, b = _vec (fu),
342
- linu = _vec (u_tmp ),
339
+ # do not use A = cache.H, b = _vec(cache.g) since it is equivalent
340
+ # to A = cache.J, b = _vec(fu) as long as the Jacobian is non-singular
341
+ linres = dolinsolve (alg. precs, linsolve, A = J, b = _vec (fu),
342
+ linu = _vec (u_gauss_newton ),
343
343
p = p, reltol = cache. abstol)
344
- cache. linsolve = linres. cache
345
- cache. u_tmp .= - 1 .* u_tmp
344
+ cache. linsolve = linres. cache
345
+ @. cache. u_gauss_newton = - 1 * u_gauss_newton
346
+ end
347
+
348
+ # Compute dogleg step
346
349
dogleg! (cache)
347
350
348
351
# Compute the potentially new u
@@ -363,11 +366,10 @@ function perform_step!(cache::TrustRegionCache{false})
363
366
cache. H = J' * J
364
367
cache. g = J' * fu
365
368
cache. stats. njacs += 1
369
+ cache. u_gauss_newton = - 1 .* (cache. H \ cache. g)
366
370
end
367
371
368
- @unpack g, H = cache
369
372
# Compute the Newton step.
370
- cache. u_tmp = - 1 .* (H \ g)
371
373
dogleg! (cache)
372
374
373
375
# Compute the potentially new u
@@ -566,25 +568,26 @@ function trust_region_step!(cache::TrustRegionCache)
566
568
end
567
569
568
570
function dogleg! (cache:: TrustRegionCache{true} )
569
- @unpack u_tmp, u_cauchy, trust_r = cache
571
+ @unpack u_tmp, u_gauss_newton, u_cauchy, trust_r = cache
570
572
571
573
# Take the full Gauss-Newton step if lies within the trust region.
572
- if norm (u_tmp ) ≤ trust_r
573
- cache. du .= u_tmp
574
+ if norm (u_gauss_newton ) ≤ trust_r
575
+ cache. du .= u_gauss_newton
574
576
return
575
577
end
576
578
577
579
# Take intersection of steepest descent direction and trust region if Cauchy point lies outside of trust region
578
580
l_grad = norm (cache. g) # length of the gradient
579
581
d_cauchy = l_grad^ 3 / dot (cache. g, cache. H, cache. g) # distance of the cauchy point from the current iterate
580
- if d_cauchy > trust_r
582
+ if d_cauchy >= trust_r
581
583
@. cache. du = - (trust_r/ l_grad) * cache. g # step to the end of the trust region
582
584
return
583
585
end
584
-
586
+
585
587
# Take the intersection of dogled with trust region if Cauchy point lies inside the trust region
586
588
@. u_cauchy = - (d_cauchy/ l_grad) * cache. g # compute Cauchy point
587
- @. u_tmp -= u_cauchy # calf of the dogleg -- use u_tmp to avoid allocation
589
+ @. u_tmp = u_gauss_newton - u_cauchy # calf of the dogleg -- use u_tmp to avoid allocation
590
+
588
591
a = dot (u_tmp, u_tmp)
589
592
b = 2 * dot (u_cauchy, u_tmp)
590
593
c = d_cauchy^ 2 - trust_r^ 2
@@ -596,11 +599,11 @@ end
596
599
597
600
598
601
function dogleg! (cache:: TrustRegionCache{false} )
599
- @unpack u_tmp, u_cauchy, trust_r = cache
602
+ @unpack u_tmp, u_gauss_newton, u_cauchy, trust_r = cache
600
603
601
604
# Take the full Gauss-Newton step if lies within the trust region.
602
- if norm (u_tmp ) ≤ trust_r
603
- cache. du = deepcopy (u_tmp )
605
+ if norm (u_gauss_newton ) ≤ trust_r
606
+ cache. du = deepcopy (u_gauss_newton )
604
607
return
605
608
end
606
609
@@ -614,7 +617,7 @@ function dogleg!(cache::TrustRegionCache{false})
614
617
615
618
# Take the intersection of dogled with trust region if Cauchy point lies inside the trust region
616
619
u_cauchy = - (d_cauchy/ l_grad) * cache. g # compute Cauchy point
617
- u_tmp -= u_cauchy # calf of the dogleg -- use u_tmp to avoid allocation
620
+ u_tmp = u_gauss_newton - u_cauchy # calf of the dogleg
618
621
a = dot (u_tmp, u_tmp)
619
622
b = 2 * dot (u_cauchy, u_tmp)
620
623
c = d_cauchy^ 2 - trust_r^ 2
0 commit comments