[英]SWI Prolog CLP(FD) scheduling
我正在使用CLPFD库解决SWI Prolog中的计划任务。 由于这是我第一次解决比情感问题更严重的事情,因此我可能需要经验丰富的用户提供一些好的建议。 让我简要地描述领域/任务。
我有一个月历。 每天一整天有2个,整夜有2个(长期12小时服务)。 另外,只有周一至周五10个工人8小时(短期服务)。
域约束显然是:
我的方法如下:
对于日历中的每个字段,我都有一个定义的变量:
DxD_y
,其中x
是一天的日期, y
是1或2(对于长日服务) DxN_y
,其中x
是一天中的天数, y
是1或2(对于长夜服务) DxA_y
,其中x
是日数, y
是0 .. 9对于短日服务 SUM_x
,其中x
是表示工作时间的总和的工作人员编号(1..19) 每个D
变量都有一个域1..19
。 为简化起见,每个X
SUM_X #=< 200
。
all_distinct()
-每个工作人员每天只能提供一项服务 global_cardinality()
来计算的出现次数为短服务和长期服务列表中的每个数字1..19 -这个定义变量LSUM_X
和SSUM_X
-工人的出现次数X
的L
翁或S
园艺服务 SUM_X #= 12*LSUM_X + 8*SSUM_X
每个工作人员SUM_X #= 12*LSUM_X + 8*SSUM_X
DxN_y #\\= Dx+1D_z
避免在一夜之后进行全天服务
DxNy #= Dx+1Ny #==> DxNy #\\= Dx+2Ny
为避免连续三个夜间服务, x
和y
每种组合都有约束 所有变量和约束条件都直接在pl脚本中说明。 我不使用prolog谓词来生成约束-因为我在.NET应用程序(前端)中有一个模型,并且可以轻松地将所有内容从.NET代码生成为prolog代码。
我认为我的方法总体上是好的。 在一些较小的示例上运行调度程序效果很好(7天,4个长期服务,1个短期服务,8个工人)。 同样,在完整的案例中,我也能得到一些有效的结果-30天,19名工人,每天4个长期服务和10个短期服务。
但是,我对目前的状态并不完全满意。 让我解释一下原因。
utilize the first worker for 100% and then grab the next one
。 因此,解决方案中的SUM看起来像[200,200,200...200,160,140,80,50,0,]
。 如果工人或多或少地得到同等的利用,我将感到高兴。 是否有一些简单/有效的方法来实现这一目标? 我曾考虑过定义一些定义,例如定义工作人员之间的差异并将其最小化,但这对我来说听起来很复杂,而且我担心我会花很多时间来计算出来。 我使用labeling([random_variable(29)], Vars)
,但它仅对变量进行重新排序,因此仍然存在这些差异,只是顺序不同。 可能我想labeling
过程将以不同于up
, down
(以某种伪随机方式)的其他顺序来获取值。 bisect
选项标记需要很长时间。 如果需要,我可以提供更多代码示例。
有很多问题,让我尝试解决一些问题。
...仅针对我的变量(日历字段)和worker的每种组合引入布尔变量,以标记是否将worker分配给特定的日历字段。 这是更好的方法吗?
通常,当使用MILP(混合整数线性规划)求解器时,必须将较高级别的概念(如alldifferent
等)表示为线性不等式,才能完成此操作。 这样的公式通常需要大量的布尔变量。 约束编程在这里更加灵活,并且提供了更多的建模选择,但是不幸的是,没有简单的答案,这取决于问题。 您对变量的选择会影响表达问题约束的难度以及解决效率。
因此,解决方案中的SUM看起来像[200,200,200 ... 200,160,140,80,50,0,]。 如果工人或多或少地得到同等的利用,我将感到高兴。 是否有一些简单/有效的方法来实现这一目标?
您已经提到了最小化差异的想法,这就是通常要实现这种平衡要求的方式。 它不需要复杂。 如果最初我们有这个不平衡的第一个解决方案:
?- length(Xs,5), Xs#::0..9, sum(Xs)#=20, labeling(Xs).
Xs = [0, 0, 2, 9, 9]
那么只需最小化列表元素的最大值,便已经为您(结合总和约束)提供了一个平衡的解决方案:
?- length(Xs,5), Xs#::0..9, sum(Xs)#=20, Cost#=max(Xs), minimize(labeling(Xs),Cost).
Xs = [4, 4, 4, 4, 4]
Cost = 4
您还可以最小化最大值和最小值之间的差异:
?- length(Xs,5), Xs#::0..9, sum(Xs)#=20, Cost#=max(Xs)-min(Xs), minimize(labeling(Xs),Cost).
Xs = [4, 4, 4, 4, 4]
Cost = 0
甚至平方和 [对不起,我的示例是针对ECLiPSe的,而不是SWI / clpfd的,但应显示出大致的思路。]
我应该如何订购约束? 我认为约束的顺序与标签的效率有关。
您不必为此担心。 尽管它可能会产生一些影响,但是它太不可预测了,并且在很大程度上取决于实现细节,因此无法提出任何一般性建议。 这确实是求解程序实现者的工作。
如何调试/优化标签性能?
对于实际问题,您通常需要(a)针对特定问题的标签启发式方法,以及(b)各种不完整的搜索。 搜索树或搜索进度的可视化可以帮助定制启发式方法。 您可以在本在线课程的第6章中找到有关这些问题的一些讨论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.