启发式算法/人工蜂群算法
2022/3/19 11:29:32
本文主要是介绍启发式算法/人工蜂群算法,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
原理
介绍:
- limit:采蜜蜂蜜源被跟随蜂选择一定次数后蜜源质量仍然低于跟随蜂蜜源把这些采蜜蜂变成工蜂
- num:固定保留+随机保留采蜜蜂之后剩余的采蜜蜂数量
分工:
- 工蜂负责采蜜
- 侦查蜂负责在田野里寻找蜜源(全局搜索)
- 采蜜蜂负责保留蜜源信息和招募跟随蜂
- 跟随蜂负责在它选择的采蜜蜂周围寻找新蜜源(局部搜索)
过程
- 开始大家都是工蜂
- 派出一部分工蜂作为侦查蜂,在田野里寻找蜜源
- 蜜源平均质量以上的侦查蜂变采蜜蜂,平均质量一下的侦查蜂变工蜂
- 采蜜蜂跳舞招募跟随蜂(从工蜂中派出一部分工蜂作为跟随蜂)在采蜜蜂蜜源周围寻找新蜜源
- 如果跟随蜂找到的新蜜源质量比采蜜蜂好,跟随蜂变成采蜜蜂,后面可以去招募跟随蜂;跟随蜂蜜源质量好于原采蜜蜂,采蜜蜂蜜源被跟随蜂选择一定次数后蜜源质量仍然低于跟随蜂蜜源把这些采蜜蜂变成工蜂
轮盘赌算法:
代码
采蜜步骤:
- 初始化种群,全部是工蜂
- 开始迭代
- 派出侦查蜂,侦查蜂占工蜂10%~20%
- 蜜源平均质量以上的侦查蜂变采蜜蜂,平均质量一下的侦查蜂变工蜂
- 采蜜蜂招募跟随蜂,跟随蜂占工蜂10%~20%
- 跟随蜂轮盘赌选择采蜜蜂蜜源,在选择的采蜜蜂蜜源周围寻找新蜜源
- 如果跟随蜂找到的新蜜源质量比采蜜蜂好,跟随蜂变成采蜜蜂,后面可以去招募跟随蜂;跟随蜂蜜源质量好于原采蜜蜂,采蜜蜂蜜源被跟随蜂选择一定次数后蜜源质量仍然低于跟随蜂找到的新蜜源把这些采蜜蜂变成工蜂
- 保存此次迭代结果
- 固定保留(%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)
这篇关于启发式算法/人工蜂群算法的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-10-06小米11i印度快充版ROM合集:极致体验,超越期待
- 2024-10-06【ROM下载】小米11i 5G 印度版系统, 疾速跃迁,定义新速度
- 2024-10-06【ROM下载】小米 11 青春活力版,青春无极限,活力全开
- 2024-10-05小米13T Pro系统合集:性能与摄影的极致融合,值得你升级的系统ROM
- 2024-10-01基于Python+Vue开发的医院门诊预约挂号系统
- 2024-10-01基于Python+Vue开发的旅游景区管理系统
- 2024-10-01RestfulAPI入门指南:打造简单易懂的API接口
- 2024-10-01初学者指南:了解和使用Server Action
- 2024-10-01Server Component入门指南:搭建与配置详解
- 2024-10-01React 中使用 useRequest 实现数据请求