much better manual mode
[imago.git] / src / pso.py
1 """Particle swarm optimization"""
2
3 import random
4 import multiprocessing
5 from functools import partial
6
7 import lhs
8
9 def particle(dimension, bound, v_max, func_d, pos=None):
10     """Create a new particle."""
11     if not pos:
12         position = [2 * bound * random.random() - bound for _ in xrange(dimension)]
13     else:
14         position = pos
15     velocity = [2 * v_max * random.random() - v_max for _ in xrange(dimension)]
16     value = func_d(*position)
17     return value, position, velocity, value, position
18
19 def move(particle, omega, phi_p, phi_g, v_max, global_best, func_d):
20     """Move the *particle*."""
21     _, position, velocity, best_value, best_position = particle
22     position = [p + v for (p, v) in zip(position, velocity)]
23     velocity = [omega * v 
24                 + phi_p * random.random() * (b - x)
25                 + phi_g * random.random() * (g - x)
26                 for (v, x, b, g) in zip(velocity, position,
27                                         best_position, global_best)]
28     velocity = [min(max(v, - v_max), v_max) for v in velocity] 
29     value = func_d(*position)
30     if value > best_value:
31         best_value, best_position = value, position
32     return value, position, velocity, best_value, best_position
33
34 def optimize(dimension, boundary, function_d, n_parts, n_turns):
35     """Optimize *function_d* of given *dimension* in space bounded by
36     symmetrical *boundary*. Use *n_parts* particles for *n_turn* turns."""
37     pool = multiprocessing.Pool(None)
38     v_max = boundary
39     particles = [particle(dimension, boundary, v_max, function_d, pos)
40                  for pos in lhs.latin_hypercube(dimension, bound, n_parts)]
41     gl_best = max(particles)
42     for _ in xrange(n_turns):
43         move_p = partial(move, 
44                          omega=0.98, phi_p=2.75, phi_g=3., v_max=v_max,
45                          global_best=gl_best[1], func_d=function_d)
46         particles = pool.map(move_p, particles)
47         gl_best = max(max(particles), gl_best)
48     pool.terminate()
49     pool.join()
50     return gl_best[1]