You are in charge of Green Freight, a logistics company that owns 5 old diesel trucks and plans to renew part of its fleet with new electric trucks to reduce costs and emissions. The company needs to decide which of the 5 old trucks to retire and may purchase up to 3 new electric trucks, while it must maintain a total fleet capacity of at least 4 trucks. The government imposes a punitive carbon tax on the company's total carbon emissions, which is proportional to the square of the total emissions, with a tax coefficient of 80. The company's goal is to make an optimal vehicle replacement decision to minimize the total operating cost for the coming year, which consists of vehicle costs, operating costs, and the punitive carbon tax. The specific vehicle information and cost data are shown in Table 1.

How should Green Freight decide which trucks to keep and which to buy to minimize its total annual cost?

Table 1: Vehicle Cost and Emission Data
| Vehicle Model | Attribute | Annual Operating Cost (¥) | Annual Carbon Emissions (tons) | Annualized Investment/Depreciation Cost (¥) |
| :--- | :--- | :--- | :--- | :--- |
| Old Diesel Truck D1 | - | 80,000 | 15 | - |
| Old Diesel Truck D2 | - | 85,000 | 16 | - |
| Old Diesel Truck D3 | - | 78,000 | 14 | - |
| Old Diesel Truck D4 | - | 92,000 | 18 | - |
| Old Diesel Truck D5 | - | 88,000 | 17 | - |
| New Electric Truck | (per vehicle) | 30,000 | 0 | 120,000 |

Problem type: NLP (Small: 6 variables, 2 constraints, 7 nonzeros)

Mathematical model:
Set:
1.  OldTrucks
    The set of old diesel trucks, \( D = \{1, 2, 3, 4, 5\} \)

Parameter:
1.  AnnualOperatingCostOld
    [80000, 85000, 78000, 92000, 88000] # Annual operating cost for each old diesel truck in ¥
2.  AnnualCarbonEmissionsOld
    [15, 16, 14, 18, 17] # Annual carbon emissions for each old diesel truck in tons
3.  AnnualOperatingCostNew
    30000 # Annual operating cost per new electric truck in ¥
4.  AnnualizedInvestmentNew
    120000 # Annualized investment cost per new electric truck in ¥
5.  CarbonTaxCoefficient
    80 # Coefficient for the carbon tax calculation
6.  MinFleetSize
    4 # Minimum number of trucks required in the fleet
7.  MaxNewTrucks
    3 # Maximum number of new electric trucks that can be purchased

Decision variable:
1.  KeepOldTruck
    Binary variable, \( KeepOldTruck[d] \forall d \in D \), equals 1 if old truck \( d \) is kept, 0 otherwise.
2.  BuyNewTrucks
    Integer variable, \( BuyNewTrucks \), the number of new electric trucks to purchase.

Objective:
1.  Minimize the total annual cost.
    min: \( \sum_{d \in D} (AnnualOperatingCostOld[d] \cdot KeepOldTruck[d]) + (AnnualOperatingCostNew + AnnualizedInvestmentNew) \cdot BuyNewTrucks + CarbonTaxCoefficient \cdot (\sum_{d \in D} (AnnualCarbonEmissionsOld[d] \cdot KeepOldTruck[d]))^2 \)

Constraint:
1.  Minimum fleet size constraint.
    \( \sum_{d \in D} KeepOldTruck[d] + BuyNewTrucks \geq MinFleetSize \)
2.  New truck purchase limit.
    \( BuyNewTrucks \leq MaxNewTrucks \)
3.  Variable domain constraints.
    \( KeepOldTruck[d] \in \{0, 1\} \forall d \in D \)
    \( BuyNewTrucks \geq 0 \), and integer

Type:
Integer, Non-linear, Linear
NLP

Gurobi implementation:
import gurobipy as gp
from gurobipy import GRB

def solve_green_freight_minlp(
    old_trucks=['D1', 'D2', 'D3', 'D4', 'D5'],
    annual_op_cost_old={
        'D1': 80000, 'D2': 85000, 'D3': 78000, 'D4': 92000, 'D5': 88000
    },
    annual_emissions_old={
        'D1': 15, 'D2': 16, 'D3': 14, 'D4': 18, 'D5': 17
    },
    annual_op_cost_new=30000,
    annualized_investment_new=120000,
    carbon_tax_coeff=80,
    min_fleet_size=4,
    max_new_trucks=3
):
    """
    Solves the Green Freight vehicle replacement problem to minimize total annual cost.
    This is a Mixed-Integer Non-Linear Programming (MINLP) problem due to the
    quadratic term in the carbon tax calculation.
    """
    # Create a new model
    model = gp.Model("GreenFreight")

    # --- Decision Variables ---
    # Binary variable: 1 if an old truck is kept, 0 if retired
    keep_old_truck = model.addVars(old_trucks, vtype=GRB.BINARY, name="KeepOldTruck")

    # Integer variable: number of new electric trucks to buy
    buy_new_trucks = model.addVar(vtype=GRB.INTEGER, name="BuyNewTrucks", lb=0)

    # --- Objective Function: Minimize Total Annual Cost ---
    
    # 1. Cost of operating the old trucks that are kept
    cost_kept_trucks = gp.quicksum(annual_op_cost_old[d] * keep_old_truck[d] 
                                   for d in old_trucks)

    # 2. Cost (operating + investment) of new trucks
    cost_new_trucks = (annual_op_cost_new + annualized_investment_new) * buy_new_trucks

    # 3. Punitive carbon tax (non-linear part)
    total_emissions = gp.quicksum(annual_emissions_old[d] * keep_old_truck[d] 
                                  for d in old_trucks)
    carbon_tax = carbon_tax_coeff * total_emissions * total_emissions

    model.setObjective(
        cost_kept_trucks + cost_new_trucks + carbon_tax,
        GRB.MINIMIZE
    )

    # --- Constraints ---
    
    # 1. Minimum fleet size constraint
    model.addConstr(keep_old_truck.sum('*') + buy_new_trucks >= min_fleet_size, 
                    name="MinFleetSize")

    # 2. New truck purchase limit
    model.addConstr(buy_new_trucks <= max_new_trucks, 
                    name="MaxNewTrucks")

    # The domain of the variables (Binary, Integer, >=0) is already set during their creation.

    # Optimize the model
    model.optimize()

    # --- 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_green_freight_minlp()
    print(result)

Solution status: OPTIMAL
Optimal objective value: 525280