I’m trying to define a nonlinear constraint programmatically via expressions. Specifically, I have a function f
that takes in arguments x
(a JuMP Variable), i
(the index of the variable), and p
(some parameters). The real function f
is somewhat involved, so I’d like to be able to pass it indices/parameters and return an expression that I can use in JuMP constraints. So far, the below attempts haven’t worked for me. What I’m hung up on is splicing the JuMP Variable into the expression.
using JuMP
##
## parameter and function
##
p = Dict()
p[:a] = 10.0
function f(x, i, p)
return :( $(x[i])^2 + $(p[:a]) )
end
The final constraint expression I’m trying to build must look something like
:( $(x[i])^2 + 10.0 == 0)
I first tried using the @NLconstraint
macro
##
## attempt
##
M = Model()
@variable(M, x[1:3])
for i in 1:3
@NLconstraint(M, :(0 == $(Expr(:call, f, x, $(i), p))))
end
but got the error
ERROR: LoadError: in @NLconstraint ($(Expr(:quote, :(0 == $(Expr(:$, :(Expr(:call, f, x, $(Expr(:$, :i)), p)))))))): constraints must be in one of the following forms:
expr1 <= expr2
expr1 >= expr2
expr1 == expr2
Stacktrace:
[1] error(::String) at ./error.jl:33
[2] @NLconstraint(::LineNumberNode, ::Module, ::Any, ::Any, ::Vararg{Any,N} where N) at /Users/jakeroth/.julia/packages/JuMP/PbnIJ/src/macros.jl:1375
in expression starting at REPL[18]:2
The issue with how I’ve written the constraint is that the JuMP Variable x
isn’t spliced in, that is, I need the final expression to contain :( $(x[i]) ... )
but I only have :( x[i] ... )
.
It seems that my function f
is to blame – is there a way to rewrite it to get $
to stop interpolating in f
? Alternatively, is there a better way to define programmatic constraints still using expressions?