web-dev-qa-db-ja.com

Prologのサブセット

私はこのように機能する述語を探しています:

?- subset([1,2,3], X).
X = [] ;
X = [1] ;
X = [2] ;
X = [3] ;
X = [1, 2] ;
X = [1, 2, 3] ;
X = [2, 3] ;
...

いくつかのsubset実装を見てきましたが、サブセットを生成するときではなく、あるリストが別のリストのサブセットであるかどうかを確認するときにすべて機能します。何か案は?

17
arubox

ここに実装があります:

subset([], []).
subset([E|Tail], [E|NTail]):-
  subset(Tail, NTail).
subset([_|Tail], NTail):-
  subset(Tail, NTail).

例に示されている順序ではありませんが、すべてのサブセットが生成されます。

コメント投稿者のリクエストに従って、ここに説明があります:

最初の節は基本ケースです。空のリストは空のリストのサブセットであると記載されています。

2番目と3番目の節は再帰を扱います。 2番目の句は、2つのリストのヘッドが同じで、右側のリストの末尾が左側のリストの末尾のサブセットである場合、右側のリストは左側のリストのサブセットであると述べています。

3番目の節は、左側のリストの先頭をスキップし、右側のリストが左側のリストの末尾のサブセットである場合、右側のリストは左側のリストのサブセットであると述べています。

上記の手順では、順序集合が生成されます。順序付けされていないセットの場合は、permutation/3を使用できます。

unordered_subset(Set, SubSet):-
  length(Set, LSet),
  between(0,LSet, LSubSet),
  length(NSubSet, LSubSet),
  permutation(SubSet, NSubSet),
  subset(Set, NSubSet).
27
gusbro

http://www.probp.com/publib/listut.html には、_subseq0_という述語の実装があります。これは次のことを実行します。

_subseq0(List, List).
subseq0(List, Rest) :-
   subseq1(List, Rest).

subseq1([_|Tail], Rest) :-
   subseq0(Tail, Rest).
subseq1([Head|Tail], [Head|Rest]) :-
   subseq1(Tail, Rest).
_

簡単な説明:subseq0(X, Y)は、Yが サブセット Xのサブシーケンス、subseq1(X, Y)はYが適切かどうかをチェックします サブセット Xのサブシーケンス。

セットのデフォルト表現は一意の要素を持つリストであるため、次の例のように、これを使用してすべてのサブセットを取得できます。

_?- subseq0([1,2,3], X).
X = [1, 2, 3] ;
X = [2, 3] ;
X = [3] ;
X = [] ;
X = [2] ;
X = [1, 3] ;
X = [1] ;
X = [1, 2] ;
false.
_
8
Nubok

セットは、定義上、distinctオブジェクトのコレクションです。サブセットプロシージャ気にしないでくださいセット内の要素の順序について(引数内)。適切な解決策(swiプロローグ)は次のようになります。

subset(_, []).
subset([X|L], [A|NTail]):-
    member(A,[X|L]),    
    subset(L, NTail),
    not(member(A, NTail)).

質問?-サブセット([1,2,3]、E)の場合、次のものが生成されます。

E = [] ;
E = [1] ;
E = [1, 2] ;
E = [1, 2, 3] ;
E = [1, 3] ;
E = [2] ;
E = [2, 3] ;
E = [3] ;
E = [3, 2] ;
false.

それが役立つことを願っています!

2

スーパーセットからサブセットのアイテムを削除してテストすることもできます。

% to delete : an item can be deleted it its in the head or in the tail of a list
delete(I,[I|L],L).
delete(I,[H|L],[H|NL]) :- delete(I,L,NL).
% an [] is an item of an set.A set is a subset of we can recursively delete its head item from the super set.
subset(_,[]).
subset(S,[I|SS]) :- delete(I,S,S1), subset(S1,SS).

例:

subset([a,b,c],S).
S = []
S = [a]
S = [a, b]
S = [a, b, c]
S = [a, c]
S = [a, c, b]
S = [b]
S = [b, a]
S = [b, a, c]
S = [b, c]
S = [b, c, a]
S = [c]
S = [c, a]
S = [c, a, b]
S = [c, b]
S = [c, b, a] 

subset([a,b,a,d,e],[a,e]).
1true
1
durga