五、python实现人工蜂群算法(简单明了版)

一、概述

  人工蜂群算法(Artificial Bee Colony Algorithm, 简称ABC算法)是一个由蜂群行为启发的算法,在2005年由Karaboga小组为优化代数问题而提出。方法人工蜂群算法是模仿蜜蜂行为提出的一种优化方法,是集群智能思想的一个具体应用,它的主要特点是不需要了解问题的特殊信息,只需要对问题进行优劣的比较,通过各人工蜂个体的局部寻优行为,最终在群体中使全局最优值突现出来,有着较快的收敛速度。
  CSDN大佬有相关算法人工蜂群算法python实现,大佬大量采用了面对对象编程,读了几遍,本来挺明白的,彻底就糊涂了,因此不敢苟同。本文章代码经过个人反复思考,简单明了。

二、算法原理

  人工蜂群算法网上教程比较多,我就不再抄书了,推荐大家读一下简书大佬的讲解人工蜂群算法。我和他的观点一致,蜜蜂之间如何转换,按照何种策略从侦查蜂中选择采蜜蜂等等,对算法的性能和结果影响都不大。基于这个思考,在编程中,我们着重关注蜜源,就可以清晰明了的理清楚思绪,并完成相关算法。

三、python实现

# 定义待优化函数
def function(position):
    x = position[0]
    y = position[1]
    # 待优化函数表达式
    z = -20*np.exp(-0.2*np.sqrt((x**2+y**2)/2))- \
        np.exp((np.cos(2*np.pi*x)+np.cos(2*np.pi*y))/2)+20+np.e
    return z

  我们可以先看一下这个函数的图形。

bounds = np.array([[-10, -10], [10, 10]])
x = np.linspace(bounds[0, 0], bounds[1, 0], 1000)
y = np.linspace(bounds[0, 1], bounds[1, 1], 1000)
X,Y=np.meshgrid(x,y)
Z = -20*np.exp(-0.2*np.sqrt((X**2+Y**2)/2))-np.exp((np.cos(2*np.pi*X)+np.cos(2*np.pi*Y))/2)+20+np.e
fig=plt.figure()
ax=plt.axes(projection='3d')
ax.plot_surface(X,Y,Z,cmap='rainbow')
plt.show()

在这里插入图片描述
  我们主要定义一下蜜源以及蜜源的评价体系。记住每个蜜源对应一个引导蜂(也有叫雇佣蜂的),同时它在搜寻新蜜源的时候称为侦查蜂,其余的全是雇佣蜂。这些蜜蜂怎么飞怎么转换,不要去关注,没有意义。

# 定义蜜源
class Nectar:
    # 初始化
    def __init__(self, position):
        # 蜜源位置
        self.position=position
        # 采蜜者数量(包含引领蜂)
        self.follower_counts = 1
        # 历史采蜜者数量
        self.counts_history = 1
    
    # 跟随蜂采蜜则增加采蜜者数量
    def add_Followers(self):
        self.follower_counts += 1
    
    # 放弃采蜜
    def cal_give_up_rate(self):
        self.give_up_rate = self.counts_history / self.follower_counts - 1
        return self.give_up_rate
        
    # 更新蜜源(flag=True,代表蜜源位置更新)
    def refresh(self, flag=True):
        # 如位置不更新,需保存前一次采蜜者数量
        if ~flag:
            self.counts_history = self.follower_counts
        # 重置该蜜源采蜜者数量
        self.follower_counts = 1
        
# 蜜源评价及更新
class Evaluate:
    
    def __init__(self, function):
        self.function = function
  
    # 待优化函数
    def cal_function(self, position):
        z = self.function(position)
        return z
    
    # 计算适应度值
    def cal_fitness(self, nectar_group):
        # 计算函数值
        values = [self.cal_function(_nectar.position) for _nectar in nectar_group]
        # 计算适应度函数
        fitness = [(_value>0) and (1/(1+_value)) or (1+np.abs(_value)) 
                  for _value in values]
        return fitness
    
    # 计算各蜜源被选中的概率
    def cal_possibility(self, nectar_group):
        # 计算适应度函数
        fitness = self.cal_fitness(nectar_group)
        possibility = [_fitness/np.sum(fitness) for _fitness in fitness]
        return possibility
    
    # 蜜源吸引跟随蜂
    def evaluate_nectar_grop(self, nectar_group, number_flowers):
        # 计算各蜜源被选中的概率
        possibility = evaluate.cal_possibility(nectar_group)
        # 跟随蜂开始工作
        for i in range(number_flowers):
            poss = 0
            # 生成随机数
            rand_poss = np.random.random()
            # 跟随蜂随机进入蜜源开始采蜜
            for i, _poss in enumerate(possibility):
                poss += _poss
                if poss > rand_poss:
                    # 蜜源跟随蜂数量增加
                    nectar_group[i].add_Followers()
        return nectar_group

  以下是主程序,代码中未关注蜜蜂是如何飞来飞去的,因为真的不重要。建议大家对照着算法看代码,简单明了。

if __name__ == '__main__':
    # 定义蜂群规模
    bee_population = 100
    # 定义引领蜂比例
    guider_rate = 0.3
    # 定义搜索次数
    iteration = 100
    # 定义搜寻范围
    bounds = np.array([[-10, -10], [10, 10]])
    # 初始化蜜源以及引领蜂位置
    init_position = np.random.uniform(low=bounds[0,:], high=bounds[1,:], 
                                      size=(int(bee_population*guider_rate), bounds.shape[1]))
    # 定义蜜源初始位置
    nectar_group = []
    for _position in init_position:
        # 引领蜂找到蜜源
        _nectar = Nectar(_position)
        # 将该蜜源加入蜜源大家庭
        nectar_group.append(_nectar)
        
    # 向蜜源传入待优化函数
    func = function
    evaluate = Evaluate(func)
    
    # 开始进入循环
    _iteration = 0
    while _iteration != iteration:
        # 跟随蜂开始选择蜜源
        nectar_group = evaluate.evaluate_nectar_grop(nectar_group, 
                                                    bee_population - len(nectar_group))    
        # 引领蜂开始工作
        for i,_nectar in enumerate(nectar_group):
            # 若该蜜源无跟随蜂,引领蜂需寻找下一个蜜源
            flag1 = _nectar.follower_counts == 1
            # 若该蜜源在上一轮被跟随蜂放弃的概率大于50%,引领蜂需寻找下一个蜜源
            flag2 = _nectar.cal_give_up_rate() > 0.5
            # 此外,引领蜂有30%的概率,不安于现状,开始搜索新的蜜源
            flag3 = np.random.random() <= 0.3
            if((flag1 | flag2) | flag3):
                # 计算该蜜源函数值
                z = evaluate.cal_function(_nectar.position)
                # 引领蜂连续搜索30次
                search_count = 0
                while search_count != 30:
                    # 搜索新的蜜源
                    rand_nectar = np.random.choice(nectar_group)
                    new_position = _nectar.position + np.random.random()*\
                                    (rand_nectar.position - _nectar.position)
                    # 计算新蜜源的函数值
                    new_z = evaluate.cal_function(new_position)
                    # 若新蜜源函数值更小,则替换最优值
                    good_z, good_position = (new_z < z) and \
                                            (new_z, new_position) or (z, _nectar.position)
                    search_count += 1
                # 若搜索30次后发现更好的蜜源则进行蜜源替换
                if good_z < z:
                    _nectar.position = good_position
                    _nectar.refresh(flag = True)
                # 若未替换蜜源,对蜜源内的跟随蜂数量置零
                else:
                    _nectar.refresh(flag = False)
        _iteration += 1
        # 展示迭代过程
        if _iteration % 10 == 0:      
            position_group = [_nectar.position for _nectar in nectar_group]
            position_group = np.array(position_group).flatten().reshape([-1, 2])
            plt.scatter(position_group[:,0], position_group[:,1])
            plt.xlim((-10,10))
            plt.ylim((-10,10))
            plt.show()

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

白银时代_

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

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

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

打赏作者

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

抵扣说明:

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

余额充值