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)
绘制序言证明树。
问题:
- 为什么
Y
匹配到 Y1/Y
而不是 Y/Y1
,为什么 Y
被进一步使用?
- 如果我匹配一个谓词(例如
p(X, Y)
),我会得到一个新的谓词(例如 p(g(X1), g(Y))
)——为什么 p(g(X1), g(Y))
只包含一个子树?我的意思是,它不应该有 3 个,因为知识库包含 3 个语句 - 而不是只有 1 个?
- 为什么树的每一层都匹配 X2/X1 之类的东西?而不是之前的谓词?
不应该是
g(X1)/fX5, g(Y1)/Y5
吗?
注:可能好像没做过教程什么的。但我做到了......我感谢每一个帮助。
老实说,我很少见过比您在这里展示的更糟糕的方法来解释 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).
此答案显示 X
和 Y
的 绑定 。首先确保您了解这一点,并了解这些绑定与 "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?
首先谈谈 term 与 predicate。术语仅在 Head :- Body
的上下文中是谓词,在这种情况下 Head
是构成谓词从句中心的术语。如果术语是谓词的参数(例如,p(g(X1), g(Y))
,则 g(X1)
和 g(Y)
是 而不是 谓词。它们只是术语。
更具体地说,在这种情况下,术语 p(g(X1), g(Y))
只有一个子树,因为它 只匹配 3 个谓词子句中 一个 的头部 是头部为 p(g(X), Y)
的那个(它与 X = X1
和 Y = 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)
.
我有以下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)
绘制序言证明树。
问题:
- 为什么
Y
匹配到Y1/Y
而不是Y/Y1
,为什么Y
被进一步使用? - 如果我匹配一个谓词(例如
p(X, Y)
),我会得到一个新的谓词(例如p(g(X1), g(Y))
)——为什么p(g(X1), g(Y))
只包含一个子树?我的意思是,它不应该有 3 个,因为知识库包含 3 个语句 - 而不是只有 1 个? - 为什么树的每一层都匹配 X2/X1 之类的东西?而不是之前的谓词?
不应该是
g(X1)/fX5, g(Y1)/Y5
吗?
注:可能好像没做过教程什么的。但我做到了......我感谢每一个帮助。
老实说,我很少见过比您在这里展示的更糟糕的方法来解释 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).
此答案显示 X
和 Y
的 绑定 。首先确保您了解这一点,并了解这些绑定与 "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 toY1/Y
and not toY/Y1
and why isY
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 containsp(g(X1), g(Y))
just one subtree? I mean, should'nt it have 3 because the knowledgebase contains 3 statements - instead of just 1?
首先谈谈 term 与 predicate。术语仅在 Head :- Body
的上下文中是谓词,在这种情况下 Head
是构成谓词从句中心的术语。如果术语是谓词的参数(例如,p(g(X1), g(Y))
,则 g(X1)
和 g(Y)
是 而不是 谓词。它们只是术语。
更具体地说,在这种情况下,术语 p(g(X1), g(Y))
只有一个子树,因为它 只匹配 3 个谓词子句中 一个 的头部 是头部为 p(g(X), Y)
的那个(它与 X = X1
和 Y = 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 beg(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)
.