mg-pso-gui 0.1.2__tar.gz → 0.1.5__tar.gz

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/PKG-INFO +1 -1
  2. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/PKG-INFO +1 -1
  3. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/SOURCES.txt +10 -1
  4. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/HomePage.py +1 -1
  5. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/util/PSORunner.py +2 -1
  6. mg-pso-gui-0.1.5/mgpsogui/util/recosu/__init__.py +10 -0
  7. mg-pso-gui-0.1.5/mgpsogui/util/recosu/pso/__init__.py +16 -0
  8. mg-pso-gui-0.1.5/mgpsogui/util/recosu/pso/csip_access.py +70 -0
  9. mg-pso-gui-0.1.5/mgpsogui/util/recosu/pso/pso.py +326 -0
  10. mg-pso-gui-0.1.5/mgpsogui/util/recosu/utils/__init__.py +10 -0
  11. mg-pso-gui-0.1.5/mgpsogui/util/recosu/utils/plot/__init__.py +4 -0
  12. mg-pso-gui-0.1.5/mgpsogui/util/recosu/utils/plot/cost_steps.py +111 -0
  13. mg-pso-gui-0.1.5/mgpsogui/util/recosu/utils/trace_writer.py +82 -0
  14. mg-pso-gui-0.1.5/mgpsogui/util/recosu/utils/utils.py +137 -0
  15. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/setup.py +1 -1
  16. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/dependency_links.txt +0 -0
  17. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/entry_points.txt +0 -0
  18. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/requires.txt +0 -0
  19. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mg_pso_gui.egg-info/top_level.txt +0 -0
  20. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/__init__.py +0 -0
  21. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/OptionManager.py +0 -0
  22. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/PlatformTab/PlatformTab.py +0 -0
  23. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/PlatformTab/__init__.py +0 -0
  24. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/RunTab/RunTab.py +0 -0
  25. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/RunTab/__init__.py +0 -0
  26. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/BoundsEditorWindow.py +0 -0
  27. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/BoundsList.py +0 -0
  28. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/CalibrationParametersView.py +0 -0
  29. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/FunctionsList.py +0 -0
  30. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/ListParametersView.py +0 -0
  31. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/SetupTab.py +0 -0
  32. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/StaticParameterView.py +0 -0
  33. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/StepView.py +0 -0
  34. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/SetupTab/__init__.py +0 -0
  35. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/VisualizeTab/VisualizeTab.py +0 -0
  36. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/VisualizeTab/__init__.py +0 -0
  37. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/__init__.py +0 -0
  38. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
  39. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/collapse.png +0 -0
  40. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/down.png +0 -0
  41. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/expand.png +0 -0
  42. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/play.png +0 -0
  43. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/refresh.png +0 -0
  44. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/refresh_hd.png +0 -0
  45. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/stop.png +0 -0
  46. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/trash.png +0 -0
  47. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/gui/images/up.png +0 -0
  48. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/mgpsogui.py +0 -0
  49. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/start.yaml +0 -0
  50. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/util/CTkToolTip/__init__.py +0 -0
  51. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/util/CTkToolTip/ctk_tooltip.py +0 -0
  52. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/util/GraphGenerator.py +0 -0
  53. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/mgpsogui/util/__init__.py +0 -0
  54. {mg-pso-gui-0.1.2 → mg-pso-gui-0.1.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mg-pso-gui
3
- Version: 0.1.2
3
+ Version: 0.1.5
4
4
  Summary: GUI for MG-PSO
5
5
  Author: Robert Cordingly
6
6
  Author-email: <rcording@uw.ed>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: mg-pso-gui
3
- Version: 0.1.2
3
+ Version: 0.1.5
4
4
  Summary: GUI for MG-PSO
5
5
  Author: Robert Cordingly
6
6
  Author-email: <rcording@uw.ed>
@@ -40,4 +40,13 @@ mgpsogui/util/GraphGenerator.py
40
40
  mgpsogui/util/PSORunner.py
41
41
  mgpsogui/util/__init__.py
42
42
  mgpsogui/util/CTkToolTip/__init__.py
43
- mgpsogui/util/CTkToolTip/ctk_tooltip.py
43
+ mgpsogui/util/CTkToolTip/ctk_tooltip.py
44
+ mgpsogui/util/recosu/__init__.py
45
+ mgpsogui/util/recosu/pso/__init__.py
46
+ mgpsogui/util/recosu/pso/csip_access.py
47
+ mgpsogui/util/recosu/pso/pso.py
48
+ mgpsogui/util/recosu/utils/__init__.py
49
+ mgpsogui/util/recosu/utils/trace_writer.py
50
+ mgpsogui/util/recosu/utils/utils.py
51
+ mgpsogui/util/recosu/utils/plot/__init__.py
52
+ mgpsogui/util/recosu/utils/plot/cost_steps.py
@@ -523,7 +523,7 @@ class App(customtkinter.CTk):
523
523
  self.footer_progress_bar.start()
524
524
  self.progress_message_left.configure(text="")
525
525
  self.progress_message_middle.configure(text="Starting new round...")
526
- self.footer_progress_label.configure(text="Continuing...")
526
+ self.footer_progress_label.configure(text="Next round...")
527
527
  self.progress_message_right.configure(text="")
528
528
 
529
529
 
@@ -7,7 +7,8 @@ import threading
7
7
  import time
8
8
  import os
9
9
 
10
- from cosu.pso import global_best
10
+ #from cosu.pso import global_best
11
+ from ...util.recosu.pso import global_best
11
12
 
12
13
  def enqueue_output(out, queue):
13
14
  for line in iter(out.readline, b''):
@@ -0,0 +1,10 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ __version__ = '1.2.8'
4
+ __built__ = '1.2.8 955b3df883a5b6e63e360bf498da9f38cc0953a8 2022-01-27 10:14 -0700 od'
5
+ __author__ = 'Olaf David'
6
+ __email__ = 'odavid@colostate.edu'
7
+
8
+ from .pso import pso
9
+ __all__ = ["pso"]
10
+
@@ -0,0 +1,16 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ """
4
+ LUCA/PSO toolkit
5
+ =========================================
6
+ This is ...
7
+
8
+ """
9
+
10
+ __author__ = """Olaf David"""
11
+ __email__ = "odavid@colostate.edu"
12
+ __version__ = "1.0"
13
+
14
+ from .pso import global_best
15
+
16
+ __all__ = ["global_best"]
@@ -0,0 +1,70 @@
1
+ from cosu import utils
2
+ from csip import Client
3
+ from typing import List, Dict, Tuple
4
+ import queue, os
5
+
6
+
7
+ def csip_worker(reqq: queue.Queue, thread_no: int, stop, full_trace,
8
+ url, files, arg_params, conf: Dict, metainfo: Dict) -> None:
9
+ async_call = conf.get('async_call', True) # default is async
10
+ save_resp = conf.get('save_response_to', None) # save response, set it to a folder if responses should be saved.
11
+
12
+ while not stop():
13
+ try:
14
+ (rnd, step, iteration, particle, x, step_param_names, calib_params, objfunc, resq) = reqq.get(True, 0.5)
15
+ # print(thread_no, particle)
16
+
17
+ c = Client(metainfo=metainfo)
18
+
19
+ # static params (from args)
20
+ for param in arg_params:
21
+ c.add_data(param['name'], param['value'])
22
+
23
+ # particle params (generated from steps)
24
+ # for i, value in enumerate(x):
25
+ for idx, value in enumerate(x[particle, :]):
26
+ c.add_data(step_param_names[idx], value)
27
+
28
+ # other, previously calibrated params (other steps)
29
+ for name, value in calib_params.items():
30
+ c.add_data(name, value)
31
+
32
+ # objective function info
33
+ for of in objfunc:
34
+ c.add_cosu(of['name'], of['of'], of['data'])
35
+ # c.add_data(of['name'], (of['data'][0], of['data'][1]))
36
+
37
+ print('.', end='', flush=True)
38
+
39
+ try:
40
+ # print(c)
41
+ if async_call:
42
+ res = c.execute_async(url, files=files, conf=conf)
43
+ else:
44
+ res = c.execute(url, files=files, conf=conf)
45
+
46
+ if res.is_failed():
47
+ print(res)
48
+
49
+ if save_resp:
50
+ res.save_to(os.path.join(save_resp, 'r{}s{}i{}p{}.json'.format(rnd, step, iteration, particle)))
51
+
52
+ # print(res)
53
+ print(u'\u2714', end='', flush=True)
54
+ cost = utils.calc_cost(res, objfunc)
55
+
56
+ if full_trace is not None:
57
+ all_params = {}
58
+ # for i, value in enumerate(x):
59
+ for idx, value in enumerate(x[particle, :]):
60
+ all_params[step_param_names[idx]] = value
61
+ for name, value in calib_params.items():
62
+ all_params[name] = value
63
+ full_trace.append((all_params, cost))
64
+
65
+ resq.put((particle, cost))
66
+ except:
67
+ print(res)
68
+ reqq.task_done()
69
+ except queue.Empty:
70
+ continue
@@ -0,0 +1,326 @@
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
+
13
+ from ..utils import utils
14
+ from .csip_access import csip_worker
15
+ from pyswarms.single.global_best import GlobalBestPSO
16
+ from os import path
17
+ from threading import Thread
18
+ from typing import Dict, List, Set, Tuple
19
+ import numpy as np
20
+ import copy
21
+ import datetime
22
+ import queue
23
+ import json
24
+ import os
25
+ from multiprocessing import Queue
26
+
27
+
28
+ def eval_cost(x, iteration, step_param_names, step_objfunc, calib_params, req_queue, files, url, param, conf: Dict, rnd,
29
+ step):
30
+ particles = len(x[:, 0])
31
+
32
+ pfail_count = conf.get('particles_fail', 1) # Number of particles allowed to fail.
33
+ pfail_retry = conf.get('particles_retry', 3) # retry number of times if more than allowed fail
34
+
35
+ while pfail_retry > 0:
36
+ cost = np.ones(particles)
37
+ res_queue = queue.Queue()
38
+
39
+ print(' ', end='', flush=True)
40
+
41
+ # submit for processing
42
+ # for i_particle, v in enumerate(x[:, 0]):
43
+ for particle in range(particles):
44
+ req_queue.put((rnd, step, iteration, particle, x, step_param_names, calib_params, step_objfunc, res_queue))
45
+ # req_queue.put((i_particle, x[i_particle,:], step_param_names, calib_params, step_objfunc, res_queue))
46
+
47
+ # wait for the cost value to come back
48
+ # for i, v in enumerate(x[:, 0]):
49
+ for idx in range(particles):
50
+ (particle, p_cost) = res_queue.get()
51
+ cost[particle] = p_cost
52
+ res_queue.task_done()
53
+
54
+ res_queue.join()
55
+
56
+ # replace the 'nan' cost values (failed/missing runs) with the mean of the
57
+ # rest of the cost values, hence ignore it
58
+
59
+ # print("cost ", cost)
60
+ nan_idx = np.where(np.isnan(cost))
61
+ failed_particles = len(nan_idx[0])
62
+
63
+ # leave the loop if fails acceptable
64
+ if failed_particles <= pfail_count:
65
+ break
66
+ print("Re-running particles, since ", failed_particles, ' out of ', particles, ' particles failed.')
67
+ pfail_retry -= 1
68
+
69
+ if pfail_retry == 0:
70
+ print('Particle evaluation failed ', conf.get('particles_retry', 3), ' times. PSO stopped.')
71
+ return None
72
+
73
+ # print("mean ", mean)
74
+ # assign the mean value to all failed runs.
75
+ mean = np.nanmean(cost)
76
+ cost[nan_idx[0]] = mean
77
+
78
+ print(flush=True)
79
+ return cost
80
+
81
+
82
+ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters: int, options: Dict,
83
+ oh_strategy: Dict = None, n_threads: int = 4, rtol: float = 0.001, ftol: float = -np.inf,
84
+ ftol_iter: int = 1, full_trace: List = None, rtol_iter: int = 1,
85
+ conf: Dict = None, metainfo: Dict = None, cost_target: float = -np.inf, result_queue: Queue = None) -> Tuple:
86
+ """Performs a stepwise particle swarm optimization PSO using a global best approach.
87
+
88
+ Parameters
89
+ ----------
90
+ steps : Dict
91
+ step definitions
92
+ rounds : tuple
93
+ round definition, (min,max) or max
94
+ args : Dict
95
+ static service args
96
+ n_particles : int
97
+ number of particles
98
+ iters : int
99
+ number of iterations
100
+ options : Dict
101
+ PSO options (see pyswarms)
102
+ oh_strategy : Dict
103
+ PSO Option handling strategy (see pyswarms)
104
+ n_threads : int
105
+ size of thread pool (default: 4)
106
+ rtol : float
107
+ percentage of change of sum(best_cost) between rounds for
108
+ convergence. (Default is 0.001 0.1%)
109
+ ftol : float
110
+ PSO tolerance (default: -np.inf)
111
+ ftol_iter : float
112
+ number of iterations over which the relative error in
113
+ objective_func is acceptable for convergence. (default: 1)
114
+ full_trace : List
115
+ trace of all runs, list of tuples
116
+ first is dictionary of parameter names to parameter values
117
+ second is the cost value (default: None)
118
+ rtol_iter : int
119
+ the number of subsequent rounds with sum(best_cost) < rtol
120
+ (default: 1)
121
+ conf : Dict
122
+ configuration settings (default: {} )
123
+ metainfo : Dict
124
+ additional metainfo for the csip client (default: {} )
125
+ cost_target: float
126
+ the cost target (default: -np.inf)
127
+ Returns
128
+ -------
129
+ Tuple
130
+ optimizer: List, step_trace: Dict
131
+
132
+ """
133
+
134
+ utils.check_url(args['url'])
135
+
136
+ step_file = conf.get('step_trace', None)
137
+
138
+ min_rounds = 1
139
+ if type(rounds) == tuple:
140
+ min_rounds = rounds[0]
141
+ max_rounds = rounds[1]
142
+ else:
143
+ max_rounds = rounds
144
+
145
+ if min_rounds < 1:
146
+ raise Exception('min rounds >= 1 expected, was "{}"'.format(min_rounds))
147
+
148
+ if max_rounds > 20:
149
+ raise Exception('max rounds <= 20 expected, was "{}"'.format(max_rounds))
150
+
151
+ if n_threads < 1:
152
+ raise Exception('n_threads >= 1, was "{}"'.format(n_threads))
153
+
154
+ if rtol_iter < 1:
155
+ raise Exception('rtol_iter >= 1, was "{}"'.format(rtol_iter))
156
+
157
+ if full_trace is not None and not isinstance(full_trace, list):
158
+ raise Exception('full_trace must be of type, was "{}"'.format(type(full_trace)))
159
+
160
+ best_cost = np.ones(len(steps)) * np.inf
161
+ optimizer = np.empty(len(steps), dtype=object)
162
+
163
+ # trace of steps info
164
+ step_trace = {}
165
+
166
+ step_trace['dir'] = os.getcwd()
167
+ step_trace['start'] = str(datetime.datetime.now())
168
+ step_trace['min_rounds'] = min_rounds
169
+ step_trace['max_rounds'] = max_rounds
170
+ step_trace['iters'] = iters
171
+ step_trace['ftol'] = ftol
172
+ step_trace['ftol_iter'] = ftol_iter
173
+ step_trace['rtol'] = rtol
174
+ step_trace['rtol_iter'] = rtol_iter
175
+ step_trace['n_threads'] = n_threads
176
+ step_trace['n_particles'] = n_particles
177
+ step_trace['n_steps'] = len(steps)
178
+ step_trace['steps'] = copy.deepcopy(steps)
179
+ step_trace['args'] = args
180
+
181
+ if step_file is not None:
182
+ with open(step_file, "w") as fo:
183
+ json.dump(step_trace, fo)
184
+
185
+ # best round cost
186
+ best_round_cost = np.inf
187
+
188
+ # request queue for worker
189
+ req_queue = queue.Queue()
190
+
191
+ conf = conf or {}
192
+ done = False
193
+ thread_pool = []
194
+ for thread_no in range(n_threads):
195
+ worker = Thread(target=csip_worker, args=(req_queue, thread_no, lambda: done,
196
+ full_trace, args['url'], args.get('files', None), args['param'],
197
+ conf, metainfo)
198
+ )
199
+ thread_pool.append(worker)
200
+ worker.start()
201
+
202
+ r_below = 0
203
+ early_exit = False
204
+ start_time = datetime.datetime.now()
205
+ for r in range(max_rounds):
206
+ no_improvement = np.full(len(steps), True)
207
+ for s, step in enumerate(steps):
208
+
209
+ # check if forced exit.
210
+ if path.exists("stop"):
211
+ print('\n>>>>> stop file found, exit now.')
212
+ early_exit = True
213
+ break
214
+
215
+ param_names, bounds, objfunc = utils.get_step_info(steps, s)
216
+ # maybe clone args?
217
+ args['step_param_names'] = param_names
218
+ args['step_objfunc'] = objfunc
219
+ # get calibrated parameter from all other steps
220
+ args['calib_params'] = utils.get_calibrated_params(steps, s)
221
+
222
+ args['req_queue'] = req_queue
223
+ args['conf'] = conf
224
+
225
+ # create optimizer in the first round.
226
+ if optimizer[s] is None:
227
+ optimizer[s] = GlobalBestPSO(step.get('n_particles', n_particles),
228
+ len(param_names),
229
+ oh_strategy=step.get('oh_strategy', oh_strategy),
230
+ options=step.get('options', options),
231
+ bounds=bounds,
232
+ ftol=step.get('ftol', ftol),
233
+ ftol_iter=step.get('ftol_iter', ftol_iter),
234
+ cost_target=step.get('cost_target', cost_target))
235
+ print('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names,
236
+ args['calib_params']))
237
+
238
+
239
+ if result_queue is not None:
240
+ result_queue.put((r + 1, s + 1, param_names, args['calib_params']))
241
+
242
+ args['rnd'] = r + 1
243
+ args['step'] = s + 1
244
+
245
+ # perform optimization
246
+ cost, pos = optimizer[s].optimize(eval_cost, iters=step.get('iters', iters), **args)
247
+ if cost is None:
248
+ early_exit = True
249
+ break
250
+
251
+ # capture the best cost
252
+ # if cost < best_cost[s] and np.abs(cost - best_cost[s]) > rtol:
253
+ if cost < best_cost[s]:
254
+ best_cost[s] = cost
255
+ no_improvement[s] = False
256
+ utils.annotate_step(best_cost[s], pos, steps, s)
257
+
258
+ print('\n Step summary, best particle values: {} '.format(pos))
259
+
260
+ key = "r{}s{}".format(r + 1, s + 1)
261
+ step_trace[key] = {}
262
+ step_trace[key]['time'] = str(datetime.datetime.now())
263
+ step_trace[key]['best_costs'] = best_cost
264
+ step_trace[key]['steps'] = copy.deepcopy(steps)
265
+
266
+ if step_file is not None:
267
+ with open(step_file, "w") as fo:
268
+ json.dump(step_trace, fo)
269
+
270
+ # print(json.dumps(steps, sort_keys=False, indent=2))
271
+
272
+ if early_exit:
273
+ step_trace['exit'] = '1'
274
+ break
275
+
276
+ round_cost = np.sum(best_cost)
277
+
278
+ # if no improvement in all steps, break out of rounds prematurely
279
+ # but start checking only after min_rounds
280
+ # if (r + 1 >= min_rounds) and all(no_improvement):
281
+ rel_round_tol = 1 - round_cost / best_round_cost
282
+
283
+ print('\n Round summary - round_cost:{}, step_costs: {}, step improvement:{}'
284
+ .format(round_cost, best_cost, np.invert(no_improvement)))
285
+ print('\n Progress - best_round_cost:{}, rel_round_tol:{}, rtol:{}'
286
+ .format(best_round_cost, rel_round_tol, rtol))
287
+
288
+ key = "r{}".format(r + 1)
289
+ step_trace[key] = {}
290
+ step_trace[key]['time'] = str(datetime.datetime.now())
291
+ step_trace[key]['round_cost'] = round_cost
292
+ step_trace[key]['best_costs'] = best_cost
293
+ step_trace[key]['improvements'] = no_improvement
294
+ if step_file is not None:
295
+ with open(step_file, "w") as fo:
296
+ json.dump(step_trace, fo)
297
+
298
+ if (r + 1 >= min_rounds) and 0 <= rel_round_tol < rtol:
299
+ r_below += 1
300
+ if r_below >= rtol_iter:
301
+ break
302
+ else:
303
+ # reset
304
+ r_below = 0
305
+
306
+ if round_cost < best_round_cost:
307
+ best_round_cost = round_cost
308
+
309
+ end_time = datetime.datetime.now()
310
+ elapsed = str(end_time - start_time)
311
+
312
+ print('Done in {} after {} out of {} rounds'.format(elapsed, r + 1, max_rounds))
313
+
314
+ done = True
315
+ for worker in thread_pool:
316
+ worker.join()
317
+
318
+ step_trace['rounds'] = r + 1
319
+ step_trace['end'] = str(datetime.datetime.now())
320
+ step_trace['time'] = elapsed
321
+
322
+ if step_file is not None:
323
+ with open(step_file, "w") as fo:
324
+ json.dump(step_trace, fo)
325
+
326
+ return optimizer, step_trace
@@ -0,0 +1,10 @@
1
+ from .utils import *
2
+
3
+
4
+ __all__ = ["get_step_info",
5
+ "get_calibrated_params",
6
+ "annotate_step",
7
+ "NORM",
8
+ "check_url",
9
+ "save",
10
+ "load"]
@@ -0,0 +1,4 @@
1
+
2
+ from .cost_steps import plot_cost_steps
3
+
4
+ __all__ = ["plot_cost_steps"]
@@ -0,0 +1,111 @@
1
+ import matplotlib.pyplot as plt
2
+ import numpy as np
3
+
4
+
5
+ def rs_key(round, step):
6
+ return "r{}s{}".format(round, step)
7
+
8
+
9
+ def get_values(name, s, steps):
10
+ nrounds = steps['rounds']
11
+ vals = []
12
+ for r in range(1, nrounds + 1):
13
+ info = steps[rs_key(r, s)]
14
+ params = info[s - 1]['param']
15
+ for i, p in enumerate(params):
16
+ if name == p['name']:
17
+ vals.append(p['value'])
18
+ return vals
19
+
20
+
21
+ col = ['tab:blue', 'tab:orange', 'tab:green', 'tab:red', 'tab:purple', 'tab:brown']
22
+
23
+
24
+ def plot_cost_steps(optimizer, step_trace):
25
+ nsteps = step_trace['steps']
26
+ nrounds = step_trace['rounds']
27
+ iter = step_trace['iters']
28
+ particles = step_trace['particles']
29
+ time = step_trace['time']
30
+
31
+ total_iter = iter * nrounds
32
+
33
+ x = np.arange(1, total_iter + 1)
34
+ f = plt.figure(figsize=(15, 15))
35
+
36
+ # top plot
37
+ plt.subplot(nsteps + 1, 1, 1)
38
+
39
+ for i in range(nsteps):
40
+ plt.plot(x, optimizer[i].cost_history, label='step ' + str(i + 1), color=col[i + 2])
41
+
42
+ mini = optimizer[0].cost_history
43
+ for i in range(1, nsteps):
44
+ mini = np.maximum(mini, optimizer[i].cost_history)
45
+
46
+ for i, it in enumerate(range(iter, total_iter + 1, iter)):
47
+ plt.axvline(x=it, color='lightgray', linestyle='--')
48
+ plt.text(it, mini[0], ' R' + str(i + 1), color='lightgray')
49
+
50
+ plt.xlim(0, iter * nrounds)
51
+ plt.title('cost function\n (rounds:{} iter:{} particles:{} time:{})'.format(nrounds, iter, particles, time))
52
+ plt.legend()
53
+
54
+ px = np.arange(iter, (nrounds + 1) * iter, iter)
55
+ for s in range(1, nsteps + 1):
56
+
57
+ a = plt.subplot(nsteps + 1, 1, s + 1)
58
+
59
+ plt.subplots_adjust(hspace=0.3)
60
+ plt.xlim(0, iter * nrounds)
61
+ if s == nsteps:
62
+ plt.xlabel('Iterations')
63
+
64
+ # rounds marks
65
+ for i, it in enumerate(range(iter, total_iter + 1, iter)):
66
+ plt.axvline(x=it, color='lightgray', linestyle='--')
67
+
68
+ info = step_trace[rs_key(1, s)][s - 1]
69
+ # print(info['param'])
70
+ i = 0
71
+ params = info['param']
72
+
73
+ p = params[i]
74
+ # print('ax ', plt)
75
+ vals = get_values(p['name'], s, step_trace)
76
+ title = "{}:{:.5f}".format(p['name'], vals[-1])
77
+ a.plot(px, vals, 'v', label=p['name'], color=col[i])
78
+ a.axhline(p['bounds'][0], linestyle='--', color='lightgray')
79
+ a.axhline(p['bounds'][1], linestyle='--', color='lightgray')
80
+ a.set_ylabel(p['name'], color=col[i])
81
+ a.tick_params(axis='y', labelcolor=col[i])
82
+ for x, y in zip(px, vals):
83
+ label = "{:.5f}".format(y)
84
+ a.annotate(label, (x, y), textcoords="offset points", xytext=(0, 10),
85
+ color="gray", ha='center')
86
+ a.legend(loc="center left")
87
+
88
+ if (len(params) > 1):
89
+ sp = a.twinx()
90
+ i = i + 1
91
+ p = params[i]
92
+ vals = get_values(p['name'], s, step_trace)
93
+ title = "{} {}:{:.5f}".format(title, p['name'], vals[-1])
94
+ # title = title + ', ' + p['name'] + ':' + str(vals[-1])
95
+ sp.plot(px, vals, 'v', label=p['name'], color=col[i])
96
+ sp.axhline(p['bounds'][0], linestyle='--', color='lightgray')
97
+ sp.axhline(p['bounds'][1], linestyle='--', color='lightgray')
98
+ sp.set_ylabel(p['name'], color=col[i])
99
+ sp.tick_params(axis='y', labelcolor=col[i])
100
+ for x, y in zip(px, vals):
101
+ label = "{:.5f}".format(y)
102
+ sp.annotate(label, (x, y), textcoords="offset points", xytext=(0, 10),
103
+ color="gray", ha='center')
104
+ sp.legend(loc="right")
105
+
106
+ # print(s, params)
107
+ plt.legend()
108
+ plt.title("step {} ({})".format(s, title))
109
+
110
+ plt.xlabel('Iterations')
111
+ plt.show()
@@ -0,0 +1,82 @@
1
+ from typing import Dict, List, Set, Tuple
2
+
3
+ TraceList = List[Tuple[Dict[str, float], float]]
4
+
5
+
6
+ def write_run_trace(file: str, run_trace: TraceList, num_steps: int = 0, num_runs_per_step: int = 0) -> None:
7
+ if num_steps <= 0 or num_runs_per_step <= 0:
8
+ write_raw_run_trace(file, run_trace)
9
+ return
10
+
11
+ variable_list: List[str] = create_variable_list(run_trace)
12
+ split_trace_list: List[List[TraceList]] = split_trace(
13
+ run_trace, num_steps, num_runs_per_step)
14
+ try:
15
+ with open(file, "w") as writer:
16
+ writer.write("@T,trace\n")
17
+ writer.write("@H,cost,round,step,{}\n".format(",".join(variable_list)))
18
+ round: int = 1
19
+ for round_list in split_trace_list:
20
+ step: int = 1
21
+ for step_list in round_list:
22
+ for param, cost in step_list:
23
+ record = ",{},{},{}".format(cost, round, step)
24
+ for name in variable_list:
25
+ if name in param:
26
+ record += ",{}".format(param[name])
27
+ else:
28
+ record += ","
29
+ writer.write(record + "\n")
30
+ step = step + 1
31
+ round = round + 1
32
+ except IOError:
33
+ print("Failed to write to file {}".format(file))
34
+
35
+
36
+ def write_raw_run_trace(file: str, run_trace: TraceList) -> None:
37
+ variable_list: List[str] = create_variable_list(run_trace)
38
+ try:
39
+ with open(file, "w") as writer:
40
+ writer.write("@T,trace\n")
41
+ writer.write("@H,cost,{}\n".format(",".join(variable_list)))
42
+ for param, cost in run_trace:
43
+ record = ",{}".format(cost)
44
+ for name in variable_list:
45
+ if name in param:
46
+ record += ",{}".format(param[name])
47
+ else:
48
+ record += ","
49
+ writer.write(record + "\n")
50
+ except IOError:
51
+ print("Failed to write to file {}".format(file))
52
+
53
+
54
+ def create_variable_list(run_trace: TraceList) -> List[str]:
55
+ variable_set: Set[str] = set()
56
+ for param, cost in run_trace:
57
+ for name in param.keys():
58
+ variable_set.add(name)
59
+ return list(variable_set)
60
+
61
+
62
+ def split_trace(run_trace: TraceList, num_steps: int, num_runs_per_step: int) -> List[List[TraceList]]:
63
+ step = 1
64
+ i = 0
65
+ split_trace_list: List[List[TraceList]] = list()
66
+ step_list: List[TraceList]
67
+ while i < len(run_trace):
68
+ if step == 1:
69
+ step_list = list()
70
+ split_trace_list.append(step_list)
71
+
72
+ endpoint = i + num_runs_per_step
73
+ if endpoint > len(run_trace):
74
+ endpoint = len(run_trace)
75
+
76
+ step_list.append(run_trace[i:endpoint])
77
+ i = endpoint
78
+ step = step + 1
79
+ if step > num_steps:
80
+ step = 1
81
+
82
+ return split_trace_list
@@ -0,0 +1,137 @@
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
+ from builtins import Exception
13
+
14
+ import requests
15
+ import numpy as np
16
+ import json
17
+ from csip import Client
18
+
19
+ NORM = {
20
+ 'kge': lambda x: 1 - x,
21
+ 'nslog': lambda x: 1 - x,
22
+ 'nslog1p': lambda x: 1 - x,
23
+ 'ns': lambda x: 1 - x,
24
+ 'rmse': lambda x: x,
25
+ 'trmse': lambda x: x,
26
+ 'pbias': lambda x: abs(x)
27
+ }
28
+
29
+
30
+ def calc_cost(response: "Client", objfunc) -> float:
31
+ """aggregated objective function value -> cost"""
32
+
33
+ # this will eliminate the failed run as a candidate solution.
34
+ if not response.is_finished():
35
+ return np.nan
36
+
37
+ cost = 0.0
38
+ for o in objfunc:
39
+ cosu_val = response.get_cosu_value(o['name'])
40
+ if cosu_val is None:
41
+ raise Exception('No cosu of value for ' + o['name'])
42
+ cosu_of = o['of']
43
+ n = NORM.get(cosu_of, lambda x: x) # default
44
+ cost += n(cosu_val) * o.get('weight', 1.0)
45
+
46
+ # of_val = response.get_data_value(of['name'])
47
+ # for name in NORM:
48
+ # if str(c['name']).startswith(name):
49
+ # cost += NORM[name](cosu_val) * c.get('weight', 1.0)
50
+ return cost
51
+
52
+ def save(file, dict):
53
+ """ Save dict to json file. """
54
+ with open(file, 'w') as json_file:
55
+ json.dump(dict, json_file, sort_keys=False, indent=2)
56
+
57
+
58
+ def load(file):
59
+ """ Load dict from json file. """
60
+ with open(file) as json_file:
61
+ data = json.load(json_file)
62
+ return data
63
+
64
+
65
+ def get_step_info(steps, index):
66
+ """Extract all relevant info from the step dict"""
67
+
68
+ step = steps[index]
69
+ l = len(step['param'])
70
+ param_min = np.ones(l)
71
+ param_max = np.ones(l)
72
+ param_names = []
73
+
74
+ # extract names and bounds
75
+ for i, p in enumerate(step['param']):
76
+ param_names.append(p['name'])
77
+ if len(p['bounds']) != 2:
78
+ raise Exception('Invalid bounds tuple: (min, max): "{}"'.format(p['bounds']))
79
+ if not p['bounds'][0] < p['bounds'][1]:
80
+ raise Exception('Invalid bounds values: "{}"'.format(p['bounds']))
81
+ param_min[i] = p['bounds'][0]
82
+ param_max[i] = p['bounds'][1]
83
+
84
+ # check if OF is supported
85
+ for o in step['objfunc']:
86
+ # if not o['name'] in NORM:
87
+ # raise Exception('OF not supported: "{}"'.format(o['name']))
88
+ found = False
89
+ for name in NORM:
90
+ if str(o['name']).startswith(name):
91
+ found = True
92
+ if not found:
93
+ raise Exception('OF not supported: "{}"'.format(o['name']))
94
+ if len(o['data']) != 2:
95
+ raise Exception('OF missing data: (sim, obs): "{}"'.format(o['name']))
96
+
97
+ return param_names, (param_min, param_max), step['objfunc']
98
+
99
+
100
+ def get_calibrated_params(steps, index):
101
+ """Get all previously calibrated parameter from any other step"""
102
+
103
+ step = steps[index]
104
+ cp = {}
105
+ for s in steps:
106
+ # skip the own step
107
+ if s is step:
108
+ continue
109
+ for p in s['param']:
110
+ # if 'value' in p.keys():
111
+ if 'value' in p:
112
+ cp[p['name']] = p['value']
113
+
114
+ # if the step parameter are in any other step, take them out since
115
+ # we rather want to calibrate them
116
+ for p in step['param']:
117
+ if p['name'] in cp:
118
+ cp.pop(p['name'])
119
+
120
+ return cp
121
+
122
+
123
+ def annotate_step(best_cost, pos, steps, index):
124
+ """Annotate the step with the best value"""
125
+
126
+ step = steps[index]
127
+ step['cost'] = best_cost
128
+ for i, p in enumerate(step['param']):
129
+ p['value'] = pos[i]
130
+
131
+
132
+ def check_url(url):
133
+ """Check is the Url is valid."""
134
+
135
+ r = requests.head(url)
136
+ if r.status_code != 200:
137
+ raise Exception('Error code {} from Url: "{}"'.format(r.status_code, url))
@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
2
2
  import codecs
3
3
  import os
4
4
 
5
- VERSION = '0.1.2'
5
+ VERSION = '0.1.5'
6
6
  DESCRIPTION = 'GUI for MG-PSO'
7
7
  LONG_DESCRIPTION = open('../README.md').read()
8
8
 
File without changes