mg-pso-gui 0.1.40__py3-none-any.whl → 0.2.75__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.
Files changed (50) hide show
  1. {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/METADATA +10 -11
  2. mg_pso_gui-0.2.75.dist-info/RECORD +76 -0
  3. {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/WHEEL +1 -1
  4. mgpsogui/gui/General/ParameterView.py +110 -0
  5. mgpsogui/gui/General/__init__.py +0 -0
  6. mgpsogui/gui/HomePage.py +234 -238
  7. mgpsogui/gui/OptionManager.py +333 -145
  8. mgpsogui/gui/OptionManager_backup.py +443 -0
  9. mgpsogui/gui/PlatformTab/PlatformTab.py +15 -6
  10. mgpsogui/gui/RunTab/OptimalParameterView.py +47 -0
  11. mgpsogui/gui/RunTab/RunTab.py +90 -17
  12. mgpsogui/gui/SetupTab/BoundsEditorWindow.py +1 -1
  13. mgpsogui/gui/SetupTab/BoundsList.py +97 -34
  14. mgpsogui/gui/SetupTab/CustomFunctionEditorWindow.py +74 -0
  15. mgpsogui/gui/SetupTab/CustomFunctionMetrics.py +156 -0
  16. mgpsogui/gui/SetupTab/FunctionsList.py +60 -6
  17. mgpsogui/gui/SetupTab/{StaticParameterView.py → ListEditor.py} +27 -16
  18. mgpsogui/gui/SetupTab/ListParametersView.py +7 -6
  19. mgpsogui/gui/SetupTab/{CalibrationParametersView.py → OverrideParameterMetrics.py} +35 -9
  20. mgpsogui/gui/SetupTab/OverrideParameterWindow.py +40 -0
  21. mgpsogui/gui/SetupTab/SetupTab.py +31 -11
  22. mgpsogui/gui/SetupTab/StepView.py +93 -22
  23. mgpsogui/gui/VisualizeTab/MatrixEditor.py +68 -0
  24. mgpsogui/gui/VisualizeTab/SideBar.py +316 -25
  25. mgpsogui/gui/VisualizeTab/VisualizeTab.py +69 -8
  26. mgpsogui/gui/defaults/__init__.py +0 -0
  27. mgpsogui/gui/defaults/optimization.json +176 -0
  28. mgpsogui/gui/defaults/sampling.json +111 -0
  29. mgpsogui/gui/defaults/sensitivity.json +20 -0
  30. mgpsogui/gui/images/plus.png +0 -0
  31. mgpsogui/util/GraphGenerator.py +721 -50
  32. mgpsogui/util/PSORunner.py +615 -86
  33. mgpsogui/util/debug.py +559 -0
  34. mgpsogui/util/helpers.py +95 -0
  35. mgpsogui/util/recosu/__init__.py +2 -1
  36. mgpsogui/util/recosu/pso/pso.py +55 -11
  37. mgpsogui/util/recosu/sampling/__init__.py +16 -0
  38. mgpsogui/util/recosu/sampling/halton/__init__.py +0 -0
  39. mgpsogui/util/recosu/sampling/halton/halton.py +45 -0
  40. mgpsogui/util/recosu/sampling/halton/prime.py +82 -0
  41. mgpsogui/util/recosu/sampling/random/__init__.py +0 -0
  42. mgpsogui/util/recosu/sampling/random/random_sampler.py +34 -0
  43. mgpsogui/util/recosu/sampling/sample_trace_writer.py +47 -0
  44. mgpsogui/util/recosu/sampling/sampler_task.py +75 -0
  45. mgpsogui/util/recosu/sampling/sampling.py +99 -0
  46. mgpsogui/util/sampler_test_driver.py +129 -0
  47. mg_pso_gui-0.1.40.dist-info/RECORD +0 -52
  48. mgpsogui/gui/images/IGOW 4 Logo.png +0 -0
  49. {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/entry_points.txt +0 -0
  50. {mg_pso_gui-0.1.40.dist-info → mg_pso_gui-0.2.75.dist-info}/top_level.txt +0 -0
@@ -22,7 +22,7 @@ import datetime
22
22
  import queue
23
23
  import json
24
24
  import os
25
- from multiprocessing import Queue
25
+ from multiprocessing import Queue as MPQueue
26
26
 
27
27
 
28
28
  def eval_cost(x, iteration, step_param_names, step_objfunc, calib_params, req_queue, files, url, param, conf: Dict, rnd,
@@ -82,7 +82,7 @@ def eval_cost(x, iteration, step_param_names, step_objfunc, calib_params, req_qu
82
82
  def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters: int, options: Dict,
83
83
  oh_strategy: Dict = None, n_threads: int = 4, rtol: float = 0.001, ftol: float = -np.inf,
84
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:
85
+ conf: Dict = None, metainfo: Dict = None, cost_target: float = -np.inf, result_queue: MPQueue = None) -> Tuple:
86
86
  """Performs a stepwise particle swarm optimization PSO using a global best approach.
87
87
 
88
88
  Parameters
@@ -168,7 +168,15 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
168
168
  step_trace['min_rounds'] = min_rounds
169
169
  step_trace['max_rounds'] = max_rounds
170
170
  step_trace['iters'] = iters
171
- step_trace['ftol'] = ftol
171
+
172
+ # BUG If ftol is -inf set it to a string
173
+ ftol_value = ftol
174
+ if ftol == -np.inf:
175
+ ftol_value = '-inf'
176
+ elif ftol == np.inf:
177
+ ftol_value = 'inf'
178
+
179
+ step_trace['ftol'] = ftol_value
172
180
  step_trace['ftol_iter'] = ftol_iter
173
181
  step_trace['rtol'] = rtol
174
182
  step_trace['rtol_iter'] = rtol_iter
@@ -176,17 +184,21 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
176
184
  step_trace['n_particles'] = n_particles
177
185
  step_trace['n_steps'] = len(steps)
178
186
  step_trace['steps'] = copy.deepcopy(steps)
179
- step_trace['args'] = args
187
+ step_trace['args'] = str(args) #BUG MUST BE REMOVED
180
188
 
181
189
  if step_file is not None:
182
190
  with open(step_file, "w") as fo:
183
191
  json.dump(step_trace, fo)
184
192
 
193
+ print("Wrote step trace")
194
+
185
195
  # best round cost
186
196
  best_round_cost = np.inf
187
197
 
188
198
  # request queue for worker
189
199
  req_queue = queue.Queue()
200
+
201
+ print("Created queue")
190
202
 
191
203
  conf = conf or {}
192
204
  done = False
@@ -199,6 +211,8 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
199
211
  thread_pool.append(worker)
200
212
  worker.start()
201
213
 
214
+ print("Started worker threads")
215
+
202
216
  r_below = 0
203
217
  early_exit = False
204
218
  start_time = datetime.datetime.now()
@@ -222,6 +236,8 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
222
236
  args['req_queue'] = req_queue
223
237
  args['conf'] = conf
224
238
 
239
+ print("Calling global best..")
240
+
225
241
  # create optimizer in the first round.
226
242
  if optimizer[s] is None:
227
243
  optimizer[s] = GlobalBestPSO(step.get('n_particles', n_particles),
@@ -232,21 +248,27 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
232
248
  ftol=step.get('ftol', ftol),
233
249
  ftol_iter=step.get('ftol_iter', ftol_iter),
234
250
  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']))
251
+
252
+ print('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names, args['calib_params']))
237
253
 
238
- if result_queue is not None:
239
- result_queue.put('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names, args['calib_params']))
254
+ #if result_queue is not None:
255
+ # result_queue.put('\n>>>>> R{}/S{} particle params: {} calibrated params: {}\n'.format(r + 1, s + 1, param_names, args['calib_params']))
256
+
257
+ print("Filled request queue...")
240
258
 
241
259
  args['rnd'] = r + 1
242
260
  args['step'] = s + 1
243
261
 
262
+ print("Evaluating cost...")
263
+
244
264
  # perform optimization
245
265
  cost, pos = optimizer[s].optimize(eval_cost, iters=step.get('iters', iters), **args)
246
266
  if cost is None:
247
267
  early_exit = True
248
268
  break
249
269
 
270
+ print("Finished evaluation...")
271
+
250
272
  # capture the best cost
251
273
  # if cost < best_cost[s] and np.abs(cost - best_cost[s]) > rtol:
252
274
  if cost < best_cost[s]:
@@ -262,7 +284,16 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
262
284
  key = "r{}s{}".format(r + 1, s + 1)
263
285
  step_trace[key] = {}
264
286
  step_trace[key]['time'] = str(datetime.datetime.now())
265
- step_trace[key]['best_costs'] = best_cost
287
+
288
+ best_costs_list = best_cost.tolist()
289
+ # If the cost is inf, set it to a string
290
+ for i, c in enumerate(best_costs_list):
291
+ if c == np.inf:
292
+ best_costs_list[i] = 'inf'
293
+ elif c == -np.inf:
294
+ best_costs_list[i] = '-inf'
295
+
296
+ step_trace[key]['best_costs'] = best_costs_list # BUG
266
297
  step_trace[key]['steps'] = copy.deepcopy(steps)
267
298
 
268
299
  if step_file is not None:
@@ -299,8 +330,17 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
299
330
  step_trace[key] = {}
300
331
  step_trace[key]['time'] = str(datetime.datetime.now())
301
332
  step_trace[key]['round_cost'] = round_cost
302
- step_trace[key]['best_costs'] = best_cost
303
- step_trace[key]['improvements'] = no_improvement
333
+
334
+ best_costs_list = best_cost.tolist() #BUG
335
+ # If the cost is inf, set it to a string
336
+ for i, c in enumerate(best_costs_list):
337
+ if c == np.inf:
338
+ best_costs_list[i] = 'inf'
339
+ elif c == -np.inf:
340
+ best_costs_list[i] = '-inf'
341
+
342
+ step_trace[key]['best_costs'] = best_costs_list
343
+ step_trace[key]['improvements'] = no_improvement.tolist()
304
344
  if step_file is not None:
305
345
  with open(step_file, "w") as fo:
306
346
  json.dump(step_trace, fo)
@@ -336,4 +376,8 @@ def global_best(steps: Dict, rounds: Tuple, args: Dict, n_particles: int, iters:
336
376
  with open(step_file, "w") as fo:
337
377
  json.dump(step_trace, fo)
338
378
 
379
+ if result_queue is not None:
380
+ result_queue.put("Step Trace")
381
+ result_queue.put(step_trace)
382
+
339
383
  return optimizer, step_trace
@@ -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 .sampling import run_sampler
15
+
16
+ __all__ = ["run_sampler"]
File without changes
@@ -0,0 +1,45 @@
1
+ from collections.abc import Iterable
2
+ import math
3
+ from ...sampling.halton.prime import generate_n_primes
4
+
5
+
6
+ def halton(index: int, base: int) -> float:
7
+ fraction: float = 1.0
8
+ result: float = 0
9
+
10
+ while index > 0:
11
+ fraction = fraction / base
12
+ result += fraction * (index % base)
13
+ index = math.floor(index / base)
14
+
15
+ return result
16
+
17
+
18
+ class HaltonSampleGenerator:
19
+ index: int
20
+ maxIndex: int
21
+ primes: list[int]
22
+
23
+ def __init__(self, count: int, offset: int, num_parameters: int):
24
+ assert (count > 0)
25
+ assert (offset >= 0)
26
+ self.index = offset + 1
27
+ self.maxIndex = offset + count + 1
28
+ self.primes = generate_n_primes(num_parameters)
29
+
30
+ def __iter__(self) -> Iterable[tuple[int, list[float]]]:
31
+ return self
32
+
33
+ def __next__(self) -> tuple[int, list[float]]:
34
+ if self.index >= self.maxIndex:
35
+ raise StopIteration
36
+
37
+ i = 0
38
+ values: list[float] = []
39
+ for base in self.primes:
40
+ values.append(halton(self.index, base))
41
+
42
+ result: tuple[int, list[float]] = (self.index, values)
43
+ self.index = self.index + 1
44
+ return result
45
+
@@ -0,0 +1,82 @@
1
+ from typing import List
2
+
3
+ PRIME_TABLE: List[int] = [
4
+ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
5
+ 31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
6
+ 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
7
+ 127, 131, 137, 139, 149, 151, 157, 163, 167, 173,
8
+ 179, 181, 191, 193, 197, 199, 211, 223, 227, 229,
9
+ 233, 239, 241, 251, 257, 263, 269, 271, 277, 281,
10
+ 283, 293, 307, 311, 313, 317, 331, 337, 347, 349,
11
+ 353, 359, 367, 373, 379, 383, 389, 397, 401, 409,
12
+ 419, 421, 431, 433, 439, 443, 449, 457, 461, 463,
13
+ 467, 479, 487, 491, 499, 503, 509, 521, 523, 541,
14
+ 547, 557, 563, 569, 571, 577, 587, 593, 599, 601,
15
+ 607, 613, 617, 619, 631, 641, 643, 647, 653, 659,
16
+ 661, 673, 677, 683, 691, 701, 709, 719, 727, 733,
17
+ 739, 743, 751, 757, 761, 769, 773, 787, 797, 809,
18
+ 811, 821, 823, 827, 829, 839, 853, 857, 859, 863,
19
+ 877, 881, 883, 887, 907, 911, 919, 929, 937, 941,
20
+ 947, 953, 967, 971, 977, 983, 991, 997, 1009, 1013,
21
+ 1019, 1021, 1031, 1033, 1039, 1049, 1051, 1061, 1063, 1069,
22
+ 1087, 1091, 1093, 1097, 1103, 1109, 1117, 1123, 1129, 1151,
23
+ 1153, 1163, 1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
24
+ 1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283, 1289, 1291,
25
+ 1297, 1301, 1303, 1307, 1319, 1321, 1327, 1361, 1367, 1373,
26
+ 1381, 1399, 1409, 1423, 1427, 1429, 1433, 1439, 1447, 1451,
27
+ 1453, 1459, 1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
28
+ 1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571, 1579, 1583,
29
+ 1597, 1601, 1607, 1609, 1613, 1619, 1621, 1627, 1637, 1657,
30
+ 1663, 1667, 1669, 1693, 1697, 1699, 1709, 1721, 1723, 1733,
31
+ 1741, 1747, 1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
32
+ 1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877, 1879, 1889,
33
+ 1901, 1907, 1913, 1931, 1933, 1949, 1951, 1973, 1979, 1987,
34
+ 1993, 1997, 1999, 2003, 2011, 2017, 2027, 2029, 2039, 2053,
35
+ 2063, 2069, 2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
36
+ 2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203, 2207, 2213,
37
+ 2221, 2237, 2239, 2243, 2251, 2267, 2269, 2273, 2281, 2287,
38
+ 2293, 2297, 2309, 2311, 2333, 2339, 2341, 2347, 2351, 2357,
39
+ 2371, 2377, 2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
40
+ 2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503, 2521, 2531,
41
+ 2539, 2543, 2549, 2551, 2557, 2579, 2591, 2593, 2609, 2617,
42
+ 2621, 2633, 2647, 2657, 2659, 2663, 2671, 2677, 2683, 2687,
43
+ 2689, 2693, 2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
44
+ 2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801, 2803, 2819,
45
+ 2833, 2837, 2843, 2851, 2857, 2861, 2879, 2887, 2897, 2903,
46
+ 2909, 2917, 2927, 2939, 2953, 2957, 2963, 2969, 2971, 2999,
47
+ 3001, 3011, 3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
48
+ 3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167, 3169, 3181,
49
+ 3187, 3191, 3203, 3209, 3217, 3221, 3229, 3251, 3253, 3257,
50
+ 3259, 3271, 3299, 3301, 3307, 3313, 3319, 3323, 3329, 3331,
51
+ 3343, 3347, 3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
52
+ 3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491, 3499, 3511,
53
+ 3517, 3527, 3529, 3533, 3539, 3541, 3547, 3557, 3559, 3571,
54
+ 3581, 3583, 3593, 3607, 3613, 3617, 3623, 3631, 3637, 3643,
55
+ 3659, 3671, 3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
56
+ 3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797, 3803, 3821,
57
+ 3823, 3833, 3847, 3851, 3853, 3863, 3877, 3881, 3889, 3907,
58
+ 3911, 3917, 3919, 3923, 3929, 3931, 3943, 3947, 3967, 3989,
59
+ 4001, 4003, 4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
60
+ 4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129, 4133, 4139,
61
+ 4153, 4157, 4159, 4177, 4201, 4211, 4217, 4219, 4229, 4231,
62
+ 4241, 4243, 4253, 4259, 4261, 4271, 4273, 4283, 4289, 4297,
63
+ 4327, 4337, 4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409
64
+ ]
65
+
66
+
67
+ def generate_n_primes(n: int) -> List[int]:
68
+ if n < len(PRIME_TABLE):
69
+ return PRIME_TABLE[0:n]
70
+
71
+ primes: List[int] = PRIME_TABLE.copy()
72
+ num: int = primes[-1] + 2
73
+ while len(primes) < n:
74
+ is_prime = True
75
+ for p in primes:
76
+ if num % p == 0:
77
+ is_prime = False
78
+ break
79
+ if is_prime:
80
+ primes.append(num)
81
+ num += 2
82
+ return primes
File without changes
@@ -0,0 +1,34 @@
1
+ from collections.abc import Iterable
2
+ import random
3
+
4
+
5
+ class RandomSampleGenerator:
6
+ index: int
7
+ count: int
8
+ num_parameters: int
9
+ rand: random.Random
10
+
11
+ def __init__(self, count: int, num_parameters: int):
12
+ assert (count > 0)
13
+ self.index = 1
14
+ self.count = count + 1
15
+ self.num_parameters = num_parameters
16
+ self.rand = random.Random()
17
+
18
+ def __iter__(self) -> Iterable[tuple[int, list[float]]]:
19
+ return self
20
+
21
+ def __next__(self) -> tuple[int, list[float]]:
22
+ if self.index >= self.count:
23
+ raise StopIteration
24
+
25
+ i: int = 0
26
+ values: list[float] = []
27
+ while i < self.num_parameters:
28
+ values.append(self.rand.uniform(0, 1))
29
+ i = i + 1
30
+
31
+ result: tuple[int, list[float]] = (self.index, values)
32
+ self.index = self.index + 1
33
+ return result
34
+
@@ -0,0 +1,47 @@
1
+ import threading
2
+
3
+
4
+ class SampleTraceWriter:
5
+ trace_file: str
6
+ parameter_indices: dict[int, str]
7
+ objective_indices: dict[int, str]
8
+ write_lock: threading.Lock
9
+
10
+ def __init__(self, trace_file: str):
11
+ assert(trace_file is not None and len(trace_file) > 0)
12
+ self.trace_file = trace_file
13
+ self.parameter_indices = {}
14
+ self.objective_indices = {}
15
+ self.write_lock = threading.Lock()
16
+
17
+ def write_header(self, parameter_names: list[str], objective_names: list[str]) -> None:
18
+ with self.write_lock:
19
+ with open(self.trace_file, 'w') as writer:
20
+ writer.write("id")
21
+ self.parameter_indices = {}
22
+ index: int = 0
23
+ for name in parameter_names:
24
+ writer.write(",{}".format(name))
25
+ self.parameter_indices[index] = name
26
+ index = index + 1
27
+ self.objective_indices = {}
28
+ index = 0
29
+ for name in objective_names:
30
+ writer.write(",{}".format(name))
31
+ self.objective_indices[index] = name
32
+ index = index + 1
33
+ writer.write("\n")
34
+
35
+ def append_sample(self, sample_id: int, parameters: dict[str, any], objectives: dict[str, any]) -> None:
36
+ with self.write_lock:
37
+ with open(self.trace_file, 'a') as writer:
38
+ writer.write("{}".format(sample_id))
39
+ index: int = 0
40
+ while index < len(self.parameter_indices):
41
+ writer.write(",{}".format(parameters[self.parameter_indices[index]]))
42
+ index = index + 1
43
+ index = 0
44
+ while index < len(self.objective_indices):
45
+ writer.write(",{}".format(objectives[self.objective_indices[index]]))
46
+ index = index + 1
47
+ writer.write("\n")
@@ -0,0 +1,75 @@
1
+ import os
2
+ from csip import Client
3
+
4
+
5
+ class SamplerTask:
6
+ task_id: int
7
+ parameters: dict[str, any]
8
+ objectives: list[dict[str, any]]
9
+ static_parameters: dict[str, any]
10
+ url: str
11
+ files: list[str]
12
+ metainfo: dict[str, any]
13
+ conf: dict[str, any]
14
+ result: dict[str, any]
15
+
16
+ def __init__(self, task_id: int, parameters: dict[str, any], objectives: list[dict[str, any]],
17
+ static_parameters: dict[str, any], url: str, files: list[str] = None, metainfo: dict[str, any] = None,
18
+ conf: dict[str, any] = None):
19
+ self.task_id = task_id
20
+ assert (parameters is not None and len(parameters) > 0)
21
+ self.parameters = parameters
22
+ assert (objectives is not None and len(objectives) > 0)
23
+ self.objectives = objectives
24
+ self.static_parameters = static_parameters if static_parameters is not None else []
25
+ assert (url is not None and len(url) > 0)
26
+ self.url = url
27
+ self.files = files if files is not None else []
28
+ self.metainfo = metainfo
29
+ self.conf = conf
30
+
31
+ def create_request(self) -> Client:
32
+ request: Client = Client(metainfo=self.metainfo)
33
+
34
+ for key, value in self.static_parameters.items():
35
+ request.add_data(key, value)
36
+
37
+ for key, value in self.parameters.items():
38
+ request.add_data(key, value)
39
+
40
+ for of in self.objectives:
41
+ request.add_cosu(of['name'], of['of'], of['data'])
42
+
43
+ return request
44
+
45
+ def run_task(self) -> bool:
46
+ self.result = {}
47
+ request: Client = self.create_request()
48
+ async_call: bool = self.conf.get('async_call', True) if self.conf is not None else True
49
+ # save response, set it to a folder if responses should be saved.
50
+ save_resp = self.conf.get('save_response_to', None) if self.conf is not None else None
51
+ successful: bool = False
52
+
53
+ response: Client = None
54
+ try:
55
+ if async_call:
56
+ response = request.execute_async(self.url, files=self.files, conf=self.conf)
57
+ else:
58
+ response = request.execute(self.url, files=self.files, conf=self.conf)
59
+
60
+ successful = response.is_finished()
61
+ if not successful:
62
+ print(response)
63
+
64
+ if save_resp:
65
+ response.save_to(os.path.join(save_resp, 'task_{}.json'.format(self.task_id)))
66
+
67
+ objectives: list[dict[str, str]] = response.get_metainfo("cosu")
68
+ for of in objectives:
69
+ self.result[of["name"]] = of["value"]
70
+ except Exception as ex:
71
+ print(ex)
72
+ print(response)
73
+ successful = False
74
+
75
+ return successful
@@ -0,0 +1,99 @@
1
+ from collections.abc import Iterable
2
+ import math
3
+ import asyncio
4
+ import concurrent
5
+ import datetime
6
+ from ..utils import utils
7
+ from ..sampling.halton.halton import HaltonSampleGenerator
8
+ from ..sampling.random.random_sampler import RandomSampleGenerator
9
+ from ..sampling.sampler_task import SamplerTask
10
+ from ..sampling.sample_trace_writer import SampleTraceWriter
11
+
12
+
13
+ def weighted_value(weight: float, lower: float, upper: float) -> float:
14
+ return lower + weight * (upper - lower)
15
+
16
+
17
+ def get_static_parameters(args: dict[str, any]) -> dict[str, any]:
18
+ static_parameters: dict[str, any] = {}
19
+ for param in args["param"]:
20
+ static_parameters[param["name"]] = param["value"]
21
+ return static_parameters
22
+
23
+
24
+ def get_objective_names(objfunc: dict[str, any]) -> list[str]:
25
+ objective_names: list[str] = []
26
+ for of in objfunc:
27
+ objective_names.append(of["name"])
28
+ return objective_names
29
+
30
+
31
+ def thread_function(task: SamplerTask) -> tuple[bool, SamplerTask]:
32
+ return task.run_task(), task
33
+
34
+
35
+ def create_generator(method: str, count: int, num_parameters: int, **kwargs) -> Iterable[tuple[int, list[float]]]:
36
+ if method == "halton":
37
+ offset: int = 0
38
+ if "offset" in kwargs:
39
+ offset = kwargs["offset"]
40
+ return HaltonSampleGenerator(count, offset, num_parameters)
41
+ elif method == "random":
42
+ return RandomSampleGenerator(count, num_parameters)
43
+
44
+ raise Exception("Sampling method is not recognized")
45
+
46
+
47
+ def run_sampler(steps: list[dict[str, any]], args: dict[str, any], count: int, num_threads: int, method: str = "halton",
48
+ metainfo: dict[str, any] = None, conf: dict[str, any] = None, trace_file: str = "trace.csv",
49
+ **kwargs) -> dict[int, tuple[dict[str, any], dict[str, any]]]:
50
+ param_names, bounds, objfunc = utils.get_step_info(steps, 0)
51
+ generator: Iterable[tuple[int, list[float]]] = create_generator(method, count, len(param_names), **kwargs)
52
+ objective_names: list[str] = get_objective_names(objfunc)
53
+ static_parameters: dict[str, any] = get_static_parameters(args)
54
+ url: str = args["url"]
55
+ files: list[str] = args["files"]
56
+
57
+ trace: dict[int, tuple[dict[str, float], dict[str, float]]] = {}
58
+ trace_writer: SampleTraceWriter = SampleTraceWriter(trace_file)
59
+ trace_writer.write_header(param_names, objective_names)
60
+
61
+ with concurrent.futures.ThreadPoolExecutor(max_workers=num_threads) as executor:
62
+ futures = []
63
+ for sample_id, sample in generator:
64
+ params: dict[str, float] = {}
65
+ index: int = 0
66
+ while index < len(sample):
67
+ params[param_names[index]] = weighted_value(sample[index], bounds[0][index], bounds[1][index])
68
+ index += 1
69
+
70
+ task: SamplerTask = SamplerTask(sample_id, params, objfunc, static_parameters, url, files, metainfo, conf)
71
+ futures.append(executor.submit(thread_function, task))
72
+ # for future in concurrent.futures.as_completed(futures):
73
+ # pass
74
+ num_finished: int = 0
75
+ percentage: float
76
+ last_percentage: float = 0
77
+ for future in concurrent.futures.as_completed(futures):
78
+ try:
79
+ successful, task = future.result()
80
+
81
+ if successful:
82
+ trace[task.task_id] = (task.parameters, task.result)
83
+ trace_writer.append_sample(task.task_id, task.parameters, task.result)
84
+ else:
85
+ print("Failed to successfully execute task: {}", task.task_id, flush=True)
86
+ except asyncio.CancelledError as ce:
87
+ pass
88
+ except asyncio.InvalidStateError as ise:
89
+ pass
90
+ except Exception as ex:
91
+ print(ex, flush=True)
92
+
93
+ num_finished = num_finished + 1
94
+ percentage = math.trunc(num_finished / count * 1000) / 10
95
+ if percentage > last_percentage:
96
+ last_percentage = percentage
97
+ print("{}% Done {}".format(percentage, datetime.datetime.now()), flush=True)
98
+
99
+ return trace