排产的两种方式(前推式与后拉式)在Optaplanner上的体现

生产计划的约束

  在制定生产计划过程中,必然是存在某些制约因素,满足某些需求才能进行的,或是交期保证、或是产能限制、或是关键工序制约。即TOC理论 - 任何系统至少存在着一个制约因素/瓶颈;否则它就可能有无限的产出。就是说,如果不存在这个(或这些)制约因素,生产计划就没必要“排”了,只需随意地,毫无约束地把任意一个或多个生产任务纳入生产日程,都能满足生产、营业等所有业务要求。那也不需要人的智慧参投入其中了。

两种计划模式

  而现实环境中,资源是有限的,且往往是在资源不足,并需要尽量满足制约因素情况下进行计划制定。在制定计划的时候,不同的公司,基于不同的经营策略,需要遵循不同的原则。即使是同一个公司,在不同的业务场景(例如淡/旺季),其需要遵循的原则也可能不同。例如旺季因为生产任务紧张,需要保证交期;而谈季相对来说可用产能会较充裕,保证交期就会不太困难,进而又需要遵循另外一些原则,譬如尽量降低生产成本等。而在这些原则之外,还有一种相对来说是比较固定,或者比较约定成俗的原则,就是尽早开始(As soon as possible),和即时生产(Just in time)。其中即时生产,是精益生产中的一个概念。本农上一家公司已推行了比较成熟的精益生产体系(精益绝对不是5S喔,更注重的是流程优化,识别并消除不增值活动,减省不增值但必须的活动)。所以当时设计APS系统时,很多时候就遵循即时生产的原则。此原则由整个供应链中最后一个环节驱动(例如出货环节),从而推动前工序的生产安排。而很多不太强调精益生产的制造企业,在老生产计划员来看,制定计划的时候,除了较低程度上实现批量生产,以便高资源利用率,而进行对小批量生产任务稍作停留等待外,通常是按尽早开始的原则进行的。因为通常人们的想法是,未来的生产任务和产能具有不可预见性,你不知道未来会不会突然因为客户加单,机器故障等客观且不可控因素导致产能吃紧,甚至令生产单位措手不及。如果这种意外情况真的出现,那么一开始使用尽早开始原则安排生产计划,令到后面的产能较充裕,应对起这些“意外”起来,就相对轻松多了,这类原则下的生产计划优势就体现出来了。而实时生产原则,则有可能因为预留在较后时间的资源(例如机台产能)是比较“准确”的,那就相对按尽早开始原则制定的计划来说,就更加被动了。但即时生产原则下的生产计划,应对这种“意外”,也是有很多相应措施的。例如使用适当的缓冲机制,和实时计划机制来应对。缓冲机制就是根据过往历史经验,在按即时生产原则制定生产计划时,预留一定程度的冗余资源作储备,当出现“意外”时,可以使用这些冗余的资源进行补救。而实时计划相对来说“先进”一点了(先进二字加个引号,是因为这只是我觉得这种方法先进一点)。这种所谓的先进,主要体现在通过自动化的排产引擎,将计划制定到足够细致且精确,对任务的生产情况(包括既有任务的执行情况,资源使用情况和新任务的增加量等)进行实时监控,使计划实时地对这些情况作出反映,并及时给出新的应对方案。例如:当有新任务出现时,即时更新新增的任务到计划中;有资源出现突发意外(例如机台突然故障)也可以反映到计划中,并即时作出反映,及时给出修正后的计划。但通过实时计划是相对比较复杂的的方案,在Optaplanner中也有real-time planning的功能,我将会在Optaplanner相关的系统列文章中,单独撰一篇来讲解实时计划。另外就是执行层面对实时计划的执行依从性问题了,如何制定的计划很精确,但执行过程相对来说是无法精确达到,比较粗糙的,例如:手工工序,人的执行能力相对机器来说,准时性会差很远的。

即时生产原则生产计划的价值

  既然即时生产如此繁琐,为何还要采用呢?为何不全部采用尽早生产的原则来制定计划呢?其实还真不是那么简单,相对生产环境的“繁琐”,对于老板来说商业上的利润更为重要。如果大家理解精益,就知道它很多情况下,要精简的活动就是 - “等待”,因为等待这个活动在整个价值链中,是不增值且不必要的,所以它是首个被除掉的活动。为何这样理解?因为如果对于一个并不非常紧急的产品,你一开始就完成了它的一大堆的半成品,或成品,占用了大量本来可以优先用于其它生产任务的的资源(库存、资金等资源),从而令到资源的利用率隆低了,对于老板来说,资源利用率高低可是实打实地影响到最终利润呀。本农曾参与过国内某一线生活用纸企业的产销协调平台的需求调研,记得讨论到关于目前的环境下,车间的批量生产是否能节省成本、是否仍有价值的问题时,当时的物流总监安奈不住情绪发飙了 - 你们到底会不会算帐? 少投几次料,少清几次机省出来的那点纸浆价值,大量生产出来的这些产品,放在北京一个物流仓里,一天的成本是多少?一个批次使用这种所谓的批量生产输出的成品,不到一个星期,库存成本就已经把所有生产环节省出来所有成本都吃掉了。所以,实时生产对于一些在制品成本高的企业,是能有效降低WIP,进而实打实地降整个供应链成本的。这也是即时生产的魅力所在。

尽早生产与实时生产的两处计划的具体制定方式

  上面讲解了尽早生产与实时生产两种原则的区别和各自的优劣,大家需要跟据自己的具体场景去采用,下面我们就针对这种原则的排产方式展开讨论。先不讲这两种制定计划的原则,在生成规划引擎Optaplanner上的实现方式的区别。假设我们是生产计划员,面对这两种原则,我们应该如何制定生产计划呢?

  先说尽早生产,其实说白了,就是有一个产品的一系列生产任务,一旦准备就绪了,就可以将它排入计划中,且排在时间轴上越靠前越好,不同工序对应的生产任务,在遵循固定的工序先后时间关系的基础上,越早开始越好,正常情况下上下任务之间是FS关系(即必须等上工序完成了,下工序才能开始),而在精益的优化流程中,特别是一些离散制造的场景,是可以实现SS的(即是上一工序一旦有工件完成,即可对这些工件开始下一工序的加工)。所以不同工序对应的任务是致密的,从而很好地实现了尽早生产。所以,我们可想而知,对于尽早生产原则下的生产计划,它是基于每个任务的就绪时间进行排产的,也就是说一个任务一旦就绪了,那么它在生产计划中的开始时间就是就绪时间的下一个时间单位了(这个时间单位可能是分钟或各车间自己制定的最小时间间隔)。当一个产品的首个工序时间在生产计划中确定了,按尽早生产的原则,可能推算出这个产品的后下所有生产工序对应的加工任务的最早开始时间,因为可能存在资源上的限制,并不一定能够在每个工序对应加工任务的最早开始时间开始加工,但还是遵循了尽早计划的原则,就是一旦上工序生产完了,当前这个工序的资源就位了,那就可以开始生产。如果按照上述的原则定制出来的生产计划,在甘特图上可以看到,所有生产任务都是尽可以靠前的且尽量致密的。

  再说说即时生产。上面已经说过,即时生产的原则是供应链最后一个环节来驱动的,同样地在供应链中的生产环节里,也是基于最后一个生产工序来驱动所有生产工序的加工任务的。也就是说,最后一个工序(例如包装)的生产任务要求什么时间要完成的,那就基于这个完成时刻 ,往前推算(例如,在要求完成时间,减去加工任务的时长,再减去一些准备时间等),就可以推算出前一个工序的生产任务的要求结束时间.....如此类推,就可以推算到整个产品的首个工序的生产任务的开始时间,从而得到所有生产任务的具体生产时间(包括开始时间与结束时间)。因为这种方式下制定生产计划是从后而往前推算的,所以从计划的甘特图上看,所有任务在时间思上是尽量往后靠且致密的。

Optaplanner对尽早开始与即时生产两种计划的实现方式

  上面我们已经知道,我们的生产计划人员,是如何排出尽早开始与实时生产两种计划的。如果我们使用规划引擎Optaplanner来辅助我们智能快速地制定这两种生产计划,应该如何设计呢?首先需要交待一下 Optaplanner在处理这些时间分配的要求时,它是如何实现的。通过前面Optaplanner系列文章中一些简单的示例我们知道,Optaplanner做规划的基本方法,就是对于被规划对象(例如生产任务),从可能的资源列表中,取出相应的资源对各个被规划对象进行尝试,通过分数的计算对比来确定资源应该如何分配才得到更好的方案。这里面的资源通常都是一些具体的物理物件,例如机台、工人等.没有提及时间这种资源是如何实现分配的呀。而我们所有的生产计划,事实上也就是在两个维度上的资源分配;分别是时间与空间上的分配,就是确定一个被规划对象的时空。例如确定一个任务应该分配在哪一个机台上(空间),需要在什么时候开始生产,需要在什么时间结束(时间)。事实上,Optaplanner的设计者早已考虑到这个问题,并提供了较完善的实现方案。针对时间维度的分配,Optaplanner提供了三种模式来实现(见图Assigning time to planning entitis),对于这三种模式,在Optaplanner系统列文章中,也将会有专门文章会讲解,在此不展开。在这三种模式中,其中一种叫做Chained Through Time pattern模式,我面对过一些复杂的排产场景,经过多翻尝试和掉过各种坑,还是觉得这种模式最为适合,它可以提供三种时间分配模式中最为丰富和灵活的接口,供我们实现一些特殊的需求,具体的应用再去参考相关文章,在此真的不够篇幅展开。这个模式的原理是,Optaplanner并不是分配哪个时间资源到哪个任务里去,而是对于所有的被规划对象,Optaplanner会把它们串成一个链(见图Chain principles),一个接着一个,Optaplanner要尝试规划的是这些被规划对象在链上的位置,它体现为当前的被规划对象,它的前一个对象是谁,每个对象有一个属性用于指向它在链中的前一个对象,而这个属性就是它的Planning Variable. 并且,Optaplanner提供了接口,当这个Planning Variable因当前对象在不同的链之间切换,或在同一个链中的不同位置切换的时候,这个接口可以让你告诉Optaplanner这个位置切换影响了被规划对象的另外的哪些属性(见图Planning Variable Listener),这些被Planning Variable的变化而被影响的属性就叫做Shadow Variable.这样的话,我们就可以应用这种机制,把Shadow Variable定为被规划对象(下面就以制定生产任务为案例,将被规划对象称作任务,这样更容易理解)的开始时间。那么我们就有:当一个任务处在不同链的不同位置时,它的开始时间就会受影响了。具体的实现方法是,当一个任务的位置变化前后(其实体现为它的前一个任务变化了),Optaplanner会触发关于这个前任务变的一系列事件。我们就在这些事件的处理方法中,去推算这个任务的开如时间,完成修改后,需要通知Optaplanner进程我们的修改,让它去计算分数来评价这个方案的优劣。从而实现了任务的位置变化,影响了开始时间,开始时间的变化,就可以推算出具体的结束时间。


  其实上面是我们在使用Chained Through Time pattern模式最常用的情景。如果实现了上述的方案,就已经排出了尽早生产的计划了。因为每个任务变化的时候,我们推算的都是它的开始时间。当然这个开始时间不仅仅是依据当前任务的前一个任务的结束时间推算出来的,还需要参照当前任务的就绪时间(若有的话),和当前任务的准备时间(若有的话)。但即使考虑了这些因素,它仍然是尽早开始的。那么如果我们而对的项目是需要实行精益生产的,需要实现即时生产的,应该如何做呢?其实大概的实现方式是一样的,只不过需要把生产任务形成的这条链的方向从时序上反转。在尽早生产的场景下,在链上的是以首个任务的开始时间作为基点,推算后面的其它任务的时间,进而推算其后方的其它任务的开始与结束时间。在即时生产的场景下,因为是由后工序驱动的,我们可以反过来,链的起头不再是首个任务的就绪时间了,而是最后一个任务的结束时间作为基点,往前推它的开始时间,而在链上的下一个下任务,而实在业务上对应的是它的上一个工序对应的任务,如此推算出来,就得到上一任务的结束时间,进而推算它的开始时间,如此类推,计算整条链的所有任务的结束时间与开始时间,在链尾就得到首个任务的开始时间了。把它反映在计划甘特图上,所有任务都是趋紧向后工序的,也就是实现了即时生产了。当然,上述提到的缓冲机制,大家应该很容易理解,也很容易在链中实现。

前推式计划 - 尽早生产,后拉式计划 - 即时生产

  通过上的两种计算的生成过程,大家应试注意到一个细节,就是尽早生产,它是基于第一个任务的就绪时间来向后推算后面任务的时间。形象点就是说,它一旦定好了开始时间,就按这个时间往后排计划了,就是告诉引擎,反正我这个时刻开始的,你就按这个时刻,根本必要的考虑因素和约束,从前往后推算出一个计划来吧。所以我们把它称为前推式生产计划。而另外一种即时生产原则下的生产计划,它是相反的,它确定了最后一个任务的开始时间,再往前推算前面各个任务的结束与开始时间,其实也是往前推算出来的时间。但因为它是基于供应链中的最后一个环节来驱动前面的生产活动的,所以我们形象地把它称为后拉式计划。也就是说,反正我定了哪个时刻需要完成的,你们前面的任务就贴着这个时间来安排结束时间和开始时间吧,就像从最后一点把前面的任务往后拉出一个生产序列来,因此我们把它称作后拉式生产计划。

  至此,我们分别探究了尽早生产(前推式生产)和即时生产(后拉式生产)两种排产原则的考虑因素,计划方案和在规划引擎Optapalnner上的实现原理。具体的实现我将会通过两篇文章来描述,一篇用于描述Optaplanner对时间的分配模式;另一篇将会以Chained Through Time pattern模式为基础,以生产任务的制定过程,探究一下Optaplanner是如何实现复杂场景下的生产计划制定的。例如目前我负责的一个排产项目,及一些朋友的产品中,就涉及一些任务之间的先后次序制约,任务之间需要根据条件放置一些不属于常规生产任务的操作等。这些林林总总的奇怪而又现实的要求,如果仅仅使用Optaplanner最基本的Planning Entity + Problem Fact进行规划的模式,是无法实现的。需要通过Chained Through Time pattern模式提供的事件接口,来实现一些我们自己的业务逻辑,才有可能把这些现实的业务需求体现在生产计划中。



如需了解更多关于Optaplanner的应用,请发电邮致:[email protected]
或到讨论组发表你的意见:https://groups.google.com/forum/#!forum/optaplanner-cn
若有需要可添加本人微信(13631823503)或QQ(12977379)实时沟通,但因本人日常工作繁忙,通过微信,QQ等工具可能无法深入沟通,较复杂的问题,建议以邮件或讨论组方式提出。(讨论组属于google邮件列表,国内网络可能较难访问,需自行解决)

原文地址:https://blog.51cto.com/1363562/2381036

时间: 2024-10-11 22:51:24

排产的两种方式(前推式与后拉式)在Optaplanner上的体现的相关文章

第六篇、文件处理之文件修改的两种方式

目录 第六篇.文件处理之文件修改的两种方式 说明 方式一 方式二 总结 第六篇.文件处理之文件修改的两种方式 说明 文件的数据是存放在硬盘上的,所以只能覆盖,不能直接修改,平时看到的修改文件都是障眼法的效果,具体的两种实现方式 方式一 将硬盘里的文件全部加载到内存里,内存是可以直接修改的,修改完了后,再由内存覆盖到硬盘里 import os with open('37r.txt') as fr, open('37r_swap.txt', 'w') as fw: data = fr.read()

CSharpGL(18)分别处理glDrawArrays()和glDrawElements()两种方式下的拾取(ColorCodedPicking)

CSharpGL(18)分别处理glDrawArrays()和glDrawElements()两种方式下的拾取(ColorCodedPicking) 我在(Modern OpenGL用Shader拾取VBO内单一图元的思路和实现)记录了基于Color-Coded-Picking的拾取方法. 最近在整理CSharpGL时发现了一个问题:我只解决了用glDrawArrays();渲染时的拾取问题.如果是用glDrawElements();进行渲染,就会得到错误的图元. 本文就彻底解决这个拾取的问题.

获取Executor提交的并发执行的任务返回结果的两种方式/ExecutorCompletionService使用

当我们通过Executor提交一组并发执行的任务,并且希望在每一个任务完成后能立即得到结果,有两种方式可以采取: 方式一: 通过一个list来保存一组future,然后在循环中轮训这组future,直到每个future都已完成.如果我们不希望出现因为排在前面的任务阻塞导致后面先完成的任务的结果没有及时获取的情况,那么在调用get方式时,需要将超时时间设置为0 Java代码 public class CompletionServiceTest { static class Task impleme

六、栈的实现两种方式

前言:栈的特点:先进先出,只在栈顶进行操作.栈低密封,不进行操作,栈的实现有两种方式,通过对线性表实现进行复用.安全性高. 实现栈的方式: 第一种:以顺序结构的方式实现:将顺序表的队尾作为栈顶 第二种:以链式结构的方式实现:将链式表的队头作为栈顶 第一种实现方式(顺序结构): 1.SeqList.h #ifndef _SEQLIST_H_ #define _SEQLIST_H_ typedef void SeqList; typedef void SeqListNode; SeqList* Se

springboot 注册服务注册中心(zk)的两种方式

在使用springboot进行开发的过程中,我们经常需要处理这样的场景:在服务启动的时候,需要向服务注册中心(例如zk)注册服务状态,以便当服务状态改变的时候,可以故障摘除和负载均衡. 我遇到过两种注册的途径: 1.在Spring的webapplication启动完成后,直接进行注册: 2.在servlet容器启动完成后,通过listener进行注册. 本文通过一个demo讲述一下这两种注册方式,使用的是传统的向zk注册的方案. 1.Spring webapplication启动完成后注册 先上

Java连接Neo4j的两种方式

1.Neo4j数据库的两种方式 Neo4j可以以两种方式运行: Java应用程序中的嵌入式数据库 通过REST的独立服务器 不管哪一种方式,这个选择不会影响查询和使用数据库的方式. 它是由应用程序的性质(无论是独立服务器还是客户端服务器),性能,监视和数据安全性驱动的架构选择. 1.1Neo4j Server(服务器式数据库) Neo4j Server是互操作性,安全性和监控的最佳选择. 实际上,REST接口允许所有现代平台和编程语言与它进行互操作. 此外,作为独立应用程序,它比嵌入式配置更安全

em创建的两种方式

em创建(两种方式1,图形dbca,当然了,前提是先创建一个监听. 2,手工命令安装em)手工命令创建em(确保数据库开启,确保监听正常并且最好是动态监听,确保system表空间够用大概1G左右),我的空间有限只给了800M,如下 select file_name,tablespace_name,bytes/1024/1024 from dba_data_files where tablespace_name like 'SYSTEM';alter database datafile '/u01

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用

使用库函数API和C代码中嵌入汇编代码两种方式使用同一个系统调用 选择调用的进程为 24 i386 getuid sys_getuid1647 i386 getgid sys_getgid16 使用库函数API方式 使用C代码中嵌入汇编代码方式

Java并发编程:线程间协作的两种方式:wait、notify、notifyAll和Condition

在前面我们将了很多关于同步的问题,然而在现实中,需要线程之间的协作.比如说最经典的生产者-消费者模型:当队列满时,生产者需要等待队列有空间才能继续往里面放入商品,而在等待的期间内,生产者必须释放对临界资源(即队列)的占用权.因为生产者如果不释放对临界资源的占用权,那么消费者就无法消费队列中的商品,就不会让队列有空间,那么生产者就会一直无限等待下去.因此,一般情况下,当队列满时,会让生产者交出对临界资源的占用权,并进入挂起状态.然后等待消费者消费了商品,然后消费者通知生产者队列有空间了.同样地,当