我正在尝试编写一个Prolog程序,该程序将依次打印出英国版的男性继承人。到目前为止我的尝试:
son(elizabeth, charles).
son(charles, william).
son(charles, henry).
son(elizabeth, andrew).
son(elizabeth, edward).
son(edward, severn).
successor(X, Y) :- son(X, Y).
successor(X, Y) :- son(X, C), successor(C, Y).
后继功能并不能完全符合我的要求:当前输出为:
successor(elizabeth, Y).
Y = charles ;
Y = andrew ;
Y = edward ;
Y = william ;
Y = henry ;
Y = severn ;
false.
第一条规则将所有三个直接子项打印出来,然后第二条规则打印出所有后代。但是第一个孩子的后代应该来到第二个直系孩子之前,如下:
successor(elizabeth, Y).
Y = charles ;
Y = william ; % william and henry should come before andrew
Y = henry ;
Y = andrew ;
Y = edward ;
Y = severn ;
false.
这是我的第一个Prolog计划,我对如何表达正确的关系感到茫然。任何人都可以给我一个想法或指向对我有帮助的资源吗?
答案 0 :(得分:5)
正如rati所述,Prolog查询通过选择规则,使用depth-first search递归评估它,然后选择下一个规则并重复该过程来解决。但是,您开始使用的特定规则实际上会导致系列树的breadth-first search,如您所述,它不会提供与实际连续行匹配的输出。相反,你想要对王室树进行深度优先遍历。此版本提供您正在寻找的结果:
successor(X, Y) :- son(X, Z), (Y = Z; successor(Z, Y)).
使用此规则,Prolog大致按如下方式解析查询successor(X, Y)
:
Z
的儿子的每个X
:
Y
绑定到Z
,将Z
作为解决方案。;
运算符用作逻辑OR,因此现在Y
未绑定,并且递归调用successor/2
以获取Z
的儿子的继任者。是的,请尝试获取Prolog艺术的副本。这不是最容易阅读的编程书籍,但我发现它对我(正在)理解逻辑编程的尝试非常有帮助。似乎有一些廉价精装本的1994年版本在eBay附近浮动。
答案 1 :(得分:3)
你说:
第一条规则会打印出所有三个直接孩子,然后第二条规则打印出所有后代。
对于任何给定的谓词(例如successor/2
),PROLOG通常会按顺序评估第1个子句的所有可能解决方案,然后是下一个,等等到最后一个子句。因此,PROLOG将完全按照您的建议行事 - 首先会找到对直系子项的解法,因为successor/2
的第一个子句就是这样,第二个子句找到了后代。如果您使用的是其他订单,请尝试重新订购这些条款(即。);
successor(X, Y) :- son(X, C), successor(C, Y).
successor(X, Y) :- son(X, Y).
这将导致PROLOG评估为:
?- successor(elizabeth, Y).
Y = william ;
Y = henry ;
Y = severn ;
Y = charles ;
Y = andrew ;
Y = edward.
即所有直系儿童之前的血统。
然而,通过对这些子目标进行简单的重新排序,无法实现您想要的顺序。相反,请考虑各种树遍历方法;即,有序,预订和后订购。您可以编写一个(简单)程序,它能够以各种不同的方式遍历树结构,而不是PROLOG的默认评估顺序。例如,请考虑以下successor/2
的新定义:
successor(Parent, [Son|SonDescendents]) :-
son(Parent, Son),
successor(Son, SonDescendents).
本条款旨在深度优先填充儿子的子列表,并将回溯以找到所有解决方案。
successor(NonParent, []) :-
\+ son(NonParent, _).
这个下一个子句处理基本情况,即给定的个体没有任何儿子,因此没有后代进入结果列表(空)。
评估这个给出:
?- successor(elizabeth, S).
S = [charles, william] ;
S = [charles, henry] ;
S = [andrew] ;
S = [edward, severn] ;
false.
PS。我强烈推荐以下用于学习PROLOG的文本:
The Art of Prolog, by Leon Sterling and Ehud Shapiro
答案 2 :(得分:1)
你的规则集对我来说很好,它给你正确的结果,它只是打印它们推断它们,这使得订单看起来不正确。在纸上完成结果,您可能会得到类似的结果。