A logistics company needs to arrange forklifts for a newly built warehouse to meet daily operational demands. The forklift requirements for the warehouse over the next 7 weeks are 6, 9, 12, 8, 5, 7 and 4. The logistics company plans to lease forklifts from a rental company, which offers the following leasing options:

1. Long-term forklift rental: The lease term is fixed at 7 weeks, with a rental cost of 240 yuan per week. Forklifts under long-term lease are available for the entire lease period.
2. Short-term forklift rental: The lease term is flexible, available on a weekly basis, with a rental cost of 390 yuan per week. Short-term leased forklifts are only available during the week they are leased.
3. Shared forklifts: These are vehicles jointly leased with other warehouses, but they are only available in weeks 2, 4, and 5. The rental cost is 220 yuan per week.
4. Promotional forklifts: These forklifts can be leased at a discounted rate during the last 4 weeks, with a rental cost of 190 yuan per week. A maximum of 2 promotional forklifts can be leased per week.

Please design a leasing plan that fully meets the warehouse's forklift requirements over the next 7 weeks while minimizing the total leasing cost.

Problem type: ILP (Small: 16 variables, 14 constraints, 31 nonzeros)

Mathematical model:
Set:
1. Week
The set of weeks, \( W = \{1, 2, \dots, WeekNum\} \)

Parameter:
1. WeekNum
7
2. Demand
[6, 9, 12, 8, 5, 7, 4]
3. LongTermCost
240
4. LongTermWeekNum
7
5. ShortTermCost
390
6. SharedCost
220
7. SharedWeek
[2, 4, 5]
8. PromoCost
190
9. PromoMaxNum
2
10. PromoWeek
[4, 5, 6, 7]

Decision variable:
1. LongTermNum
Integer variable, \( LongTermNum \), where \( LongTermNum \) is the number of long-term forklifts leased.
2. ShortTermNum
Integer variable, \( ShortTermNum_{i} \forall i \in W\), where \( ShortTermNum_i \) is the number of short-term forklifts leased in week \( i \).
3. SharedNum
Integer variable, \( SharedNum \), where \( SharedNum \) is the number of shared forklifts leased.
4. PromoNum
Integer variable, \( PromoNum_{i} \forall i \in W\), where \( PromoNum_i \) is the number of promotional forklifts leased in week \( i \).

Objective:
1. Minimize the total leasing cost.
min: LongTermCost * LongTermNum * LongTermWeekNum + ShortTermCost * \sum_{i \in W} ShortTermNum_i + SharedCost * SharedNum * len(SharedWeek) + PromoCost * \sum_{i \in PromoWeek} PromoNum_i

Constraint:
1. The total number of forklifts leased must meet the demand for each week.
LongTermNum + ShortTermNum_i + PromoNum_i \geq Demand_i \forall i \in (W / SharedWeek)
2. The total number of forklifts leased must meet the demand for each week, considering shared forklifts.
LongTermNum + ShortTermNum_i + SharedNum + PromoNum_i \geq Demand_i \forall i \in SharedWeek
3. The number of promotional forklifts leased in each week must not exceed the maximum limit.
PromoNum_i \leq PromoMaxNum \forall i \in PromoWeek
4. The promotional forklifts can't be leased in weeks other than the promotional weeks.
PromoNum_i = 0 \forall i \in (W / PromoWeek)

Type:
Integer, Linear, Linear
ILP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB


def solve_forklift_leasing(
    demand=[6, 9, 12, 8, 5, 7, 4],
    long_term_cost=240,
    short_term_cost=390,
    shared_cost=220,
    shared_weeks=[2, 4, 5],
    promo_cost=190,
    promo_max_num=2,
    promo_weeks=[4, 5, 6, 7]):
    """
    Models and solves the forklift leasing optimization problem.
    """
    # --- 1. Model Creation ---
    model = gp.Model("ForkliftLeasing")

    # --- 2. Parameters & Sets ---
    week_num = len(demand)
    weeks = range(1, week_num + 1)
    long_term_weeks = week_num

    # --- 3. Decision Variables ---
    long_term_num = model.addVar(vtype=GRB.INTEGER, name="LongTermNum")
    short_term_num = model.addVars(weeks, vtype=GRB.INTEGER, name="ShortTermNum")
    shared_num = model.addVar(vtype=GRB.INTEGER, name="SharedNum")
    promo_num = model.addVars(weeks, vtype=GRB.INTEGER, name="PromoNum")

    # --- 4. Objective Function ---
    objective = long_term_cost * long_term_num * long_term_weeks
    objective += short_term_cost * gp.quicksum(short_term_num[i] for i in weeks)
    objective += shared_cost * shared_num * len(shared_weeks)
    objective += promo_cost * gp.quicksum(promo_num[i]
                                          for i in weeks if i in promo_weeks)
    model.setObjective(objective, GRB.MINIMIZE)

    # --- 5. Constraints ---
    # Constraint 1: Total forklifts per week must meet demand (non-shared weeks)
    for i in weeks:
        if i not in shared_weeks:
            model.addConstr(long_term_num + short_term_num[i] + promo_num[i]
                            >= demand[i - 1],
                            name=f"Demand_Week_{i}")

    # Constraint 2: Total forklifts during shared weeks must meet demand
    for i in shared_weeks:
        model.addConstr(long_term_num + short_term_num[i] + shared_num +
                        promo_num[i] >= demand[i - 1],
                        name=f"Demand_SharedWeek_{i}")

    # Constraint 3: Promotional forklift quantity must not exceed maximum limit
    for i in promo_weeks:
        model.addConstr(promo_num[i] <= promo_max_num, name=f"PromoLimit_Week_{i}")

    # Constraint 4: Non-promotional weeks cannot lease promotional forklifts
    for i in weeks:
        if i not in promo_weeks:
            model.addConstr(promo_num[i] == 0, name=f"NoPromo_Week_{i}")

    # --- 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}"}


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


Solution status: OPTIMAL
Optimal objective value: 14110