粒子群算法(Particle Swarm Optimization)

粒子群算法(Particle Swarm Optimization)


  粒子群算法是一种启发式优化算法,1995年由Eberhart和kennedy提出。该算法起源于鸟群捕食的启发,进而利用群体智能在解空间中不断搜索取得最优解。


1 基本PSO算法介绍

  在粒子群算法中,每个解空间中的点被抽想成为一个d维的粒子,且每一个粒子对应着由目标函数决定的适应度(fitness)。同时每一个粒子对应着解空间中的位置以及各自拥有一个速度,它们在解空间中不断搜索问题的最优解的同时收到各自变化以及当前全局最优解的影响。粒子的速度以及位置更新公式如下:

vt+1=wvt+c1rand()(pbesttpresentt)+c2rand()(gbesttpresentt)
presentt+1=presentt+vt+1

  其中参数 w 表示每次更新后继承上一时刻的速度部分, c1c2 分别表示粒子收到自己以及全局最优的影响程度,rand()为0~1之间的随机数。


2 优缺点分析

  • 规则设置相较于遗传算法更为简单,没有交叉、变异操作
  • 实现容易、精度高、收敛快
  • 比较容易实现并行
  • 种群为随机初始化,最终迭代结果受其影响较大
  • 参数设置对于最终结果也有较大影响

3 一些简单的优化

  做过一些简单是实验以及一些比赛,发现要用好一些启发式算法,包括模拟退火,粒子群算法,遗传算法还是很不容易的,经常发现到最后还不如xjbs……总结经验如下:

  • 通常情况下,可以通过贪婪算法寻找到一个较优解,然后使用PSO算法寻找更优解可以节省时间;
  • 在寻找最优解的过程中,由于前期目标函数下降(或上升)较快,所以可以通过时间的不断增加也同时增加粒子的个数,因为粒子的个数越多,在后期陷入局部最优解时也更容易跳出。

4 c语言简单实现

/*
寻找函数y = sum(Xi - 0.5)^2的最优值,维输1000 
*/
#include
#include
#include

#define num_particle 100  //粒子个数 
#define dim 1000          //粒子维数
#define low 0             //搜索域范围,即每个维度的最大最小可能值 
#define high 1 
#define num_iter 5000     //迭代次数
#define c1 2              //参数初始化 
#define c2 2
#define w 0.5
#define v_max 0.03


double particle[num_particle][dim];              //粒子群集合 
double particle_local_best[num_particle][dim];   //每个粒子的局部最优位置 
double particle_local_fit[num_particle];         //每个粒子的局部最优适应度 
double particle_global_best[dim];                //粒子群的全局最优位置 
double particle_global_fit;                      //粒子群的全局最优适应度
double particle_v[num_particle][dim];            //每个粒子的当前速度 
double particle_fit[num_particle];               //每个粒子的当前适应度


//定义适应度函数(cost)为向量的长度平方 
double fitness(double a[]){
    int i;
    double sum = 0.0;
    for(i = 0; i < dim; i++){
        sum += (a[i] - 0.5) * (a[i] - 0.5); 
    }
    return sum;
} 

//初始化粒子群
void initial(){
    int i, j;
    for(i = 0; i < num_particle; i++){
        for(j = 0; j < dim; j++){
            particle[i][j] = low + (high - low)*1.0*rand()/RAND_MAX;  //初始化粒子群位置 
            particle_local_best[i][j] = particle[i][j];               //初始局部最优即为初始位置 
            particle_v[i][j] = 0.2*rand()/RAND_MAX;                   //初始化粒子速度 
        }
    }

    for(i = 0; i < num_particle; i++){
        particle_fit[i] = fitness(particle[i]);   //计算每个粒子的初始适应度 
        particle_local_fit[i] = particle_fit[i];  //每个粒子的初始局部最优适应度即为初始位置的适应度 
    } 

    particle_global_fit = particle_local_fit[0];  //初始化全局最优适应度 
    j = 0;
    for(i = 0; i < num_particle; i++){            //寻找全局最优位置 
        if(particle_local_fit[i] < particle_global_fit){
            particle_global_fit = particle_local_fit[i];
            j = i;
        }
    }

    for(i = 0; i < dim; i++){                     //更新全局最优位置 
        particle_global_best[i] = particle_local_best[j][i];
    }
} 


//迭代更新粒子群位置 
void renew_particle(){
    int i, j;
    for(i = 0; i < num_particle; i++){ 
        for(j = 0; j < dim; j++){
            particle[i][j] += particle_v[i][j];
            if(particle[i][j] > high){            //位置不能超过设定的最大最小值 
                particle[i][j] = high;
            }
            if(particle[i][j] < low){
                particle[i][j] =low;
            }
        }
    }
} 


//迭代后更新粒子群速度
void renew_v(){
    int i, j;
    for(i = 0; i < num_particle; i++){
        particle_fit[i] = fitness(particle[i]);                 //计算每个粒子的适应度 
        if(particle_fit[i] < particle_local_fit[i]){            //更新个体局部最优适应度 
            particle_local_fit[i] = particle_fit[i];
            for(j = 0; j < dim; j++){                           // 更新个体局部最优位置 
                particle_local_best[i][j] = particle[i][j];
            }
        }
    }

    j = -1; 
    for(i = 0; i < num_particle; i++){                          //更新全局最优适应度 
        if(particle_local_fit[i] < particle_global_fit){
            particle_global_fit = particle_local_fit[i];
            j = i;
        }
    }

    if(j != -1){                                                //若该次迭代产生全局最优,更新全局最优位置 
        for(i = 0; i < dim; i++){
            particle_global_best[i] = particle_local_best[j][i];
        }
    } 

    for(i = 0; i < num_particle; i++){
        for(j = 0; j < dim; j++){
            particle_v[i][j] = w * particle_v[i][j] + c1 * 1.0 * rand() / RAND_MAX * (particle_local_best[i][j] - particle[i][j])+ c2 * 1.0 * rand() / RAND_MAX * (particle_global_best[j] - particle[i][j]);
            if(particle_v[i][j] > v_max){
                particle_v[i][j] = v_max;
            }
            if(particle_v[i][j] < -v_max){
                particle_v[i][j] = -v_max;
            }
        }
    } 

} 


int main(){
    int i = 0;
    initial();
    srand((unsigned)time(NULL));
    while(i < num_iter){              //进行1000次迭代 
        renew_particle();
        renew_v();
        i++;
    }
    printf("粒子群个数:%d\n", num_particle);      
    printf("每个粒子群维度:%d\n", dim); 
    printf("迭代次数:%d\n", num_iter);
    //printf("最优位置:%f\n", particle_global_best);
    printf("最优适应度:%f\n", particle_global_fit);
    return 0;
}

5 改进的粒子群算法整理

  1. APSO活跃目标点粒子群算法:在标准PSO速度更新公式中引入第三个目标点,成为活跃目标点,从而构成新的基于三个目标点的速度更新机制的粒子速度更新公式;APSO的优点是避免了PSO算法的过早收敛问题,并兼具复合型法射线搜索的能力,缺点是增加了一定的额外计算开销;
  2. DPSO探测粒子群优化算法:选定少数粒子,令其单独进行有别于普通粒子折线搜索路径,而是利用螺旋折线搜索路径,该粒子称为探测粒子。整体上,该探测粒子与种群中其他普通粒子联合进行更高效率的搜索。DPSO的优点是避免PSO早熟收敛的基础上进一步提高了PSO的收敛速度和收敛精度;缺点与APSO类似增加了一定的额外计算开销;

你可能感兴趣的:(启发式优化算法)