Search code examples
pythonnumpyadjacency-matrix

Create list of items repeated N times without repeating itself


I would like to repeat a list N times but without repeating an item itself. For example,

from itertools import *

items = [ _ for _ in range(3)]
# repeat each item twice
row = sorted(list(chain(*repeat(items, 2))))
row

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

BUT, I would like to create another list (col), which also has 6 items:

col = [1, 2, 0, 2, 0, 1]

The goal of these lists is to create an adjacency matrix with diagonal items = 0. (COO format is my final goal so random.shuffle does not meet my need)

row = [0,0,1,1,2,2]
col = [1,2,0,2,0,1]
value = [1,1,1,1,1,1]

import scipy
mtx = scipy.sparse.coo_matrix((value, (row, col)), shape=(3, 3))
mtx.todense()

matrix([[0, 1, 1],
        [1, 0, 1],
        [1, 1, 0]])

I need the information into a COO format. Any suggestions? Thanks in advance!


Solution

  • If you want to fill all the non-diagonal indices of a matrix of size (n, m), you could do:

    n, m = 3, 3
    value = [1,3,7,2,1,4]
    
    row, col = np.where(np.arange(m)[:,None] != np.arange(n))
    a = np.zeros((n, m), dtype=int)
    a[row, col] = value
    
    >>> a
    array([[0, 1, 3],
           [7, 0, 2],
           [1, 4, 0]])
    

    If you just want to make a dense array from a COO spec (with specified row, col indices and corresponding values):

    n, m = 3, 3
    # or, if you only have row, col: n, m = np.max(np.c_[row, col], 0) + 1
    
    row = [0,1,2,2]
    col = [1,2,0,1]
    value = [1,2,3,4]
    
    a = np.zeros((n, m), dtype=int)
    a[row, col] = value
    
    >>> a
    array([[0, 1, 0],
           [0, 0, 2],
           [3, 4, 0]])