使用递归确定prolog中的后继者

时间:2016-10-27 19:12:23

标签: prolog

我尝试(失败)理解我给出以下条款的练习;

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小时内取得了很小的进展,因此我们将不胜感激任何提示/帮助。

1 个答案:

答案 0 :(得分: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)你似乎误解了谓词是如何工作的。谓词是一个逻辑语句,即它将始终返回 true false 。您可以将它们视为“iseven(X)”类型的经典布尔函数(如果X是偶数则测试)或“ismemberof(A,B)”(测试A是否是B的成员)等等。当你有规则如“pred1: - pred2,pred3。”这类似于说“如果pred2返回true,pred1将返回true,而pred3返回true(否则pred1返回false)”。

当使用常量调用谓词时,检查其真值是检查事实数据库以查看是否可以满足具有这些常量的谓词的问题。但是当你使用变量进行调用时,prolog会经历一次疯狂的追逐,尝试统一该变量以及它可以将其链接到的所有允许的东西,以查看它是否可以尝试使该谓词成立。如果它不能,它会放弃并说它是假的。

incr(X,Y)这样的谓词仍然需要返回true或false,但是,如果按照设计,只有当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)).

其中=执行统一。即“找到Z的值使得X是pterm(f0(Z)),对于相同的Z值,它也适用于Y = pterm(f1(Z))。”

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

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

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

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