zoukankan      html  css  js  c++  java
  • 粒子群算法(1)----粒子群简要

     

     

    一、历史粒子群算法

       从复杂适应系统衍生PSO算法(Complex Adaptive System,CAS)。CAS理论于1994年正式提出,CAS中的成员称为主体。比方研究鸟群系统,每一个鸟在这个系统中就称为主体。主体有适应性,它能够与环境及其它的主体进行交流,而且依据交流的过程学习积累经验改变自身结构与行为。

    整个系统的演变或进化包括:新层次的产生(小鸟的出生);分化和多样性的出现(鸟群中的鸟分成很多小的群);新的主题的出现(鸟寻找食物过程中。不断发现新的食物)。

       所以CAS系统中的主体具有4个基本特点(这些特点是粒子群算法发展变化的依据):

      首先,主体是主动的、活动的。

      主体与环境及其它主体是相互影响、相互作用的。这样的影响是系统发展变化的主要动力。

      环境的影响是宏观的,主体之间的影响是微观的,宏观与微观要有机结合。

      最后,整个系统可能还要受一些随机因素的影响。

      粒子群算法就是对一个CAS系统---鸟群社会系统的研究得出的。

      粒子群算法( Particle Swarm Optimization, PSO)最早是由EberhartKennedy1995年提出。它的基本概念源于对鸟群觅食行为的研究。设想这样一个场景:一群鸟在随机搜寻食物,在这个区域里仅仅有一块食物,全部的鸟都不知道食物在哪里,可是它们知道当前的位置离食物还有多远。那么找到食物的最优策略是什么呢?最简单有效的就是搜寻眼下离食物近期的鸟的周围区域。

       

       PSO算法就从这样的生物种群行为特性中得到启示并用于求解优化问题。

    PSO中,每一个优化问题的潜在解都能够想象成d维搜索空间上的一个点,我们称之为粒子Particle),全部的粒子都有一个被目标函数决定的适应值(Fitness Value ),每一个粒子另一个速度决定他们飞翔的方向和距离,然后粒子们就追随当前的最优粒子在解空间中搜索。Reynolds对鸟群飞行的研究发现。鸟仅仅是追踪它有限数量的邻居但终于的总体结果是整个鸟群好像在一个中心的控制之下.即复杂的全局行为是由简单规则的相互作用引起的。

    二、粒子群算法的详细表述

       上面罗嗦了半天。那些都是科研工作者写论文的语气,只是,PSO的历史就像上面说的那样。

    以下通俗的解释PSO算法。

       PSO算法就是模拟一群鸟寻找食物的过程,每一个鸟就是PSO中的粒子。也就是我们须要求解问题的可能解。这些鸟在寻找食物的过程中,不停改变自己在空中飞行的位置与速度。大家也能够观察一下,鸟群在寻找食物的过程中,開始鸟群比較分散,逐渐这些鸟就会聚成一群。这个群忽高忽低、忽左忽右。直到最后找到食物。这个过程我们转化为一个数学问题。

    寻找函数  y=1-cos(3*x)*exp(-x)的在[0,4]最大值。

    该函数的图形例如以下:

      当x=0.9350-0.9450,达到最大值y=1.3706

    为了得到该函数的最大值,我们在[04]之间随机的洒一些点,为了演示,我们放置两个点,而且计算这两个点的函数值。同一时候给这两个点设置在[04]之间的一个速度。

    以下这些点就会依照一定的公式更改自己的位置,到达新位置后。再计算这两个点的值,然后再依照一定的公式更新自己的位置。直到最后在y=1.3706这个点停止自己的更新。这个过程与粒子群算法作为对比例如以下:

      这两个点就是粒子群算法中的粒子。

      该函数的最大值就是鸟群中的食物 

      计算两个点函数值就是粒子群算法中的适应值,计算用的函数就是粒子群算法中的适应度函数。

      更新自己位置的一定公式就是粒子群算法中的位置速度更新公式。

      以下演示一下这个算法执行一次的大概过程:

      第一次初始化

    第一次更新位置

      第二次更新位置

      第21次更新

      最后的结果(30次迭代)

      最后全部的点都集中在最大值的地方。

      呵呵,如今粒子群算法的大概思想就讲到这里。下节介绍标准的粒子群算法。

    粒子群算法(2)----标准的粒子群算法

    在上一节的叙述中,唯一没有给大家介绍的就是函数的这些随机的点(粒子)是怎样运动的,仅仅是说依照一定的公式更新。

    这个公式就是粒子群算法中的位置速度更新公式。

    以下就介绍这个公式是什么。在上一节中我们求取函数y=1-cos(3*x)*exp(-x)的在[0,4]最大值。并在[0,4]之间放置了两个随机的点。这些点的坐标如果为x1=1.5。 x2=2.5;这里的点是一个标量,可是我们常常遇到的问题可能是更一般的情况--x为一个矢量的情况。比方二维的情况 z=2*x1+3*x22的情况。这个时候我们的每一个粒子为二维,记粒子P1(x11,x12),P2=(x21,x22),P3=(x31,x32)......Pn=(xn1,xn2)。这里n为粒子群群体的规模,也就是这个群中粒子的个数,每一个粒子的维数为2

    更一般的是粒子的维数为q,这样在这个种群中有n个粒子,每一个粒子为维。

       由n个粒子组成的群体对Q维(就是每一个粒子的维数)空间进行搜索。

    每一个粒子表示为:xi=(xi1,xi2,xi3,...,xiQ),每一个粒子相应的速度能够表示为vi=(vi1,vi2,vi3,....,viQ)。每一个粒子在搜索时要考虑两个因素:

      1。自己搜索到的历史最优值 ppi=(pi1,pi2,....,piQ)i=1,2,3,....,n

      2。全部粒子搜索到的最优值pgpg=(pg1,pg2,....,pgQ)。注意这里的pg仅仅有一个。

      以下给出粒子群算法的位置速度更新公式:

       这里有几个重要的參数须要大家记忆。由于在以后的解说中将会常常常使用到:

      它们是:

    是保持原来速度的系数,所以叫做惯性权重。

    是粒子跟踪自己历史最优值的权重系数,它表示粒子自身的认识。所以叫认知

    通常设置为2

    是粒子跟踪群体最优值的权重系数。它表示粒子对整个群体知识的认识,所以叫做社会知识,常常叫做社会

    通常设置为2

    [0,1]区间内均匀分布的随机数。

    是对位置更新的时候。在速度前面加的一个系数,这个系数我们叫做约束因子。

    通常设置为1

       这样一个标准的粒子群算法就结束了。

      以下对整个主要的粒子群的过程给一个简单的图形表示:

      推断终止条件可是设置适应值到达一定的数值或者循环一定的次数。

       注意:这里的粒子是同一时候跟踪自己的历史最优值与全局(群体)最优值来改变自己的位置预速度的,所以又叫做全局版本号的标准粒子群优化算法。

    粒子群算法(3)----标准的粒子群算法(局部版本号)

     在全局版的标准粒子群算法中,每一个粒子的速度的更新是依据两个因素来变化的,这两个因素是:1. 粒子自己历史最优值pi2.  粒子群体的全局最优值pg如果改变粒子速度更新公式,让每一个粒子的速度的更新依据以下两个因素更新,A. 粒子自己历史最优值piB. 粒子邻域内粒子的最优值pnk

    其余保持跟全局版的标准粒子群算法一样。这个算法就变为局部版的粒子群算法。

       一般一个粒子的邻域随着迭代次数的添加而逐渐添加,開始第一次迭代,它的邻域为0,随着迭代次数邻域线性变大,最后邻域扩展到整个粒子群,这时就变成全局版本号的粒子群算法了。

    经过实践证明:全局版本号的粒子群算法收敛速度快。可是easy陷入局部最优。局部版本号的粒子群算法收敛速度慢,可是非常难陷入局部最优。如今的粒子群算法大都在收敛速度与摆脱局部最优这两个方面下功夫。事实上这两个方面是矛盾的。看怎样更好的折中了。

       依据取邻域的方式的不同,局部版本号的粒子群算法有非常多不同的实现方法。

      第一种方法:依照粒子的编号取粒子的邻域。取法有四种:1。环形取法 2。随机环形取法 3,轮形取法 4,随机轮形取法。

       1  环形随机环形

       轮形 4随机轮形

      由于后面有以环形取法实现的算法,对环形取法在这里做一点点说明:以粒子1为例。当邻域是0的时候,邻域是它本身,当邻域是1时。邻域为28;当邻域是2时,邻域是2378......。以此类推,一直到邻域为4,这个时候,邻域扩展到整个样例群体。

    据文献介绍(国外的文献)。採用轮形拓扑结构,PSO的效果非常好

      另外一种方法:依照粒子的欧式距离取粒子的邻域

        在第一种方法中。依照粒子的编号来得到粒子的邻域,可是这些粒子事实上可能在实际位置上并不相邻。于是Suganthan提出基于空间距离的划分方案,在迭代中计算每一个粒子与群中其它粒子的距离。记录不论什么2个粒子间的的最大距离为dm。对每一粒子依照||xa-xb||/dm计算一个比值。

    当中||xa-xb||是当前粒子ab的距离。而选择阈值frac依据迭代次数而变化。当另一粒子b满足||xa-xb||/dm<frac时,觉得b成为当前粒子的邻域。

       这样的办法经过实验。取得较好的应用效果。可是由于要计算全部粒子之间的距离,计算量大。且须要非常大的存储空间,所以。该方法一般不常常使用。

    粒子群算法(4)----粒子群算法分类

     粒子群算法主要分为4个大的分支:

      (1)标准粒子群算法的变形

       在这个分支中。主要是对标准粒子群算法的惯性因子、收敛因子(约束因子)、认知部分的c1社会部分的c2进行变化与调节。希望获得好的效果。

        惯性因子的原始版本号是保持不变的。后来有人提出随着算法迭代的进行,惯性因子须要逐渐减小的思想。算法開始阶段。大的惯性因子能够是算法不easy陷入局部最优。到算法的后期,小的惯性因子能够使收敛速度加快。使收敛更加平稳,不至于出现振荡现象。

    经过本人測试,动态的减小惯性因子w,的确能够使算法更加稳定,效果比較好。可是递减惯性因子採用什么样的方法呢?人们首先想到的是线型递减,这样的策略的确非常好。可是是不是最优的呢?于是有人对递减的策略作了研究。研究结果指出:线型函数的递减优于凸函数的递减策略,可是凹函数的递减策略又优于线型的递减,经过本人測试,实验结果基本符合这个结论。可是效果不是非常明显。

       对于收敛因子,经过证明如果收敛因子取0.729,能够确保算法的收敛,可是不能保证算法收敛到全局最优,经过本人測试,取收敛因子为0.729效果较好。

    对于社会与认知的系数c2,c1也有人提出:c1先大后小,而c2先小后大的思想,由于在算法执行初期,每一个鸟要有大的自己的认知部分而又比較小的社会部分,这个与我们自己一群人找东西的情形比較接近。由于在我们找东西的初期。我们基本依靠自己的知识取寻找。而后来。我们积累的经验越来越丰富,于是大家開始逐渐达成共识(社会知识)。这样我们就開始依靠社会知识来寻找东西了。

       2007年希腊的两位学者提出将收敛速度比較快的全局版本号的粒子群算法与不easy陷入局部最优的局部版本号的粒子群算法相结合的办法,利用的公式是

    vn*v(全局版本号)+(1n*v(局部版本号)       速度更新公式,v代表速度

       wk1)=w(k)v                     位置更新公式

      该算法在文献中讨论了系数n取各种不同情况的情况,而且执行来了20000次来分析各种系数的结果。

      (2)粒子群算法的混合

       这个分支主要是将粒子群算法与各种算法相混合,有人将它与模拟退火算法相混合。有些人将它与单纯形方法相混合。可是最多的是将它与遗传算法的混合。依据遗传算法的三种不同算子能够生成3中不同的混合算法。

        粒子群算法与选择算子的结合,这里相混合的思想是:在原来的粒子群算法中。我们选择粒子群群体的最优值作为pg。可是相结合的版本号是依据全部粒子的适应度的大小给每一个粒子赋予一个被选中的概率,然后依据概率对这些粒子进行选择,被选中的粒子作为pg,其它的情况都不变。这样的算法能够在算法执行过程中保持粒子群的多样性。可是致命的缺点是收敛速度缓慢。

       粒子群算法与杂交算子的结合,结合的思想与遗传算法的基本一样,在算法执行过程中依据适应度的大小。粒子之间能够两两杂交,比方用一个非常easy的公式

       w(新)=n×w1+(1n×w2

      w1w2就是这个新粒子的父辈粒子。

    这样的算法能够在算法的执行过程中引入新的粒子,可是算法一旦陷入局部最优。那么粒子群算法将非常难摆脱局部最优。

       粒子群算法与变异算子的结合。结合的思想:測试全部粒子与当前最优的距离,当距离小于一定的数值的时候,能够拿出全部粒子的一个百分比(如10%)的粒子进行随机初始化。让这些粒子又一次寻找最优值。

      (3)二进制粒子群算法

    最初的PSO是从解决连续优化问题发展起来的.Eberhart等又提出了PSO的离散二进制版.用来解决project实际中的组合优化问题。他们在提出的模型中将粒子的每一维及粒子本身的历史最优、全局最优限制为10,而速度不作这样的限制。用速度更新位置时,设定一个阈值,当速度高于该阈值时。粒子的位置取1,否则取0

    二进制PSO与遗传算法在形式上非常类似,但实验结果显示,在大多数測试函数中。二进制PSO比遗传算法速度快,尤其在问题的维数添加时

      (4)协同粒子群算法

       协同PSO,该方法将粒子的D维分到D个粒子群中。每一个粒子群优化一维向量,评价适应度时将这些分量合并为一个完整的向量。比如第i个粒子群,除第i个分量外。其它D-1个分量都设为最优值,不断用第i个粒子群中的粒子替换第i个分量。直到得到第i维的最优值,其它维同样。为将有联系的分量划分在一个群,可将D维向量分配到m个粒子群优化,则前D mod m个粒子群的维数是D/m的向上取整。

    m(D mod m)个粒子群的维数是D/m的向下取整。协同PSO在某些问题上有更快的收敛速度。但该算法easy被欺骗。

       主要的粒子群算法的分支就着4个。大部分的粒子群算法都环绕着这4个分支在变化。当中粒子群算法的变形居多。从根本上来说。差点儿没有什么新的思想的提出。

    粒子群算法(5)-----标准粒子群算法的实现

     标准粒子群算法的实现思想基本依照粒子群算法(2)----标准的粒子群算法的讲述实现。主要分为3个函数。第一个函数为粒子群初始化函数

      InitSwarm(SwarmSize......AdaptFunc)其主要作用是初始化粒子群的粒子,并设定粒子的速度、位置在一定的范围内。本函数所採用的数据结构例如以下所看到的:

      表ParSwarm记录的是粒子的位置、速度与当前的适应度值,我们用W来表示位置。用V来代表速度,用F来代表当前的适应度值。在这里我们如果粒子个数为N,每一个粒子的维数为D

    W1,1

    W1,2

    ...

    W1,D

    V1,1

    V1,2

    ...

    V1,D-1

    V1,D

    F1

    1个粒子

    W2,1

    W2,2

    ...

    W2,D

    V2,1

    V2,2

    ...

    V2,D-1

    V2,D

    F2

    2个粒子

    ...

    ...

    ...

    ...

    ...

    ...

    ...

    ...

    ...

    ...

    .......

    WN-1,1

    WN-1,2

    ...

    WN-1,D-1

    VN-1,1

    VN-1,2

    ...

    VN-1,D-1

    VN-1,D

    FN-1

    N-1个粒子

    WN,1

    WN,2

    ...

    WN,D

    VN,1

    VN,2

    ...

    VN,D-1

    VN,D

    FN

    N个粒子

       表OptSwarm记录每一个粒子的历史最优解(粒子历史最好的适应度)以及全部粒子搜索到的全局最优解。

    Wg代表全局最优解。W.,1代表每一个粒子的历史最优解。粒子群初始化阶段表OptSwarm的前N行与表ParSwarm中的同样,而Wg的值为表ParSwarm中适应度值的最大值相应的行。

    Wj,1

    Wj,2

    ...

    Wj,D-1

    Wj,D

    1个粒子的历史最优解

    Wk,1

    Wk,2

    ...

    Wk,D-1

    Wk,D

    2个粒子的历史最优解

    ...

    ...

    ...

    ...

    ...

    ...

    Wl,1

    Wl,2

    ...

    Wl,D-1

    Wl,D

    N-1个粒子的历史最优解

    Wm,1

    Wm,2

    ...

    Wm,D-1

    Wm,D

    N个粒子的历史最优解

    Wg,1

    Wg,2

    ...

    Wg,D-1

    Wg,D

    全局粒子的历史最优解

      依据这样的思想MATLAB代码例如以下:

    function [ParSwarm,OptSwarm]=InitSwarm(SwarmSize,ParticleSize,ParticleScope,AdaptFunc)

    %功能描写叙述:初始化粒子群,限定粒子群的位置以及速度在指定的范围内

    %[ParSwarm,OptSwarm,BadSwarm]=InitSwarm(SwarmSize,ParticleSize,ParticleScope,AdaptFunc)

    %

    %输入參数:SwarmSize:种群大小的个数

    %输入參数:ParticleSize:一个粒子的维数

    %输入參数:ParticleScope:一个粒子在运算中各维的范围;

    %         ParticleScope格式:

    %           3维粒子的ParticleScope格式:

    %                                   [x1Min,x1Max

    %                                    x2Min,x2Max

    %                                    x3Min,x3Max]

    %

    %输入參数:AdaptFunc:适应度函数

    %

    %输出:ParSwarm初始化的粒子群

    %输出:OptSwarm粒子群当前最优解与全局最优解

    %

    %使用方法[ParSwarm,OptSwarm,BadSwarm]=InitSwarm(SwarmSize,ParticleSize,ParticleScope,AdaptFunc);

    %

    %异常:首先保证该文件在Matlab的搜索路径中,然后查看相关的提示信息。

    %

    %编制人:XXX

    %编制时间:2007.3.26

    %參考文献:无

    %

    %容错控制

    if nargin~=4

        error('输入的參数个数错误。

    ')

    end

    if nargout<2

        error('输出的參数的个数太少,不能保证以后的执行。');

    end

    [row,colum]=size(ParticleSize);

    if row>1|colum>1

        error('输入的粒子的维数错误,是一个11列的数据。');

    end

    [row,colum]=size(ParticleScope);

    if row~=ParticleSize|colum~=2

        error('输入的粒子的维数范围错误。

    ');

    end

    %初始化粒子群矩阵

    %初始化粒子群矩阵,全部设为[0-1]随机数

    %rand('state',0);

    ParSwarm=rand(SwarmSize,2*ParticleSize+1);

    %对粒子群中位置,速度的范围进行调节

    for k=1:ParticleSize

        ParSwarm(:,k)=ParSwarm(:,k)*(ParticleScope(k,2)-ParticleScope(k,1))+ParticleScope(k,1);

        %调节速度。使速度与位置的范围一致

        ParSwarm(:,ParticleSize+k)=ParSwarm(:,ParticleSize+k)*(ParticleScope(k,2)-ParticleScope(k,1))+ParticleScope(k,1);

    end

        

    %对每一个粒子计算其适应度函数的值

    for k=1:SwarmSize

        ParSwarm(k,2*ParticleSize+1)=AdaptFunc(ParSwarm(k,1:ParticleSize));

    end

    %初始化粒子群最优解矩阵

    OptSwarm=zeros(SwarmSize+1,ParticleSize);

    %粒子群最优解矩阵全部设为零

    [maxValue,row]=max(ParSwarm(:,2*ParticleSize+1));

    %寻找适应度函数值最大的解在矩阵中的位置(行数)

    OptSwarm=ParSwarm(1:SwarmSize,1:ParticleSize);

    OptSwarm(SwarmSize+1,:)=ParSwarm(row,1:ParticleSize);

      以下的函数BaseStepPso实现了标准全局版粒子群算法的单步更新位置速度的功能

    function [ParSwarm,OptSwarm]=BaseStepPso(ParSwarm,OptSwarm,AdaptFunc,ParticleScope,MaxW,MinW,LoopCount,CurCount)

    %功能描写叙述:全局版本号:主要的粒子群算法的单步更新位置,速度的算法

    %

    %[ParSwarm,OptSwarm]=BaseStepPso(ParSwarm,OptSwarm,AdaptFunc,ParticleScope,MaxW,MinW,LoopCount,CurCount)

    %

    %输入參数:ParSwarm:粒子群矩阵,包括粒子的位置。速度与当前的目标函数值

    %输入參数:OptSwarm:包括粒子群个体最优解与全局最优解的矩阵

    %输入參数:ParticleScope:一个粒子在运算中各维的范围;

    %输入參数:AdaptFunc:适应度函数

    %输入參数:LoopCount:迭代的总次数

    %输入參数:CurCount:当前迭代的次数

    %

    %返回值:含意同输入的同名參数

    %

    %使用方法:[ParSwarm,OptSwarm]=BaseStepPso(ParSwarm,OptSwarm,AdaptFunc,ParticleScope,MaxW,MinW,LoopCount,CurCount)

    %

    %异常:首先保证该文件在Matlab的搜索路径中,然后查看相关的提示信息。

    %

    %编制人:XXX

    %编制时间:2007.3.26

    %參考文献:XXX

    %參考文献:XXX

    %

    %改动记录

    %----------------------------------------------------------------

    %2007.3.27

    %改动人:XXX

    加入2*unifrnd(0,1).*SubTract1(row,:)中的unifrnd(0,1)随机数,使性能大为提高

    %參照基于MATLAB的粒子群优化算法程序设计

    %

    总体评价:使用这个版本号的调节系数,效果比較好

    %

    %容错控制

    if nargin~=8

        error('输入的參数个数错误。

    ')

    end

    if nargout~=2

        error('输出的个数太少,不能保证循环迭代。

    ')

    end

    %開始单步更新的操作

    %*********************************************

    %*****更改以下的代码,能够更改惯性因子的变化*****

    %---------------------------------------------------------------------

    %线形递减策略

    w=MaxW-CurCount*((MaxW-MinW)/LoopCount);

    %---------------------------------------------------------------------

    %w固定不变策略

    %w=0.7;

    %---------------------------------------------------------------------

    %參考文献:陈贵敏,贾建援,韩琪,粒子群优化算法的惯性权值递减策略研究,西安交通大学学报。20061

    %w非线形递减,以凹函数递减

    %w=(MaxW-MinW)*(CurCount/LoopCount)^2+(MinW-MaxW)*(2*CurCount/LoopCount)+MaxW;

    %---------------------------------------------------------------------

    %w非线形递减,以凹函数递减

    %w=MinW*(MaxW/MinW)^(1/(1+10*CurCount/LoopCount));

    %*****更改上面的代码,能够更改惯性因子的变化*****

    %*********************************************

    %得到粒子群群体大小以及一个粒子维数的信息

    [ParRow,ParCol]=size(ParSwarm);

    %得到粒子的维数

    ParCol=(ParCol-1)/2;

    SubTract1=OptSwarm(1:ParRow,:)-ParSwarm(:,1:ParCol);

    %*********************************************

    %*****更改以下的代码。能够更改c1,c2的变化*****

    c1=2;

    c2=2;

    %---------------------------------------------------------------------

    %con=1;

    %c1=4-exp(-con*abs(mean(ParSwarm(:,2*ParCol+1))-AdaptFunc(OptSwarm(ParRow+1,:))));

    %c2=4-c1;

    %----------------------------------------------------------------------

    %*****更改上面的代码,能够更改c1,c2的变化*****

    %*********************************************

    for row=1:ParRow

       SubTract2=OptSwarm(ParRow+1,:)-ParSwarm(row,1:ParCol);

       TempV=w.*ParSwarm(row,ParCol+1:2*ParCol)+2*unifrnd(0,1).*SubTract1(row,:)+2*unifrnd(0,1).*SubTract2;

       %限制速度的代码

       for h=1:ParCol

           if TempV(:,h)>ParticleScope(h,2)

               TempV(:,h)=ParticleScope(h,2);

           end

           if TempV(:,h)<-ParticleScope(h,2)

               TempV(:,h)=-ParticleScope(h,2)+1e-10;

               %1e-10防止适应度函数被零除

           end

       end  

       

       %更新速度

       ParSwarm(row,ParCol+1:2*ParCol)=TempV;

       

       %*********************************************

       %*****更改以下的代码,能够更改约束因子的变化*****

       %---------------------------------------------------------------------

       %a=1;

       %---------------------------------------------------------------------

       a=0.729;

       %*****更改上面的代码,能够更改约束因子的变化*****

       %*********************************************

       

       %限制位置的范围

       TempPos=ParSwarm(row,1:ParCol)+a*TempV;

       for h=1:ParCol

           if TempPos(:,h)>ParticleScope(h,2)

               TempPos(:,h)=ParticleScope(h,2);

           end

           if TempPos(:,h)<=ParticleScope(h,1)

               TempPos(:,h)=ParticleScope(h,1)+1e-10;           

           end

       end

       %更新位置 

       ParSwarm(row,1:ParCol)=TempPos;

       

       %计算每一个粒子的新的适应度值

       ParSwarm(row,2*ParCol+1)=AdaptFunc(ParSwarm(row,1:ParCol));

       if ParSwarm(row,2*ParCol+1)>AdaptFunc(OptSwarm(row,1:ParCol))

           OptSwarm(row,1:ParCol)=ParSwarm(row,1:ParCol);

       end

    end

    %for循环结束

    %寻找适应度函数值最大的解在矩阵中的位置(行数),进行全局最优的改变 

    [maxValue,row]=max(ParSwarm(:,2*ParCol+1));

    if AdaptFunc(ParSwarm(row,1:ParCol))>AdaptFunc(OptSwarm(ParRow+1,:))

        OptSwarm(ParRow+1,:)=ParSwarm(row,1:ParCol);

    end

      这两个函数给出以后。须要一个函数来把这两个函数组装起来。以此实现一个完整的粒子群算法,这个函数就是PsoProcess

      代码例如以下:

     function [Result,OnLine,OffLine,MinMaxMeanAdapt]=PsoProcess(SwarmSize,ParticleSize,ParticleScope,InitFunc,StepFindFunc,AdaptFunc,IsStep,IsDraw,LoopCount,IsPlot)

    %功能描写叙述:一个循环n次的PSO算法完整过程,返回这次执行的最小与最大的平均适应度,以及在线性能与离线性能

    %[Result,OnLine,OffLine,MinMaxMeanAdapt]=PsoProcess(SwarmSize,ParticleSize,ParticleScope,InitFunc,StepFindFunc,AdaptFunc,IsStep,IsDraw,LoopCount,IsPlot)

    %输入參数:SwarmSize:种群大小的个数

    %输入參数:ParticleSize:一个粒子的维数

    %输入參数:ParticleScope:一个粒子在运算中各维的范围;

    %         ParticleScope格式:

    %           3维粒子的ParticleScope格式:

    %                                   [x1Min,x1Max

    %                                    x2Min,x2Max

    %                                    x3Min,x3Max]

    %

    %输入參数:InitFunc:初始化粒子群函数

    %输入參数:StepFindFunc:单步更新速度。位置函数

    %输入參数:AdaptFunc:适应度函数

    %输入參数:IsStep:是否每次迭代暂停;IsStep0,不暂停。否则暂停。缺省不暂停

    %输入參数:IsDraw:是否图形化迭代过程;IsDraw0。不图形化迭代过程,否则,图形化表示。

    缺省不图形化表示

    %输入參数:LoopCount:迭代的次数。缺省迭代100

    %输入參数:IsPlot:控制是否绘制在线性能与离线性能的图形表示;IsPlot=0,不显示;

    %                 IsPlot=1;显示图形结果。缺省IsPlot=1

    %

    %返回值:Result为经过迭代后得到的最优解

    %返回值:OnLine为在线性能的数据

    %返回值:OffLine为离线性能的数据

    %返回值:MinMaxMeanAdapt为本次完整迭代得到的最小与最大的平均适应度

    %

    %使用方法[Result,OnLine,OffLine,MinMaxMeanAdapt]=PsoProcess(SwarmSize,ParticleSize,ParticleScope,InitFunc,StepFindFunc,AdaptFunc,IsStep,IsDraw,LoopCount,IsPlot);

    %

    %异常:首先保证该文件在Matlab的搜索路径中。然后查看相关的提示信息。

    %

    %编制人:XXX

    %编制时间:2007.3.26

    %參考文献:XXXXX%

    %改动记录:

    %加入MinMaxMeanAdapt,以得到性能评估数据

    %改动人:XXX

    %改动时间:2007.3.27

    %參考文献:XXX.

    %容错控制

    if nargin<4

        error('输入的參数个数错误。')

    end

    [row,colum]=size(ParticleSize);

    if row>1|colum>1

        error('输入的粒子的维数错误,是一个11列的数据。

    ');

    end

    [row,colum]=size(ParticleScope);

    if row~=ParticleSize|colum~=2

        error('输入的粒子的维数范围错误。

    ');

    end

    %设置缺省值

    if nargin<7

        IsPlot=1;

        LoopCount=100;

        IsStep=0;

        IsDraw=0;

    end

    if nargin<8

        IsPlot=1;

        IsDraw=0;

        LoopCount=100;

    end

    if nargin<9

        LoopCount=100;

        IsPlot=1;

    end

    if nargin<10

        IsPlot=1;

    end

    %控制是否显示2维以下粒子维数的寻找最优的过程

    if IsDraw~=0

        DrawObjGraphic(ParticleSize,ParticleScope,AdaptFunc);

    end

    %初始化种群       

    [ParSwarm,OptSwarm]=InitFunc(SwarmSize,ParticleSize,ParticleScope,AdaptFunc)

    %在測试函数图形上绘制初始化群的位置

    if IsDraw~=0

        if 1==ParticleSize

        for ParSwarmRow=1:SwarmSize

            plot([ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,1)],[ParSwarm(ParSwarmRow,3),0],'r*-','markersize',8);

            text(ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,3),num2str(ParSwarmRow));

        end

    end

        if 2==ParticleSize

            for ParSwarmRow=1:SwarmSize

                stem3(ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,2),ParSwarm(ParSwarmRow,5),'r.','markersize',8);

            end

        end

    end

        

    %暂停让抓图

    if IsStep~=0

        disp('開始迭代。按随意键:')

        pause

    end

    %開始更新算法的调用

    for k=1:LoopCount

        %显示迭代的次数:

        disp('----------------------------------------------------------')

        TempStr=sprintf('第 %g 此迭代',k);

        disp(TempStr);

        disp('----------------------------------------------------------')

        

        %调用一步迭代的算法

        [ParSwarm,OptSwarm]=StepFindFunc(ParSwarm,OptSwarm,AdaptFunc,ParticleScope,0.95,0.4,LoopCount,k)

        

        %在目标函数的图形上绘制2维以下的粒子的新位置

        if IsDraw~=0

            if 1==ParticleSize

                for ParSwarmRow=1:SwarmSize

                    plot([ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,1)],[ParSwarm(ParSwarmRow,3),0],'r*-','markersize',8);

                    text(ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,3),num2str(ParSwarmRow));

                end

            end

            if 2==ParticleSize

                for ParSwarmRow=1:SwarmSize

                    stem3(ParSwarm(ParSwarmRow,1),ParSwarm(ParSwarmRow,2),ParSwarm(ParSwarmRow,5),'r.','markersize',8);

                end

            end

        end

        

        XResult=OptSwarm(SwarmSize+1,1:ParticleSize);

        YResult=AdaptFunc(XResult);    

        if IsStep~=0

            XResult=OptSwarm(SwarmSize+1,1:ParticleSize);

            YResult=AdaptFunc(XResult);    

            str=sprintf('%g步迭代的最优目标函数值%g',k,YResult);

            disp(str);

            disp('下次迭代,按随意键继续');

            pause

        end

        

        %记录每一步的平均适应度

        MeanAdapt(1,k)=mean(ParSwarm(:,2*ParticleSize+1));

    end

    %for循环结束标志

    %记录最小与最大的平均适应度

    MinMaxMeanAdapt=[min(MeanAdapt),max(MeanAdapt)];

    %计算离线与在线性能

    for k=1:LoopCount

        OnLine(1,k)=sum(MeanAdapt(1,1:k))/k;

        OffLine(1,k)=max(MeanAdapt(1,1:k));

    end

    for k=1:LoopCount

        OffLine(1,k)=sum(OffLine(1,1:k))/k;

    end

    %绘制离线性能与在线性能曲线

    if 1==IsPlot

        figure

        hold on

        title('离线性能曲线图')

        xlabel('迭代次数');

        ylabel('离线性能');

        grid on

        plot(OffLine);

        figure

        hold on

        title('在线性能曲线图')

        xlabel('迭代次数');

        ylabel('在线性能');

        grid on

        plot(OnLine);

    end

    %记录本次迭代得到的最优结果

    XResult=OptSwarm(SwarmSize+1,1:ParticleSize);

    YResult=AdaptFunc(XResult);

    Result=[XResult,YResult];

      这里给出一个使用的样例代码,并分别解释各參数的含义:

    %打开计时器

    tic;

    %

    Scope=[-50 50

        -50 50

        -50 50

        -50 50

        -50 50

        -50 50

        -50 50

        -50 50

        -50 50

        -50 50];

    [v,on,off,minmax]=PsoProcess(20,10,Scope,@initswarm,@BasestepPSO,@Griewank,0,0,4000,0);

    toc

    在上面的代码中函数PsoProcess中的20代表粒子群的规模为20个,10代表每一个粒子的维数为10Scope是粒子的每一维的范围。同一时候也是速度的范围,@initswarm是初始化函数的句柄,@BasestepPSO是单步更新的函数句柄,@Griewank是适应度评价函数的句柄。4000代表真个算法循环4000次终止,其它參数參见说明文档。

      粒子群算法(6)-----几个适应度评价函数

    以下给出几个适应度评价函数。并给出图形表示

       头几天机子种了病毒,又一次安装了系统。不小心把程序全部格式化了,痛哭。!

    没办法,好多程序不见了。如今把这几个典型的函数又一次编写了。把他们给出来,就算粒子群算法的一个结束吧!

    痛恨病毒!!

    !!

      第一个函数:Griewank函数,图形例如以下所看到的:

      适应度函数例如以下:(为了求最大值,我去了全部函数值的相反数) 

    function y=Griewank(x)
    %Griewan函数
    %输入x,给出相应的y,x=(0,0,…,0)处有全局极小点0.
    %编制人:
    %编制日期:
    [row,col]=size(x);
    if row>1
        error('输入的參数错误');
    end
    y1=1/4000*sum(x.^2);
    y2=1;
    for h=1:col
        y2=y2*cos(x(h)/sqrt(h));
    end
    y=y1-y2+1;
    y=-y;

      绘制函数图像的代码例如以下:

    function DrawGriewank()
    %绘制Griewank函数图形
    x=[-8:0.1:8];
    y=x;
    [X,Y]=meshgrid(x,y);
    [row,col]=size(X);
    for l=1:col
        for h=1:row
            z(h,l)=Griewank([X(h,l),Y(h,l)]);
        end
    end
    surf(X,Y,z);
    shading interp

      第二个函数:Rastrigin函数。图形例如以下所看到的:

      适应度函数例如以下:(为了求最大值,我去了全部函数值的相反数) 

    function y=Rastrigin(x)
    %Rastrigin函数
    %输入x,给出相应的y,x=(0,0,…,0)处有全局极小点0.
    %编制人:
    %编制日期:
    [row,col]=size(x);
    if row>1
        error('输入的參数错误');
    end
    y=sum(x.^2-10*cos(2*pi*x)+10);
    y=-y;

      绘制函数图像的代码例如以下:

    function DrawRastrigin()
    %绘制Rastrigin函数图形
    x=[-5:0.05:5];
    y=x;
    [X,Y]=meshgrid(x,y);
    [row,col]=size(X);
    for l=1:col
        for h=1:row
            z(h,l)=Rastrigin([X(h,l),Y(h,l)]);
        end
    end
    surf(X,Y,z);
    shading interp

      粒子群有如此惨败。

  • 相关阅读:
    Java实现 LeetCode 130 被围绕的区域
    Java实现 LeetCode 130 被围绕的区域
    Java实现 LeetCode 130 被围绕的区域
    win32创建控件的一些问题
    win32 sdk绘制ListBox控件
    VC++ WIN32 sdk实现按钮自绘详解 之二.
    win32 sdk 列表视图控件绘制
    win32 sdk树形控件的项拖拽实现
    MFC 用gdi绘制填充多边形区域
    vc 按钮自绘
  • 原文地址:https://www.cnblogs.com/mengfanrong/p/4568662.html
Copyright © 2011-2022 走看看