问题描述
我受困于这种递归,这并不符合我的预期。
我的错误在哪里?
#!/usr/bin/prolog
% Facts
mother( jeanne,michel ). % great-grandmother,grandfather
mother( genevieve,aubin ). % grandmother,father
mother( irene,alain ). % great-grandmother,grandfather
mother( emilie,colette ). % great-grandmother,grandmother
mother( colette,muriel ). % grandmother,mother
mother( muriel,eve ). % mother,daughter
father( joseph,michel ). % great-grandfather,grandfather
father( michel,aubin ). % grandfather,father
father( xxx,alain ). % great-grandfather,grandfather
father( marcel,colette ). % great-grandfather,grandmother
father( alain,muriel ). % grandfather,mother
father( aubin,eve ). % father,daughter
% Rules
parent( Mother,Child ) :- mother( Mother,Child ).
parent( Father,Child ) :- father( Father,Child ).
ancestors( [Parent|Ancestors],Child ) :-
parent( Parent,Child ),ancestors( Ancestors,Parent ).
% Queries
:-
ancestors( Ancestor,eve ),format( 'Eve ancestors: ~w~n',Ancestor ).
% expected answer is [muriel,colette,alain,emilie,marcel,irene,xxx,aubin,michel,genevieve,joseph,jeanne]
编辑,这是最终的解决方案,谢谢大家。
#!/usr/bin/prolog
/*##- Facts -##*/
mother( jeanne,michel ).
mother( genevieve,sylvie ).
mother( genevieve,brigitte ).
mother( genevieve,aubin ).
mother( irène,alain ).
mother( émilie,colette ).
mother( colette,muriel ).
mother( colette,olivier ).
mother( colette,audrey ).
mother( colette,stéphane ).
mother( muriel,eve ).
father( joseph,michel ).
father( michel,sylvie ).
father( michel,brigitte ).
father( michel,aubin ).
father( séraphin,alain ).
father( marcel,colette ).
father( alain,muriel ).
father( alain,olivier ).
father( yves,audrey ).
father( yves,stéphane ).
father( aubin,eve ).
/*##- Rules -##*/
parent( Mother,Child ).
ancestor( Parent,Child ) :- parent( Parent,Child ).
ancestor( GrandParent,Child ) :-
parent( GrandParent,Parent ),ancestor( Parent,Child ).
grandMothers( GrandMother,Child ) :-
mother( GrandMother,FatherOrMother ),parent( FatherOrMother,Child ).
grandsFathers( GrandsFather,Child ) :-
father( GrandsFather,Child ).
parents( Mother,Father,Child ) :-
father( Father,mother( Mother,Child ).
strictSiblings( SisterOrbrother,Child ) :-
parents( Mother,parents( Mother,SisterOrbrother ),SisterOrbrother \= Child.
siblings( SisterOrbrother,Child ) :-
mother( Mother,SisterOrbrother \= Child ;
father( Father,father( Father,SisterOrbrother \= Child .
/*##- Queries -##*/
theMother :-
mother( Mother,format( 'Ève\'s mother: ~w~n',[Mother] ).
theFather :-
father( Father,format( 'Ève\'s father: ~w~n',[Father] ).
theParents :-
setof( MotherOrFather,parent( MotherOrFather,MotherAndFather ),format( 'Ève\'s parents: ~w~n',[MotherAndFather] ).
theGrandMothers :-
setof( GrandMother,grandMothers( GrandMother,GrandMothers ),format( 'Ève\'s grand-mothers: ~w~n',[GrandMothers] ).
theGrandFathers :-
setof( GrandsFather,grandsFathers( GrandsFather,GrandsPères ),format( 'Ève\'s grand-fathers: ~w~n',[GrandsPères] ).
lesEnfants :-
setof( Child,parents( genevieve,Children ),format( 'Geneviève and Michel children: ~w~n',[Children] ).
theTwoParents :-
parents( Mother,format( 'Ève\'s mother and father: ~w,~w~n',[Mother,Father] ).
theStrictSiblings :-
setof( SisterOrbrother,strictSiblings( SisterOrbrother,muriel ),SistersAndbrothers ),format( 'Muriel\'s strict siblings: ~w~n',[SistersAndbrothers] ).
theSiblings :-
setof( SisterOrbrother,siblings( SisterOrbrother,format( 'Muriel\'s siblings: ~w~n',[SistersAndbrothers] ).
theAncestors :-
setof( Ancestor,ancestor( Ancestor,Ancestors ),format( 'Ève\'s ancestors: ~w~n',[Ancestors] ).
:-
theMother,theFather,theParents,theGrandMothers,theGrandFathers,lesEnfants,theTwoParents,theStrictSiblings,theSiblings,theAncestors,halt( 0 ).
输出为:
Ève's mother: muriel
Ève's father: aubin
Ève's parents: [aubin,muriel]
Ève's grand-mothers: [colette,genevieve]
Ève's grand-fathers: [alain,michel]
Geneviève and Michel children: [aubin,brigitte,sylvie]
Ève's mother and father: muriel,aubin
Muriel's strict siblings: [olivier]
Muriel's siblings: [audrey,olivier,stéphane]
Ève's ancestors: [alain,irène,jeanne,muriel,séraphin,émilie]
解决方法
让我们以交互方式(在SWI Prolog中)执行此操作,而不是在脚本中使用format/2
最后打印答案。
我们希望列表中eve
的所有可能祖先。
所以我们必须
- 向Prolog程序查询目标
ancestor(A,eve)
的所有可能解决方案 - 然后将它们收集到列表中
这是使用谓词bagof/3
,setof/3
或findall/3
中的一个完成的,它们在目标答案上回溯,并用包含所有答案的列表统一变量(bagof/3>有重复答案,对于setof/3
是无重复答案,并且“没有可能的答案”产生[]
而不是{ {1}}。
所以我们只需要确保找到任何祖先的目标是正确的即可。
如果
,我们可以说findall/3
是A
的祖先
-
C
是A
或 的父级
-
C
是某些A
的父母,而D
是D
的祖先
(注意:只是'if',而不是'if a only if'。但是,假设没有其他{em> 方式,C
可能是{的祖先{1}} ...一个合理的“封闭世界假设”)
上述公式非常适合Prolog的搜索策略,该策略尝试首先解析体内最左边的子目标:
A
以“检查左侧的祖先”的方式进行操作:
C
应该导致相同的结果,但实际上却没有:在最初给出好的答案后,Prolog处理器最终将进入无限循环,其中ancestor(A,C) :- parent(A,C).
ancestor(A,D),ancestor(D,C).
调用ancestor(A,C) :- ancestor(A,parent(D,C).
。 (这可以使用更简单的“数据记录”语言)。
反正我们完成了吗?
ancestor(A,C)
现在将所有内容收集到列表中
(在SWI-Prolog中,您必须说要打印长列表,而不是用椭圆代替),
ancestor(A,D)
然后:
?- ancestor(X,eve).
X = muriel ;
X = aubin ;
X = jeanne ;
X = genevieve ;
X = irene ;
X = emilie ;
X = colette ;
X = joseph ;
X = michel ;
X = xxx ;
X = marcel ;
X = alain ;
false.