有人可以提供一个引用约束的简单示例吗?
通道约束用于组合约束问题的视点。约束编程手册很好地解释了它是如何工作的以及为什么它有用:
搜索变量可以是其中一个视点的变量,比如X1(这将在下面进一步讨论)。如 搜索继续进行,传播约束C1从域中删除值 X1中的变量。然后,信道约束可以允许从中移除值 X2中变量的域。使用约束传播这些值删除 第二个模型C2可以从这些变量中删除更多值,并再次从这些变量中删除 可以通过引导约束将删除转换回第一个视点。该 净结果可以是在视点V1内除去约束之外的更多值 仅C1,导致搜索量减少。
我不明白这是如何实现的。究竟是什么限制,它们在真正的问题中看起来如何?一个简单的例子非常有用。
答案 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) )
将在T
和Bs
之间传播信息。实现此通道的另一种方法是特殊用途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)
再见