0

I have a quick graph theory question.

I have a 13 x 13 adjacency matrix in Matlab. I've already taken just the lower diagonal (this is an undirected graph) and subtracted off the identity matrix (so there aren't edges joining a node to itself). I then added a column on the left and a row on the top with the ID numbers of the four nodes. The resulting 14 x 14 adjacency matrix looks like this:

A = 

    0   1   1   1   1   2   2   2   3   3   3   4   4   4
    1   0   0   0   0   0   0   0   0   0   0   0   0   0
    1   0   0   0   0   0   0   0   0   0   0   0   0   0
    1   0   0   0   0   0   0   0   0   0   0   0   0   0
    1   0   0   0   0   0   0   0   0   0   0   0   0   0
    2   1   0   0   0   0   0   0   0   0   0   0   0   0
    2   0   0   0   0   0   0   0   0   0   0   0   0   0
    2   0   0   0   0   0   0   0   0   0   0   0   0   0
    3   0   0   1   0   0   0   0   0   0   0   0   0   0
    3   0   0   0   0   0   0   0   0   0   0   0   0   0
    3   0   1   0   0   0   0   0   0   0   0   0   0   0
    4   1   0   0   0   1   0   0   0   0   0   0   0   0
    4   0   0   0   1   0   0   0   0   0   0   0   0   0
    4   0   0   0   0   0   0   1   0   0   0   0   0   0

How can I create the coordinate array from this? I know the result should have 7 rows (one for each unique node pair).

Please let me know if you can help. Thanks in advance!

Amro
  • 123,847
  • 25
  • 243
  • 454
DanMcK
  • 37
  • 9
  • Can you please reformat that matrix `A`? I can't make heads or tails out of it – rayryeng Jul 16 '14 at 22:15
  • Haha sure, it looked good when I was typing it--trying to figure it out now. – DanMcK Jul 16 '14 at 22:16
  • Try indenting each line by 4 spaces. This will place it in a code block. – rayryeng Jul 16 '14 at 22:17
  • Give me a quick refresher on adjacency matrices. What does the number in entry `(i,j)` symbolize? My understanding is that this should only have 0s and 1s in it, and it symbolizes for node `i`, all the other nodes `j` that are connected to `i`. – rayryeng Jul 16 '14 at 22:18
  • Beat me to it, thanks again! The entry (i,j) symbolizes that there's an edge that exists between the ith node in the first column and the jth node in the first row. So the "1" at (6,2) indicates that there's an edge between Node 2 (see first column) and Node 1 (see first row). You're correct, though, the typical adjacency matrix for undirected graphs is the 13x13 lower diagonal of 1's and 0's--I added the first row and column with the ID numbers because those are what I ultimately need to list as the coordinate pairs. – DanMcK Jul 16 '14 at 22:20
  • So you only want the position of the ones? What would be the desired result for the first one: (2,1)? (5,1)? (6,2)? – Luis Mendo Jul 16 '14 at 22:20
  • Luis, to your question, it would be (2,1). Sorry for the confusion--the first row and column are the same list of ID numbers of the nodes. – DanMcK Jul 16 '14 at 22:24
  • I have an answer. I'll write one now. – rayryeng Jul 16 '14 at 22:27
  • @Amro - The first question he is asking. He doesn't want to visualize the graph. – rayryeng Jul 16 '14 at 22:38

2 Answers2

1

It appears that what you want is:

[ii, jj] = find(A(2:end,2:end)); %// row and col indices of ones in inner matrix
result = [ A(ii+1,1) A(1,jj+1).' ]; %'// node numbers corresponding to ii and jj

In your example, this gives

result =
     2     1
     4     1
     3     1
     3     1
     4     1
     4     2
     4     2

If you need unique rows:

result = unique(result, 'rows');

which gives

result =

     2     1
     3     1
     4     1
     4     2
Luis Mendo
  • 110,752
  • 13
  • 76
  • 147
1

We can use the node IDs that are provided at the first row and first column to help us create a node adjacency list. What we need to do is split up the variables so that we separate out the first row, called rowList and the first column colList. We will denote these the row and column lists respectively. We will also extract the adjacency matrix which is the rest of the matrix. The basic algorithm is the following:

  1. Find those rows and columns that are non-zero in the adjacency matrix.
  2. Use these rows and columns to index the corresponding rows and columns lists and spit out a co-ordinate array.

Without further ado:

rowList = A(2:end,1);
colList = A(1,2:end).';
AdjMatr = A(2:end,2:end);
[nonZeroRows, nonZeroCols] = find(AdjMatr);
nodeList = [rowList(nonZeroRows) colList(nonZeroCols)];

The output thus gives:

nodeList =

 2     1
 4     1
 3     1
 3     1
 4     1
 4     2
 4     2

This answer does not give unique rows of course, and produces duplicates. If you wish to have unique rows, consider doing:

nodeListUnique = unique(nodeList, 'rows');

The output is:

nodeListUnique =

 2     1
 3     1
 4     1
 4     2
rayryeng
  • 102,964
  • 22
  • 184
  • 193
  • Thanks @LuisMendo and rayryeng ! I really appreciate the help and the speedy responses. Many thanks! – DanMcK Jul 16 '14 at 22:36
  • @DanMcK - You're very welcome, and welcome to StackOverflow! To be fair, Luis Mendo beat me to the answer first by about 3 minutes. Thank you for accepting my answer anyhow :) – rayryeng Jul 16 '14 at 22:40
  • Also, for future users who may find this useful, in the graph theory context these may not be "duplicate" rows in the traditional sense, but rather multiple edges that join two nodes--for example, let's say the nodes are baseball teams, and the edges are players who have played for both teams. It's entirely possible that multiple players have played for the same pair of teams during their careers. "Duplicate" observations of the same edge are removed by only taking the lower diagonal of the adjacency matrix. Thanks again for your help, everyone. – DanMcK Jul 16 '14 at 22:44
  • @DanMcK - Cool :) That makes sense (and I knew that). As a bonus, if you want to count how many edges there are that connect between nodes `i` and `j`, you can do this: `counts = accumarray(nodeList, 1);`. Each number will tell you how many edges are connected to the first node indexed by the row, and the second node indexed by the column. As such, at `counts(4,1)` you'll see that this equals 2, and this tells you that there are 2 edges connected between nodes 4 and 1. – rayryeng Jul 16 '14 at 22:50
  • @DanMcK - As an extra extra extra bonus, `accumarray` doesn't give you a symmetric matrix. It only allocates enough space to fit as many nodes along the rows and columns as there are unique numbers in `rowList` and `colList` respectively. If you want this to look symmetric where `counts(a,b) <-> counts(b,a)`, consider doing this: `numNodes = max(nodeList(:)); counts = accumarray(nodeList, 1, [numNodes numNodes]); counts = counts + counts.';`. This should produce a symmetric matrix like I just talked about. – rayryeng Jul 16 '14 at 22:58