A company produces seven types of food containers, ranging in volume from 17 to 33 liters. The demand and size of each container are given in Table as follows: 

| Container Type | Volume (liters) | Demand (units) |
|----------------|-----------------|----------------|
| 1              | 17              | 500            |
| 2              | 19              | 400            |
| 3              | 21              | 300            |
| 4              | 23              | 250            |
| 5              | 25              | 200            |
| 6              | 29              | 150            |
| 7              | 33              | 100            |

The variable cost (in dollars) of producing each container is equal to its volume. A fixed cost of $1,000 is incurred to produce any of a particular container type. If the company desires, demand for a container may be satisfied by a container of larger size. Formulate and solve a shortest-path problem whose solution will minimize the cost of meeting the demand for food containers.

Problem type: MILP (Medium: 35 variables, 14 constraints, 63 nonzeros)

Mathematical model:
Set:
1. Containers
The set of container types, \( C = \{1, 2, ..., 7\} \)

Parameter:
1. Volume
The volume of each container type (in liters):
[17, 19, 21, 23, 25, 29, 33]

2. Demand
The demand for each container type (in units):
[500, 400, 300, 250, 200, 150, 100]

3. VariableCost
The variable cost of producing each container type (equals its volume in dollars):
[17, 19, 21, 23, 25, 29, 33]

4. FixedCost
The fixed cost of producing any container type:
1000

Decision variable:
1. Produce
Binary variable, \( Produce_j \forall j \in C \), where \( Produce_j = 1 \) if container type j is produced, 0 otherwise.

2. Assign
Integer variable, \( Assign_{i,j} \forall i,j \in C, i \leq j \), where \( Assign_{i,j} \) is the number of demand for container type i satisfied by container type j.

Objective:
1. Minimize the total cost of production.
min: \sum_{j \in C} (FixedCost * Produce_j + VariableCost[j] * \sum_{i \in C, i \leq j} Assign_{i,j})

Constraint:
1. Demand satisfaction constraint.
\sum_{j \in C, j \geq i} Assign_{i,j} = Demand[i] \forall i \in C

2. Production activation constraint.
\sum_{i \in C, i \leq j} Assign_{i,j} \leq M * Produce_j \forall j \in C
(where M is a sufficiently large number, such as the sum of all demands)

Type:
Mixed-integer, Linear, Linear
MIP


Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_container_optimization(
    volumes=[17, 19, 21, 23, 25, 29, 33],
    demands=[500, 400, 300, 250, 200, 150, 100],
    fixed_cost=1000):
    """
    Solves the container production and assignment optimization problem.
    """
    # --- 1. Model Creation ---
    model = gp.Model("Container_Optimization")

    # --- 2. Parameters & Sets ---
    container_types = range(len(volumes))
    variable_costs = volumes  # Variable cost equals volume

    # --- 3. Decision Variables ---
    # produce[j] = 1 if container type j is produced, 0 otherwise
    produce = model.addVars(container_types, vtype=GRB.BINARY, name="Produce")

    # assign[i, j] = number of units of demand type i satisfied by container type j
    assign_keys = [(i, j) for i in container_types for j in container_types
                   if j >= i]
    assign = model.addVars(assign_keys, vtype=GRB.INTEGER, name="Assign")

    # --- 4. Objective Function ---
    # Minimize total cost (fixed production costs + variable assignment costs)
    total_cost = gp.quicksum(fixed_cost * produce[j]
                             for j in container_types) + \
                 gp.quicksum(variable_costs[j] * assign[i, j]
                             for i, j in assign_keys)
    model.setObjective(total_cost, GRB.MINIMIZE)

    # --- 5. Constraints ---
    # Demand satisfaction: All demand for type i must be met.
    model.addConstrs(
        (assign.sum(i, '*') == demands[i] for i in container_types),
        name="Demand")

    # Production activation: If any containers of type j are used, we must incur the fixed cost.
    M = sum(demands)  # Big-M: an upper bound on the total number of containers of one type
    model.addConstrs(
        (assign.sum('*', j) <= M * produce[j] for j in container_types),
        name="Activation")

    # --- 6. Solve the Model ---
    model.optimize()

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


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

Solution status: OPTIMAL
Optimal objective value: 46700