如何使用Mystic一次性约束10个以上变量实现预算管控?
问题描述
我正在使用mystic库实现总预算约束,每个独立变量对应一个需最大化的目标函数。已为每项支出设置边界,使其增减幅度不超过30%,现需添加约束确保总预算不被超出。
相关代码如下:
equations = """A + B + C + D + E + F + G + H + I + J < %s """%(budget) var = list('ABCDEFGHIJKLMNOPQ') eqns = ms.simplify(equations, variables=var, all=True) constrain = ms.generate_constraint(ms.generate_solvers(eqns, var), join=my.constraints.and_)
当变量数量不超过10个时,上述代码运行正常;但在求和项中加入第11个变量(K)后,ms.simplify函数抛出错误:NameError: name 'B0' is not defined。
请问是否存在一次性约束10个以上变量的可行方法?
解决方案
这个错误源于mystic的字符串解析器在处理超过10个变量时,会错误地将变量名解析为内部占位符(比如把K识别成B0)。可以通过以下两种方式解决:
方法1:直接定义函数式约束(推荐)
跳过字符串解析步骤,直接编写约束函数,支持任意数量的变量:
def budget_constraint(x, budget): # x是变量数组,顺序与var列表对应 return sum(x) < budget # 生成约束 constrain = my.constraints.generate_constraint(budget_constraint, args=(budget,))
这种方式无需依赖字符串解析,性能更稳定,也不会出现变量解析错误。
方法2:动态生成正确的字符串方程
如果坚持使用字符串方程的方式,通过动态拼接生成求和表达式,确保所有变量都被正确引用:
# 定义需要参与求和的变量 sum_vars = list('ABCDEFGHIJK') # 动态生成求和方程 equations = " + ".join(sum_vars) + f" < {budget}" var = list('ABCDEFGHIJKLMNOPQ') eqns = ms.simplify(equations, variables=var, all=True) constrain = ms.generate_constraint(ms.generate_solvers(eqns, var), join=my.constraints.and_)
动态拼接可以避免手动输入变量名时的遗漏或错误,同时让方程中的变量与变量列表var完全匹配,减少解析歧义。
注意要点
- 保证变量列表
var的顺序与求解器接收的变量顺序一致,避免约束对应错误。 - 函数式约束的方式更高效,且不易出现解析类bug,建议优先采用。
内容的提问来源于stack exchange,提问作者JBrack
相关产品推荐
相关产品推荐

