当前位置: 首页 > news >正文

FJSP 入门与 NSGA-II 实践:从问题到代码

FJSP 入门与 NSGA-II 实践:从问题到代码

这篇博客面向入门学习者,先介绍 FJSP(柔性车间调度)问题,再说明 NSGA-II 多目标进化算法,最后结合本项目代码,梳理如何完成求解与可视化。

项目代码地址:https://github.com/aslongaslihappy/NSGA-II-FJSP


1. FJSP 是什么

FJSP(Flexible Job Shop Scheduling Problem,柔性车间调度)是经典调度问题的扩展。
与传统车间调度不同,FJSP 允许每道工序在多台机器中选择一台进行加工,因此具有更强的灵活性,但也带来更高的搜索复杂度。

1.1 基本元素

  • 工件(Job):由多道工序组成
  • 工序(Operation):工件必须按顺序加工的步骤
  • 机器(Machine):每道工序可选的加工设备集合

1.2 典型约束

  • 同一台机器同一时间只能加工一道工序
  • 同一工件的工序必须遵循先后顺序

1.3 常见优化目标(多目标)

FJSP 通常是多目标优化问题,本项目关注两类目标:

  • Makespan(完工时间):所有工件完成的总时间
  • TEC(总能耗):加工能耗 + 机器空闲能耗

由于目标之间相互冲突,实际求解的是Pareto 最优解集合,即一组“互不支配”的解。


2. NSGA-II 简介

NSGA-II(Non-dominated Sorting Genetic Algorithm II)是经典的多目标进化算法,核心思想是:

  1. 非支配排序:将解分层,第一层是最优的非支配解
  2. 拥挤度距离:衡量解在目标空间的稀疏程度,保证多样性
  3. 精英保留:父代与子代合并后再选择

2.1 算法流程(简述)

  1. 初始化种群
  2. 计算目标函数(多目标)
  3. 非支配排序 + 拥挤度
  4. 二元锦标赛选择
  5. 交叉、变异产生子代
  6. 环境选择得到新种群
  7. 重复迭代,得到 Pareto 前沿

3. 本项目如何解决 FJSP

项目实现了 NSGA-II + FJSP 的完整流程,关键模块如下:

main.py src/ algorithms/ GA.py decode.py initialization.py selection.py crossover.py mutation.py sorting.py utils/ data.py performance _test.py

下面按求解流程梳理代码思路。


3.1 数据读取(src/utils/data.py)

data.py支持两种格式:

  • *.txt(优先读取)
  • *.fjs

读取结果返回:

  • work:记录每个工序属于哪个工件
  • Tmachinetime:每道工序的可选机器与加工时间

这为后续编码、解码提供基础数据。


3.2 编码设计(OS/MS 双层编码)

项目使用经典的OS/MS 双层编码

  • OS(Operation Sequence):全局工序加工顺序
  • MS(Machine Selection):每道工序选择哪台机器

这样可以同时表达“工序顺序”和“机器选择”两个维度,适合 FJSP 的可行解表示。


3.3 初始化、交叉与变异

主要在src/algorithms/initialization.pycrossover.pymutation.py中完成:

  • 初始化生成随机可行的 OS/MS
  • 交叉算子:例如 POX、UX
  • 变异算子:改变工序顺序或机器选择

这些操作负责探索更广的解空间。


3.4 目标函数与解码(src/algorithms/decode.py)

解码模块负责把 OS/MS 转换为可执行调度,并计算目标函数:

  1. 根据工件顺序和机器资源安排开始/结束时间
  2. 计算 Makespan
  3. 计算 TEC(加工能耗 + 空闲能耗)
  4. 可选绘制甘特图并保存结果

关键输出是一个形如[C_max, TEC]的目标向量。


3.5 NSGA-II 主流程(src/algorithms/GA.py)

GA.py是核心:

  • binary_tournament_selection:二元锦标赛选择
  • fast_non_dominated_sort:非支配排序
  • calculate_crowding_distance:拥挤度距离
  • environment_selection:环境选择保留精英

主循环:

  1. 初始化种群
  2. 交叉与变异生成子代
  3. 计算子代目标函数
  4. 合并父代与子代,进行非支配排序
  5. 用拥挤度距离选择下一代

最终输出:

  • Pareto 前沿解集
  • 最佳个体(用于甘特图绘制)

3.6 主入口(main.py)

main.py负责串联所有模块:

  1. 读取数据
  2. 初始化解码器与 GA
  3. 设置迭代次数或 CPU 时间限制
  4. 调用ga.total()得到结果
  5. 输出 Pareto 前沿并绘制甘特图

4. 结果与可视化

项目输出主要包括:

  • 甘特图:展示具体调度方案
  • Pareto 前沿图:展示多目标权衡结果

这些图像被保存在results/目录下,适合用于论文或实验报告。


5. 小结

本项目的实现路径是:
数据读取 → OS/MS 编码 → NSGA-II 进化 → 解码与多目标计算 → 可视化输出

对入门者来说,建议阅读顺序:

  1. main.py(了解整体流程)
  2. GA.py(理解 NSGA-II 主循环)
  3. decode.py(理解目标函数与调度解码)

如果想进一步提升效果,可尝试:

  • 引入局部搜索(如 VNS)
  • 自适应交叉与变异概率
  • 更真实的能耗模型
http://www.jsqmd.com/news/699312/

相关文章:

  • 基于Docker的AI模型可视化部署平台Microverse设计与实践
  • 宿州视力检查大揭秘:靠谱机构全攻略 - 品牌测评鉴赏家
  • 2026届最火的六大AI辅助论文方案解析与推荐
  • 微信机器人搭建指南:5分钟实现消息自动化处理
  • 如何通过事件委托提升uPlot图表的渲染性能:完整指南
  • 盘点那些大众/小众的windows远程控制软件(如有别的请多推荐)
  • 终极指南:如何用MAA明日方舟助手彻底解放你的游戏时间
  • rEFInd-minimal 图标库详解:支持 30+ 操作系统的完美识别
  • 告别towxml!在uni-app跨端项目里,用mp-html实现Markdown解析(支持H5和小程序)
  • 突破性跨平台方案:在Windows上高效运行Android应用的完整指南
  • 【紧急预警】C++ MCP网关正在 silently 烧钱!3类GCC未启用的PCH/PGO/LTO组合策略可立即止损
  • 解决长列表性能瓶颈:vue-infinite-loading无限滚动插件的实战优化指南
  • LiveDraw:如何在屏幕上实时自由绘画的终极指南
  • 大气层系统1.7.1:为Nintendo Switch解锁无限可能的完整指南
  • 告别窗口尺寸困扰:Loop自定义功能深度修复指南
  • Elementary多环境部署:如何在开发和生产环境中使用
  • 企业级Java SMB/CIFS客户端架构:jcifs-ng 5大核心技术优势深度解析
  • 实时口罩检测-通用开源可部署:支持ARM64架构(如树莓派5)基础适配
  • GD32F103RC从CL改HD宏定义,Keil编译报错‘CAN0_RX_IRQn重复定义’的完整解决流程
  • VS Code Dev Containers启动慢如蜗牛?5个被90%开发者忽略的内核级优化技巧,立即生效
  • 终极指南:Craft游戏存档全版本兼容无缝迁移教程
  • 如何用TestDisk和PhotoRec快速找回丢失的数据?完整免费数据恢复指南
  • 基于PCA的人脸识别系统实现与原理详解
  • 2025届毕业生推荐的AI辅助论文方案实测分析
  • Synology NAS终极指南:Realtek USB网卡驱动完整部署与性能优化实战
  • STM32CubeMX生成的代码结构详解:从启动文件到HAL库,新手如何安全添加自己的代码?
  • AI Agent在智能营销中的应用:多智能体协同投放与优化案例
  • PICO C/C++开发环境 离线搭建RaspberryPi Pico RP2040 RP2350 C/C++环境
  • RTL8852BE Linux驱动深度解析:构建现代无线网络栈的技术实践
  • KNN:K 近邻算法