A company has three warehouses storing three products with inventory: Warehouse 1 (600, 900, 750), Warehouse 2 (500, 1500, 1200), Warehouse 3 (800, 1100, 100). These products must be shipped to seven sales locations with demands: Location 1 (200, 400, 300), Location 2 (300, 800, 50), Location 3 (200, 300, 50), Location 4 (75, 250, 80), Location 5 (600, 700, 200), Location 6 (225, 850, 100), Location 7 (300, 200, 200). Transportation costs vary by product, warehouse, and destination: For Warehouse 1, the costs per unit are Product 1: 30, 10, 8, 10, 11, 71, 6 for Locations 1–7; Product 2: 39, 14, 11, 14, 16, 82, 8 for Locations 1–7; and Product 3: 41, 15, 12, 16, 17, 86, 8 for Locations 1–7. For Warehouse 2, the costs per unit are Product 1: 22, 7, 10, 7, 21, 82, 13 for Locations 1–7; Product 2: 27, 9, 12, 9, 26, 95, 17 for Locations 1–7; and Product 3: 29, 9, 13, 9, 28, 99, 18 for Locations 1–7. For Warehouse 3, the costs per unit are Product 1: 19, 11, 12, 10, 25, 83, 15 for Locations 1–7; Product 2: 24, 14, 17, 13, 28, 99, 20 for Locations 1–7; and Product 3: 26, 14, 17, 13, 31, 104, 20 for Locations 1–7. And shipments from any warehouse to any location cannot exceed 625 units. How to allocate shipments to minimize total transportation cost?

Problem type: ILP (Medium: 63 variables, 51 constraints, 189 nonzeros)

Mathematical model:
Set:
1. Warehouses
The set of warehouses, \( W = \{1, 2, \dots, WarehouseNum\} \)
2. SalesLocations
The set of sales locations, \( L = \{1, 2, \dots, LocationNum\} \)
3. Products
The set of products, \( P = \{1, 2, \dots, ProductNum\} \)

Parameter:
1. WarehouseNum
3
2. LocationNum
7
3. ProductNum
3
4. WarehouseStorage
[[800, 900, 750], [500, 1500, 1200], [800, 110, 100]]
5. LocationDemand
[[200, 400, 300], [300, 800, 50], [200, 300, 50], [75, 250, 80], [600, 900, 200], [225, 850, 100], [300, 500, 200]]
6. TransportationCost(warehouse: location: product)
[[[30, 39, 41], [10, 14, 15], [8, 11, 12], [10, 14, 16], [11, 16, 17], [71, 82, 86], [6, 8, 8]], 
 [[22, 27, 29], [7, 9, 9], [10, 12, 13], [7, 9, 9], [21, 26, 28], [82, 95, 99], [13, 17, 18]], 
 [[19, 24, 26], [11, 14, 14], [12, 17, 17], [10, 13, 13], [25, 28, 31], [83, 99, 104], [15, 20, 20]]]

Decision variable:
1. Transportation
Integer variable, \( t_{ijp} \geq 0 \) for all \( i \in W, j \in L, p \in P \), representing the amount of product \( p \) transported from warehouse \( i \) to sales location \( j \)

Objective:
The total transportation costs
min: \sum_{i\in W}\sum_{j\in L}\sum_{p\in P}TransportationCost_{ijp}\cdot t_{ijp}

Constraint:
1. Warehouse storage capacity
\sum_{j\in L}t_{ijp} \leq WarehouseStorage_{ip}, \forall i \in W, p \in P
2. Sales location demand
\sum_{i\in W}t_{ijp} = LocationDemand_{jp}, \forall j \in L, p \in P
3. Shipment limit
\sum_{p\in P}t_{ijp} \leq 625, \forall i \in W, j \in L

Type:
Integer, Linear, Linear
ILP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_multi_product_transportation(
    warehouse_storage=[
        [600, 900, 750],
        [500, 1500, 1200],
        [800, 1100, 100]
    ],
    location_demand=[
        [200, 400, 300],
        [300, 800, 50],
        [200, 300, 50],
        [75, 250, 80],
        [600, 700, 200],
        [225, 850, 100],
        [300, 200, 200]
    ],
    transportation_cost=[
        [[30, 39, 41], [10, 14, 15], [8, 11, 12], [10, 14, 16], [11, 16, 17], [71, 82, 86], [6, 8, 8]],
        [[22, 27, 29], [7, 9, 9], [10, 12, 13], [7, 9, 9], [21, 26, 28], [82, 95, 99], [13, 17, 18]],
        [[19, 24, 26], [11, 14, 14], [12, 17, 17], [10, 13, 13], [25, 28, 31], [83, 99, 104], [15, 20, 20]]
    ],
    max_one_shipment=625
):
    """
    Models and solves the multi-product transportation problem.
    """
    # --- 1. Model Creation ---
    model = gp.Model("WarehouseTransportation")

    # --- 2. Sets ---
    # Derive sets from the dimensions of the input data
    warehouses = range(len(warehouse_storage))
    locations = range(len(location_demand))
    products = range(len(warehouse_storage[0]))

    # --- 3. Decision Variables ---
    # t[i, j, p] = amount of product p transported from warehouse i to location j
    t = model.addVars(warehouses, locations, products, vtype=GRB.INTEGER, lb=0, name="transport")

    # --- 4. Objective Function ---
    # Minimize total transportation cost
    objective = gp.quicksum(transportation_cost[i][j][p] * t[i, j, p]
                           for i in warehouses
                           for j in locations
                           for p in products)
    model.setObjective(objective, GRB.MINIMIZE)

    # --- 5. Constraints ---
    # Constraint 1: Warehouse storage capacity
    for i in warehouses:
        for p in products:
            model.addConstr(gp.quicksum(t[i, j, p] for j in locations) <= warehouse_storage[i][p],
                           name=f"warehouse_capacity_{i+1}_{p+1}")

    # Constraint 2: Sales location demand must be met
    for j in locations:
        for p in products:
            model.addConstr(gp.quicksum(t[i, j, p] for i in warehouses) == location_demand[j][p],
                           name=f"location_demand_{j+1}_{p+1}")

    # Constraint 3: Shipment limit for each warehouse-location pair
    for i in warehouses:
        for j in locations:
            model.addConstr(gp.quicksum(t[i, j, p] for p in products) <= max_one_shipment,
                           name=f"shipment_limit_{i+1}_{j+1}")

    # --- 6. Solve the Model ---
    model.setParam("OutputFlag", 0)  # Suppress Gurobi output
    model.optimize()

    # --- 7. Return Results ---
    if model.status == GRB.OPTIMAL:
        return {"status": "optimal", "obj": model.ObjVal}
    else:
        # Return the Gurobi status code if no optimal solution is found
        return {"status": f"{model.status}"}


# Run the solver function
if __name__ == "__main__":
    result = solve_multi_product_transportation()
    print(result)

Solution status: OPTIMAL
Optimal objective value: 181320