[英]Python: Fast alternatives to GEKKO for solving Algebraic differential equations
为了模拟电网中的潮流,我使用 GEKKO 来求解我的代数微分方程系统。
对于较小的模拟,它工作得很好,但是连续运行几次,例如在训练强化学习代理时,需要相当长的时间。
谁能建议一个开销较小的求解器来加快模拟速度?
系统外观的一个小例子在我们的 GitHub 回购链接中:
还有其他替代品,例如 assimulo 和 CasADi。 但我还没有找到接近 GEKKO 的东西。 我的建议是,用参数而不是变量来定义 model。 这肯定会减少重新初始化 model 所需的时间。
在一些基准测试中,Gekko 比 pyomo 快大约 5 倍。 我们还与目前正在使用 CasADi 的团队合作,以加快对 Gekko 的优化。 如果它是一种代数建模语言,那么 Gekko 是最快的选择之一。 以下是对 Gekko 的一些建议。 使用m.options.TIME_SHIFT=0
切换到 IMODE IMODE=4
以从先前的解决方案作为热启动解决。 这可以显着提高求解速度。 另一种选择是并行化 function 调用,以使用multi-threading进行强化学习代理。
import numpy as np
import threading
import time, random
from gekko import GEKKO
class ThreadClass(threading.Thread):
def __init__(self, id, server, ai, bi):
s = self
s.id = id
s.server = server
s.m = GEKKO(remote=False)
s.a = ai
s.b = bi
s.objective = float('NaN')
# initialize variables
s.m.x1 = s.m.Var(1,lb=1,ub=5)
s.m.x2 = s.m.Var(5,lb=1,ub=5)
s.m.x3 = s.m.Var(5,lb=1,ub=5)
s.m.x4 = s.m.Var(1,lb=1,ub=5)
# Equations
s.m.Equation(s.m.x1*s.m.x2*s.m.x3*s.m.x4>=s.a)
s.m.Equation(s.m.x1**2+s.m.x2**2+s.m.x3**2+s.m.x4**2==s.b)
# Objective
s.m.Minimize(s.m.x1*s.m.x4*(s.m.x1+s.m.x2+s.m.x3)+s.m.x3)
# Set global options
s.m.options.IMODE = 3 # steady state optimization
s.m.options.SOLVER = 1 # APOPT solver
threading.Thread.__init__(s)
def run(self):
# Don't overload server by executing all scripts at once
sleep_time = random.random()
time.sleep(sleep_time)
print('Running application ' + str(self.id) + '\n')
# Solve
self.m.solve(disp=False)
# Retrieve objective if successful
if (self.m.options.APPSTATUS==1):
self.objective = self.m.options.objfcnval
else:
self.objective = float('NaN')
self.m.cleanup()
# Select server
server = 'https://byu.apmonitor.com'
# Optimize at mesh points
x = np.arange(20.0, 30.0, 2.0)
y = np.arange(30.0, 50.0, 2.0)
a, b = np.meshgrid(x, y)
# Array of threads
threads = []
# Calculate objective at all meshgrid points
# Load applications
id = 0
for i in range(a.shape[0]):
for j in range(b.shape[1]):
# Create new thread
threads.append(ThreadClass(id, server, a[i,j], b[i,j]))
# Increment ID
id += 1
# Run applications simultaneously as multiple threads
# Max number of threads to run at once
max_threads = 8
for t in threads:
while (threading.activeCount()>max_threads):
# check for additional threads every 0.01 sec
time.sleep(0.01)
# start the thread
t.start()
# Check for completion
mt = 3.0 # max time
it = 0.0 # incrementing time
st = 1.0 # sleep time
while (threading.activeCount()>=1):
time.sleep(st)
it = it + st
print('Active Threads: ' + str(threading.activeCount()))
# Terminate after max time
if (it>=mt):
break
# Wait for all threads to complete
#for t in threads:
# t.join()
#print('Threads complete')
# Initialize array for objective
obj = np.empty_like(a)
# Retrieve objective results
id = 0
for i in range(a.shape[0]):
for j in range(b.shape[1]):
obj[i,j] = threads[id].objective
id += 1
# plot 3D figure of results
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
fig = plt.figure()
ax = fig.gca(projection='3d')
surf = ax.plot_surface(a, b, obj, \
rstride=1, cstride=1, cmap=cm.coolwarm, \
vmin = 12, vmax = 22, linewidth=0, antialiased=False)
ax.set_xlabel('a')
ax.set_ylabel('b')
ax.set_zlabel('obj')
ax.set_title('Multi-Threaded GEKKO')
plt.show()
如果在 Sundials 中有一个 DAE 集成器,例如 IDA ,那么这也可能是模拟的替代方案。 Gekko 解决了更高的 DAE 索引问题,而大多数集成器(如 DASSL、DASPK 和 IDA)仅限于索引 1 DAE 和可选的索引 2 Hessenberg 形式。 如果可能的话,这通常会造成将方程重新排列成那种形式的巨大负担。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.