如果我理解这个任务,这样的事情可能会奏效:
import numpy as np
from collections import defaultdict, deque
def gen_mat(n, m, k):
"""
n: rows,
m: cols,
k: ones,
"""
assert k % n == 0 and k % m == 0
mat = np.zeros((n, m), dtype=int)
ns = np.repeat(np.arange(n), k // n)
ms = np.repeat(np.arange(m), k // m)
# uniform shuffle
np.random.shuffle(ms)
ms_deque = deque(ms)
assigned = defaultdict(set)
for n_i in ns:
while True:
m_i = ms_deque.popleft()
if m_i in assigned[n_i]:
ms_deque.append(m_i)
continue
mat[n_i, m_i] = 1
assigned[n_i].add(m_i)
break
return mat
我们首先观察到可以用 k 个 s.t 填充一个 n x m 矩阵。等比只有 k 可以被 n 和 m 整除。
假设这个条件成立,每个行索引将出现 k/n 次,每个列索引将出现 m/k 次。我们打乱列索引以确保分配是随机的,并将随机列索引存储在双端队列中以提高效率。
对于每一行,我们存储一组列 s.t. mat[row, column] = 1(最初为空)。
我们现在可以遍历每一行 k/n 次,选择下一列 s.t.来自双端队列的 mat[row, column] = 0 并将 mat[row, column] 设置为 1。
没有损失,假设n