编程语言
首页 > 编程语言> > 启发式算法/人工蜂群算法

启发式算法/人工蜂群算法

作者:互联网

原理

在这里插入图片描述
介绍:

分工:

过程

轮盘赌算法:
在这里插入图片描述

代码

采蜜步骤:

  1. 初始化种群,全部是工蜂
  2. 开始迭代
  3. 派出侦查蜂,侦查蜂占工蜂10%~20%
  4. 蜜源平均质量以上的侦查蜂变采蜜蜂,平均质量一下的侦查蜂变工蜂
  5. 采蜜蜂招募跟随蜂,跟随蜂占工蜂10%~20%
  6. 跟随蜂轮盘赌选择采蜜蜂蜜源,在选择的采蜜蜂蜜源周围寻找新蜜源
  7. 如果跟随蜂找到的新蜜源质量比采蜜蜂好,跟随蜂变成采蜜蜂,后面可以去招募跟随蜂;跟随蜂蜜源质量好于原采蜜蜂,采蜜蜂蜜源被跟随蜂选择一定次数后蜜源质量仍然低于跟随蜂找到的新蜜源把这些采蜜蜂变成工蜂
  8. 保存此次迭代结果
  9. 固定保留(%20到50%)最好采蜜蜂,随机保留剩下(10%到20%)采蜜蜂,其余蜜蜂变工蜂
import numpy as np
import matplotlib
import matplotlib.pyplot as plt
from enum import Enum

matplotlib.rcParams['font.family'] = 'STSong'
matplotlib.rcParams['font.size'] = 10


def fitness_F1(x):
    """
    F1函数
    :param x: 粒子当前位置 一个解4维
    :return: 适应度
    """
    return -np.sum(x ** 2) + 900


class Role(Enum):
    """
    角色枚举
    """
    WORKER = 0
    SCOUT = 1
    PICKER = 2
    FOLLOWER = 3


class BeeWorker(object):
    """
    工蜂
    """

    def __init__(self, id, x=None, role=Role.WORKER):
        """
        初始化方法
        :param: id: 唯一标识
        :param: x: 蜜源位置
        :param: role: 工蜂角色(工蜂,侦查蜂,采蜜蜂,跟随蜂)
        """
        self.__id = id
        self.__x = x
        self.__role = role

    def set_id(self, id):
        """
        setter id
        :return:
        """
        self.__id = id

    def get_id(self):
        """
        getter id
        :return:
        """
        return self.__id

    def set_role(self, role):
        """
        设置角色
        :param role:
        :return: self
        """
        self.__role = role
        return self

    def get_role(self):
        """
        getter
        :return:
        """
        return self.__role

    def set_x(self, x):
        """
        setter x
        :return:
        """
        self.__x = x

    def get_x(self):
        """
        获取x
        :return:
        """
        return self.__x


class ArtificialBeeColonyAlgorithm(object):
    """
    算法
    """

    def __init__(self, iter_num, fitness_end, x_min, x_max, NP, D, limit):
        """
        初始化方法
        :param iter_num: 迭代次数
        :param fitness_end: 截止适应度
        :param x_min: 下界
        :param x_max: 上界
        :param NP: 工蜂数量
        :param D: 蜜源位置维度
        :param limit: 蜜源保留次数
        """
        # 截止条件
        self.iter_num = iter_num
        self.fitness_end = fitness_end
        # 解空间
        self.x_min = x_min
        self.x_max = x_max
        # 求解者
        self.NP = NP
        self.D = D
        self.beeWorkers = None
        # 算法参数
        self.limit = limit
        # 蜂巢保存最好蜜源
        self.fitness_list = []

    def initilize_pop(self):
        """
        种群初始化
        :return:
        """
        # 初始化种群
        # todo bee  worker
        self.beeWorkers = [BeeWorker(i, role=Role.WORKER) for i in range(self.NP)]

    def gather(self):
        """
        采蜜
        :param: beeWorker 工蜂
        :return:
        """
        workers = [bee for bee in self.beeWorkers if bee.get_role() == Role.WORKER]
        beeid_limit = {worker.get_id(): 0 for worker in workers}  # dict生成式
        for it in range(self.iter_num):
            # 侦查蜂
            ## 侦查蜂占工蜂10%~20%
            workers = [bee for bee in self.beeWorkers if bee.get_role() == Role.WORKER]
            num_worker = len(workers)
            rs = np.random.uniform(0.1, 0.2, 1)  # 范围随机数
            num_scout = int(num_worker * rs)
            ## 工蜂变成侦查蜂
            scouts = [bee.set_role(Role.SCOUT) for bee in workers[:num_scout]]
            ## 侦查蜂全局搜索蜜源
            pop_scout = np.random.uniform(self.x_min, self.x_max, (num_scout, self.D))
            for i in range(0, num_scout):
                scouts[i].set_x(pop_scout[i])
            ## 侦查蜂适应度好于平均适应度变采蜜蜂,坏于变工蜂
            fit_scouts = np.array([fitness_F1(scout.get_x()) for scout in scouts])
            fit_avg = np.average(fit_scouts)
            for scout in scouts:
                if fitness_F1(scout.get_x()) >= fit_avg:
                    scout.set_role(Role.PICKER)
                else:
                    scout.set_role(Role.WORKER)
            # 跟随蜂
            workers = [bee for bee in self.beeWorkers if bee.get_role() == Role.WORKER]
            num_worker = len(workers)
            ## 跟随蜂占工蜂10%~20%
            rf = np.random.uniform(0.1, 0.2, 1)  # 范围随机数
            num_follower = int(num_worker * rf)
            followers = [worker.set_role(Role.FOLLOWER) for worker in workers[:num_follower]]
            pickers = [bee for bee in self.beeWorkers if bee.get_role() == Role.PICKER]
            ## 跟随蜂 局部搜索蜜源
            for i in range(num_follower):
                ## 轮盘赌选择跟随采蜜蜂
                sum_fit = np.sum([fitness_F1(one.get_x()) for one in pickers])
                p_fits = [fitness_F1(one.get_x()) / sum_fit for one in pickers]
                p_cumsum = np.array(p_fits).cumsum()  # np累计求和
                p_cumsum_1 = np.copy(p_cumsum)  # 深拷贝
                r1 = np.random.random()
                p_cumsum_1 -= r1
                picker1 = pickers[list(p_cumsum_1 > 0).index(True)]  # 返回第1个大于0的索引
                p_cumsum_2 = np.copy(p_cumsum)
                r2 = np.random.random()
                p_cumsum_2 -= r2
                picker2 = pickers[list(p_cumsum_2 > 0).index(True)]
                rr = np.random.random((self.D,))
                follower_x_temp = np.array(picker1.get_x()) + (
                        np.array(picker1.get_x()) - np.array(picker2.get_x())) * rr
                ## 防止越界
                follower_x = np.clip(follower_x_temp, self.x_min, self.x_max)
                ## 跟随蜂蜜源 好于 采蜜蜂蜜源,跟随蜂变采蜜蜂,采蜜蜂变工蜂;跟随蜂蜜源 坏于 采蜜蜂蜜源,跟随蜂变工蜂;
                if fitness_F1(follower_x) <= fitness_F1(picker1.get_x()):
                    followers[i].set_role(Role.WORKER)
                    num_follower -= 1
                    continue
                if fitness_F1(follower_x) <= fitness_F1(picker2.get_x()):
                    followers[i].set_role(Role.WORKER)
                    num_follower -= 1
                    continue
                followers[i].set_role(Role.PICKER)
                followers[i].set_x(follower_x)
                num_follower -= 1
                # 跟随蜂蜜源好于采蜜蜂蜜源limit次 采蜜蜂变为工蜂(丢弃蜜源)
                if beeid_limit[picker1.get_id()] > self.limit:
                    picker1.set_role(Role.WORKER)
                else:
                    beeid_limit[picker1.get_id()] = beeid_limit[picker1.get_id()] + 1
                pass
                if beeid_limit[picker2.get_id()] > self.limit:
                    picker2.set_role(Role.WORKER)
                else:
                    beeid_limit[picker2.get_id()] = beeid_limit[picker2.get_id()] + 1
                pass

            # 保存结果
            pickers = [bee for bee in self.beeWorkers if bee.get_role() == Role.PICKER]
            x_pickers = np.array([picker.get_x() for picker in pickers])
            fit_pickers = np.array([fitness_F1(picker.get_x()) for picker in pickers])
            fit_max_picker = np.max(fit_pickers)
            x_max_picker = x_pickers[np.argmax(fit_pickers)]
            self.fitness_list.append(fit_max_picker)
            print('第', it + 1, '迭代', ',蜜源位置:', x_max_picker, ',最佳适应度:', self.fitness_list[-1])
            # 截止条件
            if self.fitness_end < fit_max_picker:
                break
            pass
            # 固定保留(%20~50%)最好采蜜蜂,随机保留剩下(10%~20%)采蜜蜂,其余蜜蜂变工蜂
            pickers.sort(key=lambda picker: fitness_F1(picker.get_x()))  # lambda param: return expression
            len_p = len(pickers)
            rp = np.random.uniform(0.2, 0.5, 1)
            num_fix = int(len_p * rp)
            pickers_rest = pickers[:-int(num_fix)]
            np.random.shuffle(pickers_rest)
            len_pr = len(pickers_rest)
            rpr = np.random.uniform(0.1, 0.2, 1)
            num_retain = int(len_pr * rpr)
            picker_workers = pickers_rest[num_retain:]
            for pw in picker_workers: pw.set_role(Role.WORKER)
            pickers = [bee for bee in self.beeWorkers if bee.get_role() == Role.PICKER]
            np.random.shuffle(pickers)
            print("采蜜蜂数量:", len(pickers))
        pass
        return x_max_picker, self.fitness_list

    def show(self, x_best, fitness_list):
        """
        展示迭代过程
        :param x_best: 最优解
        :param fitness_list: 每次迭代适应度值
        :return:
        """
        print("最优解:", str(x_best))
        print("最优适应度:", str(fitness_list[-1]))

        plt.title("迭代过程")
        plt.xlabel("迭代次数")
        plt.ylabel("适应度")
        x = range(1, len(fitness_list) + 1)
        y = fitness_list
        plt.plot(x, y, label="ABC")
        plt.legend()
        plt.show()


if __name__ == "__main__":
    abc = ArtificialBeeColonyAlgorithm(100, 900, -30, 30, 1000, 3, 6)
    abc.initilize_pop()
    x_best, fitness_list = abc.gather()
    abc.show(x_best, fitness_list)

标签:蜂群,蜜源,get,self,np,算法,蜜蜂,启发式,role
来源: https://blog.csdn.net/baidu_35805755/article/details/123588580