HealthSupply Co. manages a medical supply chain that must fulfill demand for two types of products, Vaccine X and Vaccine Y, over the next two quarters, with demands of 100 doses of Vaccine X and 200 doses of Vaccine Y in Quarter 1, and 300 doses of Vaccine X and 100 doses of Vaccine Y in Quarter 2. The company can produce a maximum of 1,500 doses per quarter, with each dose of Vaccine X requiring 4 liters of raw biochemical material and each dose of Vaccine Y requiring 3 liters. The cost of raw material is $300 per liter in Quarter 1 and $450 per liter in Quarter 2, with a maximum purchase limit of 2,500 liters per quarter, and material can only be used in the quarter it is purchased. At the start of Quarter 1, the company has an inventory of 200 doses of Vaccine X and 300 doses of Vaccine Y, and a storage cost of $100 per dose is assessed at the end of each quarter for remaining inventory. Additionally, the company must meet a regulatory requirement that the vaccines produced each quarter have an average efficacy rate of at least 90%, with Vaccine X having an efficacy rate of 85% and Vaccine Y having an efficacy rate of 95%. How to meet the demand and regulatory requirements at minimum cost, including raw material and storage costs.

Problem type: MILP (Small: 10 variables, 12 constraints, 26 nonzeros)

Mathematical model:
Set:
1. Product
The set of products, \( P = \{1, 2\} \)  # 1: Vaccine X, 2: Vaccine Y
2. Quarter
The set of quarters, \( Q = \{1, 2\} \)  # 1: Quarter 1, 2: Quarter 2

Parameter:
1. Demand
[[100, 200], [300, 100]] # Demand for each product in each quarter
2. MaxProductionPerQuarter
[1500, 1500]
3. RawMaterialCost
[300, 450]
4. RawMaterialPerProduct
[4, 3]
5. MaxRawMaterialPurchase
[2500, 2500]
6. InitialInventory
[[200, 300], [0, 0]] # Initial inventory for each product in each quarter
7. StorageCost
[100, 100] # Storage cost per dose at the end of each quarter
8. EfficacyRate
[0.85, 0.95] # Efficacy rate for each product
9. RegulatoryEfficacyRate
0.90

Decision variable:
1. RawMaterialPurchased
Continous variable, \( RawMaterialPurchased[q] \forall q \in Q \), the amount of raw material purchased in quarter \( q \) in liters.
2. ProductProduced
Integer variable, \( ProductProduced[p][q] \forall p \in P, q \in Q \), the amount of product \( p \) produced in quarter \( q \) in doses.
3. ProductStorage
Integer variable, \( ProductStorage[p][q] \forall p \in P, q \in Q \), the amount of product \( p \) stored at the end of quarter \( q \) in doses.

Objective:
1. Minimize the total cost.
min: \sum_{q \in Q} (RawMaterialCost[q] * RawMaterialPurchased[q] + StorageCost[q] * ProductStorage[p][q] \forall p \in P)

Constraint:
1. Demand constraint.
ProductProduced[p][1] + InitialInventory[p] - ProductStorage[p][1] \geq Demand[p][1] \forall p \in P
ProductProduced[p][q] + ProductStorage[p][q-1] - ProductStorage[p][q] \geq Demand[p][q] \forall p \in P, q \in Q/{1}
2. Production capacity constraint.
\sum_{p \in P} ProductProduced[p][q] \leq MaxProductionPerQuarter[q] \forall q \in Q
3. Raw material constraint.
\sum_{p \in P} RawMaterialPerProduct[p] * ProductProduced[p][q] \leq RawMaterialPurchased[q] \forall q \in Q
4. Raw material purchase limit constraint.
RawMaterialPurchased[q] \leq MaxRawMaterialPurchase[q] \forall q \in Q
5. Regulatory efficacy constraint.
\sum_{p \in P} EfficacyRate[p] * ProductProduced[p][q] \geq \sum_{p \in P} ProductProduced[p][q] * RegulatoryEfficacyRate \forall q \in Q
6. Non-negativity constraint.
ProductProduced[p][q] \geq 0 \forall p \in P, q \in Q
ProductStorage[p][q] \geq 0 \forall p \in P, q \in Q
RawMaterialPurchased[q] \geq 0 \forall q \in Q

Type:
Mixed, Linear, Linear
MILP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_vaccine_production_optimization(
    Demand=[[100, 200], [300, 100]],
    MaxProductionPerQuarter=[1500, 1500],
    RawMaterialCost=[300, 450],
    RawMaterialPerProduct=[4, 3],
    MaxRawMaterialPurchase=[2500, 2500],
    InitialInventory=[200, 300],
    StorageCost=[100, 100],
    EfficacyRate=[0.85, 0.95],
    RegulatoryEfficacyRate=0.90
):
    """
    Models and solves the vaccine production optimization problem.
    """
    # Create a new model
    model = gp.Model("HealthSupply_Vaccine_Production")

    # Sets
    P = range(len(EfficacyRate))  # Products
    Q = range(len(MaxProductionPerQuarter))  # Quarters

    # Decision Variables
    RawMaterialPurchased = model.addVars(Q, lb=0.0, name="RawMaterialPurchased")
    ProductProduced = model.addVars(P, Q, vtype=GRB.INTEGER, lb=0, name="ProductProduced")
    ProductStorage = model.addVars(P, Q, vtype=GRB.INTEGER, lb=0, name="ProductStorage")

    # Objective Function: Minimize total cost
    raw_material_cost = gp.quicksum(RawMaterialCost[q] * RawMaterialPurchased[q] for q in Q)
    storage_cost = gp.quicksum(StorageCost[q] * ProductStorage[p, q] for p in P for q in Q)
    total_cost = raw_material_cost + storage_cost

    model.setObjective(total_cost, GRB.MINIMIZE)

    # Constraints
    # 1. Demand constraints
    for p in P:
        # First quarter uses initial inventory
        model.addConstr(
            ProductProduced[p, 0] + InitialInventory[p] - ProductStorage[p, 0] >= Demand[0][p],
            f"Demand_P{p}_Q1"
        )

    for p in P:
        # Second quarter uses storage from first quarter
        model.addConstr(
            ProductProduced[p, 1] + ProductStorage[p, 0] - ProductStorage[p, 1] >= Demand[1][p],
            f"Demand_P{p}_Q2"
        )

    # 2. Production capacity constraints
    for q in Q:
        model.addConstr(
            gp.quicksum(ProductProduced[p, q] for p in P) <= MaxProductionPerQuarter[q],
            f"ProductionCapacity_Q{q+1}"
        )

    # 3. Raw material constraints
    for q in Q:
        model.addConstr(
            gp.quicksum(RawMaterialPerProduct[p] * ProductProduced[p, q] for p in P) <= RawMaterialPurchased[q],
            f"RawMaterial_Q{q+1}"
        )

    # 4. Raw material purchase limit constraints
    for q in Q:
        model.addConstr(
            RawMaterialPurchased[q] <= MaxRawMaterialPurchase[q],
            f"RawMaterialPurchaseLimit_Q{q+1}"
        )

    # 5. Regulatory efficacy constraints
    for q in Q:
        total_produced = gp.quicksum(ProductProduced[p, q] for p in P)
        weighted_efficacy = gp.quicksum(EfficacyRate[p] * ProductProduced[p, q] for p in P)

        model.addConstr(
            weighted_efficacy >= RegulatoryEfficacyRate * total_produced,
            f"RegulatoryEfficacy_Q{q+1}"
        )

    # Optimize the model
    model.optimize()

    # Return Results
    if model.status == GRB.OPTIMAL:
        return {"status": "optimal", "obj": model.ObjVal}
    else:
        return {"status": f"{model.status}"}


if __name__ == "__main__":
    result = solve_vaccine_production_optimization()
    print(result)


Solution status: OPTIMAL
Optimal objective value: 460000