对于给定的整数N,我想生成一个NxN阶矩阵,其中行的总和是列总和的一些排列。
例如:
3
0 2 3
4 0 1
1 3 0
行总和为5,5,4 总和是5,5,4
两者都是彼此的排列。如何为任何给定的N生成这样的矩阵?
PS: 我知道对角矩阵,对称矩阵在这里可以工作,像这样的矩阵
3
1 0 0
0 0 1
0 1 0
但我想制作一些随机矩阵。
答案 0 :(得分:2)
您可以从满足要求但没有排列方面的矩阵开始:因此特定行的总和应等于具有相同索引的列的总和。例如,零矩阵就可以了。
然后随机选择一组列。迭代这些列,并从该列表中选择该行作为 previous 列的索引(因此该行将从列表中最后一列的索引开始)。这会产生一个元素循环,这样如果用相等的常数增加所有元素的值,则保持sum-requirement。此常量可以是1或任何其他整数(尽管0不是非常有用)。
根据需要多次重复此操作,直到您觉得它已经足够混乱为止。例如,您可以决定重复这两次。
最后,您可以对行进行随机播放,以增加随机性:行总和现在与列总和的排列相对应。
这是Python代码:
import random
def increment(a):
i = 1 # the increment that will be applied. Could also be random
# choose a random list of distinct columns:
perm = random.sample(range(len(a)), random.randint(1,len(a)-1))
row = perm[-1]
# cycle through them and increment the values to keep the balance
for col in perm:
a[row][col] += i
row = col
return a
### main ###
n = 7
# create square matrix with only zeroes
a = [[0 for i in range(n)] for j in range(n)]
# repeat the basic mutation that keeps the sum property in tact:
for i in range(n*n): # as many times as you wish
increment(a)
# shuffle the rows
random.shuffle(a)
一次运行产生了这个矩阵:
[[6, 5, 7, 7, 5, 2, 1],
[6, 1, 7, 6, 2, 5, 1],
[6, 1, 0, 4, 3, 5, 4],
[6, 2, 5, 1, 6, 2, 4],
[1, 3, 4, 2, 8, 3, 6],
[1, 7, 0, 3, 3, 10, 1],
[1, 4, 2, 3, 1, 6, 1]]
我在行shuffle之前使用了这个检查来确保sum属性是完整的:
# test that indeed the sums are OK
def test(a):
for i in range(len(a)):
if sum(a[i]) != sum([a[j][i] for j in range(len(a))]):
print('fail at ', i)
答案 1 :(得分:1)
获得相当随机的方法的一种方法如下:
首先创建一个随机对称矩阵。这样的矩阵的行和将等于其列和。
请注意,如果交换任何两行,则其行总和将被置换,但其列总和将保持不变。类似地,如果交换任何两列,则其列的总和被置换,但其行总和保持不变。因此 - 如果你随机交换随机行并多次交换随机列,行和列的总和将是彼此的排列,但原始的对称性将被隐藏。
Python概念证明:
import random
def randSwapRows(matrix):
i,j = random.sample(list(range(len(matrix))),2)
matrix[i], matrix[j] = matrix[j], matrix[i]
def randSwapColumns(matrix):
i,j = random.sample(list(range(len(matrix))),2)
for row in matrix:
row[i],row[j] = row[j],row[i]
def randSpecialMatrix(n):
matrix = [[0]*n for i in range(n)]
for i in range(n):
for j in range(i,n):
matrix[i][j] = random.randint(0,n-1)
matrix[j][i] = matrix[i][j]
#now swap a lot of random rows and columns:
for i in range(n**2):
randSwapRows(matrix)
randSwapColumns(matrix)
return matrix
#test:
matrix = randSpecialMatrix(5)
for row in matrix: print(row)
print('-'*15)
print('row sums: ' + ', '.join(str(sum(row)) for row in matrix))
print('col sums: ' + ', '.join(str(sum(column)) for column in zip(*matrix)))
典型输出:
[3, 2, 2, 0, 3]
[3, 1, 0, 2, 3]
[4, 1, 3, 3, 4]
[2, 0, 3, 3, 4]
[0, 0, 2, 1, 1]
---------------
row sums: 10, 9, 15, 12, 4
col sums: 12, 4, 10, 9, 15
请注意,即使这是随机的,但在从0-4中满足所需属性的条目的所有5x5矩阵的集合中统一选择的意义上,它并不是真正随机的。如果没有随机生成矩阵的命中和未命中方法,直到得到这样的矩阵,我看不出任何方法来获得均匀分布。