【问题标题】:Finding whether a number is a multiple of another判断一个数是否是另一个数的倍数
【发布时间】:2019-04-20 09:50:16
【问题描述】:

看下面的代码:

multiple(X,0).
multiple(X,Y) :- lt(0,X), lt(0,Y), diff(Y,X,D), multiple(X,D).

发生了一些错误。供您参考:
lt/2 是第一个参数是否小于第二个。
diff/3 是第三个参数是否等于第一个参数减去第二个参数。
lt/2 和 diff/3 定义正确。

定义中是否存在逻辑错误?假设 0 是每个有问题的数字的倍数还是其他地方的逻辑错误?我得到了正确的答案,但我认为查询进入了无限循环。

编辑:
这是其他定义。

natNum(0).
natNum(s(X)) :- natNum(X).

lt(0,s(X)) :- natNum(X).
lt(s(X),s(Y)) :- lt(X,Y).

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

diff(X,Y,Z) :- sum(Z,Y,X).

?- multiple(X, s(s(s(s(s(s(0))))))).

s(0) 是 1,s(s(0)) 是 2 等等。它给出了 X 的所有所需答案,但在最后一个答案之后,它就卡住了。我假设在无限递归循环中?

【问题讨论】:

  • 什么不起作用?什么查询失败了?你trace.了吗?
  • ?- multiple(X, s(s(s(s(s(s(0))))))). 其中 s(0) 为 1,s(s(0)) 为 2 等等。它为 X 提供了所有所需的答案,但在最后一个答案之后,它卡住了。我假设在无限递归循环中? @WillemVanOnsem
  • 请添加lt/2diff/3的定义。如果我们没有看到它们,我们怎么知道!
  • 已编辑。 :) @false
  • X = s(_) 代替lt(0,X)(两次)

标签: prolog failure-slice successor-arithmetics


【解决方案1】:

您的程序中发生了什么?它是永远循环,还是只需要一些时间,因为您最近几十年没有更新您的硬件?我们不能说。 (实际上,我们可以通过查看您的程序来判断,但目前这太复杂了)。

我们可以轻松地缩小这种代价高昂的工作的来源。而这,在没有深入了解你的程序的情况下。让我们从查询开始:

| ?- multiple(X, s(s(s(s(s(s(0))))))).
X = s(0) ? ;
X = s(s(0)) ? ;
X = s(s(s(0))) ? ;
X = s(s(s(s(s(s(0)))))) ? ;
** LOOPS or takes too long ***

没有更简单的方法吗?所有这些分号打字。相反,只需将 false 添加到您的查询中。通过这种方式,找到的解决方案不再显示,我们可以专注于这个烦人的循环。而且,如果我们愿意,您还可以将 false 目标添加到您的计划中!通过这样的目标,推理的数量可能会减少(或保持不变)。如果生成的片段(称为)正在循环,那么这就是您的原始程序循环的原因

multiple(_X,0) :- false。 多重(X,Y):- lt(0,X),falselt(0,Y),差异(Y,X,D),多重(X,D)。 natNum(0) :- false。 natNum(s(X)) :- natNum(X), false。 lt(0,s(X)) :- natNum(X), falselt(s(X),s(Y)) :- false, lt(X,Y)。 ?- 多个(X, s(s(s(s(s(s(0))))))), false。 ** 循环 ***

你认识你的程序吗?只剩下循环所需的那些部分。而且,实际上在这种情况下,我们有一个无限循环。

要解决这个问题,我们需要修改剩余的可见部分。我会选择lt/2,它的第一个子句可以概括为lt(0, s(_))

但是等等!为什么可以概括我们有一个自然数的要求?看看你写的multiple(X,0). 的事实。您也没有要求X 是自然数。这种过度概括经常出现在Prolog程序中。它们以相对较低的价格改进了终止属性:有时它们过于笼统,但所有另外适合概括的术语都不是自然数。它们是像any[a,b,c] 这样的术语,所以如果它们出现在某个地方,您就知道它们不属于解决方案。


所以想法是将 false 目标放入您的程序中,以便生成的程序(故障切片)仍然循环。在最坏的情况下,您将 false 放在错误的位置,程序就会终止。通过反复试验,您可以获得最小的故障片。所有那些现在划过的东西都是无关的!特别是diff/3。所以不需要理解它(暂时)。看看剩下的程序就够了。

【讨论】:

  • 非常抱歉,但我无法理解。代码中乱写的部分是什么意思?为什么我们要在定义中添加false?那不会忽略所有这些定义吗?我很困惑。
  • 阅读 如果结果片段 ... 这就是重点:剩余程序与您的原始程序有很大关系,因为它是其未终止的原因.
  • 您还有什么想要解释的吗?
  • 难道不会忽略所有这些定义吗? 是的,故障片不包含diff/3,因为问题已经独立于它出现了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-04-01
  • 2011-05-24
  • 2010-12-05
  • 2013-11-05
  • 2021-11-20
相关资源
最近更新 更多