如何生成每个行和列的总和为零的矩阵

时间:2020-10-17 14:25:42

标签: matrix random generate

我需要生成一个矩阵,其中对角线为零,每一列和每一行的总和为零。

例如第一行0、4,-2,-1、1 =总和为0
或第一列0,-4、2、1、1 =总和为0

这适用于课程的每一列和每一行

0, 4, -2, -1, -1
-4, 0, 3, 3, -2
2, -3, 0, -1, 2 
1, -3, 1, 0, 1 
1, 2, -2, -1, 0

对角线始终填充零。 我正在尝试创建一个加权图,该图针对每个连接进行平衡。

编辑:我也忘记了矩阵通过对角线用*(-1)镜像

1 个答案:

答案 0 :(得分:2)

对于1×1、2×2和3×3矩阵,唯一起作用的矩阵如下(其中r是任意随机数):

[ 0 ]    [ 0 0 ]    [  0  r -r ]
         [ 0 0 ]    [ -r  0  r ]
                    [  r -r  0 ]

对于4×4矩阵,您可以从零矩阵开始,并通过重复执行不影响零和属性的操作来增加随机性。选择四边形角处的任意四个像元(只要它们不在主对角线上)。将此四边形的角视为2×2矩阵,可以添加以下矩阵的任意倍数,而不会影响行和列之和:

[  1  -1 ]
[ -1   1 ]

例如,可以通过四个步骤将零个5×5矩阵转换为以下内容:

[   0    W+X  -X    0   -W  ]
[   Y     0    0   -Y    0  ]
[ -Y+Z   -Z    0    Y    0  ]
[  -Z   -W+Z   0    0    W  ]
[   0    -X    X    0    0  ]

以下是实现此算法的一些Python代码:

def zero_sum_matrix(n):
    #
    # Generate a random matrix with a zero leading diagonal where
    # every row and every column has a sum value of zero.
    # (n = size of matrix)
    from random import randint
    #
    # Handle trivial cases
    assert n > 0
    if n == 1:
        return [[0]]
    if n == 2:
        return [[0,0],[0,0]]
    if n == 3:
        r = randint(-10,11)
        return [[0,r,-r], [-r,0,r], [r,-r,0]]
    #
    # Start with a zero matrix
    m = [[0]*n for i in range(n)]
    #
    # Add randomness without affecting the row and column sums
    for i in range(n*n):
        while True:
            # Choose two different rows
            r1, r2 = randint(0,n-1), randint(0,n-1)
            if r1 != r2:
                break
        while True:
            # Choose two columns, making sure we aren't affecting
            # any cells on the main diagonal
            c1, c2 = randint(0,n-1), randint(0,n-1)
            if c1 != c2 and c1 not in (r1, r2) and c2 not in (r1, r2):
                break
        # Add random perturbations at the intersections of these
        # rows and columns
        x = randint(-10,11)
        m[r1][c1] += x
        m[r1][c2] -= x
        m[r2][c1] -= x
        m[r2][c2] += x
    return m

def mprint(m):
    # Formatted matrix print routine
    for row in m:
        o = '  '.join([("%4d" % x) for x in row])
        print(o)

样本输出:

>>> mprint(zero_sum_matrix(8))
   0     5     2     3    17   -13   -16     2
  -5     0   -10   -11    -2    16    17    -5
  -4    -3     0    -6    -7     9    25   -14
  18     4     0     0   -22     1     6    -7
   1   -27     2    12     0    -8    16     4
 -24    28     0    -7    15     0   -36    24
  14   -11    13   -17    17   -12     0    -4
   0     4    -7    26   -18     7   -12     0
相关问题