避免在Prolog绝对值谓词中使用cut

Olh*_*sky 6 prolog prolog-cut

我在prolog中使用以下代码实现了以下功能:

abs2(X, Y) :- X < 0, Y is -X.
abs2(X, X) :- X >= 0, !.
Run Code Online (Sandbox Code Playgroud)

如何在不使用cut("!")的情况下实现此功能?

har*_*ath 10

在Prolog的if-then-else结构中有"隐藏"的切口:

abs2(X,Y) :- X < 0 -> Y is -X ; Y = X.
Run Code Online (Sandbox Code Playgroud)

这是一个怪癖,但Prolog并没有回溯构成if-then或if-then-else结构的"前提"的子目标.这里,如果X <0成功进行第一次尝试,则提交"then"子句对"else"子句的选择(因此将此行为描述为"隐藏"剪辑).

在问题中写的谓词abs2/2第一个子句中有更多的切割角色.正如尼古拉斯所指出的那样,第二个条款末尾的削减没有任何影响(当你到达那里时没有任何选择点).但正如卡雷尔所指出的那样,如果第一个条款成功,就会有一个选择点.

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

abs2(X,X) :- X >= 0, !.
abs2(X,Y) :- Y is -X.
Run Code Online (Sandbox Code Playgroud)

尼古拉斯的评论还提出了一种方法来"绝对化"绝对价值(而不是使用逻辑定义)并避免"削减"这种方式.

  • @mat:我很乐意学习更好的术语.我写了"隐藏剪切"作为提供我的解决方案的一种披露,避免了(明显)使用剪切,因此读者可以判断我的解决方案是有效还是"作弊".比较Control Predicates的SWI-Prolog文档(Sec.2.4.7),了解"if-then-else"中的本地化提交/剪切的说明.http://www.swi-prolog.org/pldoc/doc_for?object=section%282,%274.7%27,swi%28%27/doc/Manual/control.html%27%29%29 (2认同)

Nic*_*rey 6

我的序言有点生疏,但为什么你甚至需要削减?如果正确编写谓词,则回溯无法成功,因此不需要剪切:

abs(X, Y) :- number(X) , X <  0 , Y is -X .
abs(X, X) :- number(X) , X >= 0 .
Run Code Online (Sandbox Code Playgroud)

  • 另一种选择是:`abs(X,Y): - Y是符号(X)*X .`(假设你的prolog实现支持内置的sign/1谓词). (6认同)
  • 您的代码仍然留有选择点.这种选择会导致失败,但仍然需要考虑.削减可以避免这种情况. (4认同)
  • 如果你知道你正在处理积分值,你可以通过两个位来计算带有选择点的ABS:http://www-graphics.stanford.edu/~seander/bithacks.html#IntegerAbs (3认同)
  • 另一种选择:`abs(X,Y): - Y是abs(X).` (3认同)