
scipy.optimize.linprog 默认对所有变量施加非负约束(x ≥ 0),即使用户未显式指定;当手动验证的“可行点”含负分量时,该点实际不满足默认边界条件,从而造成“明明有解却报不可行”的表观矛盾。
scipy.optimize.linprog 默认对所有变量施加非负约束(x ≥ 0),即使用户未显式指定;当手动验证的“可行点”含负分量时,该点实际不满足默认边界条件,从而造成“明明有解却报不可行”的表观矛盾。
scipy.optimize.linprog 在无显式边界声明时,默认将所有决策变量限制在非负象限:即隐含约束 lb = 0, ub = None(参见 官方文档)。这意味着,即使你仅提供 A_ub 和 b_ub,求解器仍强制要求 x[i] ≥ 0 对所有 i 成立。
在你的示例中:
x0 = np.array([ 229.1748166 , -507.05266751, 512.14005547])
print('x0 is feasible?', (A_ub @ x0 <= b_ub).all()) # True虽然 x0 满足线性不等式约束 A_ub @ x0 <= b_ub,但它违反了默认的下界约束——第二维 -507.05 < 0,因此 x0 并非该 linprog 调用所定义问题的可行解。
验证这一点只需检查默认边界:
from scipy.optimize import linprog
res = linprog(
np.zeros(3),
A_ub=A_ub,
b_ub=b_ub,
method='highs' # 显式指定以确保行为一致
)
print("Default lower bounds:", res.lbs) # [0., 0., 0.]
print("x0 satisfies lb?", np.all(x0 >= 0)) # False✅ 正确做法:若变量允许取负值,必须显式解除非负约束。使用 bounds 参数传入 (-np.inf, np.inf)(或 None)表示无界:
res = linprog(
np.zeros(3),
A_ub=A_ub,
b_ub=b_ub,
bounds=[(-np.inf, np.inf)] * 3 # 关键:取消默认 x >= 0
)
if res.success:
print("Feasible solution found:", res.x)
print("Constraint check:", np.all(A_ub @ res.x <= b_ub + 1e-10)) # 容差校验
else:
print("Still infeasible — check constraint consistency.")运行后将返回一个有效可行解(例如 x ≈ [229.17, -507.05, 512.14]),且 status == 0(优化成功)。
⚠️ 注意事项:
- bounds=None 等价于 [(-np.inf, np.inf)] * n_vars,但显式写出更清晰;
- 使用 method='highs'(推荐,默认)比旧版 simplex 更鲁棒,尤其对无界/退化问题;
- 数值精度下建议用 <= b_ub + 1e-10 替代严格 <= 进行可行性验证;
- 若仅需判断可行性(而非优化),目标函数设为 np.zeros(n) 是标准做法,但务必同步配置 bounds。
总之,linprog 的“不可行”结论本身无误——错误在于忽略了其强默认假设。明确声明变量边界,是避免此类逻辑陷阱的关键实践。

















