How to get ordering of constraints when calling eval_constraint?


I have a large JuMP model constructed programmatically as a function of some input data. My ultimate goal is to plug in arbitrary values into the variables and evaluate the values of the constraints. To accompish this, I’ve followed the initial approach from this thread here.

But here is my code:

using JuMP
using MathOptInterface
const MOI = MathOptInterface

model = complicated_model_builder()
variables = all_variables(model)

d = JuMP.NLPEvaluator(model)
MOI.initialize(d, [:Jac])
# (total_num_constraints = 61 in my case)
total_num_constraints = sum(num_constraints(model, F, S) for (F, S) in list_of_constraint_types(model))
constraint_values = zeros(total_num_constraints)
inp = ones(size(variables))*19  # Something arbitrary but noticeable
MOI.eval_constraint(d, constraint_values, inp)

This works as intended: constraint_values is populated with reasonable-looking values (e.g. some of them are 19 which I’d expect on constraints like my_var == 0)… However, it does not seem like the ordering of constraint_values matches what I get when I output print(model). Is there a way to link the output of eval_constraint/constraint_values to constraints in the original model?

Thank you.

NOTE: As I mentioned above, my ultimate goal is to get the values of constraints evaluated at arbitrary values of the variables. If there is a better way to do this, I’m also happy to hear about that. The only caveat worth mentioning is that I don’t have easy access to the internals of complicated_model_builder() to pass through any expressions that are defined during the constraint definitions.

No need to use eval_constraint. This should point you in the right direction:

julia> using JuMP

julia> model = Model();

julia> @variable(model, x >= 0)

julia> @constraint(model, c, 2x <= 1)
c : 2 x ≤ 1.0

julia> @NLconstraint(model, nl_con, 0 <= sin(x) <= 0.5)
0 ≤ sin(x) ≤ 0.5

julia> variable_values = Dict(v => rand() for v in all_variables(model))
Dict{VariableRef, Float64} with 1 entry:
  x => 0.379509

julia> cons = all_constraints(model; include_variable_in_set_constraints = true)
3-element Vector{ConstraintRef}:
 c : 2 x ≤ 1.0
 x ≥ 0.0
 0 ≤ sin(x) ≤ 0.5

julia> sol = Dict(c => value(xi -> variable_values[xi], c) for c in cons)
Dict{ConstraintRef{Model, C, ScalarShape} where C, Float64} with 3 entries:
  0 ≤ sin(x) ≤ 0.5 => 0.370465
  x ≥ 0.0          => 0.379509
  c : 2 x ≤ 1.0    => 0.759019

julia> sol[c]

julia> sol[nl_con]

julia> sol[LowerBoundRef(x)]

That works great, thank you!

1 Like