基本PSO算法实现(Java)
一.算法流程
Step1:初始化一群粒子(粒子个数为50个),包括随即位置和速度;
Step2:计算每个粒子的适应度fitness;
Step3:对每个粒子,将其适应度与其进过的最好位置(局部)pbest做比较,如果较好,则将其作为当前的最好位置pbest;
Step4:对每个粒子,将其将其适应值与群体所经过的最好位置gbest做比较,如果较好,则将其作为当前最好位置gbest;
Step5:更新所有粒子位置和速度;
Step6:未达到结束条件则转Step2。
二.实验设置
(1) 粒子数particle_num=20;
(2) 迭代次数N=50;
(3) 惯性因子w=1.4;
(4) c1=c2=2;
(5) 最大速度Vmax=2。
三.实验说明
PSO维基:https://en.wikipedia.org/wiki/Particle_swarm_optimization
目标函数:https://en.wikipedia.org/wiki/Test_functions_for_optimization 中的Ackley's function、Sphere function、和Rosenbrock function(都是求最小值)
完整代码见我的github: https://github.com/wqpod2g/PSO
四.java代码
1.particle类
package nju.iip; import java.util.Random; /** * 粒子类 * @author mrpod2g * */ public class Particle { //维数 public int dimension = 2; //粒子的位置 public double[] X = new double[dimension]; //局部最好位置 public double[] pbest = new double[dimension]; //粒子的速度 public double[] V = new double[dimension]; //最大速度 public double Vmax = 2; //适应值 public double fitness; /** * 根据当前位置计算适应值 * @return newFitness */ public double calculateFitness() { //1.Ackley's function: //double newFitness = -20*Math.pow(Math.E,(-0.2*Math.sqrt(0.5*(X[0]*X[0]+X[1]*X[1]))))-Math.pow(Math.E,(0.5*(Math.cos(2*Math.PI*X[0])+Math.cos(2*Math.PI*X[1]))))+Math.E+20; //2.Sphere function //double newFitness = X[0]*X[0]+X[1]*X[1]; //3.Rosenbrock function double newFitness = 100*(Math.pow((X[1]-X[0]*X[0]),2))+Math.pow((X[0]-1), 2); return newFitness; } /** * 初始化自己的位置和pbest */ public void initialX() { for(int i=0;i<dimension;i++) { X[i] = new Random().nextInt(100); pbest[i] = X[i]; } } /** * 初始化自己的速度 */ public void initialV() { for(int i=0;i<dimension;i++) { double tmp = new Random().nextDouble();//随机产生一个0~1的随机小数 V[i] = tmp*4+(-2); } } }
2.PSO算法实现过程
package nju.iip; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * PSO算法实现 * @author mrpod2g * */ public class PSO { private static double[] gbest;//全局最优位置 private static double gbest_fitness = Double.MAX_VALUE;//全局最优位置对应的fitness private static int particle_num = 20;//粒子数 private static int N = 50;//迭代次数 private static int c1,c2 = 2; private static double w = 1.4;//惯性因子 private static List<Particle> particles = new ArrayList<Particle>();//粒子群 /** * 初始化所有粒子 */ public static void initialParticles() { for(int i=0;i<particle_num;i++) { Particle particle = new Particle(); particle.initialX(); particle.initialV(); particle.fitness = particle.calculateFitness(); particles.add(particle); } } /** * update gbest */ public static void updateGbest() { double fitness = Double.MAX_VALUE; int index = 0; for(int i=0;i<particle_num;i++) { if(particles.get(i).fitness<fitness) { index = i; fitness = particles.get(i).fitness; } } if(fitness<gbest_fitness) { gbest = particles.get(index).pbest.clone(); gbest_fitness = fitness; } } /** * 跟新每个粒子的速度 */ public static void updateV() { for(Particle particle:particles) { for(int i=0;i<particle.dimension;i++) { double v = w*particle.V[i]+c1*rand()*(particle.pbest[i]-particle.X[i])+c2*rand()*(gbest[i]-particle.X[i]); if(v>particle.Vmax) v = particle.Vmax; else if(v<-particle.Vmax) v = -particle.Vmax; particle.V[i] = v;//更新Vi } } } /** * 更新每个粒子的位置和pbest */ public static void updateX() { for(Particle particle:particles) { for(int i=0;i<particle.dimension;i++) { particle.X[i] = particle.X[i] + particle.V[i]; } double newFitness = particle.calculateFitness();//新的适应值 //如果新的适应值比原来的小则跟新fitness和pbest if(newFitness<particle.fitness) { particle.pbest = particle.X.clone(); particle.fitness = newFitness; } } } /** * 算法主要流程 */ public static void process() { int n = 0; initialParticles(); updateGbest(); while(n++<N) { updateV(); updateX(); updateGbest(); System.out.println(n+".当前gbest:("+gbest[0]+","+gbest[1]+") fitness="+gbest_fitness); } } /** * 返回一个0~1的随机数 * @return */ public static double rand() { return new Random().nextDouble(); } public static void main(String[] args) { process(); } }