How to include a customized function which takes expressions as input values inside a constraint?

consider this program

H=4
J=3
m = Model(GLPK.Optimizer)
@variable(m, x[ 1:H , 1:J ], Bin)

I am trying to model this constraint:
Capture

Where 1.() is an indicator function.

After a few hours of playing this is the best I can do:

m = Model(GLPK.Optimizer)
@variable(m ,x[1:H , 1:J])
Hᵖ = [[2, 3], [1, 3, 4], [1, 2, 4]]

@expression(m, f[j in 1:J],  sum(x[h,j] for h in Hᵖ[j] )  )

function indicate(x)
    y =0.0
    if x>0.0
        y=1.0
    end
    return y
end
@constraint(m, sum( indicate( f[j] ) for j in 1:J) ≥ 0)

and this is the error I get

MethodError: no method matching isless(::Float64, ::AffExpr)
Closest candidates are:
  isless(::AbstractFloat, ::ForwardDiff.Dual{Ty, V, N} where {V, N}) where Ty at C:\Users\e29115\.julia\packages\ForwardDiff\PBzup\src\dual.jl:145
  isless(::Real, ::ForwardDiff.Dual{Ty, V, N} where {V, N}) where Ty at C:\Users\e29115\.julia\packages\ForwardDiff\PBzup\src\dual.jl:145
  isless(::Any, ::Missing) at missing.jl:88

I know he says, he expects to see a number but sees an expression. But I don’t know how to fix this. :frowning:

Any comment is appreciated.

You cannot model constraints like this directly in JuMP. You must reformulate into a mixed-integer linear program.

using JuMP
# To model y = 1 if sum(x) > 0
model = Model()
@variable(model, x[1:3], Bin)
@variable(model, y, Bin)
# If any x > 0, then y = 1
@constraint(model, 3 * y >= sum(x))
# if all x = 0, then y = 0
@constraint(model, y <= sum(x))
1 Like

@odow thanks a lot for your help with my previous question.

I work on a similar but more complicated constraint. I highlighted the complicating area by red

Let me explain it by an example:

z\^r = [[110000.0, 110000.0, 93000.0, 93000.0, 93000.0],
 [110000.0, 110000.0, 93000.0, 93000.0] ]

k_max = [3,2]

This means for the first situation I have to add the first 3 elements of the vector z^r. (The elements of vector are sorted descendingly)

110000 +110000 + 90000 = 310000

and for the second situation I have to add the first 2 elements of the vector z^r.

110000 + 110000 = 220000

Any solution for this?

Is z^r a variable? Is k also a variable?

I don’t understand your notation in the red box. What set is the summation over? What set is the max operator over?

Again, you’ll need a MILP reformulation:

model = Model()
@variable(model, x[1:3])
@variable(model, 1 <= k <= 3, Int)
# x is sorted from largest to smallest
@constraint(model, [i=2:3], x[i-1] >= x[I])
# sum(x[i] for i in 1:k) ???
@variable(model, ki[1:3], Bin)
@constraint(model, [i=2:3], ki[i-1] >= ki[i])
@constraint(model, sum(ki) == k)
# sum(ki[i] * x[i] for i in 1:3)
@variable(model, y[1:3])
@constraint(model, [i=1:3], y[i] <= x[i] + M * (1 - ki[i]))
@constraint(model, [i=1:3], y[i] >= x[i] - M * (1 - ki[i]))
@constraint(model, [i=1:3], y[i] <= M * ki[i])
@constraint(model, [i=1:3], y[i] >= -M * ki[i])
# Final reformulation
@expression(model, sum(y[i] for i in 1:3))
1 Like