1
|
|
|
"""Artificial Bee Colony algorithm. |
2
|
|
|
|
3
|
|
|
Date: 12. 2. 2018 |
4
|
|
|
|
5
|
|
|
Authors : Uros Mlakar |
6
|
|
|
|
7
|
|
|
License: MIT |
8
|
|
|
|
9
|
|
|
Reference paper: Karaboga, D., and Bahriye B. "A powerful |
10
|
|
|
and efficient algorithm for numerical function optimization: artificial |
11
|
|
|
bee colony (ABC) algorithm." Journal of global optimization 39.3 (2007): 459-471. |
12
|
|
|
|
13
|
|
|
""" |
14
|
|
|
|
15
|
|
|
import random as rnd |
16
|
|
|
import copy |
17
|
|
|
|
18
|
|
|
__all__ = ['ArtificialBeeColonyAlgorithm'] |
19
|
|
|
|
20
|
|
|
|
21
|
|
|
class SolutionABC: |
22
|
|
|
def __init__(self, D, LB, UB): |
23
|
|
|
self.D = D |
24
|
|
|
self.Solution = [] |
25
|
|
|
self.Fitness = float('inf') |
26
|
|
|
self.LB = LB |
27
|
|
|
self.UB = UB |
28
|
|
|
self.generateSolution() |
29
|
|
|
|
30
|
|
|
def generateSolution(self): |
31
|
|
|
self.Solution = [self.LB + (self.UB - self.LB) |
32
|
|
|
* rnd.random() for i in range(self.D)] |
33
|
|
|
|
34
|
|
|
def repair(self): |
35
|
|
|
for i in range(self.D): |
36
|
|
|
if (self.Solution[i] > self.UB): |
|
|
|
|
37
|
|
|
self.Solution[i] = self.UB |
38
|
|
|
if self.Solution[i] < self.LB: |
39
|
|
|
self.Solution[i] = self.LB |
40
|
|
|
|
41
|
|
|
def evaluate(self): |
42
|
|
|
self.Fitness = SolutionABC.FuncEval(self.D, self.Solution) |
43
|
|
|
|
44
|
|
|
def toString(self): |
45
|
|
|
pass |
46
|
|
|
|
47
|
|
|
|
48
|
|
|
class ArtificialBeeColonyAlgorithm: |
|
|
|
|
49
|
|
|
def __init__(self, NP, D, nFES, Lower, Upper, function): |
50
|
|
|
self.NP = NP |
51
|
|
|
self.D = D |
52
|
|
|
self.FoodNumber = self.NP / 2 |
53
|
|
|
self.Limit = 100 |
54
|
|
|
self.Trial = [] |
55
|
|
|
self.Foods = [] |
56
|
|
|
self.Probs = [] |
57
|
|
|
self.nFES = nFES |
58
|
|
|
self.Lower = Lower |
59
|
|
|
self.Upper = Upper |
60
|
|
|
SolutionABC.FuncEval = staticmethod(function) |
61
|
|
|
self.Best = SolutionABC(self.D, Lower, Upper) |
62
|
|
|
|
63
|
|
|
def reset(self): |
64
|
|
|
self.__init__(self.NP, self.D, self.MaxCycle) |
|
|
|
|
65
|
|
|
|
66
|
|
|
def init(self): |
67
|
|
|
self.Probs = [0 for i in range(self.FoodNumber)] |
68
|
|
|
self.Trial = [0 for i in range(self.FoodNumber)] |
69
|
|
|
for i in range(self.FoodNumber): |
70
|
|
|
self.Foods.append(SolutionABC(self.D, self.Lower, self.Upper)) |
71
|
|
|
self.Foods[i].evaluate() |
72
|
|
|
self.checkForBest(self.Foods[i]) |
73
|
|
|
|
74
|
|
|
def CalculateProbs(self): |
75
|
|
|
self.Probs = [1.0 / (self.Foods[i].Fitness + 0.01) |
76
|
|
|
for i in range(self.FoodNumber)] |
77
|
|
|
s = sum(self.Probs) |
78
|
|
|
self.Probs = [self.Probs[i] / s for i in range(self.FoodNumber)] |
79
|
|
|
|
80
|
|
|
def checkForBest(self, Solution): |
81
|
|
|
if Solution.Fitness <= self.Best.Fitness: |
82
|
|
|
self.Best = copy.deepcopy(Solution) |
83
|
|
|
|
84
|
|
|
def run(self): |
85
|
|
|
self.init() |
86
|
|
|
FEs = self.FoodNumber |
87
|
|
|
while FEs < self.nFES: |
88
|
|
|
self.Best.toString() |
89
|
|
|
for i in range(self.FoodNumber): |
90
|
|
|
newSolution = copy.deepcopy(self.Foods[i]) |
91
|
|
|
param2change = int(rnd.random() * self.D) |
92
|
|
|
neighbor = int(self.FoodNumber * rnd.random()) |
93
|
|
|
newSolution.Solution[param2change] = self.Foods[i].Solution[param2change] + (-1 + 2 * rnd.random()) * ( |
|
|
|
|
94
|
|
|
self.Foods[i].Solution[param2change] - self.Foods[neighbor].Solution[param2change]) |
|
|
|
|
95
|
|
|
newSolution.repair() |
96
|
|
|
newSolution.evaluate() |
97
|
|
|
if newSolution.Fitness < self.Foods[i].Fitness: |
98
|
|
|
self.checkForBest(newSolution) |
99
|
|
|
self.Foods[i] = newSolution |
100
|
|
|
self.Trial[i] = 0 |
101
|
|
|
else: |
102
|
|
|
self.Trial[i] += 1 |
103
|
|
|
FEs += self.FoodNumber |
104
|
|
|
self.CalculateProbs() |
105
|
|
|
t, s = 0, 0 |
106
|
|
|
while t < self.FoodNumber: |
107
|
|
|
if rnd.random() < self.Probs[s]: |
108
|
|
|
t += 1 |
109
|
|
|
Solution = copy.deepcopy(self.Foods[s]) |
110
|
|
|
param2change = int(rnd.random() * self.D) |
111
|
|
|
neighbor = int(self.FoodNumber * rnd.random()) |
112
|
|
|
while neighbor == s: |
113
|
|
|
neighbor = int(self.FoodNumber * rnd.random()) |
114
|
|
|
Solution.Solution[param2change] = self.Foods[s].Solution[param2change] + (-1 + 2 * rnd.random()) * ( |
|
|
|
|
115
|
|
|
self.Foods[s].Solution[param2change] - self.Foods[neighbor].Solution[param2change]) |
|
|
|
|
116
|
|
|
Solution.repair() |
117
|
|
|
Solution.evaluate() |
118
|
|
|
FEs += 1 |
119
|
|
|
if Solution.Fitness < self.Foods[s].Fitness: |
120
|
|
|
self.checkForBest(newSolution) |
121
|
|
|
self.Foods[s] = Solution |
122
|
|
|
self.Trial[s] = 0 |
123
|
|
|
else: |
124
|
|
|
self.Trial[s] += 1 |
125
|
|
|
s += 1 |
126
|
|
|
if s == self.FoodNumber: |
127
|
|
|
s = 0 |
128
|
|
|
|
129
|
|
|
mi = self.Trial.index(max(self.Trial)) |
130
|
|
|
if self.Trial[mi] >= self.Limit: |
131
|
|
|
self.Foods[mi] = SolutionABC(self.D, self.Lower, self.Upper) |
132
|
|
|
self.Foods[mi].evaluate() |
133
|
|
|
FEs += 1 |
134
|
|
|
self.Trial[mi] = 0 |
135
|
|
|
return self.Best.Fitness |
136
|
|
|
|