Skip to content

particle_swarm

particle_swarm(fun, lb, ub, n_particles=100, max_iter=100, momentum=0.9, phi=0.1, verbose=False, topology='full')

Particle swarm optimization.

Parameters:

Name Type Description Default
fun callable

Function to minimize

required
lb (n,) numpy double array

Vector of lower bounds

required
ub (n,) numpy double array

Vector of upper bounds

required
n_particles int, optional (default: 100)

Number of particles

100
max_iter int, optional (default: 1000)

Maximum number of iterations

100
topology str, optional (default: 'full')

Connectivity of the swarm. Either 'full' or 'ring'.

'full'
verbose bool, optional (default: False)

Print progress to stdout

False

Returns:

Name Type Description
x (n,) numpy double array

Best solution

f double

Best objective value

Source code in src/gpytoolbox/particle_swarm.py
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def particle_swarm(fun,lb,ub,n_particles=100,max_iter=100,momentum=0.9,phi=0.1,verbose=False, topology='full'):
    """Particle swarm optimization.

    Parameters
    ----------
    fun : callable
        Function to minimize
    lb : (n,) numpy double array
        Vector of lower bounds
    ub : (n,) numpy double array
        Vector of upper bounds
    n_particles : int, optional (default: 100)
        Number of particles
    max_iter : int, optional (default: 1000)
        Maximum number of iterations
    topology : str, optional (default: 'full')
        Connectivity of the swarm. Either 'full' or 'ring'.
    verbose : bool, optional (default: False)
        Print progress to stdout

    Returns
    -------
    x : (n,) numpy double array
        Best solution
    f : double
        Best objective value
    """
    current_best_f = np.inf
    n = len(lb)
    x = np.random.uniform(lb,ub,(n_particles,n))
    best_xi = x.copy()
    best_fi = np.inf*np.ones(n_particles)
    for i in range(n_particles):
        # This x
        xi = x[i,:]
        # print(xi)
        f = fun(xi)
        # print(xi)
        best_xi[i,:] = xi.copy()
        best_fi[i] = np.squeeze(f.copy())
        # if verbose:
            # print("Particle %d: f = %f" % (i,f))
        if f < current_best_f:
            current_best_x = xi.copy()
            current_best_f = f.copy()
    # print(current_best_x.reshape((-1, 3)))
    # initialize particle velocities
    velocity_lb = lb - ub
    velocity_ub = ub - lb
    v = np.random.uniform(velocity_lb,velocity_ub,(n_particles,n))

    # Repeat until convergence
    for iter in range(max_iter):
        for i in range(n_particles):
            # Pick random numbers rp and rg between 0 and 1
            rp = np.random.uniform()
            rg = np.random.uniform()
            # Update velocity
            if topology == 'full':
                best_neighbor = current_best_x.copy()
            elif topology == 'ring':
                # Pick the best among the current particle and its two neighbors
                neighbors = np.array([i-1,i,i+1])%n_particles
                xi_neighbors = np.array([best_xi[j,:] for j in neighbors])
                fi_neighbors = np.array([best_fi[j] for j in neighbors])
                best_neighbor = xi_neighbors[np.argmin(fi_neighbors)]
            v[i,:] = momentum*v[i,:] + phi*rp*(best_xi[i,:] - x[i,:]) + phi*rg*(best_neighbor - x[i,:])
            # Update position
            x[i,:] = x[i,:] + v[i,:]
            # Check bounds
            x[i,:] = np.maximum(x[i,:],lb)
            x[i,:] = np.minimum(x[i,:],ub)
            # Evaluate objective
            f = fun(x[i,:])
            # Update best position
            if f < best_fi[i]:
                best_xi[i,:] = x[i,:].copy()
                best_fi[i] = np.squeeze(f.copy())
                if f < current_best_f:
                    current_best_x = x[i,:].copy()
                    current_best_f = f.copy()
        if verbose:
            print("Iteration %d: f = %f" % (iter,current_best_f))
    # print(current_best_x)
    return current_best_x, current_best_f