[英]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.