# Adding complementarity constraints

**URL:** <https://discourse.julialang.org/t/adding-complementarity-constraints/110132>\
**Category:** Optimization (Mathematical)\
**Tags:** complementarity\
**Created:** [February 13, 2024, 6:01am UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132 "2024-02-13T06:01:31Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![anand.kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/anand.kumar/32/206982_2.png) [@anand.kumar](https://discourse.julialang.org/u/anand.kumar)\
**Post date:** [February 13, 2024, 6:01am UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132/1 "2024-02-13T06:01:31Z")

</div>

I’m new to both AMPL and JuMP. I’m trying to translate constraints below to jump but don’t understand how to do it.

```julia
compl_1{k in K}: 0 <= ll[1,k] complements y[1,k] - x[1] <= 0;
compl_2{k in K}: 0 <= ll[2,k] complements y[2,k] - x[2] <= 0;
compl_3{k in K}: 0 <= ll[3,k] complements - y[1,k] + x[3] <= 0;
compl_4{k in K}: 0 <= ll[4,k] complements - y[2,k] + x[4] <= 0;

```

One way I tried is to

```julia
@variable(model, ll[L, K] >= 0) #specifically constraint to be positive?
@constraint(model, [k=K], ll[1,k] ⟂ -y[1,k] + x[1])
@constraint(model, [k=K], ll[2,k] ⟂ -y[2,k] + x[2])
@constraint(model, [k=K], ll[3,k] ⟂ y[1,k] - x[3])
@constraint(model, [k=K], ll[4,k] ⟂ y[2,k] - x[4])

```

More generally I want to ask how to model constraints of type G\_i(x)H\_i(x) = 0 \;, G\_i(x) \geq 0,\, H\_i(x) \geq 0\,\forall x; i=1\ldots n in Julia.

link to AMPL model : [http://www.mcs.anl.gov/~leyffer/MacMPEC/problems/design-cent-4.mod](http://www.mcs.anl.gov/~leyffer/MacMPEC/problems/design-cent-4.mod)

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 13, 2024, 6:43am UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132/2 "2024-02-13T06:43:51Z")

</div>

Hi @anand.kumar, welcome to the forum 😄

JuMP supports a particularly form of mixed complementarity problems in which a variable (or vector of variables) `x` complements a function `F(x)`.

See the documentation: [Mixed complementarity problems · JuMP](https://jump.dev/JuMP.jl/stable/tutorials/nonlinear/complementarity/)

Those particular constraints would need to be written as:

```julia
using JuMP
I = 1:4
J = 1;2
K = 1:3
L = 1:4
model = Model()
@variable(model, x[i in I], start = x0[i])
@variable(model, y[j in J, k in K], start = y0[j, k])
@variable(model, ll[l in L, k in K] >= 0, start = ll0[l, k])
@constraint(model, compl_1[k in K], x[1] - y[1,k] ⟂ ll[1, k])
@constraint(model, compl_2[k in K], x[2] - y[2,k] ⟂ ll[2, k])
@constraint(model, compl_3[k in K], y[1,k] - x[3] ⟂ ll[3, k])
@constraint(model, compl_4[k in K], y[2,k] - x[4] ⟂ ll[4, k])

```

Note the signs. Since `ll >= 0`, then the complementing function `F(x)` is `0` if `ll > 0` and `F(x) >= 0` if `ll == 0`.

However, your larger example is an MPEC. Currently, JuMP is missing first-class support for converting MPECs into NLPs, . so you’ll need to use a library like Complementarity.jl:

```julia
using JuMP, Ipopt, Complementarity
I = 1:4
J = 1:2
K = 1:3
L = 1:4
x0 = [1, 1, -1, -1]
y0 = zeros(length(J), length(K))
ll0 = ones(length(L), length(K))
model = Model(Ipopt.Optimizer)
@variable(model, x[i in I], start = x0[i])
@variable(model, y[j in J, k in K], start = y0[j, k])
@variable(model, ll[l in L, k in K], start = ll0[l, k])
@objective(model, Max, (x[1] - x[3]) * (x[2] - x[4]))
@constraints(model, begin
    -y[1,1] - y[2,1]^2 <= 0
    y[1,2]/4 + y[2,2] - 3/4 <= 0
    -y[2,3] - 1 <= 0
    1 + ll[1,1] - ll[3,1] == 0
    2*y[2,1] + ll[2,1] - ll[4,1] == 0
    -1/4 + ll[1,2] - ll[3,2] == 0
     -1 + ll[2,2] - ll[4,2] == 0
    0 + ll[1,3] - ll[3,3] == 0
    1 + ll[2,3] - ll[4,3] == 0
end)
for k in K
    @complements(model, 0 >= y[1,k] - x[1], ll[1,k] >= 0)
    @complements(model, 0 >= y[2,k] - x[2], ll[2,k] >= 0)
    @complements(model, 0 >= - y[1,k] + x[3], ll[3,k] >= 0)
    @complements(model, 0 >= - y[2,k] + x[4], ll[4,k] >= 0)
end
optimize!(model)
solution_summary(model)
value.(x)
value.(y)
value.(ll)

```

This gets a trivial solution with zero volume though, so I don’t know if I made a typo or something?

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 13, 2024, 7:07pm UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132/3 "2024-02-13T19:07:51Z")

</div>

Ah. I was missing the correct starting values for `y0` and `ll0`: [https://www.mcs.anl.gov/~leyffer/MacMPEC/problems/design-cent-4.dat](https://www.mcs.anl.gov/~leyffer/MacMPEC/problems/design-cent-4.dat)

```julia
y0 = [0 3 0; 0 0 -1]
ll0 = [0 0 0; 0 0 0; 0 0 0; 0 0 1]

```

Now I get the more reasonable:

```julia
julia> solution_summary(model)
* Solver : Ipopt

* Status
  Result count : 1
  Termination status : LOCALLY_SOLVED
  Message from the solver:
  "Solve_Succeeded"

* Candidate solution (result #1)
  Primal status : FEASIBLE_POINT
  Dual status : FEASIBLE_POINT
  Objective value : 3.07920e+00
  Dual objective value : 6.17863e+00

* Work counters
  Solve time (sec) : 3.42009e-02
  Barrier iterations : 47

julia> value.(x)
1-dimensional DenseAxisArray{Float64,1,...} with index sets:
    Dimension 1, 1:4
And data, a 4-element Vector{Float64}:
  3.6188022179102477
 -0.15470053521845614
 -0.02393227263092365
 -1.0000000143111953

```

---

<div class="post-metadata">

**Author:** ![anand.kumar](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/anand.kumar/32/206982_2.png) [@anand.kumar](https://discourse.julialang.org/u/anand.kumar)\
**Post date:** [February 14, 2024, 4:33am UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132/4 "2024-02-14T04:33:15Z")

</div>

Thanks a ton @odow for quick and elaborate response. There’s lot to learn from your solution.

---

<div class="post-metadata">

**Author:** ![odow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/odow/32/28685_2.png) [@odow](https://discourse.julialang.org/u/odow)\
**Post date:** [February 14, 2024, 4:39am UTC](https://discourse.julialang.org/t/adding-complementarity-constraints/110132/5 "2024-02-14T04:39:08Z")

</div>

Let me know if you have any questions.

I hope to one day add proper MPEC support to JuMP so you dont have to use the special `@complements` macro from Complementarity.jl. It’s annoying that MCP works nicely but MPEC doesn’t!
