Search code examples
juliamathematical-optimizationjulia-jump

Julia: How to introduce binary integers for mixed integers optimization problems with JuMP?


Problem description

I am trying to do a mixed-integer optimization for a "Unit Commitment" problem in Julia with Jump. But JuMP expects my introduction of the unit activation variable, x[1:N], to be a number and not a variable. However, the unit activation is a binary integer decision variable for the optimization problem so I have trouble including the variable into the optimization problem.

What am I doing wrong?

My approaches have been:

Approach 1: Include x[1:N] as part of @variable macro for P_G.

m = Model(Cbc.Optimizer)                                        # Model
@variable(m, x[1:N], Bin)                                       # Unit activation
@variable(m, P_C[i,1]*x[i] <= P_G[i=1:N,1:T] <= P_C[i,2]*x[i])  # Unit generation limit
for i in 1:T                                                    # Load balance
    @constraint(m, sum(P_G[:,i]) == P_D[i])
end
@objective(m,Min,sum(P_G[:,1:T].*F[1:N]*x[1:N]))                # Objective function
optimize!(m)                                                    # Solve

This leads to the following error: LoadError: InexactError: convert(Float64, 50 x[1]).

Approach 2: Define the feasible region for P_G as a constraint including x[1:N]:

m = Model(Cbc.Optimizer)                                        # Model
@variable(m, x[1:N])                                            # Unit activation
@variable(m, P_G[i=1:N,1:T] )                                   # Unit generation limit
for i in 1:T                                                    # Load balance
        @constraint(m, sum(P_G[:,i]) == P_D[i])
end
for i in 1:N                                                    # Unit generation limit
        for j in 1:T
                @constraint(m, P_C[i,1]*x[i] <= P_G[i,j] <= P_C[i,2]*x[i])
        end
end
@objective(m,Min,sum(P_G[:,1:T].*F[1:N]*x[1:N]))                # Objective function
optimize!(m)                                                    # Solve

This leads to: LoadError: [..] '@constraint(m, $(Expr(:escape, :(P_C[i, 1]))) * $(Expr(:escape, :(x[i]))) <= P_G[i, j] <= $(Expr(:escape, :(P_C[i, 2]))) * $(Expr(:escape, :(x[i]))))': Expected 50 x[1] to be a number.

NB: there might be more proper iteration methods but this should be idiot proof to Julia and JuMP newbies like me.

Working code without mixed-integer optimization

using JuMP, Cbc                 # Optimization and modelling
using Plots, LaTeXStrings       # Plotting

# DATA
P_C  = [50 200;                                         # Power capacity [:, (min, max)]
        25 200;
        100 200;
        120 500;
        10 500;
        20 500;
        200 800;
        200 800;
        100 800;
        200 1000;]
P_D = LinRange(sum(P_C[:,1]), sum(P_C[:,2]), 100)       # Power demand
F = rand(100:500,10)                                    # Random prod. prices
T = length(P_D)                                         # Number of time steps
N = length(P_C[:,1])                                    # Number of generators

# MODEL
m = Model(Cbc.Optimizer)                                # Model

@variable(m, x[1:N], Bin)                               # Unit activation
@variable(m, P_C[i,1] <= P_G[i=1:N,1:T] <= P_C[i,2])    # Unit generation limit
for i in 1:T                                            # Load balance
    @constraint(m, sum(P_G[:,i]) == P_D[i])
end
@objective(m,Min,sum(P_G[:,1:T].*F[1:N]))               # Objective function
optimize!(m)                                            # Solve

# PLOT
plt = plot(P_D[:],value.(P_G[:,1:T])', xlab = L"P_{load} [MW]", ylab = L"P_{unit} [MW]")
@show plt

Which should produce something similar:

enter image description here

The expected outcome of introducing the unit activation variable would be that each unit is not required to generate power in the the lower region of the P_load.

Preliminary

I have introduced the basics of the problem with success:

  • Objective function: Minimize the cost of power generation
  • Variable, P_G: for power generation (feasible region defined by min and max capacity, P_C)
  • Production cost, F (as constant only!)
  • Power demand, P_D, is set to be a linear space from the min power cap. to the max cap.

Mathematically expressed:

enter image description here


Solution

  • Variable bounds cannot include other variables. Do:

    m = Model(Cbc.Optimizer)
    @variable(m, x[1:N], Bin)
    @variable(m, P_G[i=1:N,1:T])
    @constraint(m, [i=1:N, t=1:T], P_C[i, 1] * x[i] <= P_G[i, t])
    @constraint(m, [i=1:N, t=1:T], P_G[i, t] <= P_C[I, 2] * x[i])