pypharm 1.6.1__py3-none-any.whl → 1.6.2__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.
- PyPharm/__init__.py +4 -3
- PyPharm/algorithms/country_optimization.py +469 -469
- PyPharm/algorithms/country_optimization_v2.py +330 -330
- PyPharm/algorithms/country_optimization_v3.py +428 -428
- PyPharm/algorithms/genetic_optimization.py +130 -130
- PyPharm/algorithms/gold_digger_optimization.py +126 -126
- PyPharm/constants.py +80 -80
- PyPharm/country_optimization.py +470 -0
- PyPharm/country_optimization_v2.py +330 -0
- PyPharm/country_optimization_v3.py +426 -0
- PyPharm/genetic_optimization.py +130 -0
- PyPharm/gold_digger_optimization.py +127 -0
- PyPharm/models/__init__.py +3 -3
- PyPharm/models/compartment_models.py +985 -985
- PyPharm/models/pbpk.py +683 -683
- PyPharm/models.py +638 -0
- {pypharm-1.6.1.dist-info → pypharm-1.6.2.dist-info}/METADATA +11 -7
- pypharm-1.6.2.dist-info/RECORD +21 -0
- {pypharm-1.6.1.dist-info → pypharm-1.6.2.dist-info}/WHEEL +1 -1
- pypharm-1.6.1.dist-info/RECORD +0 -15
- {pypharm-1.6.1.dist-info → pypharm-1.6.2.dist-info}/top_level.txt +0 -0
|
@@ -1,130 +1,130 @@
|
|
|
1
|
-
import graycode
|
|
2
|
-
import numpy as np
|
|
3
|
-
import copy
|
|
4
|
-
|
|
5
|
-
class Individual:
|
|
6
|
-
|
|
7
|
-
x_min = None
|
|
8
|
-
x_max = None
|
|
9
|
-
genes = None
|
|
10
|
-
function = None
|
|
11
|
-
gray_code = None
|
|
12
|
-
f = None
|
|
13
|
-
|
|
14
|
-
def __init__(self, gray_code, x_min, x_max, genes, function, mutation_chance=None, max_mutation=1):
|
|
15
|
-
|
|
16
|
-
self.x_min = x_min
|
|
17
|
-
self.x_max = x_max
|
|
18
|
-
self.genes = genes
|
|
19
|
-
self.function = function
|
|
20
|
-
self.steps = (self.x_max - self.x_min) / (2 ** (self.genes) - 1)
|
|
21
|
-
self.gray_code = gray_code
|
|
22
|
-
if mutation_chance is not None and np.random.random() < mutation_chance:
|
|
23
|
-
self.mutation(max_mutation)
|
|
24
|
-
self.f = self.function(self.real_x)
|
|
25
|
-
|
|
26
|
-
@property
|
|
27
|
-
def real_x(self):
|
|
28
|
-
decimal_x = []
|
|
29
|
-
gray_code = copy.deepcopy(self.gray_code)
|
|
30
|
-
for g in self.genes:
|
|
31
|
-
decimal_x.append(graycode.gray_code_to_tc(int(gray_code[:g], base=2)))
|
|
32
|
-
gray_code = gray_code[g:]
|
|
33
|
-
return self.x_min + self.steps * np.array(decimal_x)
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def decimal_x(self):
|
|
37
|
-
return (self.real_x - self.x_min) / self.steps
|
|
38
|
-
|
|
39
|
-
@classmethod
|
|
40
|
-
def generate_from_decimal(cls, decimal, x_min, x_max, genes, function):
|
|
41
|
-
gray_code = ''
|
|
42
|
-
decimal = np.clip(decimal, np.zeros(decimal.size), 2 ** (genes) - 1)
|
|
43
|
-
for i in range(len(decimal)):
|
|
44
|
-
s = '{:0' + str(genes[i]) + 'b}'
|
|
45
|
-
gray_code += s.format(graycode.tc_to_gray_code(int(decimal[i])))
|
|
46
|
-
|
|
47
|
-
return cls(gray_code, x_min, x_max, genes, function)
|
|
48
|
-
|
|
49
|
-
@classmethod
|
|
50
|
-
def crossover(cls, individual1, individual2, mutation_chance, max_mutation=1):
|
|
51
|
-
k = np.random.randint(1, len(individual1.gray_code) - 1, 2)
|
|
52
|
-
while k[0] == k[1]:
|
|
53
|
-
k = np.random.randint(1, len(individual1.gray_code) - 1, 2)
|
|
54
|
-
k = np.sort(k)
|
|
55
|
-
new_gray1 = individual1.gray_code[:k[0]] + individual2.gray_code[k[0]:k[1]] + individual1.gray_code[k[1]:]
|
|
56
|
-
new_gray2 = individual2.gray_code[:k[0]] + individual1.gray_code[k[0]:k[1]] + individual2.gray_code[k[1]:]
|
|
57
|
-
return [
|
|
58
|
-
cls(new_gray1, individual1.x_min, individual1.x_max, individual1.genes,
|
|
59
|
-
individual1.function, mutation_chance, max_mutation),
|
|
60
|
-
cls(new_gray2, individual1.x_min, individual1.x_max, individual1.genes,
|
|
61
|
-
individual1.function, mutation_chance, max_mutation),
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
def mutation(self, max_mutation=1):
|
|
65
|
-
if max_mutation > 0:
|
|
66
|
-
n = 1 + np.random.randint(1, max_mutation)
|
|
67
|
-
else:
|
|
68
|
-
n = 1
|
|
69
|
-
k = np.random.choice(len(self.gray_code), n, replace=False)
|
|
70
|
-
for ki in k:
|
|
71
|
-
b = bool(int(self.gray_code[ki]))
|
|
72
|
-
b = not b
|
|
73
|
-
b = str(int(b))
|
|
74
|
-
self.gray_code = self.gray_code[:ki] + b + self.gray_code[ki+1:]
|
|
75
|
-
|
|
76
|
-
def __lt__(self, other):
|
|
77
|
-
return self.f < other.f
|
|
78
|
-
|
|
79
|
-
def __le__(self, other):
|
|
80
|
-
return self.f <= other.f
|
|
81
|
-
|
|
82
|
-
def __gt__(self, other):
|
|
83
|
-
return self.f > other.f
|
|
84
|
-
|
|
85
|
-
def __ge__(self, other):
|
|
86
|
-
return self.f >= other.f
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
class GeneticAlgorithm:
|
|
90
|
-
|
|
91
|
-
def __init__(self, f, n, child_percent, mutation_chance, max_mutation, x_min, x_max, genes, t_max, printing=False):
|
|
92
|
-
self.f = f
|
|
93
|
-
self.n = n
|
|
94
|
-
self.child_percent = child_percent
|
|
95
|
-
self.mutation_chance = mutation_chance
|
|
96
|
-
self.max_mutation = max_mutation
|
|
97
|
-
self.x_min = np.array(x_min)
|
|
98
|
-
self.x_max = np.array(x_max)
|
|
99
|
-
self.genes = np.array(genes)
|
|
100
|
-
self.t_max = np.array(t_max)
|
|
101
|
-
self.printing = printing
|
|
102
|
-
|
|
103
|
-
self.rand_n_individual = np.vectorize(lambda x: x * self.random_individual(), signature='()->(n)')
|
|
104
|
-
self.generate_population = np.vectorize(lambda decimal: Individual.generate_from_decimal(
|
|
105
|
-
decimal, self.x_min, self.x_max, self.genes, self.f), signature='(n)->()')
|
|
106
|
-
|
|
107
|
-
def random_individual(self):
|
|
108
|
-
return np.random.randint(np.zeros(self.genes.size), 2 ** self.genes)
|
|
109
|
-
|
|
110
|
-
def start(self):
|
|
111
|
-
x = self.rand_n_individual(np.ones(self.n))
|
|
112
|
-
population = self.generate_population(x)
|
|
113
|
-
child_number = int(self.child_percent * self.n)
|
|
114
|
-
|
|
115
|
-
t = 0
|
|
116
|
-
while t <= self.t_max:
|
|
117
|
-
new_population = []
|
|
118
|
-
for i in range(child_number):
|
|
119
|
-
k = np.random.randint(0, self.n, 2)
|
|
120
|
-
while k[0] == k[1]:
|
|
121
|
-
k = np.random.randint(0, self.n, 2)
|
|
122
|
-
new_population += Individual.crossover(population[k[0]], population[k[1]],
|
|
123
|
-
self.mutation_chance, self.max_mutation)
|
|
124
|
-
population = np.append(population, np.array(new_population))
|
|
125
|
-
population.sort()
|
|
126
|
-
population = population[:self.n]
|
|
127
|
-
if self.printing:
|
|
128
|
-
print("Поколение {}: {} {}".format(t, population[0].real_x, population[0].f))
|
|
129
|
-
t += 1
|
|
130
|
-
return population[0].real_x
|
|
1
|
+
import graycode
|
|
2
|
+
import numpy as np
|
|
3
|
+
import copy
|
|
4
|
+
|
|
5
|
+
class Individual:
|
|
6
|
+
|
|
7
|
+
x_min = None
|
|
8
|
+
x_max = None
|
|
9
|
+
genes = None
|
|
10
|
+
function = None
|
|
11
|
+
gray_code = None
|
|
12
|
+
f = None
|
|
13
|
+
|
|
14
|
+
def __init__(self, gray_code, x_min, x_max, genes, function, mutation_chance=None, max_mutation=1):
|
|
15
|
+
|
|
16
|
+
self.x_min = x_min
|
|
17
|
+
self.x_max = x_max
|
|
18
|
+
self.genes = genes
|
|
19
|
+
self.function = function
|
|
20
|
+
self.steps = (self.x_max - self.x_min) / (2 ** (self.genes) - 1)
|
|
21
|
+
self.gray_code = gray_code
|
|
22
|
+
if mutation_chance is not None and np.random.random() < mutation_chance:
|
|
23
|
+
self.mutation(max_mutation)
|
|
24
|
+
self.f = self.function(self.real_x)
|
|
25
|
+
|
|
26
|
+
@property
|
|
27
|
+
def real_x(self):
|
|
28
|
+
decimal_x = []
|
|
29
|
+
gray_code = copy.deepcopy(self.gray_code)
|
|
30
|
+
for g in self.genes:
|
|
31
|
+
decimal_x.append(graycode.gray_code_to_tc(int(gray_code[:g], base=2)))
|
|
32
|
+
gray_code = gray_code[g:]
|
|
33
|
+
return self.x_min + self.steps * np.array(decimal_x)
|
|
34
|
+
|
|
35
|
+
@property
|
|
36
|
+
def decimal_x(self):
|
|
37
|
+
return (self.real_x - self.x_min) / self.steps
|
|
38
|
+
|
|
39
|
+
@classmethod
|
|
40
|
+
def generate_from_decimal(cls, decimal, x_min, x_max, genes, function):
|
|
41
|
+
gray_code = ''
|
|
42
|
+
decimal = np.clip(decimal, np.zeros(decimal.size), 2 ** (genes) - 1)
|
|
43
|
+
for i in range(len(decimal)):
|
|
44
|
+
s = '{:0' + str(genes[i]) + 'b}'
|
|
45
|
+
gray_code += s.format(graycode.tc_to_gray_code(int(decimal[i])))
|
|
46
|
+
|
|
47
|
+
return cls(gray_code, x_min, x_max, genes, function)
|
|
48
|
+
|
|
49
|
+
@classmethod
|
|
50
|
+
def crossover(cls, individual1, individual2, mutation_chance, max_mutation=1):
|
|
51
|
+
k = np.random.randint(1, len(individual1.gray_code) - 1, 2)
|
|
52
|
+
while k[0] == k[1]:
|
|
53
|
+
k = np.random.randint(1, len(individual1.gray_code) - 1, 2)
|
|
54
|
+
k = np.sort(k)
|
|
55
|
+
new_gray1 = individual1.gray_code[:k[0]] + individual2.gray_code[k[0]:k[1]] + individual1.gray_code[k[1]:]
|
|
56
|
+
new_gray2 = individual2.gray_code[:k[0]] + individual1.gray_code[k[0]:k[1]] + individual2.gray_code[k[1]:]
|
|
57
|
+
return [
|
|
58
|
+
cls(new_gray1, individual1.x_min, individual1.x_max, individual1.genes,
|
|
59
|
+
individual1.function, mutation_chance, max_mutation),
|
|
60
|
+
cls(new_gray2, individual1.x_min, individual1.x_max, individual1.genes,
|
|
61
|
+
individual1.function, mutation_chance, max_mutation),
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
def mutation(self, max_mutation=1):
|
|
65
|
+
if max_mutation > 0:
|
|
66
|
+
n = 1 + np.random.randint(1, max_mutation)
|
|
67
|
+
else:
|
|
68
|
+
n = 1
|
|
69
|
+
k = np.random.choice(len(self.gray_code), n, replace=False)
|
|
70
|
+
for ki in k:
|
|
71
|
+
b = bool(int(self.gray_code[ki]))
|
|
72
|
+
b = not b
|
|
73
|
+
b = str(int(b))
|
|
74
|
+
self.gray_code = self.gray_code[:ki] + b + self.gray_code[ki+1:]
|
|
75
|
+
|
|
76
|
+
def __lt__(self, other):
|
|
77
|
+
return self.f < other.f
|
|
78
|
+
|
|
79
|
+
def __le__(self, other):
|
|
80
|
+
return self.f <= other.f
|
|
81
|
+
|
|
82
|
+
def __gt__(self, other):
|
|
83
|
+
return self.f > other.f
|
|
84
|
+
|
|
85
|
+
def __ge__(self, other):
|
|
86
|
+
return self.f >= other.f
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class GeneticAlgorithm:
|
|
90
|
+
|
|
91
|
+
def __init__(self, f, n, child_percent, mutation_chance, max_mutation, x_min, x_max, genes, t_max, printing=False):
|
|
92
|
+
self.f = f
|
|
93
|
+
self.n = n
|
|
94
|
+
self.child_percent = child_percent
|
|
95
|
+
self.mutation_chance = mutation_chance
|
|
96
|
+
self.max_mutation = max_mutation
|
|
97
|
+
self.x_min = np.array(x_min)
|
|
98
|
+
self.x_max = np.array(x_max)
|
|
99
|
+
self.genes = np.array(genes)
|
|
100
|
+
self.t_max = np.array(t_max)
|
|
101
|
+
self.printing = printing
|
|
102
|
+
|
|
103
|
+
self.rand_n_individual = np.vectorize(lambda x: x * self.random_individual(), signature='()->(n)')
|
|
104
|
+
self.generate_population = np.vectorize(lambda decimal: Individual.generate_from_decimal(
|
|
105
|
+
decimal, self.x_min, self.x_max, self.genes, self.f), signature='(n)->()')
|
|
106
|
+
|
|
107
|
+
def random_individual(self):
|
|
108
|
+
return np.random.randint(np.zeros(self.genes.size), 2 ** self.genes)
|
|
109
|
+
|
|
110
|
+
def start(self):
|
|
111
|
+
x = self.rand_n_individual(np.ones(self.n))
|
|
112
|
+
population = self.generate_population(x)
|
|
113
|
+
child_number = int(self.child_percent * self.n)
|
|
114
|
+
|
|
115
|
+
t = 0
|
|
116
|
+
while t <= self.t_max:
|
|
117
|
+
new_population = []
|
|
118
|
+
for i in range(child_number):
|
|
119
|
+
k = np.random.randint(0, self.n, 2)
|
|
120
|
+
while k[0] == k[1]:
|
|
121
|
+
k = np.random.randint(0, self.n, 2)
|
|
122
|
+
new_population += Individual.crossover(population[k[0]], population[k[1]],
|
|
123
|
+
self.mutation_chance, self.max_mutation)
|
|
124
|
+
population = np.append(population, np.array(new_population))
|
|
125
|
+
population.sort()
|
|
126
|
+
population = population[:self.n]
|
|
127
|
+
if self.printing:
|
|
128
|
+
print("Поколение {}: {} {}".format(t, population[0].real_x, population[0].f))
|
|
129
|
+
t += 1
|
|
130
|
+
return population[0].real_x
|
|
@@ -1,127 +1,127 @@
|
|
|
1
|
-
import numpy as np
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class GoldDigger:
|
|
5
|
-
|
|
6
|
-
def __init__(self, x, function):
|
|
7
|
-
self.x = x
|
|
8
|
-
self.f = function(self.x)
|
|
9
|
-
self.ep_n = 0
|
|
10
|
-
|
|
11
|
-
def __lt__(self, other):
|
|
12
|
-
return self.f < other.f
|
|
13
|
-
|
|
14
|
-
def __le__(self, other):
|
|
15
|
-
return self.f <= other.f
|
|
16
|
-
|
|
17
|
-
def __gt__(self, other):
|
|
18
|
-
return self.f > other.f
|
|
19
|
-
|
|
20
|
-
def __ge__(self, other):
|
|
21
|
-
return self.f >= other.f
|
|
22
|
-
|
|
23
|
-
def __add__(self, other):
|
|
24
|
-
return self.f + other.f
|
|
25
|
-
|
|
26
|
-
def __radd__(self, other):
|
|
27
|
-
return self.f + other
|
|
28
|
-
|
|
29
|
-
def __truediv__(self, other):
|
|
30
|
-
return self.f / other
|
|
31
|
-
|
|
32
|
-
def update_function(self, function):
|
|
33
|
-
self.f = function(self.x)
|
|
34
|
-
|
|
35
|
-
def new_sigma_digger(self, x_min, x_max, sigma, function):
|
|
36
|
-
new_x = np.array([self.x[i] + np.random.normal(0, (x_max[i] - x_min[i]) * sigma) for i in range(self.x.size)])
|
|
37
|
-
new_x = np.clip(new_x, x_min, x_max)
|
|
38
|
-
return GoldDigger(new_x, function)
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
class GoldDiggersAlgorithm:
|
|
43
|
-
|
|
44
|
-
def __init__(self, f, n, k, l, u, a, b, sigma_b, sigma_e, Xmin, Xmax, m, t_max):
|
|
45
|
-
self.f = f
|
|
46
|
-
self.n = n
|
|
47
|
-
self.k = k
|
|
48
|
-
self.l = l
|
|
49
|
-
self.u = u
|
|
50
|
-
self.a = a
|
|
51
|
-
self.b = b
|
|
52
|
-
self.sigma_b = sigma_b
|
|
53
|
-
self.sigma_e = sigma_e
|
|
54
|
-
self.Xmin = np.array(Xmin)
|
|
55
|
-
self.Xmax = np.array(Xmax)
|
|
56
|
-
self.m = m
|
|
57
|
-
self.t_max = t_max
|
|
58
|
-
self.rand_mat = np.vectorize(lambda x: self.random_matrix(x, Xmin, Xmax), signature='()->(n)')
|
|
59
|
-
self.digger_init = np.vectorize(lambda x: GoldDigger(x, self.f), signature='(n)->()')
|
|
60
|
-
|
|
61
|
-
@staticmethod
|
|
62
|
-
def random_matrix(x, x_min, x_max):
|
|
63
|
-
return x * np.random.uniform(x_min, x_max)
|
|
64
|
-
|
|
65
|
-
def start(self):
|
|
66
|
-
x = self.rand_mat(np.ones(self.n))
|
|
67
|
-
population = self.digger_init(x)
|
|
68
|
-
|
|
69
|
-
t = 0
|
|
70
|
-
intervals = []
|
|
71
|
-
while t <= self.t_max:
|
|
72
|
-
|
|
73
|
-
x = self.rand_mat(np.ones(self.n))
|
|
74
|
-
in_interval = np.array([self.interval_in(xi, intervals) for xi in x])
|
|
75
|
-
if np.any(in_interval == True):
|
|
76
|
-
ind = np.where(in_interval == False)
|
|
77
|
-
new_x = x[ind]
|
|
78
|
-
if new_x.size:
|
|
79
|
-
population = np.append(population, self.digger_init(new_x))
|
|
80
|
-
ind = np.where(in_interval == True)
|
|
81
|
-
r = np.random.rand(ind[0].size)
|
|
82
|
-
rand_ind = np.where(r <= self.a)
|
|
83
|
-
ind = (ind[0][rand_ind])
|
|
84
|
-
x = x[ind]
|
|
85
|
-
if x.size:
|
|
86
|
-
population = np.append(population, self.digger_init(x))
|
|
87
|
-
else:
|
|
88
|
-
population = np.append(population, self.digger_init(x))
|
|
89
|
-
|
|
90
|
-
sigma = (((self.t_max - t) / self.t_max) ** self.m) * (self.sigma_b - self.sigma_e) + self.sigma_e
|
|
91
|
-
|
|
92
|
-
new_diggers = []
|
|
93
|
-
for digger in population:
|
|
94
|
-
for _ in range(self.k):
|
|
95
|
-
new_diggers.append(digger.new_sigma_digger(self.Xmin, self.Xmax, sigma, self.f))
|
|
96
|
-
population = np.append(population, new_diggers)
|
|
97
|
-
population = np.sort(population)
|
|
98
|
-
|
|
99
|
-
worst_diggers = population[self.n:]
|
|
100
|
-
r = np.random.rand(worst_diggers.size)
|
|
101
|
-
ind = np.where(r <= self.b)
|
|
102
|
-
worst_diggers = worst_diggers[ind]
|
|
103
|
-
for digger in worst_diggers:
|
|
104
|
-
intervals.append(
|
|
105
|
-
(digger.x - (self.Xmax - self.Xmin) * sigma, digger.x + (self.Xmax - self.Xmin) * sigma)
|
|
106
|
-
)
|
|
107
|
-
if len(intervals) > self.u:
|
|
108
|
-
intervals = intervals[len(intervals) - self.u - 1:len(intervals) - 1]
|
|
109
|
-
population = population[:self.n]
|
|
110
|
-
print("Поколение {}: {} {}".format(t, population[0].x, population[0].f))
|
|
111
|
-
t += 1
|
|
112
|
-
return population[0].x
|
|
113
|
-
|
|
114
|
-
@staticmethod
|
|
115
|
-
def interval_in(x, intervals):
|
|
116
|
-
for interval in intervals:
|
|
117
|
-
res = [x[i] >= interval[0][i] and x[i] <= interval[1][i] for i in range(len(x))]
|
|
118
|
-
if any(res):
|
|
119
|
-
return True
|
|
120
|
-
return False
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
def f(x):
|
|
124
|
-
return sum([(xi ** 4 - 16 * xi ** 2 + 5 *xi) / 2 for xi in x])
|
|
125
|
-
|
|
126
|
-
# gda = GoldDiggersAlgorithm(f, 15, 10, 10, 50, 0.5, 0.5, 0.5, 0.000001, [-5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12], [5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12], 2, 300)
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class GoldDigger:
|
|
5
|
+
|
|
6
|
+
def __init__(self, x, function):
|
|
7
|
+
self.x = x
|
|
8
|
+
self.f = function(self.x)
|
|
9
|
+
self.ep_n = 0
|
|
10
|
+
|
|
11
|
+
def __lt__(self, other):
|
|
12
|
+
return self.f < other.f
|
|
13
|
+
|
|
14
|
+
def __le__(self, other):
|
|
15
|
+
return self.f <= other.f
|
|
16
|
+
|
|
17
|
+
def __gt__(self, other):
|
|
18
|
+
return self.f > other.f
|
|
19
|
+
|
|
20
|
+
def __ge__(self, other):
|
|
21
|
+
return self.f >= other.f
|
|
22
|
+
|
|
23
|
+
def __add__(self, other):
|
|
24
|
+
return self.f + other.f
|
|
25
|
+
|
|
26
|
+
def __radd__(self, other):
|
|
27
|
+
return self.f + other
|
|
28
|
+
|
|
29
|
+
def __truediv__(self, other):
|
|
30
|
+
return self.f / other
|
|
31
|
+
|
|
32
|
+
def update_function(self, function):
|
|
33
|
+
self.f = function(self.x)
|
|
34
|
+
|
|
35
|
+
def new_sigma_digger(self, x_min, x_max, sigma, function):
|
|
36
|
+
new_x = np.array([self.x[i] + np.random.normal(0, (x_max[i] - x_min[i]) * sigma) for i in range(self.x.size)])
|
|
37
|
+
new_x = np.clip(new_x, x_min, x_max)
|
|
38
|
+
return GoldDigger(new_x, function)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class GoldDiggersAlgorithm:
|
|
43
|
+
|
|
44
|
+
def __init__(self, f, n, k, l, u, a, b, sigma_b, sigma_e, Xmin, Xmax, m, t_max):
|
|
45
|
+
self.f = f
|
|
46
|
+
self.n = n
|
|
47
|
+
self.k = k
|
|
48
|
+
self.l = l
|
|
49
|
+
self.u = u
|
|
50
|
+
self.a = a
|
|
51
|
+
self.b = b
|
|
52
|
+
self.sigma_b = sigma_b
|
|
53
|
+
self.sigma_e = sigma_e
|
|
54
|
+
self.Xmin = np.array(Xmin)
|
|
55
|
+
self.Xmax = np.array(Xmax)
|
|
56
|
+
self.m = m
|
|
57
|
+
self.t_max = t_max
|
|
58
|
+
self.rand_mat = np.vectorize(lambda x: self.random_matrix(x, Xmin, Xmax), signature='()->(n)')
|
|
59
|
+
self.digger_init = np.vectorize(lambda x: GoldDigger(x, self.f), signature='(n)->()')
|
|
60
|
+
|
|
61
|
+
@staticmethod
|
|
62
|
+
def random_matrix(x, x_min, x_max):
|
|
63
|
+
return x * np.random.uniform(x_min, x_max)
|
|
64
|
+
|
|
65
|
+
def start(self):
|
|
66
|
+
x = self.rand_mat(np.ones(self.n))
|
|
67
|
+
population = self.digger_init(x)
|
|
68
|
+
|
|
69
|
+
t = 0
|
|
70
|
+
intervals = []
|
|
71
|
+
while t <= self.t_max:
|
|
72
|
+
|
|
73
|
+
x = self.rand_mat(np.ones(self.n))
|
|
74
|
+
in_interval = np.array([self.interval_in(xi, intervals) for xi in x])
|
|
75
|
+
if np.any(in_interval == True):
|
|
76
|
+
ind = np.where(in_interval == False)
|
|
77
|
+
new_x = x[ind]
|
|
78
|
+
if new_x.size:
|
|
79
|
+
population = np.append(population, self.digger_init(new_x))
|
|
80
|
+
ind = np.where(in_interval == True)
|
|
81
|
+
r = np.random.rand(ind[0].size)
|
|
82
|
+
rand_ind = np.where(r <= self.a)
|
|
83
|
+
ind = (ind[0][rand_ind])
|
|
84
|
+
x = x[ind]
|
|
85
|
+
if x.size:
|
|
86
|
+
population = np.append(population, self.digger_init(x))
|
|
87
|
+
else:
|
|
88
|
+
population = np.append(population, self.digger_init(x))
|
|
89
|
+
|
|
90
|
+
sigma = (((self.t_max - t) / self.t_max) ** self.m) * (self.sigma_b - self.sigma_e) + self.sigma_e
|
|
91
|
+
|
|
92
|
+
new_diggers = []
|
|
93
|
+
for digger in population:
|
|
94
|
+
for _ in range(self.k):
|
|
95
|
+
new_diggers.append(digger.new_sigma_digger(self.Xmin, self.Xmax, sigma, self.f))
|
|
96
|
+
population = np.append(population, new_diggers)
|
|
97
|
+
population = np.sort(population)
|
|
98
|
+
|
|
99
|
+
worst_diggers = population[self.n:]
|
|
100
|
+
r = np.random.rand(worst_diggers.size)
|
|
101
|
+
ind = np.where(r <= self.b)
|
|
102
|
+
worst_diggers = worst_diggers[ind]
|
|
103
|
+
for digger in worst_diggers:
|
|
104
|
+
intervals.append(
|
|
105
|
+
(digger.x - (self.Xmax - self.Xmin) * sigma, digger.x + (self.Xmax - self.Xmin) * sigma)
|
|
106
|
+
)
|
|
107
|
+
if len(intervals) > self.u:
|
|
108
|
+
intervals = intervals[len(intervals) - self.u - 1:len(intervals) - 1]
|
|
109
|
+
population = population[:self.n]
|
|
110
|
+
print("Поколение {}: {} {}".format(t, population[0].x, population[0].f))
|
|
111
|
+
t += 1
|
|
112
|
+
return population[0].x
|
|
113
|
+
|
|
114
|
+
@staticmethod
|
|
115
|
+
def interval_in(x, intervals):
|
|
116
|
+
for interval in intervals:
|
|
117
|
+
res = [x[i] >= interval[0][i] and x[i] <= interval[1][i] for i in range(len(x))]
|
|
118
|
+
if any(res):
|
|
119
|
+
return True
|
|
120
|
+
return False
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def f(x):
|
|
124
|
+
return sum([(xi ** 4 - 16 * xi ** 2 + 5 *xi) / 2 for xi in x])
|
|
125
|
+
|
|
126
|
+
# gda = GoldDiggersAlgorithm(f, 15, 10, 10, 50, 0.5, 0.5, 0.5, 0.000001, [-5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12, -5.12], [5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12, 5.12], 2, 300)
|
|
127
127
|
# gda.start()
|