Scipy trust-constr求解约束优化报布尔索引维度不匹配错误
scipy.optimize.trust-constr 索引报错排查
问题复现代码
当前编写的约束优化求解代码如下:
from scipy import optimize as opt import numpy as np def f(x): return (x[0]-5)**2 + (x[1]-6)**2 # 边界与线性约束 bounds = opt.Bounds([0,0],[np.inf, np.inf]) lin_const = opt.LinearConstraint([[1,2],[0,0]], [-np.inf, 0], [4,0]) # 非线性约束、对应雅可比与海塞矩阵 def cons_f(x): return [x[0]**2 - 4, np.exp(-x[0]) - 1] def cons_J(x): return [[2*x[0], 0], [-np.exp(-x[0])]] def cons_H(x, v): return v[0]*np.array([[2,0], [0,0]]) + v[1]*np.array([[np.exp(-x[0]), 0], [0,0]]) nonlin_const = opt.NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H) # 求解 x0 = np.array([0.50, 0.75]) res = opt.minimize(f, x0, method='trust-constr',jac="2-point", hess=opt.SR1(), bounds=bounds, constraints=[lin_const, nonlin_const], options={'verbose': 1}) print(res.x)
运行后触发numpy索引报错:boolean index did not match indexed array along dimension 0; dimension is 1 but corresponding boolean dimension is 2
完整报错栈如下:
IndexError Traceback (most recent call last) Input In [32], in <cell line: 2>() 1 x0 = np.array([0.50, 0.75]) ----> 2 res = opt.minimize(f, x0, method='trust-constr',jac=cons_J, hess=opt.SR1(), bounds=bounds, constraints=[lin_const, nonlin_const], options={'verbose': 1}) 3 print(res.x) File ~\anaconda3\envs\choquetclassifier\lib\site-packages\scipy\optimize\_minimize.py:634, in minimize(fun, x0, args, method, jac, hess, hessp, bounds, constraints, tol, callback, options) 631 return _minimize_slsqp(fun, x0, args, jac, bounds, 632 constraints, callback=callback, **options) 633 elif meth == 'trust-constr': ---> 634 return _minimize_trustregion_constr(fun, x0, args, jac, hess, hessp, 635 bounds, constraints, 636 callback=callback, **options) 637 elif meth == 'dogleg': 638 return _minimize_dogleg(fun, x0, args, jac, hess, 639 callback=callback, **options) File ~\anaconda3\envs\choquetclassifier\lib\site-packages\scipy\optimize\_trustregion_constr\minimize_trustregion_constr.py:361, in _minimize_trustregion_constr(fun, x0, args, grad, hess, hessp, bounds, constraints, xtol, gtol, barrier_tol, sparse_jacobian, callback, maxiter, verbose, finite_diff_rel_step, initial_constr_penalty, initial_tr_radius, initial_barrier_parameter, initial_barrier_tolerance, factorization_method, disp) 357 prepared_constraints.append(PreparedConstraint(bounds, x0, 358 sparse_jacobian)) 360 # 拼接初始约束为标准形式 ---> 361 c_eq0, c_ineq0, J_eq0, J_ineq0 = initial_constraints_as_canonical( 362 n_vars, prepared_constraints, sparse_jacobian) 364 # 准备所有标准约束并拼接 365 canonical_all = [CanonicalConstraint.from_PreparedConstraint(c) 366 for c in prepared_constraints] File ~\anaconda3\envs\choquetclassifier\lib\site-packages\scipy\optimize\_trustregion_constr\canonical_constraint.py:352, in initial_constraints_as_canonical(n, prepared_constraints, sparse_jacobian) 350 finite_ub = ub < np.inf 351 c_ineq.append(f[finite_ub] - ub[finite_ub]) ---> 352 J_ineq.append(J[finite_ub]) 353 elif np.all(ub == np.inf): 354 finite_lb = lb > -np.inf IndexError: boolean index did not match indexed array along dimension 0; dimension is 1 but corresponding boolean dimension is 2
报错根因
核心问题是非线性约束的雅可比矩阵返回维度不符合要求:
- 代码定义了2个优化变量、2个非线性约束,雅可比矩阵必须为
(2,2)形状的二维数组,每一行对应一个约束对两个变量的偏导 - 编写的
cons_J第二行仅返回了[-np.exp(-x[0])](长度为1),遗漏了第二个约束np.exp(-x[0]) -1对x[1]的偏导值0,导致雅可比矩阵维度不匹配,触发后续布尔索引错误 - 额外冗余问题:线性约束中
[0,0]对应的约束0*x0 +0*x1 =0是恒成立的无效约束,不会触发报错但会增加计算开销
修正后代码
from scipy import optimize as opt import numpy as np def f(x): return (x[0]-5)**2 + (x[1]-6)**2 # 边界与线性约束,移除冗余的全零约束 bounds = opt.Bounds([0,0],[np.inf, np.inf]) lin_const = opt.LinearConstraint([[1,2]], [-np.inf], [4]) # 非线性约束、对应雅可比与海塞矩阵 def cons_f(x): return [x[0]**2 - 4, np.exp(-x[0]) - 1] def cons_J(x): # 补全第二行对x[1]的偏导0,保证雅可比形状为(2,2) return [[2*x[0], 0], [-np.exp(-x[0]), 0]] def cons_H(x, v): return v[0]*np.array([[2,0], [0,0]]) + v[1]*np.array([[np.exp(-x[0]), 0], [0,0]]) nonlin_const = opt.NonlinearConstraint(cons_f, -np.inf, 1, jac=cons_J, hess=cons_H) # 求解,如果传入自定义雅可比cons_J,就不需要设置jac="2-point"做数值差分 x0 = np.array([0.50, 0.75]) res = opt.minimize(f, x0, method='trust-constr',jac=cons_J, hess=opt.SR1(), bounds=bounds, constraints=[lin_const, nonlin_const], options={'verbose': 1}) print(res.x)
修正点说明
- 补全非线性约束雅可比第二行的缺失元素,保证雅可比输出形状匹配
(约束数, 变量数)要求 - 移除冗余的恒成立线性约束,简化约束定义
- 统一雅可比传参:如果传入自定义解析雅可比
cons_J,就不需要再设置jac="2-point"用数值差分计算雅可比,避免参数冲突
内容的提问来源于stack exchange,提问作者Glenbreaks
相关产品推荐
相关产品推荐

