0

0

SimPy离散事件仿真:构建复杂的工厂生产线模型

花韻仙語

花韻仙語

发布时间:2025-11-05 12:21:19

|

1035人浏览过

|

来源于php中文网

原创

SimPy离散事件仿真:构建复杂的工厂生产线模型

本文深入探讨如何使用python的simpy库构建和模拟复杂的工厂生产线。通过一个具体的工厂模型案例,详细讲解simpy环境、进程、资源(包括操作员、机器人和工装夹具)的定义与交互,以及如何利用优先级资源管理实现零件的有序流转。文章重点阐述了资源请求与释放的正确实践,帮助读者掌握simpy进行离散事件仿真的核心技术。

SimPy离散事件仿真简介

SimPy是一个基于Python的离散事件仿真(DES)框架。它允许开发者通过模拟事件的发生和资源的使用来建模和分析复杂系统。在工厂生产线建模中,SimPy能够有效地模拟零件在不同工位、机器和操作员之间流转的过程,从而帮助工程师评估生产效率、识别瓶颈并优化资源配置。

与连续系统仿真不同,离散事件仿真关注的是系统状态在特定时间点(事件发生时)的变化。在工厂场景中,这些事件可能包括零件到达、机器完成加工、操作员开始或结束任务等。SimPy通过其核心概念——环境(Environment)、进程(Process)和资源(Resource)——来构建这些复杂的交互。

SimPy核心概念解析

在构建工厂模型之前,理解SimPy的几个核心概念至关重要:

  1. 环境 (Environment): simpy.Environment 是SimPy仿真的核心,它维护着模拟时间(env.now)和事件队列。所有的进程都在这个环境中运行。
  2. 进程 (Process): 进程是SimPy中主动的、会消耗时间的实体。在工厂模型中,每个零件的加工流程就是一个进程,操作员或机器人执行的任务也可以被视为进程。进程通过 yield env.timeout(duration) 来模拟时间的流逝,或者通过 yield request 来等待资源。
  3. 资源 (Resource): 资源是SimPy中被动、容量有限的实体,例如机器、操作员、工位或夹具。进程需要请求资源才能执行其任务,并在任务完成后释放资源。
    • simpy.Resource: 基本资源类型,支持FIFO(先入先出)请求。
    • simpy.PriorityResource: 带有优先级的资源类型,允许高优先级请求优先获得资源。这对于需要确保特定零件或任务优先处理的场景非常有用。

构建工厂生产线模型

我们将通过一个具体的工厂生产线模型来演示SimPy的应用。这个模型模拟了零件从入库到出库的完整流程,涉及操作员、多种机器人和多个工装夹具。

1. 全局配置与常量 (g 类)

首先,定义一些全局常量,如仿真时长、操作员数量以及各种加工步骤所需的时间。这有助于集中管理模型参数,方便后续调整和实验。

import simpy
import itertools

class g: # 全局常量
    t_sim = 600 # 仿真时长,这里设置为600秒,方便观察

    operator_qty = 2 # 操作员数量

    sWeld_t = 2.75 # 点焊时间 (秒/点)
    Adh_t = 1/60 # 涂胶时间 (秒/毫米)
    ArcStud_t = 5.5 # 弧焊螺柱时间 (秒/个)
    ProjStud_t = 10 # 凸焊螺柱时间 (秒/个)

2. 工厂单元模型 (cell_model 类)

cell_model 类封装了整个工厂单元的逻辑,包括环境初始化、资源定义和零件生成器。

初始化方法 (__init__)

在 __init__ 方法中,我们创建SimPy环境并初始化所有必需的资源。这里使用了 PriorityResource,它允许我们为每个请求指定一个优先级。在本例中,零件的ID(p_Id)被用作优先级,确保零件按照生成顺序(FIFO)进行处理。

class cell_model: # 代表整个工厂单元,包含所有进程、资源和仿真环境
    def __init__(self): # 单元的初始条件
        self.env = simpy.Environment() # 创建SimPy环境
        self.part_counter = 0 # 零件计数器

        # 定义操作员资源
        self.OP = simpy.PriorityResource(self.env, capacity=g.operator_qty)

        # 定义机器人资源,每个机器人容量为1
        self.R1 = simpy.PriorityResource(self.env, capacity=1)
        self.R2 = simpy.PriorityResource(self.env, capacity=1)
        self.R3 = simpy.PriorityResource(self.env, capacity=1)
        self.R4 = simpy.PriorityResource(self.env, capacity=1)

        # 定义工装夹具资源,每个夹具容量为1
        self.Fix01 = simpy.PriorityResource(self.env, capacity=1)
        self.Fix02 = simpy.PriorityResource(self.env, capacity=1)
        self.Fix101 = simpy.PriorityResource(self.env, capacity=1)

        # 启动零件生成器进程
        self.env.process(self.part_generator())

零件生成器 (part_generator)

part_generator 方法是一个SimPy进程,负责周期性地生成新的零件。itertools.count() 用于生成唯一的零件ID。yield self.env.timeout(1) 表示每隔1个模拟时间单位生成一个新零件。

Vondy
Vondy

下一代AI应用平台,汇集了一流的工具/应用程序

下载
    def part_generator(self):
        for p_Id in itertools.count(): # 无限生成零件ID
            yield self.env.timeout(1) # 每隔1秒生成一个新零件
            self.env.process(self.make_part(p_Id)) # 为每个零件启动一个加工进程

零件加工流程 (make_part)

make_part 方法是整个模型的核心,它详细描述了一个零件从开始加工到完成出库的所有步骤。每个步骤都可能涉及请求资源、等待资源、执行任务(env.timeout)和释放资源。

资源请求与释放策略:

在SimPy中,资源请求和释放有两种常见模式:

  1. with 语句 (上下文管理器): with resource.request(priority=p_Id) as req: yield req; ...
    • 优点: 简洁,确保资源在 with 块结束时自动释放,即使发生异常。
    • 适用场景: 资源占用时间与任务执行时间紧密耦合,任务完成后资源立即释放。
  2. 显式 request() 和 release(): req = resource.request(priority=p_Id); yield req; ... yield resource.release(req);
    • 优点: 允许在请求资源后长时间持有,并在进程的任意时刻手动释放资源。这对于一个资源在不同阶段被请求和释放的复杂流程非常有用。
    • 适用场景: 资源被请求后,可能在多个不同的操作或时间点后才会被释放,或者需要将资源的释放与其他资源的请求/释放解耦。

在下面的代码中,我们将看到这两种模式的混合使用,特别是对原始代码中资源释放逻辑的修正,以避免资源过早释放导致的问题。

    def make_part(self,p_Id): # 描述单个零件在单元中的一系列加工过程
        # --- 阶段1:操作员取件并放置到夹具Fix01 ---
        OP_req1 = self.OP.request(priority=p_Id) # 请求操作员资源
        print(f"part {p_Id} OP request at {self.env.now}")
        yield OP_req1 # 等待操作员可用
        print(f"part {p_Id} OP seized at {self.env.now}")
        print("Part ", p_Id, " is next available at ", self.env.now, sep="")
        yield self.env.timeout(29) # 操作员将零件搬运到工位,进行准备工作

        Fix01_req = self.Fix01.request(priority=p_Id) # 请求夹具Fix01
        print(f"part {p_Id} Fix01 request at {self.env.now}")
        yield Fix01_req # 等待夹具Fix01可用
        print(f"part {p_Id} Fix01 seized at {self.env.now}")
        yield self.env.timeout(27) # 操作员装载零件,启动工位

        yield self.OP.release(OP_req1) # 释放操作员资源
        print(f"part {p_Id} OP released at {self.env.now}")
        print("Operator 01 released part ", p_Id, " at ", self.env.now, sep="")
        yield self.env.timeout(0) # 短暂等待

        # --- 阶段2:R2机器人进行点焊 (Fix01) ---
        # R2使用with语句,因为其任务完成后即释放
        with self.R2.request(priority=p_Id) as R2_req:   
            print(f"part {p_Id} R2 request at {self.env.now}") 
            yield R2_req # 等待R2机器人可用
            print(f"part {p_Id} R2 seized at {self.env.now}")
            print("R2 moves to Fixture 01 to work on part ", p_Id, " at ", self.env.now, sep="")
            yield self.env.timeout(g.sWeld_t * 11) # R2进行11次点焊
        print(f"part {p_Id} R2 released at {self.env.now}")

        # --- 阶段3:R1机器人搬运零件,进行焊接,并放置到夹具Fix101 ---
        R1_req = self.R1.request(priority=p_Id) # 请求R1机器人
        print(f"part {p_Id} R1 request at {self.env.now}")
        yield R1_req # 等待R1机器人可用
        print(f"part {p_Id} R1 seized at {self.env.now}")
        yield self.env.timeout(8) # R1将零件从Fix01移出
        print("Part ", p_Id, " is leaving Fixture 01 at ", self.env.now, sep="")

        yield self.Fix01.release(Fix01_req) # 释放夹具Fix01
        print(f"part {p_Id} Fix01 released at {self.env.now}")
        yield self.env.timeout(g.sWeld_t * 13) # R1进行13次点焊
        yield self.env.timeout(0)
        yield self.env.timeout(g.ArcStud_t * 5) # R1进行5次弧焊螺柱
        yield self.env.timeout(8) # R1移动到夹具Fix101

        Fix101_req = self.Fix101.request(priority=p_Id) # 请求夹具Fix101
        print(f"part {p_Id} Fix101 request at {self.env.now}")
        yield Fix101_req # 等待夹具Fix101可用
        print(f"part {p_Id} Fix101 seized at {self.env.now}")
        print("Part ", p_Id, " enters Fixture 101 at ", self.env.now, sep="")

        yield self.R1.release(R1_req) # 释放R1机器人
        print(f"part {p_Id} R1 released at {self.env.now}")

        # --- 阶段4:R4机器人进行弧焊螺柱 (Fix101) ---
        # R4使用with语句
        with self.R4.request(priority=p_Id) as R4_req:
            print(f"part {p_Id} R4 request at {self.env.now}")
            yield R4_req # 等待R4机器人可用
            print(f"part {p_Id} R4 seized at {self.env.now}")
            yield self.env.timeout(g.ArcStud_t * 6) # R4进行6次弧焊螺柱
        print(f"part {p_Id} R4 released at {self.env.now}")

        # --- 阶段5:R3机器人搬运零件,进行凸焊和涂胶,并放置到夹具Fix02 ---
        R3_req = self.R3.request(priority=p_Id) # 请求R3机器人
        print(f"part {p_Id} R3 request at {self.env.now}")
        yield R3_req # 等待R3机器人可用
        print(f"part {p_Id} R3 seized at {self.env.now}")
        yield self.env.timeout(8) # R3将零件从Fix101移出
        print("Part ", p_Id, " leaves Fixture 101 at ", self.env.now, sep="")

        yield self.Fix101.release(Fix101_req) # 释放夹具Fix101
        print(f"part {p_Id} Fix101 released at {self.env.now}")
        yield self.env.timeout(g.ProjStud_t * 6) # R3进行6次凸焊螺柱
        yield self.env.timeout(0)
        yield self.env.timeout(225 * g.Adh_t) # R3涂胶225mm
        print("Part ", p_Id, " has adhesive stage finished at ", self.env.now, sep="")
        yield self.env.timeout(8) # R3移动到夹具Fix02

        Fix02_req = self.Fix02.request(priority=p_Id) # 请求夹具Fix02
        print(f"part {p_Id} Fix02 request at {self.env.now}")
        yield Fix02_req # 等待夹具Fix02可用
        print(f"part {p_Id} Fix02 seized at {self.env.now}")
        yield self.env.timeout(0)
        print("Part ", p_Id, " enters Fixture 02 at ", self.env.now, sep="")

        yield self.R3.release(R3_req) # 释放R3机器人
        print(f"part {p_Id} R3 released at {self.env.now}")

        # --- 阶段6:操作员进行辅助操作 (Fix02) ---
        # 操作员使用with语句
        with self.OP.request(priority=p_Id) as OP_req2:
            print(f"part {p_Id} OP request at {self.env.now}")
            yield OP_req2 # 等待操作员可用
            print(f"part {p_Id} OP seized at {self.env.now}")
            yield self.env.timeout(38) # 操作员进行辅助操作
            yield self.env.timeout(0)
        print(f"part {p_Id} OP released at {self.env.now}")

        # --- 阶段7:R2机器人再次进行点焊 (Fix02) ---
        # R2使用with语句
        with self.R2.request(priority=p_Id) as R2_req2:
            print(f"part {p_Id} R2 request at {self.env.now}")
            yield R2_req2 # 等待R2机器人可用
            print(f"part {p_Id} R2 seized at {self.env.now}")
            print("R2 moves to Fixture 02 to work on part ", p_Id, " at ", self.env.now, sep="")
            yield self.env.timeout(g.sWeld_t * 35) # R2进行35次点焊
            yield self.env.timeout(0)
        print(f"part {p_Id} R2 released at {self.env.now}")

        # --- 阶段8:操作员移除零件 (Fix02) ---
        # 操作员使用with语句
        with self.OP.request(priority=p_Id) as OP_req3:
            print(f"part {p_Id} OP request at {self.env.now}")
            yield OP_req3 # 等待操作员可用
            print(f"part {p_Id} OP seized at {self.env.now}")
            yield self.env.timeout(2) # 操作员移除零件

            yield self.Fix02.release(Fix02_req) # 释放夹具Fix02
            print(f"part {p_Id} Fix02 released at {self.env.now}")
            print("Part ", p_Id, " leaves process at ", self.env.now, sep="")
            yield self.env.timeout(0)
        print(f"part {p_Id} OP released at {self.env.now}")

3. 运行仿真 (run)

run 方法负责启动仿真环境,并指定仿真运行的时长。

    def run(self,t_sim=g.t_sim): # 运行方法启动实体生成器并告诉SimPy运行环境
        self.env.run(until=t_sim)

4. 启动仿真

最后,实例化 cell_model 并调用其 run 方法来启动整个仿真。

# 运行仿真
print("Simulation Starting...")
my_model=cell_model()
my_model.run()
print("Simulation Finished.")

注意事项与最佳实践

  1. 资源管理的重要性: 正确地请求和释放资源是SimPy建模成功的关键。
    • 避免死锁: 如果多个进程相互等待对方释放资源,就可能发生死锁。仔细规划资源请求顺序,避免循环等待。
    • 选择合适的释放时机: 如 make_part 方法所示,对于一个资源在不同阶段被请求和释放的场景,使用显式的 request() 和 release() 是更灵活和正确的选择。而对于任务结束后立即释放的资源,with 语句则更简洁。
  2. 优先级资源 (PriorityResource): 使用 PriorityResource 配合 p_Id (零件ID) 能够有效地模拟FIFO队列,确保零件按进入顺序加工,这在许多生产线中是常见的需求。
  3. **调试技巧:

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
resource是什么文件
resource是什么文件

Resource文件是一种特殊类型的文件,它通常用于存储应用程序或操作系统中的各种资源信息。它们在应用程序开发中起着关键作用,并在跨平台开发和国际化方面提供支持。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

182

2023.12.20

java基础知识汇总
java基础知识汇总

java基础知识有Java的历史和特点、Java的开发环境、Java的基本数据类型、变量和常量、运算符和表达式、控制语句、数组和字符串等等知识点。想要知道更多关于java基础知识的朋友,请阅读本专题下面的的有关文章,欢迎大家来php中文网学习。

1569

2023.10.24

counta和count的区别
counta和count的区别

Count函数用于计算指定范围内数字的个数,而CountA函数用于计算指定范围内非空单元格的个数。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

203

2023.11.20

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

25

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

43

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

174

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

50

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

92

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

102

2026.03.06

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
最新Python教程 从入门到精通
最新Python教程 从入门到精通

共4课时 | 22.5万人学习

Django 教程
Django 教程

共28课时 | 5万人学习

SciPy 教程
SciPy 教程

共10课时 | 1.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号