微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Prolog:让我的谓词返回所有可能的解决方案

如何解决Prolog:让我的谓词返回所有可能的解决方案

我在prolog online的99-problems中发现了这个问题。有一个解决方案(与我的无关),我想知道为什么我的不起作用。或者准确地说:它有效,但它只找到了 1 个解决方案,而不是所有解决方案。问题是这样表述的: a) 一组 9 人可以在 3 个不相交的 2、3 和 4 人小组中以多少种方式工作?

member(X,[X]).
member(X,[X|_]).
member(X,[_|R]):- member(X,R).

append(X,[],X).
append([],X,X).
append([H|R],[A|B],[H|W]):- append(R,W).

group234(G,G2,G3,G4):- length(G2,2),length(G3,3),length(G4,4),member(X,G),member(Y,member(Z,G2),G3),append(G2,I),append(I,G4,G).

q1:有没有办法像我一样使用长度和附加和成员并成功完成这个,还是我需要完全重写它?
q2:为什么这段代码只产生 1 个解决方案? Prolog 应该搜索许多可能的成员,不是吗?(显然,它不应该,因为该语言比我更了解。但据我所知,它应该搜索,为什么不?)

解决方法

您只需要 append/3 来定义谓词以选择和删除组中的一个人:

choose(X,L1,L2) :-
    append(A,[X|B],L1),append(A,B,L2).

例如:

?- choose(X,[a,b,c],Rest).
X = a,Rest = [b,c] ;
X = b,Rest = [a,c] ;
X = c,b] ;
false.

然后,使用此谓词,您可以将 group234/4 定义为:

group234(G,[A,B],[C,D,E],G4):-
    choose(A,G,G0),choose(B,G0,G1),A @< B,choose(C,G1,G2),choose(D,G2,G3),C @< D,choose(E,G3,G4),D @< E.

请注意,您需要条件 A @< B,以避免排列(因为两个列表 [A,B][B,A] 代表同一组)。类似地,条件 C @< DD @< E 避免了列表 [C,E] 的排列。

示例:

?- group234([a,c,d,e,f,g,h,i],G4).
G2 = [a,b],G3 = [c,e],G4 = [f,i] ;
G2 = [a,f],G4 = [e,g],h],i] 
...
,

我认为问题的表述相当模糊。 @slago 提出的(不错!+1)解决方案依赖于可排序的元素,但我认为该解决方案应该在列表的 positions 上进行表达。这是他们完成的解决方案,使用库谓词表示:

%!  %%%%

group234(G,G4):-
    select(A,select(B,select(C,select(D,select(E,D @< E.

n_group234_slago(N) :-
    numlist(1,9,L),aggregate_all(count,group234(L,_,_),N).

这是我的

take_ordered(L,[X],R) :-
    select(X,L,R).
take_ordered(L,[X|Xs],R) :-
    append(H,[X|T],take_ordered(T,Xs,J),append(H,J,R).

group234_cc(L,[A1,A2],[B1,B2,B3],[C1,C2,C3,C4]) :-
    take_ordered(L,U),take_ordered(U,C4]).

n_group234_cc(N) :-
    numlist(1,group234_cc(L,_A,_B,_C),N).

n_group234_slago(N)n_group234_cc(N) 都返回请求的正确数字 N

编辑

我对 take_ordered/3 不满意。然后,我试着用 DCG 来表达:

take_ordered([],[]) --> [].
take_ordered([X|Xs],Ys) --> [X],take_ordered(Xs,Ys).
take_ordered(Xs,[Y|Ys]) --> [Y],Ys).

take_ordered(L,O,R) :-
    phrase(take_ordered(O,R),L).

效率提升显着,推理次数减半。

编辑

“P-99:九十九个序言问题”站点提出的解决方案 group3/4 的效率远低于您在此处找到的 @slago 和我的建议。

?- numlist(1,time(aggregate_all(count,group3(L,A,C),N)).
% 122,373 inferences,...

?- time(n_group234_cc(N)).
% 7,549 inferences,...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。