而现实环境中,资源是有限的,且往往是在资源缺乏,并需要尽量满足制约因素情况下停止方案制定。在制定方案的时候,不同的公司,基于不同的经营战略,需要遵循不同的原则。即便是同一个公司,在不同的业务场景(例如淡/旺季),其需要遵循的原则也可能不同。例如旺季因为消费任务紧张,需要保证交期;而谈季相对来说可用产能会较富余,保证交期就会不太困难,进而又需要遵循另外一些原则,譬如尽量降低消费本钱等。而在这些原则之外,还有一种相对来说是比较固定,或者比较约定成俗的原则,就是尽早开端(As soon as possible),和即时消费(Just in time)。其中即时消费,是精益消费中的一个概念。本农上一家公司已推行了比较成熟的精益消费体系(精益绝对不是5S喔,更注重的是流程优化,识别并消除不增值活动,减省不增值但必需的活动)。所以当时设计APS系统时,很多时候就遵循即时消费的原则。此原则由整个供给链中最后一个环节驱动(例如出货环节),从而推动前工序的消费布置。而很多不太强调精益消费的制造企业,在老消费方案员来看,制定方案的时候,除了较低水平上实现批量消费,以便高资源利用率,而停止对小批量消费任务稍作停留等待外,通常是按尽早开端的原则停止的。因为通常人们的想法是,将来的消费任务和产能具有不可预见性,你不晓得将来会不会突然因为客户加单,机器故障等客观且不可控因素导致产能吃紧,甚至令消费单位措手不及。假设这种意外情况真的呈现,那么一开端使用尽早开端原则布置消费方案,令到后面的产能较富余,应对起这些“意外”起来,就相对轻松多了,这类原则下的消费方案优势就体现出来了。而实时消费原则,则有可能因为预留在较后时间的资源(例如机台产能)是比较“准确”的,那就相对按尽早开端原则制定的方案来说,就更加被动了。但即时消费原则下的消费方案,应对这种“意外”,也是有很多相应措施的。例如使用适当的缓冲机制,和实时方案机制来应对。缓冲机制就是根据过往历史经历,在按即时消费原则制定消费方案时,预留一定水平的冗余资源作贮藏,当呈现“意外”时,可以使用这些冗余的资源停止弥补。而实时方案相对来说“先进”一点了(先进二字加个引号,是因为这只是我觉得这种方法先进一点)。这种所谓的先进,主要体如今通过自动化的排产引擎,将方案制定到足够细致且准确,对任务的消费情况(包括既有任务的执行情况,资源使用情况和新任务的增加量等)停止实时监控,使方案实时地对这些情况作出反映,并及时给出新的应对方案。例如:当有新任务呈现时,即时更新新增的任务到方案中;有资源呈现突发意外(例如机台突然故障)也可以反映到方案中,并即时作出反映,及时给出修正后的方案。但通过实时方案是相对比较复杂的的方案,在OptaPlanner中也有real-time planning的功能,我将会在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形式提供的事件接口,来实现一些我们自己的业务逻辑,才有可能把这些现实的业务需求体如今消费方案中。
Constraint satisfaction solver (Java™, Open Source)
至此,我们分别探究了尽早消费(前推式消费)和即时消费(后拉式消费)两种排产原则的考虑因素,方案方案和在规划引擎Optapalnner上的实现原理。详细的实现我将会通过两篇文章来描绘,一篇用于描绘OptaPlanner对时间的分配形式;另一篇将会以Chained Through Time pattern形式为根底,以消费任务的制定过程,探究一下OptaPlanner是如何实现复杂场景下的消费方案制定的。例如目前我负责的一个排产项目,及一些朋友的产品中,就涉及一些任务之间的先后次序制约,任务之间需要根据条件放置一些不属于常规消费任务的操作等。这些林林总总的奇怪而又现实的要求,假设仅仅使用OptaPlanner最根本的Planning Entity + Problem Fact停止规划的形式,是无法实现的。需要通过Chained Through Time pattern形式提供的事件接口,来实现一些我们自己的业务逻辑,才有可能把这些现实的业务需求体如今消费方案中。