混合蛙跳算法原理与实现

一、原理

在一块湿地,有N只青蛙,都在找食物最多的地方。湿地的整个青蛙群体可以划分为多个不同的子群体,每个子群体有各自的信息(食物最多的地方的信息),每个青蛙对食物最多地方有自己的决策信息,青蛙之间互相交流,互相影响,青蛙个体的决策信息在进化,整个子群体也会进化。当一定程度后,各个子群体间进行信息交换(全局搜素),实现子群体间的混合运算。直到满足条件(全局最优解基本不变,全局优化次数已达到上限)。

二、原理步骤

  • Step1:

初试化种群信息,确定种群的数量F,模因(子群)的数量m,每个族群中青蛙的数量n,F=m*n,计算青蛙的适应值(即每个解对应的目标函数值)。

  • Step2:

按青蛙适应值的降序排序,记下第一个最佳青蛙的位置 (首个全局最优解)

  • Step3:

将F个青蛙分配到m个族群中 ,每个族群n只青蛙。

  • Step4:

族群优化(局部优化)

  • [Step4-1]
    设im=0,这im是种群计数器,用来与源种群数m比较。
    设in=0,这是组内进化步骤的数目,与族群最大进化Lmax比较。
  • [Step4-2]
    在第i个族群中选取q个可能成为最佳的青蛙构成子族群(submemeplexe),并确定子族群中最佳青蛙和最差青蛙的位置Pb,Pw。im=im+1
    选取q只青蛙的策略:给具有较好适应值的青蛙赋予更高的权重,具有较差适应值的青蛙赋较低权重。权重用三角概率分布来分配。 这样青蛙被选为子族群的最高概率为P1=2/(n+1),最低概率pn=2/n(n+1)
  • [Step4-3]
    改善子族群中最差青蛙的位置。in=in+1
    青蛙更新距离 Ds=rand()*(Pb-Pw) rand()是一个[0,1]的随机数。
    更新后的青蛙 (-Dmax≦Ds≦Dmax)
    Ds = min{ int [rand (Pb-Pw) ] ,Smax }
    = max{ int [rand (Pb-Pw) ],-Smax } Smax表示青蛙个体允许改变的最大步长
  1. a.如果 在可行的空间内,计算新的适应值(目标值f(Pw’)),新的f(Pw’)比旧的f(Pw)好,用新的Pw’ 替换Pw。
  2. b. 如果新的f(Pw’)比旧的f(Pw)差,用全局最优Px替换局部最优。
    Ds = min{ int [rand (Px-Pw) ],Smax }
    = max{ int [rand (Px-Pw) ],-Smax }
    计算新的适应值,新的f(Pw’)比旧的f(Pw)好,用新的Pw’ 替换Pw。否则执行c
  3. c. 审查制度
    如果新位置是不可行的,或者没有比旧的位置好,那么有缺陷的模因的传播就会被随机生成一个新的青蛙r在一个可行的位置上,以取代新位置不适合进步的青蛙。

不管执行了以上三次跳跃(a,b,c三次跳)中的任何一次,需重新计算本子群的最优个体Pb和最差个体Pw。

  • [Step4-4]
    如果iN

  • [Step4-5]
    如果im

  • Step 5:

把优化后的族群Ym重新组合在一起,按适应值降序排序,更新最佳青蛙的位置 (第i个全局最优解),判断是否满足停止条件。是,停止。否则,返回Step3。

三、实现与应用

    # -*- coding: utf-8 -*-
    """Created on Sun Dec  2 13:51:19 2018
    目的:混合蛙跳算法原理的简单实现
    问题:现有若干任务,并有若干台处理任务的机器,每台机器处理任务的速度不同
    找出最好的安排方案。
    比如任务长度有1,2,3的三个任务,
    而机器也有每单位时间可以处理的任务长度为1,2,3的三台机器,那么最优方案就是一一对应
    时间也只需要一个单位时间。
    
    @author: Administrator
    """
    
    import matplotlib.pyplot as plt
    import numpy as np
    import random
    import operator
    
    #适应度函数
    def F(plan):
        sum = []
        for i in range(d):
            sum.append(0)
        for i in range(d):
            if (plan[i]<0|plan[i]>nodes.__len__()):
                return 100
            sum[plan[i]] +=round(task[i]/nodes[plan[i]],3)   #任务学习的步长最大为3,因为只有三个节点
        sum.sort(reverse=True)
        return sum[0]
    
    #初始化
    task=[1,2,3,4,5,6,7,8,9]  #任务长度
    nodes=[1,2,3]   #节点
    
    #SFLA参数
    N=100    #种群数,有100中分配方案
    n=10     #子群中的青蛙数量,10个分配方案为一组
    d=task.__len__()     #解元素的个数
    m=N//n    #子群数量,共有10组
    L=5       #组内优化更新最差青蛙次数,组内优化的最差解的步数。
    G=100     #种群迭代次数
    D_max=10  
    P=[]
    
    #step1 生成蛙群,生成由0~2组成有9个元素的数组
    for i in range (N): 
        t=[[],0]         #t[[解],适应值]
        for j in range(d):
            t[0].append(random.randint(0,2))
        t[0]=np.array(t[0])
        t[1]=F(t[0])
        print(t[1])
        P.append(t)
    P.sort(key=operator.itemgetter(1))
    Xg=P[0]        #首个全局最优解
            
    for k in range(G): 
        #step2 划分子群
        M=[]
        for i in range(m):
            M.append([])    #1o个空的族群
        for i in range(N):
            M[i%m].append(P[i])   #i%10 0~9   P长度为100
        Xb=[]
        Xw=[]
        for i in range(m):
            Xb.append(M[i][0])
            Xw.append(M[i][M[i].__len__()-1])
    
    #step3 局部搜索
    for i in range(m):
        for j in range(L):
                D = random.randint(0,1)*(Xb[i][0]-Xw[i][0])  #Xb[i][0]是解空间
                temp = Xw[i][0]+D
                if(F(temp) < F(Xw[i][0])):
                    f = 0
                    Xw[i][0] = temp
                    Xw[i][1] = F(temp)             #最差解被替换
                    M[i][M[i].__len__()-1]=Xw[i]   #i族群中最后一是最差解,用新解替换
                else:
                    Xb[i] = Xg          #适应值没有变小,用全局最优替换局部最优
                    f=2  
                if(f==2):
                    t = [[], 0]
                    for j in range(d):
                        t[0].append(random.randint(0, 2))
                    t[0] = np.array(t[0])
                    t[1] = F(t[0])
                    Xw[i] = t
        P = []
        for i in range(m):
            for j in range(n):
                P.append(M[i][j])
     
        # sorted(P,key=lambda P:P[1])
        P.sort(key=operator.itemgetter(1))
        Xg = P[0]
        x=[]
        y=[]
        for i in range(P.__len__()):
            x.append(k)
            y.append(P[i][1])
        plt.scatter(x,y,s=5)
     
    print(P[0])
    plt.show()

你可能感兴趣的:(混合蛙跳算法原理与实现)