Prolog 加法练习

发布于 2024-12-12 06:04:51 字数 503 浏览 0 评论 0原文

我有这个非常简单的代码作为数字的表示。问题是当我使用 add2 函数时。

示例:add2(s(0)+s(s(0)), s(s(0)), Z)。 返回 s(s(s(s(s(0) ))))) 正确。但是,add2(0, s(0)+s(s(0)), Z). 始终返回 s(0)+s(s(0))。谁能明白为什么会发生这种情况?

numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).

add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).

%%  exercise 1
add2(X,Y,R) :- add(X,Y,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).

I have this very simple code as a representation of numerals. The problem is when I use the add2 function.

Example: add2(s(0)+s(s(0)), s(s(0)), Z). returns s(s(s(s(s(0))))) correctly. However add2(0, s(0)+s(s(0)), Z). always returns s(0)+s(s(0)). Can anyone see why this is happening?

numeral(0).
numeral(s(X)) :- numeral(X).
numeral(X+Y) :- numeral(X), numeral(Y).

add(0,X,X).
add(s(X),Y,s(Z)) :- add(X,Y,Z).

%%  exercise 1
add2(X,Y,R) :- add(X,Y,R).
add2(X+Y,Z,R) :- add(X,Y,A),add2(A,Z,R).
add2(X,Y+Z,R) :- add(Y,Z,A),add2(X,A,R).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

深爱不及久伴 2024-12-19 06:04:51

发生这种情况是因为第一个 add2 子句和第一个 add 子句的组合。您的 add2(0, ..., ...) 将触发 add(0, ..., ...) ,它始终统一第二个和第三个参数。

It's happening because of the combination of the first add2 clause and the first add clause. Your add2(0, ..., ...) will trigger add(0, ..., ...) which always unifies the second and third argument.

乖乖兔^ω^ 2024-12-19 06:04:51

在 Prolog 中,中缀 + 之类的函数符号不会被求值。您似乎正在尝试评估所有出现的 + 。然而,其中一些仍然没有被评估,如果您尝试像 add2/3 中那样临时执行此操作,这可能会非常棘手。考虑
add2(0+0+0,0,R) 因您的定义而失败。

您所说的 numeral/1 可能更好地称为 expression/1

考虑定义一个辅助谓词 eval/2 将表达式简化为 s(X) 数字。
但请注意,对于像 add2(0,0,0+0) 这样的目标,即使这样的定义仍然会失败。这是一个固有的问题,只能使用约束或类似的技术来解决......

In Prolog function symbols like the infix + are not evaluated. It seems you are trying to evaluate all occurrences of +. However, some of them are still not evaluated and this can be quite tricky if you try to do this ad hoc as in add2/3. Consider
add2(0+0+0,0,R) which fails with your definition.

What you call numeral/1 might better be called expression/1.

Consider to define an auxiliary predicate eval/2 to simplify expressions to s(X)-numbers.
Note however, that even such a definition will still fail for goals like add2(0,0,0+0). This is an inherent problem which can only be solved using constraints or similar techniques...

琉璃梦幻 2024-12-19 06:04:51

当调用add2(0, s(0)+s(s(0)), Z)时,会与add2/3的第一个子句统一,由于第一个子句的头部只有三个变量,因此它可以与任何 add2/3 调用统一。这反过来将在您的示例中导致调用 add/3 的第一个子句,因此 Z 将绑定到 s(0)+s(s(0))

您的代码的问题在于,add2/3 的更具体子句放置在通用子句之后。因此,为了使您的代码正常工作,请将 add2/3 的第一个子句放在最后,并对其他两个子句添加剪切,例如,

add2(X+Y,Z,R) :- !,add(X,Y,A),add2(A,Z,R).

因为当该子句的头部与查询匹配时,您确定你正在执行正确的子句,并且你不会在回溯时遇到麻烦。

When you call add2(0, s(0)+s(s(0)), Z), it will be unified with the first clause of add2/3, since this first clause only has three variables in the head, so it can be unified with any call of add2/3. This in turn will in your example lead to calling the first clause of add/3, so Z will be bound to s(0)+s(s(0)).

The problem with your code is that the more specific clauses of add2/3 are placed after the general clause. So to make your code work, place the first clause of add2/3 last, and add cuts to the other two, e.g.

add2(X+Y,Z,R) :- !,add(X,Y,A),add2(A,Z,R).

since when the head of that clause has matched the query, you're sure that you're executing the right clause and you won't have trouble on backtracking.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文