Home > Enterprise >  Adjacency matrix using numpy
Adjacency matrix using numpy

Time:02-01

I need to generate the following adjacency matrices:

No of Nodes = 3

    A   B   C   AB  AC  BC
A   0   1   1   0   0   1
B   1   0   1   0   1   0
C   1   1   0   1   0   0
AB  0   0   1   0   0   0
AC  0   1   0   0   0   0
BC  1   0   0   0   0   0

To generate an adjacency matrix for 3 nodes, I can use the code available here, which is

out = np.block([
    [1 - np.eye(3), np.eye(3)       ],
    [    np.eye(3), np.zeros((3, 3))]
]).astype(int)

But it cannot use for different number of nodes, for example if we have 5 nodes then:

No of Nodes = 5

    A   B   C   D   E   AB  AC  AD  AE  BC  BD  BE  CD  CE  DE
A   0   1   1   1   1   0   0   0   0   1   1   1   1   1   1
B   1   0   1   1   1   0   1   1   1   0   0   0   1   1   1
C   1   1   0   1   1   1   0   1   1   0   1   1   0   0   1
D   1   1   1   0   1   1   1   0   1   1   0   1   0   1   0
E   1   1   1   1   0   1   1   1   0   1   1   0   1   0   0
AB  0   0   1   1   1   0   0   0   0   0   0   0   0   0   0
AC  0   1   0   1   1   0   0   0   0   0   0   0   0   0   0
AD  0   1   1   0   1   0   0   0   0   0   0   0   0   0   0
AE  0   1   1   1   0   0   0   0   0   0   0   0   0   0   0
BC  1   0   0   1   1   0   0   0   0   0   0   0   0   0   0
BD  1   0   1   0   1   0   0   0   0   0   0   0   0   0   0
BE  1   0   1   1   0   0   0   0   0   0   0   0   0   0   0
CD  1   1   0   0   1   0   0   0   0   0   0   0   0   0   0
CE  1   1   0   1   0   0   0   0   0   0   0   0   0   0   0
DE  1   1   1   0   0   0   0   0   0   0   0   0   0   0   0

Is there any simple and easiest way to implement these adjacency matrices?

CodePudding user response:

Inferring the logic of the output from your two examples, I think something like this might do what you want:

import numpy as np

def make_matrix(N, dtype=int):
  n_comb = N * (N - 1) // 2
  upper_left = 1 - np.eye(N, dtype=dtype)
  lower_right = np.zeros((n_comb, n_comb), dtype=dtype)
  cross = np.ones((N, N, N), dtype=dtype)
  i = np.arange(N)
  cross[i, :, i] = 0
  cross[:, i, i] = 0
  cross = cross[(np.triu_indices(N, k=1))]
  return np.block([[upper_left, cross.T],
                   [cross, lower_right]])
print(make_matrix(3))
[[0 1 1 0 0 1]
 [1 0 1 0 1 0]
 [1 1 0 1 0 0]
 [0 0 1 0 0 0]
 [0 1 0 0 0 0]
 [1 0 0 0 0 0]]
print(make_matrix(5))
[[0 1 1 1 1 0 0 0 0 1 1 1 1 1 1]
 [1 0 1 1 1 0 1 1 1 0 0 0 1 1 1]
 [1 1 0 1 1 1 0 1 1 0 1 1 0 0 1]
 [1 1 1 0 1 1 1 0 1 1 0 1 0 1 0]
 [1 1 1 1 0 1 1 1 0 1 1 0 1 0 0]
 [0 0 1 1 1 0 0 0 0 0 0 0 0 0 0]
 [0 1 0 1 1 0 0 0 0 0 0 0 0 0 0]
 [0 1 1 0 1 0 0 0 0 0 0 0 0 0 0]
 [0 1 1 1 0 0 0 0 0 0 0 0 0 0 0]
 [1 0 0 1 1 0 0 0 0 0 0 0 0 0 0]
 [1 0 1 0 1 0 0 0 0 0 0 0 0 0 0]
 [1 0 1 1 0 0 0 0 0 0 0 0 0 0 0]
 [1 1 0 0 1 0 0 0 0 0 0 0 0 0 0]
 [1 1 0 1 0 0 0 0 0 0 0 0 0 0 0]
 [1 1 1 0 0 0 0 0 0 0 0 0 0 0 0]]

The logic here is that each row of the upper-right matrix is like the flattened upper-triangle of a straightforward NxN matrix. For example:

# construct second row of upper-right matrix for 5x5 case:
x = np.ones((5, 5), dtype=int)
x[1] = 0
x[:, 1] = 0
print(x)
# [[1 0 1 1 1]
#  [0 0 0 0 0]
#  [1 0 1 1 1]
#  [1 0 1 1 1]
#  [1 0 1 1 1]]

print(x[np.triu_indices(5, k=1)])
# [0 1 1 1 0 0 0 1 1 1]
  • Related