GEKKO求解NLP报错TypeError: must be real number, not GK_Operators
错误原因
你遇到的类型错误核心原因是混用了Python原生math库函数和GEKKO符号变量:
- GEKKO建模阶段声明的
m.Var对象都是GK_Operators类型的符号表达式,不是普通浮点数值 math.sqrt、math.atan、math.degrees这类原生函数只能处理Python原生实数类型,无法解析GEKKO的符号对象,因此直接抛出类型错误- 除此之外你的代码还有几个隐藏问题:未定义目标函数里用到的常量
A、B;用Python内置函数名sum做变量名会覆盖内置方法;原生sum对GEKKO符号数组求和存在兼容风险;取求解结果时.value返回的是单元素列表,直接打印会带列表括号。
修复方法
所有涉及GEKKO符号变量的数学运算,全部替换为GEKKO内置的对应数学函数,这类函数原生支持GK_Operators类型,可以正确构建求解所需的符号表达式,具体调整点如下:
- 用
m.sqrt()替换math.sqrt() - 用
m.atan()替换math.atan() - 用GEKKO内置常量
m.pi实现弧度转角度(角度值=弧度值 * 180/m.pi),替换math.degrees() - 用
m.sum()替换Python原生sum()处理GEKKO变量求和,避免兼容问题 - 提前定义目标函数用到的常量
A、B - 取求解结果时取
.value[0],拿到单元素列表里的实际数值
修复后可运行代码
import numpy as np from gekko import GEKKO # 替换为你实际使用的A、B常量取值 A = 1 B = 0 def calculateLossFunction(m, h, x, y, lmbd, n): total_loss = 0 x_star = np.dot(np.transpose(lmbd), x) y_star = np.dot(np.transpose(lmbd), y) for i in range(n): RNJ = m.sqrt((x_star - x[i]) ** 2 + (y_star - y[i]) ** 2) atan_rad = m.atan(h[i] / RNJ) # 手动实现弧度转角度,不调用math.degrees atan_deg = atan_rad * (180 / m.pi) P = 1 / atan_deg total_loss += A * P + B return total_loss # 建模流程 m = GEKKO(remote=True) H = [500, 1500, 2500] locations = np.array([[1, 2], [2, 3], [3, 1]]) XN = locations[:, 0] YN = locations[:, 1] n = len(locations) lambdas = m.Array(m.Var, n, lb=0, ub=1, value=0) lambdas[0].value = 1 m.Minimize(calculateLossFunction(m, H, XN, YN, lambdas, n)) m.Equation(m.sum(lambdas) == 1) m.solve(disp=True) # 输出结果 print('\nResults') print(f'lambda1: {lambdas[0].value[0]}') print(f'lambda2: {lambdas[1].value[0]}') print(f'lambda3: {lambdas[2].value[0]}')
内容的提问来源于stack exchange,提问作者Berk Karasu
相关产品推荐
相关产品推荐

