我正在制定一项计划,测试一个人是否可以成为公民。当数据库中的某个人被传入时,它应该返回他们做或不符合的所有原因。我的问题是,为了显示所有原因,我使用了无法回溯并找到其他原因,这使得返回false应该是真的。
born(frank,usa,1944).
child(frank,mary,jack).
child(mary,sean,ruth).
born(fiona,usa,1920).
child(fiona,sean,ruth).
citizen(X):- born(X,'irl',_).
natcitizen(X):-naturalized(X,_).
marriedirl(X):-married(X,Y,_),born(Y,'irl',_).
adoptedirl(X):-adopted(X,P1,P2),born(P1,'irl',_),born(P2,'irl',_).
irlparent(X):-child(X,P1,P2),(born(P1,'irl',_);born(P2,'irl',_)).
irlgrandparent(X):- child(X,P1,P2),(child(P1,G1,G2),(born(G1,'irl',_);born(G2,'irl',_));child(P2,G3,G4),(born(G3,'irl',_);born(G4,'irl',_))).
permres5(X):-(permres(X,Start,End),born(X,_,B),A is B, 2015-A@>=18,End==2015,N is End-Start,(N@>=5)).
qualify(X):- \+(citizen(X) ->write(X) ->write_ln( ' is already an irish born citizen')), \+ (natcitizen(X) ->write(X) ->write( ' is already a naturalized Irish citizen')),
(marriedirl(X)->write(X) ->write_ln(' qualifies: he/she is married to an Irish citizen'));
(adoptedirl(X))->write(X) ->write_ln(' qualifies: he/she was adopted by Irish-born parents');
(irlparent(X)->write(X) ->write_ln(' qualifies: he/she has an Irish parent')),fail;
(irlgrandparent(X) ->write(X) ->write_ln(' qualifies: he/she has an Irish grandparent')),fail;
(permres5(X) ->write(X) ->write_ln(' qualifies: he/she is an Irish permanent resident and has been for at least 5 years')),fail.
所以当fiona被召唤时: 菲奥娜有资格:他/她有一个爱尔兰父母 假。 返回而不是真。
坦白说: 弗兰克有资格:他/她有一个爱尔兰父母 弗兰克有资格:他/她有一个爱尔兰祖父母 假的。
它应该说是真的,我不确定如何在不改变失败的情况下改变真值,并打破回溯。
整个代码的pastebin:http://pastebin.com/tp7Mi5s6
答案 0 :(得分:1)
您用来强制枚举所有解决方案的方法称为"故障驱动循环"。
像setof/3
这样的全解决方案谓词可能更适合您的需求。
首先,我将qualify/1
替换为person_qualified_reason/3
:
person_qualified_reason(P,Decision,Reason) :-
citizen(P),
!,
Decision = no,
Reason = 'already an irish born citizen'.
person_qualified_reason(P,Decision,Reason) :-
natcitizen(P),
!,
Decision = no,
Reason = 'already a naturalized Irish citizen'.
person_qualified_reason(P,yes,'married to an Irish citizen') :-
marriedirl(P).
person_qualified_reason(P,yes,'adopted by Irish-born parents') :-
adoptedirl(P).
person_qualified_reason(P,yes,'has an Irish parent') :-
irlparent(P).
person_qualified_reason(P,yes,'has an Irish grandparent') :-
irlgrandparent(P).
person_qualified_reason(P,yes,'has been Irish permanent resident for 5+ years') :-
permres5(P).
示例查询:
?- person_qualified_reason(frank,D,Reason).
D = yes, Reason = 'has an Irish parent' ;
D = yes, Reason = 'has an Irish parent' ; % redundant answer
D = yes, Reason = 'has an Irish grandparent' ;
D = yes, Reason = 'has an Irish grandparent' ; % redundant answer
false.
要收集所有原因,我们可以使用内置setof/3
:
?- setof(Decision-Reason,person_qualified_reason(frank,Decision,Reason),All).
All = [yes-'has an Irish grandparent', yes-'has an Irish parent'].
knownPerson/1
适用于数据库中已知的所有人员:
knownPerson(X) :- adopted(X,_,_).
knownPerson(X) :- adopted(_,X,_).
knownPerson(X) :- adopted(_,_,X).
knownPerson(X) :- naturalized(X,_).
knownPerson(X) :- permres(X,_,_).
knownPerson(X) :- child(X,_,_).
knownPerson(X) :- child(_,X,_).
knownPerson(X) :- child(_,_,X).
knownPerson(X) :- married(X,_,_).
knownPerson(X) :- married(_,X,_).
knownPerson(X) :- born(X,_,_).
为了摆脱knownPerson/1
的冗余答案,我们定义了一个辅助谓词:
person(X) :- setof(t,knownPerson(X),_).
最后,让我们看看谁有资格,谁没有,以及出于哪些原因。我把你在pastebin链接中提供的数据拿走了:
?- person(P),
setof(Q-Reason,person_qualified_reason(P,Q,Reason),Verdict).
P = aisling, Verdict = [yes-'has an Irish grandparent'] ;
P = andy, Verdict = [no-'already a naturalized Irish citizen'] ;
P = anna, Verdict = [yes-'has an Irish grandparent'] ;
P = brendan, Verdict = [no-'already an irish born citizen'] ;
P = bridgen, Verdict = [no-'already an irish born citizen'] ;
P = bridget, Verdict = [yes-'has an Irish parent'] ...