wake-up-neo.com

Generiere alle möglichen Kombinationen der Elemente einiger Vektoren (kartesisches Produkt)

Ich möchte alle möglichen Kombinationen der Elemente einer bestimmten Anzahl von Vektoren erzeugen.

Zum Beispiel für [1 2], [1 2] und [4 5] möchte ich die Elemente generieren:

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

Das Problem ist, dass ich nicht die Anzahl der Vektoren kenne, für die ich die Kombinationen berechnen muss. Möglicherweise gibt es 3 wie in diesem Fall oder 10, und ich brauche eine Generalisierung . Können Sie mir bitte in MATLAB dabei helfen? Gibt es bereits eine vordefinierte Funktion, die diese Aufgabe erledigen kann?

32
Simon

Testen Sie die Funktion ALLCOMB bei FileExchange.

Wenn Sie Ihre Vektoren in einem Zellenfeld speichern, können Sie es wie folgt ausführen:

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
16
yuk

Betrachten Sie diese Lösung mit der Funktion NDGRID :

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

Oder wenn Sie eine generelle Lösung für eine beliebige Anzahl von Mengen wünschen (ohne die Variablen manuell erstellen zu müssen), verwenden Sie diese Funktionsdefinition:

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

Wenn Sie möchten, können Sie die Ergebnisse sortieren:

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

Der obige Code prüft auch nicht, ob die Sets keine doppelten Werte haben (zB: {[1 1] [1 2] [4 5]}). Fügen Sie diese eine Zeile hinzu, wenn Sie möchten:

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

Diese späte Antwort bietet zwei zusätzliche Lösungen, wobei die zweite die Lösung ist (meiner Meinung nach) und eine Verbesserung von Amros Antwortlösung mit ndgrid durch Anwenden der leistungsstarken kommagetrennten Listen von MATLAB anstelle von Zellenarrays für eine hohe Leistung,

  1. Wenn Sie über die Neural Network Toolbox verfügen: Verwenden Sie combvec
  2. Wenn Sie nicht über die Toolbox verfügen , wie dies normalerweise der Fall ist: Im Folgenden finden Sie eine andere Möglichkeit, das kartesische Produkt für eine beliebige Anzahl von Sätzen zu verallgemeinern.

Genau wie Amro in seiner Antwort liefert die durch Kommas getrennte Listensyntax (v{:}) Sowohl die Eingaben als auch die Ausgaben von ndgrid. Der Unterschied (vierte Zeile) besteht darin, dass cellfun und cell2mat Vermieden werden, indem kommagetrennte Listen erneut als Eingaben für cat angewendet werden:

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

Durch die Verwendung von cat und reshape wird die Ausführungszeit fast halbiert. Dieser Ansatz wurde in meine Antwort auf eine andere Frage und mehr formal von Luis Mendo demonstriert.

11
chappjc

wir können auch die 'combvec'-Anweisung in Matlab verwenden

    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 

Ich hoffe es hilft. Viel Glück.

0