在前一篇关于APS系统设计分享文章(《APS系统设计经验分享(时间推导 - 2023.03)》)中,我们提到将会分享使用OptaPlanner作为规划引擎开发APS系统过程中,遇到的一些时间相关的设计建议与异常情况分析。后来一直忙于项目工作,直到现在才想起仍欠着这一篇,今天趁着给自己一点休息时间,把它总结一下,好让有类似设计场景的朋友们稍作参考。
任务加工时间受资源时间制约
任务加工的开始时间与完成时间,除了遵循工单、前后工序等时间限制外,还受资源可用性的限制。即一个时间段是否有足够的资源量用于任务加工,资源量是否充足制约着任务的开始与结束时间。对于任务的时间限制,需要分别从可再生资源(即设备、人员等)与非可再生资源(通常表示物料)两个方面考虑。这两种资源,在我们的易排平台中定义如下:
可再生资源
在时间轴上的不同时刻,资源的可用量不存在相关性,我称为可再生资源。例如设备、人员等资源,第1天分配了多少任务,并不影响第二天的产能。即只要任务不跨天,第2天的产能会"再生出来"。
非可再生资源
在时间轴上的不同时刻,资源的可用量存在相关性,称为非可再资源。例如生产原料,耗材等消耗性物料,在一定库存量的基础上,第1天的消耗量将会影响第二天的可用量。即第1天消耗的物料,第2天不会再重新生成。
可再生资源的资源日历与资源可用性
资源日历
大多数资源不可能 7 x 24工作,也不可能所有任务都能在一个班次(8或12小时)内完成,那么如何对资源的这些不规则时间片段与进行合理的表达呢?常见的APS产品,及我们的易排规划平台上都使用了资源日历的概念,为资源提供时间维度的资源量定义。即通过资源日历定义一个资源在什么时候有多少量可用。一些日常常规的、具有共通性的时间安排,可以通过资源日历来定义,当我们设计好一个日历后,适用于该日历的资源可共用该日历,从而大大减少各个资源独自设定工作时间的冗余工作。例如一个3班倒的加工企业,只需定义好早中晚班3个班次的工作时间,各个班组(每个班组可视作一个资源)直接套用适合自己的日历即可。那么从一个班组的角度来看,他们所在时间段的资源可用量是班组的成员人数,其它时间段(班组休息时段)资源可用量为0(即无人上班),引擎在对任务进行资源冲突判断时,休息时段将会被视作资源不足,从而不会安排任务在这些休息时段开始工作。
要实现这个逻辑,我们在设计一个任务的计划开始时间与计划结束时间过程中,就需要结合资源日历来推导开始时间与完成时间。
资源可用性
资源可用性是资源日历的补充与修订,前者通常用于资源的日常工作安排,后者则用于资源的特殊个性化工作时间设定。例如,一个设备原来按一周6天,每天20小时的资源日历安排作息时间,但当该资源遇到意外停机时,或该设备被分配于加工一个长周期的任务,在未来数天都不能再分配给其它任务时;这些停机的时间无法在资源日历上反映,而是通过资源可用性,针对性地为该设备提供其特殊的作息信息。当资源日历与资源可用性存在冲突时(例如同一资源的资源日历与可用性存在时间重复,或同一时间上的资源可用量不一致),以资源可用性为准。
资源日历与资源可用性综合在一起,成为一个资源的真正作息时间。基于作息时间,在设计引擎的规划逻辑时,如何利用这些时间安排,令到任务安排遵循作息要求呢?
示例
下面我们以具体案例方式细说一下,基于不固定资源工作时间条件下,具有静置时间要求的任务,实现前推式排程与后拉式排程的扮演过程。
静置时间的定义是:加工完一个工序后,需要等待一定的时候,其后置工序才能开始。例如一个工件完成喷漆工序的一,需要等待4个小时才能进行下一个工序,则称这喷漆工序的静置时间为4小时。
因为一个资源在时间轴上不同的时刻, 有休息(资源可用量等于0)与工作(资源可用量大于0,通常为1)两种状态. 规划过程中,假设一个工单有以下3个任务,以它们的前后关系以任务编号为序,形成前后依赖, 即 1 -> 2 -> 3
工单的就绪时间(时间索引)为0, 交付时间为21. 即工单在第0天才能开始, 必须在第21天前完成. 排程方式,分别有正排(前推式排程)和倒排(后推式排程)两种方式.下面分别讨论这两种排程方式的时间推导过程。
正向排程
当一个任务被分配到资源时, 若属于正排(即前推式排程), 则基于工单就绪时间, 往后推导各个任务的计划开始时间与计划结束时间,当遇到休息时间时,根据情况延后开始或结束, 推导过程逻辑如下图:
通过图3可知:
-
任务1:从时间第0天开始加工,经历第1,2两天休息后,在第4天完成加工生产, 并使用第5天作为静置时间;
-
任务2: 从第6天开始加工,经过第8, 9和12三天休息后,在第14天完成生产, 并在第15天作为静置时间, 虽然第15天是休息日,但静置时间并不占用资源,因此在第15天完成静置;
-
任务3: 跳过第16天(休息日),从第17开始加工, 在第18天完成加工, 至少整个工单在第18天完成, 早于第21天, 满足排程目标.
总结:当使用正向排程时, 首个任务(任务1)从工单的就绪时间开始生产, 最快可以在第18天可以完成整个工单中所有任务.
反向排程
当一个任务被分配到资源时,若属于倒排(即后拉式排程), 则基于工单的交付时间,往前推导工单中各个任务的计划开始赶时间和计划结束时间,遇到资源休息时间则根据实际情况提前开始. 推导过程逻辑如下图:
通过图4可知:
-
任务3:需要在第21天完成的话,则需要从第20天开始加工;
-
任务2: 因为任务2有1天的静置时间,因此根据任务3的开始时间(索引20)进行推导,第19天为任务2的静置时间,因此其结束时间为第18天, 根据其加工时长,得到开始时间为第10天.
-
任务1: 任务2需要在第10天开始的话,通过推导任务1必须在第7天完成, 并使用第8天作为任务1的静置时间, 尽管第8天是休息时间,但静置时间并不占用资源,因此可以把第8天作为静置.若任务需在第7天完成的话,则需要在第5天开始加工.
总结:当使用反向排程时, 末个任务(任务3)从工单的交付时间作为最晚生产时间, 往前推导,首个任务需要在第5天开始.
非可再生资源的库存量与入库计划对任务的影响
除了可再生资源(通常用于表示设备、人员等)的作息时间安排对任务的开始、结束时间产生制约作用,非可再生资源(通常用于表示物料)同样也会对任务的时候安排产生影响。若待排数据中,非可再生资源仅存在库存量一个数量相关信息,则表示在该规划周期内(例如一个星期),可安排对某种物料存在依赖关系的任务,其物料的总要求量不能超过该物料的库存量。如下图:
一个星期内硫酸的库存量为200升,现有三个任务:任务1要求120L;任务2要求50L,任务3要求90L。在这一周的计划内,引擎按照资源量足够的前提下,尽可能安排多任务的原则,会得到一个方案如下:安排任务1与任务2在本周内执行,任务3因为资源不足,需要延后在本周以后才能执行。
若一个物料除了提供初始状态时的库存量,还提供了计划周期内的补货计划(即在什么时候入库多少资源量),则引擎将会在库存量的基础上,还考虑补货计划,对生产计划作进一步优化。如下图:
计划初始状态的硫酸库存量与上面一致200L,同样也有3个任务,对硫酸的需求量也一样。但本次计划中,周三将有100L补充进库存,因此,3个任务都可以在本周内开始执行,只是其一个任务(例如上图中的任务3)需要等到周三的入库补充后才能执行。从而得到更精确的计划时间控制。
因时间计算逻辑,引起的OptaPlanner各种Corruption问题
在处理时间推导逻辑过程中,经常遇到本来很正常的程序,加上一些时间推导逻辑后,就会出现“Score corruption”,"UndoMove corruption"与"Variable Listener Corruption". 这些异常产生的原因有很多,出现在计划启动阶段都是因为问题对象的数据不符合OptaPlanner对规划空间的一致性要求而导致的。
我们知道,OptaPlanner在规划运算过程中,会使用栈结构来保存两个相邻方案的分数变更过程,当一个方案的评分为100分时,引擎会将它保存在栈中,并进行下一步探索,完成下一步探索后得到的新分数再压进栈中,例如得到新分数为110分,然后,再进行逆操作回到上一个分数为100的方案,但这个逆操作不是通过直接的变更回撤,而进行一个称为UndoMove的操作(因此被为doMove的逆操作),并计算逆操作得到的分数是否等于原方案的100分。当逆操作得到的分数不是100分时,就会抛出一个undoMove corruption的异常消息,表示引擎在进行探索过程中,出现逆操作得到的分数与原来的原始位置分数不一致。若doMove -> undoMove的过程存在异常,可证明这一步(即这个Move)的评分逻辑存在缺陷。这是最简单的一种异常,过程如下图。
规划运算的一致性原则
但其实在进行规划运算之前,引擎还会对传进来待求解问题对象进行一次合规性检验过程,该验证过程通过后,才会启动真正的规划运算,即Construction heuristic过程(启发式构造过程,简称CH阶段)。在合规性检验过程中,会进行方案分数评估以及影子变量侦听更新过程的合规性检验。此过程与规划过程中出现的Listenr Corruption的原理一致。总结为:你所提交问题对象的初始状态,必须符合规划运算中的一致性原则,否则引擎就无法进行启发式构造,形成一个用于寻优的启始化方案,进而对后续优化就无从谈起了。
这些一致性原则中,很大一部分是我们在构造任务的时间维度的逻辑时,隐藏在实现代码中的缺陷造成的,例如:同时当一个任务存在静置时间的任务,在资源日历复杂性较强的资源上进行时间推导时,对任务的结束时间进行推算过程中,因为存在某些逻辑错误,导致同一个方案的两次推算得出不同的分值。例如上述doMove与UndoMove所使用的逻辑中,因时间运算逻辑考虑不周,导致两个步骤的评分不一致。这也是易排平台首次实现静置时间与资源日历,综合推导各种时间过程中,遇到的首个较难解决的UndoMove Corruption问题。当然也有一部分是违反了OptaPlanner规划中的某些变量修改原则,例如存在某些代码变更了Problem Fact的值,而造成的
可以从OptaPlanner开发手册的以下一句话得到总论。当然文档对于一致性原则有详细讲解,需要细心阅读结合一定的开发积累,很容易识别引擎的这些构造要求。
这个警告是描述一个关于各个变量之间互成影子变量的情况需要遵守的原则,但其实在上述提到的时间一致要求时,应该遵守同样的一致性原则,否则就会出现异常。而且因为时间推导过程出现的违反一致性原则与业务相关性较强,OptaPlanner的开发手册中并没有显示提及,需要通过一定的积累调试才能总结。
与易排平台相关疑问,可以添加本人微信(13631823503)探讨,或关注我们的公众号【让APS成为可能】及时接收相关消息。
【完】