Firstly, I'm going to assume that the adjacency list is undirected. In any case, it's not that far of a stretch to go to multiple neighbours. What you need to do first is detect the total number of non-zero elements per row from columns 2 to 5. Once you do this, for the rows of the adjacency matrix, you would copy the point number for as many times as there are non-zero elements per that row. The function repelem
is perfectly suitable to do that for you. The column indices would simply be the second to fifth columns removing all of the zero elements. How you can do this is first transpose the matrix resulting in indexing the second to fifth columns, then using a logical
indexing matrix to remove out the zero entries. Doing this will unroll your vector in a column-major fashion, which is why transposing is required before doing this operation. Once you do this, you can create row and column access indices so that these can be input into sparse
much like that post you linked.
Supposing that your matrix was stored in A
, you would do something like this. This also assumes that each of the weights connecting the nodes are 1:
% Find total number of non-zero elements per row, skipping first column
non_zero = sum(A(:,2:end) ~= 0, 2);
% Create row indices
rows = repelem(A(:,1), non_zero);
% Create column indices
cols = A(:,2:end).';
cols = cols(cols ~= 0);
% Create adjacency matrix
adj = sparse([rows; cols],[cols; rows], 1);
The above representation is in sparse
. If you want the full numeric version, cast the output using full
:
adj = full(adj);
If your graph is directed
If you have a directed graph instead of an undirected graph, the above call to sparse
duplicates edges so that you are creating links to and from each of the neighbours. If your graph is actually directed, then you simply have to only use the row and column indices once instead of twice as seen in the above code:
% Create adjacency matrix
adj = sparse(rows, cols , 1);
Test Case
Here's a small test case to show you that this works. Supposing my adjacency list looked like the following:
>> A = [1 0 2 3; 2 4 0 0; 3 0 0 4]
A =
1 0 2 3
2 4 0 0
3 0 0 4
The adjacency matrix is now:
>> full(adj)
ans =
0 1 1 0
1 0 0 1
1 0 0 1
0 1 1 0
Taking a look at the list above and how the matrix is populated, we can verify that this is correct.
Note about repelem
repelem
assumes you have MATLAB R2015a or later. If you don't have this, you can consult this answer by user Divakar on a custom implementation of repelem
here: Repeat copies of array elements: Run-length decoding in MATLAB