'MILP using BigM Method for maintenance schedule - setting the production to 0

as mentioned in the title, I am looking to optimize a maintenance schedule with regard to cost using the bigM technique. The scheduler in itself seems to work just fine, but I want to add a constraint that the production (noted p in the code) has to be null during the maintenance period, tried a lot of things but can't seem to get it to work, anyone has an idea?

Thanks!

import matplotlib.pyplot as plt

import numpy as np

import pandas as pd
from IPython.display import display, HTML
import pyomo.environ as pyo

import shutil
import sys
import os.path

# problem parameters
T = 90        # planning period from 1..T
M = 5         # length of maintenance period
P = 4         # number of maintenance periods
N = 10        # minimum number of operational days between maintenance periods

# daily profits
c = {k:np.random.uniform() for k in range(1, T+1)}
p = {k:np.random.uniform() for k in range(1, T+1)}


def maintenance_planning_bigm(c, p, T, M, P, N):
    m = pyo.ConcreteModel()

    m.T = pyo.RangeSet(1, T)
    m.Z = pyo.RangeSet(1, T-1)

    m.Y = pyo.RangeSet(1, T - M + 1)
    m.S = pyo.RangeSet(0, M - 1)
    m.W = pyo.RangeSet(0, M+N-1)

    m.c = pyo.Param(m.T, initialize = c)
    m.p = pyo.Param(m.T, initialize = p)
    m.x = pyo.Var(m.T, domain=pyo.Binary)
    m.y = pyo.Var(m.T, domain=pyo.Binary)

    # objective
    m.profit = pyo.Objective(expr = sum(m.c[t]*m.x[t] for t in m.T), sense=pyo.maximize)

    # required number P of maintenance starts
    m.sumy = pyo.Constraint(expr = sum(m.y[t] for t in m.Y) == P)

    # no more than one maintenance start in the period of length M
    m.sprd = pyo.Constraint(m.Y, rule = lambda m, t: sum(m.y[t+s] for s in m.S) <= 1)

    # disjunctive constraints
    m.bigm = pyo.Constraint(m.Y, rule = lambda m, t: sum(m.x[t+s] for s in m.S) <= (M+N)*(1 - m.y[t]))
    
    
    return m
    
    
m = maintenance_planning_bigm(c, p, T, M, P, N)
pyo.SolverFactory('gurobi').solve(m, tee=False)

def plot_schedule(m):
    fig,ax = plt.subplots(4,1, figsize=(5,4))
    
    ax[0].bar(m.T, [m.c[t] for t in m.T])
    ax[0].set_title('daily profit $c_t$')
    
    ax[1].bar(m.T, [m.x[t]() for t in m.T], label='normal operation')
    ax[1].set_title('unit operating schedule $x_t$')
    
    ax[2].bar(m.Y, [m.y[t]() for t in m.Y])
    ax[2].set_title(str(P) + ' maintenance starts $y_t$')
    
    ax[3].bar(m.T, [m.p[t] for t in m.T])
    ax[3].set_title('production') 
    
    for a in ax:
        a.set_xlim(0.1, len(m.T)+0.9)
        
     
    
    plt.tight_layout()
    
    
    

plot_schedule(m)


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source