简体   繁体   中英

if condition in Gurobi Python Objective Function

I have an objective function with if condition. I am having trouble implementing it in Gurobi Python.

Background information: there are multiple items (1,5). LP need to generate a production plan for 12 months on how to replenish these items to meet the demand (uniformly distributed) in a way that the cost of units remaining in inventory (I) and the shortage (B) is minimized. The if condition in the objective function says that for each item there is either shortage or inventory. If either is the case, safety stock needs to be reduced from it before multiplying the unit cost. My objective function is:

目标函数

My main constraints are C1, C2, and C3. C2 and C3 vary based on item type. I added C4 to implement the condition in the objective function but it seems something is wrong. The constraints are:

约束条件

I have the code as below but it does not work with the fourth condition:

import numpy as np
import pandas as pd
import random

import gurobipy as gp
from gurobipy import GRB

#Parameters

items = ["item1", "item2", "item3", "item4", "item5"]
months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]

revenue = {"item1":10, "item2":10, "item3":0, "item4":0, "item5":0}
cost_assembly = {"item1":2, "item2":2, "item3":0, "item4":0, "item5":0}
cost_replenish = {"item1":0, "item2":0, "item3":1, "item4":1, "item5":1}
cost_inventory = {"item1":1, "item2":1, "item3":0.5, "item4":0.5, "item5":0.5}
cost_backlog = {"item1":10, "item2":10, "item3":0, "item4":0, "item5":0}

material_req = {"item1": {"item1": 0, "item2":0, "item3": 0, "item4":0, "item5": 0},
                "item2": {"item1": 0, "item2":0, "item3": 0, "item4":0, "item5": 0},
                "item3": {"item1": 1, "item2":0, "item3": 0, "item4":0, "item5": 0},
                "item4": {"item1": 1, "item2":1, "item3": 0, "item4":0, "item5": 0},
                "item5": {"item1": 0, "item2":1, "item3": 0, "item4":0, "item5": 0}}

safety_stock = {"item1":5, "item2":5, "item3":10, "item4":15, "item5":10}
lead_time = {"item1":1, "item2":1, "item3":1, "item4":1, "item5":1}

forecast = {
    "Jan": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Feb": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Mar": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Apr": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "May": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Jun": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Jul": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Aug": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Sep": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Oct": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Nov": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0},
    "Dec": {"item1": 10, "item2": 20, "item3":0, "item4":0, "item5":0}
}


demand = {
    "Jan": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Feb": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Mar": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Apr": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "May": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Jun": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Jul": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Aug": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Sep": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Oct": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Nov": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0},
    "Dec": {"item1": 10 + random.randint(-5,5), "item2": 20 + random.randint(-5,5), "item3":0, "item4":0, "item5":0}
}
demand
LP = gp.Model("Production Planning")
#Variables
I = LP.addVars(months, items, name = "Inventory") #units at inventory
B = LP.addVars(months, items, name = "Backlog") #units short for products (cost of shortage of material is 0)
R = LP.addVars(months, items, lb = 0 ,name = "Orders") #order of material or assembly of products
R[months[months.index("Jan") -1], "item2"]
#Constraints
Constraint1 = LP.addConstrs((B[month, item] - B[months[months.index(month) -1], item] - forecast[month][item]<= 0
                            for month in months
                            for item in items
                            if month != month[0] or month[1]), name = "C1")

Constraint2 = LP.addConstrs((I[month, item] - B[month, item] -
                            I[months[months.index(month) -1], item] + B[months[months.index(month) -1], item] -
                            R[months[months.index(month) -2], item] + forecast[month][items[items.index(item) -1]] == 0
                            for month in months
                            for item in items
                            if item == item[0] or item[1]
                            if month != month[0] or month[1]), name = "C2")

for item in items:
    if item != item[0] or item[1]:
        for month in months:
            if month != month[0]:
                Constraint3 = LP.addConstr((I[month, item] - I[months[months.index(month) -1], item] -
                                             R[months[months.index(month) -2], item] + 
                                             material_req[item]["item1"] * R[months[months.index(month) -1], "item1"] + 
                                             material_req[item]["item2"] * R[months[months.index(month) -1], "item2"] == 0), name = "C3")
                
Y = [LP.addVar(vtype= "B")]
for I, Y_I in enumerate(Y):
    for B, Y_B in enumerate(Y):
        LP.addConstr((Y_I + Y_B == 1  ), name = "C4")
#Objective Function
obj = gp.quicksum(cost_inventory[item] * (Y_I * (I[month,item] - safety_stock[item])) +
                  cost_backlog[item] * (Y_B * (B[month,item] - safety_stock[item]))
                  for month in months
                  for item in items)


LP.setObjective(obj, GRB.MINIMIZE)

If I understand your question correctly, it seems like you are asking how to convert an objective function that has a conditional into a linear function. It seems like you are already doing that thought, using "indicator variables."

Given the complexity of your code and not knowing your exact error message it is difficult to provide you with specific assistance, my advice would be to try to simplify your code and have fewer nested loop comprehensions with conditionals inside of the addVars , then hopefully you can see your error, if not post an edit here again.

My guess is that it has something to do with those conditionals inside the comprehensions, with Gurobi thinking you are adding a "varying conditional" when you mean to add a "static conditional" (see this ).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM