简体   繁体   中英

Binary Asymmetric Matrix of Size 100 with Numpy

please take it easy, I'm new to Python and new to this site. I'm trying to create a random, 100 by 100 binary matrix using numpy. It's supposed to represent a co-citation network, so cycles aren't allowed (basically the matrix has to be asymmetrical across the diagonal, at least for nonzero values.

import numpy as np
n=100
array = np.random.randint(0,2,size=(n,n))

for i,j in range (0,n):
        if A[i][j] == 1:
                A[j,i] == 0


print(array)

A directed graph whose adjacency matrix is asymmetrical in the sense you described will not be in general acyclic. It will not have cycles of length 2, but it can have longer cycles eg 1 -> 2 -> 3 -> 1.

Any directed acyclic graph can be represented by a lower triangular adjacency matrix by rearranging its nodes in an appropriate order . Thus, to get a random directed acyclic graph you can create a random lower triangular matrix with 0 and 1 values. With numpy, it can be done as follows:

import numpy as np

frac = 0.5 #probability that an edge between two nodes will be created
N = 8 #number of nodes 

rng = np.random.default_rng()
A = (rng.random((N, N)) < frac).astype(int)
A = np.tril(A, k=-1)
print(A)

This gives:

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

You can use the networkx library to plot this graph:

import networkx as nx
import matplotlib.pyplot as plt

edges = list(zip(*np.nonzero(A)))
gr = nx.DiGraph(directed=True)
gr.add_nodes_from(range(N))
gr.add_edges_from(edges)
nx.draw(gr, node_size=500, with_labels=True, node_color='orange', arrowsize=20)
plt.show()

This produces the following picture:

在此处输入图像描述

If you want to obtain an adjacency matrix which represents a directed acyclic graph but it is not in the lower triangular form, you can reorder the nodes in some random order. This amounts to selecting a random permutation of node indices and conjugating the above adjacency matrix by the resulting permutation matrix:

#a random permutation of nodes
p = rng.permutation(range(N)) 
#the permutation matrix
P = np.zeros((N, N), dtype=int)
P[np.r_[:N], p] = 1
#conjugate the adjacency matrix A by P
new_A = P@A@P.T
print(new_A) 

This gives:

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

thanks for the response, I think the cycle longer cycles will work, for example if A cites B and B cites C, then A can cite C, then A can cite C as long as they are not both citing each other. The biggest problem was that obviously you can't have instances where the citations don't follow chronological order.

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