Some good news is that you can stop using Complementarity.jl. We’ve recently added first-class support for mixed-complementarity problems to JuMP. See:
Here’s what the translation would look like:
using JuMP
import PATHSolver
A = [300, 350, 400, 450, 500]
theta = [0.2, 0.2, 0.2, 0.2, 0.2]
B = 1
I = 90
C = 60
Tau = 8760
technologies = [1, 2, 3, 4, 5]
m = Model(PATHSolver.Optimizer)
@variables(m, begin
x[technologies] >= 0
Q[technologies] >= 0
alpha[technologies] >= 0
end)
for i in 2:length(technologies)
@constraint(m, x[1] == x[i])
end
@constraints(m, begin
max_capacity[i in technologies], x[i] - Q[i] ⟂ alpha[i]
kkt_Q[i in technologies], Tau * sum(theta[j] * (C - A[j] + B * Q[j]) for j in technologies) + alpha[i] ⟂ Q[i]
kkt_x[i in technologies], 1000 * I - alpha[i] ⟂ x[i]
end)
optimize!(m)
println("x = ", value.(x))
println("Q = ", value.(Q))
But if you run the code, you’ll get the error:
julia> for i in 2:length(technologies)
@constraint(m, x[1] == x[i])
end
ERROR: Constraints of type MathOptInterface.ScalarAffineFunction{Float64}-in-MathOptInterface.EqualTo{Float64} are not supported by the solver.
If you expected the solver to support your problem, you may have an error in your formulation. Otherwise, consider using a different solver.
The list of available solvers, along with the problem types they support, is available at https://jump.dev/JuMP.jl/stable/installation/#Supported-solvers.
Stacktrace:
[1] error(s::String)
@ Base ./error.jl:33
[2] _moi_add_constraint(model::MathOptInterface.Utilities.CachingOptimizer{MathOptInterface.Bridges.LazyBridgeOptimizer{MathOptInterface.Utilities.GenericOptimizer{Float64, MathOptInterface.Utilities.ObjectiveContainer{Float64}, MathOptInterface.Utilities.VariablesContainer{Float64}, PATHSolver.OptimizerFunctionConstraints{Float64}}}, MathOptInterface.Utilities.UniversalFallback{MathOptInterface.Utilities.Model{Float64}}}, f::MathOptInterface.ScalarAffineFunction{Float64}, s::MathOptInterface.EqualTo{Float64})
@ JuMP ~/.julia/packages/JuMP/ToPd2/src/constraints.jl:679
[3] add_constraint(model::Model, con::ScalarConstraint{AffExpr, MathOptInterface.EqualTo{Float64}}, name::String)
@ JuMP ~/.julia/packages/JuMP/ToPd2/src/constraints.jl:706
[4] macro expansion
@ ~/.julia/packages/JuMP/ToPd2/src/macros.jl:1345 [inlined]
[5] top-level scope
@ ./REPL[14]:2
That’s because you cannot add equality constraints to a mixed-complementarity problem.
You need to do instead:
using JuMP
import PATHSolver
A = [300, 350, 400, 450, 500]
theta = [0.2, 0.2, 0.2, 0.2, 0.2]
B = 1
I = 90
C = 60
Tau = 8760
technologies = [1, 2, 3, 4, 5]
m = Model(PATHSolver.Optimizer)
@variables(m, begin
x[technologies] >= 0
Q[technologies] >= 0
alpha[technologies] >= 0
μ[technologies[2:end]] # !!! NEW !!!
end)
@constraints(m, begin
[i=technologies[2:end]], x[1] - x[i] ⟂ μ[i] # !!! NEW !!!
max_capacity[i in technologies], x[i] - Q[i] ⟂ alpha[i]
kkt_Q[i in technologies], Tau * sum(theta[j] * (C - A[j] + B * Q[j]) for j in technologies) + alpha[i] ⟂ Q[i]
kkt_x[i in technologies], 1000 * I - alpha[i] ⟂ x[i]
end)
optimize!(m)
println("x = ", value.(x))
println("Q = ", value.(Q))
and now I get the same solution as Complementarity.jl.
If this solution isn’t what you expect, then you have a mistake somewhere in your equations.