moospread 0.1.0__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.
- moospread/__init__.py +3 -0
- moospread/core.py +1881 -0
- moospread/problem.py +193 -0
- moospread/tasks/__init__.py +4 -0
- moospread/tasks/dtlz_torch.py +139 -0
- moospread/tasks/mw_torch.py +274 -0
- moospread/tasks/re_torch.py +394 -0
- moospread/tasks/zdt_torch.py +112 -0
- moospread/utils/__init__.py +8 -0
- moospread/utils/constraint_utils/__init__.py +2 -0
- moospread/utils/constraint_utils/gradient.py +72 -0
- moospread/utils/constraint_utils/mgda_core.py +69 -0
- moospread/utils/constraint_utils/pmgda_solver.py +308 -0
- moospread/utils/constraint_utils/prefs.py +64 -0
- moospread/utils/ditmoo.py +127 -0
- moospread/utils/lhs.py +74 -0
- moospread/utils/misc.py +28 -0
- moospread/utils/mobo_utils/__init__.py +11 -0
- moospread/utils/mobo_utils/evolution/__init__.py +0 -0
- moospread/utils/mobo_utils/evolution/dom.py +60 -0
- moospread/utils/mobo_utils/evolution/norm.py +40 -0
- moospread/utils/mobo_utils/evolution/utils.py +97 -0
- moospread/utils/mobo_utils/learning/__init__.py +0 -0
- moospread/utils/mobo_utils/learning/model.py +40 -0
- moospread/utils/mobo_utils/learning/model_init.py +33 -0
- moospread/utils/mobo_utils/learning/model_update.py +51 -0
- moospread/utils/mobo_utils/learning/prediction.py +116 -0
- moospread/utils/mobo_utils/learning/utils.py +143 -0
- moospread/utils/mobo_utils/lhs_for_mobo.py +243 -0
- moospread/utils/mobo_utils/mobo/__init__.py +0 -0
- moospread/utils/mobo_utils/mobo/acquisition.py +209 -0
- moospread/utils/mobo_utils/mobo/algorithms.py +91 -0
- moospread/utils/mobo_utils/mobo/factory.py +86 -0
- moospread/utils/mobo_utils/mobo/mobo.py +132 -0
- moospread/utils/mobo_utils/mobo/selection.py +182 -0
- moospread/utils/mobo_utils/mobo/solver/__init__.py +5 -0
- moospread/utils/mobo_utils/mobo/solver/moead.py +17 -0
- moospread/utils/mobo_utils/mobo/solver/nsga2.py +10 -0
- moospread/utils/mobo_utils/mobo/solver/parego/__init__.py +1 -0
- moospread/utils/mobo_utils/mobo/solver/parego/parego.py +62 -0
- moospread/utils/mobo_utils/mobo/solver/parego/utils.py +34 -0
- moospread/utils/mobo_utils/mobo/solver/pareto_discovery/__init__.py +1 -0
- moospread/utils/mobo_utils/mobo/solver/pareto_discovery/buffer.py +364 -0
- moospread/utils/mobo_utils/mobo/solver/pareto_discovery/pareto_discovery.py +571 -0
- moospread/utils/mobo_utils/mobo/solver/pareto_discovery/utils.py +168 -0
- moospread/utils/mobo_utils/mobo/solver/solver.py +74 -0
- moospread/utils/mobo_utils/mobo/surrogate_model/__init__.py +2 -0
- moospread/utils/mobo_utils/mobo/surrogate_model/base.py +36 -0
- moospread/utils/mobo_utils/mobo/surrogate_model/gaussian_process.py +177 -0
- moospread/utils/mobo_utils/mobo/surrogate_model/thompson_sampling.py +79 -0
- moospread/utils/mobo_utils/mobo/surrogate_problem.py +44 -0
- moospread/utils/mobo_utils/mobo/transformation.py +106 -0
- moospread/utils/mobo_utils/mobo/utils.py +65 -0
- moospread/utils/mobo_utils/spread_mobo_utils.py +854 -0
- moospread/utils/offline_utils/__init__.py +10 -0
- moospread/utils/offline_utils/handle_task.py +203 -0
- moospread/utils/offline_utils/proxies.py +338 -0
- moospread/utils/spread_utils.py +91 -0
- moospread-0.1.0.dist-info/METADATA +75 -0
- moospread-0.1.0.dist-info/RECORD +63 -0
- moospread-0.1.0.dist-info/WHEEL +5 -0
- moospread-0.1.0.dist-info/licenses/LICENSE +10 -0
- moospread-0.1.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
from sklearn.preprocessing import StandardScaler
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
'''
|
|
6
|
+
Data transformations (normalizations) for fitting surrogate model
|
|
7
|
+
'''
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### 1-dim scaler
|
|
11
|
+
|
|
12
|
+
class Scaler(ABC):
|
|
13
|
+
|
|
14
|
+
def fit(self, X):
|
|
15
|
+
return self
|
|
16
|
+
|
|
17
|
+
@abstractmethod
|
|
18
|
+
def transform(self, X):
|
|
19
|
+
pass
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def inverse_transform(self, X):
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class BoundedScaler(Scaler):
|
|
27
|
+
'''
|
|
28
|
+
Scale data to [0, 1] according to bounds
|
|
29
|
+
'''
|
|
30
|
+
def __init__(self, bounds):
|
|
31
|
+
self.bounds = bounds
|
|
32
|
+
|
|
33
|
+
def transform(self, X):
|
|
34
|
+
#return np.clip((X - self.bounds[0]) / (self.bounds[1] - self.bounds[0]), 0, 1)
|
|
35
|
+
return (X - self.bounds[0]) / (self.bounds[1] - self.bounds[0])
|
|
36
|
+
|
|
37
|
+
def inverse_transform(self, X):
|
|
38
|
+
#return np.clip(X, 0, 1) * (self.bounds[1] - self.bounds[0]) + self.bounds[0]
|
|
39
|
+
return X * (self.bounds[1] - self.bounds[0]) + self.bounds[0]
|
|
40
|
+
|
|
41
|
+
### 2-dim transformation
|
|
42
|
+
|
|
43
|
+
class Transformation:
|
|
44
|
+
|
|
45
|
+
def __init__(self, x_scaler, y_scaler):
|
|
46
|
+
self.x_scaler = x_scaler
|
|
47
|
+
self.y_scaler = y_scaler
|
|
48
|
+
|
|
49
|
+
def fit(self, x, y):
|
|
50
|
+
self.x_scaler = self.x_scaler.fit(x)
|
|
51
|
+
self.y_scaler = self.y_scaler.fit(y)
|
|
52
|
+
|
|
53
|
+
def do(self, x=None, y=None):
|
|
54
|
+
assert x is not None or y is not None
|
|
55
|
+
if x is not None:
|
|
56
|
+
x_res = self.x_scaler.transform(np.atleast_2d(x))
|
|
57
|
+
if len(np.array(x).shape) < 2:
|
|
58
|
+
x_res = x_res.squeeze()
|
|
59
|
+
|
|
60
|
+
if y is not None:
|
|
61
|
+
y_res = self.y_scaler.transform(np.atleast_2d(y))
|
|
62
|
+
if len(np.array(y).shape) < 2:
|
|
63
|
+
y_res = y_res.squeeze()
|
|
64
|
+
|
|
65
|
+
if x is not None and y is not None:
|
|
66
|
+
return x_res, y_res
|
|
67
|
+
elif x is not None:
|
|
68
|
+
return x_res
|
|
69
|
+
elif y is not None:
|
|
70
|
+
return y_res
|
|
71
|
+
|
|
72
|
+
def undo(self, x=None, y=None):
|
|
73
|
+
assert x is not None or y is not None
|
|
74
|
+
if x is not None:
|
|
75
|
+
x_res = self.x_scaler.inverse_transform(np.atleast_2d(x))
|
|
76
|
+
if len(np.array(x).shape) < 2:
|
|
77
|
+
x_res = x_res.squeeze()
|
|
78
|
+
|
|
79
|
+
if y is not None:
|
|
80
|
+
y_res = self.y_scaler.inverse_transform(np.atleast_2d(y))
|
|
81
|
+
if len(np.array(y).shape) < 2:
|
|
82
|
+
y_res = y_res.squeeze()
|
|
83
|
+
|
|
84
|
+
if x is not None and y is not None:
|
|
85
|
+
return x_res, y_res
|
|
86
|
+
elif x is not None:
|
|
87
|
+
return x_res
|
|
88
|
+
elif y is not None:
|
|
89
|
+
return y_res
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class StandardTransform(Transformation):
|
|
93
|
+
|
|
94
|
+
def __init__(self, x_bound):
|
|
95
|
+
super().__init__(
|
|
96
|
+
BoundedScaler(x_bound),
|
|
97
|
+
StandardScaler()
|
|
98
|
+
)
|
|
99
|
+
|
|
100
|
+
class BoundTransform(Transformation):
|
|
101
|
+
|
|
102
|
+
def __init__(self, x_bound, y_bound):
|
|
103
|
+
super().__init__(
|
|
104
|
+
BoundedScaler(x_bound),
|
|
105
|
+
BoundedScaler(y_bound),
|
|
106
|
+
)
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
from time import time
|
|
2
|
+
import numpy as np
|
|
3
|
+
from pymoo.indicators.hv import HV
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Timer:
|
|
7
|
+
'''
|
|
8
|
+
For time recording and message logging
|
|
9
|
+
'''
|
|
10
|
+
def __init__(self):
|
|
11
|
+
self.t = time()
|
|
12
|
+
|
|
13
|
+
def log(self, string=None, reset=True):
|
|
14
|
+
msg = '%.2fs' % (time() - self.t)
|
|
15
|
+
|
|
16
|
+
if string is not None:
|
|
17
|
+
msg = string + ': ' + msg
|
|
18
|
+
print(msg)
|
|
19
|
+
|
|
20
|
+
if reset:
|
|
21
|
+
self.t = time()
|
|
22
|
+
|
|
23
|
+
def reset(self):
|
|
24
|
+
self.t = time()
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def find_pareto_front(Y, return_index=False):
|
|
28
|
+
'''
|
|
29
|
+
Find pareto front (undominated part) of the input performance data.
|
|
30
|
+
'''
|
|
31
|
+
if len(Y) == 0: return np.array([])
|
|
32
|
+
sorted_indices = np.argsort(Y.T[0])
|
|
33
|
+
pareto_indices = []
|
|
34
|
+
for idx in sorted_indices:
|
|
35
|
+
# check domination relationship
|
|
36
|
+
if not (np.logical_and((Y <= Y[idx]).all(axis=1), (Y < Y[idx]).any(axis=1))).any():
|
|
37
|
+
pareto_indices.append(idx)
|
|
38
|
+
pareto_front = Y[pareto_indices].copy()
|
|
39
|
+
|
|
40
|
+
if return_index:
|
|
41
|
+
return pareto_front, pareto_indices
|
|
42
|
+
else:
|
|
43
|
+
return pareto_front
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def calc_hypervolume(pfront, ref_point):
|
|
47
|
+
'''
|
|
48
|
+
Calculate hypervolume of pfront based on ref_point
|
|
49
|
+
'''
|
|
50
|
+
hv = HV(ref_point=ref_point)
|
|
51
|
+
return hv(pfront)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def safe_divide(x1, x2):
|
|
55
|
+
'''
|
|
56
|
+
Divide x1 / x2, return 0 where x2 == 0
|
|
57
|
+
'''
|
|
58
|
+
return np.divide(x1, x2, out=np.zeros(np.broadcast(x1, x2).shape), where=(x2 != 0))
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def expand(x, axis=-1):
|
|
62
|
+
'''
|
|
63
|
+
Concise way of expand_dims
|
|
64
|
+
'''
|
|
65
|
+
return np.expand_dims(x, axis=axis)
|