Prolog标签在Prolog中提供了冗余解决方案

时间:2018-12-23 13:32:28

标签: prolog clpfd

我有一个学校要做的作业,如下: 安妮(Anne)和米歇尔(Michel)是与一群人一起组织晚餐的人 夫妻。它们必须面对面地放在桌子上。

男人也必须与女人交往,已婚人士不能 邻居,对于不相容的人也是如此。最后,邻居们 必须分享至少一项嗜好。

我的解决方案似乎有效,但是我有两个问题: 首先,当我使用“ go”生成解决方案时。然后按“;”,我收到了太多的解决方案(似乎要绕圈...)。其次,当我删除一对夫妇(在注释部分中)时,解决方案在很长一段时间后出现了……我看不到任何有关这些行为的解释,但是我两个月前才发现Prolog。任何帮助将不胜感激。

Program can be tried here...

:- use_module(library(clpfd)).
% ---------------------------------------------------------------------- %
%                                                                        %
%                        MAIN PREDICATE                                  %
%                                                                        %
% ---------------------------------------------------------------------- %

go :- Guests = [  manon, alice, juliette, lucie, charlotte, olivia, margaux,
                     jules, hugo, tom, louis, paul, jean, antoine  ],
%go :- Guests = [  alice, juliette, lucie, charlotte, olivia, margaux,
%                     hugo, tom, louis, paul, jean, antoine  ],
      produce_table(Guests).

produce_table(Guests) :-

    length([anne, michel|Guests],Nb),
    produce_assoc_list([anne, michel|Guests],La,Nb),

    reduce_domain(La,Nb),
    different_places(La),
    label_places(La),

    sort(2,@<,La,La_trie),
    print_table(La_trie).

% ---------------------------------------------------------------------- %
%                                                                        %
%                          ASSOCIATIVE LIST                              %
%                                                                        %
% ---------------------------------------------------------------------- %

produce_assoc_list([],[],_) :- !.
produce_assoc_list([N|L],[pers(N,P)|La],Nb) :-
    P in 1..Nb,
    ( N == anne -> P#=1
    ; true),
    ( N == michel -> P*2 #>= Nb, P*2 #=< Nb+2
    ; true),
    produce_assoc_list(L,La,Nb).

% ---------------------------------------------------------------------- %
%                                                                        %
%                               CONSTRAINTS                              %
%                                                                        %
% ---------------------------------------------------------------------- %

reduce_domain_aux(_,[],_) :- !.
reduce_domain_aux(pers(N1,P1),[pers(N2,P2)|T],Nb) :-
    gender(N1,S1),gender(N2,S2),
    ( S1==S2 -> separate_neighbors(P1,P2,Nb)
    ; true),

    hobby(N1,H1),hobby(N2,H2),
    intersection(H1,H2,I),
    ( I==[] -> separate_neighbors(P1,P2,Nb)
    ; true),

    ( married(N1,N2) -> separate_neighbors(P1,P2,Nb)
    ; true),

    ( incompatibles(N1,N2) -> separate_neighbors(P1,P2,Nb)
    ; true),

    reduce_domain_aux(pers(N1,P1),T,Nb).

reduce_domain([],_) :- !.
reduce_domain([H|T],Nb) :-
    reduce_domain_aux(H,T,Nb),
    reduce_domain(T,Nb).


% Persons at different places
% ----------------------------------

vars_list([],[]) :- !.
vars_list([pers(_,P)|T],[P|L]) :-
    vars_list(T,L).

different_places(Lp) :-
    vars_list(Lp,Lv),
    all_distinct(Lv).

% ---------------------------------------------------------------------- %
%                                                                        %
%                                LABELING                                %
%                                                                        %
% ---------------------------------------------------------------------- %

label_places(Lp) :-
    vars_list(Lp,Lv),
    label(Lv).

% ---------------------------------------------------------------------- %
%                                                                        %
%                            USEFULL PREDICATES                          %
%                                                                        %
% ---------------------------------------------------------------------- %

married(X,Y) :-
    spouses(X,Y);spouses(Y,X), !.

incompatibles(X,Y) :-
    incompatible(X,Y); incompatible(Y,X), !.

separate_neighbors(P1,P2,Nb) :- 
    P1  #\= (P2+1) mod Nb,
    P1  #\= (P2-1) mod Nb.

% ---------------------------------------------------------------------- %
%                                                                        %
%                                PRINT RESULTS                           %
%                                                                        %
% ---------------------------------------------------------------------- %

print_table([]) :- !, nl.
print_table([pers(N,P)|T]) :-
    nl, format('~w ~d ~w ~a ',['Place ',P, ' :', N]),
    print_table(T).

% ---------------------------------------------------------------------- %
%                                                                        %
%                            DATABASE                                    %
%                                                                        %
% ---------------------------------------------------------------------- %

spouses(anne,michel).
spouses(manon,jules).
spouses(alice,hugo).
spouses(juliette,tom).
spouses(lucie,louis).
spouses(charlotte,paul).
spouses(olivia,jean).
spouses(margaux,antoine).

gender(anne,f).
gender(manon,f).
gender(alice,f).
gender(juliette,f).
gender(lucie,f).
gender(charlotte,f).
gender(olivia,f).
gender(margaux,f).

gender(michel,m).
gender(jules,m).
gender(hugo,m).
gender(tom,m).
gender(louis,m).
gender(paul,m).
gender(jean,m).
gender(antoine,m).

hobby(anne,[sport,jardinage,voyages]).
hobby(manon,[jardinage,voyages]).
hobby(alice,[jardinage,voyages]).
hobby(juliette,[sport,voyages]).
hobby(lucie,[jardinage]).
hobby(charlotte,[jardinage]).
hobby(olivia,[sport,jardinage]).
hobby(margaux,[sport]).

hobby(michel,[sport,jardinage,voyages]).
hobby(jules,[sport,jardinage]).
hobby(hugo,[sport,jardinage]).
hobby(tom,[sport,voyages]).
hobby(louis,[sport,jardinage]).
hobby(paul,[sport]).
hobby(jean,[sport,jardinage]).
hobby(antoine,[sport,jardinage]).

incompatible(manon,louis).
incompatible(charlotte,antoine).
incompatible(margaux,hugo).

0 个答案:

没有答案