2010-11-12 17 views
31

Chciałbym wygenerować wszystkie możliwe kombinacje elementów z danej liczby wektorów.Wygeneruj wszystkie możliwe kombinacje elementów niektórych wektorów (iloczyn kartezjański)

Na przykład dla [1 2], [1 2] i [4 5] Chcę wygenerować elementy:

[1 1 4; 1 1 5; 1 2 4; 1 2 5; 2 1 4; 2 1 5; 2 2 4; 2 2 5]

Problemem jest to, że nie wiem liczbę wektorów, dla których muszę obliczyć kombinacje . Mogą być 3, jak w tym przypadku, lub może być 10, i potrzebuję generalizacji. Czy możesz mi pomóc w tym w MATLAB? Czy istnieje już predefiniowana funkcja, która może wykonać to zadanie?

+10

to, czego szukasz, nazywa się "produktem kartezjańskim" wektorów. Możesz mieć trochę szczęścia w szukaniu go. –

Odpowiedz

16

Wypróbuj funkcję ALLCOMB w FileExchange.

Jeśli przechowujesz ci wektorów w macierzy komórkowej, można uruchomić go tak:

a = {[1 2], [1 2], [4 5]}; 
allcomb(a{:}) 
ans = 

    1  1  4 
    1  1  5 
    1  2  4 
    1  2  5 
    2  1  4 
    2  1  5 
    2  2  4 
    2  2  5 
+6

Zauważ, że 'ALLCOMB' używa' NDGRID' w zasadniczo taki sam sposób jak w odpowiedzi Amro, z odpornością na błędy na górze. – lodhb

+0

Tak, właśnie to, czego szukałem .. :-) – tim

46

Rozważmy to rozwiązanie za pomocą NDGRID funkcję:

sets = {[1 2], [1 2], [4 5]}; 
[x y z] = ndgrid(sets{:}); 
cartProd = [x(:) y(:) z(:)]; 

cartProd = 
    1  1  4 
    2  1  4 
    1  2  4 
    2  2  4 
    1  1  5 
    2  1  5 
    1  2  5 
    2  2  5 

Albo jeśli chcesz rozwiązanie ogólne dla dowolnej liczby zestawów (bez konieczności ręcznego tworzenia zmiennych) użyj tej definicji funkcji:

function result = cartesianProduct(sets) 
    c = cell(1, numel(sets)); 
    [c{:}] = ndgrid(sets{:}); 
    result = cell2mat(cellfun(@(v)v(:), c, 'UniformOutput',false)); 
end 

Zauważ, że jeśli wolisz, możesz sortować wyniki:

cartProd = sortrows(cartProd, 1:numel(sets)); 

Ponadto, powyższy kod nie sprawdza, czy zestawy nie mają zduplikowanych wartości (EX: {[1 1] [1 2] [4 5]}). Dodaj tę jedną linię, jeśli chcesz:

sets = cellfun(@unique, sets, 'UniformOutput',false); 
11

tak późno odpowiedzi udostępnia dwa dodatkowe rozwiązania, gdzie drugi jest rozwiązanie (moim zdaniem) i poprawa na rozwiązanie odpowiedzi Amro z ndgrid stosując MATLAB Potężny oddzielone przecinkami listy zamiast tablic komórkowych do wysokiej wydajności,

  1. Jeśli masz Neural Network Toolbox: Redakcyjne combvec
  2. Jeśli nie nie posiadać zestaw narzędzi, jak to zwykle bywa: poniżej jest inny sposób uogólnienia produktu kartezjańskiego dla dowolnej liczby zestawów.

Podobnie jak Amro zrobił w swojej odpowiedzi, list składnia oddzielone przecinkami (v{:}) dostarcza zarówno wejścia i wyjścia ndgrid. Różnica (czwarta linia) jest to, że unika cellfun i cell2mat stosując list oddzielonych przecinkami, znowu, teraz, jak wejść do cat:

N = numel(a); 
v = cell(N,1); 
[v{:}] = ndgrid(a{:}); 
res = reshape(cat(N+1,v{:}),[],N); 

Zastosowanie cat i reshape skraca czas wykonania prawie w połowie. To podejście zostało zademonstrowane w my answer to an different question i more formally by Luis Mendo.

0

możemy również użyć 'combvec' dyspozycję w Matlab

no_inp=3 % number of inputs we want...in this case we have 3 inputs     
    a=[1 2 3] 
    b=[1 2 3] 
    c=[1 2 3] 

    pre_final=combvec(c,b,a)'; 
    final=zeros(size(pre_final)); 

    for i=1:no_inp 
    final(:,i)=pre_final(:,no_inp-i+1); 
    end 
    final 

Nadzieję, że to pomaga. Powodzenia.

Powiązane problemy