python 实现布谷鸟算法(CS)

在网上搜索没有发现比较完整用Python写的CS算法,只能自己动手编写一个。

CS算法注意事项:

1.执行流程是,初始化 -> levy飞行变换巢穴位置 -> 与之前的巢穴对比保留好的巢穴 -> 按照发现概率值丢弃部分巢穴重新生成 ->

-> 再与之前的巢穴对比保留好的巢穴 ->判断循环是否结束 ->  …………

2.levy飞行步长的计算通常是使用Mantegna方法模拟二维平面莱维飞行

3.迭代公式中大量涉及随机数,需要注意的是一部分是服从均匀分布,还有部分是服从正态分布

4.编写可以参照yang的matlab代码源代码(参考的链接中包含源代码)

Python代码如下:

公式就不写了,可以参考链接。

from random import uniform
from random import randint
import math
import numpy as np
import matplotlib.pyplot as plt
'''
根据levy飞行计算新的巢穴位置
'''
def GetNewNestViaLevy(Xt,Xbest,Lb,Ub,lamuda):
    beta = 1.5
    sigma_u = (math.gamma(1 + beta) * math.sin(math.pi * beta / 2) / (
                math.gamma((1 + beta) / 2) * beta * (2 ** ((beta - 1) / 2)))) ** (1 / beta)
    sigma_v = 1
    for i in range(Xt.shape[0]):
        s = Xt[i,:]
        u = np.random.normal(0, sigma_u, 1)
        v = np.random.normal(0, sigma_v, 1)
        Ls = u / ((abs(v)) ** (1 / beta))
        stepsize = lamuda*Ls*(s-Xbest)   #lamuda的设置关系到点的活力程度  方向是由最佳位置确定的  有点类似PSO算法  但是步长不一样
        s = s + stepsize * np.random.randn(1, len(s))  #产生满足正态分布的序列
        Xt[i, :] = s
        Xt[i,:] = simplebounds(s,Lb,Ub)
    return Xt
'''
按pa抛弃部分巢穴
'''
def empty_nests(nest,Lb,Ub,pa):
    n = nest.shape[0]
    nest1 = nest.copy()
    nest2 = nest.copy()
    rand_m =pa - np.random.rand(n,nest.shape[1])
    rand_m = np.heaviside(rand_m,0)
    np.random.shuffle(nest1)
    np.random.shuffle(nest2)
    # stepsize = np.random.rand(1,1) * (nest1 - nest)
    stepsize = np.random.rand(1,1) * (nest1 - nest2)
    new_nest = nest + stepsize * rand_m
    nest = simplebounds(new_nest,Lb,Ub)
    return nest
'''
获得当前最优解
'''
def get_best_nest(nest, newnest,Nbest,nest_best):
    fitall = 0
    for i in range (nest.shape[0]):
        temp1 = fitness(nest[i,:])
        temp2 = fitness(newnest[i,:])
        if temp1 > temp2:
            nest[i, :] = newnest[i,:]
            if temp2 < Nbest :
                Nbest = temp1
                nest_best = nest[i,:]
            fitall = fitall + temp2
        else:
            fitall = fitall + temp1
    meanfit = fitall/nest.shape[0]
    return  nest , Nbest , nest_best ,meanfit

'''
进行适应度计算
'''
def fitness(nest_n):
    X = nest_n[0]
    Y = nest_n[1]
    # Ackley函数
    Z = -20 * np.exp(-0.2 * np.sqrt(0.5 * (X ** 2 + Y ** 2))) - \
        np.exp(0.5 * (np.cos(2 * np.pi * X) + np.cos(2 * np.pi * Y))) + np.e + 20


    return Z
'''
进行全部适应度计算
'''
def fit_function(X,Y):
    # rastrigin函数
    A = 10
    Z = 2 * A + X ** 2 - A * np.cos(2 * np.pi * X) + Y ** 2 - A * np.cos(2 * np.pi * Y)
    return Z
'''
约束迭代结果
'''
def simplebounds(s,Lb,Ub):
    for i in range(s.shape[0]):
        for j in range(s.shape[1]):
            if s[i][j] < Lb[j]:
                s[i][j] = Lb[j]
            if s[i][j] > Ub[j]:
                s[i][j] = Ub[j]
    return s

def Get_CS(lamuda = 1,pa =0.25):
    Lb=[-5,-5] #下界
    Ub=[5,5]   #上界
    population_size = 20
    dim = 2
    nest= np.random.uniform(Lb[0], Ub[0],(population_size,dim))  # 初始化位置
    nest_best = nest[0,:]
    Nbest =fitness(nest_best)
    nest ,Nbest, nest_best ,fitmean = get_best_nest(nest,nest,Nbest,nest_best)
    for i in range (30):
        nest_c = nest.copy()
        newnest = GetNewNestViaLevy(nest_c, nest_best, Lb, Ub,lamuda) # 根据莱维飞行产生新的位置

        nest,Nbest, nest_best ,fitmean = get_best_nest(nest, newnest,Nbest, nest_best) # 判断新的位置优劣进行替换

        nest_e = nest.copy()
        newnest = empty_nests(nest_e,Lb,Ub,pa) #丢弃部分巢穴

        nest,Nbest, nest_best ,fitmean = get_best_nest(nest,newnest, Nbest, nest_best)  # 再次判断新的位置优劣进行替换

    print("最优解的适应度函数值",Nbest)
    return  Nbest
Get_CS()

代码如果需要使用的话,建议仔细检查,虽然我检查没有发现问题。有不对的地方欢迎指正。

参考:

https://blog.csdn.net/zyqblog/article/details/80905019

https://vlight.me/2017/12/17/Cuckoo-Search/

文献:动态适应布谷鸟搜索算法  《控制与策略》 2014年  

 

点赞