Hi there,
I’m trying to use the max function in one of my NLconstraint. Following @ odow’s advice, I use auto-differentiation to allow max into the constraint. The problem is that the length of the array that I want to take max over is not fixed and depend on problem instances, so ideally I want to be able to write
m = Model(solver=IpoptSolver(print_level=0))
f(array) = maximum(array)
JuMP.register(m, :f, 1, f, autodiff=true)
...
@variable(m, x[1:T])
@variable(m, y)
@NLconstraint(m, y == f(x))
However, due to the restriction to scalar operation in NLconstraint, right now I’m forced to write, e.g. when L = 2:
m = Model(solver=IpoptSolver(print_level=0))
f(a,b) = max(a,b)
JuMP.register(m, :f, 2, f, autodiff=true)
...
@variable(m, x[1:T])
@variable(m, y)
@NLconstraint(m, y == f(x[1],x[2]))
and for different L, the code will have to change. Any idea to help me write proper code?
Thanks for the comment, but it doesn’t exactly solve my problem. I think the main problem is in the restriction of NLconstraint that doesn’t allow vector input, so I can’t use a maximum(array) or reduce(max, array) syntax, but instead have to use max(array[1],array[2],...,array[L])
It’s nice that max can take any number of input, but is there any syntax that allows me to pass a variable number of inputs into the max function, just like the ... sign above.
@zhangxz1123, you’re looking for the splatting syntax (note: I’m not sure if this works on JuMP v0.18, which it looks like you’re using. It does on the latest JuMP v0.19.):
using JuMP, Ipopt
m = Model(with_optimizer(Ipopt.Optimizer))
N = 4
@variable(m, x[i=1:N] >= i)
f(y...) = max(y...)
JuMP.register(m, :f, N, f, autodiff=true)
@NLobjective(m, Min, f(x...))
optimize!(m)
@odow, this is neat, thank you! I’m trying to update my JuMP package, but seems to have some problem with it. My current JuMP version is v0.18.5, but doing Pkg.update() doesn’t update JuMP to v0.19. Below is the output that I get
@odow, a follow-up question on splatting syntax. It seems that currently the splatting only works on the variable itself. However, in my problem, the variable is saved as a matrix, but the max is only taken over one column of the variable, e.g.
using JuMP, Ipopt
m = Model(with_optimizer(Ipopt.Optimizer))
M=5
N=2
@variable(m, x[1:M,1:N])
f(y...) = max(y...)
JuMP.register(m, :f, N, f, autodiff=true)
@NLobjective(m, Min, f(x[1,:]...)
optimize!(m)
But this is not allowed. I tried to make f act on x itself, but didn’t get it to work. Is there any elegant solution?
In fact, I need to compute f(x[i,:]...) for all i=1:M, so does explicitly claim a variable y still work? It seems that I need to claim M explicit variables in this case.