Skip to content

Commit 9fd21df

Browse files
SebastianM-Cclaude
andcommitted
cleanup OptimizationMadNLP interface
expose linear_solver & kkt_system pass barrier options via MadNLP structs pass quasi_newton_options via MadNLP structs Co-authored-by: Claude <[email protected]>
1 parent becf556 commit 9fd21df

File tree

3 files changed

+112
-90
lines changed

3 files changed

+112
-90
lines changed

lib/OptimizationMadNLP/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name = "OptimizationMadNLP"
22
uuid = "5d9c809f-c847-4062-9fba-1793bbfef577"
3-
version = "1.0.0"
3+
version = "1.1.0"
44
authors = ["Sebastian Micluța-Câmpeanu <[email protected]> and contributors"]
55

66
[deps]

lib/OptimizationMadNLP/src/OptimizationMadNLP.jl

Lines changed: 60 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,8 @@ function NLPModels.hess_coord!(
169169

170170
if !isnothing(nlp.cache.f.cons_h) && !isempty(y)
171171
# Add weighted constraint Hessians
172-
cons_hessians = [similar(nlp.hess_buffer, eltype(nlp.hess_buffer)) for _ in 1:length(y)]
172+
cons_hessians = [similar(nlp.hess_buffer, eltype(nlp.hess_buffer))
173+
for _ in 1:length(y)]
173174
nlp.cache.f.cons_h(cons_hessians, x)
174175
for (λ, H_cons) in zip(y, cons_hessians)
175176
nlp.hess_buffer .+= λ .* H_cons
@@ -193,15 +194,17 @@ function NLPModels.hess_coord!(
193194
return H
194195
end
195196

196-
function NLPModels.jtprod!(nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jtv::AbstractVector)
197+
function NLPModels.jtprod!(
198+
nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jtv::AbstractVector)
197199
# Compute J^T * v using the AD-provided VJP (Vector-Jacobian Product)
198200
if !isnothing(nlp.cache.f.cons_vjp) && !isempty(Jtv)
199201
nlp.cache.f.cons_vjp(Jtv, x, v)
200202
end
201203
return Jtv
202204
end
203205

204-
function NLPModels.jprod!(nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jv::AbstractVector)
206+
function NLPModels.jprod!(
207+
nlp::NLPModelsAdaptor, x::AbstractVector, v::AbstractVector, Jv::AbstractVector)
205208
# Compute J * v using the AD-provided JVP (Jacobian-Vector Product)
206209
if !isnothing(nlp.cache.f.cons_jvp) && !isempty(Jv)
207210
nlp.cache.f.cons_jvp(Jv, x, v)
@@ -228,15 +231,16 @@ end
228231
hessian_constant::Bool = false
229232
hessian_approximation::Type = MadNLP.ExactHessian
230233

231-
# Barrier
232-
mu_init::T = 1e-1
234+
# Linear solver configuration
235+
linear_solver::Union{Nothing, Type} = nothing # e.g., MumpsSolver, LapackCPUSolver, UmfpackSolver
236+
237+
kkt_system::Union{Nothing, Type} = nothing # e.g. DenseKKTSystem
238+
239+
# Barrier method (defaults to MonotoneUpdate)
240+
barrier::Union{Nothing, MadNLP.AbstractBarrierUpdate} = nothing
233241

234242
# 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)
243+
quasi_newton_options::Union{Nothing, MadNLP.QuasiNewtonOptions} = nothing
240244

241245
# Additional MadNLP options
242246
additional_options::Dict{Symbol, Any} = Dict{Symbol, Any}()
@@ -362,8 +366,6 @@ function __map_optimizer_args(cache,
362366
minimize = cache.sense !== MaxSense # Default to minimization when sense is nothing or MinSense
363367
)
364368

365-
nlp = NLPModelsAdaptor(cache, meta, NLPModels.Counters())
366-
367369
if verbose isa Bool
368370
print_level = verbose ? MadNLP.INFO : MadNLP.WARN
369371
else
@@ -375,38 +377,57 @@ function __map_optimizer_args(cache,
375377
max_iter = isnothing(maxiters) ? 3000 : maxiters
376378
max_wall_time = isnothing(maxtime) ? 1e6 : maxtime
377379

378-
# Create QuasiNewtonOptions if using quasi-Newton methods
379-
quasi_newton_options = MadNLP.QuasiNewtonOptions{T}(;
380-
opt.init_strategy,
381-
opt.max_history,
382-
opt.init_value,
383-
opt.sigma_min,
384-
opt.sigma_max
385-
)
380+
# Build final options dictionary
381+
options = Dict{Symbol, Any}(opt.additional_options)
386382

387-
MadNLP.MadNLPSolver(nlp;
388-
opt.additional_options...,
389-
print_level, tol, max_iter, max_wall_time,
390-
opt.rethrow_error,
391-
opt.disable_garbage_collector,
392-
opt.blas_num_threads,
393-
opt.output_file,
394-
opt.file_print_level,
395-
opt.acceptable_tol,
396-
opt.acceptable_iter,
397-
opt.jacobian_constant,
398-
opt.hessian_constant,
399-
opt.hessian_approximation,
400-
opt.mu_init,
401-
quasi_newton_options = quasi_newton_options,
402-
)
383+
# Add barrier if provided, otherwise create default
384+
if !isnothing(opt.barrier)
385+
options[:barrier] = opt.barrier
386+
else
387+
# Create default barrier (MonotoneUpdate with default mu_init)
388+
options[:barrier] = MadNLP.MonotoneUpdate{T}()
389+
end
390+
391+
# Add quasi_newton_options if provided, otherwise create default
392+
if !isnothing(opt.quasi_newton_options)
393+
options[:quasi_newton_options] = opt.quasi_newton_options
394+
else
395+
# Create default quasi-Newton options
396+
options[:quasi_newton_options] = MadNLP.QuasiNewtonOptions{T}()
397+
end
398+
399+
# Add linear_solver if provided
400+
if !isnothing(opt.linear_solver)
401+
options[:linear_solver] = opt.linear_solver
402+
end
403+
404+
if !isnothing(opt.kkt_system)
405+
options[:kkt_system] = opt.kkt_system
406+
end
407+
408+
options[:rethrow_error] = opt.rethrow_error
409+
options[:disable_garbage_collector] = opt.disable_garbage_collector
410+
options[:blas_num_threads] = opt.blas_num_threads
411+
options[:output_file] = opt.output_file
412+
options[:file_print_level] = opt.file_print_level
413+
options[:acceptable_tol] = opt.acceptable_tol
414+
options[:acceptable_iter] = opt.acceptable_iter
415+
options[:jacobian_constant] = opt.jacobian_constant
416+
options[:hessian_constant] = opt.hessian_constant
417+
options[:hessian_approximation] = opt.hessian_approximation
418+
options[:print_level] = print_level
419+
options[:tol] = tol
420+
options[:max_iter] = max_iter
421+
options[:max_wall_time] = max_wall_time
422+
423+
meta, options
403424
end
404425

405426
function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: MadNLPOptimizer}
406427
maxiters = OptimizationBase._check_and_convert_maxiters(cache.solver_args.maxiters)
407428
maxtime = OptimizationBase._check_and_convert_maxtime(cache.solver_args.maxtime)
408429

409-
solver = __map_optimizer_args(cache,
430+
meta, options = __map_optimizer_args(cache,
410431
cache.opt;
411432
abstol = cache.solver_args.abstol,
412433
reltol = cache.solver_args.reltol,
@@ -417,6 +438,8 @@ function SciMLBase.__solve(cache::OptimizationCache{O}) where {O <: MadNLPOptimi
417438
callback = cache.callback
418439
)
419440

441+
nlp = NLPModelsAdaptor(cache, meta, NLPModels.Counters())
442+
solver = MadNLP.MadNLPSolver(nlp; options...)
420443
results = MadNLP.solve!(solver)
421444

422445
stats = OptimizationBase.OptimizationStats(; time = results.counters.total_time,

0 commit comments

Comments
 (0)