Существует несколько команд, которые предоставляют высокоуровневую информацию о ненулевых элементах разреженной матрицы:
Чтобы попробовать некоторые из них, загрузите предоставленную разреженную матрицу west0479
, один из набора Харуэлла-боинга.
load west0479
whos
Name Size Bytes Class Attributes west0479 479x479 34032 double sparse
Это матричные модели восьмиэтапный химический столбец дистилляции.
Попробуйте эти команды.
nnz(west0479)
ans = 1887
format short e west0479
west0479 = (25,1) 1.0000e+00 (31,1) -3.7648e-02 (87,1) -3.4424e-01 (26,2) 1.0000e+00 (31,2) -2.4523e-02 (88,2) -3.7371e-01 (27,3) 1.0000e+00 (31,3) -3.6613e-02 (89,3) -8.3694e-01 (28,4) 1.3000e+02 . . .
nonzeros(west0479)
ans = 1.0000e+00 -3.7648e-02 -3.4424e-01 1.0000e+00 -2.4523e-02 -3.7371e-01 1.0000e+00 -3.6613e-02 -8.3694e-01 1.3000e+02 . . .
Используйте Ctrl+C, чтобы остановить nonzeros
, перечисляющий в любое время.
Обратите внимание на то, что первоначально nnz
имеет то же значение как nzmax
по умолчанию. Таким образом, количество ненулевых элементов эквивалентно количеству мест хранения, выделенных для ненулей. However, MATLAB® динамически не выпускает память, если вы обнуляете дополнительные элементы массива. Изменение значения некоторых элементов матрицы, чтобы обнулить изменяет значение nnz
, но не тот из nzmax
.
Однако можно добавить столько ненулевых элементов к матрице сколько желаемый. Вы не ограничиваетесь исходным значением nzmax
.
Для любой матрицы, полной или разреженной, функция find
возвращает индексы и значения ненулевых элементов. Его синтаксис
[i,j,s] = find(S)
find
возвращает индексы строки ненулевых значений в векторном i
, индексов столбца в векторном j
и самих ненулевых значений в векторном s
. Пример ниже использует find
, чтобы определить местоположение индексов и значений ненулей в разреженной матрице. Функция sparse
использует find
вывод, вместе с размером матрицы, чтобы воссоздать матрицу.
[i,j,s] = find(S); [m,n] = size(S); S = sparse(i,j,s,m,n)
Поскольку разреженные матрицы сохранены в сжатом разреженном формате столбца, существуют различные затраты, сопоставленные с индексацией в разреженную матрицу, чем существует с индексацией в полную матрицу. Такие затраты незначительны, когда необходимо изменить только несколько элементов в разреженной матрице, таким образом, в тех случаях нормально использовать регулярную индексацию массива, чтобы повторно присвоить значения:
B = speye(4); [i,j,s] = find(B); [i,j,s]
ans = 1 1 1 2 2 1 3 3 1 4 4 1
B(3,1) = 42; [i,j,s] = find(B); [i,j,s]
ans = 1 1 1 3 1 42 2 2 1 3 3 1 4 4 1
42
в (3,1)
, MATLAB вставляет дополнительную строку в ненулевые значения векторные и нижние векторы, затем переключает все матричные значения после (3,1)
.Использование линейной индексации, чтобы получить доступ или присвоить элемент в большой разреженной матрице перестанет работать, если линейный индекс превысит 2^48-1
, который является текущей верхней границей для числа элементов, позволенного в матрице.
S = spalloc(2^30,2^30,2); S(end) = 1
Maximum variable size allowed by the program is exceeded.
Чтобы получить доступ к элементу, линейный индекс которого больше, чем intmax
, используйте индексацию массива:
S(2^30,2^30) = 1
S = (1073741824,1073741824) 1
В то время как стоимость индексации в разреженную матрицу, чтобы изменить единственный элемент незначительна, это составлено в контексте цикла и может стать довольно медленным для больших матриц. По этой причине, в случаях, где много элементов разреженной матрицы должны быть изменены, лучше векторизовать операцию вместо того, чтобы использовать цикл. Например, рассмотрите разреженную единичную матрицу:
n = 10000; A = 4*speye(n);
A
в цикле взятия медленнее, чем подобная векторизованная операция:tic; A(1:n-1,n) = -1; A(n,1:n-1) = -1; toc
Elapsed time is 0.003344 seconds.
tic; for k = 1:n-1, C(k,n) = -1; C(n,k) = -1; end, toc
Elapsed time is 0.448069 seconds.
A
во время каждого, проходят через цикл.Предварительное выделение памяти для разреженной матрицы и затем заполнение ее поэлементным способом так же вызывают существенное количество издержек в индексации в разреженный массив:
S1 = spalloc(1000,1000,100000); tic; for n = 1:100000 i = ceil(1000*rand(1,1)); j = ceil(1000*rand(1,1)); S1(i,j) = rand(1,1); end toc
Elapsed time is 2.577527 seconds.
Построение векторов индексов и значений избавляет от необходимости индексировать в разреженный массив, и таким образом значительно быстрее:
i = ceil(1000*rand(100000,1)); j = ceil(1000*rand(100000,1)); v = zeros(size(i)); for n = 1:100000 v(n) = rand(1,1); end tic; S2 = sparse(i,j,v,1000,1000); toc
Elapsed time is 0.017676 seconds.
По этой причине, лучше создавать разреженные матрицы целиком с помощью функции конструкции, как функции spdiags
или sparse
.
Например, предположите, что вы хотели разреженную форму координатного матричного C
:
Создайте матрицу с пятью столбцами непосредственно с функцией sparse
использование пар триплета для индексов строки, индексов столбца и значений:
i = [1 5 2 5 3 5 4 5 1 2 3 4 5]'; j = [1 1 2 2 3 3 4 4 5 5 5 5 5]'; s = [4 1 4 1 4 1 4 1 -1 -1 -1 -1 4]'; C = sparse(i,j,s)
C = (1,1) 4 (5,1) 1 (2,2) 4 (5,2) 1 (3,3) 4 (5,3) 1 (4,4) 4 (5,4) 1 (1,5) -1 (2,5) -1 (3,5) -1 (4,5) -1 (5,5) 4
Часто полезно использовать графический формат, чтобы просмотреть распределение ненулевых элементов в разреженной матрице. Функция spy
MATLAB производит шаблонное представление структуры разреженности, где каждая точка на графике представляет местоположение ненулевого элемента массива.
Например:
Загрузите предоставленную разреженную матрицу west0479
, один из набора Харуэлла-боинга.
load west0479
Просмотрите структуру разреженности.
spy(west0479)