在序言中制定自然数规则的正确方法是什么?

时间:2019-12-04 02:50:40

标签: prolog

我想我在理解序言时还存在更大的问题,但是由于我无法完全表述,所以我将重点放在单个问题上

我想创建一个规则natural(X),如果X是1,2,3,4,...
更重要的是,我都希望:natural(5)是真实的 natural(X)是输出X=1; X=2; ...


所以,我解释规则如下(伪):

natural(1) must be true
natural(X) is true if natural(X-1) is true

或者,在序言方面:

natural(1).
natural(X) :- natural(X-1).

但是我遇到了一个问题-如果我尝试natural(5)会得到无限递归
调试器说程序评估:

natural(5)
 natural(5-1)
  natural(5-1-1)
   natural(5-1-1-1)
    natural(5-1-1-1-1)
     natural(5-1-1-1-1-1)
      natural(5-1-1-1-1-1-1)
...

我猜问题出在X-1未被评估吗?
让我们尝试解决该问题:

natural(1).
natural(X) :-
  Y is X-1,
  natural(Y).

现在,natural(5)可以正常工作了
但是,如果我使用natural(X),我会得到X=1; Exception: Arguments not sufficiently instantiated (Y is X-1)


好吧,我想问题是我们试图评估可能还没有价值的东西
如果我尝试使用Y = X-1,我们将回到第一个问题。 Y == X-1返回false

我发现唯一可行的解​​决方案是切换行和定义顺序:

natural(1).
natural(X) :-
  natural(Y),
  X is Y+1.

将最后一行更改为=会得到“ + 1 + 1 + 1 ...”结果。 ==失败了。

此解决方案在生成X=1; X=2; ...时效果很好,但是当我将其用作检查(natural(5))时,它会显示为“ 0,(0,1),(0,1,2), (0,1,2,3),...“顺序。是的,我得到了正确的结果,但是那条路很长,而不是我想像的那样。
如果在以前的解决方案中没有看到检查natural(5)的更快方法,我会在这里停止。


那么,我错过了哪种更好的创建此规则的方法?

我猜一种方法是将“ true / false”查询与生成器查询分开...但是有没有一种方法可以使其“可能评估的话进行评估”,即从has变量中分离唯一常量? var(X-1)某种程度上是假的...

1 个答案:

答案 0 :(得分:2)

使用APIManager.callRequest(url: "someURL", type: Model.self) 通常可以大大改善自然交易。正如您所发现的,Prolog需要 succ/2来评估算术表达式,但是它具有单个实例化模式:is/2。没有限制,拥有-Number is +Expr之类的完全开放的模式将是完全的疯狂。

另一方面,

?Number is ?Expr具有两种模式:succ/2succ(+Pred, -Succ)。举例来说:succ(-Pred, +Succ)统一X = 2,而succ(X, 3)统一X =3。尽管succ(2, X)仍然是错误。但是,您可以使用succ(X, Y)构建natural/1的解决方案,但要注意:

succ/2

从逻辑上讲,这应该与natural(1). natural(X) :- natural(X0), succ(X0, X). 相同,但是Prolog不是逻辑,它具有评估顺序。该技巧基本上会强制您要求X是否自然地从X-1开始,立即转到X-2,然后向下直到X达到1,然后它可以备份并开始成功。如果提供负数,则它会立即失败,因为succ(X0, X), natural(X0)的负数将失败。这可以通过您所需的两种方式工作,但是有一个令人讨厌的问题:

succ/2

是的,如果在提供值之后要求第二个结果,则会出现无限循环。 Prolog尝试找出5之后是否再次出现5。

一个避免问题的简单解决方案是使用?- natural(X). X = 1 ; X = 2 ; X = 3 ; .... ?- natural(5). true ; ^CAction (h for help) ? abort

between/3

无循环。这将是我的首选解决方案。

natural(X) :- between(1, inf, X). ?- natural(X). X = 1 ; X = 2 ; X = 3 ; ... ?- natural(5). true. var/1外,还有nonvar/1,它们可以区分具有变量的术语和不具有变量的术语。您可以使用它来区分(一侧)5、3-1等与另一侧的X,X-1。以我的经验,将这样的情况分开通常会导致眼泪和向后正确性的麻烦,但在极端情况下,这是有必要的。

在这一点上,您可能对Prolog的逻辑感到有些不适。标准系统的算法令人失望。但是clpfd更加强大和灵活,许多人建议您首先学习它,因为它更擅长生成解决方案(ground/1确实无法生成,但是可以使用clpfd进行标记)。根据我的经验,is/2与Peano算术足够接近,以至于整数混乱通常是可以的,但是对于任何严重的问题,您都希望使用clpfd。