粒子群优化算法及其java实现

憋了两周终于把开题报告憋出来了,再一次证明自己不适合搞学术,哎……,花了点时间把报告中提到的粒子群算法看了看,看了些资料,用java跑起来。

算法简介

粒子群算法最先由Barnhart博士和Kennedy博士于1995 年提出,是一种源于对鸟群捕食行为的研究而发明的进化计算技术,原理是模仿鸟群寻觅食物的搜索过程,设想鸟群在一定区域搜寻食物,在不知道食物确切位置的情况下,鸟群依靠群体中个体判断距离食物的远近程度来调节飞行方向和飞行速度,最终通过群体的经验和自身记忆的智慧找到食物。

算法原理

算法描述
image

image
算法流程图
image

算法的实现(java)

  • Particle.java文件
package com.jiajia.pso;

import java.util.Random;

/**
 * @ClassName: Particle
 * @Author: fanjiajia
 * @Date: 2019/5/13 上午11:01
 * @Version: 1.0
 * @Description:
 */
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(50);
            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);
        }
    }
}
  • PSO.java
package com.jiajia.pso;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;


import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

/**
 * @ClassName: PSO
 * @Author: fanjiajia
 * @Date: 2019/5/13 上午11:02
 * @Version: 1.0
 * @Description:
 */
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 = 500;//迭代次数

    private static int c1,c2 = 2;

    private static double w = 1.4;//惯性因子

    private static List<Particle> particles = new ArrayList<Particle>();//粒子群

    private static List<Double> fittessList = new ArrayList<>(N);

    /**
     * 主程序入口
     * @param args
     */
    public static void main(String[] args) {
        process();
    }

    /**
     * 初始化所有粒子
     */
    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(int n) {
        for(Particle particle:particles) {
            for(int i=0;i<particle.dimension;i++) {
                double v =(0.9 - n*(0.9-0.4)/N) * 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(n);
            updateX();
            updateGbest();
            fittessList.add(gbest_fitness);
            System.out.println(n+".当前gbest:("+gbest[0]+","+gbest[1]+")  fitness="+gbest_fitness);
        }
        write2File();
    }
    
    /**
     * 返回一个0~1的随机数
     * @return
     */
    public static double rand() {
        return new Random().nextDouble();
    }
}

代码参考了其他资料,后面有说明,但是对其中部分进行了改进。

Particle(粒子类)中设定了三个适应函数,Ackley,Sphere,Rosenbrock,关于这三个函数的介绍可以参考资料,这里面列出来了很多优化测试函数,很多的paper在设计了优化策略或者改进相应的优化策略之后,都会利用其中的函数进行测试。
这里用到的函数是Rosenbrock:

Rosenbrock函数

可以看出这里最小值在(1,1,,,1)处取的。
为了看到相应的效果,这里将全局适应值写到txt文件中,并利用python绘制出来(莫名的感觉繁琐,要是python,哪有这么麻烦,只可惜最后的实验都是java写)。
w为1时

上面是
w
为1时,即惯性系数为1时的收敛结果,可以看出,算法前期搜索很快,后期较慢,且偶尔会陷入局部最优解里面。

惯性因子w的优化

惯性因子w代表受上一次粒子速度的影响程度,w越大,收敛越快,但容易错过最优解。w越小,收敛较慢,容易陷入局部最优解,出不来。因此改进w成为很多改进的焦点,其中采用较多的是Shi建议的线性递减权值策略,通常将w设定在[0.4,0.9]之间:

image

采用线性递减权值策略后得到的收敛效果:
image

可以看出前期收敛直线下降,且不容易陷入局部最优,最后达到全局收敛。
除了上面的线性递减权值策略,还有自适应权值策略,随机权重策略。详见参考资料[4];

参考资料

最后

生命不息,生活好难!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,319评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,801评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,567评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,156评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,019评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,090评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,500评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,192评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,474评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,566评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,338评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,212评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,572评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,890评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,169评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,478评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,661评论 2 335

推荐阅读更多精彩内容