pydmoo 0.0.18__py3-none-any.whl → 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.
- pydmoo/algorithms/base/__init__.py +20 -0
- pydmoo/algorithms/base/core/__init__.py +0 -0
- pydmoo/algorithms/base/core/algorithm.py +416 -0
- pydmoo/algorithms/base/core/genetic.py +129 -0
- pydmoo/algorithms/base/dmoo/__init__.py +0 -0
- pydmoo/algorithms/base/dmoo/dmoead.py +131 -0
- pydmoo/algorithms/base/dmoo/dmoeadde.py +131 -0
- pydmoo/algorithms/base/dmoo/dmopso.py +0 -0
- pydmoo/algorithms/base/dmoo/dnsga2.py +137 -0
- pydmoo/algorithms/base/moo/__init__.py +0 -0
- pydmoo/algorithms/base/moo/moead.py +199 -0
- pydmoo/algorithms/base/moo/moeadde.py +105 -0
- pydmoo/algorithms/base/moo/mopso.py +0 -0
- pydmoo/algorithms/base/moo/nsga2.py +122 -0
- pydmoo/algorithms/modern/__init__.py +94 -0
- pydmoo/algorithms/modern/moead_imkt.py +161 -0
- pydmoo/algorithms/modern/moead_imkt_igp.py +56 -0
- pydmoo/algorithms/modern/moead_imkt_lstm.py +109 -0
- pydmoo/algorithms/modern/moead_imkt_n.py +117 -0
- pydmoo/algorithms/modern/moead_imkt_n_igp.py +56 -0
- pydmoo/algorithms/modern/moead_imkt_n_lstm.py +111 -0
- pydmoo/algorithms/modern/moead_ktmm.py +112 -0
- pydmoo/algorithms/modern/moeadde_imkt.py +161 -0
- pydmoo/algorithms/modern/moeadde_imkt_clstm.py +223 -0
- pydmoo/algorithms/modern/moeadde_imkt_igp.py +56 -0
- pydmoo/algorithms/modern/moeadde_imkt_lstm.py +212 -0
- pydmoo/algorithms/modern/moeadde_imkt_n.py +117 -0
- pydmoo/algorithms/modern/moeadde_imkt_n_clstm.py +146 -0
- pydmoo/algorithms/modern/moeadde_imkt_n_igp.py +56 -0
- pydmoo/algorithms/modern/moeadde_imkt_n_lstm.py +114 -0
- pydmoo/algorithms/modern/moeadde_ktmm.py +112 -0
- pydmoo/algorithms/modern/nsga2_imkt.py +162 -0
- pydmoo/algorithms/modern/nsga2_imkt_clstm.py +223 -0
- pydmoo/algorithms/modern/nsga2_imkt_igp.py +56 -0
- pydmoo/algorithms/modern/nsga2_imkt_lstm.py +248 -0
- pydmoo/algorithms/modern/nsga2_imkt_n.py +117 -0
- pydmoo/algorithms/modern/nsga2_imkt_n_clstm.py +146 -0
- pydmoo/algorithms/modern/nsga2_imkt_n_igp.py +57 -0
- pydmoo/algorithms/modern/nsga2_imkt_n_lstm.py +154 -0
- pydmoo/algorithms/modern/nsga2_ktmm.py +112 -0
- pydmoo/algorithms/utils/__init__.py +0 -0
- pydmoo/algorithms/utils/utils.py +166 -0
- pydmoo/core/__init__.py +0 -0
- pydmoo/{response → core}/ar_model.py +4 -4
- pydmoo/{response → core}/bounds.py +35 -2
- pydmoo/core/distance.py +45 -0
- pydmoo/core/inverse.py +55 -0
- pydmoo/core/lstm/__init__.py +0 -0
- pydmoo/core/lstm/base.py +291 -0
- pydmoo/core/lstm/lstm.py +491 -0
- pydmoo/core/manifold.py +93 -0
- pydmoo/core/predictions.py +50 -0
- pydmoo/core/sample_gaussian.py +56 -0
- pydmoo/core/sample_uniform.py +63 -0
- pydmoo/{response/tca_model.py → core/transfer.py} +3 -3
- pydmoo/problems/__init__.py +53 -49
- pydmoo/problems/dyn.py +94 -13
- pydmoo/problems/dynamic/cec2015.py +10 -5
- pydmoo/problems/dynamic/df.py +6 -3
- pydmoo/problems/dynamic/gts.py +69 -34
- pydmoo/problems/real_world/__init__.py +0 -0
- pydmoo/problems/real_world/dsrp.py +168 -0
- pydmoo/problems/real_world/dwbdp.py +189 -0
- {pydmoo-0.0.18.dist-info → pydmoo-0.1.0.dist-info}/METADATA +11 -10
- pydmoo-0.1.0.dist-info/RECORD +70 -0
- {pydmoo-0.0.18.dist-info → pydmoo-0.1.0.dist-info}/WHEEL +1 -1
- pydmoo-0.0.18.dist-info/RECORD +0 -15
- /pydmoo/{response → algorithms}/__init__.py +0 -0
- {pydmoo-0.0.18.dist-info → pydmoo-0.1.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def uniform_sample_in_neighborhood(x, radius=0.1, bounds=None, size=1, random_state=None):
|
|
5
|
+
"""
|
|
6
|
+
Generate uniformly distributed samples within hypercube neighborhoods of input points.
|
|
7
|
+
|
|
8
|
+
Parameters
|
|
9
|
+
----------
|
|
10
|
+
x : ndarray, shape (m, n)
|
|
11
|
+
Input matrix of m solutions in n-dimensional space.
|
|
12
|
+
radius : float or array_like, optional
|
|
13
|
+
Neighborhood sampling radius. Can be:
|
|
14
|
+
- Scalar: uniform radius for all dimensions (default=0.1)
|
|
15
|
+
- Array of shape (n,): dimension-specific radii
|
|
16
|
+
- Array of shape (m, n): solution-specific and dimension-specific radii
|
|
17
|
+
bounds : tuple of array_like, optional
|
|
18
|
+
Tuple containing (lower_bound, upper_bound) where each is of shape (n,).
|
|
19
|
+
If provided, samples will be clipped to these bounds.
|
|
20
|
+
size : int, optional
|
|
21
|
+
Number of samples to generate per solution (default=1).
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
ndarray
|
|
26
|
+
Sampled solutions:
|
|
27
|
+
- If size=1: shape (m, n)
|
|
28
|
+
- If size>1: shape (m, size, n)
|
|
29
|
+
|
|
30
|
+
Notes
|
|
31
|
+
-----
|
|
32
|
+
1. Sampling is performed using uniform distribution within [-radius, +radius]
|
|
33
|
+
around each solution coordinate.
|
|
34
|
+
2. For bounded sampling, uses np.clip to enforce constraints.
|
|
35
|
+
3. The function preserves input dtype for numerical precision.
|
|
36
|
+
|
|
37
|
+
Examples
|
|
38
|
+
--------
|
|
39
|
+
>>> x = np.array([[1.0, 2.0], [3.0, 4.0]])
|
|
40
|
+
>>> # Single sample with uniform radius
|
|
41
|
+
>>> samples = uniform_sample_in_neighborhood(x, radius=0.5)
|
|
42
|
+
>>> # Multiple samples with dimension-specific radii
|
|
43
|
+
>>> samples = uniform_sample_in_neighborhood(x, radius=[0.1, 0.2], size=10)
|
|
44
|
+
"""
|
|
45
|
+
# Input validation and shape processing
|
|
46
|
+
x = np.asarray(x)
|
|
47
|
+
m, n = x.shape # m solutions, n dimensions
|
|
48
|
+
|
|
49
|
+
# Process radius parameter
|
|
50
|
+
if np.isscalar(radius):
|
|
51
|
+
radius = np.full((1, n), radius) # Broadcast scalar to all dimensions
|
|
52
|
+
elif isinstance(radius, (list, np.ndarray)) and len(radius) == n:
|
|
53
|
+
radius = np.reshape(radius, (1, n)) # Convert 1D vector to row vector
|
|
54
|
+
|
|
55
|
+
# Generate random perturbations
|
|
56
|
+
samples = x[:, np.newaxis, :] + random_state.uniform(low=-radius, high=radius, size=(m, size, n)) # np.random
|
|
57
|
+
|
|
58
|
+
# Apply bounds constraint if provided
|
|
59
|
+
if bounds is not None:
|
|
60
|
+
lb, ub = np.asarray(bounds[0]), np.asarray(bounds[1])
|
|
61
|
+
samples = np.clip(samples, lb, ub)
|
|
62
|
+
|
|
63
|
+
return samples.squeeze()
|
|
@@ -2,7 +2,7 @@ import numpy as np
|
|
|
2
2
|
from scipy.linalg import eigh
|
|
3
3
|
|
|
4
4
|
|
|
5
|
-
class
|
|
5
|
+
class TCA:
|
|
6
6
|
"""Transfer Component Analysis (TCA) for domain adaptation.
|
|
7
7
|
|
|
8
8
|
TCA finds a latent space where source and target domain distributions are similar.
|
|
@@ -141,8 +141,8 @@ class TCAModel:
|
|
|
141
141
|
if self.kernel_type == 'linear':
|
|
142
142
|
return X1 @ X2.T # Linear kernel: K(x,y) = x^T y
|
|
143
143
|
elif self.kernel_type == 'rbf':
|
|
144
|
-
# RBF kernel: K(x,y) = exp(
|
|
145
|
-
# Efficient computation using ||x-y
|
|
144
|
+
# RBF kernel: K(x,y) = exp(-\gamma||x-y||^2)
|
|
145
|
+
# Efficient computation using ||x-y||^2 = ||x||^2 + ||y||^2 - 2x^T y
|
|
146
146
|
dist_sq = (np.sum(X1**2, axis=1)[:, np.newaxis] + np.sum(X2**2, axis=1) - 2 * X1 @ X2.T)
|
|
147
147
|
return np.exp(-self.kernel_param * dist_sq)
|
|
148
148
|
elif self.kernel_type == 'poly':
|
pydmoo/problems/__init__.py
CHANGED
|
@@ -35,57 +35,61 @@ from pydmoo.problems.dynamic.gts import (
|
|
|
35
35
|
GTS11_2,
|
|
36
36
|
GTS11_3,
|
|
37
37
|
)
|
|
38
|
+
from pydmoo.problems.real_world.dsrp import DSRP
|
|
39
|
+
from pydmoo.problems.real_world.dwbdp import DWBDP
|
|
38
40
|
|
|
39
41
|
PROBLEM = {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
42
|
+
"fda4": FDA4,
|
|
43
|
+
"fda5": FDA5,
|
|
44
|
+
"gts1": GTS1,
|
|
45
|
+
"gts2": GTS2,
|
|
46
|
+
"gts3": GTS3,
|
|
47
|
+
"gts4": GTS4,
|
|
48
|
+
"gts5": GTS5,
|
|
49
|
+
"gts6": GTS6,
|
|
50
|
+
"gts7": GTS7,
|
|
51
|
+
"gts8": GTS8,
|
|
52
|
+
"gts9": GTS9,
|
|
53
|
+
"gts10": GTS10,
|
|
54
|
+
"gts11": GTS11,
|
|
55
|
+
"gts1_2": GTS1_2,
|
|
56
|
+
"gts2_2": GTS2_2,
|
|
57
|
+
"gts3_2": GTS3_2,
|
|
58
|
+
"gts4_2": GTS4_2,
|
|
59
|
+
"gts5_2": GTS5_2,
|
|
60
|
+
"gts6_2": GTS6_2,
|
|
61
|
+
"gts7_2": GTS7_2,
|
|
62
|
+
"gts8_2": GTS8_2,
|
|
63
|
+
"gts9_2": GTS9_2,
|
|
64
|
+
"gts10_2": GTS10_2,
|
|
65
|
+
"gts11_2": GTS11_2,
|
|
66
|
+
"gts1_3": GTS1_3,
|
|
67
|
+
"gts2_3": GTS2_3,
|
|
68
|
+
"gts3_3": GTS3_3,
|
|
69
|
+
"gts4_3": GTS4_3,
|
|
70
|
+
"gts5_3": GTS5_3,
|
|
71
|
+
"gts6_3": GTS6_3,
|
|
72
|
+
"gts7_3": GTS7_3,
|
|
73
|
+
"gts8_3": GTS8_3,
|
|
74
|
+
"gts9_3": GTS9_3,
|
|
75
|
+
"gts10_3": GTS10_3,
|
|
76
|
+
"gts11_3": GTS11_3,
|
|
77
|
+
"df1": DF1,
|
|
78
|
+
"df2": DF2,
|
|
79
|
+
"df3": DF3,
|
|
80
|
+
"df4": DF4,
|
|
81
|
+
"df5": DF5,
|
|
82
|
+
"df6": DF6,
|
|
83
|
+
"df7": DF7,
|
|
84
|
+
"df8": DF8,
|
|
85
|
+
"df9": DF9,
|
|
86
|
+
"df10": DF10,
|
|
87
|
+
"df11": DF11,
|
|
88
|
+
"df12": DF12,
|
|
89
|
+
"df13": DF13,
|
|
90
|
+
"df14": DF14,
|
|
91
|
+
"dsrp": DSRP,
|
|
92
|
+
"dwbdp": DWBDP,
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
|
pydmoo/problems/dyn.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Includes modified code from [pymoo](https://github.com/anyoptimization/pymoo).
|
|
3
|
+
|
|
4
|
+
Sources:
|
|
5
|
+
- [dyn.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dyn.py)
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0. Original copyright and license terms are preserved.
|
|
5
8
|
"""
|
|
6
9
|
|
|
7
10
|
from abc import ABC
|
|
@@ -16,17 +19,74 @@ class DynamicProblem(Problem, ABC):
|
|
|
16
19
|
pass
|
|
17
20
|
|
|
18
21
|
|
|
19
|
-
class
|
|
22
|
+
class DynamicApplProblem(DynamicProblem):
|
|
23
|
+
|
|
24
|
+
def __init__(self, nt, taut, t0=50, tau=1, time=None, **kwargs):
|
|
25
|
+
super().__init__(**kwargs)
|
|
26
|
+
self.tau = tau
|
|
27
|
+
self.nt = nt
|
|
28
|
+
self.taut = taut
|
|
29
|
+
self.t0 = t0
|
|
30
|
+
self._time = time
|
|
31
|
+
|
|
32
|
+
def tic(self, elapsed=1):
|
|
33
|
+
|
|
34
|
+
# increase the time counter by one
|
|
35
|
+
self.tau += elapsed
|
|
36
|
+
|
|
37
|
+
# remove the cache of the problem to recreate ps and pf
|
|
38
|
+
self.__dict__["cache"] = {}
|
|
39
|
+
|
|
40
|
+
@property
|
|
41
|
+
def time(self):
|
|
42
|
+
if self._time is not None:
|
|
43
|
+
return self._time
|
|
44
|
+
else:
|
|
45
|
+
# return 1 / self.nt * (self.tau // self.taut)
|
|
46
|
+
|
|
47
|
+
# Calculate base time step
|
|
48
|
+
delta_time = 1 / self.nt
|
|
49
|
+
|
|
50
|
+
# Calculate time count considering initial offset
|
|
51
|
+
count = max((self.tau + self.taut - (self.t0 + 1)), 0) // self.taut
|
|
52
|
+
|
|
53
|
+
# Return time value
|
|
54
|
+
return delta_time * count
|
|
55
|
+
|
|
56
|
+
@time.setter
|
|
57
|
+
def time(self, value):
|
|
58
|
+
self._time = value
|
|
59
|
+
|
|
60
|
+
def update_to_next_time(self):
|
|
61
|
+
"""Advance problem to the next significant time step.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
elapsed: The actual time units advanced
|
|
66
|
+
"""
|
|
67
|
+
# Calculate how many time steps to advance
|
|
68
|
+
count = max((self.tau + self.taut - (self.t0 + 1)), 0) // self.taut
|
|
69
|
+
|
|
70
|
+
# Calculate exact elapsed time needed to reach next discrete time point
|
|
71
|
+
elapsed = int(count * self.taut + (self.t0 + 1) - self.tau)
|
|
72
|
+
|
|
73
|
+
# Advance time by calculated amount
|
|
74
|
+
self.tic(elapsed=elapsed)
|
|
75
|
+
|
|
76
|
+
return elapsed
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class DynamicTestProblem(DynamicProblem):
|
|
20
80
|
|
|
21
81
|
def __init__(self, nt, taut, t0=50, tau=1, time=None, add_time_perturbation=False, **kwargs):
|
|
22
82
|
super().__init__(**kwargs)
|
|
23
83
|
self.tau = tau
|
|
24
84
|
self.nt = nt
|
|
25
85
|
self.taut = taut
|
|
26
|
-
self.t0 = t0 # added by DynOpt
|
|
86
|
+
self.t0 = t0 # Initial time offset - added by DynOpt Team
|
|
27
87
|
self._time = time
|
|
28
88
|
|
|
29
|
-
self.add_time_perturbation = add_time_perturbation # added by DynOpt
|
|
89
|
+
self.add_time_perturbation = add_time_perturbation # Stochastic perturbation flag - added by DynOpt Team
|
|
30
90
|
|
|
31
91
|
def tic(self, elapsed=1):
|
|
32
92
|
|
|
@@ -43,48 +103,69 @@ class DynamicTestProblem(DynamicProblem, ABC):
|
|
|
43
103
|
else:
|
|
44
104
|
# return 1 / self.nt * (self.tau // self.taut)
|
|
45
105
|
|
|
46
|
-
#
|
|
106
|
+
# Modified by DynOpt Team
|
|
107
|
+
# Calculate base time step
|
|
47
108
|
delta_time = 1 / self.nt
|
|
109
|
+
|
|
110
|
+
# Calculate time count considering initial offset
|
|
48
111
|
count = max((self.tau + self.taut - (self.t0 + 1)), 0) // self.taut
|
|
49
112
|
|
|
113
|
+
# Calculate perturbation ratio if enabled
|
|
50
114
|
if not self.add_time_perturbation:
|
|
51
115
|
ratio = 0
|
|
52
116
|
|
|
53
117
|
else:
|
|
118
|
+
# Use mathematical constants to generate deterministic perturbations
|
|
54
119
|
mp.dps = max(ceil(10 + count), 10)
|
|
55
|
-
mp_pi = 0 if count == 0 else int(str(mp.pi).split(".")[-1][count - 1])
|
|
120
|
+
mp_pi = 0 if count == 0 else int(str(mp.pi).split(".")[-1][count - 1]) # Extract digit from pi
|
|
56
121
|
ratio = 0.5 * 1 / 9 * mp_pi
|
|
57
122
|
|
|
123
|
+
# Return time value with optional perturbation
|
|
58
124
|
return delta_time * count + delta_time * ratio
|
|
59
125
|
|
|
60
126
|
@time.setter
|
|
61
127
|
def time(self, value):
|
|
62
128
|
self._time = value
|
|
63
129
|
|
|
64
|
-
#
|
|
130
|
+
# Added by DynOpt Team
|
|
65
131
|
def update_to_next_time(self):
|
|
132
|
+
"""Advance problem to the next significant time step.
|
|
66
133
|
|
|
67
|
-
|
|
134
|
+
Returns
|
|
135
|
+
-------
|
|
136
|
+
elapsed: The actual time units advanced
|
|
137
|
+
"""
|
|
138
|
+
# Calculate how many time steps to advance
|
|
68
139
|
count = max((self.tau + self.taut - (self.t0 + 1)), 0) // self.taut
|
|
69
140
|
|
|
141
|
+
# Calculate exact elapsed time needed to reach next discrete time point
|
|
70
142
|
elapsed = int(count * self.taut + (self.t0 + 1) - self.tau)
|
|
71
143
|
|
|
144
|
+
# Advance time by calculated amount
|
|
72
145
|
self.tic(elapsed=elapsed)
|
|
73
146
|
|
|
74
147
|
return elapsed
|
|
75
148
|
|
|
76
149
|
|
|
77
150
|
class TimeSimulation(Callback):
|
|
151
|
+
"""Callback for simulating time evolution in dynamic optimization problems.
|
|
152
|
+
|
|
153
|
+
Handles time-linkage properties and time step updates.
|
|
154
|
+
"""
|
|
78
155
|
|
|
79
156
|
def update(self, algorithm):
|
|
157
|
+
"""Update method called at each algorithm iteration."""
|
|
80
158
|
problem = algorithm.problem
|
|
81
159
|
|
|
82
|
-
#
|
|
83
|
-
#
|
|
160
|
+
# Added by DynOpt Team
|
|
161
|
+
# Emulate time-linkage property: Update problem state based on current optimal solutions
|
|
162
|
+
# Must execute before the problem.tic() to ensure proper time sequencing
|
|
84
163
|
if hasattr(problem, "time_linkage") and hasattr(problem, "cal"):
|
|
164
|
+
# Calculate time-linkage effects using current optimal objective values
|
|
85
165
|
problem.cal(algorithm.opt.get("F"))
|
|
86
166
|
|
|
167
|
+
# Advance time step for dynamic problem simulation
|
|
87
168
|
if hasattr(problem, "tic"):
|
|
88
|
-
problem.tic()
|
|
169
|
+
problem.tic() # Progress the dynamic problem to next time step
|
|
89
170
|
else:
|
|
90
171
|
raise Exception("TimeSimulation can only be used for dynamic test problems.")
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Includes modified code from [pymoo](https://github.com/anyoptimization/pymoo).
|
|
3
|
+
|
|
4
|
+
Sources:
|
|
5
|
+
- [cec2015.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dynamic/cec2015.py)
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0. Original copyright and license terms are preserved.
|
|
8
|
+
|
|
9
|
+
Add the method `_calc_pareto_front` for FDA4 and FDA5.
|
|
5
10
|
"""
|
|
6
11
|
|
|
7
12
|
from math import cos, fabs, floor, pi, sin, sqrt
|
|
@@ -39,7 +44,7 @@ class FDA4(DynamicCEC2015):
|
|
|
39
44
|
from pymoo.vendor.gta import FDA4 as f
|
|
40
45
|
out["F"] = np.array([f(x, t) for x in X])
|
|
41
46
|
|
|
42
|
-
#
|
|
47
|
+
# Added by DynOpt
|
|
43
48
|
def _calc_pareto_front(self, *args, n_pareto_points=100, **kwargs):
|
|
44
49
|
H = 20
|
|
45
50
|
x1, x2 = np.meshgrid(np.linspace(0, 1, H), np.linspace(0, 1, H), indexing='xy')
|
|
@@ -62,7 +67,7 @@ class FDA5(DynamicCEC2015):
|
|
|
62
67
|
from pymoo.vendor.gta import FDA5 as f
|
|
63
68
|
out["F"] = np.array([f(x, t) for x in X])
|
|
64
69
|
|
|
65
|
-
#
|
|
70
|
+
# Added by DynOpt
|
|
66
71
|
def _calc_pareto_front(self, *args, n_pareto_points=100, **kwargs):
|
|
67
72
|
H = 20
|
|
68
73
|
x1, x2 = np.meshgrid(np.linspace(0, 1, H), np.linspace(0, 1, H), indexing='xy')
|
pydmoo/problems/dynamic/df.py
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
"""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
Includes modified code from [pymoo](https://github.com/anyoptimization/pymoo).
|
|
3
|
+
|
|
4
|
+
Sources:
|
|
5
|
+
- [df.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dynamic/df.py)
|
|
6
|
+
|
|
7
|
+
Licensed under the Apache License, Version 2.0. Original copyright and license terms are preserved.
|
|
5
8
|
"""
|
|
6
9
|
|
|
7
10
|
import numpy as np
|
pydmoo/problems/dynamic/gts.py
CHANGED
|
@@ -8,55 +8,55 @@ from pydmoo.problems.dyn import DynamicTestProblem
|
|
|
8
8
|
from pydmoo.problems.dynamic.df import get_PF
|
|
9
9
|
|
|
10
10
|
|
|
11
|
-
def knee_point(
|
|
12
|
-
ideal_point = np.min(
|
|
13
|
-
distances = cdist(
|
|
11
|
+
def knee_point(solved_pf: np.ndarray):
|
|
12
|
+
ideal_point = np.min(solved_pf, axis=0)
|
|
13
|
+
distances = cdist(solved_pf, [ideal_point])
|
|
14
14
|
knee_idx = np.argmax(distances)
|
|
15
|
-
return
|
|
15
|
+
return solved_pf[knee_idx]
|
|
16
16
|
|
|
17
17
|
|
|
18
18
|
def G_t(t):
|
|
19
|
-
|
|
19
|
+
# $G(t) = \\sin(0.5\\pi t)$
|
|
20
20
|
return np.sin(0.5 * np.pi * t)
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
def H_t(t):
|
|
24
|
-
|
|
24
|
+
# $H(t) = 1.5 + G(t)$
|
|
25
25
|
return 1.5 + G_t(t)
|
|
26
26
|
|
|
27
27
|
|
|
28
28
|
def alpha_t(t):
|
|
29
|
-
|
|
29
|
+
# $\\alpha_t = 5\\cos(0.5\\pi t)$
|
|
30
30
|
return 5 * np.cos(0.5 * np.pi * t)
|
|
31
31
|
|
|
32
32
|
|
|
33
33
|
def beta_t(t):
|
|
34
|
-
|
|
34
|
+
# $\\beta_t = 0.2 + 2.8|G(t)|$
|
|
35
35
|
return 0.2 + 2.8 * np.abs(G_t(t))
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def omega_t(t):
|
|
39
|
-
|
|
39
|
+
# $\\omega_t = \\lfloor 10G(t) \\rfloor$
|
|
40
40
|
return np.floor(10 * G_t(t))
|
|
41
41
|
|
|
42
42
|
|
|
43
43
|
def a_t(t):
|
|
44
|
-
|
|
44
|
+
# $a(t) = \\sin(0.5\\pi t)$
|
|
45
45
|
return np.sin(0.5 * np.pi * t)
|
|
46
46
|
|
|
47
47
|
|
|
48
48
|
def b_t(t):
|
|
49
|
-
|
|
49
|
+
# $b(t) = 1 + |\\cos(0.5\\pi t)|$
|
|
50
50
|
return 1 + np.abs(np.cos(0.5 * np.pi * t))
|
|
51
51
|
|
|
52
52
|
|
|
53
53
|
def y_t(x1, t):
|
|
54
|
-
|
|
54
|
+
# $y_t(x_1) = 0.5 + G(t)(x_1 - 0.5)$
|
|
55
55
|
return 0.5 + G_t(t) * (x1 - 0.5)
|
|
56
56
|
|
|
57
57
|
|
|
58
58
|
def p_t(t):
|
|
59
|
-
|
|
59
|
+
# $p_t = \\lfloor 6G(t) \\rfloor$
|
|
60
60
|
return np.floor(6 * G_t(t))
|
|
61
61
|
|
|
62
62
|
|
|
@@ -131,23 +131,69 @@ class GTS(DynamicTestProblem):
|
|
|
131
131
|
|
|
132
132
|
|
|
133
133
|
class GTS1(GTS):
|
|
134
|
-
r"""
|
|
134
|
+
r"""GTS1 test problem.
|
|
135
|
+
|
|
136
|
+
- Inherits all parameters from parent class GTS.
|
|
137
|
+
|
|
138
|
+
Attributes
|
|
139
|
+
----------
|
|
140
|
+
name : str
|
|
141
|
+
Problem name, default is 'GTS3'
|
|
142
|
+
n_var : int
|
|
143
|
+
Number of decision variables
|
|
144
|
+
n_obj : int
|
|
145
|
+
Number of objective functions
|
|
146
|
+
time_linkage : bool
|
|
147
|
+
Whether the problem has time linkage
|
|
148
|
+
|
|
149
|
+
Notes
|
|
150
|
+
-----
|
|
151
|
+
- Mathematical Formulation:
|
|
152
|
+
|
|
135
153
|
\begin{equation}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
154
|
+
\text{min}
|
|
155
|
+
\begin{cases}
|
|
156
|
+
f_1(\mathbf{x},t) = x_1 \\
|
|
157
|
+
f_2(\mathbf{x},t) = g(\mathbf{x},t)(1 - (\frac{x_1}{g(\mathbf{x},t)})^{H(t)})
|
|
158
|
+
\end{cases}
|
|
141
159
|
\end{equation}
|
|
142
160
|
|
|
143
|
-
|
|
161
|
+
\begin{equation}
|
|
162
|
+
\text{min}
|
|
163
|
+
\begin{cases}
|
|
164
|
+
f_1(\mathbf{x},t) = x_1 \\
|
|
165
|
+
f_2(\mathbf{x},t) = g(\mathbf{x},t)(1 - (\frac{x_1}{g(\mathbf{x},t)})^{H(t)})
|
|
166
|
+
\end{cases}
|
|
167
|
+
\end{equation}
|
|
168
|
+
|
|
169
|
+
with
|
|
170
|
+
|
|
171
|
+
\begin{equation*}
|
|
172
|
+
\begin{split}
|
|
173
|
+
g(\mathbf{x},t) = 1
|
|
174
|
+
& + \Bigl(\bigl(\mathbf{x}_{II,1} - h_1(\mathbf{x}_I)\bigr)^T \mathbf{R}_{II,1}(t) \bigl(\mathbf{x}_{II,1} - h_1(\mathbf{x}_I)\bigr)\Bigr)^{\frac{1}{p}} \\
|
|
175
|
+
& + \Bigl(\bigl(\mathbf{x}_{II,2} - h_2(\mathbf{x}_I)\bigr)^T \mathbf{R}_{II,2}(t) \bigl(\mathbf{x}_{II,2} - h_2(\mathbf{x}_I)\bigr)\Bigr)^{\frac{1}{p}}
|
|
176
|
+
\end{split}
|
|
177
|
+
\end{equation*}
|
|
178
|
+
|
|
179
|
+
where $p \geq 1$, $\mathbf{x}_I = (x_1)$, $\mathbf{x}_{II,1} = (x_2, \cdots, x_{\lfloor\frac{D}{2}\rfloor})$ and $\mathbf{x}_{II,2} = (x_{\lfloor\frac{D}{2}\rfloor + 1}, \cdots, x_D)$,
|
|
180
|
+
$h_1(\mathbf{x}_I, t) = \cos(0.5\pi t)$ and $h_2(\mathbf{x}_I, t) = G(t) + x_1^{H(t)}$,
|
|
181
|
+
$\mathbf{R}_{II,1}(t)$ and $\mathbf{R}_{II,2}(t)$ are symmetric positive semidefinite matrices in the $t$-th environment,
|
|
182
|
+
the search space is $[0,1] \times [-1,1]^{\lfloor\frac{D}{2}\rfloor -1} \times [-1, 2]^{\lceil\frac{D}{2}\rceil}$.
|
|
144
183
|
|
|
145
|
-
|
|
184
|
+
- Pareto set (PS)
|
|
185
|
+
|
|
186
|
+

|
|
187
|
+
|
|
188
|
+
- Pareto front (PF)
|
|
189
|
+
|
|
190
|
+

|
|
146
191
|
"""
|
|
147
192
|
def __init__(self, **kwargs):
|
|
148
193
|
super().__init__(part_idx=1, bounds=((0, 1), (-1, 1), (-1, 2)), **kwargs)
|
|
149
194
|
|
|
150
195
|
def _evaluate(self, x, out, *args, **kwargs):
|
|
196
|
+
"""Evaluate."""
|
|
151
197
|
xi = np.cos(0.5 * np.pi * self.time)
|
|
152
198
|
xj = G_t(self.time) + np.power(x[:, 0], H_t(self.time))
|
|
153
199
|
|
|
@@ -164,12 +210,14 @@ class GTS1(GTS):
|
|
|
164
210
|
out["F"] = np.column_stack([f1, f2])
|
|
165
211
|
|
|
166
212
|
def _calc_pareto_front(self, *args, n_pareto_points=100, **kwargs):
|
|
213
|
+
"""Pareto front."""
|
|
167
214
|
x = np.linspace(0, 1, n_pareto_points)
|
|
168
215
|
f1 = x
|
|
169
216
|
f2 = 1 - np.power(x, H_t(self.time))
|
|
170
217
|
return np.array([f1, f2]).T
|
|
171
218
|
|
|
172
219
|
def _calc_pareto_set(self, *args, n_pareto_points=100, **kwargs):
|
|
220
|
+
"""Pareto set."""
|
|
173
221
|
x_vec1 = np.linspace(0, 1, n_pareto_points)
|
|
174
222
|
x_vec2 = np.full(len(x_vec1), np.cos(0.5 * np.pi * self.time))
|
|
175
223
|
x_vec3 = G_t(self.time) + np.power(x_vec1, H_t(self.time))
|
|
@@ -178,19 +226,6 @@ class GTS1(GTS):
|
|
|
178
226
|
|
|
179
227
|
|
|
180
228
|
class GTS2(GTS):
|
|
181
|
-
r"""
|
|
182
|
-
\begin{equation}
|
|
183
|
-
\text{min}
|
|
184
|
-
\begin{cases}
|
|
185
|
-
f_1(\mathbf{x},t) = 0.5x_1+x_2 \\
|
|
186
|
-
f_2(\mathbf{x},t) = g(\mathbf{x},t)(2.8 - (\frac{0.5x_1+x_2}{g(\mathbf{x},t)})^{H(t)})
|
|
187
|
-
\end{cases}
|
|
188
|
-
\end{equation}
|
|
189
|
-
|
|
190
|
-

|
|
191
|
-
|
|
192
|
-

|
|
193
|
-
"""
|
|
194
229
|
def __init__(self, **kwargs):
|
|
195
230
|
super().__init__(part_idx=2, bounds=((0, 1), (0, 1), (-1, 2)), **kwargs)
|
|
196
231
|
|
|
File without changes
|