Skip to content

Commit 02b6cce

Browse files
make LMModel type stable
1 parent 3ffc73b commit 02b6cce

1 file changed

Lines changed: 19 additions & 17 deletions

File tree

src/LMModel.jl

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
export LMModel
22

33
@doc raw"""
4-
LMModel(J, F, v, σ, x0)
4+
LMModel(j_prod!, jt_prod, F, v, σ, xk)
55
66
Given the unconstrained optimization problem:
77
```math
@@ -11,45 +11,47 @@ this model represents the smooth LM subproblem:
1111
```math
1212
\min_s \ \tfrac{1}{2} \| F(x) + J(x)s \|^2 + \tfrac{1}{2} σ \|s\|^2
1313
```
14-
where `J` is the Jacobian of `F` at `x0` in sparse format or as a linear operator.
15-
`σ > 0` is a regularization parameter and `v` is a vector of the same size as `F(x0)` used for intermediary computations.
14+
where `J` is the Jacobian of `F` at `xk`, represented via matrix-free operations.
15+
`j_prod!(xk, s, out)` computes `J(xk) * s`, and `jt_prod!(xk, r, out)` computes `J(xk)' * r`.
16+
17+
`σ > 0` is a regularization parameter and `v` is a vector of the same size as `F(xk)` used for intermediary computations.
1618
"""
17-
mutable struct LMModel{T <: Real, V <: AbstractVector{T}, G <: Union{AbstractMatrix{T}, AbstractLinearOperator{T}}} <:
19+
mutable struct LMModel{T <: Real, V <: AbstractVector{T}, J <: Function , Jt <: Function} <:
1820
AbstractNLPModel{T, V}
19-
J::G
21+
j_prod!::J
22+
jt_prod!::Jt
2023
F::V
2124
v::V
25+
xk::V
2226
σ::T
2327
meta::NLPModelMeta{T, V}
2428
counters::Counters
2529
end
2630

27-
function LMModel(J::G, F::V, σ::T, x0::V) where {T, V, G}
28-
@assert length(x0) == size(J, 2)
29-
@assert length(F) == size(J, 1)
31+
function LMModel(j_prod!::J, jt_prod!::Jt, F::V, σ::T, xk::V) where {T, V, J, Jt}
3032
meta = NLPModelMeta(
31-
length(x0),
32-
x0 = x0, # Perhaps we should add lvar and uvar as well here.
33+
length(xk),
34+
x0 = xk, # Perhaps we should add lvar and uvar as well here.
3335
)
3436
v = similar(F)
35-
return LMModel(J::G, F::V, v::V, σ::T, meta, Counters())
37+
return LMModel(j_prod!, jt_prod!, F, v, xk, σ, meta, Counters())
3638
end
3739

3840
function NLPModels.obj(nlp::LMModel, x::AbstractVector{T}) where{T}
3941
@lencheck nlp.meta.nvar x
4042
increment!(nlp, :neval_obj)
41-
nlp.v .= nlp.F
42-
mul!(nlp.v, nlp.J, x, one(T), one(T))
43+
nlp.j_prod!(nlp.xk, x, nlp.v) # v = J(xk)x
44+
nlp.v .+= nlp.F
4345
return ( dot(nlp.v, nlp.v) + nlp.σ * dot(x, x) ) / 2
4446
end
4547

4648
function NLPModels.grad!(nlp::LMModel, x::AbstractVector{T}, g::AbstractVector{T}) where{T}
4749
@lencheck nlp.meta.nvar x
4850
@lencheck nlp.meta.nvar g
4951
increment!(nlp, :neval_grad)
50-
nlp.v .= nlp.F
51-
@. g = nlp.σ .* x
52-
mul!(nlp.v, nlp.J, x, one(T), one(T))
53-
mul!(g, nlp.J', nlp.v, one(T), one(T))
52+
nlp.j_prod!(nlp.xk, x, nlp.v) # v = J(xk)x + F
53+
nlp.v .+= nlp.F
54+
nlp.jt_prod!(nlp.xk, nlp.v, g) # g = J^T(xk) v
55+
@. g += nlp.σ .* x
5456
return g
5557
end

0 commit comments

Comments
 (0)