以下の論文のPSOアルゴリズムに従った。


In [1]:
%matplotlib inline

import numpy as np
import pylab as pl
import math 
from sympy import *
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from mpl_toolkits.mplot3d import Axes3D

In [182]:
def TSP_map(N): #100×100の正方格子内にN個の点を配置する関数
    TSP_map = []
    X = [i for i in range(100)]
    Y = [i for i in range(100)]
    x = np.array([])
    y = np.array([])
    for i in range(N):
        x = np.append(x, np.random.choice(X))
        y = np.append(y, np.random.choice(Y))
    for i in range(N):
        TSP_map.append([x[i], y[i]])
    return TSP_map

In [400]:
class PSO:
    def __init__(self, N, pN, omega, alpha, beta):
        self.N = N
        self.pN = pN
        self.omega = omega
        self.alpha = alpha 
        self.beta = beta
        self.city = TSP_map(N)
        
    def initialize(self):
        ptcl = np.array([])
        for i in range(self.pN):
            a = np.random.choice([i for i in range(self.N - 1)])
            b = np.random.choice([i for i in range(a, self.N)])
            V = [a, b]
            ptcl = np.append(ptcl, particle(i, V, self.N, self.omega, self.alpha, self.beta))
        self.ptcl = ptcl
        return self.ptcl
    
    def one_simulate(self):
        for i in range(self.pN):
            self.ptcl[i].SS_id()
            self.ptcl[i].SS_gd(self.p_gd_X)
            self.ptcl[i].new_V()
            self.ptcl[i].new_X()
            self.ptcl[i].P_id(self.city)
            
    def simulate(self, sim_num):
        for i in range(self.pN):
            self.ptcl[i].initial(self.city)
        self.p_gd_X = self.P_gd()
        for i in range(sim_num):
            self.one_simulate()
            self.p_gd_X = self.P_gd()
        self.p_gd_X = self.P_gd()
        return self.p_gd_X
     
    def P_gd(self):
        P_gd = self.ptcl[0].p_id
        no = 0
        for i in range(self.pN):
            if P_gd < self.ptcl[i].p_id:
                P_gd = self.ptcl[i].p_id
                self.no = i
        return self.ptcl[self.no].p_id_X

In [417]:
class particle:
    def __init__(self, No, V, num_city, omega, alpha, beta): #noは粒子の番号(ナンバー)である。
        self.No = No
        self.V = V
        self.num_city = num_city
        self.omega = omega
        self.alpha = alpha 
        self.beta = beta
        self.X = self.init_X()
        
    def initial(self, city):
        self.ss_id = []
        self.ss_gd = []
        self.P_id(city)
    
    def init_X(self):
        c = np.array([i for i in range(self.num_city)])
        np.random.shuffle(c)
        return c
    
    def SO(self, V, P):
        SO = []
        for i in range(len(V)):
            if V[i] != P[i]:
                t = np.where(V == P[i])
                t = int(t[0])
                a = V[i]
                b = V[t]
                V[i] = b
                V[t] = a
                SO.append([i, t])
        return SO
        
    def SS_id(self):
        self.ss_id = self.SO(self.X, self.p_id_X)
        
    def SS_gd(self, p_gd_X):
        self.ss_gd = self.SO(self.X, p_gd_X)
             
    def select(self, V, v, p):
        select_v = np.array([])
        for i in range(len(V)):
            x = np.random.choice([1, 0], p=[p, 1-p])
            if x == 1:
                select_v = np.append(select_v,V[i])
        return select_v
    
    def new_V(self):
        V = np.array([])
        self.select(V, self.V, self.omega)
        self.select(V, self.SS_id, self.alpha)
        self.select(V, self.ss_gd, self.beta)
        self.V = V
        return self.V
    
    def new_X(self):
        for i in range(len(self.V)):
            j = self.V[i][0]
            k = self.V[i][1]
            a = self.X[j]
            b = self.X[k]
            self.X[j] = b
            self.X[k] = a
        return self.X
    
    
    def P_id(self, city): #二都市間の距離を足し上げてP_idを求める関数。
        P_id = 0
        for i in range(self.num_city):
            if i != self.num_city-1:
                x1 = city[self.X[i]][0]
                y1 = city[self.X[i]][1]
                x2 = city[self.X[i+1]][0]
                y2 = city[self.X[i+1]][1]
            else:
                x1 = city[self.X[i]][0]
                y1 = city[self.X[i]][1]
                x2 = city[self.X[0]][0]
                y2 = city[self.X[0]][1]
            a = np.array([x1, y1])
            b = np.array([x2, y2])
            u = b - a
            p = np.linalg.norm(u)
            P_id += p
        if P_id < self.P_id:
            self.p_id = P_id
            self.p_id_X = self.X
        return self.p_id

10都市で行う。パラメータは左から順に、(都市の数、粒子の数、前期の速度の影響率、localベストの影響率、globalベストの影響率)である。


In [418]:
pso = PSO(10, 10, 0.3, 0.1, 0.3)

都市の座標とプロット。


In [419]:
pso.city


Out[419]:
[[40.0, 26.0],
 [16.0, 74.0],
 [74.0, 49.0],
 [55.0, 20.0],
 [20.0, 14.0],
 [24.0, 75.0],
 [87.0, 84.0],
 [15.0, 87.0],
 [8.0, 9.0],
 [34.0, 70.0]]

In [420]:
x = []
y = []
for i in range(len(pso.city)):
    x.append(pso.city[i][0])
    y.append(pso.city[i][1])
plt.scatter(x, y)


Out[420]:
<matplotlib.collections.PathCollection at 0x10b55bb50>

粒子の初期化。


In [421]:
pso.initialize()


Out[421]:
array([<__main__.particle instance at 0x10b55ae18>,
       <__main__.particle instance at 0x10ac81e18>,
       <__main__.particle instance at 0x10ac81ab8>,
       <__main__.particle instance at 0x10b4bba70>,
       <__main__.particle instance at 0x10b4bbe60>,
       <__main__.particle instance at 0x10b4bbea8>,
       <__main__.particle instance at 0x10b4bbd40>,
       <__main__.particle instance at 0x10b4bbbd8>,
       <__main__.particle instance at 0x10b4bbab8>,
       <__main__.particle instance at 0x10b4bbb00>], dtype=object)

100回シミュレーションした。


In [422]:
pso.simulate(100)


---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
<ipython-input-422-f8bd8acc09d9> in <module>()
----> 1 pso.simulate(100)

<ipython-input-400-22e24e62e66e> in simulate(self, sim_num)
     31         self.p_gd_X = self.P_gd()
     32         for i in range(sim_num):
---> 33             self.one_simulate()
     34             self.p_gd_X = self.P_gd()
     35         self.p_gd_X = self.P_gd()

<ipython-input-400-22e24e62e66e> in one_simulate(self)
     23             self.ptcl[i].SS_gd(self.p_gd_X)
     24             self.ptcl[i].new_V()
---> 25             self.ptcl[i].new_X()
     26             self.ptcl[i].P_id(self.city)
     27 

<ipython-input-417-1bd4fcf98187> in new_X(self)
     62             self.X[j] = b
     63             self.X[k] = a
---> 64         print b, a
     65         return self.X
     66 

UnboundLocalError: local variable 'b' referenced before assignment

In [415]:
x = []
y = []
for i in pso.p_gd_X:
    x.append(pso.city[i][0])
    y.append(pso.city[i][1])
plt.plot(x, y)


Out[415]:
[<matplotlib.lines.Line2D at 0x109d30a10>]

In [416]:
pso.no


Out[416]:
1

In [ ]:


In [ ]: