Complementarity constraints containing sum statements

Hi,

I’m trying to model an mathematical program with equilibrium constraints (MPEC) in Julia/JuMP. I am currently using the Complementarity.jl package. I am following this example (“bard1”) and try to adapt it to my needs.

Now, I run into problems when I try to include a summation statement in a complementarity constraint. To explain the issue, consider the following reformulation of the bard1 example, which works fine:

using JuMP, Ipopt, Complementarity

m = Model(Ipopt.Optimizer)
@variable(m, x[i in 1:2]>=0)
@variable(m, l[j in 1:3])

@NLobjective(m, Min, (x[1] - 5)^2 + (2*x[2] + 1)^2)

@NLconstraint(m, 2*(x[2]-1) - 1.5*x[1] + l[1] - l[2]*0.5 + l[3] == 0)

@complements(m, 0 <= 3*x[1] - x[2] - 3,        l[1] >= 0)
@complements(m, 0 <= - x[1] + 0.5*x[2] + 4,    l[2] >= 0)
@complements(m, 0 <= - x[1] - x[2] + 7,        l[3] >= 0)

optimize!(m)

Now, my problem arises when I try to rewrite the third complementarity constraint as follows:

@complements(m, 0 <= - sum(x[i] for i in 1:2) + 7,        l[3] >= 0)

If I try to run this line, I get the following error message:

ERROR: UndefVarError: i not defined
Stacktrace:
 [1] macro expansion
   @ C:\Users\egbertrv\.julia\packages\JuMP\klrjG\src\parse_nlp.jl:521 [inlined]
 [2] macro expansion
   @ C:\Users\egbertrv\.julia\packages\JuMP\klrjG\src\macros.jl:1978 [inlined]
 [3] top-level scope
   @ C:\Users\egbertrv\.julia\packages\Complementarity\sQ4xs\src\mpec.jl:265

Of course I could hardcode all the constraints without using the summation function, but that will not be practically feasible for my problem.

Does anyone have an idea how to solve this issue? I’m open for any alternative that allows me to formulate and solve an MPEC in Julia/JuMP.

Really not sure, but I would try

sum{x[i], i in 1:2}

or

for i in 1:2
@complements(m, 0 <= - sum(x[i]) + 7,        l[3] >= 0)
end

Or something like that… This is how I did a long time ago in my former blog but there was no @complements.

Thanks for the reply! I tried both suggestions, but they don’t work unfortunately.

  1. The curly brackets no longer seem to be supported:
ERROR: LoadError: The curly syntax (sum{},prod{},norm2{}) is no longer supported. Expression: sum{x[i], i in 1:2}.
  1. The other suggestion also fails:
ERROR: sum() can appear in nonlinear expressions  only if the argument is a generator statement, for example, sum(x[i] for i in 1:N).
  1. Out of curiosity, I also tried
@complements(m, 0 <= - sum(x[:]) + 7,        l[3] >= 0)

which is in line with the example in your blog post, but it throws the same error as under 2. above.

Not sure if this is the best way, but you can create an auxiliary expression with the sum and use the expression in complements:

using JuMP, Ipopt, Complementarity

m = Model(Ipopt.Optimizer)
@variable(m, x[i in 1:2]>=0)
@variable(m, l[j in 1:3])

@NLobjective(m, Min, (x[1] - 5)^2 + (2*x[2] + 1)^2)

@NLconstraint(m, 2*(x[2]-1) - 1.5*x[1] + l[1] - l[2]*0.5 + l[3] == 0)
@NLexpression(m,sumExp, sum(x[i] for i in 1:2)) #Create the expression


@complements(m, 0 <= 3*x[1] - x[2] - 3,        l[1] >= 0)
@complements(m, 0 <= - x[1] + 0.5*x[2] + 4,    l[2] >= 0)
@complements(m, 0 <= - x[1] - x[2] + 7,        l[3] >= 0)

@complements(m, 0 <= - sumExp + 7, l[3] >= 0) #Use the expression here

optimize!(m)
3 Likes

Thanks, this works! :slight_smile:

For future reference, I think the simplest way to use this workaround is as follows. For variable x[i in I], define the expression

@NLexpression(m, exp_x[i in I], **my_expression**)

(where **my_expression** may contain summations), and use them to define the complementarity constraints as follows:

for i in I
    @complements(m, 0 <= exp_x[i], x[i] >= 0)
end

Thanks again!