-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcuckoo.py
87 lines (65 loc) · 2.97 KB
/
cuckoo.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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
from config import beta,alpha,pa,niter
from utils import init_population
import numpy as np
import random
import math
class Cuckoo:
def __init__(self, problem, fitness_fn ,nest=None):
self.nest = nest
self.problem = problem
self.fitness_fn = fitness_fn
self.fitness = self.fitness_fn(self.problem,nest)
def __levy_flight(self, nest, problem): # discrete implementation for community detection
dimension = len(nest)
nest = np.array(nest)
sigma1 = np.power((math.gamma(1 + beta) * np.sin((np.pi * beta) / 2)) / math.gamma((1 + beta) / 2) * np.power(2, (beta - 1) / 2), 1 / beta)
sigma2 = 1
mu = np.random.normal(0, sigma1, size=dimension)
v = np.random.normal(0, sigma2, size=dimension)
step = mu / np.power(np.fabs(v), 1 / beta)
step *= alpha
sig_step = np.fabs((1 - np.exp(-1 * step)) / (1 + np.exp(-1 * step)))
new_nest = []
for j in range(dimension):
p = random.random()
if p < sig_step[j]:
new_nest.append(nest[j])
else:
k = random.choice(problem.adjList[j + 1]).opposite(j + 1)
new_nest.append(k)
return new_nest
def abandon_nest(self, problem):
new_nest = init_population(problem, 1)
self.nest = new_nest[0]
self.fitness = self.fitness_fn(self.problem,self.nest)
def get_cuckoo(self, problem): # by levy flight
return self.__levy_flight(self.nest, problem)
def cuckoo_algorithm(population, fitness_fn, problem, f_thres=1):
cuckoos = []
N = len(population)
for nest in population:
cuckoos.append(Cuckoo(problem,fitness_fn,nest))
cuckoos = sorted(cuckoos, key=lambda cuckoo: cuckoo.fitness,reverse=True)
best_nest = cuckoos[0].nest
best_fitness = cuckoos[0].fitness
iter = 0
while iter < niter and best_fitness < f_thres:
for i, cuckoo in enumerate(cuckoos):
candidate_nest = cuckoo.get_cuckoo(problem)
candidate_fitness = fitness_fn(problem,candidate_nest)
j = random.randint(0, N-1)
while j == i: # random j != i
j = random.randint(0, N-1)
if cuckoos[j].fitness < candidate_fitness: # for maximization
cuckoos[j].nest = candidate_nest
cuckoos[j].fitness = candidate_fitness
cuckoos = sorted(cuckoos, key=lambda cuckoo: cuckoo.fitness,reverse=True)
for cuckoo in cuckoos[int(-1 * N * pa):]:
cuckoo.abandon_nest(problem)
cuckoos = sorted(cuckoos, key=lambda cuckoo: cuckoo.fitness,reverse=True)
best_nest = cuckoos[0].nest
best_fitness = cuckoos[0].fitness
avg_fitness = sum([cuckoo.fitness for cuckoo in cuckoos])
print(f"[+] iter {iter} - best score: {best_fitness} - avg score: {avg_fitness/N}")
iter += 1
return best_nest