如何修改Docplex模型的约束与目标函数以适配无限数量卡车类型,实现订单总成本最小化
Got it, let's tackle this problem. The original model treats each truck type as a single vehicle—so assigning multiple orders to the same type tries to cram all those orders onto one truck, and it charges the truck's cost for every order assigned to it, which isn't right when you can use unlimited trucks of each type. Here's how to adjust the model properly:
Key Issues with the Original Model
- Incorrect Cost Calculation: It adds the truck's cost for every order assigned to the type, not for each truck actually used.
- Missing Capacity Checks: There's no guardrail to ensure the total weight of orders assigned to a type fits into the number of trucks deployed for that type.
- Implicit Single Truck Assumption: No variable tracks how many trucks of each type we're actually using.
Modified Solution Approach
We'll rework the decision variables, objective function, and constraints to account for unlimited trucks per type:
Step 1: Redefine Decision Variables
We need two sets of variables to separate assignment from fleet size:
num_trucks[f]: Non-negative integer variable representing how many trucks of typefwe'll deploy.assign[o,f]: Binary variable (1 if orderois assigned to a truck of typef, 0 otherwise).
Step 2: Update the Objective Function
Instead of charging per order-type assignment, we charge per truck used. The objective becomes minimizing the total cost of all trucks we deploy:
mdl.minimize(mdl.sum(num_trucks[f] * get_truck_type(f).TruckCost for f in truck_types))
Step 3: Adjust Constraints
- Keep the "Each Order Assigned to Exactly One Type" Constraint: This part was correct—every order needs to go to some truck type.
- Add Capacity Constraint: For each truck type, the total weight of orders assigned to it must not exceed the total capacity of all trucks we use for that type:
for f in truck_types: total_weight = mdl.sum(assign[o,f] * get_order(o).Weight for o in orders) mdl.add_constraint(total_weight <= num_trucks[f] * get_truck_type(f).Capacity, f"Capacity_Constraint_{f}")
Full Modified Code
import pandas as pd import docplex.mp from docplex.mp.model import Model df_order = pd.DataFrame([[1,5000],[2,1000],[3,2000]], columns =['OrderID','Weight']) orders = df_order['OrderID'].values.tolist() df_order.set_index('OrderID', inplace=True) df_truck_types = pd.DataFrame([[1,'TYPE1',20000,'SP TRANSPORTS',40000],[2,'TYPE2',20000,'SP TRANSPORTS',40000],[3,'TYPE3',10000,'SP TRANSPORTS',30000]], columns =['TruckTypeID','VehicleType','Capacity','Transporter','TruckCost']) truck_types = df_truck_types['TruckTypeID'].values.tolist() df_truck_types.set_index('TruckTypeID', inplace=True) def get_order(o): return df_order.loc[o] def get_truck_type(f): return df_truck_types.loc[f] # Decision Variables - Updated for unlimited trucks mdl = Model(name='itc_load_planning') assign = mdl.binary_var_matrix(orders, truck_types, name='Assign_Order_To_TruckType') num_trucks = mdl.integer_var_dict(truck_types, name='Num_Trucks_Of_Type', lb=0) # Objective Function - Now based on number of trucks used, not per order assignment mdl.minimize(mdl.sum(num_trucks[f] * get_truck_type(f).TruckCost for f in truck_types)) # C1: Each order is assigned to exactly one truck type for o in orders: mdl.add_constraint(mdl.sum(assign[o,f] for f in truck_types)==1, f"Assign_Order_{o}") # Capacity Constraint: Total weight for a truck type doesn't exceed total capacity of trucks used for f in truck_types: total_assigned_weight = mdl.sum(assign[o,f] * get_order(o).Weight for o in orders) mdl.add_constraint(total_assigned_weight <= num_trucks[f] * get_truck_type(f).Capacity, f"Capacity_Check_{f}") # Solve and print solution print("===solution===") si = mdl.solve() if si: mdl.print_solution() else: print("No feasible solution found.")
What This Does
- The model now calculates cost based on how many trucks of each type you actually deploy, not how many orders you assign to the type.
- It ensures that the total weight of orders assigned to a truck type fits into the number of trucks you use for that type.
- You can use as many trucks of any type as needed, since
num_trucks[f]is an unbounded non-negative integer (the solver will automatically cap it at the minimum number needed for the assigned orders).
内容的提问来源于stack exchange,提问作者william007




