Non-linear expressions in optimization

Hi!
I use the version JuMP v0.21.4 and Julia v1.4.2 and I optimizing with Ipopt
I ve been working in a non-linear optimization model. Sorry for not presenting a MWE but my code is full of things.
I have a problems with an exponential expression that I would like to use afterwards in an @NLconstraint. In the following piece of code S is my array of variables.
I originally created this code without the convert(Array{Any}... but I got an error and I coudn’t even calculate the array Sd. Now the problem is that when including Sd in a non-linear expression I get the error copied at the end. I also tried to build this into an @NLexpression but that didn’t work either.

for e in 1:E
    for i in 2:K*T
        Sd[i,1,e]=S[i,1,e]-S[i-1,1,e]
    end
end
Sd
exp(ϵ*Sd)/(1+exp(ϵ*Sd))```

MethodError: no method matching exp(::Array{Any,3})
Closest candidates are:
  exp(!Matched::Float16) at math.jl:1114
  exp(!Matched::Complex{Float16}) at math.jl:1115
  exp(!Matched::Missing) at math.jl:1167
1 Like

I never used JuMP and I don’t know exactly what you want to achieve.
If you want to calculate the exponential elementwise, you have to sprinkle some dots here and there:

exp.(e*Sd) ./ (1 .+ exp.(e*Sd))

The above snippet assumes that e is a scalar. This is called broadcasting and allows any function that operates on a single element to be called on the whole collection.

Thanks a lot for your answer. The piece of code I showed is part of a non-linear optimization problem I’m building with JUMP. The exponential function I wrote will be used to create some of the no-linear constraints in my problem.
Yes you are right, in fact I have tried with this expression before exp.(ϵ*Sd)./(1+exp.(ϵ*Sd)) . With the dots the expression is correct but I still recieve the following error message:
exp is not defined for type GenericAffExpr. Are you trying to build a nonlinear problem? Make sure you use @NLconstraint/@NLobjective.

You cannot use broadcasting within @NLconstraint/@NLobjective in JuMP. You need to have a loop in the constraint/objective. JuMP’s documentation specifies:

" With the exception of the splatting syntax discussed below, all expressions must be simple scalar operations. You cannot use dot , matrix-vector products, vector slices, etc."

There are some examples here: Nonlinear Modeling · JuMP

1 Like

Since your S is a variable, your Sd by default will be an affine expression. As far as I know, it is not possible to mix affine expressions and nonlinear expressions in JuMP. To avoid that mix, you should define your Sd as a nonlinear expression, something like:
@NLexpression(model, Sd[e=1:K,1,i=2:K*T], S[i,1,e]-S[i-1,1,e])
where model is your JuMP model. Then you should be able to do:

for e in 1:E
  for i in 2:K*T
     @NLexpression(model, expExpr[e,i], exp(ϵ*Sd[e,1,i])/(1.0+exp(ϵ*Sd[e,1,i])))
  end
end

and use expExpr later in your model. The @NLexpression cannot take arrays, that’s why the two loops are necessary.

Disclaimer: I have not tested this solution (it would be easier with an MWE). There may be troubles with the middle indicator in Sd - if it is only 1, then you could remove it.

1 Like

Hello blob and thanks for your reply, by following the code you suggested, I was able to create a new loop that seems ok. The non-linear expression must be anonymous for it to work.

for e in 1:E
  for i in 2:K*T
     Sd[i-1,1,e]=@NLexpression(m, exp(ϵ*(Sd[i,1,e]-S[i-1,1,e]))/(1.0+exp(ϵ*(Sd[i,1,e]-S[i-1,1,e]))))   
  end
end
Sd```
1 Like