A company has three industries located in different locations and needs to deliver goods to five shops in different locations. The delivery costs from the first industry to the shops are 4, 9, 2, 6, and 5, respectively, with a storage capacity of 60. The delivery costs from the second industry to the shops are 2, 6, 1, 7, and 9, respectively, with a storage capacity of 30. The delivery costs from the third industry to the shops are 2, 4, 9, 8, and 3, respectively, with a storage capacity of 45. The demands of the five shops are 15, 35, 20, 5, and 40. How can the goods be transported to minimize the cost?

Problem type: ILP (Small: 15 variables, 8 constraints, 30 nonzeros)

Mathematical model:
Set:
1. Industries
The set of industries, \( I = \{1, 2, \dots, IndustryNum\} \)
2. Shops
The set of shops, \( S = \{1, 2, \dots, ShopNum\} \)

Parameter:
1. IndustryNum
3
2. ShopNum
5
3. IndustryStorage
[60, 30, 45]
4. ShopDemand
[15, 35, 20, 5, 40]
5. TransportationCost(row: industry, column: shop)
[[4, 9, 2, 6, 5], 
 [2, 6, 1, 7, 9], 
 [2, 4, 9, 8, 3]]

Decision variable:
1. Transportation
Integer variable, \( t_{ij} \geq 0 \) for all \( i \in I, j \in S \), representing the amount of goods transported from industry \( i \) to shop \( j \)

Objective:
The total transportation cost
min: \sum_{i\in I}\sum_{j\in S}TransportationCost_{ij}\cdot t_{ij}

Constraint:
1. Industry storage capacity
\sum_{j\in S}t_{ij} \leq IndustryStorage_i, \forall i \in I
2. Shop demand
\sum_{i\in I}t_{ij} = ShopDemand_j, \forall j \in S

Type:
Integer, linear, Linear
ILP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_transportation_problem(
    industry_storage=[60, 30, 45],
    shop_demand=[15, 35, 20, 5, 40],
    transportation_cost=[
        [4, 9, 2, 6, 5],
        [2, 6, 1, 7, 9],
        [2, 4, 9, 8, 3]
    ]
):
    """
    Models and solves the classic transportation problem.
    """
    # --- 1. Model Creation ---
    model = gp.Model("TransportationProblem")

    # --- 2. Sets and Parameters ---
    # Derive dimensions from the input data for robustness
    industries = range(len(industry_storage))
    shops = range(len(shop_demand))

    # --- 3. Decision Variables ---
    # t[i, j] = amount transported from industry i to shop j
    t = model.addVars(industries, shops, vtype=GRB.INTEGER, name="transport")

    # --- 4. Objective Function ---
    # Minimize total transportation cost
    model.setObjective(
        gp.quicksum(transportation_cost[i][j] * t[i, j] for i in industries for j in shops),
        GRB.MINIMIZE
    )

    # --- 5. Constraints ---
    # Constraint 1: Supply constraint for each industry
    for i in industries:
        model.addConstr(gp.quicksum(t[i, j] for j in shops) <= industry_storage[i],
                        name=f"supply_{i}")

    # Constraint 2: Demand constraint for each shop
    for j in shops:
        model.addConstr(gp.quicksum(t[i, j] for i in industries) == shop_demand[j],
                        name=f"demand_{j}")

    # --- 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 {"status": f"{model.status}"}


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

Solution status: OPTIMAL
Optimal objective value: 405