簡體   English   中英

如何生成矩陣,其中行的總和是列的總和的排列?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM