Prolog cut and fail 没有按预期工作

Prolog cut and fail not working as expected

我正在学习序言并且遇到了“cut and fail”组合,据我了解它们可以用作保护子句。我试过试验它,但它没有按预期工作。

old(person1).
old(person2).
skilled(person1).
skilled(person2).
skilled(person3).
skilled(person4).
possible_employee(X):-
    old(X),!,fail.
possible_employee(X):-
    skilled(X).

在上面的示例中,它应该“过滤掉”old 人,但它过滤掉了所有人,并且在查询 possible_employee 时过滤掉了 returns false。是我的代码有缺陷还是我对这个概念的理解?

Prolog 中的概念执行模型是搜索树。 Prolog 的推理引擎对树进行深度优先、从左到右的搜索,寻找与谓词中的所有约束匹配的解决方案(叶节点)。

切割 (!) 消除了选择点——例如,它修剪了搜索树。

所以你的 possible_employee/1 谓词

possible_employee(X) :- old(X), !, fail.
possible_employee(X) :- skilled(X).
一旦满足 old(X)

完全 失败。这就是 !, fail 的意思。 old(X) 的替代解决方案将不会尝试;谓词的第二项也不会被尝试。

Prolog 是一种描述性 语言:用您在评论中所做的相同方式描述您的解决方案:

I'm expecting "possible_employee(X)" to unify X with all persons that are not old and which are skilled (X=person3;X=person4).

这让我们找到了这个简单的解决方案,它几乎就是您的问题陈述:

possible_employee(X) :- % a possible employee is one who
  skilled(X) ,          % - is skilled, and
  \+ old(X)  .          % - is not old

\+/1既是一元前缀运算符,又是表示“不可证明”的谓词。

https://www.swi-prolog.org/pldoc/doc_for?object=(%5C%2B)/1

(old(X) ; skilled(X)), possible_employee(X)随心所欲

member(X, [person1, person2, person3, person4]), possible_employee(X)随心所欲

您的谓词过滤器 out 解决方案。由于剪切,它不能以生成方式使用。一旦 old(X) 得到满足,谓词 possible_employee/1 就会按照规定不可撤销地失败。所以它必须从一些外部来源提供更多的可能性。它本身就是在那个时候完成的。

您的谓词(重新)实现的是“not”,\+

在 Prolog 中,not 不是 “不是”。它必须被解读为“不能证明那...”。

在这个解读下,possible_employee(X)的意思是,“不能证明old(X),可以证明skilled(X)”。但是 old(X) 有了新鲜的 X 可以总是 被证明,有了那个知识库。

如果调换从句顺序,则完全改变了谓词的含义。谓词的(几个)子句在隐含的析取中,“或”:

possible_employee(X):-
    skilled(X).
possible_employee(X):-
    old(X),!,fail.

的意思是,“可以证明 skilled(X)”,仅此而已(你明白为什么了吗?)。那么,在

old(person1).
old(person2).
skilled(person1).
skilled(person2).
skilled(person3).
skilled(person4).
possible_employee(X):-
    skilled(X).
possible_employee(X):-
    old(X),!,fail.

呼叫possible_employee(X)应该成功四次,对于所有四个人。确实如此,即使他们两个也是 old/1.

所以你看,cut 的出现改变了一切。它使谓词的含义完全依赖于操作语义。

在逻辑上,A ; BB ; A是一样的。但不是 操作 所以。

带上切入,忘掉逻辑,开始思考Prolog解释的操作细节