粒子群算法(PSO)的实现,具有详细的注释

# -*- coding: utf-8 -*-
"""
Created on Mon Mar 14 09:06:35 2022

@author: aa
"""

import numpy as np#调用numpy
import matplotlib.pylab as plt#画图
np.random.seed(1)#确实随机种子

def fitnessEvalute(x,problemIndex):#适应性评估
    # x:被优化问题的候选解,可以是矩阵形式,也可是一维数组形式。
    # problemIndex: 被优化问题的序号,方便主程序调用。

    if problemIndex == 1: # 球形函数
        return np.sum(x**2,axis=1)
        
    elif problemIndex == 2:# Rosenbrock function
        dim = len(x[0])
        a = 100*(x[:,1:dim] - x[:,0:dim-1]**2)**2
        b = (x[:,0:dim-1]-1)**2
        return np.sum(np.add(a,b),axis=1)
    
    
    

def diversity(pop):#多样性评估
    # 通过欧氏距离测量群体多样性。
    edist = []
    popsize,dim = pop.shape
    for i in range(popsize-1):
        for j in range(i,popsize):
            temp = np.sqrt(np.sum((pop[i,:]-pop[j,:])**2))
            edist.append(temp)
    return (sum(edist))/len(edist)
    

def validCheck(lb,ub,pop,check_select):
    # 1、随机赋值,2、定为边界,3、弹回
    init = np.random.uniform(lb,ub, pop.shape)#init是在上界和下界以及pop的大小范围确定的一个随机数
    #用来随机赋值
    if check_select == "rand": # 随机赋值
        pop = np.where(pop<lb,init,pop)
        pop = np.where(pop>ub,init,pop)
    elif check_select == "bound": # 超出边界以边界赋值
        pop = np.where(pop<lb,lb,pop)
        pop = np.where(pop>ub,ub,pop)
    elif check_select == "bound_back": # 弹回
        x = np.argwhere(pop<lb)
        y = np.argwhere(pop>ub)
        # print(x.shape,y.shape)
        for i in range(x.shape[0]):
            pop[x[i][0],x[i][1]] = 2 * lb - pop[x[i][0],x[i][1]]              
        for i in range(y.shape[0]):
            pop[y[i][0],y[i][1]] = 2 * ub - pop[y[i][0],y[i][1]]  
    return pop 







if __name__ == '__main__':
    lb,ub = -10,10#确定粒子的上边界和下边界
    popsize,dim = 100,50#确定粒子的个数和维度
    maxIter =10000 #确定最大迭代次数
    omiga,c1,c2 = 0.7,1.4,1.4 # 确定参数表,此时的参数为经验值
    problemIndex = 1
    
    #初始化过程
    pop = np.random.uniform(lb,ub,(popsize,dim))#使用random函数中的uniform函数生成popsize个个体,维度为dim,uniform是生成[popsize,dim)
    velocity = pop.copy() # 确实每一个个体的次数
    fit = fitnessEvalute(pop,problemIndex) # 进行适应值评估
    individualBestFit = fit.copy() # location and the individual best
    individualBest = pop.copy()#将当前适应性评估的值作为个体最优的初始值
    globalBest = pop[0].copy() # 将pop的第一个值作为全局最优解
    globalBestFit = fit[0].copy()#适应性评估的第一个值作为全局适应性评估的最优解
    fitBest = globalBestFit.copy()
    
    
    
    #初始化结束了,进入迭代过程
    fitBest = []#使用fitBest存储每一代的最优值
    # 初始化过程结束,进入迭代过程
    fitBest = []  # 用列表存储每一代的最优值
    for gen in range(maxIter):#迭代次数
        if gen % 100 == 0:#每100次进行一次输出
            edist = diversity(pop)#评价多样性
            print("gen:{}, globalBestFit:{} edist={}".format(gen, globalBestFit,edist))
        for i in range(popsize):#对每一个个体进行一次循环,
            r1 = np.random.random(dim)#
            r2 = np.random.random(dim) # 生成两个随机数
            r3 = np.random.randint(0,popsize,2)
        # 更新速度和位置,公式
            velocity[i,:] = velocity[i,:] * omiga + r1*c1*(globalBest - pop[i,:]) + r2*c2*(individualBest[i,:] - pop[i,:]) # 
                    
            #velocity[i,:] = velocity[i,:] * omiga + r1*c1*(globalBest - pop[i,:]) + r2*c2*(individualBest[r3[0],:] - pop[i,:]) # 
    ##        
    #        velocity[i,:] = velocity[i,:] * omiga + r1*c1*(globalBest - pop[i,:]) \
    #                + r2*c2*(individualBest[r3[0],:] - individualBest[i,:])
        
    #        velocity[i,:] = velocity[i,:] * omiga + r1*c1*(individualBest[r3[0],:] - pop[i,:]) \
    #                + r2*c2*(individualBest[r3[1],:] - pop[i,:]) # 
    #        
    #        velocity[i,:] = velocity[i,:] * omiga + r1*c1*(pop[r3[0],:] - pop[r3[1],:])               
        
                    
            pop[i,:] = pop[i,:] + velocity[i,:]
    
         #合法性检查 ,用来规避个体有越界的行为
        popchild = validCheck(lb,ub,pop,"rand") # 此处的第四个参数的取值有"rand","bound","bound_back"
        #
        #对当前进行适应性评估
        fitCurrent = fitnessEvalute(popchild,problemIndex)#适用性函数相当于一个评估函数,进行比较与评估
            
        
        #更新历史最优解和个体最优解
        for i in range(popsize):
            if fitCurrent[i] < fit[i]: # 如果当前的适应性的值小于fit存储的值,就进行更新
                pop[i,:],fit[i] = popchild[i,:],fitCurrent[i]#如果子代的值优于父代,就把子代的值覆盖掉父代的值
                if fitCurrent[i] < individualBestFit[i]: # 更新个体最优解和位置
                    individualBestFit[i] = fitCurrent[i]  #个体最优适应性更新  
                    individualBest[i,:] = popchild[i,:] #个体最优值
        
        
        if np.min(individualBestFit)<globalBestFit:#如果个体总群中有值小于全局最优值,那么将最优适应性进行更新,将群居最优解也进行更新
            globalBestFit = np.min(individualBestFit)
            globalBest = individualBest[np.argmin(individualBestFit),:]
        
        fitBest.append(globalBestFit)  # 记录每一代最优值。
        
    print(fitBest[-10:]) # 输出最后五个值
    # 汇出函数图像。为了便于观察,取适应值的对数。
    plt.plot(np.log(fitBest))
    plt.show() 
    
   

运行结果:
gen:0, globalBestFit:3474.868421982262 edist=79.6682356664077
gen:100, globalBestFit:140.48546901908603 edist=4.102766066578025
gen:200, globalBestFit:52.55578309791457 edist=1.401527044098573
gen:300, globalBestFit:25.878779822377165 edist=0.48473753238003375
gen:400, globalBestFit:23.285714829255852 edist=0.2110591677581779
gen:500, globalBestFit:20.615111916463608 edist=0.10705842601159207
gen:600, globalBestFit:12.295009224335312 edist=0.21221435423446272
gen:700, globalBestFit:12.045860570955622 edist=0.028524440328110825
gen:800, globalBestFit:11.594352179114685 edist=0.022423928726239363
gen:900, globalBestFit:10.63460907436306 edist=0.008949303488937677
gen:1000, globalBestFit:10.342613452960736 edist=0.025739792111941773
gen:1100, globalBestFit:10.278183028539402 edist=0.01966159442339601
gen:1200, globalBestFit:10.230571716986748 edist=0.004781061180254118
gen:1300, globalBestFit:10.206778154515673 edist=0.0027585356551705327
gen:1400, globalBestFit:4.21199214946001 edist=0.11044276390279283
gen:1500, globalBestFit:4.209998843036691 edist=0.0028659065728237885
gen:1600, globalBestFit:4.2035010423581225 edist=0.0055041306035474745
gen:1700, globalBestFit:4.202363573217319 edist=0.00185579918822108
gen:1800, globalBestFit:4.2019167071476655 edist=0.0004010604761363078
gen:1900, globalBestFit:4.2003246265829945 edist=0.0005337626937005378
gen:2000, globalBestFit:4.035943689183826 edist=0.0006156148545869195
gen:2100, globalBestFit:3.493170104391786 edist=0.007735864742317073
gen:2200, globalBestFit:3.4931191189882345 edist=0.00024931370394743754
gen:2300, globalBestFit:3.4912596189648433 edist=0.0001549454032002674
gen:2400, globalBestFit:3.4911936330446287 edist=0.0001831807970544893
gen:2500, globalBestFit:3.4911613219665285 edist=0.00032676222476040053
gen:2600, globalBestFit:3.490804294866671 edist=0.0004056227143997571
gen:2700, globalBestFit:3.4900755979953337 edist=0.001168432874858142
gen:2800, globalBestFit:3.4900754481408707 edist=1.3346724706805687e-05
gen:2900, globalBestFit:3.4900740002058406 edist=5.048235604124714e-05
gen:3000, globalBestFit:3.4900735578862796 edist=8.424026856664483e-06
gen:3100, globalBestFit:3.3849269004992886 edist=0.0068067067561920595
gen:3200, globalBestFit:3.148913649320306 edist=2.2935768502744297e-05
gen:3300, globalBestFit:3.1488948924627387 edist=4.567153422387e-06
gen:3400, globalBestFit:3.135293771118033 edist=8.971370104422628e-05
gen:3500, globalBestFit:3.1340031874495815 edist=4.6380419962587546e-05
gen:3600, globalBestFit:2.289747397418629 edist=0.00019145220989673026
gen:3700, globalBestFit:2.289736435955503 edist=1.0276812898504331e-05
gen:3800, globalBestFit:2.288121631430392 edist=1.4154205436656599e-05
gen:3900, globalBestFit:2.28812163073056 edist=2.2083803462505684e-06
gen:4000, globalBestFit:2.288118583854497 edist=3.3065313796153507e-05
gen:4100, globalBestFit:2.28811858378051 edist=1.5934859221160837e-07
gen:4200, globalBestFit:2.2881185830966047 edist=1.3569036566932365e-07
gen:4300, globalBestFit:2.1021249015614165 edist=0.013452444030302614
gen:4400, globalBestFit:1.839192615679958 edist=1.4032264185780908e-05
gen:4500, globalBestFit:1.8389182768308665 edist=9.894243874537981e-06
gen:4600, globalBestFit:1.2009247318466547 edist=0.00027616139434793503
gen:4700, globalBestFit:1.2009247298919337 edist=4.2455652814341236e-08
gen:4800, globalBestFit:1.0634456461923518 edist=0.016093128415467724
gen:4900, globalBestFit:1.063445646170368 edist=6.379338506255092e-07
gen:5000, globalBestFit:1.0634456461686805 edist=2.556073278318917e-09
gen:5100, globalBestFit:1.0609334727196071 edist=0.0005444926725752089
gen:5200, globalBestFit:1.044946857982695 edist=8.019115574376528e-06
gen:5300, globalBestFit:1.044946857982695 edist=5.648460111558194e-09
gen:5400, globalBestFit:1.044946857982695 edist=4.706677788923633e-09
gen:5500, globalBestFit:1.044946857982695 edist=6.124950431751896e-09
gen:5600, globalBestFit:1.044946857982695 edist=5.245436965043857e-09
gen:5700, globalBestFit:1.044946857982695 edist=5.109895639391901e-09
gen:5800, globalBestFit:1.044946857982695 edist=6.0806834627457175e-09
gen:5900, globalBestFit:1.044946857982695 edist=5.901550715670337e-09
gen:6000, globalBestFit:1.044946857982695 edist=5.402952303104211e-09
gen:6100, globalBestFit:1.044946857982695 edist=5.1068643875222125e-09
gen:6200, globalBestFit:1.044946857982695 edist=5.199160412573614e-09
gen:6300, globalBestFit:1.044946857982695 edist=5.0077877882783456e-09
gen:6400, globalBestFit:1.044946857982695 edist=4.567956456774929e-09
gen:6500, globalBestFit:1.044946857982695 edist=5.3463461093980934e-09
gen:6600, globalBestFit:1.044946857982695 edist=4.847356599918589e-09
gen:6700, globalBestFit:1.044946857982695 edist=4.710416365992886e-09
gen:6800, globalBestFit:1.044946857982695 edist=4.86152283862822e-09
gen:6900, globalBestFit:1.044946857982695 edist=5.1712110900914705e-09
gen:7000, globalBestFit:1.044946857982695 edist=5.4012591540265925e-09
gen:7100, globalBestFit:1.044946857982695 edist=4.0962133979048434e-09
gen:7200, globalBestFit:1.044946857982695 edist=4.935868281547475e-09
gen:7300, globalBestFit:1.044946857982695 edist=6.607166580586777e-09
gen:7400, globalBestFit:1.044946857982695 edist=4.837894706244063e-09
gen:7500, globalBestFit:1.044946857982695 edist=4.824448067440524e-09
gen:7600, globalBestFit:1.044946857982695 edist=4.380139829717852e-09
gen:7700, globalBestFit:1.044946857982695 edist=4.621512218864146e-09
gen:7800, globalBestFit:1.044946857982695 edist=4.957605851581997e-09
gen:7900, globalBestFit:1.044946857982695 edist=5.222133493948974e-09
gen:8000, globalBestFit:1.044946857982695 edist=4.654821602961558e-09
gen:8100, globalBestFit:1.044946857982695 edist=5.1458517165638435e-09
gen:8200, globalBestFit:1.044946857982695 edist=5.477250273260866e-09
gen:8300, globalBestFit:1.044946857982695 edist=5.966652205340479e-09
gen:8400, globalBestFit:1.044946857982695 edist=5.9957101848306745e-09
gen:8500, globalBestFit:1.044946857982695 edist=4.874319227254483e-09
gen:8600, globalBestFit:1.044946857982695 edist=4.686255861582584e-09
gen:8700, globalBestFit:1.044946857982695 edist=5.7445786081714244e-09
gen:8800, globalBestFit:1.044946857982695 edist=5.4628722603045426e-09
gen:8900, globalBestFit:1.044946857982695 edist=4.922253145189731e-09
gen:9000, globalBestFit:1.044946857982695 edist=4.546249811369738e-09
gen:9100, globalBestFit:1.044946857982695 edist=4.3431760615486774e-09
gen:9200, globalBestFit:1.044946857982695 edist=4.557314989559076e-09
gen:9300, globalBestFit:1.044946857982695 edist=4.432872199030961e-09
gen:9400, globalBestFit:1.044946857982695 edist=5.955503539330763e-09
gen:9500, globalBestFit:1.044946857982695 edist=5.5025801560197266e-09
gen:9600, globalBestFit:1.044946857982695 edist=5.691153115048001e-09
gen:9700, globalBestFit:1.044946857982695 edist=4.764220635576974e-09
gen:9800, globalBestFit:1.044946857982695 edist=4.99556833682449e-09
gen:9900, globalBestFit:1.044946857982695 edist=4.884152101567283e-09
[1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695, 1.044946857982695]

在这里插入图片描述

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
本框架提供了有关粒子群算法(PSO)和遗传算法(GA)的完整实现,以及一套关于改进、应用、测试、结果输出的完整框架。 本框架对粒子群算法与遗传算法进行逻辑解耦,对其中的改进点予以封装,进行模块化,使用者可以采取自己对该模块的改进替换默认实现组成新的改进算法与已有算法进行对比试验。试验结果基于Excel文件输出,并可通过设定不同的迭代结束方式选择试验数据的输出方式,包括: 1. 输出随迭代次数变化的平均达优率数据(设定终止条件区间大于0)。 2. 输出随迭代次数变化的平均最优值数据(设定终止条件区间等于0)。 本框架了包含了常用基准函数的实现以及遗传算法粒子群算法对其的求解方案实现和对比,如TSP,01背包,Banana函数,Griewank函数等。并提供大量工具方法,如KMeans,随机序列生成与无效序列修补方法等等。 对遗传算法的二进制编码,整数编码,实数编码,整数序列编码(用于求解TSP等),粒子群算法的各种拓扑结构,以及两种算法的参数各种更新方式均有实现,并提供接口供使用者实现新的改进方式并整合入框架进行试验。 其中还包括对PSO进行离散化的支持接口,和自己的设计一种离散PSO方法及其用以求解01背包问题实现样例。 欢迎参考并提出宝贵意见,特别欢迎愿意协同更新修补代码的朋友(邮箱starffly@foxmail.com)。 代码已作为lakeast项目托管在Google Code: http://code.google.com/p/lakeast http://code.google.com/p/lakeast/downloads/list 某些类的功能说明: org.lakest.common中: BoundaryType定义了一个枚举,表示变量超出约束范围时为恢复到约束范围所采用的处理方式,分别是NONE(不处理),WRAP(加减若干整数个区间长度),BOUNCE(超出部分向区间内部折叠),STICK(取超出方向的最大限定值)。 Constraint定义了一个代表变量约束范围的类。 Functions定义了一系列基准函数的具体实现以供其他类统一调用。 InitializeException定义了一个代表程序初始化出现错误的异常类。 Randoms类的各个静态方法用以产生各种类型的随机数以及随机序列的快速产生。 Range类的实现了用以判断变量是否超出约束范围以及将超出约束范围的变量根据一定原则修补到约束范围的方法。 ToStringBuffer是一个将数组转换为其字符串表示的类。 org.lakeast.ga.skeleton中: AbstractChromosome定义了染色体的公共方法。 AbstractDomain是定义问题域有关的计算与参数的抽象类。 AbstractFactorGenerator定义产生交叉概率和变异概率的共同方法。 BinaryChromosome是采用二进制编码的染色体的具体实现类。 ConstantFactorGenerator是一个把交叉概率和变异概率定义为常量的参数产生器。 ConstraintSet用于在计算过程中保存和获取应用问题的各个维度的约束。 Domain是遗传算法求解中所有问题域必须实现的接口。 EncodingType是一个表明染色体编码类型的枚举,包括BINARY(二进制),REAL(实数),INTEGER(整型)。 Factor是交叉概率和变异概率的封装。 IFactorGenerator参数产生器的公共接口。 Population定义了染色体种群的行为,包括种群的迭代,轮盘赌选择和交叉以及最优个体的保存。 org.lakeast.ga.chromosome中: BinaryChromosome二进制编码染色体实现。 IntegerChromosome整数编码染色体实现。 RealChromosome实数编码染色体实现。 SequenceIntegerChromosome整数序列染色体实现。 org.lakeast.pso.skeleton中: AbstractDomain提供一个接口,将粒子的位置向量解释到离散空间,同时不干扰粒子的更新方式。 AbstractFactorGenerator是PSO中参数产生器的公共抽象类。 AbstractParticle定义了PSO种群中粒子的基本行为,最主要是实现了如何根据现有位置计算得到下一代粒子的位置的合法值。 ConstraintSet用于在粒子迭代过程中保存和获取应用问题的各个维度的约束。 AbstractSwarm.java各种拓扑结构的PSO种群的抽象父类,主要实现了种群迭代过程中计算流程的定义以及中间数据被如何输出到测试工具类。 Domain是PSO算法求解中所有问题域必须实现的接口。 DynamicFatorGenerator若种群在迭代过程中,w,c1,c2随迭代次数发生变化,那么它们的产生器需要继承这个抽象类。 Factor封装了w,c1,c2三个参数的字面值。 Location用于保存和获取迭代中粒子的位置和速度向量的数值。 NeighborhoodBestParticle定义了采用邻域版本的PSO算法的具体实现。主要是实现了如何根据邻域版本的PSO算法计算下一迭代中的粒子速度。 RingTopoSwarm定义环拓扑结构的具体实现,主要是定义了如何获取粒子的邻域粒子的方法。 StaticTopoSwarm静态拓扑结构的PSO算法的抽象父类。 org.lakeast.pso.swarm中包含粒子群拓扑结构的各种实现,基本见名知意。 对各种问题的求解样例位于org.lakeast.main包中,以...TaskTest结尾,基本见名知意。 以ShafferF6DomainTaskTes对ShafferF6函数进行求解(采用的是PSO,遗传算法样例参见TSPValueTaskTest)为例说明求解过程如下: 1. 入口函数位于org.lakeast.main.ShafferF6DomainTaskTest中,go函数执行。 2. 在go函数中,首先指定迭代次数(numberOfIterations),测试多少轮(testCount,多次运行以得到平均达优值),种群大小(popSize),邻域大小(neighborhoodSize),迭代结束条件(exitCondition,由于制定了迭代次数,所以设定为[0,0],也就是只有达到指定迭代次数才退出)。 3. 以testCount,numberOfIterations以及迭代结束条件exitCondition为参数构建TestBatch类的实例batch。这个类用来进行管理参与测试的各种具体算法,且把数据结果按指定的格式输出为Excel文件。 4. 指定PSO中的因子产生方法,采用ExponentFactorGenerator和ConstrictFactorGenerator两种方式(实现位于org.lakeast.pso.gen包)。 5. Y表示参与测试的算法数目。 6. Testable是所有可以被TestBatch测试的类需要实现的接口,以提供TestBatch生成结果Excel文件所需要的数据。 7. Domain接口是所有可以被算法解决的问题所需要实现的接口,比如说明该问题所需要的粒子位置约束范围,速度约束范围,以及适值评估的公司等。这里的Domain被实例化为ShafferF6Domain,也就是按照ShafferF6函数评估适值。 8. RingTopoSwarm是用来封装环拓扑邻域结构的类,NeighboordBestParticle是配合该类来实现按邻域最优更新速度而不是全局最优来更新。 9. 各个测试算法都被加入到TestBatch以后,batch.run()开始执行算法比较过程并输出结果Excel文件到C盘根目录(输出路径可在Testable接口中配置,除了生成Excel文件外,还可以通过修改log4j.properties在制定的位置产生运行结果日志)。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iWTknow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值