Skip to content

Commit 9a0f0c4

Browse files
MaxenceGollierdpo
authored andcommitted
implicit jacobian update
1 parent ef0a2d0 commit 9a0f0c4

File tree

2 files changed

+11
-18
lines changed

2 files changed

+11
-18
lines changed

src/LMModel.jl

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ where `J` is the Jacobian of `F` at `xk`, represented via matrix-free operations
1616
1717
`σ > 0` is a regularization parameter and `v` is a vector of the same size as `F(xk)` used for intermediary computations.
1818
"""
19-
mutable struct LMModel{T <: Real, V <: AbstractVector{T}, J <: Function, Jt <: Function} <:
19+
mutable struct LMModel{T <: Real, V <: AbstractVector{T}, Jac <: Union{AbstractMatrix, AbstractLinearOperator}} <:
2020
AbstractNLPModel{T, V}
21-
j_prod!::J
22-
jt_prod!::Jt
21+
J::Jac
2322
F::V
2423
v::V
2524
xk::V
@@ -28,19 +27,19 @@ mutable struct LMModel{T <: Real, V <: AbstractVector{T}, J <: Function, Jt <: F
2827
counters::Counters
2928
end
3029

31-
function LMModel(j_prod!::J, jt_prod!::Jt, F::V, σ::T, xk::V) where {T, V, J, Jt}
30+
function LMModel(J::Jac, F::V, σ::T, xk::V) where {T, V, Jac}
3231
meta = NLPModelMeta(
3332
length(xk),
3433
x0 = xk, # Perhaps we should add lvar and uvar as well here.
3534
)
3635
v = similar(F)
37-
return LMModel(j_prod!, jt_prod!, F, v, xk, σ, meta, Counters())
36+
return LMModel(J, F, v, xk, σ, meta, Counters())
3837
end
3938

4039
function NLPModels.obj(nlp::LMModel, x::AbstractVector{T}) where {T}
4140
@lencheck nlp.meta.nvar x
4241
increment!(nlp, :neval_obj)
43-
nlp.j_prod!(nlp.xk, x, nlp.v) # v = J(xk)x
42+
mul!(nlp.v, nlp.J, x)
4443
nlp.v .+= nlp.F
4544
return (dot(nlp.v, nlp.v) + nlp.σ * dot(x, x)) / 2
4645
end
@@ -49,9 +48,9 @@ function NLPModels.grad!(nlp::LMModel, x::AbstractVector{T}, g::AbstractVector{T
4948
@lencheck nlp.meta.nvar x
5049
@lencheck nlp.meta.nvar g
5150
increment!(nlp, :neval_grad)
52-
nlp.j_prod!(nlp.xk, x, nlp.v) # v = J(xk)x + F
51+
mul!(nlp.v, nlp.J, x)
5352
nlp.v .+= nlp.F
54-
nlp.jt_prod!(nlp.xk, nlp.v, g) # g = J^T(xk) v
53+
mul!(g, nlp.J', nlp.v)
5554
@. g += nlp.σ .* x
5655
return g
5756
end

src/LM_alg.jl

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,8 @@ function LMSolver(reg_nls::AbstractRegularizedNLPModel{T, V}; subsolver = R2Solv
6161
has_bnds ? shifted(reg_nls.h, xk, l_bound_m_x, u_bound_m_x, reg_nls.selected) :
6262
shifted(reg_nls.h, xk)
6363

64-
jprod! = let nls = reg_nls.model
65-
(x, v, Jv) -> jprod_residual!(nls, x, v, Jv)
66-
end
67-
jt_prod! = let nls = reg_nls.model
68-
(x, v, Jtv) -> jtprod_residual!(nls, x, v, Jtv)
69-
end
70-
71-
sub_nlp = LMModel(jprod!, jt_prod!, Fk, T(1), xk)
64+
Jk = jac_op_residual(reg_nls.model, xk)
65+
sub_nlp = LMModel(Jk, Fk, T(1), xk)
7266
subpb = RegularizedNLPModel(sub_nlp, ψ)
7367
substats = RegularizedExecutionStats(subpb)
7468
subsolver = subsolver(subpb)
@@ -283,7 +277,7 @@ function SolverCore.solve!(
283277
jtprod_residual!(nls, xk, Fk, ∇fk)
284278
fk = dot(Fk, Fk) / 2
285279

286-
σmax, found_σ = opnorm(jac_op_residual!(nls, xk, Jv, Jtv))
280+
σmax, found_σ = opnorm(solver.subpb.model.J)
287281
found_σ || error("operator norm computation failed")
288282
ν = θ / (σmax^2 + σk) # ‖J'J + σₖ I‖ = ‖J‖² + σₖ
289283
sqrt_ξ1_νInv = one(T)
@@ -407,7 +401,7 @@ function SolverCore.solve!(
407401

408402
# update opnorm if not linear least squares
409403
if nonlinear == true
410-
σmax, found_σ = opnorm(jac_op_residual!(nls, xk, Jv, Jtv))
404+
σmax, found_σ = opnorm(solver.subpb.model.J)
411405
found_σ || error("operator norm computation failed")
412406
end
413407
end

0 commit comments

Comments
 (0)