Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

More elegant way to generate adjacency matrix from list of tuples

Suppose we start with a "friendship" graph represented by a list of tuples,

friendships = [(0, 1), (0, 2), (1, 2), (1, 3), (2,
3), (3, 4),(4, 5), (5, 6), (5, 7), (6, 8), (7, 8), (8, 9)]

where element 0 is a friend of 1 (and hence 1 is a friend of 0).

I want to construct the adjacency matrix from scratch in a way that will always work for this type of tuple representation.

I have the following (repulsive) Python code:

def make_matrix(num_rows,num_cols,entry_fn):
    return [[entry_fn(i,j)
             for j in range(num_cols)]
            for i in range(num_rows)]
def adjacency(connections):
    new=connections+[(x[1],x[0]) for x in connections]
    elements=list(set([x[0] for x in connections]+ [x[1] for x in connections]))
    def test(i,j):
        if (elements[i],elements[j]) in new:
            return 1
        else: return 0
    return make_matrix(len(elements),len(elements),test)

I know that it is inefficient and very ugly. Is there a smarter way to solve this problem? The output for the example list that I gave above should be

[[0, 1, 1, 0, 0, 0, 0, 0, 0, 0],
 [1, 0, 1, 1, 0, 0, 0, 0, 0, 0],
 [1, 1, 0, 1, 0, 0, 0, 0, 0, 0],
 [0, 1, 1, 0, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 1, 0, 1, 0, 0, 0, 0],
 [0, 0, 0, 0, 1, 0, 1, 1, 0, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 0, 1, 1, 0, 1],
 [0, 0, 0, 0, 0, 0, 0, 0, 1, 0]]

update: as per one of the answers, I have the following possible solution, although I don't know if it's any better

def adj(connections):
    ##step 1
    temp=(set(elem[0] for elem in connections).union(
        set(elem[1] for elem in connections)))
    n=max(temp)+1
    ans=[]
    ##step 2
    for i,_ in enumerate(temp):
        ans.append([])
        for j,_ in enumerate(temp):
            ans[i].append(0)
    ##step 3
    for pair in connections:
        ans[pair[0]][pair[1]]=1
        ans[pair[1]][pair[0]]=1
    return ans
like image 416
Andres Mejia Avatar asked Mar 04 '23 00:03

Andres Mejia


1 Answers

My algorithm would be something like this:

  1. Find the maximum vertex id. Call this n.
  2. Create an n+1 by n+1 array of zeros. Call this M.
  3. For each pair x, y in the input list, set M[x][y] = 1

To come up with this solution, I first thought of step 3. With the given input, this seems the most straightforward way to populate the adjacency matrix. However, it requires a 2D array of a fixed size. So the problem is how do I figure out n for step 2. From there it doesn't take much thought to figure out step 1 is what is needed.

The details are left as an exercise for the reader.

like image 111
Code-Apprentice Avatar answered Apr 28 '23 04:04

Code-Apprentice