juliametaprogrammingjulia-jump

Adding constraints to jump model from dict


Suppose I have a Dict where I store a config with the optimisation I want to do. So something like the below:

portfolio = Model(Ipopt.Optimizer)
@variable(portfolio, x[1:5])

max_ = 10.0
min_ = [1,2,3,4,5]
constraints = Dict{String, String}()
constraints["max_constraint"] = "x .<= max_"
constraints["min_constraint"] = "x  >= min_"

I want to loop through everything in constraints and put it into model as a constraint with the name as per the name of the key in the dict. So basically I want to do:

for k in keys(constraints)
    @constraint(portfolio, k, constraints[k])
end

This doesnt work for either constraint but I can copy paste the contents of the Dict to make it work:

@constraint(portfolio, max_constraint, x .<= max_)
@constraint(portfolio, min_constraint, x  >= min_)

So how can I add the constraints using the strings directly from the Dict? In addition is there a way to do this that is robust to if max_ and min_ fall out of scope (for instance the additional of constraints are added in a function call with the model being returned).


Solution

  • In order to get from strings describing the constraint to expressions, there needs to be a parsing stage. After parsing, the macro/function to add the constraint expression needs to be called. So the following did work for me in a test:

    for (name, con) in constraints
        e = Meta.parse("@constraint(portfolio, $name, $con)")
        @eval $e
    end
    

    In any case, JuMP allows to produce constraints programmatically, and that may be something to explore.

    Finally, if the strings describing the constraints are coming from an external file or source, using @eval introduces risks (security and such) and you may want to control the strings parsed and evaluated somehow.