Prolog - 证明树错过了可能性

Prolog - proof tree misses possibilities

我有以下Prolog程序:

p(f(X), Y) :- p(g(X), g(Y)).
p(g(X), Y) :- p(f(Y), f(X)).
p(f(a), g(b)).

必须为谓词p(X, Y)绘制序言证明树。

问题

:可能好像没做过教程什么的。但我做到了......我感谢每一个帮助。

老实说,我很少见过比您在这里展示的更糟糕的方法来解释 Prolog。

,我希望作者在这两种情况下的意思是Y/Y1而不是Y1/Y,否则符号会很不一致。

关于您的其他问题:您面临的是在对 Prolog 采取如此极端 操作性 观点时出现的常见问题。核心问题是此方法 无法扩展 :您没有执行此方法的心智能力。不要把这个当成个人的:一般来说,人类不善于记住呈指数增长的执行树的所有细节。这使得整个方法极其繁琐且容易出错。相比之下,想想为什么人类大师在很多年前就已经停止与国际象棋计算机竞争。在这个具体案例中,请注意例如最右边的分支甚至不会出现在实际的 Prolog 执行中,但图表错误地表明它出现了!

这里的部分问题是术语的混淆:请注意Prolog使用统一(不是"matching",这是片面的统一)。当您 统一 一个带有子句 head 的目标并且统一 成功 时,您会得到 bindings 用于变量。您继续这些绑定

要使整个方法远程可行,请考虑程序的 片段

例如,假设我给你以下事实:

p(f(a), g(b)).

然后你查询:

?- p(X, Y).
X = f(a),
Y = g(b).

此答案显示 XY 绑定 。首先确保您了解这一点,并了解这些绑定与 "new predicate"(不会出现!)之间的区别。

此外,没有 "statements",但有 3 个 子句 ,它们是合乎逻辑的 替代项

现在,再次简化整个任务,考虑您程序的以下 片段 ,其中我 查看两个规则:

p(f(X), Y) :- p(g(X), g(Y)).
p(g(X), Y) :- p(f(Y), f(X)).

已经有了这个程序,我们得到:

?- p(X, Y).
nontermination

添加一个进一步的纯子句不能阻止这种不终止。因此,我建议您从程序的这个简化版本开始,并更深入地考虑它。

从那里,您可以再次添加剩余的事实,并考虑差异。

非常好的问题!

Why is Y matched to Y1/Y and not to Y/Y1 and why is Y used further on?

这里的命名似乎有点武断,因为他们可以使用Y/Y1,但随后需要进一步使用Y1。在这种情况下,他们选择 Y1/Y 并继续使用 Y。虽然这个表达式树的作者在他们的约定中不一致,但我不会太在意命名,因为他们是否正确地沿着树向下跟随变量。

if I match a predicate (e.g. p(X, Y)), I get a new predicate (e.g. p(g(X1), g(Y))) - why contains p(g(X1), g(Y)) just one subtree? I mean, should'nt it have 3 because the knowledgebase contains 3 statements - instead of just 1?

首先谈谈 termpredicate。术语仅在 Head :- Body 的上下文中是谓词,在这种情况下 Head 是构成谓词从句中心的术语。如果术语是谓词的参数(例如,p(g(X1), g(Y)),则 g(X1)g(Y) 而不是 谓词。它们只是术语。

更具体地说,在这种情况下,术语 p(g(X1), g(Y)) 只有一个子树,因为它 只匹配 3 个谓词子句中 一个 的头部 是头部为 p(g(X), Y) 的那个(它与 X = X1Y = g(Y) 匹配)。其他两个无法匹配,因为它们的形式为 p(f(...), ...),并且 f(...) 项无法匹配 g(X1) 项。

And why is at each layer of the tree matched with something like X2/X1 and so on ? and not with the predicate before ? Shouldn't it be g(X1)/fX5, g(Y1)/Y5 ?

我不确定我是否在关注这个问题,但要遵循的原则是树试图使用 相同的 变量名,如果它适用于 内存中的相同变量,而如果它是不同 X。例如,如果我有 foo(X, Y) :- <some code>, bar(f(X), Y).bar(X, Y) :- blah(X), ...,那么 bar 谓词中引用的 X 不同于 X 中引用的 foo谓词。所以我们可能会说,在 foo(X, Y) 的调用中我们调用 bar(f(X), Y),或者 bar(X1, Y) 其中 X1 = f(X).