Матрица неизвестной длины в MATLAB?

Я пытаюсь создать нулевую матрицу переменной длины с двумя столбцами, в которые я могу выводить результаты в цикл while (с намерением использовать его для хранения данных из шага метод Эйлера с уточнением времени действия). Длина будет определяться количеством итераций цикла.

Мне интересно, есть ли способ сделать это, пока я запускаю цикл, или мне нужно настроить его для начала, и как это сделать.

4 ответов


если количество столбцов фиксировано, вы всегда можете добавить строки в свою матрицу (внутри цикла)

например

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

конечно, если вы знаете количество итераций до цикла while, более эффективно предварительно выделить матрицу


другой подход, который имеет производительность в виду, все еще пытаясь быть эффективным с пространством, заключается в предварительном распределении памяти большими партиями, добавляя больше партии по мере необходимости. Это хорошо подходит, если вам нужно добавить большое количество товаров, не зная, сколько заранее.

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

редактировать: в качестве сравнения, рассмотрим следующие случаи:

  1. тот же код, что и выше, для 50000 повторения.
  2. предварительное распределение всей матрицы заранее:list = zeros(50000,2); list(k,:) = [x y];
  3. динамическое добавление векторов в матрицу:list = []; list(k,:) = [x y];

на моей машине, результаты были:

1) затраченное время 0.080214 секунд.
2) истекшее время 0,065513 секунды.
3) истекшее время 24.433315 секунд.


обновление:

после обсуждения в комментариях, я повторите некоторые тесты, используя последнюю версию r2014b. Вывод состоит в том, что последние версии MATLAB значительно улучшили производительность автоматического роста массива!

однако есть уловка; массив должен расти по последнему измерению (столбцы в случае 2D-матриц). Вот почему добавление строк, как первоначально предполагалось, все еще слишком медленно без предварительного распределения. Именно здесь предлагаемое выше решение может действительно помочь (путем расширения массива в партии.)

см. здесь полный набор тестов:https://gist.github.com/amroamroamro/0f104986796f2e0aa618


MATLAB использует динамическую типизацию с автоматическим управлением памятью. Это означает, что вам не нужно объявлять матрицу фиксированного размера перед ее использованием - вы можете изменить ее по мере продвижения, и MATLAB динамически выделит вам память.

но это путь эффективнее сначала выделить память для матрицы и затем использовать его. Но если ваши программы нуждаются в такой гибкости, идите на это.

Я думаю, что вам нужно продолжайте добавлять строки в матрицу. Следующий код должен работать.

Matrix = [];

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

disp(Matrix);

здесь мы динамически перераспределяем пространство, необходимое для Matrix каждый раз, когда вы добавляете новую строку. Если вы заранее знаете, скажем, верхнюю границу количества строк, которые у вас будут, вы можете объявить Matrix = zeros(20,2) а затем вставьте каждую строку в матрицу постепенно.

% 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,:) = [];

еще один аромат того же, что и Джейкоб опубликовал.

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

одна "хорошая" вещь об этом - вы можете угадать минимальный размер, чтобы помочь производительности.

Это также может представлять интерес: http://www.mathworks.com/help/matlab/math/resizing-and-reshaping-matrices.html#f1-88760