-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add DenseKKTSystem structure #65
Conversation
Codecov Report
@@ Coverage Diff @@
## master #65 +/- ##
==========================================
+ Coverage 86.69% 87.33% +0.64%
==========================================
Files 30 30
Lines 3141 3213 +72
==========================================
+ Hits 2723 2806 +83
+ Misses 418 407 -11
Continue to review full report at Codecov.
|
Solve #36 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @frapac what an incredible work! It seems that the AbstractKKTSystem abstraction you built really pays here. It is even quite surprising that dense formulation just works with this small change. I only have a few minor comments. Could you run a benchmark just to make sure that we don't have an unexpected performance regression? I think running the benchmark with --quick option would be enough here.
src/interiorpointsolver.jl
Outdated
@@ -331,13 +332,26 @@ function Solver(nlp::NonlinearProgram; | |||
set_blas_num_threads(opt.blas_num_threads; permanent=true) | |||
|
|||
@trace(logger,"Initializing variables.") | |||
ind_ineq = findall(nlp.gl.!=nlp.gu) | |||
ns = length(ind_ineq) | |||
info_constraints = get_index_constraints(nlp; fixed_variable_treatment=opt.fixed_variable_treatment) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This makes the code way cleaner :) Maybe just rename it consistently as ind_cons?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
src/interiorpointsolver.jl
Outdated
|
||
function set_con_scale!(con_scale::AbstractVector, jac::SparseMatrixCOO, nlp_scaling_max_gradient) | ||
for i in 1:nnz(jac) | ||
row = jac.I[i] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe @inbounds here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, indeed.
ind_fixed::Vector{Int} | ||
jacobian_scaling::VT | ||
end | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤩
|
||
# If the the problem is unconstrained, then KKT system is directly equal | ||
# to the Hessian (+ some regularization terms) | ||
aug_com = if (m == 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
interesting, maybe there are things we can do less (or further) in the NLP formulation as well as the algorithm when it is unconstrained.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed. We may want to use a different line-search in the unconstrained case, too. Maybe that's something we want to investigate in the future.
jac::MT | ||
pr_diag::VT | ||
du_diag::VT | ||
diag_hess::VT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why do we separately need diag_hess, which we don't have in sparse KKT?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In sparse KKT, pr_diag
and du_diag
are defined implicitly in the KKT's COO matrix, by adding artificial duplicate entries to the sparsity pattern. That allows to do the regularization seamlessly.
In dense KKT, things are a bit different, as we cannot store pr_diag
and du_diag
directly in the dense KKT matrix. Each time we update the regularization, we need to update the diagonal terms in the dense KKT matrix, as
for i in 1:n
aug_com[i, i] = hess[i, i] + pr_diag[i]
In case aug_com === hess
, we are adding two time the terms pr_diag
in the second regularization. That's why I thought it would be better to store the diagonal terms of the Hessian matrix once, and then do the regularization as
for i in 1:n
aug_com[i, i] = diag_hess[i] + pr_diag[i]
But there might be a better solution!
@@ -51,7 +50,6 @@ testset = [ | |||
()->MadNLP.Optimizer( | |||
inertia_correction_method=MadNLP.INERTIA_FREE, | |||
kkt_system=MadNLP.SPARSE_UNREDUCED_KKT_SYSTEM, | |||
reduced_system=false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops. Great catch!
I'll add a benchmark for dense problems using the dense problems within CUTEst instances. |
One observation is that the current DenseKKT system assumes a different behavior of NonlinearProgramming functions; in particular, the hessian and jacobian callback functions should behave differently. Maybe it would be good to introduce a new abstract type AbstractNonlinearProgram, and separate SparseNonlinearProgram and DenseNonlinearProgram. And this can be independent of the KKTSystem type, since some dense NLPs are in sparse NLP format and the vice versa is also possible. Could you make those NonlinearProgram subtypes? I can work on MOI/NLPModels interfaces in a separate PR |
You are raising an interesting question about
|
Indeed. Totally agreed. I think one way we can check the availability of sparse (or dense) callback is by checking With regards to closures, I think we should discuss entirely relying on NLPModels and getting rid of |
|
||
struct DenseKKTSystem{T, VT, MT} <: AbstractKKTSystem{T, MT} | ||
hess::MT | ||
jac::MT |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Didn't realize this in my first review, but can't these be views so that we don't need to transfer this in _build_dense_kkt_system
?
* add proper constructor for KKTSystems
748978c
to
fe8ee1f
Compare
AbstractKKTSystem
interfaceAbstractKKTSystem
directly from aNonLinearProgram