Skip to content

Commit 735edb9

Browse files
SebastianM-Cclaude
andcommitted
Add support for NLPModels.jtprod!, NLPModels.jprod! & LBFGS options
Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 42cd5fd commit 735edb9

File tree

1 file changed

+40
-1
lines changed

1 file changed

+40
-1
lines changed

lib/OptimizationMadNLP/src/OptimizationMadNLP.jl

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,22 @@ function NLPModels.hess_coord!(
193193
return H
194194
end
195195

196+
function NLPModels.jtprod!(nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jtv::AbstractVector)
197+
# Compute J^T * v using the AD-provided VJP (Vector-Jacobian Product)
198+
if !isnothing(nlp.cache.f.cons_vjp) && !isempty(Jtv)
199+
nlp.cache.f.cons_vjp(Jtv, x, v)
200+
end
201+
return Jtv
202+
end
203+
204+
function NLPModels.jprod!(nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jv::AbstractVector)
205+
# Compute J * v using the AD-provided JVP (Jacobian-Vector Product)
206+
if !isnothing(nlp.cache.f.cons_jvp) && !isempty(Jv)
207+
nlp.cache.f.cons_jvp(Jv, x, v)
208+
end
209+
return Jv
210+
end
211+
196212
@kwdef struct MadNLPOptimizer{T}
197213
# General options
198214
rethrow_error::Bool = true
@@ -215,6 +231,13 @@ end
215231
# Barrier
216232
mu_init::T = 1e-1
217233

234+
# Quasi-Newton options (used when hessian_approximation is CompactLBFGS, BFGS, or DampedBFGS)
235+
max_history::Int = 6 # Number of past gradients to store for L-BFGS
236+
init_strategy::MadNLP.BFGSInitStrategy = MadNLP.SCALAR1 # How to initialize Hessian
237+
init_value::T = 1.0 # Initial scaling value
238+
sigma_min::T = 1e-8 # Minimum allowed σ (safeguard)
239+
sigma_max::T = 1e+8 # Maximum allowed σ (safeguard)
240+
218241
# Additional MadNLP options
219242
additional_options::Dict{Symbol, Any} = Dict{Symbol, Any}()
220243
end
@@ -225,7 +248,7 @@ function SciMLBase.requiresgradient(opt::MadNLPOptimizer)
225248
true
226249
end
227250
function SciMLBase.requireshessian(opt::MadNLPOptimizer)
228-
true
251+
opt.hessian_approximation === MadNLP.ExactHessian
229252
end
230253
function SciMLBase.allowsbounds(opt::MadNLPOptimizer)
231254
true
@@ -237,6 +260,12 @@ function SciMLBase.requiresconsjac(opt::MadNLPOptimizer)
237260
true
238261
end
239262
function SciMLBase.requireslagh(opt::MadNLPOptimizer)
263+
opt.hessian_approximation === MadNLP.ExactHessian
264+
end
265+
function SciMLBase.allowsconsvjp(opt::MadNLPOptimizer)
266+
true
267+
end
268+
function SciMLBase.allowsconsjvp(opt::MadNLPOptimizer)
240269
true
241270
end
242271

@@ -351,6 +380,15 @@ function __map_optimizer_args(cache,
351380
max_iter = isnothing(maxiters) ? 3000 : maxiters
352381
max_wall_time = isnothing(maxtime) ? 1e6 : maxtime
353382

383+
# Create QuasiNewtonOptions if using quasi-Newton methods
384+
quasi_newton_options = MadNLP.QuasiNewtonOptions{T}(;
385+
opt.init_strategy,
386+
opt.max_history,
387+
opt.init_value,
388+
opt.sigma_min,
389+
opt.sigma_max
390+
)
391+
354392
MadNLP.MadNLPSolver(nlp;
355393
opt.additional_options...,
356394
print_level, tol, max_iter, max_wall_time,
@@ -365,6 +403,7 @@ function __map_optimizer_args(cache,
365403
opt.hessian_constant,
366404
opt.hessian_approximation,
367405
opt.mu_init,
406+
quasi_newton_options = quasi_newton_options,
368407
)
369408
end
370409

0 commit comments

Comments
 (0)