Gekko优化中预定义变量集合的代码修改及报错解决咨询
Gekko优化中预定义变量集合的代码修改及报错解决咨询
我明白你现在遇到的问题啦——你想让优化模型里的每个x变量只能从指定集合[2,5,6,13]中取值,但修改代码时因为参数传递错误触发了TypeError,而且还可能存在约束逻辑的矛盾。咱们一步步来解决:
一、先解决你触发的TypeError
你修改代码时写了x = m.Array(m.Var,9,[2, 5, 6, 13]),这是对Gekko Array方法的用法误解导致的报错。
Gekko的Array方法正确调用格式是:
m.Array(func, dims, **kwargs)
其中:
func是要批量创建的对象(比如m.Var)dims是数组的维度(这里是9,代表9个变量)**kwargs是传递给func的关键字参数(比如给m.Var传lb、ub、integer等)
你不能直接把可选值列表作为位置参数传进去,这就是报错提示“takes 3 positional arguments but 4 were given”的原因。
二、正确实现「变量只能取指定集合值」的约束
在Gekko中,要让变量只能取离散的可选值,我们需要给每个变量添加显式约束。这里推荐用二进制变量+线性约束的方式,确保每个变量只能从[2,5,6,13]中选一个值。
另外要特别提醒你:你原来的约束sum(x)==7和新的变量可选值存在逻辑矛盾——每个x的最小值是2,9个变量的和最小是9*2=18,根本不可能等于7,这个约束必须调整(比如是不是应该把可选值改成更小的数?或者约束条件写错了?)
以下是修正后的完整代码:
from gekko import GEKKO m = GEKKO(remote=False) # 先创建9个整数变量,上下界设为可选值的最小和最大值 x = m.Array(m.Var,9,lb=2,ub=13,integer=True) # 定义允许的取值集合 allowed_values = [2,5,6,13] # 给每个变量添加约束:必须是允许集合中的一个值 for xi in x: # 创建4个二进制变量,对应每个可选值(只能选一个) b = m.Array(m.Var,4,integer=True,lb=0,ub=1) m.Equation(sum(b) == 1) # 确保只选中一个可选值 # 用二进制变量线性组合出当前变量的取值 m.Equation(xi == sum(v * b[j] for j, v in enumerate(allowed_values))) def f(x): return (481.79/(5+x[0]))+(412.04/(4+x[1]))\ +(365.54/(3+x[2]))+(375.88/(3+x[3]))\ +(379.75/(3+x[4]))+(632.92/(5+x[5]))\ +(127.89/(1+x[6]))+(835.71/(6+x[7]))\ +(200.21/(1+x[8])) m.Minimize(f(x)) # 注意:这里的sum约束必须调整,原约束sum(x)==7和变量可选值矛盾,示例先改成sum(x)>=18 m.Equation(sum(x) >= 18) m.options.SOLVER = 1 # 用APOPT求解器,支持整数和离散约束 m.solve(disp=True) # 打印每个变量的最终取值 print([xi.value[0] for xi in x])
三、简化版离散约束实现
如果你想简化离散值约束,也可以用Gekko的sos1(Special Ordered Set of Type 1)功能,它专门用于从离散集合中选一个值的场景,代码可以简化为:
from gekko import GEKKO m = GEKKO(remote=False) x = m.Array(m.Var,9,lb=2,ub=13,integer=True) allowed_values = [2,5,6,13] for xi in x: m.sos1([xi - v for v in allowed_values]) # sos1约束确保其中一个项为0,即xi=v # 后续的目标函数、约束、求解代码和上面一致
备注:内容来源于stack exchange,提问作者繆征達
相关产品推荐
相关产品推荐

