-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
4d3a3aa
commit ca8bf81
Showing
4 changed files
with
236 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
import random | ||
import Problem | ||
import numpy as np | ||
|
||
# This class contains the code of the Particles in the swarm | ||
class Particle: | ||
def __init__(self,problem,c1,c2,w): | ||
self.problem = problem | ||
self.c1 = c1 | ||
self.c2 = c2 | ||
self.w = w | ||
self.position = problem.generate_random_ponit() | ||
self.velocity = np.random.uniform(0,1,problem.n) | ||
self.personal_best = self.position.copy() | ||
self.personal_best_value = 0 | ||
|
||
def update_positions(self): | ||
#Update the position: | ||
#position = position + velocity | ||
self.position = self.position + self.velocity | ||
return | ||
|
||
def update_velocities(self, golbal_best): | ||
#Update the velocity: | ||
#velocity = w * velocity + c1 * r1 * (golbal_best - position) | ||
# + c2 * r2 * (personal_best - position). | ||
for i in range(self.problem.n): | ||
r1 = np.random.rand() | ||
r2 = np.random.rand() | ||
|
||
#social part | ||
social = self.c1 * r1 * (golbal_best[i] - self.position[i]) | ||
|
||
#recognition part | ||
cognitive = self.c2 * r2 * (self.personal_best[i] - self.position[i]) | ||
|
||
self.velocity[i] = (self.w * self.velocity[i]) + social + cognitive | ||
return | ||
|
||
|
||
# This class contains the particle swarm optimization algorithm | ||
class ParticleSwarmOptimizer: | ||
def __init__(self,problem,swarmSize,iterations,c1,c2,w): | ||
self.problem = problem | ||
self.swarmSize = swarmSize | ||
self.iterations = iterations | ||
self.swarm = [] | ||
self.generate_init_swarms(c1,c2,w) | ||
|
||
def generate_init_swarms(self,c1,c2,w): | ||
for i in range(self.swarmSize): | ||
#Initialize particle | ||
particle = Particle(self.problem,c1,c2,w) | ||
particle.personal_best_value = self.fitness_function(particle.personal_best) | ||
self.swarm.append(particle) | ||
self.update_global_best() | ||
|
||
|
||
#update the global best particle | ||
def update_global_best(self): | ||
self.global_best = self.swarm[0].position | ||
self.global_best_value = self.swarm[0].personal_best_value | ||
for j in range(self.swarmSize): | ||
|
||
#If the personal best value value is better than the global best | ||
# value Set current personal best value as the new global best | ||
personal_best_value = self.swarm[j].personal_best_value | ||
if personal_best_value < self.global_best_value: | ||
self.global_best = self.swarm[j].personal_best | ||
self.global_best_value = personal_best_value | ||
|
||
#Update the personal best positions | ||
def update_personal_best(self): | ||
for l in range(self.swarmSize): | ||
|
||
#If the fitness value is better than the personal best fitness | ||
# value Set current value as the personal best | ||
personal_best_value = self.swarm[l].personal_best_value | ||
current_value = self.fitness_function(self.swarm[l].position) | ||
if current_value < personal_best_value: | ||
self.swarm[l].personal_best = self.swarm[l].position | ||
self.swarm[l].personal_best_value = current_value | ||
|
||
def fitness_function(self,position): | ||
return self.problem.get_value(position) | ||
|
||
def optimize(self): | ||
for i in range(self.iterations ): | ||
for k in range(self.swarmSize): | ||
#Update velocitie of each paricle | ||
self.swarm[k].update_velocities(self.global_best) | ||
#Update position of each paricle | ||
self.swarm[k].update_positions() | ||
self.update_personal_best() | ||
self.update_global_best() | ||
return self.global_best |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
from abc import ABC,abstractmethod | ||
from enum import Enum | ||
import numpy as np | ||
import math | ||
#Problem interface for all test functions | ||
class IProblem(ABC): | ||
n = 0 | ||
lbound = 0 | ||
ubound = 0 | ||
|
||
def generate_random_ponit(self): | ||
return np.random.uniform(self.lbound,self.ubound,size=(self.n)) | ||
|
||
def generate_random_ponits(self,count): | ||
return np.random.uniform(self.lbound,self.ubound,size=(count,self.n)) | ||
|
||
@abstractmethod | ||
def get_value(self, swarm): | ||
pass | ||
|
||
#an enum for test functions | ||
class ProblemType(Enum): | ||
Ackley = 1, | ||
PowellSum = 2, | ||
Booth = 3, | ||
DropWave = 4, | ||
SumSquares = 5, | ||
Griewank = 6 | ||
|
||
#a factory class for generate test function class | ||
class ProblemFactory: | ||
@staticmethod | ||
def generateProblem(type: ProblemType,n,lbound,ubound): | ||
if type == ProblemType.Ackley: | ||
return Ackley(n,lbound,ubound) | ||
elif type == ProblemType.Booth: | ||
return Booth(n,lbound,ubound) | ||
elif type == ProblemType.PowellSum: | ||
return PowellSum(n,lbound,ubound) | ||
elif type == ProblemType.DropWave: | ||
return DropWave(n,lbound,ubound) | ||
elif type == ProblemType.SumSquares: | ||
return SumSquares(n,lbound,ubound) | ||
elif type == ProblemType.Griewank: | ||
return Griewank(n,lbound,ubound) | ||
class PowellSum(IProblem): | ||
|
||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
|
||
#get value for custom state | ||
def get_value(self, swarm): | ||
value = 0 | ||
for i in range(self.n): | ||
value = value + abs(swarm[i])**(i+2) | ||
return value | ||
|
||
class Booth(IProblem): | ||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
|
||
def get_value(self,swarm): | ||
value = (swarm[0] + (2 * swarm[1]) - 7)**2 + ( (2 * swarm[0]) + swarm[1] - 5)**2 | ||
return value | ||
|
||
class DropWave(IProblem): | ||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
|
||
def get_value(self, swarm): | ||
part1 = -1 * math.cos(12 * (math.sqrt((swarm[0]**2) + (swarm[1]**2)))) | ||
part2 = (0.5 * (swarm[0]**2) + (swarm[1]**2)) + 2 | ||
value = part1 / part2 | ||
return value | ||
|
||
class Ackley(IProblem): | ||
C1=20 | ||
C2=.2 | ||
C3=2*np.pi | ||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
def get_value(self, swarm): | ||
part1 = -1. * self.C1 * np.exp( | ||
-1. * self.C2 * np.sqrt((1./self.n) * sum(map(lambda nb: nb**2, swarm))) | ||
) | ||
part2 = -1. * np.exp( | ||
(1./self.n) * \ | ||
sum(map(lambda nb: np.cos(self.C3 * nb), swarm)) | ||
) | ||
return part1 + part2 + self.C1 + np.exp(1) | ||
|
||
class SumSquares(IProblem): | ||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
def get_value(self, swarm): | ||
return np.sum(np.arange(1,self.n+1) * (swarm**2)) | ||
|
||
class Griewank(IProblem): | ||
def __init__(self,n,lbound,ubound): | ||
self.n = n | ||
self.lbound = lbound | ||
self.ubound = ubound | ||
def get_value(self, swarm): | ||
part1 = 0 | ||
for i in range(len(swarm)): | ||
part1 += swarm[i]**2 | ||
part2 = 1 | ||
for i in range(len(swarm)): | ||
part2 *= math.cos(float(swarm[i]) / math.sqrt(i+1)) | ||
return 1 + (float(part1)/4000.0) - float(part2) | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
# PSO | ||
#Particle Swarm Optimization (PSO) with Python |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
import PSO | ||
import Problem | ||
import numpy as np | ||
|
||
|
||
problem = Problem.ProblemFactory.generateProblem( | ||
Problem.ProblemType.Ackley, 5, -32, 32) | ||
|
||
iterations = 100 | ||
swarmSize = 50 | ||
c1 = 2 #social constant | ||
c2 = 2 #cognative constant | ||
w = 0.2 #constant inertia weight | ||
pso = PSO.ParticleSwarmOptimizer(problem, swarmSize, iterations, c1, c2, w) | ||
solution = pso.optimize() | ||
print('global best position : {0} - global best value : {1}'.format(solution,problem.get_value(solution))) | ||
|