【问题标题】:Prolog: stop condition?Prolog:停止条件?
【发布时间】:2014-01-27 20:16:57
【问题描述】:

这是一个非常简单的 Prolog 知识库:

spouse(bill,cheryl).
married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).

我运行了以下查询。请注意,有时答案是正确的名称(仅),但有时答案是正确的名称和“假”。

1 ?- married(bill,X).
X = cheryl ;
false.

2 ?- married(cheryl,X).
X = bill.

3 ?- married(X,bill).
X = cheryl.

4 ?- married(X,cheryl).
X = bill ;
false.

有人可以解释这种看似不一致的行为吗?提前致谢。

【问题讨论】:

  • false 表示 Prolog 有一个选择点可以返回以尝试找到更多答案,但它没有找到更多答案,所以它返回了 false。你的谓词和事实的设置顺序会影响它是否认为它有更多的选择可供探索。交换married 子句的顺序,看看会发生什么。 :) 在您的情况下,false 在您的第一个子句成功时发生,然后 Prolog 返回尝试第二个子句。
  • 你是对的。没有递归。当我说配偶(X,Y):-配偶(Y,X)时,递归是在早期尝试解决这个问题。但这只是导致循环,所以我改为这个(更简单?)示例。我尝试交换结婚条款,但结果相同。
  • 我修好了……有点。我加了一个剪辑。上面显示的查询现在可以正常工作(没有“假”)。但是...添加另一个配偶谓词,查询仅在第一对之后停止。配偶(比尔,谢丽尔)。配偶(艾玛,纳特)。已婚(X,Y):-配偶(Y,X),!。已婚(X,Y):- 配偶(X,Y)。查询...缺少 emma,nate: 6 ?- 已婚(X,Y)。 X = 谢丽尔,Y = 比尔。 7 ?-
  • 根据我的经验,你几乎总是在代码的中间层出现一个额外的false。性能问题通常在代码的其他地方,并且由于普通用户受到保护,不受 REPL 的“美学”影响,因此尝试找到并删除它往往不值得。对于像我们这样的初学者来说,剪掉它通常比它的价值更麻烦。

标签: prolog prolog-toplevel


【解决方案1】:

来自 Prolog 的false 响应意味着 Prolog 有一个选择点可以返回以尝试找到进一步的答案,但它没有找到更多的答案。您的谓词和事实的设置顺序会影响它是否认为有更多选择可供探索。

在给定的情况下:

spouse(bill,cheryl).

married(X,Y) :- spouse(X,Y).
married(X,Y) :- spouse(Y,X).

1 ?- married(bill,X).
X = cheryl ;
false.

2 ?- married(cheryl,X).
X = bill.

3 ?- married(X,bill).
X = cheryl.

4 ?- married(X,cheryl).
X = bill ;
false.

在两个false 情况下,查询married/2 由两个married/2 子句中的第一个满足。一旦满足,Prolog 就会意识到它还有另一个选择(第二个married/2 子句),并提示您寻找更多。你按;,然后Prolog 探索第二个(也是最后一个)子句,找不到更多解决方案,然后返回false

交换married/2 子句的顺序,看看会发生什么:

spouse(bill,cheryl).

married(X,Y) :- spouse(Y,X).
married(X,Y) :- spouse(X,Y).

?- married(bill,X).
X = cheryl.

?- married(cheryl,X).
X = bill ;
false.

?- married(X,bill).
X = cheryl ;
false.

?- married(X,cheryl).
X = bill.

正如预期的那样,结果是相反的,因为我们已经更改了第一个子句满足哪些查询。

false 响应对于 Prolog 初学者来说可能看起来不一致,并且“感觉”像是一个错误或警告,但它实际上是一个完全正常的 Prolog 响应。 Prolog 在尝试寻找解决方案的行为上非常一致,当没有更多选择存在时,将返回false。如果 Prolog 在找到最终解决方案之前已经用尽了所有其他选择,它会显示解决方案并且不会返回 false(如上面的情况,第二个子句是唯一的解决方案)。

有一种尝试通过使用剪切来“清理”false 响应的诱惑。虽然这可能会产生理想的短期结果,但这是有风险的,因为您要从谓词中删除选择点,并且在添加数据和逻辑时可能会消除您真正想要的解决方案。

因此,在修改的情况下:

spouse(bill,cheryl).
spouse(emma,nate).

married(X,Y) :- spouse(X,Y), !.  % If we found the spouse, we're done, no more!
married(X,Y) :- spouse(Y,X).

?- married(bill,X).
X = cheryl.

?- married(cheryl,X).
X = bill.

?- married(X,bill).
X = cheryl.

?- married(X, cheryl).
X = bill.

是的,生活是美好的!但是等等,如果我们这样做会怎样:

?- married(X,Y).
X = bill,
Y = cheryl.

?-

billcheryl 是唯一的已婚夫妇吗?不......它遗漏了nateemma。剪切消除了其余的解决方案。

【讨论】:

  • 您说“错误的响应对于 Prolog 初学者来说可能看起来不一致,并且“感觉”像是错误或警告,但它实际上是一个完全正常的 Prolog 响应。”如此真实!谢谢你的解释。
  • +1 很好的答案!正是@BillQualls 所说的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-11-28
  • 2014-05-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-03
  • 2018-04-24
相关资源
最近更新 更多