In [1]:
# -*- coding: utf-8 -*-
import sys
import numpy as np

##### Class dealing with particles #####
class PSOclass:
    ##### Inner class on each particle #####
    class particles:
        def __init__(self, set_dim):
            ### Information each particle ###
            self.position = np.zeros(set_dim)
            self.velocity = np.zeros(set_dim)
            self.fitness = 3.0 + pow(self.position[0],2) + pow(self.position[1],2)
            self.bestPosition = np.zeros(set_dim)
            self.bestFitness = sys.maxsize
            
        def update_fitness(self):
            self.fitness = 3.0 + pow(self.position[0],2) + pow(self.position[1],2)
            
        def disp_info(self):
            print('--\n Information of particle: ')
            print(' position = ' + str(self.position))
            print(' velocity = ' + str(self.velocity))
            print(' fitness = ' + str(self.fitness))
            print(' bestPosition = ' + str(self.bestPosition))
            print(' bestFitness = ' + str(self.bestFitness))
    
    def __init__(self, pp={}):
        if len(pp) == 0:
            ### PSO parameters ###
            self.__num_particles = 10                               # Number of perticle members
            self.__num_iterations = 10000                           # Number of iteration
            self.__dim = 2                                          # Number of solutions to calculate
            self.__minX = np.array([-100]*self.__dim)               # Minimum boundary of position solutions
            self.__maxX = np.array([100]*self.__dim)                # Maximum boundary of position solutions
            self.__minV = np.array([-1.0*i/5 for i in self.__maxX]) # Minimum boundary of velocity solutions
            self.__maxV = np.array([1.0*i/5 for i in self.__maxX])  # Maximum boundary of velocity solutions
            self.__best_global_posi = np.zeros(self.__dim)          # Optimal particle positions in all group
            self.__best_global_fit = sys.maxsize                    # Fitness of position
            self.__w = 0.7                                          # Inertial constant (recommended value)
            self.__c1 = 1.49445                                     # Local mass of particles (recommended value)
            self.__c2 = 1.49445                                     # Global mass of particles (recommended value)
            self.disp_param()
        else:
            self.set_param(pp)
            
        # Generate particle group
        self.ps = [PSOclass.particles(self.__dim) for i in range(self.__num_particles)]
    
    def set_param(self, pp):
        ### PSO parameters ###
        if "num_particles" in pp:
            self.__num_particles = pp["num_particles"]     
        if "num_iterations" in pp:
            self.__num_iterations = pp["num_iterations"]         
        if "dim" in pp:
            self.__dim = pp["dim"]                             
        if "minX" in pp:
            self.__minX = pp["minX"]                              
        if "maxX" in pp:
            self.__maxX = pp["maxX"]                              
        if "minV" in pp:
            self.__minV = pp["minV"]                            
        if "maxV" in pp:
            self.__maxV = pp["maxV"]                              
        if "best_global_posi" in pp:
            self.__best_global_posi = pp["best_global_posi"]     
        if "best_global_fit" in pp:
            self.__best_global_fit = pp["best_global_fit"]       
        if "w" in pp:
            self.__w = pp["w"]                              
        if "c1" in pp:
            self.__c1 = pp["c1"]                                  
        if "c2" in pp:
            self.__c2 = pp["c2"]
            
        self.disp_param()
    
    def disp_param(self):
        print('--\n PSO parameters are setted as follows: ')
        print(' Number of particles = ' + str(self.__num_particles))
        print(' Number of iterations = ' + str(self.__num_iterations))
        print(' Dimension of parameters = ' + str(self.__dim))
        print(' Minimum limit of parameters = ' + str(self.__minX))
        print(' Maximum limit of solutions = ' + str(self.__maxX))
        print(' Minimum limit of velocities = ' + str(self.__minV))
        print(' Maximum limit of velocities = ' + str(self.__maxV))
        print(' Best global positions = ' + str(self.__best_global_posi))
        print(' Best global fitnesses = ' + str(self.__best_global_fit))
        print(' Inertial constant = ' + str(self.__w))
        print(' Local mass of particles = ' + str(self.__c1))
        print(' Global mass of particles = ' + str(self.__c2))
    
    ### Calculate fitness to optimize ###
    def get_fitness(self):
        return self.__fitness
    
    ### disp current best global fitness and best global position
    def disp_global_optimal(self):
        print(' Best global fitness = ' + str(self.__best_global_fit))
        print(' Best global position = ' + str(self.__best_global_posi))
    
    ##### Initilize particle group #####
    def initialize_particle(self):
        rap = np.zeros(self.__dim)   # random position
        rav = np.zeros(self.__dim)   # random velocity
        
        for i in range(self.__num_particles):
            # Initializing positions and velocities
            for j in range(self.__dim):
                rap[j] = abs(self.__maxX[j] - self.__minX[j]) * np.random.rand() + self.__minX[j]
                rav[j] = abs(self.__maxV[j] - self.__minV[j]) * np.random.rand() + self.__minV[j]

            self.ps[i].position = rap.copy()
            self.ps[i].velocity = rav.copy()

            # fitness in current random position
            self.ps[i].update_fitness() 
            self.ps[i].bestPosition = rap.copy()
            self.ps[i].bestFitness = self.ps[i].fitness
            
            if self.ps[i].fitness<self.__best_global_fit:
                self.__best_global_fit = self.ps[i].fitness
                self.__best_global_posi = self.ps[i].position.copy()
                
        print('--\n >> Finished initializing particles')
        self.disp_global_optimal()
        
    def optimize_particle(self):
        newp = np.zeros(self.__dim)
        newv = np.zeros(self.__dim)
        
        print('--\n >> Start optimizing particles')
        
        update_cnt = 0
        for ite in range(self.__num_iterations):
            for i in range(self.__num_particles):

                ### Updating velocities ###
                for j in range(self.__dim):
                    # Velocity upating formula in PSO
                    newv[j] = ((self.__w * self.ps[i].velocity[j]) +\
                               (self.__c1 * np.random.rand() * (self.ps[i].bestPosition[j] - self.ps[i].position[j])) +\
                               (self.__c2 * np.random.rand() * (self.__best_global_posi[j] - self.ps[i].position[j])))
                    # Check if updated velocity is between minimum value and maximum value
                    if newv[j] < self.__minV[j]:
                        newv[j] = self.__minV[j]
                    elif newv[j] > self.__maxV[j]:
                        newv[j] = self.__maxV[j]
                    # Position upating formula in PSO
                    newp[j] = self.ps[i].position[j] + newv[j]
                    # Check if updated position is between minimum value and maximum value
                    if newp[j] < self.__minX[j]:
                        newp[j] = self.__minX[j]
                    elif newp[j] > self.__maxX[j]:
                        newp[j] = self.__maxX[j]
                    
                # Update velocity and position of particle object
                self.ps[i].velocity = newv.copy()
                self.ps[i].position = newp.copy()
                
                # Update best fitness
                self.ps[i].update_fitness() 
                if self.ps[i].fitness < self.ps[i].bestFitness:
                    self.ps[i].bestPosition = newp.copy()
                    self.ps[i].bestFitness = self.ps[i].fitness
                if self.ps[i].fitness < self.__best_global_fit:
                    update_cnt += 1
                    self.__best_global_posi = newp.copy()
                    self.__best_global_fit = self.ps[i].fitness
                    print('\n >> Update optimal solution')
                    self.disp_global_optimal()
                    
        print('--\n >> Finished optimizing')
        self.disp_global_optimal()
                    
def main():
    pso_param = {"num_particles":5,
                "num_iterations":50,
                "dim":2,
                "best_global_fit":sys.maxsize,
                "w":0.7,
                "c1":1.49445,
                "c2":1.49445}
    pso_param.update(
        {"best_global_posi":np.zeros(pso_param["dim"]),
         "minX":np.array([-100]*pso_param["dim"]),
         "maxX":np.array([100]*pso_param["dim"])})
    pso_param.update(
         {"maxV":np.array([1.0*i/5 for i in pso_param["maxX"]]),
          "minV":np.array([-1.0*i/5 for i in pso_param["maxX"]])})
    
    ##### PSO #####
    pps = PSOclass(pso_param)
    pps.initialize_particle()
    pps.optimize_particle()
        
if __name__ == '__main__':
    main()


--
 PSO parameters are setted as follows: 
 Number of particles = 5
 Number of iterations = 50
 Dimension of parameters = 2
 Minimum limit of parameters = [-100 -100]
 Maximum limit of solutions = [100 100]
 Minimum limit of velocities = [-20. -20.]
 Maximum limit of velocities = [20. 20.]
 Best global positions = [0. 0.]
 Best global fitnesses = 9223372036854775807
 Inertial constant = 0.7
 Local mass of particles = 1.49445
 Global mass of particles = 1.49445
--
 >> Finished initializing particles
 Best global fitness = 2792.751977830244
 Best global position = [31.56805195 42.34631122]
--
 >> Start optimizing particles

 >> Update optimal solution
 Best global fitness = 2697.4665832621045
 Best global position = [26.04887062 44.89903031]

 >> Update optimal solution
 Best global fitness = 2300.095864960968
 Best global position = [12.04887062 46.38879802]

 >> Update optimal solution
 Best global fitness = 2196.4840658739386
 Best global position = [-14.27249735  44.60694884]

 >> Update optimal solution
 Best global fitness = 2196.021639521214
 Best global position = [10.68080071 45.59541792]

 >> Update optimal solution
 Best global fitness = 1902.1575789469862
 Best global position = [16.87933084 40.1776775 ]

 >> Update optimal solution
 Best global fitness = 987.6124220083785
 Best global position = [-29.50911837 -10.66884974]

 >> Update optimal solution
 Best global fitness = 762.5891194514835
 Best global position = [-7.95112938 26.38879802]

 >> Update optimal solution
 Best global fitness = 608.6189599264892
 Best global position = [-0.34209426 24.60694884]

 >> Update optimal solution
 Best global fitness = 575.3106845101931
 Best global position = [-3.12066916 23.71860258]

 >> Update optimal solution
 Best global fitness = 180.4936974024197
 Best global position = [-9.50911837  9.33115026]

 >> Update optimal solution
 Best global fitness = 112.87657260156888
 Best global position = [4.98883848 9.21889707]

 >> Update optimal solution
 Best global fitness = 60.28052902222638
 Best global position = [-3.97590386 -6.43993148]

 >> Update optimal solution
 Best global fitness = 55.07533274279115
 Best global position = [-3.77152181 -6.15231306]

 >> Update optimal solution
 Best global fitness = 18.06952205853753
 Best global position = [-1.5092023   3.57656686]

 >> Update optimal solution
 Best global fitness = 4.18487130340344
 Best global position = [-0.15192388  1.07786383]

 >> Update optimal solution
 Best global fitness = 3.030291553402719
 Best global position = [-0.12337392  0.12276167]

 >> Update optimal solution
 Best global fitness = 3.0275538040059353
 Best global position = [-0.14570401  0.0795245 ]

 >> Update optimal solution
 Best global fitness = 3.005996300190242
 Best global position = [-0.03313307 -0.06998928]

 >> Update optimal solution
 Best global fitness = 3.0057477939245425
 Best global position = [0.01175084 0.07489801]

 >> Update optimal solution
 Best global fitness = 3.0011938602248085
 Best global position = [0.03275574 0.01099644]

 >> Update optimal solution
 Best global fitness = 3.0009245624935956
 Best global position = [0.02827437 0.01118582]

 >> Update optimal solution
 Best global fitness = 3.0005869563102605
 Best global position = [0.02419271 0.00129194]

 >> Update optimal solution
 Best global fitness = 3.0003054938169846
 Best global position = [-0.01591781 -0.00721922]
--
 >> Finished optimizing
 Best global fitness = 3.0003054938169846
 Best global position = [-0.01591781 -0.00721922]