【问题标题】:Determining successor in prolog using recursion使用递归确定序言中的继任者
【发布时间】:2016-10-28 20:16:43
【问题描述】:

我正在尝试(失败)理解一个练习,其中给了我以下条款;

pterm(null).
pterm(f0(X)) :- pterm(X).
pterm(f1(X)) :- pterm(X).

它们代表二进制数,例如。 f0(null) 等价于 0,f1(null) 等价于 1,以此类推

目标是在pterm 上定义一个谓词,这样一个谓词在为真时是另一个谓词。这似乎是一个相对简单的练习,但我很难理解它。

这是我目前写的代码;

incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)).
incr(X,Y) :- pterm(f0(f1(X))), pterm(f1(f1(Y))).

经过测试,我知道这是非常不正确的。我该如何检查每个 pterm 的顶级参数?

我在过去 4 小时内取得的进展很小,因此我们将不胜感激任何提示/帮助。

【问题讨论】:

  • 这与后继算术无关!
  • 您的程序等同于(w.r.t. 解决方案集):incr(X, Y) :- pterm(X), pterm(Y). 显然这个程序太笼统了!

标签: prolog


【解决方案1】:

1)
我将从“如何检查”问题开始,因为我认为这将是最有用的。如果您在 xpce 中使用 swi-prolog,请运行 guitracer:

?- consult('pterm').   % my input file
% pterm compiled 0.00 sec, 5 clauses
true.

?- guitracer.
% The graphical front-end will be used for subsequent tracing
true.

?- trace.   % debugs step by step
true.

[trace]  ?- pterm(f0(f1(null))).    % an example query to trace
true.

会出现一个图形界面。按向下箭头逐步统一事物。发生的事情应该很快就能理解。
(使用notrace.nodebug. 之后适当地退出跟踪和调试模式)。


2)您似乎误解了谓词的工作原理。谓词是一个逻辑语句,即它总是返回 truefalse。您可以将它们视为“iseven(X)”类型的经典布尔函数(测试 X 是否为偶数)或“ismemberof(A,B)”(测试 A 是否为 B 的成员)等。当您有像“pred1 :- pred2, pred3”这样的规则。这类似于说“如果 pred2 返回 true,pred1 将返回 true,并且 pred3 返回 true(否则 pred1 返回 false)”。

当使用常量调用谓词时,检查其真值就是检查事实数据库以查看是否可以满足具有这些常量的谓词。但是,当您调用 using variables 时,prolog 会遇到麻烦,试图unify 该变量与它可以链接到的所有允许的东西,看看它是否可以尝试使该谓词为真。如果做不到,它就放弃并说它是假的。

incr(X,Y) 这样的谓词仍然需要返回真或假,但是,如果按照设计,这只有在 Y 是 X 的递增版本时才成立,其中 X 是预期的要在查询时作为输入给出,那么我们已经欺骗 prolog 制作了一个“函数”,该“函数”将 X 作为输入,并“返回”Y 作为输出,因为 prolog 将尝试找到一个合适的 Y 使谓词为真。

因此,在您的示例中,incr(X,Y) :- pterm(f0(X)), pterm(f1(Y)). 没有任何意义,因为您告诉它incr(X,Y) 将为任何 X、Y 返回 true,只要 prolog 可以使用 X 在事实数据库中查找任何 pterm (f0(X)) 这将导致一个已知事实,并且还使用 Y 来找到一个 pterm(f1(Y)) 项。您没有以任何方式使 Y 依赖于 X。例如,对于 X = null 和 Y = null,此查询将成功。

你的第一个子句应该是这样的。

incr(X,Y) :- X = pterm(f0(Z)), Y = pterm(f1(Z)).

= 在哪里执行统一。 IE。 “为 Z 找到一个值,使得 X 为 pterm(f0(Z)),对于相同的 Z 值,它也适用于 Y = pterm(f1(Z))。”

事实上,这可以更简洁地重写为事实:

incr( pterm(f0(Z)), pterm(f1(Z)) ).


3)
您的第二个子句可以类似地调整。但是,我不确定这在您试图实现的逻辑(即二进制算术)方面是否正确。但我可能误解了您要解决的问题。 我的假设是,如果你有 (0)111,那么后继应该是 1000,而不是 1111。为此,我猜你需要创建一个谓词,递归检查当前处理的数字以下的增量是否导致一个“携带”的数字。

(因为实际的逻辑是你的任务的内容,我不会在这里提供解决方案。但希望这有助于你了解正在发生的事情。随意尝试递归版本并询问另一个基于该代码的问题!)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-27
    • 2019-03-08
    相关资源
    最近更新 更多