CLPFD和无限可数域

时间:2016-06-01 13:50:43

标签: prolog clpfd

I #> 0, I #< 10, indomain(I).

之前的代码显然会执行以下操作:

I = 1 ;
I = 2 ;
I = 3 ;
I = 4 ;
I = 5 ;
I = 6 ;
I = 7 ;
I = 8 ;
I = 9.

以下代码不起作用(参数未充分实例化):

I #> 0, indomain(I).

现在我明白在这种情况下,I有无数可能的绑定,而且CLPFD的名称也适用于有限域。

但是我不明白为什么在这种特殊情况下存在这种限制。是不是可以列举从最小到最大规范的可能解决方案,并获得以下内容:

I = 1 ;
I = 2 ;
I = 3 ;
.
.
.

即使存在多个变量的问题,请说:

0 #< I, I #< J, label([I,J]).

为什么不能实现它,以便发生以下行为:

I = 1,
J = 2 ;
I = 1,
J = 3 ;
I = 2,
J = 3 ;
I = 1,
J = 4 ;
.
.
.

简而言之:为什么CLPFD仍然适用于无限域,如果这些域很容易用振幅计算?

2 个答案:

答案 0 :(得分:6)

原因是CLP(FD)保留了以下重要属性:

  

如果谓词p(Vs) 终止 ?- p(Vs), label(Vs). 终止普遍。

目标G 普遍终止 iff ?- G, false. 终止

为什么这么重要?因为CLP(FD)程序通常由两部分组成:

  1. 发布所有约束
  2. 寻找解决方案。
  3. 通过简单的检查,通常很容易证明建模部分(1)普遍终止。但是(2)是通常占用大部分计算时间的困难部分,而且通常我们不知道先验是否存在单一解决方案。搜索部分可能会运行数天,数月或数年而不会产生结果。

    许多Prolog初学者描述了一个搜索任务,运行它,并在几秒钟后抱怨Prolog很慢。事实上,事实证明,他们经常意外地编写不终止的程序,并且永远不会找到解决方案。

    由于这些原因,令人鼓舞的是,如果您只能显示(通常可以,也很容易)部分(1)终止,那么您的整个程序 - 部分(1) part(2) - 终止。

    完全正确的是,任何可数无限的搜索空间都可以通过您描述的方式系统地覆盖到任何有限的范围。但是,这样做会破坏这种基本的不变性。您必须能够依靠以下属性才能应用上述推理:

      

    label/1labeling/2indomain/1 始终终止。

    在SWI-Prolog和YAP中,这是通过设计确保的。在其他系统中,它有不同程度的保留。

答案 1 :(得分:2)

没有理由不在CLP(FD)中允许无限域枚举。以来 当 user:mat 正确地观察到约束本身终止时,如果存在解决方案,无限枚举可能会找到解决方案。

基本上我们有:

  

约束终止普遍,即(#=)/ 2,(#=&lt;)/ 2等。给   完全实例化时为true或false,并且不发散。

然后我们观察:

  

约束的标记以存在的方式终止,即它发现   如果我们也可以枚举多个问题,那么在一段时间后解决问题   公平的无限领域。

所以主要的问题是以公平的方式枚举多个无限域,因为当我们不以公平的方式枚举时,我们可能会误入域的一个子集而不能找到解决方案,即使存在一个。我想到了以下枚举多个无限域的方法:

1)取消配对功能
使用函数unpair:N - &gt; NxN,仅枚举此函数的参数。这是一个旧的Mathematica技术:An Elegant Pairing Function。每次都需要计算平方根的缺点。

2)公平合作
使用公平的连接来组合无限的枚举器。这是一种应用于函数式编程的技术,例如参见:Backtracking, Interleaving, and Terminating Monad Transformers。缺点连接在常量内存空间中不起作用,会产生越来越多的右侧枚举器实例。

3)额外变量
使用额外变量H和额外约束,例如H = abs(X1)+ .. + abs(Xn)用于cantor配对。然后,您可以枚举此变量并让约束求解器完成剩余的工作。对于您可能会早期修剪的某些值的优势。

Jekejeke Minlog我们最近选择了变体3.以下是枚举毕达哥拉斯三元组的示例:

?- use_module(library(finite/clpfd)).

?- [X,Y,Z] ins 1..sup, X*X+Y*Y #= Z*Z, label([X,Y,Z]).
X = 3,
Y = 4,
Z = 5 ;
X = 4,
Y = 3,
Z = 5 ;
X = 6,
Y = 8,
Z = 10 ;
X = 8,
Y = 6,
Z = 10 

一般情况下,当使用无限标记时,人们将尝试解决Diophantine Equation,它不总是一个解决方案,这甚至不是可判定的,我们知道在希尔伯特的第十个问题出现之后。因此,甚至无法保证普遍终止。

另一方面,如果有解决方案,您可能会在一段时间后找到它,前提是解决方案不是太大并且会超出计算机内存空间和计算时间的限制。但这不应该导致您的计算机崩溃,一个体面的Prolog系统实现应该优雅地返回顶级。您也可以打断翻译或停止要求进一步的解决方案。

再见