How to compare JuMP variables?


#1

I have a LP problem with many variables that represent different things. One of my variables can assume negatives or positives values, according to the timeslice. Inside an expression(@expression) I would like to accumulate ONLY the values positives of this variable. My variable is var_x. In reality, I have other loops nested, but to make it simpler the general idea is to get something that looks like that :

                for t in timeslice
                    if var_x[t]> 0
                        acc_x = @expression(model,acc_x + var_x[t] )
                    end
                end   

I have tried this idea but I got the following error :

ERROR: LoadError: MethodError: no method matching isless(::Int64, ::JuMP.Variable)

Anyone knows another way to compare variables JuMP? Thanks in advance.


#2

You cannot compare variable with numbers since the variable value is unknown during the modeling phase.
What you would like to do is to have an expression having the value sum(max.(0, var_x)).
You could do

@variable m x_plus[timeslice] >= 0
@constraint m x_plus .>= var_x

If you minimize the expression, in an optimial solution, you will automatically have x_plus equal to 0 when var_x is negative and equal to var_x otherwise.


#3

Thanks for you answer. But I already have a objective function(minimization) that, among other expressions, needs to use the result of the accumulation I would like to do . Like:

min( acc_x * parameter_costs + ......) 

I didn’t understand your suggestion. That means I have to solve two problems of optimization? I really cannot see how to do it…

If you minimize the expression, in an optimial solution

Thanks in advance if you could help me.


#4

You don’t have to actually minimize the expression separately. You simply have that the sum of the x_plus is not necessarily equal to the sum of max(0, var_x), it is also allowed to be larger. You still need to show that in an optimal solution, it will always be equal.
This is the case if you minimize this sum alone but it is also the case in many other situations.
In fact, this will work if your problem is convex. That is, if it can be reformulated as

min_x g(x)
f_i(x) <= 0

where g(x) and the f_i are convex functions.
Indeed, this can be reformulated as

min z
g(x) - z <= 0
f_i(x) <= 0

which is equivalent since z is minimized so in an optimal solution, g(x) - z will be tight.

Here, max(0, x) is convex so sum max(0, x_i) is a convex function and the problem is convex.

min_x sum max(0, x_i)
...

If you reformulate it as

min_x sum z_i
max(0, x_i) - z_i = 0
...

it is not convex since max(0, x_i) - z_i is not linear.
However, since you minimize z_i, constraining max(0, x_i) - z_i <= 0 is sufficient since it will be tight for optimal solution so you can reformulate it as

min_x sum z_i
max(0, x_i) - z_i <= 0
...

which is convex since max(0, x_i) - z_i is convex.

If in your objective, you have the sum of the max(0, x_i) multiplied by a positive constant plus other stuff, the argument still works.


#5

Thanks a lot for your detailed explanation. I don’t have a great math base, so could you like to confirm my conclusions to solve this problem? Consider var_x as the variable that I want to accumulate when its value is positive.

  1. Firstly, I have to include an expression like that:
@expression(model, myExpression, sum(max(0,var_x))
  1. Then my objective function takes this form
@objective(model, Min, myExpression*(parameter) + other sum*(other parameters)
  1. To finalize, I also have to include a constraint that uses myExpression. Like that:
@constraint(model, myConstraint, myExpression - myObjectiveFunction) <=0

Thanks again!!


#6

Firstly, I have to include an expression like that:

@expression(model, myExpression, sum(max(0,var_x))

You need to explicitely create the x_plus variables that I mentioned above

To finalize, I also have to include a constraint that uses myExpression. Like that:

@constraint(model, myConstraint, myExpression - myObjectiveFunction) <=0

What do you mean by that ? You want to add a constraint that myExpression*(1-parameter) - other sum*(other parameters) is nonpositive ?


#8

I think I understood now, in fact I only need to create x_plus and its constraint, right?

@variable m x_plus[timeslice] >= 0
@constraint m x_plus .>= var_x

And then, instead of having an expression sum(var_x) I would have an expression(sum (x_plus))

I don’t need to create explicitly an expression like bellow, once I will have to deal with the same error no method matching isless
@expression(model, myExpression, sum(max(0,var_x))

Also, as my problem is convex I can be sure that
sum(var_x) is equal to sum (x_plus)
Thanks in advance for your help.


#9

Yes, exactly :slight_smile:


#10

Thanks a lot for your time and patience :grinning::grinning: