Completed
Push — master ( 6e6649...6e34b7 )
by Grega
9s
created

ParticleSwarmAlgorithm.evalSwarm()   A

Complexity

Conditions 3

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
c 0
b 0
f 0
dl 0
loc 5
rs 9.4285
1
import random as rnd
2
import copy
3
from NiaPy.benchmarks.utility import Utility
4
5
__all__ = ['ParticleSwarmAlgorithm']
6
7
8
class Particle(object):
9
    """Defines particle for population."""
10
11
    def __init__(self, D, LB, UB, vMin, vMax):
12
        self.D = D  # dimension of the problem
13
        self.LB = LB  # lower bound
14
        self.UB = UB  # upper bound
15
        self.vMin = vMin  # minimal velocity
16
        self.vMax = vMax  # maximal velocity
17
        self.Solution = []
18
        self.Velocity = []
19
20
        self.pBestPosition = []
21
        self.pBestSolution = []
22
        self.bestFitness = float('inf')
23
24
        self.Fitness = float('inf')
25
        self.generateParticle()
26
27
    def generateParticle(self):
28
        self.Solution = [self.LB + (self.UB - self.LB) * rnd.random()
29
                         for _i in range(self.D)]
30
        self.Velocity = [0 for _i in range(self.D)]
31
32
        self.pBestSolution = [0 for _i in range(self.D)]
33
        self.bestFitness = float('inf')
34
35
    def evaluate(self):
36
        self.Fitness = Particle.FuncEval(self.D, self.Solution)
37
        self.checkPersonalBest()
38
39
    def checkPersonalBest(self):
40
        if self.Fitness < self.bestFitness:
41
            self.pBestSolution = self.Solution
42
            self.bestFitness = self.Fitness
43
44
    def simpleBound(self):
45
        for i in range(self.D):
46
            if self.Solution[i] < self.LB:
47
                self.Solution[i] = self.LB
48
            if self.Solution[i] > self.UB:
49
                self.Solution[i] = self.UB
50
            if self.Velocity[i] < self.vMin:
51
                self.Velocity[i] = self.vMin
52
            if self.Velocity[i] > self.vMax:
53
                self.Velocity[i] = self.vMax
54
55
    def toString(self):
56
        pass
57
58
    def __eq__(self, other):
59
        return self.Solution == other.Solution and self.Fitness == other.Fitness
60
61
62
class ParticleSwarmAlgorithm(object):
63
    r"""Implementation of Particle Swarm Optimization algorithm.
64
65
    **Algorithm:** Particle Swarm Optimization algorithm
66
67
    **Date:** 2018
68
69
    **Author:** Uros Mlakar
70
71
    **License:** MIT
72
73
    **Reference paper:**
74
        Kennedy, J. and Eberhart, R. "Particle Swarm Optimization".
75
        Proceedings of IEEE International Conference on Neural Networks.
76
        IV. pp. 1942--1948, 1995.
77
78
    EDITED: TODO: Tests and validation! Bug in code.
79
    """
80
81
    def __init__(self, Np, D, nFES, C1, C2, w, vMin, vMax, benchmark):
82
        r"""**__init__(self, Np, D, nFES, C1, C2, w, vMin, vMax, benchmark)**.
83
84
        Arguments:
85
            NP {integer} -- population size
86
87
            D {integer} -- dimension of problem
88
89
            nFES {integer} -- number of function evaluations
90
91
            C1 {decimal} -- cognitive component
92
93
            C2 {decimal} -- social component
94
95
            w {decimal} -- inertia weight
96
97
            vMin {decimal} -- minimal velocity
98
99
            vMax {decimal} -- maximal velocity
100
101
            benchmark {object} -- benchmark implementation object
102
103
        """
104
105
        self.benchmark = Utility().get_benchmark(benchmark)
106
        self.Np = Np  # population size; number of search agents
107
        self.D = D  # dimension of the problem
108
        self.C1 = C1  # cognitive component
109
        self.C2 = C2  # social component
110
        self.w = w  # inertia weight
111
        self.vMin = vMin  # minimal velocity
112
        self.vMax = vMax  # maximal velocity
113
        self.Lower = self.benchmark.Lower  # lower bound
114
        self.Upper = self.benchmark.Upper  # upper bound
115
        self.Swarm = []
116
        self.nFES = nFES  # number of function evaluations
117
        self.FEs = 0
118
        self.Done = False
119
        Particle.FuncEval = staticmethod(self.benchmark.function())
120
121
        self.gBest = Particle(
122
            self.D,
123
            self.Lower,
124
            self.Upper,
125
            self.vMin,
126
            self.vMax)
127
128
    def evalSwarm(self):
129
        for p in self.Swarm:
130
            p.evaluate()
131
            if p.Fitness < self.gBest.Fitness:
132
                self.gBest = copy.deepcopy(p)
133
134
    def initSwarm(self):
135
        for _i in range(self.Np):
136
            self.Swarm.append(
137
                Particle(self.D,
138
                         self.Lower,
139
                         self.Upper,
140
                         self.vMin,
141
                         self.vMax))
142
143
    def tryEval(self, p):
144
        if self.FEs <= self.nFES:
145
            p.evaluate()
146
            self.FEs += 1
147
        else:
148
            self.Done = True
149
150
    def moveSwarm(self, Swarm):
151
        MovedSwarm = []
152
        for p in Swarm:
153
154
            part1 = ([(a - b) * rnd.random() * self.C1 for a,
155
                      b in zip(p.pBestSolution, p.Solution)])
156
            part2 = ([(a - b) * rnd.random() * self.C2 for a,
157
                      b in zip(self.gBest.Solution, p.Solution)])
158
159
            p.Velocity = ([self.w * a + b + c for a, b,
160
                           c in zip(p.Velocity, part1, part2)])
161
            p.Solution = ([a + b for a, b in zip(p.Solution, p.Velocity)])
162
163
            p.simpleBound()
164
            self.tryEval(p)
165
            if p.Fitness < self.gBest.Fitness:
166
                self.gBest = copy.deepcopy(p)
167
168
            MovedSwarm.append(p)
169
        return MovedSwarm
170
171
    def run(self):
172
        self.initSwarm()
173
        self.evalSwarm()
174
        self.FEs += self.Np
175
        while not self.Done:
176
            MovedSwarm = self.moveSwarm(self.Swarm)
177
            self.Swarm = MovedSwarm
178
179
        return self.gBest.Fitness
180