智能优化算法之禁忌搜索(Tabu Search, TS)

上图展示的是使用禁忌搜索算法解决电力系统孤岛问题。该问题旨在在发生严重扰动后将电力系统划分为几个不同的孤岛,目标是在将相关发电机放置在同一孤岛中并保持每个孤岛的连通性的同时,最小化所有孤岛的总发电负荷不平衡状态。

禁忌搜索(Tabu Search)是由Fred W. Glover在1986年提出的一种基于邻域搜索的元启发式算法。其发展历史可以追溯到20世纪80年代中期,当时Glover在研究组合优化问题时,提出了一种利用禁忌表来记录和避免循环路径的方法,从而跳出局部最优解的陷阱。禁忌搜索通过系统地探索解空间,不断改进当前解,并利用禁忌表防止回溯到先前的解。随着时间的推移,该算法在优化领域得到了广泛的应用和认可,被用于解决各种复杂的优化问题,如旅行商问题、调度问题、网络设计和其他组合优化问题,逐步发展成为一种重要的优化工具。

禁忌表(Tabu List)是禁忌搜索算法中的一个关键数据结构,用于记录最近一段时间内访问过的解或移动,防止搜索过程回到这些解或重复这些移动。禁忌表的引入旨在避免局部最优解陷阱和循环,从而促进更广泛的搜索空间探索。禁忌表具有一定的长度,超出长度的旧解或移动会被移除,使搜索过程动态适应问题的复杂性。通过在禁忌表中存储禁忌条件,可以有效地控制搜索路径,提高算法的全局优化能力。

数学原理

禁忌搜索的基本思想是通过在搜索过程中引入“禁忌表”(Tabu List),记录近期访问的解,并禁止这些解在一定时间内再次被访问,从而促进搜索空间的更广泛探索。其核心步骤如下:

  1. 初始解生成:随机生成一个初始解 。

  2. 邻域搜索:在当前解 的邻域中搜索最优解。

  3. 禁忌表更新:将当前解 加入禁忌表,并更新禁忌表的内容,保持禁忌表的长度不超过预设值。

  4. 解的接受准则:若找到的邻域解 比当前解 更优,则接受该解,否则检查其是否在禁忌表中,若不在禁忌表中也接受该解。

  5. 迭代停止条件:若达到预设的最大迭代次数或其他停止条件,则停止搜索,返回最优解。

邻域搜索公式

在禁忌搜索中,解的邻域通常通过一些局部操作生成。例如,对于旅行商问题,可以通过交换路径上的两个城市来生成邻域解。设当前解为 ,邻域解为 ,则有:

是通过一次交换操作得到的解

禁忌条件

禁忌条件是禁忌搜索的重要组成部分,用于避免搜索过程中的循环和局部最优解陷阱。若邻域解 在禁忌表中,则拒绝该解。禁忌条件通常表示为:

评价函数

评价函数用于衡量解的优劣,通常定义为目标函数值。设目标函数为 ,则对于解 ,其评价值为:

评价函数的具体形式取决于所要解决的问题。在旅行商问题中,目标函数通常是路径的总长度,目标是最小化这个长度。在其他优化问题中,目标函数可能是成本、时间或其他需要最小化或最大化的量。禁忌搜索通过不断优化评价函数的值,来寻找问题的最优解。

停止条件

禁忌搜索的停止条件可以是预设的最大迭代次数 或者目标函数值在若干迭代中未能显著改善等。

应用场景

禁忌搜索算法具有广泛的应用场景,主要包括但不限于以下领域:

  1. 旅行商问题(TSP):通过禁忌搜索优化城市巡回路径,寻找最短路径。

  2. 生产调度:用于制造业中的生产计划和调度优化,减少生产成本和时间。

  3. 图着色问题:优化图的着色方案,减少所需颜色数量。

  4. 组合优化问题:解决各种组合优化问题,如装箱问题、分配问题等。

  5. 网络路由:优化计算机网络和通信网络中的路由选择,提高网络效率。

Python 可视化实现

我们假设有一个排课问题,其中有4位教师(假设每位老师所有课程都可以教)、10门课程、4间教室,每周5天,每天有上午和下午两个时间段。通过禁忌搜索算法,生成无冲突的课程表,确保每门课程安排在不同的时间段和教室内,并使用Python进行可视化。

import numpy as np
import random
import matplotlib.pyplot as plt
import pandas as pd# 定义教师、课程、教室和时间段
teachers = ["Teacher A", "Teacher B", "Teacher C", "Teacher D"]
courses = ["Math", "English", "History", "Science", "Art", "Music", "PE", "Biology", "Chemistry", "Physics"]
rooms = ["Room 1", "Room 2", "Room 3", "Room 4"]
days = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"]
time_slots_per_day = ["Morning", "Afternoon"]
time_slots = [f"{day} {slot}" for day in days for slot in time_slots_per_day]# 生成初始解
def generate_initial_solution(teachers, courses, rooms, time_slots):solution = []for i, course in enumerate(courses):teacher = random.choice(teachers)room = random.choice(rooms)time_slot = time_slots[i % len(time_slots)]solution.append((course, teacher, room, time_slot))return solution# 评估解的优劣
def evaluate_solution(solution):conflicts = 0for i, (course1, teacher1, room1, time_slot1) in enumerate(solution):for j, (course2, teacher2, room2, time_slot2) in enumerate(solution):if i != j:if time_slot1 == time_slot2:if teacher1 == teacher2 or room1 == room2:conflicts += 1return conflicts# 生成邻域解
def generate_neighborhood(solution):neighborhood = []for i in range(len(solution)):for j in range(i + 1, len(solution)):neighbor = solution[:]neighbor[i], neighbor[j] = neighbor[j], neighbor[i]neighborhood.append(neighbor)return neighborhood# 禁忌搜索主循环
def tabu_search(teachers, courses, rooms, time_slots, num_iterations, tabu_tenure):current_solution = generate_initial_solution(teachers, courses, rooms, time_slots)best_solution = current_solution[:]best_score = evaluate_solution(best_solution)tabu_list = []for iteration in range(num_iterations):neighborhood = generate_neighborhood(current_solution)best_candidate = Nonebest_candidate_score = float('inf')for candidate in neighborhood:if candidate not in tabu_list:candidate_score = evaluate_solution(candidate)if candidate_score < best_candidate_score:best_candidate = candidatebest_candidate_score = candidate_scorecurrent_solution = best_candidate[:]tabu_list.append(current_solution)if len(tabu_list) > tabu_tenure:tabu_list.pop(0)if best_candidate_score < best_score:best_solution = best_candidate[:]best_score = best_candidate_scoreprint(f"Iteration {iteration + 1}/{num_iterations}, Best Score: {best_score}")return best_solution, best_score# 参数设置
num_iterations = 1000  # 增加迭代次数
tabu_tenure = 20  # 增加禁忌表长度# 求解学生课程安排问题
best_solution, best_score = tabu_search(teachers, courses, rooms, time_slots, num_iterations, tabu_tenure)# 可视化学生课程安排结果
def visualize_timetable(solution):timetable = pd.DataFrame(index=days, columns=time_slots_per_day)for course, teacher, room, time_slot in solution:day, slot = time_slot.split()timetable.at[day, slot] = f"{course}\n{teacher}\n{room}"fig, ax = plt.subplots(figsize=(12, 6))ax.set_axis_off()table = ax.table(cellText=timetable.values, colLabels=timetable.columns, rowLabels=timetable.index, cellLoc='center', loc='center', fontsize=14)table.auto_set_font_size(False)table.set_fontsize(12)table.scale(1.2, 1.2)  # 调整表格大小# 调整单元格高度for key, cell in table.get_celld().items():cell.set_height(0.15)plt.title("Student Timetable")plt.show()# 可视化最佳课程安排
visualize_timetable(best_solution)

最终结果:

以上内容总结自网络,如有帮助欢迎关注与转发,我们下次再见!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3245635.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

ARM架构(一)—— ARMV8V9基础概念

目录 1.ARMCore的时间线2.ARM术语小结2.1 A64和arrch642.2ARM架构现在的5个系列2.3 微架构2.4 PE2.5 Banked2.6 ARM文档术语2.7 IMPLEMENTATION DEFINFD 和 DEPRECATED2.8 EL1t和EL1h 3 ARMv7的软件架构4 安全状态切换模型4.1 Secure state和Non-secure state介绍 5 Interproce…

C++(week11): C++基础 第六章:关联式容器 set、map

文章目录 第六章&#xff1a;关联式容器1.set(1)set的特点(2)set的构造(3)set的查找操作 (set访问元素)(4)set的插入操作、pair(5)set的遍历 2.map(1)map的特点(2)map的构造(3)map的查找操作(4)map的插入操作(5)map的下标操作 &#xff08;重点&#xff09;(5)map的遍历 第六章…

入度与出度在数据结构中的应用

文章目录 应用案例1. 邻接矩阵2. 邻接链表3. 邻接集&#xff08;字典实现&#xff09;4. 入度列表&#xff08;基于邻接链表计算&#xff09; 特别补充3. 邻接集计算入度&#xff08;补充&#xff09;4. 邻接多重表&#xff08;概念介绍&#xff09; 入度和出度是图论中的概念&…

手机误删图片怎么办?2个照片恢复大师来帮忙,轻松找回

手机照片早已成为我们日常生活中的一部分&#xff0c;记录着欢笑、泪水等各种瞬间。但有时候&#xff0c;因为各种原因&#xff0c;它们会突然消失&#xff0c;让人痛心疾首。照片恢复有哪些方法呢&#xff1f;别急&#xff0c;今天就给大家带来2位照片恢复大师&#xff0c;它们…

【手写数据库内核组件】0501多线程并发模型,任务分发多工作者执行架构实现,多线程读写状态时volatile存储类型使用技巧

0501 多线程管理 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 0501 多…

[C++] 由浅入深理解面向对象思想的组成模块

文章目录 (一) 类的默认成员函数(二) 构造函数构造函数的特征构造函数示例无参构造带参构造 冲突:全缺省参数的构造函数与无参构造函数 &#xff08;三&#xff09;析构函数特性析构函数的析构过程解析 &#xff08;四&#xff09;拷贝构造函数什么是拷贝构造&#xff1f;特性为…

数据结构——单链表详解(超详细)(2)

前言&#xff1a; 上一篇文章小编简单的介绍了单链表的概念和一些函数的实现&#xff0c;不过为了保证文章的简洁&#xff0c;小编把它分成了两篇来写&#xff0c;这一篇小编紧接上一篇文章继续写单链表函数功能的实现&#xff1a; 目录&#xff1a; 1.单链表剩余函数的编写 1.…

MBR40150FCT-ASEMI无人机专用MBR40150FCT

编辑&#xff1a;ll MBR40150FCT-ASEMI无人机专用MBR40150FCT 型号&#xff1a;MBR40150FCT 品牌&#xff1a;ASEMI 封装&#xff1a;TO-220F 批号&#xff1a;最新 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;40A 最大循环峰值反向电压&#xff08;VRRM&a…

小程序-视图与逻辑

一、页面导航 声明式导航 编程式导航 导航传参 1.声明式导航传参 2.编程式导航传参 3.在onload中接收导航参数 二、页面事件 下拉刷新 上拉触底 三、生命周期 分类 生命周期函数分类 1.应用的生命周期函数 2.页面的生命周期函数 四、WXS脚本 基础语法 wxs的特点 五、案…

智能硬件——0-1开发流程

文章目录 流程图1. 市场分析具体分析 2. 团队组建2. 团队组建早期团队配置建议配置一&#xff1a;基础型团队 (4人)配置二&#xff1a;扩展型团队 (6人)配置三&#xff1a;全面型团队 (7人) 3. 产品需求分析4. ID设计&#xff08;Industrial Design, 工业设计&#xff09;5. 结…

MathType加载项被word禁用怎么办 MathType加载到Word不能用

Word中的MathType加载项是指将MathType软件与Word文档进行关联的一项功能。它允许用户在Word中直接使用MathType的功能&#xff0c;方便地输入和编辑数学公式等内容。通过加载项&#xff0c;MathType的强大数学公式编辑能力可以与Word的文档处理功能相结合&#xff0c;提高工作…

谷歌账号异常的常见8种状态,前三种有望立刻恢复,越往后越难(1)

生搬硬套列夫•托尔斯泰的一句话名言“幸福的家庭都是相似的,不幸的家庭各有各的不幸。” 工作、学习、娱乐中需要使用谷歌账号的朋友可能会发现&#xff0c;幸福的人就是谷歌账号一直都好好的&#xff0c;每次登陆都如所愿&#xff0c;丝滑无比。但是“不幸”的人就会发现&am…

【微信小程序知识点】自定义构建npm

在实际开发中&#xff0c;随着项目的功能越来越多&#xff0c;项目越来越复杂&#xff0c;文件目录也变得很繁琐&#xff0c;为了方便进行项目的开发&#xff0c;开发人员通常会对目录结构进行优化调整&#xff0c;例如&#xff1a;将小程序源码放到miniprogram目录下。 &…

电脑型号数据源的性能提升:新一代技术的突破

随着科技的不断发展&#xff0c;电脑型号的数据源性能也得到了显著的提升。新一代技术的突破使得电脑型号的数据源更加准确、全面且易于使用。本文将从代码的角度解释这一突破&#xff0c;并参考挖数据平台的内容&#xff0c;向大家介绍电脑型号数据源的性能提升。 首先&#…

【scrapy】——个人笔记

scrapy简介 Scrapy&#xff0c;Python开发的一个快速、高层次的屏幕抓取和web抓取框架&#xff0c;用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛&#xff0c;可以用于数据挖掘、监测和自动化测试。 Scrapy吸引人的地方在于它是一个框架&#xff0c;任何人都可…

HEVC编码中的MPM(最可能模式,Most Probable Mode)

简介 最近看到有文章用视频编码时的MPM参数来映射特征并用于数字取证&#xff0c;故做该文章记录。 HEVC&#xff08;高效视频编码&#xff09;中的MPM&#xff08;最可能模式&#xff0c;Most Probable Mode&#xff09;用于预测帧内块的模式&#xff0c;以提高编码效率并减…

【python】PyQt5的窗口界面的各种交互逻辑实现,轻松掌控图形化界面程序

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

【ABB】示教器可编程按钮的配置

【ABB】示教器可编程按钮的配置 操作流程演示 操作流程 首先我要配置的是如图所示控制器上的四个按钮&#xff0c;这四个按钮是可以自定义功能的。 点击【菜单】点击【Control Panel】点击【ProgKeys】即可配置对应按键功能 演示 点击【菜单】 点击【配置可编程按键】 这里…

12306高铁票如何打印电子发票?

高铁票报销凭证电子版如何打印&#xff1f; 高铁票报销目前没有电子发票形式&#xff0c;只有纸质版报销凭证&#xff0c;不过虽然没有电子版报销凭证&#xff0c;但是可以通过多种方式获取纸质版报销凭证。 报销凭证只能打印一次&#xff0c;丢失不能补打&#xff0c;请妥善…

cpp 强制转换

一、static_cast static_cast 是 C 中的一个类型转换操作符&#xff0c;用于在类的层次结构中进行安全的向上转换&#xff08;从派生类到基类&#xff09;或进行不需要运行时类型检查的转换。它主要用于基本数据类型之间的转换、对象指针或引用的向上转换&#xff08;即从派生…