Подмножества в Прологе - PullRequest
       11

Подмножества в Прологе

17 голосов
/ 06 февраля 2011

Я ищу предикат, который работает следующим образом:

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

Я видел несколько subset реализаций, но все они работают, когда вы хотите проверить, является ли один список подмножествомдругой, не когда вы хотите создать подмножества.Есть идеи?

Ответы [ 5 ]

26 голосов
/ 07 февраля 2011

Здесь идет реализация:

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

Он сгенерирует все подмножества, но не в порядке, указанном в вашем примере.

В соответствии с запросом комментатора здесь приводится объяснение:

Первый пункт - базовый вариант. В нем говорится, что пустой список является подмножеством пустого списка.

Второй и третий пункты касаются рекурсии. Второе предложение гласит, что если два списка имеют одинаковый заголовок и хвост правого списка является подмножеством хвоста левого списка, то правый список является подмножеством левого списка.

В третьем пункте говорится, что если мы пропустим заголовок левого списка, а правый список является подмножеством хвоста левого списка, то правый список является подмножеством левого списка.

Процедура, показанная выше, создает упорядоченные множества. Для неупорядоченных множеств вы можете использовать permutation/3:

unordered_subset(Set, SubSet):-
  length(Set, LSet),
  between(0,LSet, LSubSet),
  length(NSubSet, LSubSet),
  permutation(SubSet, NSubSet),
  subset(Set, NSubSet).
8 голосов
/ 06 февраля 2011

В 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.

Поскольку представление по умолчанию дляset - это список с уникальными элементами, вы можете использовать его для получения всех подмножеств, как в следующем примере:

?- 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.
2 голосов
/ 01 января 2016

Set - это набор различных объектов по определению.Процедура подмножества не должна заботиться о порядке элементов в наборе (в аргументах).Правильное решение (swi prolog) может выглядеть так:

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.

Надеюсь, это поможет!

1 голос
/ 11 октября 2018

мы также можем проверить, удалив элемент подмножества из супер-набора.

% 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
0 голосов
/ 29 апреля 2014
append([],L,L).

append([H|T],L,[H|L1]):-append(T,L,L1).


subset([X|T],[X|L]) :-subset(T,L).

subset([X|T],[G|L]) :-subset([X],L),append(L2,[X|L3],[G|L]),append(L2,L3,L4),subset(T,L4).

subset([],_).

----------------------------------------------
?- subset([1,2],[1,2]).

yes

?- subset([1,2],[2,1]).

yes

?- subset([1,1],[1,2]).

no

?- subset(D,[1,2]).

D = [1,2] ;

D = [1] ;

D = [2,1] ;

D = [2] ;

D = '[]' ;

no
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...