一、原理
在一块湿地,有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表示青蛙个体允许改变的最大步长
- a.如果 在可行的空间内,计算新的适应值(目标值f(Pw’)),新的f(Pw’)比旧的f(Pw)好,用新的Pw’ 替换Pw。
- 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 - c. 审查制度
如果新位置是不可行的,或者没有比旧的位置好,那么有缺陷的模因的传播就会被随机生成一个新的青蛙r在一个可行的位置上,以取代新位置不适合进步的青蛙。
不管执行了以上三次跳跃(a,b,c三次跳)中的任何一次,需重新计算本子群的最优个体Pb和最差个体Pw。
-
[Step4-4]
如果iN<LS,则转到步骤4-3。 -
[Step4-5]
如果im<m,则转到步骤4-2,否则转到全局搜索过程的step5。 -
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()