2017-05-26 7 views
2

Ich versuche im Wesentlichen herauszufinden, wie man Code für Basisvektoren verschiedener Konfigurationen von M Objekten in N verschiedenen Zuständen generiert (zum Beispiel, wenn ich 2 Snacks zwischen 2 Kindern hätte, könnte ich haben (2,0) (0,2) oder (1,1), schreckliches Beispiel, aber das ist die Idee)Generiere alle möglichen Spaltenvektoren in Matlab

Ich kämpfe, um herauszufinden, wie man das macht, ohne in viele verschiedene Schleifen zu gehen (ich will das zu sei automatisch). Die Idee wäre, eine Matrix zu erstellen, in der jede Zeile ein Vektor der Länge M ist. Ich würde mit vec (1) = N beginnen und dann eine if-Schleife, wenn sum (vec) == N, Matrix (1,:) = vec ; Dann könnte ich vec (1) = N-i nehmen und dasselbe machen.

Mein einziges Problem ist, ich sehe nicht, wie man das if verwendet und es vergessen, so dass wenn ich vielleicht 2 Objekte an 5 Standorten hätte, wie würde ich das tun (1 0 0 0 1).

Ich sehe nicht, wie das geht.

+0

Also, für 5 Standorte und 20 Objekte, Ihre Vektoren würden '[14 0 3 2 1]' und '[2 1 3 9 5]'? – beaker

+0

An der Börse gibt es eine Funktion namens 'combn'. Überprüfen Sie, ob es das tut, was Sie wollen. – Matt

Antwort

1

Sie könnten eine rekursive Funktion verwenden:

function out = combos(M,N) 

if N == 1 
    out = M; 
else 
    out = []; 
    for i = 0:M 
    subout = combos(M-i,N-1); 
    subout(:,end+1) = i; 
    out = [out;subout]; 
    end 
end 
1

Ich denke, das tut, was Sie wollen.

Die Schlüsselidee besteht darin, nicht die Anzahl der Elemente in jeder Gruppe zu generieren, sondern die Splitpunkte zwischen den Gruppen. Dies kann über Kombinationen mit Wiederholung erfolgen. Matlab nchoosek erzeugt Kombinationen ohne Wiederholung, aber diese werden leicht in das, was wir brauchen, umgewandelt.

M = 5; % number of objects 
N = 3; % number of groups 
t = nchoosek(1:M+N-1, N-1); % combinations without repetition... 
t = bsxfun(@minus, t, 1:N-1); % ...convert into combinations with repetition 
t = diff([zeros(size(t,1), 1) t repmat(M, size(t,1), 1) ], [], 2); % the size of each 
    % group is the distance between split points 

In diesem Beispiel ist das Ergebnis

t = 
    0  0  5 
    0  1  4 
    0  2  3 
    0  3  2 
    0  4  1 
    0  5  0 
    1  0  4 
    1  1  3 
    1  2  2 
    1  3  1 
    1  4  0 
    2  0  3 
    2  1  2 
    2  2  1 
    2  3  0 
    3  0  2 
    3  1  1 
    3  2  0 
    4  0  1 
    4  1  0 
    5  0  0 
1

Dies ist ein ähnlicher Ansatz Luis' ohne bsxfun. Weil wir Spaß nicht mögen.

n = 5; 
k = 3; 

c = nchoosek(n+k-1, k-1); 
result = diff([zeros(c, 1) nchoosek(1:(n+k-1), k-1) ones(c, 1)*(n+k)], [], 2) - 1; 

Dies schafft die Partitionen der ganzen Zahl n mit Länge k. Bei einem Array der Länge n + (k-1) finden wir alle Kombinationen von (k-1) Stellen, um Partitionen zwischen den (unären) Ganzzahlen zu platzieren. Für 5 Einzelteile und 3 Standorte, haben wir 7 Auswahl von wo die Partitionen setzen:

[ 0 0 0 0 0 0 0 ] 

Wenn unsere gewählte Kombination [2 4] ist, ersetzen wir Positionen 2 und 4 mit Partitionen wie folgt aussehen:

[ 0 | 0 | 0 0 0 ] 

Die O geben den Wert in unary, also ist diese Kombination 1 1 3. Um die Werte leicht wiederherzustellen, erweitern wir einfach die Kombinationen mit imaginären Partitionen bei den nächsten Werten links und rechts des Arrays (0 und n+k) und nehmen die Differenz und subtrahieren 1 (weil die Partitionen selbst nicht zum Wert beitragen):

diff([0 2 4 8]) - 1 
ans = 

    1 1 3 

durch die Trennwände in jeder möglichen Kombination von Positionen gleitet, bekommen wir alle Partitionen von n.

Ausgang:

result = 

    0 0 5 
    0 1 4 
    0 2 3 
    0 3 2 
    0 4 1 
    0 5 0 
    1 0 4 
    1 1 3 
    1 2 2 
    1 3 1 
    1 4 0 
    2 0 3 
    2 1 2 
    2 2 1 
    2 3 0 
    3 0 2 
    3 1 1 
    3 2 0 
    4 0 1 
    4 1 0 
    5 0 0 
Verwandte Themen