scipy.optimize约束定义问题:含未知数量约束的极小化求解
解决scipy.optimize约束极小化问题的正确姿势
首先,你的代码报错是因为完全用错了scipy.optimize.Bounds的语法,而且混淆了「独立边界约束」和「变量间依赖约束」的区别——后者不能用Bounds处理,得用专门的约束对象。
先理清楚你的约束(从问题描述和代码反推)
根据你提供的信息,约束应该分为三类:
- 第一个变量:
0 ≤ η₁ ≤ 1 - 中间变量(第2到第n-1个):
η_{i-1} ≤ η_i ≤ η_{i+1}(变量间的依赖约束) - 全局等式约束:
Σ(a_i * η_i) = y_max
第一步:纠正边界约束的写法
scipy.optimize.Bounds只负责每个变量自身的独立上下界,需要传入两个一维numpy数组:
lb:每个变量的下界ub:每个变量的上界
比如针对第一个变量的约束,初始化lb和ub:
import numpy as np from scipy.optimize import minimize, Bounds, LinearConstraint n = len(rates) # 变量总数 lb = np.full(n, -np.inf) # 默认下界设为负无穷 ub = np.full(n, np.inf) # 默认上界设为正无穷 # 第一个变量的约束:0 ≤ η₁ ≤1 lb[0] = 0 ub[0] = 1 bnds = Bounds(lb, ub)
第二步:处理变量间的依赖约束(η_{i-1} ≤ η_i ≤ η_{i+1})
这类约束是线性不等式约束,需要用LinearConstraint来定义。我们把每个约束转化为线性形式:
- 对于第i个变量(Python索引从1到n-2):
η[i] - η[i-1] ≥ 0(对应η_i ≥ η_{i-1}) - 同时:
η[i+1] - η[i] ≥ 0(对应η_i ≤ η_{i+1})
我们可以把这些约束整理成矩阵A和向量b:
# 构建约束矩阵A和右侧向量b constraint_rows = [] constraint_b = [] # 处理η[i] ≥ η[i-1] for i in range(1, n-1): row = np.zeros(n) row[i] = 1 row[i-1] = -1 constraint_rows.append(row) constraint_b.append(0) # 处理η[i] ≤ η[i+1] → 等价于η[i+1] - η[i] ≥0 for i in range(1, n-1): row = np.zeros(n) row[i+1] = 1 row[i] = -1 constraint_rows.append(row) constraint_b.append(0) # 转化为numpy数组 A = np.array(constraint_rows) b = np.array(constraint_b) # 创建线性不等式约束:A @ η ≥ b var_dep_constraint = LinearConstraint(A, lb=b, ub=np.inf)
第三步:处理全局等式约束(Σa_iη_i = y_max)
这也是线性约束,直接用LinearConstraint的等式形式:
# a_i是已知的numpy数组,y_max是已知数值 eq_constraint = LinearConstraint(a_i, lb=y_max, ub=y_max)
第四步:调用minimize函数
把所有约束合并,传入目标函数g(你已经定义好的)和初始猜测rates:
# 合并所有约束 constraints = [var_dep_constraint, eq_constraint] # 执行极小化 result = minimize(g, x0=rates, bounds=bnds, constraints=constraints) # 查看结果 print(result.x) # 最优解 print(result.fun) # 最优目标值
为什么你的原代码报错?
你直接在Bounds里写生成器表达式,既不符合Bounds的参数要求(需要两个数组),又犯了Python语法错误——生成器表达式必须用括号括起来,但就算括起来,Bounds也不接受这种依赖其他变量的动态边界,因为Bounds只能处理每个变量的独立上下界,变量间的依赖必须放到constraints参数里。
内容的提问来源于stack exchange,提问作者honkhonk
相关产品推荐
相关产品推荐

