mg-pso-gui 0.2.125__py3-none-any.whl → 0.2.126__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {mg_pso_gui-0.2.125.dist-info → mg_pso_gui-0.2.126.dist-info}/METADATA +1 -1
- {mg_pso_gui-0.2.125.dist-info → mg_pso_gui-0.2.126.dist-info}/RECORD +10 -8
- mgpsogui/gui/HomePage.py +5 -5
- mgpsogui/gui/SetupTab/ListParametersView.py +1 -1
- mgpsogui/util/recosu/pso/pso modified.py +585 -0
- mgpsogui/util/recosu/pso/pso.py +48 -292
- mgpsogui/util/recosu/pso/pso_new.py +627 -0
- {mg_pso_gui-0.2.125.dist-info → mg_pso_gui-0.2.126.dist-info}/WHEEL +0 -0
- {mg_pso_gui-0.2.125.dist-info → mg_pso_gui-0.2.126.dist-info}/entry_points.txt +0 -0
- {mg_pso_gui-0.2.125.dist-info → mg_pso_gui-0.2.126.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
|
|
1
1
|
mgpsogui/__init__.py,sha256=q7AfBjeJABnFtbsZnsObpUwaXKPDVYtz46G6MKXLF74,42
|
2
2
|
mgpsogui/mgpsogui.py,sha256=NIZmyNcbwC8EgSwf1ubdMUSJscrIEgoD4jLYziqHQ-k,148
|
3
3
|
mgpsogui/start.yaml,sha256=ZjCVLb-MLqAxrGRm9kA7_SDpa-45EuKIELNQ2QqCAiU,4713
|
4
|
-
mgpsogui/gui/HomePage.py,sha256=
|
4
|
+
mgpsogui/gui/HomePage.py,sha256=fTGAuCUBWaydSe0t7HO95snJ1B6j2xa5GJcEJSLymBA,25974
|
5
5
|
mgpsogui/gui/OptionManager.py,sha256=t0aXOeBo48qQ-P8OykpP2v_3KJoaJtUPSkYtacjloCc,22844
|
6
6
|
mgpsogui/gui/OptionManager_backup.py,sha256=TCWfPnHL2foN5id47jsi267lamRG6yGU6y_M29eOOJk,18530
|
7
7
|
mgpsogui/gui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -19,7 +19,7 @@ mgpsogui/gui/SetupTab/CustomFunctionEditorWindow.py,sha256=lZ9a20YucwhCDiUN3eGA6
|
|
19
19
|
mgpsogui/gui/SetupTab/CustomFunctionMetrics.py,sha256=vOJpElbTgz043m6JYwe9xz_2MBHg985S6KdbJkJERW4,5923
|
20
20
|
mgpsogui/gui/SetupTab/FunctionsList.py,sha256=wmYmppyB5y8QADe3X_FQ5mAYVDC0HAPQgqtkegNwmLA,7007
|
21
21
|
mgpsogui/gui/SetupTab/ListEditor.py,sha256=nin7Pl8z7d_yfKoAxM-yVS34uhj-LnprJ2mNRSB7Z0A,3197
|
22
|
-
mgpsogui/gui/SetupTab/ListParametersView.py,sha256=
|
22
|
+
mgpsogui/gui/SetupTab/ListParametersView.py,sha256=CdK7OVdccwk0_OLgrwwNFTHuV2hMvETsocQIKndZoV4,7459
|
23
23
|
mgpsogui/gui/SetupTab/OverrideParameterMetrics.py,sha256=rBfaSitYDOajbHvyi2TfoXAHYlz1cCt028UVpIJ_Dc0,3369
|
24
24
|
mgpsogui/gui/SetupTab/OverrideParameterWindow.py,sha256=1UJHel0BH4sYa5WQnuSaFd3cdpRwAIwOpFIbhDS30IY,1824
|
25
25
|
mgpsogui/gui/SetupTab/SamplingListView.py,sha256=DhZBAhDcrqZn1XioCs1gTe_v-8W10C0UfPm0fLAbeXM,5260
|
@@ -58,7 +58,9 @@ mgpsogui/util/CTkToolTip/ctk_tooltip.py,sha256=SZMovpQIGvdpDRbqCKl9SHs92DrFCO2MO
|
|
58
58
|
mgpsogui/util/recosu/__init__.py,sha256=pPR0lB6clIi6q73H1W8eT5u0dd3bIemwa9-XFmOaVVk,279
|
59
59
|
mgpsogui/util/recosu/pso/__init__.py,sha256=PQ548aEKVOk6MMzxxDg7yMO_1hHfoEoYLLkGLeij73Y,247
|
60
60
|
mgpsogui/util/recosu/pso/csip_access.py,sha256=_oA71d6CSwhKSa3pgywIW7mXRJtgJTNu1X2DiBkQkuA,4152
|
61
|
-
mgpsogui/util/recosu/pso/pso.py,sha256=
|
61
|
+
mgpsogui/util/recosu/pso/pso modified.py,sha256=sFY1csASu5Os5SSheWWdpVcjpPwJeBqZKsv89DLXdxk,21648
|
62
|
+
mgpsogui/util/recosu/pso/pso.py,sha256=iPqT6aI1vi8LYuWmtxuHkLEM9sQwhUznPInBgps7ANI,13708
|
63
|
+
mgpsogui/util/recosu/pso/pso_new.py,sha256=qUwpp6gjhCTXA6twKGAda84HIeQebKGB6MJ4K9GfcdM,23181
|
62
64
|
mgpsogui/util/recosu/sampling/__init__.py,sha256=dWs1MPx0o2UFmOmUfFaomQWBTIZAwALsVJzZQNZePZU,252
|
63
65
|
mgpsogui/util/recosu/sampling/sample_trace_writer.py,sha256=M9w-POLlZgjL5a7J7yxr73OG6mCsS2aUuP9d3HKfkbA,1966
|
64
66
|
mgpsogui/util/recosu/sampling/sampler_task.py,sha256=uZobpR83u6xEaUzIknvW9FbB84c2AL7T-5T8O8QIhzY,2776
|
@@ -73,8 +75,8 @@ mgpsogui/util/recosu/utils/trace_writer.py,sha256=V9BJlOjCbNYGoXGEk3CF5wjifBxvar
|
|
73
75
|
mgpsogui/util/recosu/utils/utils.py,sha256=6MIoJb0nhIa4tNv7qhBfZi-AtL3L95CgJf6eAf12NQs,4140
|
74
76
|
mgpsogui/util/recosu/utils/plot/__init__.py,sha256=h1KjM7_tNDv351pcwt8A6Ibb1jhwWyx5Gbu-zj-sI3Q,71
|
75
77
|
mgpsogui/util/recosu/utils/plot/cost_steps.py,sha256=1Ce11AJyweWkmvjXPxEygzS-h8yVLmQEDLS53yjPLqQ,3779
|
76
|
-
mg_pso_gui-0.2.
|
77
|
-
mg_pso_gui-0.2.
|
78
|
-
mg_pso_gui-0.2.
|
79
|
-
mg_pso_gui-0.2.
|
80
|
-
mg_pso_gui-0.2.
|
78
|
+
mg_pso_gui-0.2.126.dist-info/METADATA,sha256=WoBCQFVK_l0TIamnui7_FpcDK8hr6Tc0-a5kYKXAQV0,9542
|
79
|
+
mg_pso_gui-0.2.126.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
80
|
+
mg_pso_gui-0.2.126.dist-info/entry_points.txt,sha256=jg82VOFjR1XDGrchs1wJSCqKYE4Ozv12aBcCSp--koA,117
|
81
|
+
mg_pso_gui-0.2.126.dist-info/top_level.txt,sha256=y7JuS9xJN5YdxUsQ3PSVjN8MzQAnR146bP3ZN3PYWdE,9
|
82
|
+
mg_pso_gui-0.2.126.dist-info/RECORD,,
|
mgpsogui/gui/HomePage.py
CHANGED
@@ -145,7 +145,7 @@ class App(customtkinter.CTk):
|
|
145
145
|
self.sidebar_frame.grid_columnconfigure(4, weight=1)
|
146
146
|
self.logo_label = customtkinter.CTkLabel(self.sidebar_frame, text="COSU Manager (" + version + ")", font=customtkinter.CTkFont(size=20, weight="bold"))
|
147
147
|
self.logo_label.grid(row=0, column=0, padx=(20, 10), pady=header_padding_y)
|
148
|
-
self.save_button = customtkinter.CTkButton(self.sidebar_frame, text="Save", width=60, command=self.save_project)
|
148
|
+
self.save_button = customtkinter.CTkButton(self.sidebar_frame, text="Save As", width=60, command=self.save_project)
|
149
149
|
self.save_button.grid(row=0, column=1, padx=header_padding_x, pady=header_padding_y)
|
150
150
|
self.load_button = customtkinter.CTkButton(self.sidebar_frame, text="Load", width=60, command=self.load_project)
|
151
151
|
self.load_button.grid(row=0, column=2, padx=header_padding_x, pady=header_padding_y)
|
@@ -258,11 +258,11 @@ class App(customtkinter.CTk):
|
|
258
258
|
os.makedirs(os.path.join(folder, "results"))
|
259
259
|
|
260
260
|
self.save_button.configure(text="Saved!")
|
261
|
-
self.after(3000, lambda: self.save_button.configure(text="Save"))
|
261
|
+
self.after(3000, lambda: self.save_button.configure(text="Save As"))
|
262
262
|
except Exception as e:
|
263
263
|
self.save_button.configure(text="Error!")
|
264
264
|
print(e)
|
265
|
-
self.after(3000, lambda: self.save_button.configure(text="Save"))
|
265
|
+
self.after(3000, lambda: self.save_button.configure(text="Save As"))
|
266
266
|
|
267
267
|
def auto_save_project(self):
|
268
268
|
data = self.option_manager.get_project_data()
|
@@ -281,8 +281,6 @@ class App(customtkinter.CTk):
|
|
281
281
|
if not os.path.exists(os.path.join(folder, "results")):
|
282
282
|
os.makedirs(os.path.join(folder, "results"))
|
283
283
|
|
284
|
-
self.save_button.configure(text="Saved!")
|
285
|
-
self.after(1000, lambda: self.save_button.configure(text="Save"))
|
286
284
|
except Exception as e:
|
287
285
|
self.save_button.configure(text="Error!")
|
288
286
|
print(e)
|
@@ -445,6 +443,8 @@ class App(customtkinter.CTk):
|
|
445
443
|
NW(title="Error", message="A process is already running!", x = 400, y = 200)
|
446
444
|
return 0
|
447
445
|
|
446
|
+
self.auto_save_project()
|
447
|
+
|
448
448
|
data = self.option_manager.get_all_data()
|
449
449
|
mode = self.option_manager.get_mode()
|
450
450
|
data = data[mode]
|
@@ -138,7 +138,7 @@ class ListParametersView(CTkScrollableFrame):
|
|
138
138
|
row += 1
|
139
139
|
|
140
140
|
CTkButton(self.containerFrame, text="Open", command=self.open_csv).grid(row=row, column=0, padx=(5, 5), pady=(5, 5), sticky="ew")
|
141
|
-
CTkButton(self.containerFrame, text="
|
141
|
+
CTkButton(self.containerFrame, text="Paste", command=self.import_csv).grid(row=row, column=1, padx=(5, 5), pady=(5, 5), sticky="ew")
|
142
142
|
row += 1
|
143
143
|
|
144
144
|
|
@@ -0,0 +1,585 @@
|
|
1
|
+
#
|
2
|
+
# $Id:$
|
3
|
+
#
|
4
|
+
# This file is part of the Cloud Services Integration Platform (CSIP),
|
5
|
+
# a Model-as-a-Service framework, API, and application suite.
|
6
|
+
#
|
7
|
+
# 2012-2020, OMSLab, Colorado State University.
|
8
|
+
#
|
9
|
+
# OMSLab licenses this file to you under the MIT license.
|
10
|
+
# See the LICENSE file in the project root for more information.
|
11
|
+
#
|
12
|
+
import numpy
|
13
|
+
|
14
|
+
from ..utils import utils
|
15
|
+
from .csip_access import csip_worker
|
16
|
+
from pyswarms.single.global_best import GlobalBestPSO
|
17
|
+
from os import path
|
18
|
+
from threading import Thread
|
19
|
+
from typing import Dict, List, Set, Tuple
|
20
|
+
import numpy as np
|
21
|
+
import copy
|
22
|
+
import datetime
|
23
|
+
import queue
|
24
|
+
import json
|
25
|
+
import os
|
26
|
+
|
27
|
+
cost2 = {}
|
28
|
+
|
29
|
+
|
30
|
+
def eval_cost(x, iteration, step_param, step_objfunc, calib_params, req_queue, files, url, param, conf: Dict, rnd,
|
31
|
+
step):
|
32
|
+
particles = len(x[:, 0])
|
33
|
+
|
34
|
+
pfail_count = conf.get('particles_fail', 1) # Number of particles allowed to fail.
|
35
|
+
pfail_retry = conf.get('particles_retry', 3) # retry number of times if more than allowed fail
|
36
|
+
|
37
|
+
while pfail_retry > 0:
|
38
|
+
cost = np.ones(particles)
|
39
|
+
res_queue = queue.Queue()
|
40
|
+
|
41
|
+
print(' ', end='', flush=True)
|
42
|
+
|
43
|
+
# submit for processing
|
44
|
+
# for i_particle, v in enumerate(x[:, 0]):
|
45
|
+
for particle in range(particles):
|
46
|
+
req_queue.put((rnd, step, iteration, particle, x, step_param, calib_params, step_objfunc, res_queue))
|
47
|
+
# print(' rnd: ', rnd)
|
48
|
+
# print(' step: ', step)
|
49
|
+
# print(' interation: ', iteration)
|
50
|
+
# print(' particle: ', particle)
|
51
|
+
# print(' x[particle,:]: ', x[particle,:])
|
52
|
+
|
53
|
+
# req_queue.put((i_particle, x[i_particle,:], step_param_names, calib_params, step_objfunc, res_queue))
|
54
|
+
|
55
|
+
# wait for the cost value to come back
|
56
|
+
# for i, v in enumerate(x[:, 0]):
|
57
|
+
for idx in range(particles):
|
58
|
+
(particle, p_cost) = res_queue.get()
|
59
|
+
cost[particle] = p_cost
|
60
|
+
cost1 = []
|
61
|
+
cost1.append(iteration)
|
62
|
+
cost1.append(p_cost)
|
63
|
+
cost1.append(str('r{}s{}i{}p{}.json'.format(rnd, step, iteration, particle)))
|
64
|
+
|
65
|
+
if particle not in cost2:
|
66
|
+
cost2[particle] = []
|
67
|
+
|
68
|
+
cost2[particle].append(cost1)
|
69
|
+
|
70
|
+
res_queue.task_done()
|
71
|
+
|
72
|
+
res_queue.join()
|
73
|
+
|
74
|
+
# replace the 'nan' cost values (failed/missing runs) with the mean of the
|
75
|
+
# rest of the cost values, hence ignore it
|
76
|
+
|
77
|
+
# print("cost ", cost)
|
78
|
+
nan_idx = np.where(np.isnan(cost))
|
79
|
+
failed_particles = len(nan_idx[0])
|
80
|
+
|
81
|
+
# leave the loop if fails acceptable
|
82
|
+
if failed_particles <= pfail_count:
|
83
|
+
break
|
84
|
+
print("Re-running particles, since ", failed_particles, ' out of ', particles, ' particles failed.')
|
85
|
+
pfail_retry -= 1
|
86
|
+
|
87
|
+
if pfail_retry == 0:
|
88
|
+
print('Particle evaluation failed ', conf.get('particles_retry', 3), ' times. PSO stopped.')
|
89
|
+
return None
|
90
|
+
|
91
|
+
# print("mean ", mean)
|
92
|
+
# assign the mean value to all failed runs.
|
93
|
+
mean = np.nanmean(cost)
|
94
|
+
cost[nan_idx[0]] = mean
|
95
|
+
|
96
|
+
for key in cost2:
|
97
|
+
# print(key, ' - ', cost2[key])
|
98
|
+
cost2[key][iteration][1] = cost[key]
|
99
|
+
# print(key, ' - ', cost2[key])
|
100
|
+
|
101
|
+
print(flush=True)
|
102
|
+
return cost
|
103
|
+
|
104
|
+
|
105
|
+
def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters: int, options: Dict,
|
106
|
+
oh_strategy: Dict = None, n_threads: int = 4, rtol: float = 0.001, ftol: float = -np.inf,
|
107
|
+
ftol_iter: int = 1, full_trace: List = None, rtol_iter: int = 1,
|
108
|
+
conf: Dict = None, metainfo: Dict = None, cost_target: float = -np.inf) -> Tuple:
|
109
|
+
"""Performs a stepwise particle swarm optimization PSO using a global best approach.
|
110
|
+
|
111
|
+
Parameters
|
112
|
+
----------
|
113
|
+
steps : Dict
|
114
|
+
step definitions
|
115
|
+
rounds : tuple
|
116
|
+
round definition, (min,max) or max
|
117
|
+
args : Dict
|
118
|
+
static service args
|
119
|
+
n_particles : int
|
120
|
+
number of particles
|
121
|
+
iters : int
|
122
|
+
number of iterations
|
123
|
+
options : Dict
|
124
|
+
PSO options (see pyswarms)
|
125
|
+
oh_strategy : Dict
|
126
|
+
PSO Option handling strategy (see pyswarms)
|
127
|
+
n_threads : int
|
128
|
+
size of thread pool (default: 4)
|
129
|
+
rtol : float
|
130
|
+
percentage of change of sum(best_cost) between rounds for
|
131
|
+
convergence. (Default is 0.001 0.1%)
|
132
|
+
ftol : float
|
133
|
+
PSO tolerance (default: -np.inf)
|
134
|
+
ftol_iter : float
|
135
|
+
number of iterations over which the relative error in
|
136
|
+
objective_func is acceptable for convergence. (default: 1)
|
137
|
+
full_trace : List
|
138
|
+
trace of all runs, list of tuples
|
139
|
+
first is dictionary of parameter names to parameter values
|
140
|
+
second is the cost value (default: None)
|
141
|
+
rtol_iter : int
|
142
|
+
the number of subsequent rounds with sum(best_cost) < rtol
|
143
|
+
(default: 1)
|
144
|
+
conf : Dict
|
145
|
+
configuration settings (default: {} )
|
146
|
+
metainfo : Dict
|
147
|
+
additional metainfo for the csip client (default: {} )
|
148
|
+
cost_target: float
|
149
|
+
the cost target (default: -np.inf)
|
150
|
+
Returns
|
151
|
+
-------
|
152
|
+
Tuple
|
153
|
+
optimizer: List, step_trace: Dict
|
154
|
+
|
155
|
+
"""
|
156
|
+
|
157
|
+
utils.check_url(args['url'])
|
158
|
+
|
159
|
+
step_file = conf.get('step_trace', None)
|
160
|
+
|
161
|
+
min_rounds = 1
|
162
|
+
if type(rounds) == tuple:
|
163
|
+
min_rounds = rounds[0]
|
164
|
+
max_rounds = rounds[1]
|
165
|
+
else:
|
166
|
+
max_rounds = rounds
|
167
|
+
|
168
|
+
if min_rounds < 1:
|
169
|
+
raise Exception('min rounds >= 1 expected, was "{}"'.format(min_rounds))
|
170
|
+
|
171
|
+
if max_rounds > 20:
|
172
|
+
raise Exception('max rounds <= 20 expected, was "{}"'.format(max_rounds))
|
173
|
+
|
174
|
+
if n_threads < 1:
|
175
|
+
raise Exception('n_threads >= 1, was "{}"'.format(n_threads))
|
176
|
+
|
177
|
+
if rtol_iter < 1:
|
178
|
+
raise Exception('rtol_iter >= 1, was "{}"'.format(rtol_iter))
|
179
|
+
|
180
|
+
if full_trace is not None and not isinstance(full_trace, list):
|
181
|
+
raise Exception('full_trace must be of type, was "{}"'.format(type(full_trace)))
|
182
|
+
|
183
|
+
best_cost = np.ones(len(steps)) * np.inf
|
184
|
+
optimizer = np.empty(len(steps), dtype=object)
|
185
|
+
|
186
|
+
# best_pos = {}
|
187
|
+
#
|
188
|
+
# best_pos[0] = numpy.array([1.18792343e+02, 5.43472746e+01, 7.10091373e+01, 1.80144959e+00,
|
189
|
+
# 2.63979951e+00, 4.61775754e+00, 4.84808030e-01, 3.97179059e+00,
|
190
|
+
# 4.12612823e+00, 2.29275033e-01, 5.86661573e+01, 4.33933491e-01,
|
191
|
+
# 3.80515317e-01, 2.32299702e+01, 1.29697400e+01, 3.94149865e+01,
|
192
|
+
# 2.78110081e+01, 1.71484176e+01, 4.59081223e+01, 3.25059995e+01,
|
193
|
+
# 3.03662465e+01, 4.15040920e-01, 4.21613876e-01, 4.07747156e-01,
|
194
|
+
# 4.32604236e-01, 4.19428929e-01, 4.01926017e-01, 4.36295072e-01,
|
195
|
+
# 4.37658392e-01, 4.14423735e-01, 4.39537540e-01, 2.65952198e-01,
|
196
|
+
# 2.63096106e-01, 2.24934845e-01, 1.66953435e-01, 2.32302802e-01,
|
197
|
+
# 2.55939246e-01, 2.42916828e-01, 2.39205412e-01, 2.79600625e-01,
|
198
|
+
# 9.58733328e-02, 8.08481274e-02, 7.34124368e-02, 1.04667432e-01,
|
199
|
+
# 1.26246347e-01, 1.14700200e-01, 1.22694002e-01, 7.86003659e-02,
|
200
|
+
# 1.34393803e-01])
|
201
|
+
|
202
|
+
# trace of steps info
|
203
|
+
step_trace = {}
|
204
|
+
|
205
|
+
step_trace['dir'] = os.getcwd()
|
206
|
+
step_trace['start'] = str(datetime.datetime.now())
|
207
|
+
step_trace['min_rounds'] = min_rounds
|
208
|
+
step_trace['max_rounds'] = max_rounds
|
209
|
+
step_trace['iters'] = iters
|
210
|
+
step_trace['ftol'] = ftol
|
211
|
+
step_trace['ftol_iter'] = ftol_iter
|
212
|
+
step_trace['rtol'] = rtol
|
213
|
+
step_trace['rtol_iter'] = rtol_iter
|
214
|
+
step_trace['n_threads'] = n_threads
|
215
|
+
step_trace['n_particles'] = n_particles
|
216
|
+
step_trace['n_steps'] = len(steps)
|
217
|
+
step_trace['steps'] = copy.deepcopy(steps)
|
218
|
+
step_trace['args'] = args
|
219
|
+
|
220
|
+
if step_file is not None:
|
221
|
+
with open(step_file, "w") as fo:
|
222
|
+
json.dump(step_trace, fo)
|
223
|
+
|
224
|
+
# best round cost
|
225
|
+
best_round_cost = np.inf
|
226
|
+
|
227
|
+
# request queue for worker
|
228
|
+
req_queue = queue.Queue()
|
229
|
+
|
230
|
+
conf = conf or {}
|
231
|
+
done = False
|
232
|
+
thread_pool = []
|
233
|
+
for thread_no in range(n_threads):
|
234
|
+
worker = Thread(target=csip_worker, args=(req_queue, thread_no, lambda: done,
|
235
|
+
full_trace, args['url'], args.get('files', None), args['param'],
|
236
|
+
conf, metainfo)
|
237
|
+
)
|
238
|
+
thread_pool.append(worker)
|
239
|
+
worker.start()
|
240
|
+
|
241
|
+
r_below = 0
|
242
|
+
early_exit = False
|
243
|
+
start_time = datetime.datetime.now()
|
244
|
+
for r in range(max_rounds):
|
245
|
+
no_improvement = np.full(len(steps), True)
|
246
|
+
best_step_request = None
|
247
|
+
for s, step in enumerate(steps):
|
248
|
+
|
249
|
+
# check if forced exit.
|
250
|
+
if path.exists("stop"):
|
251
|
+
print('\n>>>>> stop file found, exit now.')
|
252
|
+
early_exit = True
|
253
|
+
break
|
254
|
+
|
255
|
+
param_names, bounds, objfunc = utils.get_step_info(steps, s)
|
256
|
+
# maybe clone args?
|
257
|
+
# args['step_param_names'] = param_names
|
258
|
+
args['step_param'] = step['param']
|
259
|
+
args['step_objfunc'] = objfunc
|
260
|
+
# get calibrated parameter from all other steps
|
261
|
+
args['calib_params'] = utils.get_calibrated_params(steps, s)
|
262
|
+
|
263
|
+
args['req_queue'] = req_queue
|
264
|
+
args['conf'] = conf
|
265
|
+
|
266
|
+
# if r < 1:
|
267
|
+
# best_pos[s] = np.full(len(param_names), True)
|
268
|
+
# best_pos[s] = np.empty(len(param_names), dtype=object)
|
269
|
+
# best_pos[s] = None
|
270
|
+
|
271
|
+
# create optimizer in the first round.
|
272
|
+
if optimizer[s] is None:
|
273
|
+
# if r <= 1:
|
274
|
+
optimizer[s] = GlobalBestPSO(step.get('n_particles', n_particles),
|
275
|
+
len(param_names),
|
276
|
+
oh_strategy=step.get('oh_strategy', oh_strategy),
|
277
|
+
options=step.get('options', options),
|
278
|
+
bounds=bounds,
|
279
|
+
ftol=step.get('ftol', ftol),
|
280
|
+
ftol_iter=step.get('ftol_iter', ftol_iter),
|
281
|
+
cost_target=step.get('cost_target', cost_target),
|
282
|
+
init_pos=None)
|
283
|
+
print('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names,
|
284
|
+
args['calib_params']))
|
285
|
+
|
286
|
+
args['rnd'] = r + 1
|
287
|
+
args['step'] = s + 1
|
288
|
+
|
289
|
+
# perform optimization
|
290
|
+
cost, pos = optimizer[s].optimize(eval_cost, iters=step.get('iters', iters), **args)
|
291
|
+
|
292
|
+
for key in cost2:
|
293
|
+
# print(key, ' - ', cost2[key])
|
294
|
+
inner_arrays = cost2[key]
|
295
|
+
for arrays_part in inner_arrays:
|
296
|
+
if arrays_part[1] == cost:
|
297
|
+
print(' best-file ', arrays_part[2])
|
298
|
+
|
299
|
+
cost2.clear()
|
300
|
+
print(' cost: ', cost, ' pos: ', pos)
|
301
|
+
if cost is None:
|
302
|
+
early_exit = True
|
303
|
+
break
|
304
|
+
|
305
|
+
if cost == best_cost[s]:
|
306
|
+
print(' !! equal cost !!!')
|
307
|
+
|
308
|
+
# # capture the best cost
|
309
|
+
# # if cost < best_cost[s] and np.abs(cost - best_cost[s]) > rtol:
|
310
|
+
# if cost < best_cost[s]:
|
311
|
+
# best_cost[s] = cost
|
312
|
+
# no_improvement[s] = False
|
313
|
+
# utils.annotate_step(best_cost[s], pos, steps, s)
|
314
|
+
|
315
|
+
print('\n Step summary, best particle values: {} '.format(pos))
|
316
|
+
|
317
|
+
key = "r{}s{}".format(r + 1, s + 1)
|
318
|
+
step_trace[key] = {}
|
319
|
+
step_trace[key]['time'] = str(datetime.datetime.now())
|
320
|
+
step_trace[key]['best_costs'] = best_cost
|
321
|
+
step_trace[key]['steps'] = copy.deepcopy(steps)
|
322
|
+
|
323
|
+
# capture the best cost
|
324
|
+
# if cost < best_cost[s] and np.abs(cost - best_cost[s]) > rtol:
|
325
|
+
if cost < best_cost[s]:
|
326
|
+
best_cost[s] = cost
|
327
|
+
no_improvement[s] = False
|
328
|
+
utils.annotate_step(best_cost[s], pos, steps, s)
|
329
|
+
best_step_request = key
|
330
|
+
# best_pos[s] = pos
|
331
|
+
|
332
|
+
if step_file is not None:
|
333
|
+
with open(step_file, "w") as fo:
|
334
|
+
json.dump(step_trace, fo)
|
335
|
+
|
336
|
+
# print(json.dumps(steps, sort_keys=False, indent=2))
|
337
|
+
|
338
|
+
if early_exit:
|
339
|
+
step_trace['exit'] = '1'
|
340
|
+
break
|
341
|
+
|
342
|
+
round_cost = np.sum(best_cost)
|
343
|
+
|
344
|
+
# if no improvement in all steps, break out of rounds prematurely
|
345
|
+
# but start checking only after min_rounds
|
346
|
+
# if (r + 1 >= min_rounds) and all(no_improvement):
|
347
|
+
rel_round_tol = 1 - round_cost / best_round_cost
|
348
|
+
|
349
|
+
print('\n Round summary - round_cost:{}, step_costs: {}, step improvement:{}'
|
350
|
+
.format(round_cost, best_cost, np.invert(no_improvement)))
|
351
|
+
print('\n Progress - best_round_cost:{}, rel_round_tol:{}, rtol:{}'
|
352
|
+
.format(best_round_cost, rel_round_tol, rtol))
|
353
|
+
print('\n Progress - best_step_request:{}'.format(best_step_request))
|
354
|
+
|
355
|
+
key = "r{}".format(r + 1)
|
356
|
+
step_trace[key] = {}
|
357
|
+
step_trace[key]['time'] = str(datetime.datetime.now())
|
358
|
+
step_trace[key]['round_cost'] = round_cost
|
359
|
+
step_trace[key]['best_costs'] = best_cost
|
360
|
+
step_trace[key]['improvements'] = no_improvement
|
361
|
+
if step_file is not None:
|
362
|
+
with open(step_file, "w") as fo:
|
363
|
+
json.dump(step_trace, fo)
|
364
|
+
|
365
|
+
if (r + 1 >= min_rounds) and 0 <= rel_round_tol < rtol:
|
366
|
+
r_below += 1
|
367
|
+
if r_below >= rtol_iter:
|
368
|
+
break
|
369
|
+
else:
|
370
|
+
# reset
|
371
|
+
r_below = 0
|
372
|
+
|
373
|
+
if round_cost < best_round_cost:
|
374
|
+
best_round_cost = round_cost
|
375
|
+
|
376
|
+
end_time = datetime.datetime.now()
|
377
|
+
elapsed = str(end_time - start_time)
|
378
|
+
|
379
|
+
print('Done in {} after {} out of {} rounds'.format(elapsed, r + 1, max_rounds))
|
380
|
+
|
381
|
+
done = True
|
382
|
+
for worker in thread_pool:
|
383
|
+
worker.join()
|
384
|
+
|
385
|
+
step_trace['rounds'] = r + 1
|
386
|
+
step_trace['end'] = str(datetime.datetime.now())
|
387
|
+
step_trace['time'] = elapsed
|
388
|
+
|
389
|
+
if step_file is not None:
|
390
|
+
with open(step_file, "w") as fo:
|
391
|
+
json.dump(step_trace, fo)
|
392
|
+
|
393
|
+
return optimizer, step_trace
|
394
|
+
|
395
|
+
# def p_global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters: int, options: Dict,
|
396
|
+
# n_threads: int = 4, rtol: float = 0.001, ftol: float = -np.inf,
|
397
|
+
# full_trace: List = None, rounds_below: int = 1) -> Tuple:
|
398
|
+
# """Performs a parallel stepwise particle swarm optimization PSO using a global best approach.
|
399
|
+
#
|
400
|
+
# Parameters
|
401
|
+
# ----------
|
402
|
+
# steps : Dict
|
403
|
+
# step definitions
|
404
|
+
# rounds : tuple
|
405
|
+
# round definition, (min,max) or max
|
406
|
+
# args : Dict
|
407
|
+
# static service args
|
408
|
+
# n_particles : int
|
409
|
+
# number of particles
|
410
|
+
# iters : int
|
411
|
+
# number of iterations
|
412
|
+
# options : Dict
|
413
|
+
# PSO options (see pyswarms)
|
414
|
+
# n_threads : int
|
415
|
+
# size of thread pool (default: 4)
|
416
|
+
# rtol : float
|
417
|
+
# percentage of change of sum(best_cost) between rounds for
|
418
|
+
# convergence. (Default is 0.001 0.1%)
|
419
|
+
# ftol : float
|
420
|
+
# PSO tolerance (default: -np.inf)
|
421
|
+
# full_trace : List
|
422
|
+
# trace of all runs, list of tuples
|
423
|
+
# first is dictionary of parameter names to parameter values
|
424
|
+
# second is the cost value (default: None)
|
425
|
+
# rounds_below : int
|
426
|
+
# the number of subsequent rounds with sum(best_cost) < rtol
|
427
|
+
# (default: 1)
|
428
|
+
# Returns
|
429
|
+
# -------
|
430
|
+
# Tuple
|
431
|
+
# optimizer: List, step_trace: Dict
|
432
|
+
# """
|
433
|
+
#
|
434
|
+
# utils.check_url(args['url'])
|
435
|
+
#
|
436
|
+
# min_rounds = 1
|
437
|
+
# if type(rounds) == tuple:
|
438
|
+
# min_rounds = rounds[0]
|
439
|
+
# max_rounds = rounds[1]
|
440
|
+
# else:
|
441
|
+
# max_rounds = rounds
|
442
|
+
#
|
443
|
+
# if min_rounds < 1:
|
444
|
+
# raise Exception('min rounds >= 1 expected, was "{}"'.format(min_rounds))
|
445
|
+
#
|
446
|
+
# if max_rounds > 20:
|
447
|
+
# raise Exception('max rounds <= 20 expected, was "{}"'.format(max_rounds))
|
448
|
+
#
|
449
|
+
# if n_threads < 1:
|
450
|
+
# raise Exception('n_threads >= 1, was "{}"'.format(n_threads))
|
451
|
+
#
|
452
|
+
# if rounds_below < 1:
|
453
|
+
# raise Exception('rounds_below >= 1, was "{}"'.format(rounds_below))
|
454
|
+
#
|
455
|
+
# if full_trace is not None and not isinstance(full_trace, list):
|
456
|
+
# raise Exception('full_trace must be of type, was "{}"'.format(type(full_trace)))
|
457
|
+
#
|
458
|
+
# best_cost = np.ones(len(steps))
|
459
|
+
# cost = np.ones(len(steps))
|
460
|
+
# optimizer = np.empty(len(steps), dtype=object)
|
461
|
+
# pos = np.empty(len(steps), dtype=object)
|
462
|
+
# args_s = np.empty(len(steps), dtype=object)
|
463
|
+
#
|
464
|
+
# # trace of steps info
|
465
|
+
# step_trace = {}
|
466
|
+
#
|
467
|
+
# # best round cost
|
468
|
+
# best_round_cost = 1000
|
469
|
+
#
|
470
|
+
# # request queue for worker
|
471
|
+
# req_queue = queue.Queue()
|
472
|
+
#
|
473
|
+
# # Threadpool management
|
474
|
+
# done = False
|
475
|
+
# thread_pool = []
|
476
|
+
# for thread_no in range(n_threads):
|
477
|
+
# worker = Thread(target=csip_worker, args=(req_queue, thread_no, lambda: done,
|
478
|
+
# full_trace, args['url'], args['files'], args['param']))
|
479
|
+
# thread_pool.append(worker)
|
480
|
+
# worker.start()
|
481
|
+
#
|
482
|
+
# start_time = datetime.datetime.now()
|
483
|
+
#
|
484
|
+
# # setup Step PSOs
|
485
|
+
# for s, step in enumerate(steps):
|
486
|
+
# param_names, bounds, objfunc = utils.get_step_info(steps, s)
|
487
|
+
# optimizer[s] = GlobalBestPSO(n_particles,
|
488
|
+
# len(param_names),
|
489
|
+
# options=options,
|
490
|
+
# bounds=bounds,
|
491
|
+
# ftol=ftol)
|
492
|
+
#
|
493
|
+
# def step_thread(s, args):
|
494
|
+
# cost[s], pos[s] = optimizer[s].optimize(eval_cost, iters=iters, **args)
|
495
|
+
#
|
496
|
+
# # Run PSOs in parallel
|
497
|
+
# r_below = 0
|
498
|
+
# for r in range(max_rounds):
|
499
|
+
# no_improvement = np.full(len(steps), True)
|
500
|
+
# # check if forced exit.
|
501
|
+
# if path.exists("stop"):
|
502
|
+
# print('\n>>>>> stop file found, exit now.')
|
503
|
+
# break
|
504
|
+
#
|
505
|
+
# # cross copy calibrated parameter, setup the arguments
|
506
|
+
# for s, step in enumerate(steps):
|
507
|
+
# param_names, bounds, objfunc = utils.get_step_info(steps, s)
|
508
|
+
# # maybe clone args?
|
509
|
+
# args_s[s] = args
|
510
|
+
# args_s[s]['step_param_names'] = param_names
|
511
|
+
# args_s[s]['step_objfunc'] = objfunc
|
512
|
+
# # get calibrated parameter from all other steps
|
513
|
+
# args_s[s]['calib_params'] = utils.get_calibrated_params(steps, s)
|
514
|
+
#
|
515
|
+
# args_s[s]['req_queue'] = req_queue
|
516
|
+
#
|
517
|
+
# # create optimizer in the first round.
|
518
|
+
# print('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names,
|
519
|
+
# args_s[s]['calib_params']))
|
520
|
+
#
|
521
|
+
# # perform optimization
|
522
|
+
# s_threads = []
|
523
|
+
# for s, step in enumerate(steps):
|
524
|
+
# s_thread = threading.Thread(target=step_thread, args=(s, args_s[s]))
|
525
|
+
# s_threads.append(s_thread)
|
526
|
+
# s_thread.start()
|
527
|
+
#
|
528
|
+
# for t in s_threads:
|
529
|
+
# t.join()
|
530
|
+
#
|
531
|
+
# # eval cost
|
532
|
+
# for s, step in enumerate(steps):
|
533
|
+
# # capture the best cost
|
534
|
+
# # if cost < best_cost[s] and np.abs(cost - best_cost[s]) > rtol:
|
535
|
+
# if cost[s] < best_cost[s]:
|
536
|
+
# best_cost[s] = cost[s]
|
537
|
+
# no_improvement[s] = False
|
538
|
+
# utils.annotate_step(best_cost[s], pos[s], steps, s)
|
539
|
+
#
|
540
|
+
# print('\n Step {} summary, best particle values: {} '.format(s, pos[s]))
|
541
|
+
#
|
542
|
+
# key = "r{}s{}".format(r + 1, s + 1)
|
543
|
+
# step_trace[key] = copy.deepcopy(steps)
|
544
|
+
#
|
545
|
+
# # print(json.dumps(steps, sort_keys=False, indent=2))
|
546
|
+
#
|
547
|
+
# round_cost = np.sum(best_cost)
|
548
|
+
#
|
549
|
+
# # if no improvement in all steps, break out of rounds prematurely
|
550
|
+
# # but start checking only after min_rounds
|
551
|
+
# # if (r + 1 >= min_rounds) and all(no_improvement):
|
552
|
+
# rel_round_tol = 1 - round_cost / best_round_cost
|
553
|
+
#
|
554
|
+
# print('\n Round summary - round_cost:{}, step_costs: {}, step improvement:{}'
|
555
|
+
# .format(round_cost, best_cost, np.invert(no_improvement)))
|
556
|
+
# print('\n Progress - best_round_cost:{}, rel_round_tol:{}, rtol:{}'
|
557
|
+
# .format(best_round_cost, rel_round_tol, rtol))
|
558
|
+
#
|
559
|
+
# if (r + 1 >= min_rounds) and 0 <= rel_round_tol < rtol:
|
560
|
+
# r_below += 1
|
561
|
+
# if r_below == rounds_below:
|
562
|
+
# break
|
563
|
+
# else:
|
564
|
+
# # reset
|
565
|
+
# r_below = 0
|
566
|
+
#
|
567
|
+
# if round_cost < best_round_cost:
|
568
|
+
# best_round_cost = round_cost
|
569
|
+
#
|
570
|
+
# end_time = datetime.datetime.now()
|
571
|
+
# elapsed = str(end_time - start_time)
|
572
|
+
#
|
573
|
+
# print('Done in {} after {} out of {} rounds'.format(elapsed, r + 1, max_rounds))
|
574
|
+
#
|
575
|
+
# done = True
|
576
|
+
# for worker in thread_pool:
|
577
|
+
# worker.join()
|
578
|
+
#
|
579
|
+
# step_trace['rounds'] = r + 1
|
580
|
+
# step_trace['steps'] = len(steps)
|
581
|
+
# step_trace['iters'] = iters
|
582
|
+
# step_trace['particles'] = n_particles
|
583
|
+
# step_trace['time'] = elapsed
|
584
|
+
#
|
585
|
+
# return optimizer, step_trace
|