Python PuLP优化问题:如何正确编写最小化Aisle销售额与平均值绝对偏差总和的目标函数
Fixing Your PuLP Aisle Optimization Problem
Let's walk through the problems in your code and fix them to get a working optimization model. The core issues are with how you've defined variables, structured constraints, and handled the absolute deviation in the objective function—linear programming can't directly use absolute values, so we need a workaround for that.
Key Issues in Your Original Code
- Incorrect Variable Definition: Your
AislePickvariable assigns each product an integer (0 or 1) for the aisle, but you can't use conditional checks likeais == aislein constraints because PuLP variables aren't evaluated until solving. We need binary variables to track product-aisle assignments explicitly. - Absolute Deviation Handling: You can't directly use
|x - avg|in a linear objective. Instead, we introduce auxiliary variables to represent positive and negative deviations, then minimize their sum. - Invalid Objective Function: Using
value()anditertools.groupbyin the objective is wrong—these operate on actual values, but PuLP needs linear expressions of variables to build the model.
Corrected Code
import pulp # Product data products = ['Fruit Loops', 'Frosted Flakes', 'Cocoa Pebbles', 'Fruitty Pebbles', 'Corn Flakes', 'Cheerios'] sales = {'Fruit Loops': 20, 'Frosted Flakes': 15, 'Cocoa Pebbles': 8, 'Fruitty Pebbles': 9, 'Corn Flakes': 12, 'Cheerios': 6} shelves = {'Fruit Loops': 2, 'Frosted Flakes': 1, 'Cocoa Pebbles': 1, 'Fruitty Pebbles': 1, 'Corn Flakes': 2, 'Cheerios': 1} # Problem setup Num_of_Aisles = 2 Max_Shelves_Aisle = 4 total_sales = sum(sales.values()) avg_sales = total_sales / Num_of_Aisles # Initialize problem problem = pulp.LpProblem('AisleOptimization', pulp.LpMinimize) # Binary variables: AislePick[prod][aisle] = 1 if product is assigned to aisle, 0 otherwise AislePick = pulp.LpVariable.dicts( "AisleAssignment", [(prod, aisle) for prod in products for aisle in range(Num_of_Aisles)], cat='Binary' ) # Auxiliary variables for absolute deviation: d_plus[aisle] = positive deviation, d_minus[aisle] = negative deviation d_plus = pulp.LpVariable.dicts("PositiveDeviation", range(Num_of_Aisles), lowBound=0) d_minus = pulp.LpVariable.dicts("NegativeDeviation", range(Num_of_Aisles), lowBound=0) # Objective: Minimize sum of absolute deviations (sum of d_plus + d_minus) problem += pulp.lpSum([d_plus[aisle] + d_minus[aisle] for aisle in range(Num_of_Aisles)]), "TotalAbsoluteDeviation" # Constraints # 1. Each product is assigned to exactly one aisle for prod in products: problem += pulp.lpSum([AislePick[(prod, aisle)] for aisle in range(Num_of_Aisles)]) == 1, f"Assign_{prod}" # 2. Each aisle's total shelf usage doesn't exceed max for aisle in range(Num_of_Aisles): problem += pulp.lpSum([shelves[prod] * AislePick[(prod, aisle)] for prod in products]) <= Max_Shelves_Aisle, f"ShelfLimit_Aisle{aisle}" # 3. Link aisle sales to average and deviation variables for aisle in range(Num_of_Aisles): aisle_sales = pulp.lpSum([sales[prod] * AislePick[(prod, aisle)] for prod in products]) # aisle_sales - avg_sales = d_plus[aisle] - d_minus[aisle] problem += aisle_sales - avg_sales == d_plus[aisle] - d_minus[aisle], f"DeviationLink_Aisle{aisle}" # Solve the problem problem.solve() # Print results print(f"Status: {pulp.LpStatus[problem.status]}") print(f"Total Absolute Deviation: {pulp.value(problem.objective)}") # Print assignments for aisle in range(Num_of_Aisles): assigned_products = [prod for prod in products if pulp.value(AislePick[(prod, aisle)]) == 1] aisle_total_sales = sum(sales[prod] for prod in assigned_products) aisle_total_shelves = sum(shelves[prod] for prod in assigned_products) print(f"\nAisle {aisle}:") print(f" Products: {', '.join(assigned_products)}") print(f" Total Sales: {aisle_total_sales}") print(f" Total Shelves Used: {aisle_total_shelves}")
Explanation of Changes
- Binary Assignment Variables:
AislePick[(prod, aisle)]makes it clear which product goes to which aisle, and lets us build linear constraints without conditional logic. - Deviation Variables: By splitting the absolute deviation into
d_plus(how much an aisle's sales exceed the average) andd_minus(how much they fall short), we convert the non-linear absolute value into a linear expression the solver can handle. - Proper Constraints: We ensure each product is assigned exactly once, and each aisle's shelf limit is respected using linear sums of variables multiplied by their shelf counts.
Expected Output
When you run this code, you should get an optimal solution with a total absolute deviation of 6 (matching your example), and the assignment you described:
- Aisle 0: Fruit Loops, Corn Flakes (sales 32, shelves 4)
- Aisle 1: Frosted Flakes, Cocoa Pebbles, Fruitty Pebbles, Cheerios (sales 38, shelves 4)
内容的提问来源于stack exchange,提问作者Bo Anderson
相关产品推荐
相关产品推荐

