pythonarraysmatrixrowsumcolumn-sum

Generate an m*n matrix with 1 and 0 (No identity)


I need to generate an m*n matrix with 1 and 0 where the sum of each row is 1 and each column is greater than or equal to 1. I'm trying this code but I don't know how to limit my condition on the columns, since sometimes I get zero columns and I need them all to have at least one 1. How could I limit the sum in the columns to be at least 1?

pt = []

sumr = 0
sumc = []

for i in range(n):
    
    quantity = random.choices([1])
    row = np.zeros(p, dtype=int)
    idx = np.random.choice(range(p), quantity, replace=False)
    row[idx] = 1
    pt.append(row)
    
for j in range(len(pt[0])):
    sumc.append(sum([row[j] for row in pt]))
    print(sumc)

Solution

  • I would just create a matrix with ones in random places, and then check if there are still zero columns once we near the end so we don't leave any empty:

    import numpy as np
    import random
    
    def make_mat(m, n):
        if (n > m):
            print("Invalid matrix dimensions.")
            return
        
        mat = np.zeros((m,n))
        zero_cols = [True]*n   # keep track of zero columns
        
        for row in range(m):
            # if there are N zero cols and N rows remaining, place 1 at randomly selected zero column place
            if len(np.where(zero_cols)[0]) == (m - row):
                idx = random.choice(np.where(zero_cols)[0])
            # otherwise, just select a random index
            else:
                idx = random.randint(0, n-1)
            mat[row][idx] = 1
            zero_cols[idx] = False
        
        return mat
    
    print(make_mat(10, 8))
    

    However, this can be simplified if we make use of an identity matrix:

    import numpy as np
    
    def make_mat_id(m, n):
        if (n > m):
            print("Invalid matrix dimensions.")
            return
        
        id_mat = np.identity(n)
        # add rows with one in random place
        mat = np.concatenate((id_mat, [np.where(np.arange(n) == np.random.choice(np.arange(n)), 1, 0) for _ in range(m-n)]))
        # make sure we no longer have the identity matrix
        np.random.shuffle(mat)
        return mat
    
    print(make_mat_id(10, 8)