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.
Files changed (69) hide show
  1. pydmoo/algorithms/base/__init__.py +20 -0
  2. pydmoo/algorithms/base/core/__init__.py +0 -0
  3. pydmoo/algorithms/base/core/algorithm.py +416 -0
  4. pydmoo/algorithms/base/core/genetic.py +129 -0
  5. pydmoo/algorithms/base/dmoo/__init__.py +0 -0
  6. pydmoo/algorithms/base/dmoo/dmoead.py +131 -0
  7. pydmoo/algorithms/base/dmoo/dmoeadde.py +131 -0
  8. pydmoo/algorithms/base/dmoo/dmopso.py +0 -0
  9. pydmoo/algorithms/base/dmoo/dnsga2.py +137 -0
  10. pydmoo/algorithms/base/moo/__init__.py +0 -0
  11. pydmoo/algorithms/base/moo/moead.py +199 -0
  12. pydmoo/algorithms/base/moo/moeadde.py +105 -0
  13. pydmoo/algorithms/base/moo/mopso.py +0 -0
  14. pydmoo/algorithms/base/moo/nsga2.py +122 -0
  15. pydmoo/algorithms/modern/__init__.py +94 -0
  16. pydmoo/algorithms/modern/moead_imkt.py +161 -0
  17. pydmoo/algorithms/modern/moead_imkt_igp.py +56 -0
  18. pydmoo/algorithms/modern/moead_imkt_lstm.py +109 -0
  19. pydmoo/algorithms/modern/moead_imkt_n.py +117 -0
  20. pydmoo/algorithms/modern/moead_imkt_n_igp.py +56 -0
  21. pydmoo/algorithms/modern/moead_imkt_n_lstm.py +111 -0
  22. pydmoo/algorithms/modern/moead_ktmm.py +112 -0
  23. pydmoo/algorithms/modern/moeadde_imkt.py +161 -0
  24. pydmoo/algorithms/modern/moeadde_imkt_clstm.py +223 -0
  25. pydmoo/algorithms/modern/moeadde_imkt_igp.py +56 -0
  26. pydmoo/algorithms/modern/moeadde_imkt_lstm.py +212 -0
  27. pydmoo/algorithms/modern/moeadde_imkt_n.py +117 -0
  28. pydmoo/algorithms/modern/moeadde_imkt_n_clstm.py +146 -0
  29. pydmoo/algorithms/modern/moeadde_imkt_n_igp.py +56 -0
  30. pydmoo/algorithms/modern/moeadde_imkt_n_lstm.py +114 -0
  31. pydmoo/algorithms/modern/moeadde_ktmm.py +112 -0
  32. pydmoo/algorithms/modern/nsga2_imkt.py +162 -0
  33. pydmoo/algorithms/modern/nsga2_imkt_clstm.py +223 -0
  34. pydmoo/algorithms/modern/nsga2_imkt_igp.py +56 -0
  35. pydmoo/algorithms/modern/nsga2_imkt_lstm.py +248 -0
  36. pydmoo/algorithms/modern/nsga2_imkt_n.py +117 -0
  37. pydmoo/algorithms/modern/nsga2_imkt_n_clstm.py +146 -0
  38. pydmoo/algorithms/modern/nsga2_imkt_n_igp.py +57 -0
  39. pydmoo/algorithms/modern/nsga2_imkt_n_lstm.py +154 -0
  40. pydmoo/algorithms/modern/nsga2_ktmm.py +112 -0
  41. pydmoo/algorithms/utils/__init__.py +0 -0
  42. pydmoo/algorithms/utils/utils.py +166 -0
  43. pydmoo/core/__init__.py +0 -0
  44. pydmoo/{response → core}/ar_model.py +4 -4
  45. pydmoo/{response → core}/bounds.py +35 -2
  46. pydmoo/core/distance.py +45 -0
  47. pydmoo/core/inverse.py +55 -0
  48. pydmoo/core/lstm/__init__.py +0 -0
  49. pydmoo/core/lstm/base.py +291 -0
  50. pydmoo/core/lstm/lstm.py +491 -0
  51. pydmoo/core/manifold.py +93 -0
  52. pydmoo/core/predictions.py +50 -0
  53. pydmoo/core/sample_gaussian.py +56 -0
  54. pydmoo/core/sample_uniform.py +63 -0
  55. pydmoo/{response/tca_model.py → core/transfer.py} +3 -3
  56. pydmoo/problems/__init__.py +53 -49
  57. pydmoo/problems/dyn.py +94 -13
  58. pydmoo/problems/dynamic/cec2015.py +10 -5
  59. pydmoo/problems/dynamic/df.py +6 -3
  60. pydmoo/problems/dynamic/gts.py +69 -34
  61. pydmoo/problems/real_world/__init__.py +0 -0
  62. pydmoo/problems/real_world/dsrp.py +168 -0
  63. pydmoo/problems/real_world/dwbdp.py +189 -0
  64. {pydmoo-0.0.18.dist-info → pydmoo-0.1.0.dist-info}/METADATA +11 -10
  65. pydmoo-0.1.0.dist-info/RECORD +70 -0
  66. {pydmoo-0.0.18.dist-info → pydmoo-0.1.0.dist-info}/WHEEL +1 -1
  67. pydmoo-0.0.18.dist-info/RECORD +0 -15
  68. /pydmoo/{response → algorithms}/__init__.py +0 -0
  69. {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 TCAModel:
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(-γ||x-y||²)
145
- # Efficient computation using ||x-y||² = ||x||² + ||y||² - 2x^T 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':
@@ -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
- 'fda4': FDA4,
41
- 'fda5': FDA5,
42
- 'gts1': GTS1,
43
- 'gts2': GTS2,
44
- 'gts3': GTS3,
45
- 'gts4': GTS4,
46
- 'gts5': GTS5,
47
- 'gts6': GTS6,
48
- 'gts7': GTS7,
49
- 'gts8': GTS8,
50
- 'gts9': GTS9,
51
- 'gts10': GTS10,
52
- 'gts11': GTS11,
53
- 'gts1_2': GTS1_2,
54
- 'gts2_2': GTS2_2,
55
- 'gts3_2': GTS3_2,
56
- 'gts4_2': GTS4_2,
57
- 'gts5_2': GTS5_2,
58
- 'gts6_2': GTS6_2,
59
- 'gts7_2': GTS7_2,
60
- 'gts8_2': GTS8_2,
61
- 'gts9_2': GTS9_2,
62
- 'gts10_2': GTS10_2,
63
- 'gts11_2': GTS11_2,
64
- 'gts1_3': GTS1_3,
65
- 'gts2_3': GTS2_3,
66
- 'gts3_3': GTS3_3,
67
- 'gts4_3': GTS4_3,
68
- 'gts5_3': GTS5_3,
69
- 'gts6_3': GTS6_3,
70
- 'gts7_3': GTS7_3,
71
- 'gts8_3': GTS8_3,
72
- 'gts9_3': GTS9_3,
73
- 'gts10_3': GTS10_3,
74
- 'gts11_3': GTS11_3,
75
- 'df1': DF1,
76
- 'df2': DF2,
77
- 'df3': DF3,
78
- 'df4': DF4,
79
- 'df5': DF5,
80
- 'df6': DF6,
81
- 'df7': DF7,
82
- 'df8': DF8,
83
- 'df9': DF9,
84
- 'df10': DF10,
85
- 'df11': DF11,
86
- 'df12': DF12,
87
- 'df13': DF13,
88
- 'df14': DF14,
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
- Include modified code from [pymoo](https://github.com/anyoptimization/pymoo):
3
- [dyn.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dyn.py),
4
- licensed under Apache License 2.0. Original copyright and license terms are preserved.
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 DynamicTestProblem(DynamicProblem, ABC):
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
- # added by DynOpt
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
- # added by DynOpt
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
- # update to next time
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
- # added by DynOpt
83
- # Designed to handle time-linkage properties within the GTS test suites.
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
- Include modified code from [pymoo](https://github.com/anyoptimization/pymoo):
3
- [cec2015.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dynamic/cec2015.py),
4
- licensed under Apache License 2.0. Original copyright and license terms are preserved.
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
- # added by DynOpt
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
- # added by DynOpt
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')
@@ -1,7 +1,10 @@
1
1
  """
2
- Include modified code from [pymoo](https://github.com/anyoptimization/pymoo):
3
- [df.py](https://github.com/anyoptimization/pymoo/blob/main/pymoo/problems/dynamic/df.py),
4
- licensed under Apache License 2.0. Original copyright and license terms are preserved.
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
@@ -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(F):
12
- ideal_point = np.min(F, axis=0)
13
- distances = cdist(F, [ideal_point])
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 F[knee_idx]
15
+ return solved_pf[knee_idx]
16
16
 
17
17
 
18
18
  def G_t(t):
19
- """\\( G(t) = \\sin(0.5\\pi t) \\)"""
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
- """\\( H(t) = 1.5 + G(t) \\)"""
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
- """\\( \\alpha_t = 5\\cos(0.5\\pi t) \\)"""
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
- """\\( \\beta_t = 0.2 + 2.8|G(t)| \\)"""
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
- """\\( \\omega_t = \\lfloor 10G(t) \\rfloor \\)"""
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
- """\\( a(t) = \\sin(0.5\\pi t) \\)"""
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
- """\\( b(t) = 1 + |\\cos(0.5\\pi t)| \\)"""
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
- """\\( y_t(x_1) = 0.5 + G(t)(x_1 - 0.5) \\)"""
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
- """\\( p_t = \\lfloor 6G(t) \\rfloor \\)"""
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
- \text{min}
137
- \begin{cases}
138
- f_1(\mathbf{x},t) = x_1 \\
139
- f_2(\mathbf{x},t) = g(\mathbf{x},t)(1 - (\frac{x_1}{g(\mathbf{x},t)})^{H(t)})
140
- \end{cases}
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
- ![GTS1 PS](../figs/PS/GTS1.png)
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
- ![GTS1 PF](../figs/PF/GTS1.png)
184
+ - Pareto set (PS)
185
+
186
+ ![GTS1 PS](../../figs/PS/GTS1.png)
187
+
188
+ - Pareto front (PF)
189
+
190
+ ![GTS1 PF](../../figs/PF/GTS1.png)
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
- ![GTS2 PS](../figs/PS/GTS2.png)
191
-
192
- ![GTS2 PF](../figs/PF/GTS2.png)
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