A logistics company needs to schedule deliveries for 8 customer orders using 3 available trucks. Each order has a specific processing time (hours) and must be assigned to exactly one truck. Some orders require multiple visits to the same truck (reentrant processing) due to intermediate handling requirements. The trucks have different capacities (maximum total processing time they can handle) and operating costs per hour. The objective is to minimize the total operating cost while ensuring no truck exceeds its capacity and all orders are completed. 

Order details:
- Order processing times: [4, 5, 3, 6, 2, 5, 4, 3]
- Reentrant requirements: Orders 2 and 5 must be processed twice by their assigned truck
- Truck capacities: [15, 18, 12] hours
- Truck operating costs: [30, 25, 35] per hour

Problem type: ILP (Medium: 27 variables, 14 constraints, 75 nonzeros)

Mathematical model:
Set:
1. Orders
The set of Orders, \( O = \{1, 2, ..., 8\} \)
2. Trucks
The set of Trucks, \( T = \{1, 2, 3\} \)

Parameter:
1. ProcessingTime
[4, 5, 3, 6, 2, 5, 4, 3] (hours for each order)
2. ReentrantFactor
[1, 2, 1, 1, 2, 1, 1, 1] (number of times each order must be processed)
3. TruckCapacity
[15, 18, 12] (maximum total processing hours per truck)
4. OperatingCost
[30, 25, 35] (cost per hour for each truck)

Decision variable:
1. Assignment
Binary variable \( x_{ot} \in \{0, 1\} \) for all \( o \in O, t \in T \), where \( x_{ot} = 1 \) if order \( o \) is assigned to truck \( t \), and \( x_{ot} = 0 \) otherwise
2. TruckUsed
Binary variable \( y_t \in \{0, 1\} \) for all \( t \in T \), where \( y_t = 1 \) if truck \( t \) is used, and \( y_t = 0 \) otherwise

Objective:
Minimize total operating cost
min: \sum_{t\in T} \left( \sum_{o\in O} ProcessingTime_o \cdot ReentrantFactor_o \cdot x_{ot} \right) \cdot OperatingCost_t

Constraint:
1. Each order must be assigned to exactly one truck
\sum_{t\in T}x_{ot} = 1, \forall o \in O
2. Total processing time on each truck must not exceed its capacity
\sum_{o\in O} ProcessingTime_o \cdot ReentrantFactor_o \cdot x_{ot} \leq TruckCapacity_t, \forall t \in T
3. Truck usage indicator
\sum_{o\in O}x_{ot} \leq M \cdot y_t, \forall t \in T (where M is a large constant)

Type:
Integer, Linear, Linear
ILP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_logistics_problem(
    orders=list(range(1, 9)),
    trucks=list(range(1, 4)),
    processing_time=[4, 5, 3, 6, 2, 5, 4, 3],
    reentrant_factor=[1, 2, 1, 1, 2, 1, 1, 1],
    truck_capacity=[15, 18, 12],
    operating_cost=[30, 25, 35]
):
    """Solve the truck scheduling problem with reentrant processing requirements."""
    model = gp.Model("LogisticsScheduling")

    x = model.addVars(orders, trucks, vtype=GRB.BINARY, name="Assign")
    y = model.addVars(trucks, vtype=GRB.BINARY, name="TruckUsed")

    model.setObjective(
        gp.quicksum(
            gp.quicksum(
                processing_time[o - 1] * reentrant_factor[o - 1] * x[o, t] * operating_cost[t - 1]
                for o in orders
            )
            for t in trucks
        ),
        GRB.MINIMIZE
    )

    model.addConstrs((gp.quicksum(x[o, t] for t in trucks) == 1 for o in orders))

    model.addConstrs(
        (gp.quicksum(
            processing_time[o - 1] * reentrant_factor[o - 1] * x[o, t]
            for o in orders
        ) <= truck_capacity[t - 1]
        for t in trucks),
        name="Capacity"
    )

    M = len(orders)
    model.addConstrs((gp.quicksum(x[o, t] for o in orders) <= M * y[t] for t in trucks))

    model.optimize()

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


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


Solution status: OPTIMAL
Optimal objective value: 1110