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
既是一元前缀运算符,又是表示“不可证明”的谓词。
(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 ; B
和B ; A
是一样的。但不是 操作 所以。
带上切入,忘掉逻辑,开始思考Prolog解释的操作细节
我正在学习序言并且遇到了“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
既是一元前缀运算符,又是表示“不可证明”的谓词。
(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 ; B
和B ; A
是一样的。但不是 操作 所以。
带上切入,忘掉逻辑,开始思考Prolog解释的操作细节