使用Scipy Optimise与Mystic时max_limit约束持续被违反
解决Scipy Optimize中总和约束被违反的问题
问题根源
你的代码把约束处理逻辑嵌入到了目标函数内部,通过mystic修改输入变量后再计算目标值。但Scipy的SLSQP优化器无法识别这种隐式约束,它需要显式的约束定义来指导优化过程,因此导致总和始终突破max_limit限制。
修正方案
直接使用Scipy Optimize原生的约束定义方式,将总和约束单独声明,让优化器在搜索过程中主动遵守约束:
import random from scipy.optimize import minimize as so max_limit = 2000 # 定义目标函数(最大化model.func等价于最小化其负值) def objective_func(x): return -model.func(x) # 定义总和不等式约束:sum(x) <= max_limit def sum_constraint(x): return max_limit - sum(x) # SLSQP要求不等式约束返回值 >= 0 # 初始化变量 initial_matrix = [random.randint(0, 3) for _ in range(260)] # 设置约束参数:类型为不等式约束 constraints = {'type': 'ineq', 'fun': sum_constraint} # 执行优化 output = so.minimize( objective_func, initial_matrix, method='SLSQP', bounds=[(0, max_limit)] * 260, constraints=[constraints], tol=0.01, options={'disp': True, 'maxiter': 100} )
关键改动说明
- 移除目标函数内的约束处理:让目标函数仅负责计算目标值,保证优化器能获取到原始变量的目标反馈。
- 显式定义Scipy兼容的约束:通过
constraints参数传入不等式约束,SLSQP会在每一步迭代中检查约束是否满足,调整搜索方向以避免违反约束。 - 简化约束逻辑:直接计算总和与max_limit的差值,符合Scipy对不等式约束的要求(返回值≥0表示约束满足)。
额外建议
如果需要保留mystic的复杂约束能力,建议直接使用mystic的优化器(而非嵌套Scipy),比如:
import mystic as my from mystic.solvers import fmin_slsqp # 用mystic定义约束 eqns = my.simplify(f"sum(x) <= {max_limit}", all=True) constraint = my.generate_constraint(my.generate_solvers(eqns)) # 使用mystic的SLSQP求解器 output = fmin_slsqp( objective_func, initial_matrix, bounds=[(0, max_limit)]*260, constraints=constraint, disp=True, maxiter=100, tol=0.01 )
这样能更好地兼容mystic的约束定义方式,避免两种工具的工作流程冲突。
内容的提问来源于stack exchange,提问作者star_it8293
相关产品推荐
相关产品推荐

