CLPB的不良特性

  • 本文关键字:不良 CLPB prolog clpb
  • 更新时间 :
  • 英文 :


library(clpb)目前在SICStus(原始版本)和SWI(按mat)中可用。让我很快来谈谈本质:

?- X = 1+1, sat(X), X = 1+1.
X = 1+1.
?-          sat(X), X = 1+1.
false.

因此,这与library(clpfd)的默认状态下存在的问题类似。

在这种情况下该怎么办?

更新:在mat的library(clpfd)中,现在有了用于此目的的函子# /1。理想情况下,伴随着运算符声明op(150,fx,#),我们现在可以写:

?- X = 1+1, #X #= Y.
ERROR: Type error: `integer' expected, found `1+1' (a compound)

为了确保完整的代数性质,必须声明:

:- set_prolog_flag(clpfd_monotonic, true).

现在,不明确的变量(因此,要么是整数,要么是表达式)会产生实例化错误:

?-  1 + 1 #= Y.
ERROR: Arguments are not sufficiently instantiated
?- 1 + 1 #= #Y.
Y = 2.

在这种情况下该怎么办?

同时,library(clpb)也保证了类似于library(clpz)/library(clfd)的单调性。在这种执行模式中,显式变量必须使用(v)/1进行修饰。

?- current_prolog_flag(clpb_monotonic,B).
B = false.                             % the default
?- sat(X).
X = 1.
?- set_prolog_flag(clpb_monotonic,true).
true.
?- sat(X).
ERROR: Arguments are not sufficiently instantiated
?- sat(v(X)).
X = 1.

在Scryer中,说:

?- use_module(library(clpb)).
   true.
?- asserta(clpb:monotonic).
   true.
?- sat(X).
   error(instantiation_error,instantiation_error(unknown(_67),1)).
?- sat(v(X)).
   X = 1.

是,CLP(FD)和CLP(B)中相同:

情况

CLP(FD),(+)/2在有限域中充当加法:

?- X = 1+1, X #= 2.
X = 1+1.
?- X #= 2.
X = 2
?- X #= 2, X = 1+1.
false.

CLP(B),(+)/2在布尔域中充当析取:

?- X = 1+1, sat(X)
X = 1+1
?- sat(X)
X = 1
?- sat(X), X = 1+1.
false

但现在要注意,这样的事情已经在普通的序言中发生了:

?- X = 3, X = 4.
X = 3.
?- X = 4, X = 3.
false.

问题

那么我们应该告诉学生什么呢?我不认为CLP(FD)或CLP(B)应对此负责。

它更根深蒂固,而且不可能陷入(=)/2,因此它所做的不仅仅是verify_attribute/3。

在理想世界中,(=)/2用代数运算,X=1+1不会失败,系统会看到1+1等于2(FD情况)分别为1+1等于1(B情况)。

但为此,Prolog系统将需要类型作为启动,否则(=)/2不能解释(+)/2,它有两种不同的解释在我们的例子中。

解决方案

解决方案是在需要特定类型的情况下避免使用(=)/2。在此我推荐阅读:

使用ECLiPSe的约束逻辑编程
Krzysztof R.Apt和Mark Wallace,
2006年5月16日,全文PDF

上面的文章稍微强调了散列符号(#)作为运算符(=)/2、(<)/2等的前缀的动机。它已经是一种类型注释了。本文中还有另一个前缀,即美元符号($)。

在ECLiPSe-Prolog中,散列符号(#)表示约束整数/1,美元符号($)表示约束实数/1。这些约束也可以独立使用,如以下示例所示:

?- integers([X,Y]), X = 3, Y = 4.5.
No
?- reals(X), X = [1,2.1,a].
No

回到(=)/2的非交换性问题。虽然(=)/2是不可交换的,但(#=)/2及其布尔兄弟当然是可交换的。我们有:

CLP(FD),(+)/2在有限域中充当加法,与(#=)/2交换存在:

?- X #= 1+1, X #= 2.
X = 2
?- X #= 2, X #= 1+1.
X = 2

CLP(B),(+)/2在布尔域中充当析取,并且具有sat/1和(=:=)/2的交换性:

?- sat(X=:=1+1), sat(X).
X = 1.
?- sat(X), sat(X=:=1+1).
X = 1

verify_attribute/3挂钩只会唤醒约束,这些约束可能会使Herbrand域统一失败。但是,在将术语分配给Prolog变量之前,它们无法实时评估术语。

只有唤醒的约束可能会将值分配给其他变量。但例如,verify_atribute/3的当前SICStus规范甚至建议不要直接执行此操作,而只在延续队列中执行。请参阅最近的SWI Prolog小组讨论。

长话短说:永远不要忘记,(=)/1只适用于Prolog中的Herbrand域,即使我们使用了约束。我并不是说Prolog系统不能以不同的方式工作,但这就是群体或Prolog系统的艺术状态。

再见

最新更新