Skip to content

Commit 31afbe0

Browse files
committed
Store the label of the constraints
1 parent ab61a3c commit 31afbe0

File tree

4 files changed

+86
-16
lines changed

4 files changed

+86
-16
lines changed

src/MOI_wrapper.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
9292
"No solver specified, use for instance `using Percival; JuMP.set_attribute(model, \"solver\", PercivalSolver)`",
9393
)
9494
end
95-
dest.nlp, index_map = nlp_model(src)
95+
dest.nlp = nlp_model(src)
9696
dest.solver = dest.options["solver"](dest.nlp)
97-
return index_map
97+
return dest
9898
end
9999

100100
function MOI.optimize!(model::Optimizer)

src/moi_nlp_model.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mutable struct MathOptNLPModel <: AbstractNLPModel{Float64, Vector{Float64}}
44
meta::NLPModelMeta{Float64, Vector{Float64}}
55
eval::MOI.Nonlinear.Evaluator
66
jump_variables::Dict{String,Int}
7+
jump_constraints::Dict{String,Int}
78
lincon::LinearConstraints
89
quadcon::QuadraticConstraints
910
nlcon::NonLinearStructure
@@ -32,9 +33,9 @@ end
3233

3334
function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String = "Generic")
3435
jump_variables, variables, nvar, lvar, uvar, x0 = parser_variables(moimodel)
35-
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon = parser_MOI(moimodel, variables)
36+
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon, jump_constraints_linear, jump_constraints_quadratic, valid_label = parser_MOI(moimodel, variables)
3637

37-
nlp_data = _nlp_block(moimodel)
38+
nlp_data, valid_label2, jump_constraints_nonlinear = _nlp_block(moimodel)
3839
nlcon = parser_NL(nlp_data, hessian = hessian)
3940
oracles = parser_oracles(moimodel)
4041
counters = Counters()
@@ -74,10 +75,26 @@ function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String =
7475
hess_available = hessian && oracles.hessian_oracles_supported,
7576
)
7677

78+
# Label of the constraints
79+
jump_constraints = Dict{String, Int}()
80+
if valid_label && valid_label2 && (oracles.ncon == 0)
81+
sizehint!(jump_constraints, ncon)
82+
for (key, val) in jump_constraints_linear
83+
jump_constraints[key] = val
84+
end
85+
for (key, val) in jump_constraints_quadratic
86+
jump_constraints[key] = val + nlin
87+
end
88+
for (key, val) in jump_constraints_nonlinear
89+
jump_constraints[key] = val + nlin + quadcon.nquad
90+
end
91+
end
92+
7793
return MathOptNLPModel(
7894
meta,
7995
nlp_data.evaluator,
8096
jump_variables,
97+
jump_constraints,
8198
lincon,
8299
quadcon,
83100
nlcon,

src/moi_nls_model.jl

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ mutable struct MathOptNLSModel <: AbstractNLSModel{Float64, Vector{Float64}}
66
Feval::MOI.Nonlinear.Evaluator
77
ceval::MOI.Nonlinear.Evaluator
88
jump_variables::Dict{String,Int}
9+
jump_constraints::Dict{String,Int}
910
lls::Objective
1011
linequ::LinearEquations
1112
nlequ::NonLinearStructure
@@ -34,9 +35,9 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
3435

3536
_nlp_sync!(cmodel)
3637
moimodel = backend(cmodel)
37-
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon = parser_MOI(moimodel, variables)
38+
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon, jump_constraints_linear, jump_constraints_quadratic, valid_label = parser_MOI(moimodel, variables)
3839

39-
nlp_data = _nlp_block(moimodel)
40+
nlp_data, valid_label2, jump_constraints_nonlinear = _nlp_block(moimodel)
4041
nlcon = parser_NL(nlp_data, hessian = hessian)
4142
oracles = parser_oracles(moimodel)
4243
nls_counters = NLSCounters()
@@ -75,12 +76,28 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
7576

7677
nls_meta = NLSMeta(nequ, nvar, nnzj = Fnnzj, nnzh = Fnnzh, lin = collect(1:nlinequ))
7778

79+
# Label of the constraints
80+
jump_constraints = Dict{String, Int}()
81+
if valid_label && valid_label2 && (oracles.ncon == 0)
82+
sizehint!(jump_constraints, ncon)
83+
for (key, val) in jump_constraints_linear
84+
jump_constraints[key] = val
85+
end
86+
for (key, val) in jump_constraints_quadratic
87+
jump_constraints[key] = val + nlin
88+
end
89+
for (key, val) in jump_constraints_nonlinear
90+
jump_constraints[key] = val + nlin + quadcon.nquad
91+
end
92+
end
93+
7894
return MathOptNLSModel(
7995
meta,
8096
nls_meta,
8197
Feval,
8298
nlp_data.evaluator,
8399
jump_variables,
100+
jump_constraints,
84101
lls,
85102
linequ,
86103
nlequ,

src/utils.jl

Lines changed: 46 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,11 @@ function parser_MOI(moimodel, variables)
452452
# Number of variables
453453
nvar = length(variables)
454454

455+
# Ensure that each constraint has a valid label
456+
valid_label = true
457+
jump_constraints_linear = Dict{String, Int}()
458+
jump_constraints_quadratic = Dict{String, Int}()
459+
455460
# Variables associated to linear constraints
456461
nlin = 0
457462
linrows = Int[]
@@ -481,23 +486,36 @@ function parser_MOI(moimodel, variables)
481486
(F == VI) && continue
482487
conindices = MOI.get(moimodel, MOI.ListOfConstraintIndices{F, S}())
483488
for cidx in conindices
489+
cname = MOI.get(moimodel, MOI.ConstraintName(), cidx)
484490
fun = MOI.get(moimodel, MOI.ConstraintFunction(), cidx)
485491
set = MOI.get(moimodel, MOI.ConstraintSet(), cidx)
486492
if typeof(fun) <: SAF
487493
parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
488494
nlin += 1
495+
if valid_label && (cname != "")
496+
jump_constraints_linear[cname] = nlin
497+
else
498+
valid_label = false
499+
end
489500
end
490501
if typeof(fun) <: VAF
491502
parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
492503
nlin += set.dimension
504+
valid_label = false
493505
end
494506
if typeof(fun) <: SQF
495507
parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
496508
nquad += 1
509+
if valid_label && (cname != "")
510+
jump_constraints_quadratic[cname] = nquad
511+
else
512+
valid_label = false
513+
end
497514
end
498515
if typeof(fun) <: VQF
499516
parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
500517
nquad += set.dimension
518+
valid_label = false
501519
end
502520
end
503521
end
@@ -512,28 +530,43 @@ function parser_MOI(moimodel, variables)
512530
end
513531
quadcon = QuadraticConstraints(nquad, qcons, quad_nnzj, quad_nnzh)
514532

515-
return nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon
533+
return nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon, jump_constraints_linear, jump_constraints_quadratic, valid_label
516534
end
517535

518536
# Affine or quadratic, nothing to do
519-
_nlp_model(::MOI.Nonlinear.Model, ::MOI.ModelLike, ::Type, ::Type) = false
537+
function _nlp_model(::MOI.Nonlinear.Model, ::MOI.ModelLike, ::Dict{String, Int}, ::Type, ::Type)
538+
has_nonlinear = false
539+
valid_label = true
540+
return has_nonlinear, valid_label
541+
end
520542

521-
function _nlp_model(dest::MOI.Nonlinear.Model, src::MOI.ModelLike, F::Type{SNF}, S::Type)
543+
function _nlp_model(dest::MOI.Nonlinear.Model, src::MOI.ModelLike, jump_constraints_nonlinear::Dict{String, Int}, F::Type{SNF}, S::Type)
522544
has_nonlinear = false
545+
valid_label = true
546+
ncon = 0
523547
for ci in MOI.get(src, MOI.ListOfConstraintIndices{F, S}())
548+
cname = MOI.get(src, MOI.ConstraintName(), ci)
549+
ncon += 1
550+
if valid_label && (cname != "")
551+
jump_constraints_nonlinear[cname] = ncon
552+
else
553+
valid_label = false
554+
end
524555
MOI.Nonlinear.add_constraint(
525556
dest,
526557
MOI.get(src, MOI.ConstraintFunction(), ci),
527558
MOI.get(src, MOI.ConstraintSet(), ci),
528559
)
529560
has_nonlinear = true
530561
end
531-
return has_nonlinear
562+
return has_nonlinear, valid_label
532563
end
533564

534-
function _nlp_model(model::MOI.ModelLike)::Union{Nothing, MOI.Nonlinear.Model}
565+
function _nlp_model(model::MOI.ModelLike)
535566
nlp_model = MOI.Nonlinear.Model()
536567
has_nonlinear = false
568+
valid_label = true
569+
jump_constraints_nonlinear = Dict{String, Int}()
537570
for attr in MOI.get(model, MOI.ListOfModelAttributesSet())
538571
if attr isa MOI.UserDefinedFunction
539572
has_nonlinear = true
@@ -542,24 +575,26 @@ function _nlp_model(model::MOI.ModelLike)::Union{Nothing, MOI.Nonlinear.Model}
542575
end
543576
end
544577
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
545-
has_nonlinear |= _nlp_model(nlp_model, model, F, S)
578+
has_nonlinear_constraint, valid_label_constraint = _nlp_model(nlp_model, model, jump_constraints_nonlinear, F, S)
579+
has_nonlinear |= has_nonlinear_constraint
580+
valid_label = valid_label && valid_label_constraint
546581
end
547582
F = MOI.get(model, MOI.ObjectiveFunctionType())
548583
if F <: SNF
549584
MOI.Nonlinear.set_objective(nlp_model, MOI.get(model, MOI.ObjectiveFunction{F}()))
550585
has_nonlinear = true
551586
end
552587
if !has_nonlinear
553-
return nothing
588+
return nothing, valid_label, jump_constraints_nonlinear
554589
end
555-
return nlp_model
590+
return nlp_model, valid_label, jump_constraints_nonlinear
556591
end
557592

558593
function _nlp_block(model::MOI.ModelLike)
559594
# Old interface with `@NL...`
560595
nlp_data = MOI.get(model, MOI.NLPBlock())
561596
# New interface with `@constraint` and `@objective`
562-
nlp_model = _nlp_model(model)
597+
nlp_model, valid_label, jump_constraints_nonlinear = _nlp_model(model)
563598
vars = MOI.get(model, MOI.ListOfVariableIndices())
564599
if isnothing(nlp_data)
565600
if isnothing(nlp_model)
@@ -572,6 +607,7 @@ function _nlp_block(model::MOI.ModelLike)
572607
nlp_data = MOI.NLPBlockData(evaluator)
573608
end
574609
else
610+
valid_label = false
575611
if !isnothing(nlp_model)
576612
error(
577613
"Cannot optimize a model which contains the features from " *
@@ -581,7 +617,7 @@ function _nlp_block(model::MOI.ModelLike)
581617
)
582618
end
583619
end
584-
return nlp_data
620+
return nlp_data, valid_label, jump_constraints_nonlinear
585621
end
586622

587623
"""

0 commit comments

Comments
 (0)