比較で 1 つのセットを削除できます。
brother(X, Y) :-
son(X, P),
son(Y, P),
X \= Y, X @< Y.
?- brother(X, Y).
X = a,
Y = b ;
X = a,
Y = b ;
false.
X と Y は両方の方法でインスタンス化されるため、X が Y よりも小さいことを要求することは、ソリューションを半分に削減する良い方法です。
2 番目の問題は、X と Y が複数の親を持つ兄弟であることです。ここでの最も簡単な解決策は、ルールをより明確にすることです。
mother(a, d).
mother(b, d).
father(a, c).
father(b, c).
brother(X, Y) :-
mother(X, M), mother(Y, M),
father(X, F), father(Y, F),
X \= Y, X @< Y.
?- brother(X, Y).
X = a,
Y = b ;
false.
このメソッドはこの特定の問題に非常に固有のものですが、根本的な理由はそうではありません:a
とb
が「兄弟」であるため、2 つのコピーがあっc
た — d
Prolog がそのソリューションを 2 回作成したのは正しかったのです。異なる値。
より洗練された解決策は、おそらく を使用setof/3
して解決策を取得することです。これは、元のコードでも機能します。
?- setof(X-Y, (brother(X, Y), X @< Y), Brothers).
Brothers = [a-b].
このアプローチの欠点は、Prolog がさまざまなソリューションを生成するのではなく、リストになってしまうことですが、member/2
.