示例通道约束ECLiPSe

时间:2016-06-21 14:48:36

标签: prolog constraints clpfd constraint-programming eclipse-clp

有人可以提供一个引用约束的简单示例吗?

通道约束用于组合约束问题的视点。约束编程手册很好地解释了它是如何工作的以及为什么它有用:

  

搜索变量可以是其中一个视点的变量,比如X1(这将在下面进一步讨论)。如   搜索继续进行,传播约束C1从域中删除值   X1中的变量。然后,信道约束可以允许从中移除值   X2中变量的域。使用约束传播这些值删除   第二个模型C2可以从这些变量中删除更多值,并再次从这些变量中删除   可以通过引导约束将删除转换回第一个视点。该   净结果可以是在视点V1内除去约束之外的更多值   仅C1,导致搜索量减少。

我不明白这是如何实现的。究竟是什么限制,它们在真正的问题中看起来如何?一个简单的例子非常有用。

2 个答案:

答案 0 :(得分:5)

当在模型中,问题的各个方面以多种方式表示时,使用通道约束。然后,它们必须同步这些多个表示,即使它们本身并不模拟问题的某个方面。

通常,在使用约束对问题进行建模时,您可以通过多种方式选择变量。例如,在计划问题中,您可以选择

  • 每个作业的整数变量(指示哪台机器完成作业)
  • 每台机器的整数变量(表示它执行的作业)
  • 一个布尔矩阵(表明哪个作业在哪台机器上运行)
  • 或更具异国情调的东西

在一个足够简单的问题中,您可以选择最简单的表示形式来解决问题的约束。然而,在许多异构约束的现实问题中,通常不可能找到这样一个单一的最佳表示:一些约束最好用一种变量表示,另一些用另一种变量表示。

在这种情况下,您可以使用多组变量,并在最方便的变量集上制定每个单独的问题约束。当然,您最终会遇到多个独立的子问题,单独解决这些问题并不能为您提供整个问题的解决方案。但是通过添加通道约束,可以同步变量集,从而重新连接子问题。结果是整个问题的有效模型。

正如手册中引用的那样,在这样的表述中,只需对其中一个变量集(“观点”)进行搜索就足够了,因为其他变量集的值是由通道约束所暗示的。

在两个表示之间进行通道的一些常见示例是:

整数变量布尔数组: 考虑一个整数变量T,表示发生事件时的时间段1..N,以及一个布尔值Bs[N]数组,如果事件发生在时间段Bs[T] = 1 T { {1}}。在ECLiPSe:

    T #:: 1..N,
    dim(Bs, [N]), Bs #:: 0..1,

然后可以使用

设置两个表示之间的通道
    ( for(I,1,N), param(T,Bs) do Bs[I] #= (T#=I) )

将在TBs之间传播信息。实现此通道的另一种方法是特殊用途bool_channeling/3约束。

开始/结束整数变量布尔数组(时间表): 我们有整数变量S,E,表示活动的开始和结束时间。另一方面是一系列布尔值Bs[N],如果活动发生在Bs[T] = 1 T,则为 [S,E] #:: 1..N, dim(Bs, [N]), Bs #:: 0..1, 。在ECLiPSe:

    ( for(I,1,N), param(S,E,Bs) do Bs[I] #= (S#=<I and I#=<E) ).

可以通过

实现频道切换
Js[J] = M

双重表示作业/机器整数变量: 在此处,J表示作业M在计算机Ms[M] = J上执行,而双重制定M表示计算机J执行作业 dim(Js, [NJobs]), Js #:: 0..NMach, dim(Ms, [NMach]), Ms #:: 1..NJobs, < / p>

    ( multifor([J,M],1,[NJobs,NMach]), param(Js,Ms) do
        (Js[J] #= M) #= (Ms[M] #= J)
    ).

通过

实现渠道化
public static void checkTheCar(ParkedCar pc, ParkingMeter pm){
       // do something

}

设置变量布尔数组: 如果使用可以直接处理集变量的求解器(例如library(ic_sets)),这些可以反映到布尔数组中,表示集合中元素的成员资格。为此目的,库提供了专用约束membership_booleans/2

答案 1 :(得分:1)

这是一个简单的例子,适用于SWI-Prolog,但应该如此 也可以在ECLiPSe Prolog中工作(以后你必须使用(::)/ 2而不是(in)/ 2):

约束C1:

 ?- Y in 0..100.
 Y in 0..100.

约束C2:

 ?- X in 0..100.
 X in 0..100.

引导约束:

 ?- 2*X #= 3*Y+5.
 2*X#=3*Y+5.

所有在一起:

?- Y in 0..100, X in 0..100, 2*X #= 3*Y+5.
Y in 1..65,
2*X#=3*Y+5,
X in 4..100.

因此,渠道约束在两个方向都有效 减少C1的域以及C2的域。

有些系统使用迭代方法,结果是这种通道化 可能需要一段时间,这是一个需要的例子 在SWI-Prolog中计算1分钟:

?- time(([U,V] ins 0..1_000_000_000, 36_641*U-24 #= 394_479_375*V)).
% 9,883,559 inferences, 53.616 CPU in 53.721 seconds 
(100% CPU, 184341 Lips)
U in 346688814..741168189,
36641*U#=394479375*V+24,
V in 32202..68843.

另一方面,ECLiPSe Prolog眨眼间就做了:

[eclipse]: U::0..1000000000, V::0..1000000000, 
              36641*U-24 #= 394479375*V.
U = U{346688814 .. 741168189}
V = V{32202 .. 68843}
Delayed goals:
     -394479375 * V{32202 .. 68843} + 
     36641 * U{346688814 .. 741168189} #= 24
Yes (0.11s cpu)

再见