使用scipy.optimize.linprog求解线性规划失败,请求问题排查
Troubleshooting "No Feasible Initial Point" in scipy.optimize.linprog
Let's walk through fixing your linear programming implementation step by step. The core issues are related to constraint formatting and redundant constraints, which are preventing the solver from finding a valid starting point.
Key Problems in Your Original Code
- Incorrect Constraint Array Format:
scipy.optimize.linprogexpectsA_ubandA_eqto be 2D numpy arrays, not lists of 1D arrays/lists. This shape mismatch confuses the solver. - Redundant Constraint: You added a constraint
astringency @ x >= 0, which is completely unnecessary (allxvalues are non-negative, and astringency scores are positive). This redundant constraint can interfere with the solver's feasibility check. - Minor Bound Setup Inefficiency: Your loop to set bounds works, but it can be simplified to avoid potential errors.
Fixed Implementation
Here's the corrected code with explanations embedded:
import pandas as pd import numpy as np from scipy.optimize import linprog df = pd.read_csv('Supplier Specs.csv') # Simplified helper to get 1D numpy arrays from DataFrame columns def fromPandas(dataframe, colName): return dataframe[colName].values # Directly gets a 1D array (no need for reshape) # Extract all required parameters from the DataFrame BAR = fromPandas(df, 'Brix / Acid Ratio') acid = fromPandas(df, 'Acid (%)') astringency = fromPandas(df, 'Astringency (1-10 Scale)') color = fromPandas(df, 'Color (1-10 Scale)') price = fromPandas(df, 'Price (per 1K Gallons)') shipping = fromPandas(df, 'Shipping (per 1K Gallons)') upperBounds = fromPandas(df, 'Qty Available (1,000 Gallons)') # Objective function: Minimize total cost (price + shipping per 1k gallons) c = price + shipping # Demand constraint (sum of all juice purchases = 600k gallons) demand = 600.0 A_eq = np.array([[1.0]*11]) # 2D array (1 constraint, 11 variables) b_eq = np.array([demand]) # Variable bounds: x2 >= 240k gallons (Florida tax requirement), all others >=0 lowerBounds = np.zeros(11) lowerBounds[2] = 0.4 * demand bnds = list(zip(lowerBounds, upperBounds)) # Simplified bound setup # Inequality constraints (all formatted as A_ub @ x <= b_ub) # We scale all average-based constraints by total demand to avoid division constraint_rows = [ BAR, # (BAR @ x)/demand <= 12.5 → BAR @ x <= 12.5*demand acid, # (acid @ x)/demand <= 1.0 → acid @ x <= 1.0*demand astringency, # (astringency @ x)/demand <= 4.0 → astringency @ x <=4.0*demand color, # (color @ x)/demand <=5.5 → color @x <=5.5*demand -BAR, # (BAR @x)/demand >=11.5 → -BAR @x <= -11.5*demand -acid, # (acid @x)/demand >=0.75 → -acid @x <= -0.75*demand -color # (color @x)/demand >=4.5 → -color @x <= -4.5*demand ] A_ub = np.array(constraint_rows) # Convert to 2D numpy array (7 constraints, 11 variables) b_ub = np.array([12.5, 1.0, 4.0, 5.5, -11.5, -0.75, -4.5]) * demand # Debug output to verify parameters print("------------------------------------- Debugging Output ------------------------------------- \n") print("Objective function coefficients: ", c) print("Bounds: ", bnds) print("Equality constraint matrix (A_eq): ", A_eq) print("Equality target (b_eq): ", b_eq) print("Inequality constraint matrix (A_ub): ", A_ub) print("Inequality targets (b_ub): ", b_ub) print("\n") # Run optimization with the robust 'highs' solver (default in recent scipy versions) result = linprog(c, A_ub=A_ub, b_ub=b_ub, A_eq=A_eq, b_eq=b_eq, bounds=bnds, method='highs') print("Optimization Result:") print(result) # Verify your expected solution meets all constraints expected_x = np.array([0,0,240,0,15.8,0,0,0,126.3,109.7,108.2]) print("\nValidating Expected Solution:") print(f"Total volume: {expected_x.sum():.1f} (should equal {demand})") print(f"BAR average: {(BAR @ expected_x)/demand:.2f} (should be between 11.5 and 12.5)") print(f"Acid average: {(acid @ expected_x)/demand:.2f} (should be between 0.75 and 1.0)") print(f"Astringency average: {(astringency @ expected_x)/demand:.2f} (should be ≤4.0)") print(f"Color average: {(color @ expected_x)/demand:.2f} (should be between 4.5 and5.5)") print(f"Total cost: {c @ expected_x:.0f} (should match your target of 371724)")
Why This Fixes the Issue
- Proper Constraint Formatting: Converting
A_ubandA_eqto 2D numpy arrays ensures the solver correctly interprets the number of constraints and variables. - Removed Redundant Constraint: Removing the
astringency >=0constraint eliminates unnecessary complexity that could have confused the solver's feasibility check. - Explicit Solver Selection: Using
method='highs'(scipy's modern LP solver) improves robustness compared to older methods like the simplex algorithm, making it more likely to find feasible solutions.
Additional Tips
- Always validate your expected solution against constraints first (as shown in the code) to confirm your constraint logic matches the problem requirements.
- If you still encounter issues, check if your supplier data has values that could create conflicting constraints (e.g., a supplier with BAR outside the allowed range that's forced to be used via bounds).
内容的提问来源于stack exchange,提问作者Vasil Yordanov




