Nonlinear expressions may contain only scalar expressions

using JuMP,Gurobi
 n=4
PL=[0.3;0.55;0;0]
model=Model(Gurobi.Optimizer)
G=[1.04209 -0.588235 -0.0 -0.453858;-0.588235 1.069 0 -0.480769;-0 0 0 0;-0.453858 -0.480769 0 0.934627]
Q=[-8.24288   2.35294   3.66667   1.89107;  2.35294  -4.72738   0.0       2.40385;3.66667   0.0      -3.33333   0.0;  1.89107   2.40385   0.0      -4.26159]
@variable(model, U[1:n])
@variable(model, P[1:n])
@variable(model, Ang[1:n])
@variable(model, Angle[1:n,1:n])
@constraint(model, con5[i = 1:n, j = 1:n], Angle[i,j]==Ang[i] .-Ang[j])
@expression(model, my_expr, P-PL)
@NLconstraint(model,co1,my_expr==U.*((G.*cos.(Angle)+Q.*sin.(Angle))*U))

error:


Is P-PL wrong? How could I solve it?

Two issues.

  1. As stated in the error, you can only use scalar expressions. That means no vectors, and no broadcasting. Here is the documentation: Nonlinear Modeling · JuMP

  2. Gurobi doesn’t support nonlinear. Use Ipopt instead.

2 Likes

@Shayan (and anyone else coming across this post): with version v1.15 of JuMP you can use @constraint instead of @NLconstraint and everything works:

julia> using JuMP, Ipopt

julia> n = 4
4

julia> PL = [0.3, 0.55, 0.0, 0.0]
4-element Vector{Float64}:
 0.3
 0.55
 0.0
 0.0

julia> model=Model(Ipopt.Optimizer)
A JuMP Model
Feasibility problem with:
Variables: 0
Model mode: AUTOMATIC
CachingOptimizer state: EMPTY_OPTIMIZER
Solver name: Ipopt

julia> G = [
            1.04209  -0.588235 0.0 -0.453858
           -0.588235  1.069    0.0 -0.480769
            0.0       0.0      0.0  0
           -0.453858 -0.480769 0.0  0.934627
       ]
4×4 Matrix{Float64}:
  1.04209   -0.588235  0.0  -0.453858
 -0.588235   1.069     0.0  -0.480769
  0.0        0.0       0.0   0.0
 -0.453858  -0.480769  0.0   0.934627

julia> Q = [
           -8.24288   2.35294   3.66667   1.89107
            2.35294  -4.72738   0.0       2.40385
            3.66667   0.0      -3.33333   0.0
            1.89107   2.40385   0.0      -4.26159
       ]
4×4 Matrix{Float64}:
 -8.24288   2.35294   3.66667   1.89107
  2.35294  -4.72738   0.0       2.40385
  3.66667   0.0      -3.33333   0.0
  1.89107   2.40385   0.0      -4.26159

julia> @variable(model, U[1:n])
4-element Vector{VariableRef}:
 U[1]
 U[2]
 U[3]
 U[4]

julia> @variable(model, P[1:n])
4-element Vector{VariableRef}:
 P[1]
 P[2]
 P[3]
 P[4]

julia> @variable(model, Ang[1:n])
4-element Vector{VariableRef}:
 Ang[1]
 Ang[2]
 Ang[3]
 Ang[4]

julia> @variable(model, Angle[1:n,1:n])
4×4 Matrix{VariableRef}:
 Angle[1,1]  Angle[1,2]  Angle[1,3]  Angle[1,4]
 Angle[2,1]  Angle[2,2]  Angle[2,3]  Angle[2,4]
 Angle[3,1]  Angle[3,2]  Angle[3,3]  Angle[3,4]
 Angle[4,1]  Angle[4,2]  Angle[4,3]  Angle[4,4]

julia> @constraint(model, con5[i = 1:n, j = 1:n], Angle[i,j] == Ang[i] .- Ang[j])
4×4 Matrix{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarAffineFunction{Float64}, MathOptInterface.EqualTo{Float64}}, ScalarShape}}:
 con5[1,1] : Angle[1,1] = 0                    …  con5[1,4] : -Ang[1] + Ang[4] + Angle[1,4] = 0
 con5[2,1] : Ang[1] - Ang[2] + Angle[2,1] = 0     con5[2,4] : -Ang[2] + Ang[4] + Angle[2,4] = 0
 con5[3,1] : Ang[1] - Ang[3] + Angle[3,1] = 0     con5[3,4] : -Ang[3] + Ang[4] + Angle[3,4] = 0
 con5[4,1] : Ang[1] - Ang[4] + Angle[4,1] = 0     con5[4,4] : Angle[4,4] = 0

julia> @expression(model, my_expr, P - PL)
4-element Vector{AffExpr}:
 P[1] - 0.3
 P[2] - 0.55
 P[3]
 P[4]

julia> @constraint(model, my_expr .== U .* ((G .* cos.(Angle) + Q .* sin.(Angle)) * U))
4-element Vector{ConstraintRef{Model, MathOptInterface.ConstraintIndex{MathOptInterface.ScalarNonlinearFunction, MathOptInterface.EqualTo{Float64}}, ScalarShape}}:
 (P[1] - 0.3) - (U[1] * ((((+(0.0) + (((1.04209 * cos(Angle[1,1])) + (-8.24288 * sin(Angle[1,1]))) * U[1])) + (((-0.588235 * cos(Angle[1,2])) + (2.35294 * sin(Angle[1,2]))) * U[2])) + (((0.0 * cos(Angle[1,3])) + (3.66667 * sin(Angle[1,3]))) * U[3])) + (((-0.453858 * cos(Angle[1,4])) + (1.89107 * sin(Angle[1,4]))) * U[4]))) = 0
 (P[2] - 0.55) - (U[2] * ((((+(0.0) + (((-0.588235 * cos(Angle[2,1])) + (2.35294 * sin(Angle[2,1]))) * U[1])) + (((1.069 * cos(Angle[2,2])) + (-4.72738 * sin(Angle[2,2]))) * U[2])) + (((0.0 * cos(Angle[2,3])) + (0.0 * sin(Angle[2,3]))) * U[3])) + (((-0.480769 * cos(Angle[2,4])) + (2.40385 * sin(Angle[2,4]))) * U[4]))) = 0
 (P[3]) - (U[3] * ((((+(0.0) + (((0.0 * cos(Angle[3,1])) + (3.66667 * sin(Angle[3,1]))) * U[1])) + (((0.0 * cos(Angle[3,2])) + (0.0 * sin(Angle[3,2]))) * U[2])) + (((0.0 * cos(Angle[3,3])) + (-3.33333 * sin(Angle[3,3]))) * U[3])) + (((0.0 * cos(Angle[3,4])) + (0.0 * sin(Angle[3,4]))) * U[4]))) = 0
 (P[4]) - (U[4] * ((((+(0.0) + (((-0.453858 * cos(Angle[4,1])) + (1.89107 * sin(Angle[4,1]))) * U[1])) + (((-0.480769 * cos(Angle[4,2])) + (2.40385 * sin(Angle[4,2]))) * U[2])) + (((0.0 * cos(Angle[4,3])) + (0.0 * sin(Angle[4,3]))) * U[3])) + (((0.934627 * cos(Angle[4,4])) + (-4.26159 * sin(Angle[4,4]))) * U[4]))) = 0
3 Likes

Dear @odow, Hi
My case is a bit different, and this topic helped me tackle the problem. I’m super grateful for the tremendous support and time that you put into assisting Julia users and devs.
But, great to know that in this case using @constraint is all we need.

1 Like