简体   繁体   中英

MATLAB - sparse to dense matrix

I have a sparse matrix in a data file produced by a code(which is not MATLAB ). The data file consists of four columns. The first two column are the real and imaginary part of a matrix entry and the third and fourth columns are the corresponding row and column index respectively.

I convert this into a dense matrix in Matlab using the following script.

tic
dataA = load('sparse_LHS.dat');
toc
% Initialise matrix
tic
Nr = 15; Nz = 15; Neq = 5;
A (Nr*Nz*Neq,Nr*Nz*Neq) = 0;
toc

tic
lA = length(dataA)
rowA = dataA(:,3); colA = dataA(:,4);
toc

tic
for i = 1:lA
    A(rowA(i), colA(i)) = complex(dataA(i,1), dataA(i,2));
end
toc

This scipt is, however, very slow(the for loop is the culprit).

Elapsed time is 0.599023 seconds.

Elapsed time is 0.001978 seconds.

Elapsed time is 0.000406 seconds.

Elapsed time is 275.462138 seconds.

Is there any fast way of doing this in matlab ?

Here is what I tried so far:

parfor - This gives me

valid indices are restricted in parfor loops

I tired to recast the for loop as something like this:

A(rowA(:),colA(:)) = complex(dataA(:,1), dataA(:,2));

and I get an error

Subscripted assignment dimension mismatch.

The reason your last try doesn't work is that Matlab can't take a list of subscripts for both columns and rows, and match them to assign elements in order. Instead, it's making all the combinations of rows and columns from the list - this is how it looks:

dataA = magic(4)
dataA =
    16     2     3    13
     5    11    10     8
     9     7     6    12
     4    14    15     1

dataA([1,2],[1,4]) =

    16    13
     5     8

So we got 4 elements ( [1,1] , [1,4] , [2,1] , [2,4] ) instead of 2 ( [1,1] and [2,4] ).

In order to use subscripts in a list, you need to converts them to linear indexing , and one simple way to do this is using the function sub2ind .

Using this function you can write the following code to do it all at once:

% Initialise matrix
Nr = 15; Nz = 15; Neq = 5;
A(Nr*Nz*Neq,Nr*Nz*Neq) = 0;
% Place all complex values from dataA(:,1:2) in to A by the subscripts in dataA(:,3:4):
A(sub2ind(size(A),dataA(:,3),dataA(:,4))) = complex(dataA(:,1), dataA(:,2));

sub2ind is not such a quick function (but it will be much quicker than your loop), so if you have a lot of data, you might want to do the computation of the linear index by yourself:

rowA = dataA(:,3);
colA = dataA(:,4);
% compute the linear index:
ind = (colA-1)*size(A,1)+rowA;
 % Place all complex values from dataA(:,1:2) in to A by the the index 'ind':
A(ind) = complex(dataA(:,1), dataA(:,2));

PS:

If you are using Matlab R2015b or later:

A = zeros(Nr*Nz*Neq,Nr*Nz*Neq);

is quicker than:

A(Nr*Nz*Neq,Nr*Nz*Neq) = 0;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM