I wish to generate 10,000 random binary matrices which have the same number of 1s per row and per column as a given binary matrix.
The matrix is ~500 x ~10,000. There are about 2,000,000 1s. There are no zero rows or columns.
My current method converts the binary matrix into a bipartite adjacency matrix, and performs 1,000,000 random edge switches to guarantee randomness. This takes 13,000 seconds for 1 matrix. I'm coding in python, using a modified version of networkx's double_edge_swap function.
Is there a more efficient way to generate such matrices?
shuffle(arr) #np. random. shuffle(arr. T) to shuffle the columns arr Out[89]: array([[ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.], [ 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.], [ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.], [ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]])
The rand function generates arrays of random numbers whose elements are uniformly distributed in the interval ( 0 , 1 ). Y = rand(n) returns an n -by- n matrix of random entries. An error message appears if n is not a scalar. Y = rand(m,n) or Y = rand([m n]) returns an m -by- n matrix of random entries.
You can use the randperm function to create a double array of random integer values that have no repeated values. For example, r4 = randperm(15,5);
I think you can first build a special case of such a matrix, and then use numpy.shuffle
to shuffle it:
row_sum = 2
col_sum = 1
arr = np.zeros((5, 10))
#generate a special case, with given row_sum and col_sum
for i in range(row_sum):
arr.ravel()[i::arr.shape[1]+row_sum] = 1
arr
Out[84]:
array([[ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.]])
np.random.shuffle(arr)
#np.random.shuffle(arr.T) to shuffle the columns
arr
Out[89]:
array([[ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.],
[ 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.],
[ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.],
[ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]])
arr.sum(1) #row sums
Out[90]: array([ 2., 2., 2., 2., 2.])
arr.sum(0) #col sums
Out[91]: array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With