2015-11-10 11 views
7

Mi piacerebbe creare una matrice in MATLAB dove:Matrice di 0 e 1 Dove Assegnazione a righe successive sono condizionate sulla riga precedente

La prima riga è costituito da una disposizione casuale di 0 e 1, diviso equamente (cioè 50-50).

La seconda riga assegna in modo casuale gli zeri al 50% degli 0 e 1 nella prima riga e quelli al restante 50%.

La terza riga assegna a caso zero zeri al 50% degli 0 e 1 secondo nella seconda riga e uno al restante 50%.

non-randomizzato Esempio:

0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 
0 0 0 0 1 1 1 1 0 0 0 0 1 1 1 1 
0 0 1 1 0 0 1 1 0 0 1 1 0 0 1 1 

Qualche suggerimento?

+0

È che non è la stessa come solo mischiare le colonne del non- esempio randomizzato? Se è così, basta usare 'randperm' – Dan

+2

@Dan: Non pensarlo, per caso la terza riga potrebbe sembrare la prima se capisco bene la descrizione. Permutando, non puoi ottenere questo. – Daniel

risposta

7

Una soluzione basata sulla verifica se i numeri sono più grandi o più piccolo rispetto alla mediana. Finché il numero di colonne testate è pari, esattamente la metà di un insieme di doppi casuali sarà più grande della mediana e metà sarà più piccola. Questo garantisce che esca esattamente il 50% dei bit capovolti.

nRows = 3; 
nCols = 16; %# divisible by 4 

%# seed the array 
%# assume that the numbers in each row are unique (very, very likely) 
array = rand(nRows,nCols); 


out = false(nRows,nCols); 

%# first row is special 
out(1,:) = array(1,:) > median(array(1,:)); 

%# for the rest of the row, check median for the zeros/ones in the previous row 
for iRow = 2:nRows 
    zeroIdx = out(iRow-1,:) == 0; 
    %# > or < do not matter, both will replace zeros/ones 
    %# and replace with exactly half zeros and half ones 
    out(iRow,zeroIdx) = array(iRow,zeroIdx) > median(array(iRow,zeroIdx)); 
    out(iRow,~zeroIdx) = array(iRow,~zeroIdx) > median(array(iRow,~zeroIdx)); 
end 
2

Una soluzione con randperm:

nrows = 3; 
ncols = 16; 
M = zeros(nrows,ncols);  

%// seed the first row 
M(1,1:ncols/2) = 1; 
M(1,:) = M(1,randperm(ncols)); 

for r = 2:nrows 

    %// Find ncols/4 random between 1 and ncols/2. These will be used to index half of the previous rows 1 elements and set them to one 
    idx = randperm(ncols/2); 
    idx1 = idx(1:ncols/4); 
    %// Do the same thing again, but this time it will be used for the 0 elements of the previous row 
    idx = randperm(ncols/2); 
    idx0 = idx(1:ncols/4); 

    idx_prev1 = find(M(r-1,:)); %// Find where the 1 elements were in the last row 
    idx_prev0 = find(~M(r-1,:)); %// Find where the 0 elements were in the last row 

    M(r,idx_prev1(idx1))=1; %// Set half of the previous rows 1 elements in this row to 1 
    M(r,idx_prev0(idx0))=1; %// Set half of the previous rows 0 elements in this row to 1 

end 
3

Ti offrirei un breve bsxfun soluzione:

%// number of divisions 
n = 4; 

%// unshuffled matrix like in your example 
unshuffled = bsxfun(@(a,b) mod(a,2*b) > b-1, meshgrid(1:n^2,1:n) - 1, (2.^((n-1):-1:0)).') %' 

%// shuffle columns 
shuffled = unshuffled(:,randperm(n^2)) 

unshuffled = 

0  0  0  0  0  0  0  0  1  1  1  1  1  1  1  1 
0  0  0  0  1  1  1  1  0  0  0  0  1  1  1  1 
0  0  1  1  0  0  1  1  0  0  1  1  0  0  1  1 
0  1  0  1  0  1  0  1  0  1  0  1  0  1  0  1 


shuffled = 

1  0  1  1  0  1  0  1  1  1  1  0  0  0  0  0 
1  1  1  0  0  1  1  0  1  0  0  0  1  0  1  0 
1  0  0  1  0  0  0  0  1  1  0  1  1  0  1  1 
1  1  1  1  0  0  0  0  0  0  1  0  0  1  1  1 

In primo luogo è necessario creare la matrice unshuffled, che può essere fatto confrontando la matrice generata da meshgrid(1:n^2,1:n) con un modulo dipendente dalla fila. Finalmente hai solo bisogno di mischiare le colonne.

+1

Come sottolineato nei commenti alla domanda, mischiare le colonne della matrice perfetta non randomizzata potrebbe non essere sufficiente. Poiché la domanda è formulata, a condizione che non sia formulata correttamente, non vi è alcuna ragione per cui non potrebbero esserci 2 colonne di solo '1's per esempio. Questo metodo considera efficacemente tutte le righe precedenti ad ogni passaggio e non solo la riga immediatamente precedente. – Dan

+0

@Dan Non importa quanto mi tormenti la mente, non riesco a interpretare la domanda in questo modo. Dobbiamo aspettare il PO che immagino. – thewaywewalk

+0

OP afferma "La terza riga assegna a caso zeri al 50% degli 0 e 1 nella riga ** secondo ** e quelli al restante 50%.", Quindi la terza riga non deve considerare la prima riga e così potrebbe infatti essere identico alla prima riga ... – Dan

3

Se avete la Statistics Toolbox, si può fare molto facilmente con randsample: risultato

M = 3; %// number of rows 
N = 16; %// number of columns. Should be multiple of 4, according to problem definition 
result = zeros(M,N); %// preallocate and initiallize to zeros 
result(1, randsample(1:N,N/2)) = 1; %// first row: half values set to one, half to zero 
for m = 2:M 
    result(m, :) = result(m-1, :); %// initiallize row m equal to row m-1 
    result(m, randsample(find(result(m-1,:)), N/4)) = 0; %// change half of ones 
    result(m, randsample(find(~result(m-1,:)), N/4)) = 1; %// change half of zeros 
end 

Esempio:

result = 
    0 1 0 1 1 0 0 0 0 1 0 1 1 0 1 1 
    1 1 0 0 0 1 1 1 0 1 0 1 0 0 0 1 
    1 0 0 0 1 0 0 1 0 1 1 0 1 1 0 1 
+0

Non penso che sia corretto. La mia comprensione è che per gli 8 '1 nella riga 2, esattamente 4 degli elementi corrispondenti della riga 3 dovrebbero essere' 1'. Nel tuo esempio 'result' solo 2 sono' 1' – Dan

+1

@Dan Grazie per averlo fatto notare. Mancava una riga per inizializzare ogni riga a quella precedente.Corretto! –

Problemi correlati