我正在使用Gekko来解决一个优化问题,该问题的约束要求对数组变量求和。因为这些数组很长,所以我不断收到错误:APM model error: string > 15000 characters
需要对三个变量求和:i在范围(1,年)中,n在范围(1,i)中,j在范围(1,受体)中。编译时,每个求和中包含的变量数量增加。我想将代码作为总结与以下行:
m.Equation(emissions[:,3] == sum(sum(sum(f[n,j]*-r[j,2]*unit *(.001*(i-n)**2 + 0.062*(i-n)) for i in range(years)) for n in range(i))for j in range(rec)))
但是,这些约束导致一行错误超过15,000个字符。
我以前已经解决了使用for循环和中间体来解决“约束”环境之外的所有这些变量的问题。它给了我正确的答案,但是编译模型花费的时间很长(模型构建最多需要4个小时,而解决模型所需的时间不到3分钟)。代码如下:
for i in range(years):
emissions[i,0] = s[i,1]
emissions[i,1] = s[i,3]
emissions[i,2] = s[i,5]
emissions[i,3] = 0
emissions[i,4] = 0
emissions[i,5] = 0
for n in range(i):
for j in range(rec):
#update + binary * flux * conversion * growth
emissions[i,3] = m.Intermediate(emissions[i,3] + f[n,j] * - rankedcopy[j,2] * unit * (.001*(i-n)**2 + 0.062*(i-n)))
emissions[i,4] = m.Intermediate(emissions[i,4] + f[n,j] * - rankedcopy[j,3] * unit * (.001*(i-n)**2 + 0.062*(i-n)))
emissions[i,5] = m.Intermediate(emissions[i,5] + f[n,j] * - rankedcopy[j,4] * unit * (.001*(i-n)**2 + 0.062*(i-n)))
我希望避免for循环会提高效率,这使我能够扩展模型,但是我不确定增加APM模型字符串限制的方法。
我也欢迎其他关于如何将中间体嵌入求和中的建议。
答案 0 :(得分:2)
尝试将m.sum()
函数用作内置的GEKKO对象。如果使用Python sum
函数,则它将创建一个较大的求和方程,需要在运行时进行解释,并且可能超出方程大小限制。 m.sum()
改为以字节码创建求和。
m.Equation(emissions[:,3] == \
m.sum(m.sum(m.sum(f[n,j]*-r[j,2]*unit *(.001*(i-n)**2 + 0.062*(i-n)) \
for i in range(years)) for n in range(i))for j in range(rec)))
这是一个简单的示例,显示了性能上的差异。
from gekko import GEKKO
import numpy as np
import time
n = 5000
v = np.linspace(0,n-1,n)
# summation method 1 - Python sum
m = GEKKO()
t = time.time()
s = sum(v)
y = m.Var()
m.Equation(y==s)
m.solve(disp=False)
print(y.value[0])
print('Elapsed time: ' + str(time.time()-t))
m.cleanup()
# summation method 2 - Intermediates
m = GEKKO()
t = time.time()
s = 0
for i in range(n):
s = m.Intermediate(s + v[i])
y = m.Var()
m.Equation(y==s)
m.solve(disp=False)
print(y.value[0])
print('Elapsed time: ' + str(time.time()-t))
m.cleanup()
# summation method 3 - Gekko sum
m = GEKKO()
t = time.time()
s = m.sum(v)
y = m.Var()
m.Equation(y==s)
m.solve(disp=False)
print(y.value[0])
print('Elapsed time: ' + str(time.time()-t))
m.cleanup()
结果
12497500.0
Elapsed time: 0.17874956130981445
12497500.0
Elapsed time: 5.171698570251465
12497500.0
Elapsed time: 0.1246955394744873
单个等式的15,000个字符限制是一个硬限制。我们考虑过使用m.options.MAX_MEMORY
进行调整,但是大型方程可以为求解器提供非常密集的矩阵分解。通常最好分解等式或使用其他方法来减小等式的大小。