Scipy Optimize循环创建约束时出现奇异矩阵错误求助
问题描述
我正在尝试优化一个20×5的矩阵以最大化返回值y,核心约束是所有元素的总和必须处于指定的最小与最大范围之间。但通过循环创建约束时,持续出现如下奇异矩阵错误:
Singular matrix C in LSQ subproblem (Exit mode 6) Current function value: -3.0867160133139926 Iterations: 1 Function evaluations: 261 Gradient evaluations: 1
循环创建约束的代码版本
# 导入库 import pandas as pd import numpy as np import scipy.optimize as so import random # 定义目标函数 def obj_func(matrix): # 定义各列的计算逻辑 return np.sum(output_matrix) # 优化器函数 def optimizer_result(tot_sum_max, tot_sum_min, col_min, col_max, matrix_input): constraints_list = [ {'type': 'ineq', 'fun': lambda x: np.sum(x) - tot_sum_max}, {'type': 'ineq', 'fun': lambda x: -(np.sum(x) - tot_sum_min)} ] # 生成初始矩阵 start_matrix = [random.randint(0, 3) for i in range(0, 260)] # 运行优化器 optimizer_solution = so.minimize( obj_func, start_matrix, method='SLSQP', bounds=[(0, tot_sum_max)] * 20, tol=0.01, options={'disp': True, 'maxiter': 100}, constraints=constraints_list, callback=callback )
但手动编写约束时,优化器能正常运行(为简洁未包含全部260个元素约束),不清楚两者差异的原因。
手动创建约束的代码版本
# 导入库 import pandas as pd import numpy as np import scipy.optimize as so import random # 定义目标函数 def obj_func(matrix): return np.sum(output_matrix) # 优化器函数 def optimizer_result(tot_sum_max, tot_sum_min, col_min, col_max, matrix_input): total_and_col_cons = [ {'type': 'ineq', 'fun': lambda x: np.sum(x) - tot_sum_min}, {'type': 'ineq', 'fun': lambda x: -(np.sum(x) - tot_sum_max)} ] # 生成初始矩阵 start_matrix = [random.randint(0, 3) for i in range(0, 260)] # 运行优化器 optimizer_solution = so.minimize( obj_func, start_matrix, method='SLSQP', bounds=[(0, tot_sum_max)] * 20, tol=0.01, options={'disp': True, 'maxiter': 100}, constraints=constraints_list, callback=callback )
问题原因与解决方法
你遇到的奇异矩阵错误,本质是代码中存在多处维度不匹配、变量未定义的问题,和“循环/手动创建约束”本身无关,具体问题如下:
1. 目标函数的致命错误
两个版本的obj_func都直接引用了未定义的output_matrix变量,优化器无法计算目标值,直接导致后续迭代逻辑混乱,这是触发奇异矩阵的核心诱因之一。
2. 维度不匹配问题
- 你要优化的是20×5=100个元素的矩阵,但
start_matrix生成了260个元素,变量维度和优化目标完全不符。 - 边界参数
bounds=[(0, tot_sum_max)] * 20只设置了20个边界,和260个变量的数量不匹配,导致约束矩阵维度错乱,SLSQP算法无法构建有效的雅可比矩阵,最终出现奇异矩阵。
3. 手动版本的笔误
手动版本中定义了total_and_col_cons约束列表,但优化器调用时仍使用constraints_list,如果实际运行时你修正了这个笔误,约束逻辑才会生效;而循环版本没有这个笔误,但其他维度错误依然存在,所以出现报错。
修正后的代码示例
import numpy as np import scipy.optimize as so import random # 修正目标函数:基于传入的matrix参数计算输出,最大化等价于最小化负值 def obj_func(matrix): # 转换为20×5的二维矩阵 matrix_2d = matrix.reshape(20, 5) # 替换为你实际的各列计算逻辑,示例为各列求和的总和 total_output = np.sum([np.sum(col) for col in matrix_2d.T]) # scipy.minimize是最小化器,最大化需返回负值 return -total_output def optimizer_result(tot_sum_max, tot_sum_min, col_min, col_max, matrix_input): # 总和约束:sum(x) ≥ tot_sum_min 且 sum(x) ≤ tot_sum_max constraints_list = [ {'type': 'ineq', 'fun': lambda x: np.sum(x) - tot_sum_min}, {'type': 'ineq', 'fun': lambda x: tot_sum_max - np.sum(x)} ] # 初始矩阵:匹配20×5=100个元素的维度 start_matrix = [random.randint(0, 3) for _ in range(20*5)] # 边界:每个元素的范围,数量与变量一致 bounds = [(0, tot_sum_max // 100 + 1)] * (20*5) # 运行优化器 optimizer_solution = so.minimize( obj_func, start_matrix, method='SLSQP', bounds=bounds, tol=0.01, options={'disp': True, 'maxiter': 100}, constraints=constraints_list ) return optimizer_solution
关键修正点
- 目标函数使用传入的
matrix参数,正确计算输出值,适配scipy的最小化逻辑返回负值。 - 初始矩阵、边界数量均匹配20×5矩阵的100个元素维度。
- 约束逻辑简化,避免符号错误。
内容的提问来源于stack exchange,提问作者star_it8293
相关产品推荐
相关产品推荐

