本文不對PSO多做解釋,代碼主打通俗,只是最普通的PSO。
因為作業沒有要求保存每一代的position and speed並且沒有要求做自適應的動態慣性因子,所以一切從簡。
作業要求:
粒子數:100
迭代次數:100 // solving的參數
x1 x2 x3 范圍:[0, 15]
求解函數:y = 2x12 - 3x22 - 4x1 + 5x2 + x3
以圖的形式體現全局最優的變化
1 import math 2 import random 3 import matplotlib.pyplot as plt 4 5 c1 = 2 # 學習因子 # Learning coefficient 6 c2 = 2 7 8 def fitness(x1,x2,x3): #適應度函數 # Fitness Function 9 return math.floor((2*x1**2 - 3*x2**2 - 4*x1 + 5*x2 + x3)*100) / 100 10 11 class PSO: 12 def __init__(self): 13 self.pop_size = 100 # 粒子群個體數 # the number of the instance in Particle swarm 14 self.dim = 3 # 變量數 # the number of variables 15 self.omega = 0.4 # 慣性因子 # Inertia factor 16 self.x_max = 15 17 self.x_min = 0 18 self.v_max = (self.x_max - self.x_min) * 0.05 19 self.v_min = -(self.x_max - self.x_min) * 0.05 20 self.position = [[]] # 記錄當前粒子位置 # record the current position of each particle 21 self.speed = [[]] # 記錄當前粒子速度 # record the moving speed 22 self.best_value = [[]] # 記錄全局最優 # record the global optimal 23 self.value = [[]] # 記錄當前值 # record the current fitness and position 24 def initial(self): 25 for i in range(self.pop_size): 26 "第一輪初始化" 27 "first round of initialization" 28 x = [] 29 v = [] 30 for j in range(self.dim): 31 "所有math函數只為取兩位小數" 32 "all the math.floor() are used for rounding the result up to two decimal places" 33 x.append(math.floor(random.uniform(self.x_min,self.x_max) * 100) / 100) 34 v.append(math.floor(random.uniform(self.v_min,self.v_max) * 100) / 100) 35 self.position.append(x) 36 self.speed.append(v) 37 #self.value.append((fitness(x[0],x[1],x[2])) 38 self.value.append(((fitness(x[0],x[1],x[2])),x[0],x[1],x[2])) 39 self.value = self.value[1:] 40 # -------------------選擇取最大值/最小值-------------------# 41 "choose to get the max or the min value" 42 #index = self.value.index(max(self.value)) 43 index = self.value.index(min(self.value)) 44 # -------------------選擇取最大值/最小值-------------------# 45 self.best_value.append((self.value[index][0],self.position[index][0],self.position[index][1],self.position[index][2])) 46 self.best_value = self.best_value[1:] 47 self.position = self.position[1:] 48 self.speed = self.speed[1:] 49 print("the population and fitness after initialization:") 50 print("position :",self.position) 51 print("value:",self.value) 52 print("best value:",self.best_value) 53 print("------------------------split line------------------------") 54 def solving(self,times): 55 for i in range(times): 56 #print(self.value) 57 # -------------------選擇取最大值/最小值-------------------# 58 "choose to get the max or the min value" 59 #pbest = self.value[self.value.index(max(self.value))] 60 #gbest = self.best_value[self.best_value.index(max(self.best_value))] 61 pbest = self.value[self.value.index(min(self.value))] 62 gbest = self.best_value[self.best_value.index(min(self.best_value))] 63 # -------------------選擇取最大值/最小值-------------------# 64 print("pbest:",pbest) 65 print("gbest",gbest) 66 for j in range(self.pop_size): 67 x = [] 68 v = [] 69 for k in range(self.dim): 70 v.append(math.floor((self.omega * self.speed[j][k] + c1 * random.uniform(0,1) * (pbest[1+k] - self.position[j][k]) + c2 * random.uniform(0,1) * (gbest[1+k] - self.position[j][k])) * 100) / 100 ) 71 x.append(math.floor((self.position[j][k] + self.speed[j][k]) * 100) / 100) 72 "將位置和速度限制在規定范圍內" 73 "restrict the position and the speed" 74 if (v[k] < self.v_min): 75 v[k] = self.v_min 76 if (v[k] > self.v_max): 77 v[k] = self.v_max 78 if(x[k] < self.x_min): 79 x[k] = self.x_min 80 if(x[k] > self.x_max): 81 x[k] = self.x_max 82 "數據更新" 83 "updating" 84 self.position[j] = x 85 self.speed[j] = v 86 self.value[j] = (fitness(self.position[j][0],self.position[j][1],self.position[j][2]),self.position[j][0],self.position[j][1],self.position[j][2]) 87 # -------------------選擇取最大值/最小值-------------------# 88 "choose to get the max or the min value" 89 #index = self.value.index(max(self.value)) 90 index = self.value.index(min(self.value)) 91 # -------------------選擇取最大值/最小值-------------------# 92 "獲得全局最優" 93 "get the global optimal" 94 self.best_value.append((self.value[index][0], self.position[index][0], self.position[index][1],self.position[index][2])) 95 def returnbest(self): 96 return self.best_value 97 98 99 100 if __name__ == '__main__': 101 demo = PSO() 102 demo.initial() 103 demo.solving(100) 104 result = demo.returnbest() 105 for i in result: 106 print("value:",i[0],"x1:",i[1],"x2:",i[2],"x3:",i[3]) 107 X = [] 108 Y = [] 109 for i in range(100): 110 X.append(i) 111 Y.append(result[i][0]) 112 plt.plot(X, Y) 113 plt.show()
因為作業要交給日本老師看,所以打了比較詳細的雙語注釋,這里就不對代碼多做解釋了。
如果要更詳細地理解PSO的流程推薦這篇:https://blog.csdn.net/daaikuaichuan/article/details/81382794
本文代碼流程與上面文章所講流程基本相同。
博主水平一般,歡迎批評指正。