setof 创建多个列表而不是一个列表序言
setof creates many list instead of one list prolog
我有一个使用序言创建的函数,出于某种原因,它总是为每个元素创建多个列表而不是一个列表,有人可以帮我吗?
这是我写的:(问题是最后一个函数创建了很多列表)
father(_father,_child) :- parent(_father,_child), gender(_father,male).
mother(_mother,_child) :- parent(_mother,_child), gender(_mother,female).
couple(_woman,_man):- gender(_woman,female),gender(_man,male),parent(_man,_child),parent(_woman,_child).
parents(_woman,_man,_child) :- father(_man,_child),mother(_woman,_child).
count([],0).
count([H|T],N) :- count(T,N1) , N is N1+1.
child_to_couple(_woman,_man,_num):- couple(_woman,_man),findall(_child,parents(_woman,_man,_child),_childs),count(_childs,_num).
num_of_childs(_list):- couple(_woman,_man),setof(childrens(_man,_woman,_num),child_to_couple(_woman,_man,_num),_list).
数据示例:
gender(sagi,male).
gender(limor,female).
gender(yuval,male).
gender(gilad,male).
gender(shahaf,male).
gender(yaara,female).
parent(eyal,noam).
parent(shiri,yuval2).
parent(eyal,yuval2).
parent(shiri,yonatan).
parent(eyal,yonatan).
parent(shahaf,gan).
parent(yaara,gan).
但是当我 运行
?- num_of_childs(_x).
我得到:
_x = [childrens(mordechai, miriam, 1)] ;
_x = [childrens(salax, naima, 1)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(zvi, tova, 1)] ;
_x = [childrens(avram, yokeved, 1)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(shahaf, yaara, 1)] ;
而不是:
_x = [childrens(sagi, limor, 2),childrens(sagi, limor, 2),childrens(shahaf, yaara, 1),..........etc]
您的 num_of_childs/1
在 setof/3
之前调用了 couple/2
,因此您获得了 couple/2
returns 个结果。因为 child_to_couple/3
也调用 couple/2
你实际上根本不需要它。
num_of_childs(L) :- findall(childrens(M,W,N),child_to_couple(W,M,N),L).
但最大的问题是 couple/2
,按照你写的方式,每次 child 总是成功一次。这会向上传播,因此 child_to_couple/2
和 num_of_childs/1
也会成功多次。
如果你改成这个
couple(W,M):-
gender(W,female), gender(M,male),
( parent(M,C), parent(W,C) -> true ; false ).
无论child人有多少,每对夫妇只能获得一个结果。我感觉可能有更简单的方法来完成此操作,但我找不到它。
?- num_of_childs(L).
L = [childrens(eyal,shiri,2),childrens(shahaf,yaara,1)] ? ;
no
补充:使用切割会稍微简单一些,但也更难看。
我有一个使用序言创建的函数,出于某种原因,它总是为每个元素创建多个列表而不是一个列表,有人可以帮我吗?
这是我写的:(问题是最后一个函数创建了很多列表)
father(_father,_child) :- parent(_father,_child), gender(_father,male).
mother(_mother,_child) :- parent(_mother,_child), gender(_mother,female).
couple(_woman,_man):- gender(_woman,female),gender(_man,male),parent(_man,_child),parent(_woman,_child).
parents(_woman,_man,_child) :- father(_man,_child),mother(_woman,_child).
count([],0).
count([H|T],N) :- count(T,N1) , N is N1+1.
child_to_couple(_woman,_man,_num):- couple(_woman,_man),findall(_child,parents(_woman,_man,_child),_childs),count(_childs,_num).
num_of_childs(_list):- couple(_woman,_man),setof(childrens(_man,_woman,_num),child_to_couple(_woman,_man,_num),_list).
数据示例:
gender(sagi,male).
gender(limor,female).
gender(yuval,male).
gender(gilad,male).
gender(shahaf,male).
gender(yaara,female).
parent(eyal,noam).
parent(shiri,yuval2).
parent(eyal,yuval2).
parent(shiri,yonatan).
parent(eyal,yonatan).
parent(shahaf,gan).
parent(yaara,gan).
但是当我 运行
?- num_of_childs(_x).
我得到:
_x = [childrens(mordechai, miriam, 1)] ;
_x = [childrens(salax, naima, 1)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(eli, bella, 2)] ;
_x = [childrens(zvi, tova, 1)] ;
_x = [childrens(avram, yokeved, 1)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(haim, irit, 3)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(guy, pelit, 2)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(eyal, shiri, 3)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(sagi, limor, 2)] ;
_x = [childrens(shahaf, yaara, 1)] ;
而不是:
_x = [childrens(sagi, limor, 2),childrens(sagi, limor, 2),childrens(shahaf, yaara, 1),..........etc]
您的 num_of_childs/1
在 setof/3
之前调用了 couple/2
,因此您获得了 couple/2
returns 个结果。因为 child_to_couple/3
也调用 couple/2
你实际上根本不需要它。
num_of_childs(L) :- findall(childrens(M,W,N),child_to_couple(W,M,N),L).
但最大的问题是 couple/2
,按照你写的方式,每次 child 总是成功一次。这会向上传播,因此 child_to_couple/2
和 num_of_childs/1
也会成功多次。
如果你改成这个
couple(W,M):-
gender(W,female), gender(M,male),
( parent(M,C), parent(W,C) -> true ; false ).
无论child人有多少,每对夫妇只能获得一个结果。我感觉可能有更简单的方法来完成此操作,但我找不到它。
?- num_of_childs(L).
L = [childrens(eyal,shiri,2),childrens(shahaf,yaara,1)] ? ;
no
补充:使用切割会稍微简单一些,但也更难看。