You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用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

  1. Incorrect Constraint Array Format: scipy.optimize.linprog expects A_ub and A_eq to be 2D numpy arrays, not lists of 1D arrays/lists. This shape mismatch confuses the solver.
  2. Redundant Constraint: You added a constraint astringency @ x >= 0, which is completely unnecessary (all x values are non-negative, and astringency scores are positive). This redundant constraint can interfere with the solver's feasibility check.
  3. 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

  1. Proper Constraint Formatting: Converting A_ub and A_eq to 2D numpy arrays ensures the solver correctly interprets the number of constraints and variables.
  2. Removed Redundant Constraint: Removing the astringency >=0 constraint eliminates unnecessary complexity that could have confused the solver's feasibility check.
  3. 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

火山引擎 最新活动