Metaheuristic: Particle Swarm Optimization (PSO) in Python
By Maxime Biais, Sunday 14 January 2007 at 23:27 :: Python :: #13 :: rss
From : PSO wikipedia article
Particle swarm optimization (PSO) is a form of swarm intelligence. Imagine a swarm of insects or a school of fish. If one sees a desirable path to go (e.g., for food, protection, etc.) the rest of the swarm will be able to follow quickly even if they are on the opposite side of the swarm. On the other hand, in order to facilitate felicitous exploration of the search space, typically one wants to have each particle to have a certain level of "craziness" or randomness in their movement, so that the movement of the swarm has a certain explorative capability: the swarm should be influenced by the rest of the swarm but also should independently explore to a certain extent. (This is a manifestation of the basic exploration-exploitation tradeoff that occurs in any search problem.)
PSO is a metaheuristic (also called global optimization algorithm), for dealing with problems in which a best solution can be represented as a point or surface in an n-dimensional space. Other famous metaheuristics:
- Simulated annealing, generalization of Monte Carlo method
- Cross-entropy method another generalization of Monte Carlo method
- Genetic algorithm
- Tabu search
- Ant colony organization
PSO is one of the best to find best solution of continuous functions (for example tabu search is better to find best solution of discrete functions). This article is about writing a PSO in Python for solving unary (arity 1) functions, code is easily generalizable to solve any arity functions. Each red point is an element of the swarm. The blue point is the global best element.
Python PSO code, nothing difficult to write, the complete code including PygamePrinter, is available here under GPL.
from random import uniform class PSO: def __init__(self, pop_size, min, max, phi, phi2, lr, maxiter, func): self.func = func self.pop = [] # 0: position, 1: velocity, 2: fitness self.min = min self.max = max for i in xrange(pop_size): self.pop.append([uniform(self.min, self.max), uniform(-1, 1), 0]) self.evaluate() self.gdest = self.pop[0] self.pdest = self.pop[0] self.phi = phi self.phi2 = phi2 self.lr = lr self.maxiter = maxiter def update_velocity(self): for i in self.pop: i[1] = self.lr * i[1] + uniform(0, self.phi) \ * (self.pdest[0] - i[0]) + uniform(0, self.phi2) \ * (self.gdest[0] - i[0]) def evaluate(self): for i in self.pop: i[2] = self.func(i[0]) def move(self): for i in self.pop: i[0] += i[1] def __cmp_by_fitness(self, a, b): return cmp(a[2], b[2]) def run(self, update_func=False): for i in xrange(self.maxiter): if update_func: update_func() self.update_velocity() self.move() self.evaluate() self.pop.sort(self.__cmp_by_fitness, reverse=0) self.pdest = self.pop[0] if self.pdest[2] < self.gdest[2]: self.gdest = self.pdest
Printed run on this test function:
func = lambda x:math.cos(x) * math.exp(math.sin(x)) * math.sin(x) / 1.5
Note the global best element is not computed at step 0:




Comments
1. Friday 26 January 2007 at 12:57, by Warren Henning
2. Friday 26 January 2007 at 13:01, by Warren Henning
3. Friday 26 January 2007 at 13:43, by Rob C
4. Friday 26 January 2007 at 13:49, by maxime
5. Friday 26 January 2007 at 15:11, by Mike
6. Friday 26 January 2007 at 15:48, by Warren Henning
7. Friday 26 January 2007 at 16:36, by jj
8. Friday 26 January 2007 at 19:08, by Jim
9. Tuesday 6 February 2007 at 11:46, by Maurice Clerc
10. Wednesday 6 June 2007 at 08:18, by J C Bansal
11. Tuesday 25 September 2007 at 20:09, by danvalho
Write your comment