Skip to content

Commit ab61a3c

Browse files
committed
Add an attribute jump_variables in the model
1 parent 5abe6b5 commit ab61a3c

File tree

4 files changed

+69
-58
lines changed

4 files changed

+69
-58
lines changed

docs/src/tutorial.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ Let's define the famous Rosenbrock function
2323
```math
2424
f(x) = (x_1 - 1)^2 + 100(x_2 - x_1^2)^2,
2525
```
26-
with starting point ``x^0 = (-1.2,1.0)``.
26+
with starting point ``x_0 = (-1.2, 1.0)``.
2727

2828
```@example jumpnlp
2929
using NLPModels, NLPModelsJuMP, JuMP
3030
3131
x0 = [-1.2; 1.0]
3232
model = Model() # No solver is required
3333
@variable(model, x[i=1:2], start=x0[i])
34-
@NLobjective(model, Min, (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2)
34+
@objective(model, Min, (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2)
3535
3636
nlp = MathOptNLPModel(model)
3737
```
@@ -148,9 +148,9 @@ using NLPModels, NLPModelsJuMP, JuMP
148148
model = Model()
149149
x0 = [-1.2; 1.0]
150150
@variable(model, x[i=1:2] >= 0.0, start=x0[i])
151-
@NLobjective(model, Min, (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2)
151+
@objective(model, Min, (x[1] - 1)^2 + 100 * (x[2] - x[1]^2)^2)
152152
@constraint(model, x[1] + x[2] == 3.0)
153-
@NLconstraint(model, x[1] * x[2] >= 1.0)
153+
@constraint(model, x[1] * x[2] >= 1.0)
154154
155155
nlp = MathOptNLPModel(model)
156156
@@ -184,7 +184,7 @@ using NLPModels, NLPModelsJuMP, JuMP
184184
model = Model()
185185
x0 = [-1.2; 1.0]
186186
@variable(model, x[i=1:2], start=x0[i])
187-
@NLexpression(model, F1, x[1] - 1)
187+
@expression(model, F1, x[1] - 1)
188188
@NLexpression(model, F2, 10 * (x[2] - x[1]^2))
189189
190190
nls = MathOptNLSModel(model, [F1, F2], name="rosen-nls")

src/moi_nlp_model.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ export MathOptNLPModel
33
mutable struct MathOptNLPModel <: AbstractNLPModel{Float64, Vector{Float64}}
44
meta::NLPModelMeta{Float64, Vector{Float64}}
55
eval::MOI.Nonlinear.Evaluator
6+
jump_variables::Dict{String,Int}
67
lincon::LinearConstraints
78
quadcon::QuadraticConstraints
89
nlcon::NonLinearStructure
@@ -26,13 +27,12 @@ function MathOptNLPModel(jmodel::JuMP.Model; kws...)
2627
end
2728

2829
function MathOptNLPModel(moimodel::MOI.ModelLike; kws...)
29-
return nlp_model(moimodel; kws...)[1]
30+
return nlp_model(moimodel; kws...)
3031
end
3132

3233
function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String = "Generic")
33-
index_map, nvar, lvar, uvar, x0 = parser_variables(moimodel)
34-
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon =
35-
parser_MOI(moimodel, index_map, nvar)
34+
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)
3636

3737
nlp_data = _nlp_block(moimodel)
3838
nlcon = parser_NL(nlp_data, hessian = hessian)
@@ -44,7 +44,7 @@ function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String =
4444
if nlp_data.has_objective
4545
obj = Objective("NONLINEAR", 0.0, spzeros(Float64, nvar), COO(), 0)
4646
else
47-
obj = parser_objective_MOI(moimodel, nvar, index_map)
47+
obj = parser_objective_MOI(moimodel, variables)
4848
end
4949

5050
# Total counts
@@ -77,6 +77,7 @@ function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String =
7777
return MathOptNLPModel(
7878
meta,
7979
nlp_data.evaluator,
80+
jump_variables,
8081
lincon,
8182
quadcon,
8283
nlcon,
@@ -85,8 +86,7 @@ function nlp_model(moimodel::MOI.ModelLike; hessian::Bool = true, name::String =
8586
hv,
8687
obj,
8788
counters,
88-
),
89-
index_map
89+
)
9090
end
9191

9292
function NLPModels.obj(nlp::MathOptNLPModel, x::AbstractVector)

src/moi_nls_model.jl

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ mutable struct MathOptNLSModel <: AbstractNLSModel{Float64, Vector{Float64}}
55
nls_meta::NLSMeta{Float64, Vector{Float64}}
66
Feval::MOI.Nonlinear.Evaluator
77
ceval::MOI.Nonlinear.Evaluator
8+
jump_variables::Dict{String,Int}
89
lls::Objective
910
linequ::LinearEquations
1011
nlequ::NonLinearStructure
@@ -26,15 +27,14 @@ Construct a `MathOptNLSModel` from a `JuMP` model and a container of JuMP
2627
"""
2728
function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::String = "Generic")
2829
moimodel = backend(cmodel)
29-
index_map, nvar, lvar, uvar, x0 = parser_variables(moimodel)
30+
jump_variables, variables, nvar, lvar, uvar, x0 = parser_variables(moimodel)
3031

31-
lls, linequ, nlinequ = parser_linear_expression(cmodel, nvar, index_map, F)
32-
Feval, nlequ, nnlnequ = parser_nonlinear_expression(cmodel, nvar, F, hessian = hessian)
32+
lls, linequ, nlinequ = parser_linear_expression(cmodel, variables, F)
33+
Feval, nlequ, nnlnequ = parser_nonlinear_expression(cmodel, variables, F, hessian = hessian)
3334

3435
_nlp_sync!(cmodel)
3536
moimodel = backend(cmodel)
36-
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon =
37-
parser_MOI(moimodel, index_map, nvar)
37+
nlin, lincon, lin_lcon, lin_ucon, quadcon, quad_lcon, quad_ucon = parser_MOI(moimodel, variables)
3838

3939
nlp_data = _nlp_block(moimodel)
4040
nlcon = parser_NL(nlp_data, hessian = hessian)
@@ -80,6 +80,7 @@ function MathOptNLSModel(cmodel::JuMP.Model, F; hessian::Bool = true, name::Stri
8080
nls_meta,
8181
Feval,
8282
nlp_data.evaluator,
83+
jump_variables,
8384
lls,
8485
linequ,
8586
nlequ,

src/utils.jl

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -252,13 +252,13 @@ function coo_sym_dot(
252252
end
253253

254254
"""
255-
parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
255+
parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
256256
257257
Parse a `ScalarAffineFunction` fun with its associated set.
258258
`linrows`, `lincols`, `linvals`, `lin_lcon` and `lin_ucon` are updated.
259259
"""
260-
function parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
261-
_index(v::MOI.VariableIndex) = index_map[v].value
260+
function parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
261+
_index(v::MOI.VariableIndex) = v.value
262262

263263
# Parse a ScalarAffineTerm{Float64}(coefficient, variable)
264264
for term in fun.terms
@@ -285,13 +285,13 @@ function parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_uco
285285
end
286286

287287
"""
288-
parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
288+
parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
289289
290290
Parse a `VectorAffineFunction` fun with its associated set.
291291
`linrows`, `lincols`, `linvals`, `lin_lcon` and `lin_ucon` are updated.
292292
"""
293-
function parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
294-
_index(v::MOI.VariableIndex) = index_map[v].value
293+
function parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
294+
_index(v::MOI.VariableIndex) = v.value
295295

296296
# Parse a VectorAffineTerm{Float64}(output_index, scalar_term)
297297
for term in fun.terms
@@ -314,13 +314,13 @@ function parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_uco
314314
end
315315

316316
"""
317-
parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
317+
parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
318318
319319
Parse a `ScalarQuadraticFunction` fun with its associated set.
320320
`qcons`, `quad_lcon`, `quad_ucon` are updated.
321321
"""
322-
function parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
323-
_index(v::MOI.VariableIndex) = index_map[v].value
322+
function parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
323+
_index(v::MOI.VariableIndex) = v.value
324324

325325
b = spzeros(Float64, nvar)
326326
rows = Int[]
@@ -376,13 +376,13 @@ function parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
376376
end
377377

378378
"""
379-
parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
379+
parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
380380
381381
Parse a `VectorQuadraticFunction` fun with its associated set.
382382
`qcons`, `quad_lcon`, `quad_ucon` are updated.
383383
"""
384-
function parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
385-
_index(v::MOI.VariableIndex) = index_map[v].value
384+
function parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
385+
_index(v::MOI.VariableIndex) = v.value
386386

387387
ncon = length(fun.constants)
388388
for k = 1:ncon
@@ -443,11 +443,14 @@ function parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
443443
end
444444

445445
"""
446-
parser_MOI(moimodel, index_map, nvar)
446+
parser_MOI(moimodel, variables)
447447
448448
Parse linear constraints of a `MOI.ModelLike`.
449449
"""
450-
function parser_MOI(moimodel, index_map, nvar)
450+
function parser_MOI(moimodel, variables)
451+
452+
# Number of variables
453+
nvar = length(variables)
451454

452455
# Variables associated to linear constraints
453456
nlin = 0
@@ -475,30 +478,25 @@ function parser_MOI(moimodel, index_map, nvar)
475478
F <: AF || F <: QF || F == SNF || F == VI || error("Function $F is not supported.")
476479
S <: LS || error("Set $S is not supported.")
477480

481+
(F == VI) && continue
478482
conindices = MOI.get(moimodel, MOI.ListOfConstraintIndices{F, S}())
479483
for cidx in conindices
480484
fun = MOI.get(moimodel, MOI.ConstraintFunction(), cidx)
481-
if F == VI
482-
index_map[cidx] = MOI.ConstraintIndex{F, S}(fun.value)
483-
continue
484-
else
485-
index_map[cidx] = MOI.ConstraintIndex{F, S}(nlin)
486-
end
487485
set = MOI.get(moimodel, MOI.ConstraintSet(), cidx)
488486
if typeof(fun) <: SAF
489-
parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
487+
parser_SAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
490488
nlin += 1
491489
end
492490
if typeof(fun) <: VAF
493-
parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon, index_map)
491+
parser_VAF(fun, set, linrows, lincols, linvals, nlin, lin_lcon, lin_ucon)
494492
nlin += set.dimension
495493
end
496494
if typeof(fun) <: SQF
497-
parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
495+
parser_SQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
498496
nquad += 1
499497
end
500498
if typeof(fun) <: VQF
501-
parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon, index_map)
499+
parser_VQF(fun, set, nvar, qcons, quad_lcon, quad_ucon)
502500
nquad += set.dimension
503501
end
504502
end
@@ -633,7 +631,7 @@ function parser_oracles(moimodel)
633631
MOI.ListOfConstraintIndices{MOI.VectorOfVariables, MOI.VectorNonlinearOracle{Float64}}(),
634632
)
635633
f = MOI.get(moimodel, MOI.ConstraintFunction(), ci) # ::MOI.VectorOfVariables
636-
set = MOI.get(moimodel, MOI.ConstraintSet(), ci) # ::MOI.VectorNonlinearOracle{Float64}
634+
set = MOI.get(moimodel, MOI.ConstraintSet(), ci) # ::MOI.VectorNonlinearOracle{Float64}
637635

638636
cache = _VectorNonlinearOracleCache(set)
639637
push!(oracles, (f, cache))
@@ -668,20 +666,23 @@ Parse variables informations of a `MOI.ModelLike`.
668666
"""
669667
function parser_variables(model::MOI.ModelLike)
670668
# Number of variables and bounds constraints
671-
vars = MOI.get(model, MOI.ListOfVariableIndices())
672-
nvar = length(vars)
669+
variables = MOI.get(model, MOI.ListOfVariableIndices())
670+
nvar = length(variables)
673671
lvar = zeros(nvar)
674672
uvar = zeros(nvar)
673+
675674
# Initial solution
676675
x0 = zeros(nvar)
677676
has_start = MOI.VariablePrimalStart() in MOI.get(model, MOI.ListOfVariableAttributesSet())
678677

679-
index_map = MOI.Utilities.IndexMap()
680-
for (i, vi) in enumerate(vars)
681-
index_map[vi] = MOI.VariableIndex(i)
682-
end
678+
jump_variables = Dict{String,Int}()
679+
sizehint!(jump_variables, nvar)
680+
681+
for vi in variables
682+
i = vi.value
683+
name = MOI.get(model, MOI.VariableName(), vi)
684+
jump_variables[name] = i
683685

684-
for (i, vi) in enumerate(vars)
685686
lvar[i], uvar[i] = MOI.Utilities.get_bounds(model, Float64, vi)
686687
if has_start
687688
val = MOI.get(model, MOI.VariablePrimalStart(), vi)
@@ -691,16 +692,19 @@ function parser_variables(model::MOI.ModelLike)
691692
end
692693
end
693694

694-
return index_map, nvar, lvar, uvar, x0
695+
return jump_variables, variables, nvar, lvar, uvar, x0
695696
end
696697

697698
"""
698-
parser_objective_MOI(moimodel, nvar, index_map)
699+
parser_objective_MOI(moimodel, variables)
699700
700701
Parse linear and quadratic objective of a `MOI.ModelLike`.
701702
"""
702-
function parser_objective_MOI(moimodel, nvar, index_map)
703-
_index(v::MOI.VariableIndex) = index_map[v].value
703+
function parser_objective_MOI(moimodel, variables)
704+
_index(v::MOI.VariableIndex) = v.value
705+
706+
# Number of variables
707+
nvar = length(variables)
704708

705709
# Variables associated to linear and quadratic objective
706710
type = "UNKNOWN"
@@ -751,11 +755,14 @@ function parser_objective_MOI(moimodel, nvar, index_map)
751755
end
752756

753757
"""
754-
parser_linear_expression(cmodel, nvar, index_map, F)
758+
parser_linear_expression(cmodel, variables, F)
755759
756760
Parse linear expressions of type `VariableRef` and `GenericAffExpr{Float64,VariableRef}`.
757761
"""
758-
function parser_linear_expression(cmodel, nvar, index_map, F)
762+
function parser_linear_expression(cmodel, variables, F)
763+
764+
# Number of variables
765+
nvar = length(variables)
759766

760767
# Variables associated to linear expressions
761768
rows = Int[]
@@ -810,7 +817,7 @@ function parser_linear_expression(cmodel, nvar, index_map, F)
810817
end
811818
end
812819
moimodel = backend(cmodel)
813-
lls = parser_objective_MOI(moimodel, nvar, index_map)
820+
lls = parser_objective_MOI(moimodel, variables)
814821
return lls, LinearEquations(COO(rows, cols, vals), constants, length(vals)), nlinequ
815822
end
816823

@@ -844,11 +851,14 @@ function add_constraint_model(Fmodel, Fi::AbstractArray)
844851
end
845852

846853
"""
847-
parser_nonlinear_expression(cmodel, nvar, F; hessian)
854+
parser_nonlinear_expression(cmodel, variables, F; hessian)
848855
849856
Parse nonlinear expressions of type `NonlinearExpression`.
850857
"""
851-
function parser_nonlinear_expression(cmodel, nvar, F; hessian::Bool = true)
858+
function parser_nonlinear_expression(cmodel, variables, F; hessian::Bool = true)
859+
860+
# Number of variables
861+
nvar = length(variables)
852862

853863
# Nonlinear least squares model
854864
F_is_array_of_containers = F isa Array{<:AbstractArray}

0 commit comments

Comments
 (0)