我需要"基本步骤"在Prolog上做一个递归?

时间:2015-08-31 23:11:02

标签: prolog transitive-closure

我在大学里学习Prolog,而且我遇到了一个问题。 请注意,我是Prolog的新手,我甚至不知道Prolog元素的正确拼写。

我需要在我的.pl文件中定义一个递归规则,而且我不知道我是否需要一个"基本步骤"根据我的规则。检查我的规则:

arr[i].sensor

这是有效的,但我不能做以下的事情吗?

recur_disciplinas(X, Y) :- requisito(X, Y).
recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y).

当我声明相同的"规则名称"会发生什么? (recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y). )两次?发生有点像覆盖?

我目前正在使用swi-prolog。十分感谢大家!

3 个答案:

答案 0 :(得分:4)

如何理解Prolog规则的最佳方法是查看:-运算符,它是一个20世纪70年代的箭头渲染(是的,Pascal中的赋值运算符:=也是一个箭头)。所以你看看右边那边有什么说:如果一切都是真的,我可以得出结论左边的东西。所以你正在从右到左阅读你的规则:

 recur_disciplinas(X, Y) :- requisito(X, Z), recur_disciplinas(Z, Y).
 %                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read

你说:如果有一些XYZ这样右手是真的,我们可以断定recur_disciplians(X, Y)成立。现在,让我们通过删除requisito(X, Z)来概括这一点。现在留下的是:

 recur_disciplinas(X, Y) :- /******/ recur_disciplinas(Z, Y).

因此,您可以recur_disciplinas(Z, Y)得出结论recur_disciplinas(X, Y)成立。但是你没有什么可以从这个结论开始!如此有效,这意味着根本没有解决这种关系的方法。

就像说,只要我能飞,我会像鸟一样飞翔。

也许这是真的,但只要你不飞,那一切都是徒劳的。

请参阅this answer如何允许更紧凑地表达您的关系。目标closure(requisito, X, Y)就足够了!它甚至可以处理潜在的循环。

作为旁注,我怀疑recur是一些动词,甚至是必要的。对?尽量避免关系的必要性。改变事物的势在必行。就像“打开灯”一样,它将世界从关灯关闭的世界改变为开启灯的世界。对于告诉无意识的实体该做什么,势在必行。如果你想要推理事情,那么必要的就是malaprop。而是关注应该是什么情况,什么不是。

答案 1 :(得分:1)

如果您的规则名称不止一次,它会在您的控制流中创建一个or-branch。 Prolog将尝试统一第一个条款。如果失败,它将尝试第二个子句,第三个等等。

在上面的代码中,requisito规则将首先尝试查找匹配的def find_disciplinas(X, Y): if find_requisito(X,Y): # halting condition return (X, Y) else: # recursive call for all Z such that find_requisito(X, Z): return find_disciplinas(X, Z) 。如果它失败了,它将试图找到一个requisito-a-requisito,transitively和递归。

如果你没有放置一个基本子句,Prolog总是会尝试递归子句,因此它可能会进入一个无限循环。

写作基础条件并非Prolog独有。每种允许递归的语言都是一样的。如果没有暂停条件,您的函数将进入无限循环。

考虑这个等效的程序伪代码:

<?xml version="1.0" encoding="UTF-8"?>
<ProductDetails ProductID="TuscanWengeShoeRack010cfg" ProductcfgPath="http://localhost/media/productattachment/176/TuscanWengeShoeRack010cfg.xml" SKUID="TWS090" />

如果您的“requisito”记录包含一个循环,并且您删除了暂停条件,则上述过程将无限循环。

答案 2 :(得分:1)

这里我们说recur_disciplinas/2是一个带有两个参数的谓词,并且您已经询问了谓词的两个子句(规则)是否必要。< / p>

正如其他Answers所说,在递归中需要一个“基本案例”,以便递归终止,这通常是可取的!最常见的安排就像你的第一个例子:第一个规则是终止条件(基本情况),第二个规则是递归步骤(归纳案例)。阅读代码的人可能会发现这种安排很熟悉且易于理解。

但是,基本情况和递归步骤可以合并为一个规则,这有时很有用。例如,我们可以使用OR语法:

recur_disciplinas(X, Y) :-
    requisito(X, Y) ; ( requisito(X, Z), recur_disciplinas(Z, Y) ).

此处;表示OR,此单一规则与原始双规则版本产生的解决方案基本相同。

也可能存在多个基本案例,每个案例都有自己的规则或写入更复杂的“组合”规则。与任何编程学科一样,清晰度和正确性应该仅仅是代码的简洁性。

在某些特殊情况下,将递归步骤定位为第一个规则并将基本案例(或多个案例)移动到以下规则中可能是有利的。这需要特别小心以确保始终达到终止条件,因为您不太可能希望代码可以无限循环。当调用谓词时,Prolog引擎始终以第一个规则开始;只有在第一条规则失败后才会尝试以下规则。