含GEKKO未知变量的NumPy数组数学运算方法及Gekko整数规划目标函数问题求助
解决Gekko中未知变量与NumPy数组运算及整数规划目标函数问题
首先,你遇到的核心问题是:Gekko的未知变量(Var)不能直接参与NumPy的数值运算,因为Gekko需要构建优化问题的符号表达式,而NumPy是针对确定数值的运算,在变量未求解前会引发错误。下面我们一步步修正你的代码,并解释关键要点。
原代码的主要问题
- 错误的数组索引:
w1[:,0]是无效的,因为w1是一维NumPy数组(形状为(3,)),没有第二维索引,应该直接用w1[i]访问单个元素。 - 误用NumPy函数处理Gekko变量:
d.min(axis=1).sum()这类NumPy操作无法处理Gekko的Var对象,必须改用Gekko内置的符号函数来构建目标函数。 - 目标函数的构建方式错误:直接将包含NumPy运算的函数返回值传给
m.Obj(),会导致Gekko无法识别符号表达式,进而求解失败。
修正后的代码及解释
from gekko import GEKKO import numpy as np # 初始化数据 d_initial = np.array([10, 30, 50]) # 对应原d[:,0]的初始值 w1 = np.array([0, 1.2, 2]) w2 = np.array([0, 2, 0]) w3 = np.array([0.1, 0, 0.2]) # 初始化Gekko模型 m = GEKKO(remote=False) m.options.SOLVER = 1 # 使用APOPT求解器,支持整数规划 # 定义整数变量 x1 = m.Var(value=1, lb=1, ub=3, integer=True) x2 = m.Var(value=1, lb=1, ub=4, integer=True) x3 = m.Var(value=1, lb=1, ub=5, integer=True) # 构建每个行的剩余值(对应原d[:,1]的每个元素) d_residual = [] for i in range(3): # 计算d_i = d_initial[i] - w1[i]*x1 - w2[i]*x2 - w3[i]*x3 res = m.Intermediate(d_initial[i] - w1[i]*x1 - w2[i]*x2 - w3[i]*x3) d_residual.append(res) # 构建目标函数:每行取d_initial[i]和residual的最小值,再求和 obj = 0 for i in range(3): # 使用Gekko的min2函数计算两个值的最小值(符号化操作) row_min = m.min2(d_initial[i], d_residual[i]) obj += row_min # 设置目标函数(默认是最小化,若需最大化可加负号) m.Obj(obj) # 求解 m.solve(disp=True) # 打开disp=True便于查看求解过程 # 输出结果 print('Results') print('x1: ' + str(x1.value[0])) print('x2: ' + str(x2.value[0])) print('x3: ' + str(x3.value[0])) print('Objective: ' + str(m.options.objfcnval))
关键要点说明
使用
m.Intermediate处理中间表达式:
对于涉及Gekko变量的数组运算,我们需要用m.Intermediate将每个元素的表达式包装为Gekko可识别的符号变量,而不是直接用NumPy数组存储。用Gekko内置函数替代NumPy函数:
- 求最小值用
m.min2(a, b)(针对两个值)或m.min3(a,b,c),多值最小可嵌套使用; - 求和直接用Python的
+累加,或者m.sum()函数(例如m.sum(row_mins),其中row_mins是Gekko变量的列表); - 其他运算如最大值、绝对值等,都有对应的Gekko内置函数(
m.max2、m.abs等)。
- 求最小值用
整数规划求解器选择:
你设置的m.options.SOLVER=1是正确的,APOPT求解器支持整数变量(Integer Programming),而默认的IPOPT求解器仅支持连续变量。
关于Gekko变量与NumPy数组运算的通用建议
- 避免直接将Gekko
Var对象放入NumPy数组进行运算,而是逐个处理每个元素,用m.Intermediate保存符号表达式; - 所有需要参与优化的运算,都必须使用Gekko的符号函数,确保优化器能正确构建问题的梯度和约束;
- 如果需要批量处理数组,可以用循环遍历每个元素,构建对应的Gekko中间变量。
内容的提问来源于stack exchange,提问作者Reza_nadimi
相关产品推荐
相关产品推荐

