粒子群算法的调参技巧及改进方法

C++源码实现



1 基本粒子群算法简单介绍


1.1 粒子群算法( Particle Swarm Optimization, PSO)是一种典型的群体智能算法。最早是由美国心理学家Eberhart和电气工程师Kennedy于1995年提出,是一种模拟鸟类群体觅食行为的仿生智能计算方法。鸟群在整个搜寻的过程中,通过相互传递各自的信息,让其他的鸟知道自己的位置,同时也将最优解的信息传递给整个鸟群,最终,整个鸟群都能聚集在食物源周围,即我们所说的找到了最优解,即问题收敛。每只鸟会实时记录下自己的历史最优位置、鸟群的全局最优位置,作为下一次更新位置和速度的依据。


1.2 优点:简单容易实现、参数少、易于改进、对初始位置的依耐性弱、时间复杂度底


1.3 标准PSO算法的流程:(本博客,附源码实现)


        步骤1: 随机初始化粒子群的位置和速度(种群规模N);


        步骤2: 计算每个粒子的适应度;


        步骤3: 对每个粒子,将其适应值与其经过的最好位置pbest作比较,如果当前值更好,更新pbest(历史最优);


        步骤4: 对每个粒子,将其适应值与其经过的最好位置gbest作比较,如果当前值更好,更新gbest(全局最优);


        步骤5: 调整粒子速度和位置;


        步骤6: 满足结束条件,结束;否则,转到第2)步。



2 调参与改进综述


        看了不少论文,目前学术界提高粒子群算法的性能主要有如下三种方法:


2.1 合理的设置基本参数: (本博客,附源码实现)


    (1)种群规模amout的设置:根据模型复杂度定义


    (2)惯性权重w,加速系数c1、c2的设置:w范围在0.7-0.9,c1=c2=(1-w)/2


    (3)最大速度系数V_scale:范围在0.05-0.15之间


    (4)退火思想(学习率渐渐减小):种群规模N、Vmax、w前期设置较大,后期渐渐变小,前期偏重全局搜索避免遗漏最优解,后期偏重局部搜索以提高收敛速度。


2.2 使用拓扑结构(本博客,附源码实现)


    全局拓扑:全连接(标准粒子群算法)   


    局部拓扑:环形拓扑、冯诺依曼、四簇结构     


    优缺点:


            全局拓扑结构速度快,但易早熟,陷入局部最优;


            局部拓扑结构收敛速度慢一点,全局搜索的能力强;


    通常情况下,冯诺依曼、四簇结构的综合性能比较好。


2.3 与其他智能优化算法联用(源码实现,见后续博客)


    1 粒子群算法与禁忌搜索联用:可以过早避免陷入局部 (仿真速度和优化结构与四簇结构相似);


    2 粒子群算法与PCA主成分分析联用:可以大大提高收敛速度(参数之间有较强相关性时使用有较好效果);


    3 粒子群与梯度下降联用:可以提高收敛速度;


    4 将基因算法的变异因子引入粒子群:在所有粒子陷入局部并停滞后,可以通过变异因子跳出局部继续仿真


    等等

3. C++源码文件

3.1 Pso_single类:包含单个粒子的基本信息和方法函数,粒子的位置、适应值、各权重和系数、速度位置的更新方法、适应值计算方法等。所在文.3件:SinglePso.cpp、SinglePso.h;


3.2 Pso类:包含多个Pso_single对象,组成粒子群。包括系数退火方法、gbest计算方法、粒子群初始化、更新等。所在文件:Pso.cpp、Pso.h;


3.3 Pso_Top类:继承自Pso类。实现了3种局部top结构(环形拓扑、冯诺依曼、四簇结构)。所在文件:top.cpp、top.h;


3.4 工具函数:适应值函数、随机数组生成函数、粒子群优劣度比较函数等。所在文件:funs.cpp、funs.h;


3.5 主函数:main.cpp


4. 源码

4.1 SinglePso.h

#ifndef SINGLEPSO_H_INCLUDED
#define SINGLEPSO_H_INCLUDED
/*
Pso_single:封装了单个粒子的类;
该类的数据成员,包括粒子的:
坐标维度:in_dims,坐标,适应值,位置上下限,速度上下限,惯性系数,
全局速度因子,局部速度因子,速度上下限,速度范围因子,局部最优解,全局最优解,
方法: 随机初始化、计算适应值、更新全局最优、更新局部最优
*/
class Pso_single
{
private:
    int in_dims; //坐标维度
    float *in_max, *in_min; //位置上下限
    float *v_max,*v_min; //速度上下限
    float w,c1,c2; //惯性系数,局部速度因子、全局速度因子
public:
    float *v_; //速度
    float fitness_; //粒子的适应值
    float *in_; //粒子的坐标
    float fitness_pbest; //粒子的历史最优适应值
    float *in_pbest;    //粒子的历史最优坐标
    float fitness_gbest; //粒子的全局最优适应值
    float *in_gbest; //粒子的全局最优坐标

    //Pso_single:构造函数
    Pso_single(int in_dims_,float *inmax, float *inmin, float *vmax, float *vmin,float w_,float c1_,float c2_);
    //init_:随机初始化粒子的速度和位置
    void init_();
    //get_fitness:计算当前坐标的适应值
    void get_fitness();
    //init_pbest:初始化历史最优
    void init_pbest();
    //updata_pbest:更新历史最优
    void updata_pbest();
    //get_gbest: 更新全局最优
    void get_gbest(float *in_gbest_,float fitness_gbest_);
    //updata_v::更新速度
    void updata_v();
    //updata_in:更新坐标
    void updata_in();
};

#endif // SINGLEPSO_H_INCLUDED

4.2 SinglePso.cpp


#include <iostream>
#include<algorithm>
#include"SinglePso.h"
#include"funs.hpp"

using namespace std;


Pso_single::Pso_single(int in_dims_,float *inmax, float *inmin, float *vmax, float *vmin,float w_,float c1_,float c2_)
        {
            in_dims = in_dims_; //坐标维度
            fitness_ = 0.0; //粒子的适应值
            in_ = new float [in_dims]; //粒子的坐标
            v_ = new float [in_dims];  //速度
            fitness_pbest = 0.0 ;  //粒子的历史最优适应值
            in_pbest = new float [in_dims]; //粒子的历史最优坐标
            fitness_gbest = 0.0;  //粒子的全局最优适应值
            in_gbest = new float [in_dims]; //粒子的全局最优坐标
            in_max = inmax;  //位置上限
             in_min = inmin;  //位置下限
            v_max = vmax;  //速度上限
            v_min = vmin;  //速度下限
            w = w_; //惯性系数,
            c1 = c1_; //历史速度因子
            c2 = c2_; //全局速度因子
        }

void Pso_single::init_()
        {   // 随机初始化坐标
            in_ = random_array(in_dims,in_max,in_min);
            // 随机初始化速度
            v_ = random_array(in_dims,v_max,v_min);
        }

void Pso_single::get_fitness()
        {
            //计算适应值
            fitness_ = fitness_fun(in_);
        }

void Pso_single::init_pbest()
        {
            //将坐标值和适应值,直接拷贝
            copy_(in_,in_pbest,in_dims);
            fitness_pbest = fitness_;
        }

void Pso_single::updata_pbest()
        {   //如果当前粒子的适应值大于历史最优值pbest,重新拷贝
            if (fitness_<=fitness_pbest)
            copy_(in_,in_pbest,in_dims);
            fitness_pbest = fitness_;
        }

void Pso_single::get_gbest(float *in_gbest_,float fitness_gbest_)
        {   //将传入的全局最优,赋值给当前粒子的全局最优
            //全局最优需要比较所有粒子的适应值,
            //所以先在外部对所有粒子进行比较。然后再传入。
            copy_(in_gbest_,in_gbest,in_dims);
            fitness_gbest = fitness_gbest_;
        }

void Pso_single::updata_v(){
            //根据如下公式更新速度
            //v=v*w + (pbestin-in)*c1 + (gbestin-in)*c2
            //速度不得超过上限、下限
            for(int i = 0;i<in_dims;i++){
                v_[i] = v_[i]*w + (in_pbest[i] - in_[i])*c1 + (in_gbest[i] - in_[i])*c2;
                if (v_[i]>v_max[i])
                    {v_[i] = v_max[i];}
                if (v_[i]<v_min[i])
                    {v_[i] = v_min[i];}
                }
            }

void Pso_single::updata_in(){
            //更新位置。位置不得超过上限、下限
            for(int i = 0;i<in_dims;i++){
                in_[i] = in_[i] + v_[i];
                if (in_[i]>in_max[i])
                    {in_[i] = in_max[i];}
                if (in_[i]<in_min[i])
                    {in_[i] = in_min[i];}
                }
}

4.3 Pso.h

#ifndef PSO_H_INCLUDED
#define PSO_H_INCLUDED
#include "SinglePso.h"
#include <vector>
using namespace std;
/*
Pso类:标准粒子群算法
成员:多个Single_pso,速度因子、惯性因子等
*/
class Pso
{
protected:
    int swarm_amount; //粒子群数量
    int in_dim;  //粒子坐标的维度
    float w,c1,c2;  //
    float* max_in;  //
    float* min_in;  //
    float* max_v;   //
    float* min_v;   //
    float* fitness_list; //
    float v_scale = 0.1; //速度范围因子。建议0.05<v_scale<0.2
    float w_col = 1.0;   // 惯性衰减因子,建议0.96<w_col<1.0
    float v_col = 1.0;   //速度衰减因子,建议0.96<v_col<1.0
    vector<Pso_single> vector_pso;  //存储所有粒子的容器

public:
    float* in_gbest_final;  //存放最终的最优坐标
    float fitness_gbest_final; //最优坐标对应的最优适应值
    //Pso:构造函数
    Pso(int swarm_amount_,int in_dim_,float w_,float* max_,float* min_,float v_scale_);
    //set_w_col:设置惯性衰减因子
    void set_w_col(float w_col);
    //set_v_col:设置速度衰减因子
    void set_v_col(float v_col);
    //gbest:计算全局最优gbest
    void gbest(int flag);
    //initialize:初始化每个粒子的坐标值、速度、适应值、局部最优、全局最优、
    void initialize();
    //update:更新坐标值、速度、适应值、局部最优、全局最优、
    void update();
    //gone:循环迭代。circle_表示迭代次数
    void gone(int circle_);
};


#endif // PSO_H_INCLUDED

4.4 Pso.cpp

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <time.h>
#include<algorithm>
#include "Pso.h"
#include"funs.hpp"
using namespace std;

//构造函数:初始化参数
Pso::Pso(int swarm_amount_,int in_dim_,float w_,float* max_,float* min_,float v_scale_)
{
    in_gbest_final = new float[in_dim];
    swarm_amount = swarm_amount_;
    fitness_list = new float[swarm_amount];
    in_dim = in_dim_;
    w = w_;
    c1 = (1-w)/2;
    c2 = (1-w)/2;
    min_in = new float[in_dim];
    max_in = new float[in_dim];
    min_v = new float[in_dim];
    max_v = new float[in_dim];
    max_in = max_;
    min_in = min_;
    v_scale = v_scale_;
    for(int i = 0; i<in_dim; i++)
    {
        max_v[i] = (max_[i]-min_[i])*v_scale;
        min_v[i] = -(max_[i]-min_[i])*v_scale;
    }
}

//设置惯性衰减系数
void Pso::set_w_col(float w_col_)
{
    w_col = w_col_;
}

//设置速度范围的衰减系数
void Pso::set_v_col(float v_col_)
{
    v_col = v_col_;
}

//更新粒子群的全局最优解gbest
void Pso::gbest(int init_flag)
{
    float* in_gbest_temp = new float[in_dim]; //存放每轮的最优粒子坐标
    float fitness_gbest_temp; //每一轮最优适应值
    get_min(swarm_amount,vector_pso,in_gbest_temp,&fitness_gbest_temp,in_dim);
    for(int i=0; i<swarm_amount; i++)
    {
        //如果是处于第一轮迭代,或者fitness_gbest_temp优于粒子的gbest
        //将粒子的gbest替换为fitness_gbest_temp和in_gbest_temp
        if (init_flag == 0 ||fitness_gbest_temp < vector_pso[i].fitness_gbest)
        {
            vector_pso[i].get_gbest(in_gbest_temp,fitness_gbest_temp);
        }
    }
}

//初始化粒子群的坐标、速度、历史最优、全局最优
void Pso::initialize()
{
    for(int i=0; i<swarm_amount; i++)
    {
        Pso_single single(in_dim,max_in,min_in,max_v,min_v,w,c1,c2);
        single.init_();
        single.get_fitness();
        single.init_pbest();
        vector_pso.push_back(single);
    }
    gbest(0);
}

//更新粒子群的速度、坐标、历史最优、全局最优
void Pso::update()
{
    if (w_col != 1.0)
    {
        w = w*w_col; //衰减w
        c1 = (1-w)/2; //增加c1
        c2 = (1-w)/2; //增加c2
    }
    if (v_col != 1.0)
    {
        v_scale = v_scale * v_col; //衰减v_scale
    }
    for(int i=0; i<swarm_amount; i++)
    {
        vector_pso[i].updata_v();
        vector_pso[i].updata_in();
        vector_pso[i].get_fitness();
        vector_pso[i].updata_pbest();
    }
    gbest(1);
}

//初始化,并且反复进行circle_轮的迭代
void Pso::gone(int circle_)
{
    this->initialize();
    for (int i = 0; i<circle_; i++)
    {
        if (i%5 == 0)
        {
            cout<<"第"<<i<<"次迭代"<<endl;
        }
        this->update();
    }
    //get_final_gbest:计算最终的最优粒子
    get_final_gbest(swarm_amount,vector_pso,in_gbest_final,&fitness_gbest_final,in_dim);
}

4.5 top.h

#ifndef TOP_H_INCLUDED
#define TOP_H_INCLUDED
#include <iostream>
#include <vector>
#include "Pso.h"
using namespace std;

/*
Pso_Top :
为Pso的子类,实现局部top结构的功能。
*/

class Pso_Top : public Pso
{
private:
    int top_flag = 0; //拓扑值标签
public:
    //Pso_Top: 构造函数
    Pso_Top(int swarm_amount_,int in_dim_,float w_,float* max_,float* min_,float v_scale_):Pso(swarm_amount_,in_dim_,w_,max_,min_,v_scale_)
    {
    }
    //set_topFlag: 设置top类型
    void set_topFlag(int topFlag);
    //gbest:生成全局最优
    void gbest(int init_flag);
};
#endif // TOP_H_INCLUDED

4.6 top.cpp

#include <iostream>
//#include <stdlib.h>
#include <vector>
#include <cmath>
#include <time.h>
//#include<algorithm>
#include "top.h"
#include"funs.hpp"

using namespace std;


void Pso_Top::set_topFlag(int topFlag)
{
    top_flag = topFlag;
}

/*top_index_0:环形top结构中,每个粒子共享其前后粒子的信息
top_index_1:冯诺依曼top结构中,每个粒子共享其前后粒子的信息
top_index_2:四簇结构,将所有粒子等分为4簇,簇内粒子共享信息;部分粒子与其他簇共享信息*/


//环形top结构的索引获取
void top_index_0(int i_ ,int size_v,int* index_v)
{
    index_v[0] = (i_+size_v-1)%size_v;
    index_v[1] = i_;
    index_v[2] = (i_+1)%size_v;
}


//get_row_col:top_index_1的内置函数。
//功能:合理的分配行和列,行和列的值尽量接近些
int get_row_col(int num_)
{
    int row = 0;
    for(int i=1; i<=sqrt(num_); i++)
    {
        if (num_%i==0)
        {
            row = i;
        }
    }
    return row;
}

//get_index:top_index_1的内置函数。
//功能:获取目标粒子前、后、左、右的索引。
//(i,j) = (-1,0)    前
//(i,j) = (1,0)     后
//(i,j) = (0,-1)    左
//(i,j) = (0,1)     右
int get_index(int row,int col,int row_curr,int col_curr,int i,int j)
{
    return ((row_curr+i+row)%row)*col + ((col_curr+j+col)%col);
}

//冯诺依曼结构的索引获取
void top_index_1(int i_ ,int size_v,int* index_v)
{
    int row,col,row_curr,col_curr;
    row = get_row_col(size_v);
    col = size_v/row;
    row_curr = i_/col;
    col_curr = i_%col;
    index_v[0] = get_index(row,col,row_curr,col_curr,-1,0);//上
    index_v[1] = get_index(row,col,row_curr,col_curr,1,0);//上
    index_v[2] = i_;//中间
    index_v[3] = get_index(row,col,row_curr,col_curr,0,-1);//左
    index_v[4] = get_index(row,col,row_curr,col_curr,0,11);;//右
}

//四簇结构:将所有粒子等分为4簇,簇内粒子共享信息;部分粒子与其他簇共享信息
int top_index_2(int group_id ,int swarm_id)
{
    /*
    注:下文以group-i-k表示第i簇的第k号粒子;例如group-1-0,表示第1簇的第0号粒子;
    group_index_0数组表示:group-0中的第0、1、2个粒子分别与group-1-0,group-2-1,
    group-3-2相连接;group_index_1,group_index_2,group_index_3以此类推。
    */
    int  group_index_0[3][2] = {{1,0},{2,1},{3,2}};
    int  group_index_1[3][2] = {{0,0},{3,1},{2,0}};
    int  group_index_2[3][2] = {{1,2},{0,1},{3,0}};
    int  group_index_3[3][2] = {{2,2},{1,1},{0,2}};
    switch(group_id)
    {
    case 0:
        return group_index_0[swarm_id][0]*4 + group_index_0[swarm_id][1];
        break;
    case 1:
        return group_index_1[swarm_id][0]*4 + group_index_0[swarm_id][1];
        break;
    case 2:
        return group_index_2[swarm_id][0]*4 + group_index_0[swarm_id][1];
        break;
    case 3:
        return group_index_3[swarm_id][0]*4 + group_index_0[swarm_id][1];
        break;
    };
}


void Pso_Top::gbest(int init_flag)
{
    float* in_gbest_temp = new float[in_dim];
    float fitness_gbest_temp;
    int* index_;
    if (top_flag < 2)
    {
        // top_flag = 0:环形结构
        // top_flag = 1:冯诺依曼结构
        for(int i=0; i<swarm_amount; i++)
        {
            //for循环:用于计算每个粒子的在当前top模型下的全局最优解gbest
            switch(top_flag)
            {
            case 0:
                index_ = new int[3]; //每个粒子以及与其共享信息的粒子的索引
                top_index_0(i ,swarm_amount,index_); //索引值复杂
                break;
            case 1:
                index_ = new int[5];//每个粒子以及与其共享信息的粒子的索引
                top_index_1(i ,swarm_amount,index_);//索引值复杂
                break;
            }
            vector<Pso_single> vector_local; //定义容器,用于存储与当前粒子共享信息的粒子
            for(int j = 0; j<sizeof(index_); j++)
            {
                vector_local[j] = vector_pso[index_[j]];//逐个存储共享信息的粒子
            }
            //获取最优适应值的粒子
            get_min(vector_local.size(),vector_local,in_gbest_temp,&fitness_gbest_temp,in_dim);
            //更新粒子的gbest
            // init_flag == 0,代表是第一轮迭代
            if (init_flag == 0||fitness_gbest_temp<vector_pso[i].fitness_gbest)
            {
                vector_pso[i].get_gbest(in_gbest_temp,fitness_gbest_temp);
            }
        }
    }
    else
    {
        //top_flag = 2:四簇结构
        //下面的for循环:循环4次,分别计算每一个簇中的粒子的gbest
        for(int i=0; i<4; i++)
        {
            int sub_amout = int(swarm_amount/4);//sub_amout:每个子簇的粒子数量
            vector<Pso_single> vector_local; //定义容器,用于存储每个簇粒子群
            for(int j = 0; j<sub_amout; j++)
            {
                vector_local[j] = vector_pso[index_[i*sub_amout+j]];//存储当前簇内的所有粒子
            }

            //get_min:计算当前子簇内的gbest
            get_min(vector_local.size(),vector_local,in_gbest_temp,&fitness_gbest_temp,in_dim);
            for(int j=0; j<sub_amout; j++)
            {
                //给当前簇的所有粒子的gbest赋值
                if (init_flag == 0||fitness_gbest_temp<vector_pso[i].fitness_gbest)
                {
                    vector_pso[i*sub_amout+j].fitness_gbest = fitness_gbest_temp;
                    vector_pso[i*sub_amout+j].in_gbest = in_gbest_temp;
                }
                if(j<3)
                {
                    //如果j<3:前三个粒子,还要再比较一下其和外簇相连粒子的gbest
                    int index_ = top_index_2(i ,j);
                    if (fitness_gbest_temp<vector_pso[i].fitness_gbest)
                    {
                        vector_pso[i*sub_amout+j].fitness_gbest = vector_pso[index_].fitness_;
                        vector_pso[i*sub_amout+j].in_gbest = vector_pso[index_].in_;
                    }
                }
            }
        }
    }
}

4.7 funs.h

#ifndef FUNS_HPP_INCLUDED
#define FUNS_HPP_INCLUDED
#include <vector>
#include "SinglePso.h"

using namespace std;

//random_single:生成0-1的浮点数
float random_single();

//random_array:随机生成dims维度的数组
float* random_array(int dims,float *max_, float *min_);

//fitness_fun:生成适应值的函数
float fitness_fun(float* in_);

//copy_:数组 深拷贝
void copy_(float src[],float dst[],int dims);

//get_max:通过计算,得到适应值最小的粒子
void get_min(int mount,vector<Pso_single> temp_pso,float* max_in,float* max_fit,int in_dims_);

//get_max:通过计算,得到适应值最小的粒子
void get_final_gbest(int mount,vector<Pso_single> temp_pso,float* final_in,float* final_fit,int in_dims_);

#endif // FUNS_HPP_INCLUDED

4.8 funs.cpp

#include <iostream>
#include <stdlib.h>
#include <time.h>
#include <vector>
#include <math.h>
#include "SinglePso.h"
#include "funs.hpp"

#define PI 3.1415926

using namespace std;

//生成0——1之间的随机数
float random_single()
{
    return ((float)(rand()%1000))/1000.0;
}

//生成维度为dims的随机数组
float* random_array(int dims,float *max_,float *min_)
{
    float *temp = new float[dims];
    for(int i=0; i<dims; i++)

    {
        float random_ = random_single();
        temp[i] = (max_[i] - min_[i])*random_ + min_[i];
    }
    return temp;
}

//fitness_fun:适应度函数使用 “Rastrigin's 函数”
float fitness_fun(float* inin)
{
    float x1 = inin[0];
    float x2 = inin[1];
    float rastrigin_ = 20 + pow(x1,2) + pow(x2,2) - 10*(cos(2*PI*x1) + cos(2*PI*x2));
    return rastrigin_;
}

//数组复制
void copy_(float src[],float dst[],int dims)
{
    for(int i = 0; i<dims; i++)
    {
        dst[i] = src[i];
    }
}

//通过计算,得到vector中的最小适应值和对应的坐标
void get_min(int mount,vector<Pso_single> temp_pso,float* min_in,float* min_fit,int in_dims_)
{
    for(int i=0; i<mount; i++)
    {
        if(i == 0 || temp_pso[i].fitness_ < *min_fit)
        {
            *min_fit = temp_pso[i].fitness_;
            copy_(temp_pso[i].in_,min_in,in_dims_);

        }
    }
}

//通过计算,得到最终的最优解
void get_final_gbest(int mount,vector<Pso_single> temp_pso,float* final_in,float* final_fit,int in_dims_)
{
    for(int i=0; i<mount; i++)
    {
        if(i == 0 || temp_pso[i].fitness_ < *final_fit)
        {
            *final_fit = temp_pso[i].fitness_gbest;
            copy_(temp_pso[i].in_,final_in,in_dims_);
        }
    }
}

4.9 main.cpp

#include <iostream>
#include <stdlib.h>
#include <vector>
#include <time.h>
#include <math.h>
#include "SinglePso.h"
#include "Pso.h"
#include "funs.hpp"
#include "top.h"
using namespace std;

int main()
{
    srand(time(0)); //随机种子
    int amout_ = 400; //粒子数
    float w_ = 0.8; // 惯性权重
    // 通常情况下,全局加速因子 c1、历史加速因子c2 ,等于 (1-w)/2
    float v_scale_ = 0.1; //速度比例因子。最大速度、最小速度的范围
    int circle_ = 80 ;//迭代次数
    //本适应度函数是两维。网友可以根据自身需要更改适应度函数、
    int in_dims_ = 2; //输入坐标的维度为2
    float max_in[] = {5.0,5.0}; //输入参数的上限
    float min_in[] = {-5.0,-5.0};  //输入参数的下限
    Pso_Top pso_(amout_,2,0.8,max_in,min_in,v_scale_); //初始化粒子群对象,局部top结构的粒子群对象
    //使用冯诺依曼top结构,粒子数应为偶数且大于12
    //使用四簇拓扑结构,粒子数应为4的倍数且大于12
    pso_.set_topFlag(2); //设置top类型{0:环形拓扑结构;1:冯诺依曼拓扑结构; 2:四簇拓扑结构}
    /*
        上述代码为 局部top结构的粒子群算法的初始方式。
        标准粒子群算法的初始化代码如下:
        Pso pso_(amout_,2,0.8,max_in,min_in,v_scale_);
    */
    pso_.set_w_col(0.99); //设置惯性衰减系数。惯性系数每次迭代乘以0.99。c1和c2相应增加
    pso_.set_v_col(0.99); //设置速度衰减因子。速度的上限和下限。随着迭代衰减
    pso_.gone(circle_); //执行
    cout<<"*********迭代完成********"<<endl;
    cout<<"*****final_gbest   fitness:"<<pso_.fitness_gbest_final<<endl;
    cout<<"*****final_gbest   in_:("<<pso_.in_gbest_final[0]<<","<<pso_.in_gbest_final[1]<<")"<<endl;
    cout<<"*********迭代完成********"<<endl;
}