2011-01-26 87 views
5

使用切我已经用下面的代码来实现以下功能在序言:避免在序言绝对值谓词

abs2(X, Y) :- X < 0, Y is -X. 
abs2(X, X) :- X >= 0, !. 

我怎样才能实现这个功能,而无需使用切(“!”)的?

回答

8

有 “隐藏” 切的Prolog的if-then-else结构:

abs2(X,Y) :- X < 0 -> Y is -X ; Y = X. 

这是一个怪癖,但Prolog不会回溯到构成if-then或if-then-else构造的“前提”的子目标。在这里,如果X < 0成功完成第一次尝试,那么在“else”子句之上的“then”子句的选择将被提交(因此,将该行为描述为“隐藏”子事件)。

有谓词写在问题ABS2/2第一子句中削减更多的作用。正如尼古拉斯指出的那样,第二个条款结尾处的裁减没有任何影响(当你到达那里时没有选择点)。但正如卡雷尔指出的那样,如果第一个条款成功,还有一个选择点可以开放。

所以,我会写,允许使用切割的,是这样的:

abs2(X,X) :- X >= 0, !. 
abs2(X,Y) :- Y is -X. 

尼古拉斯的评论也暗示方法“arithmetize”绝对值(而不是使用一个逻辑的定义),并避免“削减”这种方式。

5

我的序言有点生疏,但为什么你甚至需要剪切?如果你写正确的谓词,回溯能不能成功,所以切是不必要的:

abs(X, Y) :- number(X) , X < 0 , Y is -X . 
abs(X, X) :- number(X) , X >= 0 . 
+4

您的代码仍然留下一个选择点。这种选择导致失败,但仍然被考虑。剪切可以避免这种情况。 – Kaarel 2011-01-26 20:34:56

+3

如果你知道你在处理积分值,你可以通过旋转位来计算ABS的选择点:http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerAbs – 2011-01-26 20:56:07