本文不对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
本文代码流程与上面文章所讲流程基本相同。
博主水平一般,欢迎批评指正。