Skip to content

Instantly share code, notes, and snippets.

@arneschreuder
Last active December 7, 2018 08:38
Show Gist options
  • Save arneschreuder/06d5a5befcf2c4fbe97d to your computer and use it in GitHub Desktop.
Save arneschreuder/06d5a5befcf2c4fbe97d to your computer and use it in GitHub Desktop.
Global Best Particle Swarm Optimisation (PSO) in 100 lines of Python code.
# IMPORTS
from random import uniform
from copy import deepcopy
# TUNABLE CONSTANTS
swarm_size = 10
w = 0.729844
c1 = 1.496180
c2 = 1.496180
dimensions = 5
domain = {"min": -30, "max": 30}
iterations = 1000
runs = 1
pso = None
# VARIABLES
class Particle:
position = [None]*dimensions
velocity = [None]*dimensions
fitness = float("inf")
pbest = [None]*dimensions
class Swarm:
particles = map(lambda particle: Particle(), [None]*swarm_size)
class GBestPSO:
swarm = Swarm()
gbest = None
def f(x):
# Quadratic problem
return sum(map(lambda x_i: x_i**2, x))
def evaluate():
global pso
for particle in pso.swarm.particles:
particle.fitness = f(particle.position)
pbestFitness = f(particle.pbest)
# Keep track of pbest and pbest fitness
particle.pbest = deepcopy(particle.position) if (particle.pbest == None) or (particle.fitness < pbestFitness) else particle.pbest
# Keep track of gbest and gbest fitness.
pso.gbest = deepcopy(particle) if (pso.gbest == None) or (particle.fitness < pso.gbest.fitness) else pso.gbest
def init():
global pso
pso = GBestPSO()
# Place particles and evaluate on the spot
for particle in pso.swarm.particles:
particle.position = map(lambda j: uniform(domain["min"], domain["max"]), particle.position)
particle.velocity = map(lambda j: 0, particle.velocity)
particle.pbest = deepcopy(particle.position)
evaluate()
def update():
global pso
for particle in pso.swarm.particles:
for j in range(dimensions):
r1 = uniform(0,1)
r2 = uniform(0,1)
# Velocity update rule
particle.velocity[j] = (
w*particle.velocity[j] + # Velocity clamping via inertia weight
c1*r1*(particle.pbest[j] - particle.position[j]) + # Cognitive component
c2*r2*(pso.gbest.position[j] - particle.position[j]) # Social Component
)
# Position update rule
particle.position[j] = (
particle.position[j] +
particle.velocity[j]
)
# Boundary clamping
particle.position[j] = max(domain["min"], particle.position[j])
particle.position[j] = min(domain["max"], particle.position[j])
def step():
global pso
update()
evaluate()
def run():
global pso
init()
for iteration in range(iterations):
step()
print pso.gbest.fitness
if __name__ == "__main__":
for runs in range(runs):
run()
@arneschreuder
Copy link
Author

Urggh... was bored. So not the best way to combine OOP and Functional programming. But it does the job. I hope this can aid as a simple example for someone studying Artificial Intelligence paradigms such as PSO.

@arneschreuder
Copy link
Author

Fixed pbest not being updated correctly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment