0

Prologに人々の単純なデータベースがあるとしましょう

person(john).
person(mary).    
person(john).
person(susan).

全体を 1 回だけ一致させる必要があります。

john-mary, john-john, john-susan, mary-john, mary-susan, john-susan

私はこのようなものを考え出そうとしました:

match:- person(X),!,person(Y),   write(X),write(-), write(Y),nl.
run:- person(X), match(X), fail.

しかし、それは何度も一致していて、人を自分自身に一致させるべきではありません。

基本的に、私が必要とするのは、すべての X を反復処理し、Prolog が Y を厳密に「下」に見えるようにすることです。

4

2 に答える 2

2

手っ取り早い解決策は、あなたの人々に番号を付けることです:

person(1, john).
person(2, mary).
person(3, john).
person(4, susan).

次に、次のような人と一致させることができます。

match(X-Y) :-
  person(I, X), person(J, Y), I < J.

2つのjohnエントリがあるため、他のソリューションが機能するかどうかはわかりません。通常、を使用して順序付けを偽造することもできますが@>/2、その場合は原子が一意である必要があり、そうでないため、解決が妨げられjohn-johnます。

編集:私たちは人々のデータベースを具体化するために喜んで使用するのでfindall/3、これをリストの問題として扱い、機能的な解決策を見つけることができます。リスト内のすべての組み合わせを取得しましょう。

combinations([X|Rest], X, Y) :- member(Y, Rest).
combinations([_|Rest], X, Y) :- combinations(Rest, X, Y).

この述語が手元にあれば、解決策を見つけることができます。

combined_folks(People) :-
  findall(P, person(P), Persons),
  findall(X-Y, combinations(Persons, X, Y), People).

?- combined_folks(X).
X = [john-mary, john-john, john-susan, mary-john, mary-susan, john-susan].

それは実際にはかなりきれいであることが判明しました!

于 2013-02-25T20:27:13.713 に答える
1
person(john).
person(mary).    
person(john).
person(susan).    

match :- findall(P,person(P),People), match_all(People).

match_all([_]) :- !.
match_all([P|People]) :- match_2(P,People), match_all(People).

match_2(_,[]) :- !.
match_2(P1,[P2|People]) :- format('~a-~a~n',[P1,P2]), match_2(P1,People).

?- match.
于 2013-02-25T20:59:13.057 に答える