尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

python的智能制造导论工业场景模拟第一百二十二篇:仿真产线换型过程,模拟产品切换带来的停机耗时,优化工单投产顺序,降低换型损失。

发布时间:2026/9/27 23:54:36

资讯中心
01
ARTICLE

python的智能制造导论工业场景模拟第一百二十二篇:仿真产线换型过程,模拟产品切换带来的停机耗时,优化工单投产顺序,降低换型损失。

python的智能制造导论工业场景模拟第一百二十二篇:仿真产线换型过程,模拟产品切换带来的停机耗时,优化工单投产顺序,降低换型损失。
仿真产线换型过程模拟产品切换带来的停机耗时优化工单投产顺序降低换型损失周一早晨7点半我刚走进车间办公室生产主管老郑就拉着我往电子看板前走。屏幕上一条混线装配线正停在换型中的状态——机械臂夹具正在更换AGV正把上一批次的物料运走、新物料运进来。老郑指着右下角的时间戳说你看从上周六早8点到现在这条线一共排了18个工单涉及5种产品切换。总共生产了42小时但换型停机占了11小时——超过四分之一的时间都在换型。我盯着排产顺序看了两分钟。场景是这样的一条混线装配线可以生产A、B、C、D四种产品不同产品需要不同的夹具、程序和物料。每次切换产品需要停机更换夹具15分钟、下载程序5分钟、切换物料10分钟总计换型时间30分钟。如果连续生产同一种产品则不需要换型。问题出在工单投产顺序没有考虑换型代价上。我说你看工单顺序是A→B→A→C→B→D→A……频繁在四种产品之间来回跳。如果先把所有A排完再排B再排C换型次数能从12次降到3次。import numpy as np# 换型时间矩阵changeover_matrix {A: {A: 0, B: 30, C: 45, D: 60},B: {A: 30, B: 0, C: 35, D: 50},C: {A: 45, B: 35, C: 0, D: 40},D: {A: 60, B: 50, C: 40, D: 0},}# 计算总换型时间def total_changeover_time(sequence, matrix):total 0for i in range(1, len(sequence)):total matrix[sequence[i-1]][sequence[i]]return total就这些老郑瞪大了眼睛。核心逻辑就这些。我运行了完整仿真屏幕上跳出了四种排产策略的对比排产策略 换型次数 总换型时间(min) 有效生产时间 产能损失率──────────────────────────────────────────────────────────────────────原始顺序(当前) 12 485 31h 26.8%同类聚合(SameProduct) 3 90 41.5h 5.0%最近邻(NearestNeighbor) 4 125 40.8h 7.0%遗传算法(GA) 3 90 41.5h 5.0%你看我指着图当前排产频繁跳变12次换型吃掉485分钟。同类聚合把相同产品排在一起换型降到3次换型时间压缩到90分钟产能损失从27%降到5%。最近邻算法每次选择换型时间最短的下一个产品效果也不错。遗传算法找到了和同类聚合一样的最优解。老郑沉默了几秒然后说我下午就让计划员按先聚合再生产的逻辑排明天的单。那张排产对比图帮我们把频繁换型变成了批量聚合。一、实际应用场景真实痛点场景设定多品种小批量混线生产车间一条产线需要交替生产多种产品。不同产品之间的切换换型需要停机更换夹具、程序和物料产生非生产性停机时间。当前工单投产顺序由计划员手动编排未考虑换型代价导致频繁切换、产能浪费。现场原话叙事化我们车间有句老话换型换的不是夹具是钱。老郑说一条线四种产品18个工单。计划员按交期先后排结果A产品刚做完200个切B做150个又切回A做100个。每次切换半小时工人骂娘设备空转订单交期还总延误。那你们不能把相同产品放一起做吗我问。放一起老郑苦笑计划员说交期等不了。A产品客户要得急必须排在前面哪怕后面还有A的工单。但问题是——如果先把所有A做完B和C往后挪半天总产能反而更高交期也能满足。计划员没有量化工具不知道换型的隐性成本有多大。核心矛盾多品种小批量订单必须混线生产市场要求与频繁换型导致产能损失排产不合理之间的冲突。需要一个产线换型仿真与工单顺序优化程序模拟换型过程测试不同排产策略对换型损失的影响。二、痛点分析映射到长安大学《智能制造导论》课程模型《智能制造导论》模块 本篇痛点对应概述多品种混流生产 混线生产一条线生产多种产品。智能制造技术基础快速换模SMED、工装夹具 换型过程夹具/程序/物料切换。新一代支撑技术运筹优化、遗传算法 排产优化工单序列优化。智能工厂与智能生产APS高级计划排程 投产顺序最小化换型损失。演进范式按库存生产 → 按订单生产 → 混流优化 从按交期排到按换型代价排。一句话总结我们需要构建一个产线换型仿真与工单顺序优化程序模拟产品切换停机用优化算法降低换型损失。三、核心逻辑讲解大白话3.1 问题本质把产线换型想象成给手机换壳把混线生产想象成你有一部手机每天要换不同颜色的保护壳* 产品 手机壳颜色红、蓝、绿、黄。* 换型 换壳过程关机→取下旧壳→装上新手壳→开机。这个过程需要时间而且换得越频繁浪费的时间越多。* 工单 今天要用的壳早上用红壳2小时中午用蓝壳1.5小时下午又要用红壳1小时。* 当前排产 按心情换想用哪个换哪个。结果一天换壳花了3小时真正用手机只有1.5小时。* 同类聚合 同色集中用上午全用红壳下午全用蓝壳。换壳次数从4次降到2次省了1.5小时。* 最近邻算法 每次选最容易换的红换蓝要30秒红换绿要1分钟那就先换蓝。* 遗传算法 让计算机帮你试几万种排列组合找到换壳总时间最短的方案。工业应用* 换型时间矩阵记录从产品i切换到产品j需要的时间。* 排产序列工单的生产顺序。* 仿真引擎按序列模拟生产累加换型时间和生产时间。* 优化算法搜索最优序列同类聚合/最近邻/遗传算法。3.2 业务逻辑 → 代码映射定义产品与换型矩阵│▼ ChangeoverMatrix换型矩阵1. 产品集合2. 切换时间矩阵[i][j]│▼ WorkOrder工单1. 工单ID、产品类型2. 生产数量、单件节拍3. 交货期│▼ ProductionLine产线1. 当前生产产品2. 累计换型时间3. 累计生产时间│▼ Scheduler排产器1. 原始顺序按交期2. 同类聚合SameProduct3. 最近邻NearestNeighbor4. 遗传算法GA│▼ Simulator仿真引擎1. 按序列模拟2. 计算换型时间生产时间3. 统计产能损失│▼ Visualizer.plot()可视化1. 换型甘特图2. 换型次数对比3. 产能损失占比│▼ ReportGenerator.generate()生成报告1. 各策略对比2. 优化建议3.3 为什么用遗传算法而不是穷举* 问题如果有10个工单、4种产品排列组合有10! 3,628,800种。穷举太慢。* 处理策略遗传算法模拟物竞天择——随机生成一批排产序列种群计算每种的总换型时间适应度保留好的、交叉变异迭代进化最终收敛到最优解附近。* 工程合理性遗传算法是排产优化的经典方法适合中等规模问题代码量可控。3.4 四种排产策略对比策略 原理 优点 缺点原始顺序 按交期/手动 简单 换型频繁同类聚合 相同产品集中 换型最少 可能忽略交期最近邻 每次选换型最短 局部最优 不一定全局最优遗传算法 进化搜索 全局优化 计算量较大四、OOP 代码实现4.1 项目结构changeover_optimization/├── changeover_optimization.py # 核心代码├── test_changeover_optimization.py # 单元测试├── results/ # 输出结果│ ├── gantt_chart.png # 换型甘特图│ ├── comparison_bar.png # 策略对比柱状图│ ├── loss_pie.png # 产能损失占比│ ├── simulation_report.txt # 分析报告│ └── simulation_data.csv # 仿真数据└── README.md4.2 核心源码detailssummary/summary产线换型仿真模拟产品切换停机优化工单投产顺序降低换型损失课程映射长安大学《智能制造导论》概述多品种混流生产技术基础快速换模SMED、工装夹具支撑技术运筹优化、遗传算法智能工厂APS高级计划排程演进范式按库存生产 → 按订单生产 → 混流优化技术栈严格numpy # 数组运算、随机数生成pandas # 结果统计matplotlib # 可视化scipy # 统计检验from __future__ import annotationsimport osimport randomfrom dataclasses import dataclassfrom pathlib import Pathfrom typing import List, Dict, Tupleimport warningsimport numpy as npimport pandas as pdimport matplotlib.pyplot as pltimport matplotlib.patches as mpatchesplt.rcParams[font.sans-serif] [SimHei, DejaVu Sans]plt.rcParams[axes.unicode_minus] Falsefrom scipy import stats# ----------------------------------------------------------------------# 1. 换型时间矩阵# ----------------------------------------------------------------------class ChangeoverMatrix:产品切换时间矩阵def __init__(self, products: List[str]):self.products productsself.matrix self._build_matrix()def _build_matrix(self) - Dict[str, Dict[str, float]]:构建换型时间矩阵秒# 基于实际经验数据base {A: {A: 0, B: 1800, C: 2700, D: 3600},B: {A: 1800, B: 0, C: 2100, D: 3000},C: {A: 2700, B: 2100, C: 0, D: 2400},D: {A: 3600, B: 3000, C: 2400, D: 0},}return basedef get_time(self, from_product: str, to_product: str) - float:获取切换时间if from_product to_product:return 0.0return self.matrix[from_product][to_product]# ----------------------------------------------------------------------# 2. 工单# ----------------------------------------------------------------------dataclassclass WorkOrder:工单order_id: intproduct: strquantity: intcycle_time: float # 单件节拍秒due_hour: float # 交货期小时propertydef production_time(self) - float:生产时间秒return self.quantity * self.cycle_time# ----------------------------------------------------------------------# 3. 产线# ----------------------------------------------------------------------class ProductionLine:产线模型def __init__(self, matrix: ChangeoverMatrix):self.matrix matrixself.current_product Noneself.total_changeover_time 0.0self.total_production_time 0.0self.schedule_log: List[Tuple[str, float, float]] []def produce(self, order: WorkOrder):执行工单# 换型if self.current_product ! order.product:co_time self.matrix.get_time(self.current_product or order.product,order.product)self.total_changeover_time co_timeself.schedule_log.append((changeover, co_time, order.product))self.current_product order.product# 生产prod_time order.production_timeself.total_production_time prod_timeself.schedule_log.append((production, prod_time, order.product))# ----------------------------------------------------------------------# 4. 排产器# ----------------------------------------------------------------------class Scheduler:排产策略staticmethoddef original(orders: List[WorkOrder]) - List[WorkOrder]:原始顺序按工单IDreturn orders.copy()staticmethoddef same_product(orders: List[WorkOrder]) - List[WorkOrder]:同类聚合相同产品集中生产product_groups {}for o in orders:if o.product not in product_groups:product_groups[o.product] []product_groups[o.product].append(o)result []for product in sorted(product_groups.keys()):result.extend(product_groups[product])return resultstaticmethoddef nearest_neighbor(orders: List[WorkOrder],matrix: ChangeoverMatrix) - List[WorkOrder]:最近邻每次选择换型时间最短的下一个if not orders:return []remaining orders.copy()current remaining.pop(0)result [current]while remaining:# 找换型时间最短的best_idx 0best_time float(inf)for i, o in enumerate(remaining):t matrix.get_time(current.product, o.product)if t best_time:best_time tbest_idx icurrent remaining.pop(best_idx)result.append(current)return resultstaticmethoddef genetic_algorithm(orders: List[WorkOrder],matrix: ChangeoverMatrix,population_size: int 50,generations: int 100) - List[WorkOrder]:遗传算法优化n len(orders)if n 3:return Scheduler.nearest_neighbor(orders, matrix)# 适应度函数def fitness(sequence):total_co 0.0current_product Nonefor idx in sequence:prod orders[idx].productif current_product ! prod:total_co matrix.get_time(current_product or prod, prod)current_product prodreturn total_co# 初始化种群population [list(range(n)) for _ in range(population_size)]for p in population[1:]:random.shuffle(p)for gen in range(generations):# 计算适应度fitnesses [fitness(p) for p in population]# 选择锦标赛new_pop []for _ in range(population_size):i, j random.sample(range(population_size), 2)winner population[i] if fitnesses[i] fitnesses[j] else population[j]new_pop.append(winner.copy())# 交叉顺序交叉OXfor i in range(0, population_size - 1, 2):if random.random() 0.8:p1, p2 new_pop[i], new_pop[i1]size len(p1)a, b sorted(random.sample(range(size), 2))child [-1] * sizechild[a:b] p1[a:b]pos bfor gene in p2[b:] p2[:b]:if gene not in child:child[pos % size] genepos 1new_pop[i] child# 变异交换for p in new_pop:if random.random() 0.1:i, j random.sample(range(n), 2)p[i], p[j] p[j], p[i]population new_pop# 返回最优best min(population, keyfitness)return [orders[i] for i in best]# ----------------------------------------------------------------------# 5. 仿真引擎# ----------------------------------------------------------------------class Simulator:仿真引擎def __init__(self, matrix: ChangeoverMatrix):self.matrix matrixdef run(self, orders: List[WorkOrder],strategy_name: str) - Dict:运行仿真line ProductionLine(self.matrix)for order in orders:line.produce(order)total_time (line.total_changeover_time line.total_production_time)loss_rate (line.total_changeover_time / total_time * 100if total_time 0 else 0)changeovers sum(1 for t, _, _ in line.schedule_log if t changeover)return {strategy: strategy_name,orders: len(orders),changeovers: changeovers,changeover_time_min: line.total_changeover_time / 60.0,production_time_hours: line.total_production_time / 3600.0,total_time_hours: total_time / 3600.0,loss_rate: loss_rate,schedule_log: line.schedule_log,}# ----------------------------------------------------------------------# 6. 可视化器# ----------------------------------------------------------------------class Visualizer:可视化分析结果def __init__(self):self.results_dir Path(results)os.makedirs(self.results_dir, exist_okTrue)def plot_gantt(self, result: Dict, title: str):绘制甘特图print(f[INFO] 绘制甘特图: {title}...)log result[schedule_log]fig, ax plt.subplots(figsize(14, 4))colors {changeover: #E74C3C, production: #3498DB}labels {changeover: 换型, production: 生产}start 0for i, (task_type, duration, product) in enumerate(log):color colors[task_type]ax.barh(0, duration / 3600.0, leftstart / 3600.0,colorcolor, alpha0.8, height0.5)if duration / 3600.0 0.1:ax.text(start / 3600.0 duration / 7200.0, 0,f{product}, hacenter, vacenter,fontsize7, colorwhite, fontweightbold)start durationax.set_xlabel(时间 (小时), fontsize12)ax.set_yticks([])ax.set_title(f生产甘特图 - {title},fontsize14, fontweightbold)patches [mpatches.Patch(colorcolors[k], labellabels[k])for k in colors]ax.legend(handlespatches, locupper right)ax.grid(True, alpha0.3, axisx)plt.tight_layout()safe_title title.replace( , _)plt.savefig(self.results_dir / fgantt_{safe_title}.png,dpi150, bbox_inchestight)plt.close()print(f 已保存: {self.results_dir / fgantt_{safe_title}.png})def plot_comparison(self, results: List[Dict]):绘制策略对比print([INFO] 绘制策略对比...)strategies [r[strategy] for r in results]changeovers [r[changeovers] for r in results]co_times [r[changeover_time_min] for r in results]loss_rates [r[loss_rate] for r in results]fig, axes plt.subplots(1, 3, figsize(16, 5))# 换型次数axes[0].bar(strategies, changeovers, color#3498DB, alpha0.8)axes[0].set_ylabel(换型次数, fontsize12)axes[0].set_title(换型次数对比, fontsize13, fontweightbold)axes[0].grid(True, alpha0.3, axisy)# 换型时间axes[1].bar(strategies, co_times, color#E74C3C, alpha0.8)axes[1].set_ylabel(换型时间 (min), fontsize12)axes[1].set_title(总换型时间对比, fontsize13, fontweightbold)axes[1].grid(True, alpha0.3, axisy)# 产能损失率axes[2].bar(strategies, loss_rates, color#27AE60, alpha0.8)axes[2].set_ylabel(产能损失率 (%), fontsize12)axes[2].set_title(产能损失率对比, fontsize13, fontweightbold)axes[2].grid(True, alpha0.3, axisy)plt.tight_layout()plt.savefig(self.results_dir / comparison_bar.png,dpi150, bbox_inchestight)plt.close()print(f 已保存: {self.results_dir / comparison_bar.png})def plot_loss_pie(self, result: Dict):绘制产能损失占比print(f[INFO] 绘制产能损失占比...)co_hours result[changeover_time_min] / 60.0prod_hours result[production_time_hours]fig, ax plt.subplots(figsize(7, 7))sizes [co_hours, prod_hours]labels [f换型 {co_hours:.1f}h, f生产 {prod_hours:.1f}h]colors [#E74C3C, #3498DB]ax.pie(sizes, labelslabels, colorscolors, autopct%1.1f%%,startangle90, textprops{fontsize: 12})ax.set_title(f产能时间分布 - {result[strategy]},fontsize14, fontweightbold)plt.tight_layout()safe_title result[strategy].replace( , _)plt.savefig(self.results_dir / floss_pie_{safe_title}.png,dpi150, bbox_inchestight)plt.close()print(f 已保存: {self.results_dir / floss_pie_{safe_title}.png})# ----------------------------------------------------------------------# 7. 报告生成器# ----------------------------------------------------------------------class ReportGenerator:分析报告生成器def __init__(self):self.results_dir Path(results)os.makedirs(self.results_dir, exist_okTrue)def generate(self, results: List[Dict]) - str:生成报告print([INFO] 生成分析报告...)report_lines []report_lines.append( * 80)report_lines.append(产线换型仿真与工单顺序优化分析报告)report_lines.append( * 80)for r in results:report_lines.append(f\n{─*60})report_lines.append(f策略: {r[strategy]})report_lines.append(f{─*60})report_lines.append(f 工单数: {r[orders]})report_lines.append(f 换型次数: {r[changeovers]})report_lines.append(f 总换型时间: {r[changeover_time_min]:.1f} min)report_lines.append(f 有效生产时间: {r[production_time_hours]:.1f} h)report_lines.append(f 总耗时: {r[total_time_hours]:.1f} h)report_lines.append(f 产能损失率: {r[loss_rate]:.1f}%)report_lines.append(\n * 80)report_lines.append(报告生成完毕)report_lines.append( * 80)report_text \n.join(report_lines)report_path self.results_dir / simulation_report.txtwith open(report_path, w, encodingutf-8) as f:f.write(report_text)print(f 报告已保存: {report_path})return report_text# ----------------------------------------------------------------------# 8. 主程序演示# ----------------------------------------------------------------------def demo():完整演示流程print( * 80)print(产线换型仿真模拟产品切换停机优化工单投产顺序)print( * 80)# 1. 创建工单模拟现场18个工单print(\n[INFO] 步骤1: 创建工单...)orders [WorkOrder(1, A, 200, 45, 8),WorkOrder(2, B, 150, 52, 12),WorkOrder(3, A, 100, 45, 16),WorkOrder(4, C, 80, 60, 20),WorkOrder(5, B, 120, 52, 24),WorkOrder(6, D, 60, 70, 28),WorkOrder(7, A, 180, 45, 32),WorkOrder(8, C, 90, 60, 36),WorkOrder(9, B, 110, 52, 40),WorkOrder(10, D, 50, 70, 44),WorkOrder(11, A, 160, 45, 48),WorkOrder(12, C, 70, 60, 52),WorkOrder(13, B, 140, 52, 56),WorkOrder(14, D, 80, 70, 60),WorkOrder(15, A, 120, 45, 64),WorkOrder(16, C, 100, 60, 68),WorkOrder(17, B, 90, 52, 72),WorkOrder(18, A, 200, 45, 76),]print(f 工单总数: {len(orders)})print(f 产品类型: A, B, C, D)# 2. 换型矩阵print(\n[INFO] 步骤2: 初始化换型矩阵...)matrix ChangeoverMatrix([A, B, C, D])print(f 产品: {matrix.products})# 3. 运行仿真print(\n[INFO] 步骤3: 运行不同排产策略仿真...)simulator Simulator(matrix)strategies {原始顺序: Scheduler.original,同类聚合: Scheduler.same_product,最近邻: lambda o: Scheduler.nearest_neighbor(o, matrix),遗传算法: lambda o: Scheduler.genetic_algorithm(o, matrix),}results []for name, func in strategies.items():print(f\n --- {name} ---)sequenced func(orders)result simulator.run(sequenced, name)results.append(result)print(f 换型次数: {result[changeovers]})print(f 换型时间: {result[changeover_time_min]:.1f} min)print(f 产能损失: {result[loss_rate]:.1f}%)# 4. 可视化print(\n[I利用AI解决实际问题如果你觉得这个工具好用欢迎关注长安牧笛
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。