Matrice di lunghezza sconosciuta in MATLAB?

Sto provando ad impostare una matrice zero di lunghezza variabile con due colonne in cui posso produrre i risultati di un ciclo while (con l’intenzione di usarlo per memorizzare i dati del passo dal metodo di Eulero con intervalli di tempo regolati). La lunghezza sarà determinata dal numero di iterazioni del ciclo.

Mi chiedo se c’è un modo per farlo mentre sto eseguendo il ciclo o se devo configurarlo per cominciare e come farlo.

se il numero di colonne è fisso puoi sempre aggiungere righe alla tua matrice (all’interno del ciclo)

per esempio

while (....) ..... new_row =[xy] ; % new row with values x & y mat = [mat ; new_row]; 

naturalmente se si conosce il numero di iterazioni prima del ciclo while è più efficiente pre-allocare la matrice

Un altro approccio che ha in mente le prestazioni mentre si cerca ancora di essere efficiente in termini di spazio è quello di preallocare la memoria in lotti di grandi dimensioni, aggiungendo più lotti secondo necessità. Questo è adatto se devi aggiungere un gran numero di oggetti senza sapere quanti in anticipo.

 BLOCK_SIZE = 2000; % initial capacity (& increment size) listSize = BLOCK_SIZE; % current list capacity list = zeros(listSize, 2); % actual list listPtr = 1; % pointer to last free position while rand<1-1e-5 % (around 1e5 iterations on avrg) % push items on list list(listPtr,:) = [rand rand]; % store new item listPtr = listPtr + 1; % increment position pointer % add new block of memory if needed if( listPtr+(BLOCK_SIZE/10) > listSize ) % less than 10%*BLOCK_SIZE free slots listSize = listSize + BLOCK_SIZE; % add new BLOCK_SIZE slots list(listPtr+1:listSize,:) = 0; end end list(listPtr:end,:) = []; % remove unused slots 

EDIT : come un confronto temporale, considerare i seguenti casi:

  1. Lo stesso codice di cui sopra fatto per 50000 iterazioni.
  2. Preallocare in anticipo l’intera matrice: list = zeros(50000,2); list(k,:) = [xy]; list = zeros(50000,2); list(k,:) = [xy];
  3. Aggiunta dynamic di vettori alla matrice: list = []; list(k,:) = [xy]; list = []; list(k,:) = [xy];

Sulla mia macchina, i risultati sono stati:

1) Il tempo trascorso è 0.080214 secondi .
2) Il tempo trascorso è 0,065513 secondi.
3) Il tempo trascorso è 24,433315 secondi.


Aggiornare:

Dopo le discussioni nei commenti, ho eseguito nuovamente alcuni test utilizzando l’ultima versione di R2014b. La conclusione è che le versioni recenti di MATLAB hanno notevolmente migliorato le prestazioni della crescita automatica degli array!

Comunque c’è una presa; la matrice deve essere in crescita attraverso l’ultima dimensione (colonne nel caso di matrici 2D). Ecco perché accodare file come originariamente previsto è ancora troppo lento senza preallocazione. È qui che la soluzione proposta sopra può davvero aiutare (estendendo l’array in lotti).

Vedi qui per il set completo di test: https://gist.github.com/amroamroamro/0f104986796f2e0aa618

MATLAB utilizza la digitazione dynamic con gestione automatica della memoria. Ciò significa che non è necessario dichiarare una matrice di dimensioni fisse prima di utilizzarla: è ansible modificarla mentre procedete e MATLAB allocerà dynamicmente la memoria per voi.

MA è molto più efficiente allocare prima la memoria per la matrice e poi usarla. Ma se i tuoi programmi hanno bisogno di questo tipo di flessibilità, provaci.

Suppongo che tu debba continuare ad accodare le righe alla tua matrice. Il seguente codice dovrebbe funzionare.

 Matrix = []; while size(Matrix,1) <= 10 Matrix = [Matrix;rand(1,2)]; end disp(Matrix); 

Qui, stiamo riallocando dynamicmente lo spazio richiesto per Matrix ogni volta che aggiungi una nuova riga. Se si conosce in anticipo, ad esempio, un limite superiore al numero di righe che si avranno, è ansible dichiarare Matrix = zeros(20,2) e quindi inserire ogni riga nella matrice in modo incrementale.

 % Allocate space using the upper bound of rows (20) Matrix = zeros(20,2); k = 1; for k = 1:10 Matrix(k,:) = rand(1,2); end % Remove the rest of the dummy rows Matrix(k+1:end,:) = []; 

Un altro sapore della stessa cosa che ha pubblicato Jacob.

 for counter = 1:10 Matrix(counter,:) = rand(1,2); end disp(Matrix); 

Una cosa “carina” di questo è che puoi indovinare una dimensione minima per aiutare la performance.

Questo potrebbe essere di interesse: http://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-88760