[英]How to generate matrix where sum of rows is a permutation of sum of columns?
對於給定的整數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
但我想做一點隨機矩陣。
您可以從滿足要求但沒有排列方面的矩陣開始:因此特定行的總和應等於具有相同索引的列的總和。 例如,零矩陣就可以了。
然后隨機選擇一組列。 迭代這些列,並從該列表中選擇該行作為上一列的索引(因此該行將以列表中最后一列的索引開始)。 這會產生一個元素循環,這樣如果用相等的常數增加所有元素的值,則保持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)
獲得相當隨機的方法的一種方法如下:
首先創建一個隨機對稱矩陣。 這樣的矩陣的行和將等於其列和。
請注意,如果交換任何兩行,則其行總和將被置換,但其列總和將保持不變。 類似地,如果交換任何兩列,則其列的總和被置換,但其行總和保持不變。 因此 - 如果您隨機交換隨機行並多次交換隨機列,則行和列的總和將是彼此的排列,但原始對稱性將被隱藏。
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矩陣的集合中統一選擇的意義上,它並不是真正隨機的。 如果沒有隨機生成矩陣的命中和未命中方法,直到得到這樣的矩陣,我看不出任何方法來獲得均勻分布。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.