一个简单的优化示例在(0,0,8)目标为936.0和(7,0,0)目标为处有 2 个局部最小值。在 Python Gekko ( , , ) 中使用局部优化器来找到全局解决方案951.0的技巧有哪些?APOPT``BPOPT``IPOPT
(0,0,8)
936.0
(7,0,0)
951.0
APOPT``BPOPT``IPOPT
from gekko import GEKKO m = GEKKO(remote=False) x = m.Array(m.Var,3,lb=0) x1,x2,x3 = x m.Minimize(1000-x1**2-2*x2**2-x3**2-x1*x2-x1*x3) m.Equations([8*x1+14*x2+7*x3==56, x1**2+x2**2+x3**2>=25]) m.solve(disp=False) res=[print(f'x{i+1}: {xi.value[0]}') for i,xi in enumerate(x)] print(f'Objective: {m.options.objfcnval:.2f}')
这产生了一个局部最小值:
x1: 7.0 x2: 0.0 x3: 0.0 Objective: 951.00
有用于全局优化的求解器,例如BARON、COCOS、GlobSol、、和,但有哪些快速策略可以与局部优化器一起使用来搜索全局解决方案?一些工业应用具有高度非线性的模型,尚未在控制和ICOS设计方面对全局解决方案进行全面测试。该策略可以在 Python 中并行化吗?LGO``LINGO``OQNLP
BARON
COCOS
GlobSol
ICOS
LGO``LINGO``OQNLP
多起点方法(使用随机起点)可能很有用。虽然不能保证全局最优,但至少可以在一定程度上防止出现一些令人尴尬的糟糕局部解决方案。一些本地 NLP 求解器内置了此功能(例如 Knitro)。
以下是使用多启动方法获取全局解决方案的示例 Python 代码。它使用多线程来并行化搜索。
import numpy as np import threading import time, random from gekko import GEKKO class ThreadClass(threading.Thread): def __init__(self, id, xg): s = self s.id = id s.m = GEKKO(remote=False) s.xg = xg s.objective = float('NaN') # initialize variables s.m.x = s.m.Array(s.m.Var,3,lb=0) for i in range(3): s.m.x[i].value = xg[i] s.m.x1,s.m.x2,s.m.x3 = s.m.x # Equations s.m.Equation(8*s.m.x1+14*s.m.x2+7*s.m.x3==56) s.m.Equation(s.m.x1**2+s.m.x2**2+s.m.x3**2>=25) # Objective s.m.Minimize(1000-s.m.x1**2-2*s.m.x2**2-s.m.x3**2 -s.m.x1*s.m.x2-s.m.x1*s.m.x3) # Set solver option s.m.options.SOLVER = 1 threading.Thread.__init__(s) def run(self): print('Running application ' + str(self.id) + '\n') self.m.solve(disp=False,debug=0) # solve # Retrieve objective if successful if (self.m.options.APPSTATUS==1): self.objective = self.m.options.objfcnval else: self.objective = float('NaN') self.m.cleanup() # Optimize at mesh points x1_ = np.arange(0.0, 10.0, 3.0) x2_ = np.arange(0.0, 10.0, 3.0) x3_ = np.arange(0.0, 10.0, 3.0) x1,x2,x3 = np.meshgrid(x1_,x2_,x3_) threads = [] # Array of threads # Load applications id = 0 for i in range(x1.shape[0]): for j in range(x1.shape[1]): for k in range(x1.shape[2]): xg = (x1[i,j,k],x2[i,j,k],x3[i,j,k]) # Create new thread threads.append(ThreadClass(id, xg)) # 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 = 10.0 # max time (sec) it = 0.0 # time counter st = 1.0 # sleep time (sec) while (threading.active_count()>=3): time.sleep(st) it = it + st print('Active Threads: ' + str(threading.active_count())) # Terminate after max time if (it>=mt): break # Initialize array for objective obj = np.empty_like(x1) # Retrieve objective results id = 0 id_best = 0; obj_best = 1e10 for i in range(x1.shape[0]): for j in range(x1.shape[1]): for k in range(x1.shape[2]): obj[i,j,k] = threads[id].objective if obj[i,j,k]<obj_best: id_best = id obj_best = obj[i,j,k] id += 1 print(obj) print(f'Best objective {obj_best}') print(f'Solution {threads[id_best].m.x}')
它产生了全局解决方案:
Best objective 936.0 Solution [[0.0] [0.0] [8.0]]