UQPyL 2.0.1__cp39-cp39-win_amd64.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 (98) hide show
  1. UQPyL/DoE/__init__.py +8 -0
  2. UQPyL/DoE/_lhs.py +90 -0
  3. UQPyL/DoE/fast_sampler.py +77 -0
  4. UQPyL/DoE/full_fact.py +57 -0
  5. UQPyL/DoE/lhs.py +73 -0
  6. UQPyL/DoE/random.py +28 -0
  7. UQPyL/DoE/sampler_ABC.py +26 -0
  8. UQPyL/DoE/sobol_sequence.py +47 -0
  9. UQPyL/__init__.py +13 -0
  10. UQPyL/optimization/__init__.py +21 -0
  11. UQPyL/optimization/_binary_ga.py +61 -0
  12. UQPyL/optimization/_ga.py +120 -0
  13. UQPyL/optimization/adam.py +81 -0
  14. UQPyL/optimization/asmo.py +86 -0
  15. UQPyL/optimization/boxmin.py +95 -0
  16. UQPyL/optimization/ga.py +122 -0
  17. UQPyL/optimization/mo_asmo.py +115 -0
  18. UQPyL/optimization/nsga_ii.py +219 -0
  19. UQPyL/optimization/sce_ua.py +182 -0
  20. UQPyL/problems/__init__.py +22 -0
  21. UQPyL/problems/multi_DTLZ.py +577 -0
  22. UQPyL/problems/multi_ZDT.py +224 -0
  23. UQPyL/problems/pratical_problem.py +31 -0
  24. UQPyL/problems/problem_ABC.py +42 -0
  25. UQPyL/problems/single_Benchmarks.py +475 -0
  26. UQPyL/problems/utility_functions/_NDsort.py +34 -0
  27. UQPyL/problems/utility_functions/__init__.py +0 -0
  28. UQPyL/problems/utility_functions/_uniformPoint.py +47 -0
  29. UQPyL/sensibility/__init__.py +15 -0
  30. UQPyL/sensibility/delta_test.py +78 -0
  31. UQPyL/sensibility/fast.py +74 -0
  32. UQPyL/sensibility/mars_sa.py +60 -0
  33. UQPyL/sensibility/morris.py +88 -0
  34. UQPyL/sensibility/rbd_fast.py +59 -0
  35. UQPyL/sensibility/rsa.py +51 -0
  36. UQPyL/sensibility/sa_ABC.py +133 -0
  37. UQPyL/sensibility/sobol.py +141 -0
  38. UQPyL/surrogates/BaggingEnsemble.py +1 -0
  39. UQPyL/surrogates/BootstrapEnsemble.py +1 -0
  40. UQPyL/surrogates/__init__.py +23 -0
  41. UQPyL/surrogates/fully_connect_neural_network.py +415 -0
  42. UQPyL/surrogates/gaussian_process.py +191 -0
  43. UQPyL/surrogates/gp_kernels/Kernel.py +459 -0
  44. UQPyL/surrogates/gp_kernels/__init__.py +9 -0
  45. UQPyL/surrogates/kriging.py +315 -0
  46. UQPyL/surrogates/lasso_/__init__.py +8 -0
  47. UQPyL/surrogates/lasso_/lasso_fast.c +53419 -0
  48. UQPyL/surrogates/lasso_/lasso_fast.cp39-win_amd64.pyd +0 -0
  49. UQPyL/surrogates/linear_regression.py +225 -0
  50. UQPyL/surrogates/mars.py +1233 -0
  51. UQPyL/surrogates/mars_/__init__.py +4 -0
  52. UQPyL/surrogates/mars_/_basis.c +55538 -0
  53. UQPyL/surrogates/mars_/_basis.cp39-win_amd64.pyd +0 -0
  54. UQPyL/surrogates/mars_/_forward.c +44565 -0
  55. UQPyL/surrogates/mars_/_forward.cp39-win_amd64.pyd +0 -0
  56. UQPyL/surrogates/mars_/_knot_search.c +56654 -0
  57. UQPyL/surrogates/mars_/_knot_search.cp39-win_amd64.pyd +0 -0
  58. UQPyL/surrogates/mars_/_pruning.c +20134 -0
  59. UQPyL/surrogates/mars_/_pruning.cp39-win_amd64.pyd +0 -0
  60. UQPyL/surrogates/mars_/_qr.c +39824 -0
  61. UQPyL/surrogates/mars_/_qr.cp39-win_amd64.pyd +0 -0
  62. UQPyL/surrogates/mars_/_record.c +28565 -0
  63. UQPyL/surrogates/mars_/_record.cp39-win_amd64.pyd +0 -0
  64. UQPyL/surrogates/mars_/_types.c +7104 -0
  65. UQPyL/surrogates/mars_/_types.cp39-win_amd64.pyd +0 -0
  66. UQPyL/surrogates/mars_/_util.c +14073 -0
  67. UQPyL/surrogates/mars_/_util.cp39-win_amd64.pyd +0 -0
  68. UQPyL/surrogates/mars_/pyearth/__init__.py +4 -0
  69. UQPyL/surrogates/mlp_utility/__init__.py +9 -0
  70. UQPyL/surrogates/mlp_utility/_activation_funcs.py +63 -0
  71. UQPyL/surrogates/mlp_utility/base.py +281 -0
  72. UQPyL/surrogates/mo_surrogates.py +35 -0
  73. UQPyL/surrogates/polynomial_regression.py +113 -0
  74. UQPyL/surrogates/radial_basis_function.py +93 -0
  75. UQPyL/surrogates/rbf_kernels/__init__.py +14 -0
  76. UQPyL/surrogates/rbf_kernels/base_kernel.py +447 -0
  77. UQPyL/surrogates/rbf_kernels/cubic_kernel.py +14 -0
  78. UQPyL/surrogates/rbf_kernels/gaussian_kernel.py +9 -0
  79. UQPyL/surrogates/rbf_kernels/linear_kernel.py +15 -0
  80. UQPyL/surrogates/rbf_kernels/multiquadric_kernel.py +18 -0
  81. UQPyL/surrogates/rbf_kernels/thin_plate_spline_kernel.py +20 -0
  82. UQPyL/surrogates/support_vector_machine.py +106 -0
  83. UQPyL/surrogates/surrogate_ABC.py +111 -0
  84. UQPyL/surrogates/svr_/__init__.py +7 -0
  85. UQPyL/surrogates/svr_/libsvm_interface.cp39-win_amd64.pyd +0 -0
  86. UQPyL/surrogates/svr_/libsvm_interface.cpp +106 -0
  87. UQPyL/surrogates/svr_/svm.cpp +3313 -0
  88. UQPyL/utility/__init__.py +17 -0
  89. UQPyL/utility/grid_search.py +85 -0
  90. UQPyL/utility/metrics.py +52 -0
  91. UQPyL/utility/model_selections.py +62 -0
  92. UQPyL/utility/polynomial_features.py +61 -0
  93. UQPyL/utility/scalers.py +87 -0
  94. UQPyL-2.0.1.dist-info/LICENSE.md +21 -0
  95. UQPyL-2.0.1.dist-info/METADATA +66 -0
  96. UQPyL-2.0.1.dist-info/RECORD +98 -0
  97. UQPyL-2.0.1.dist-info/WHEEL +5 -0
  98. UQPyL-2.0.1.dist-info/top_level.txt +1 -0
UQPyL/DoE/__init__.py ADDED
@@ -0,0 +1,8 @@
1
+ from .lhs import LHS
2
+ from .full_fact import FFD
3
+ from .random import RANDOM
4
+ from .sampler_ABC import Sampler
5
+ from .sobol_sequence import Sobol_Sequence
6
+ from .fast_sampler import FAST_Sampler
7
+
8
+ __all__=['LHS', 'FFD', 'RANDOM','Sobol_Sequence', 'FAST_Sampler','Sampler']
UQPyL/DoE/_lhs.py ADDED
@@ -0,0 +1,90 @@
1
+ import numpy as np
2
+ from scipy.spatial.distance import pdist,squareform
3
+
4
+
5
+ def _lhs_classic(nt: int, nx: int) -> np.ndarray:
6
+ # Generate the intervals
7
+ cut = np.linspace(0, 1, nt + 1)
8
+
9
+ # Fill points uniformly in each interval
10
+ u = np.random.rand(nt, nx)
11
+ a = cut[:nt]
12
+ b = cut[1:nt + 1]
13
+ rdpoints = np.zeros_like(u)
14
+ for j in range(nx):
15
+ rdpoints[:, j] = u[:, j]*(b-a) + a
16
+
17
+ # Make the random pairings
18
+ H = np.zeros_like(rdpoints)
19
+ for j in range(nx):
20
+ order = np.random.permutation(range(nt))
21
+ H[:, j] = rdpoints[order, j]
22
+
23
+ return H
24
+
25
+ ################################################################################
26
+
27
+ def _lhs_centered(nt: int, nx: int) -> np.ndarray:
28
+ # Generate the intervals
29
+ cut = np.linspace(0, 1, nt + 1)
30
+
31
+ # Fill points uniformly in each interval
32
+ u = np.random.rand(nt, nx)
33
+ a = cut[:nt]
34
+ b = cut[1:nt + 1]
35
+ _center = (a + b)/2
36
+
37
+ # Make the random pairings
38
+ H = np.zeros_like(u)
39
+ for j in range(nx):
40
+ H[:, j] = np.random.permutation(_center)
41
+
42
+ return H
43
+
44
+ ################################################################################
45
+
46
+ def _lhs_maximin(nt: int, nx: int, iterations: int)-> np.ndarray:
47
+
48
+ maxdist = 0
49
+
50
+ # Maximize the minimum distance between points
51
+ for i in range(iterations):
52
+
53
+ H_candidate = _lhs_classic(nt, nx)
54
+
55
+ d = pdist(H_candidate,'euclidean')
56
+ if maxdist<np.min(d):
57
+ maxdist = np.min(d)
58
+ H = H_candidate.copy()
59
+
60
+ return H
61
+
62
+ def _lhs_centered_maximin(nt: int, nx: int, iterations: int)-> np.ndarray:
63
+ maxdist = 0
64
+
65
+ # Maximize the minimum distance between points
66
+ for i in range(iterations):
67
+
68
+ H_candidate = _lhs_centered(nt, nx)
69
+ d = pdist(H_candidate,'euclidean')
70
+ if maxdist<np.min(d):
71
+ maxdist = np.min(d)
72
+ H = H_candidate.copy()
73
+
74
+ return H
75
+ ################################################################################
76
+
77
+ def _lhs_correlate(nt: int, nx: int, iterations: int) -> np.ndarray:
78
+ mincorr = np.inf
79
+
80
+ # Minimize the components correlation coefficients
81
+ for i in range(iterations):
82
+ # Generate a random LHS
83
+ H_candidate = _lhs_classic(nt, nx)
84
+ R = np.corrcoef(H_candidate)
85
+ if np.max(np.abs(R[R!=1]))<mincorr:
86
+ mincorr = np.max(np.abs(R-np.eye(R.shape[0])))
87
+ print('new candidate solution found with max,abs corrcoef = {}'.format(mincorr))
88
+ H = H_candidate.copy()
89
+
90
+ return H
@@ -0,0 +1,77 @@
1
+ import numpy as np
2
+
3
+ from .sampler_ABC import Sampler
4
+
5
+ class FAST_Sampler(Sampler):
6
+ '''
7
+ The sample technique for FAST(Fourier Amplitude Sensitivity Test) method
8
+
9
+ Parameters:
10
+ M: int
11
+ The interference parameter, i.e., the number of harmonics to sum in the
12
+ Fourier series decomposition (defalut 4).
13
+ But, the number of sample must be greater than 4*M**2!
14
+
15
+ Methods:
16
+ __call__ or sample: Generate a sample for FAST method
17
+
18
+ Examples:
19
+ >>> fast=FAST_Sampler()
20
+ >>> samples=fast(5, 4) or fast.sample(5,4)
21
+
22
+ '''
23
+ def __init__(self, M: int=4):
24
+
25
+ super().__init__()
26
+ self.M=M
27
+
28
+ def _generate(self, nt: int, nx: int) -> np.ndarray:
29
+ '''
30
+ Generate a shape of (nt*nx, nx) sample for FAST
31
+
32
+ parameters:
33
+ nt: int
34
+ the number of sample points
35
+ nx: int
36
+ the input dimensions of sampled points
37
+
38
+ Returns:
39
+ H: 2d-array
40
+ An n-by-samples design matrix that has been normalized so factor values
41
+ are uniformly spaced between zero and one.
42
+ '''
43
+
44
+ if nt<=4*self.M**2:
45
+ raise ValueError("the number of sample must be greater than 4*M**2!")
46
+
47
+ w=np.zeros(nx)
48
+ w[0]=np.floor((nt-1)/(2*self.M))
49
+ max_wi=np.floor(w[0]/(2*self.M)) #Saltelli
50
+
51
+ if max_wi>=nx-1:
52
+ w[1:]=np.floor(np.linspace(1,max_wi, nx-1))
53
+ else:
54
+ w[1:]=np.arange(nx-1)%max_wi+1
55
+
56
+ s=(2*np.pi/nt)*np.arange(nt)
57
+
58
+ X_sa=np.zeros((nt*nx, nx))
59
+ w_tmp=np.zeros(nx)
60
+
61
+ for i in range(nx):
62
+ w_tmp[i]=w[0]
63
+ idx=list(range(i))+list(range(i+1,nx))
64
+ w_tmp[idx]=w[1:]
65
+ idx=range(i*nt, (i+1)*nt)
66
+ phi=2*np.pi*np.random.rand()
67
+ sin_result=np.sin(w_tmp[:,None]*s+phi)
68
+ arsin_result=(1/np.pi)*np.arcsin(sin_result) #saltelli formula
69
+ X_sa[idx, :]=0.5+arsin_result.transpose()
70
+
71
+ return X_sa
72
+
73
+ def sample(self, nt: int, nx: int) -> np.ndarray:
74
+
75
+ return self._generate(nt, nx)
76
+
77
+
UQPyL/DoE/full_fact.py ADDED
@@ -0,0 +1,57 @@
1
+ import numpy as np
2
+ from typing import Union
3
+ from itertools import product
4
+
5
+ from .sampler_ABC import Sampler
6
+
7
+ class FFD(Sampler):
8
+ '''
9
+ Full Factorial Design
10
+
11
+ Methods:
12
+ __call__ or sample: Generate a Latin-hypercube design
13
+
14
+ Examples:
15
+ >>> ffd=FFD()
16
+ >>> samples=ffd(3, [2,3,4]) or samples=ffd.sample(3, [2,3,4])
17
+ '''
18
+
19
+ def __call__(self, nx: int, levels: Union[np.ndarray, int, list]) -> np.ndarray:
20
+
21
+ return self._generate(nx, levels)
22
+
23
+ def _generate(self, nx: int, levels: Union[np.ndarray, int, list]) -> np.ndarray:
24
+
25
+ if isinstance(levels, int):
26
+ levels = [levels]*nx
27
+ elif isinstance(levels, np.ndarray):
28
+ levels = levels.ravel().tolist()
29
+
30
+ if len(levels)!=nx:
31
+ raise ValueError('The length of levels should be equal to nx or 1')
32
+
33
+ factor_levels = [np.linspace(0, 1, num=level + 1)[:level] for level in levels]
34
+
35
+ factor_combinations = list(product(*factor_levels))
36
+
37
+ H = np.array(factor_combinations)
38
+
39
+ return H
40
+
41
+ def sample(self, nx: int, levels: Union[np.ndarray, int, list]) -> np.ndarray:
42
+ '''
43
+ Parameters:
44
+ nx: int
45
+ The number of input dimensions
46
+
47
+ levels: Union[np.ndarray, int, list]
48
+ The levels for each input dimension
49
+
50
+ Returns:
51
+ H: 2d-array
52
+ An n-by-samples design matrix between zero and one.
53
+ '''
54
+
55
+ return self._generate(nx, levels)
56
+
57
+
UQPyL/DoE/lhs.py ADDED
@@ -0,0 +1,73 @@
1
+ import numpy as np
2
+ from typing import Literal
3
+
4
+ from .sampler_ABC import Sampler
5
+ from ._lhs import _lhs_classic, _lhs_centered, _lhs_correlate, _lhs_maximin, _lhs_centered_maximin
6
+
7
+ Criterion=Literal['classic','center','maximin','center_maximin','correlation']
8
+ LHS_METHOD={'classic': _lhs_classic, 'center': _lhs_centered, 'maximin': _lhs_maximin,
9
+ 'center_maximin': _lhs_centered_maximin, 'correlation': _lhs_correlate}
10
+
11
+ class LHS(Sampler):
12
+ '''
13
+ Latin-hypercube design
14
+
15
+ Parameters:
16
+ criterion : str
17
+ Allowable values are "classic", "center", "maximin", "center_maximin",
18
+ and "correlation". (Default: classic)
19
+
20
+ iterations : int
21
+ The number of iterations in the maximin, center_maximin and correlations methods
22
+ (Default: 5).
23
+
24
+ Methods:
25
+ __call__ or sample: Generate a Latin-hypercube design
26
+
27
+ Examples:
28
+ >>>lhs=LHS('classic')
29
+ >>>samples=lhs(5,10) or samples=lhs.sample(5,10)
30
+
31
+ '''
32
+ def __init__(self, criterion: Criterion='classic', iterations: int=5)-> None:
33
+ self.criterion=criterion
34
+ self.iterations=iterations
35
+
36
+ def _generate(self, nt: int, nx: int) -> np.ndarray:
37
+ '''
38
+ Generate a Latin-hypercube design
39
+
40
+ Parameters
41
+ nt: int
42
+ the number of sampled points
43
+ nx: int
44
+ the input dimensions of sampled points
45
+
46
+ Returns:
47
+ H: 2d-array
48
+ An n-by-samples design matrix that has been normalized so factor values
49
+ are uniformly spaced between zero and one.
50
+ '''
51
+ Sampling_method=LHS_METHOD[self.criterion]
52
+ if self.criterion in ['maximin', 'center_maximin', 'correlation']:
53
+ return Sampling_method(nt, nx, self.iterations)
54
+ else:
55
+ return Sampling_method(nt, nx)
56
+
57
+ def sample(self, nt: int, nx:int) -> np.ndarray:
58
+ '''
59
+ Generate a Latin-hypercube design
60
+
61
+ Parameters
62
+ nt: int
63
+ the number of sampled points
64
+ nx: int
65
+ the input dimensions of sampled points
66
+
67
+ Returns:
68
+ H: 2d-array
69
+ An n-by-samples design matrix that has been normalized so factor values
70
+ are uniformly spaced between zero and one.
71
+ '''
72
+
73
+ return self._generate(nt, nx)
UQPyL/DoE/random.py ADDED
@@ -0,0 +1,28 @@
1
+ import numpy as np
2
+
3
+ from .sampler_ABC import Sampler
4
+
5
+ class RANDOM(Sampler):
6
+ '''
7
+ Random Design
8
+
9
+ Method:
10
+ __call__ or sample: Generate a random design
11
+
12
+ Examples:
13
+ >>> random=RANDOM()
14
+ >>> random(10,10) or random.sample(10,10)
15
+ '''
16
+
17
+ def _generate(self,nt: int, nx: int) -> np.ndarray:
18
+
19
+ H=np.random.random((nt,nx))
20
+
21
+ return H
22
+
23
+ def sample(self, nt: int, nx: int) -> np.ndarray:
24
+ '''
25
+ Generate a sample with random values between zero and one
26
+ '''
27
+
28
+ return self._generate(nt, nx)
@@ -0,0 +1,26 @@
1
+ import abc
2
+ import numpy as np
3
+
4
+ class Sampler(metaclass=abc.ABCMeta):
5
+ def __init__(self):
6
+ pass
7
+
8
+ def __call__(self, nt:int, nx: int) -> np.ndarray:
9
+ return self._generate(nt, nx)
10
+
11
+ def sample(self, nt:int, nx:int) -> np.ndarray:
12
+ return self._generate(nt, nx)
13
+
14
+ @abc.abstractmethod
15
+ def _generate(self, nt: int, nx: int) -> np.ndarray:
16
+ '''
17
+ nt: the number of sampled points
18
+ nx: the dimensions of decision variables
19
+
20
+ return:
21
+ ndarry[nt,nx]
22
+
23
+ '''
24
+ pass
25
+
26
+
@@ -0,0 +1,47 @@
1
+ import numpy as np
2
+ from scipy.stats.qmc import Sobol
3
+
4
+ from .sampler_ABC import Sampler
5
+
6
+ class Sobol_Sequence(Sampler):
7
+ '''
8
+ Sobol Sequence
9
+
10
+ Methods:
11
+ __call__ or sample: generate the shape of (nt*nx, nx) and numpy array Sobol sequence.
12
+
13
+ '''
14
+ def __init__(self):
15
+
16
+ super().__init__()
17
+
18
+ def _generate(self, nt: int, nx: int) -> np.ndarray:
19
+ '''
20
+ generate the shape of (nt*nx, nx) and numpy array Sobol sequence.
21
+ '''
22
+
23
+ return Sobol(d=nx).random(nt)
24
+
25
+ def sample(self, nt: int, nx: int) -> np.ndarray:
26
+ '''
27
+ generate the shape of (nt, nx) and numpy array Sobol sequence.
28
+
29
+ Parameters
30
+ nt: int
31
+ the number of sampled points
32
+ nx: int
33
+ the input dimensions of sampled points
34
+
35
+ Returns:
36
+ H: 2d-array
37
+ An n-by-samples design matrix that has been normalized so factor values
38
+ are uniformly spaced between zero and one.
39
+ '''
40
+ return self._generate(nt, nx)
41
+
42
+
43
+
44
+
45
+
46
+
47
+
UQPyL/__init__.py ADDED
@@ -0,0 +1,13 @@
1
+ from . import problems, surrogates, optimization, sensibility, DoE, utility
2
+
3
+ __version__ = "2.0.1"
4
+ __author__ = "wmtSky"
5
+
6
+ __all__=[
7
+ "problems",
8
+ "surrogates",
9
+ "optimization",
10
+ "sensibility",
11
+ "DoE",
12
+ "utility"
13
+ ]
@@ -0,0 +1,21 @@
1
+ from .ga import GA
2
+ from .boxmin import Boxmin
3
+ from .adam import Adam
4
+ from .sce_ua import SCE_UA
5
+ from .asmo import ASMO
6
+ from .nsga_ii import NSGAII
7
+ from .mo_asmo import MOASMO
8
+ from ._binary_ga import Binary_GA
9
+ __all__=[
10
+ 'GA',
11
+ 'Boxmin',
12
+ 'Adam',
13
+ 'SCE_UA',
14
+ 'ASMO',
15
+ 'NSGAII',
16
+ 'MOASMO',
17
+ 'Binary_GA'
18
+ ]
19
+
20
+ MP_List=['Boxmin']
21
+ EA_List=['GA']
@@ -0,0 +1,61 @@
1
+ import numpy as np
2
+
3
+ class Binary_GA():
4
+ def __init__(self, evaluate, n_features, population_size=50, n_generations=100, crossover_rate=0.7, mutation_rate=0.01):
5
+ self.population_size = population_size
6
+ self.n_generations = n_generations
7
+ self.crossover_rate = crossover_rate
8
+ self.mutation_rate = mutation_rate
9
+ self.n_features = n_features
10
+ self.evaluate = evaluate
11
+ def initialize_population(self):
12
+ return np.random.randint(2, size=(self.population_size, self.n_features))
13
+
14
+ def select(self, fitnesses):
15
+ inverse_fitnesses = [1.0/f for f in fitnesses]
16
+ total_fitness = sum(inverse_fitnesses)
17
+ selection_probs = [f/total_fitness for f in inverse_fitnesses]
18
+ return np.random.choice(range(self.population_size), size=self.population_size, replace=True, p=selection_probs)
19
+
20
+ def crossover(self, parent1, parent2):
21
+ if np.random.rand() < self.crossover_rate:
22
+ point = np.random.randint(1, self.n_features)
23
+ child1 = np.concatenate([parent1[:point], parent2[point:]])
24
+ child2 = np.concatenate([parent2[:point], parent1[point:]])
25
+ return child1, child2
26
+ return parent1, parent2
27
+
28
+ def mutate(self, individual):
29
+ for i in range(self.n_features):
30
+ if np.random.rand() < self.mutation_rate:
31
+ individual[i] = 1 - individual[i]
32
+ return individual
33
+
34
+ def run(self):
35
+ population = self.initialize_population()
36
+ best_individual = None
37
+ best_fitness = float('inf')
38
+ history_individuals = []
39
+ history_values=[]
40
+ for generation in range(self.n_generations):
41
+ fitnesses = [self.evaluate(individual) for individual in population]
42
+ if min(fitnesses) < best_fitness:
43
+ best_fitness = min(fitnesses)
44
+ best_individual = population[np.argmin(fitnesses)]
45
+
46
+ history_individuals.append(best_individual)
47
+ history_values.append(best_fitness)
48
+
49
+ selected_indices = self.select(fitnesses)
50
+ selected_population = population[selected_indices]
51
+ offspring_population = []
52
+ for i in range(0, self.population_size, 2):
53
+ parent1, parent2 = selected_population[i], selected_population[i+1]
54
+ child1, child2 = self.crossover(parent1, parent2)
55
+ offspring_population.append(self.mutate(child1))
56
+ offspring_population.append(self.mutate(child2))
57
+ population = np.array(offspring_population)
58
+ # 精英保留
59
+ if best_individual is not None:
60
+ population[0] = best_individual
61
+ return best_individual, best_fitness, history_individuals, history_values
@@ -0,0 +1,120 @@
1
+ import numpy as np
2
+ import warnings
3
+ import math
4
+ from typing import Callable
5
+
6
+ class GA():
7
+ type="EA" #Evolutionary Algorithm
8
+ proC=None
9
+ disC=None
10
+ proM=None
11
+ disM=None
12
+ tolerate=1e-6
13
+ def __init__(self, dim: int, ub: np.ndarray, lb: np.ndarray, n_samples: int,
14
+ proC: float=1, disC: float=20, proM: float=1, disM: float=20,
15
+ tolerate_times: int=1000):
16
+ self.__check__(dim,ub,lb)
17
+ self.dim=dim;self.ub=ub.reshape(1,-1);self.lb=lb.reshape(1,-1)
18
+
19
+ self.proC=proC;self.disC=disC
20
+ self.proM=proM;self.disM=disM
21
+ self.tolerate=1e-6; self.tolerate_times=tolerate_times
22
+ self.n_samples=n_samples
23
+ self.iterTimes=4000
24
+ def _tournamentSelection(self,decs: np.ndarray, objs: np.ndarray, K: int=2):
25
+ '''
26
+ K-tournament selection
27
+ '''
28
+ rankIndex=np.argsort(objs,axis=0)
29
+ rank=np.argsort(rankIndex,axis=0)
30
+
31
+ tourSelection=np.random.randint(0,high=objs.shape[0],size=(objs.shape[0],K))
32
+ winner=np.min(rank[tourSelection,:].ravel().reshape(objs.shape[0],2),axis=1)
33
+ winIndex=rankIndex[winner]
34
+
35
+ return decs[winIndex.ravel(),:]
36
+
37
+ def _operationGA(self,decs: np.ndarray):
38
+ '''
39
+ GA Operation
40
+ '''
41
+ n_samples=decs.shape[0]
42
+ Parent1=decs[:math.floor(n_samples/2),:]
43
+ Parent2=decs[math.floor(n_samples/2):math.floor(n_samples/2)*2,:]
44
+
45
+ N,D=Parent1.shape
46
+
47
+ beta=np.zeros((N,D))
48
+ mu=np.random.random((N,D))
49
+
50
+ beta[mu<=0.5]=np.power(2*mu[mu<=0.5],1/(self.disC+1))
51
+ beta[mu>0.5]=np.power(2-2*mu[mu>0.5],-1/(self.disC+1))
52
+ beta=beta*np.power(-1,np.random.randint(0,high=2,size=(N,D)))
53
+ beta[np.random.random((N,D))<0.5]=1
54
+ beta[np.repeat(np.random.random((N,1))>self.proC,D,axis=1)]=1
55
+
56
+ off1=(Parent1+Parent2)/2+beta*(Parent1-Parent2)/2
57
+ off2=(Parent1+Parent2)/2-beta*(Parent1-Parent2)/2
58
+ Offspring=np.vstack((off1,off2))
59
+
60
+ Lower=np.repeat(self.lb,2*N,axis=0)
61
+ Upper=np.repeat(self.ub,2*N,axis=0)
62
+ Site=np.random.random((2*N,D))<self.proM/D
63
+ mu=np.random.random((2*N,D))
64
+ temp=np.zeros((2*N,D),dtype=np.bool_)
65
+ temp[Site * mu<=0.5]=1
66
+ Offspring=np.minimum(np.maximum(Offspring,Lower),Upper)
67
+
68
+ t1=(1-2*mu[temp])*np.power(1-(Offspring[temp]-Lower[temp])/(Upper[temp]-Lower[temp]),self.disM+1)
69
+ Offspring[temp]=Offspring[temp]+(Upper[temp]-Lower[temp])*(np.power(2*mu[temp]+t1,1/(self.disM+1))-1)
70
+
71
+ temp=np.zeros((2*N,D),dtype=np.bool_);temp[Site * mu>0.5]=1
72
+ t2=2*(mu[temp]-0.5)*np.power(1-(Upper[temp]-Offspring[temp])/(Upper[temp]-Lower[temp]),self.disM+1)
73
+
74
+ Offspring[temp]=Offspring[temp]+(Upper[temp]-Lower[temp])*(1-np.power(2*(1-mu[temp])+t2,1/(self.disM+1)))
75
+
76
+ return Offspring
77
+
78
+ def run(self, func: Callable):
79
+
80
+ best_objs=np.inf
81
+ best_decs=None
82
+ time=1
83
+ iter=0
84
+
85
+ decs=np.random.random((self.n_samples,self.dim))*(self.ub-self.lb)+self.lb
86
+ objs=func(decs)
87
+
88
+ while iter<self.iterTimes:
89
+
90
+ matingPool=self._tournamentSelection(decs,objs,2)
91
+ matingDecs=self._operationGA(matingPool)
92
+ matingObjs=func(matingDecs)
93
+
94
+ tempObjs=np.vstack((objs,matingObjs))
95
+ tempDecs=np.vstack((decs,matingDecs))
96
+ rank=np.argsort(tempObjs,axis=0)
97
+ decs=tempDecs[rank[:self.n_samples,0],:]
98
+ objs=tempObjs[rank[:self.n_samples,0],:]
99
+
100
+ if(abs(best_objs-np.min(objs))>self.tolerate):
101
+ best_objs=np.min(objs)
102
+ best_decs=decs[np.argmin(objs,axis=0),:]
103
+ time=0
104
+ else:
105
+ time+=1
106
+
107
+ if(time>self.tolerate_times):
108
+ break
109
+
110
+ iter+=1
111
+
112
+ return best_decs,best_objs
113
+
114
+ def __check__(self,dim: int, ub: np.ndarray, lb: np.ndarray):
115
+ if(ub.size==lb.size and dim==ub.size):
116
+ pass
117
+ else:
118
+ raise ValueError("The dimensions should be consistent among dim, ub and lb")
119
+
120
+