如何生成特定形式的 NxN 矩阵

How to Generate an NxN Matrix of a Particular Form

我正在使用马尔可夫链解决问题,为此我需要生成一个 NxN 转换矩阵。

矩阵的第一行、第一列和左下对角线应包含零,并且随着行的增加,矩阵的大小也会增加。对于 NxN 矩阵,第一行中的分数是 1/n,下一行是 1/n-1 等等,直到分数为 1 的第 n-1 行。我在下面包含了 10x10 和 5x5 的示例.

p10 = ([0, 1/10, 1/10, 1/10, 1/10, 1/10, 1/10, 1/10, 1/10, 1/10, 1/10],
         [0, 0, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9],
         [0, 0, 0, 1/8, 1/8, 1/8, 1/8, 1/8, 1/8, 1/8, 1/8],
         [0, 0, 0, 0, 1/7, 1/7, 1/7, 1/7, 1/7, 1/7, 1/7],
         [0, 0, 0, 0, 0, 1/6, 1/6, 1/6, 1/6, 1/6, 1/6],
         [0, 0, 0, 0, 0, 0, 1/5, 1/5, 1/5, 1/5, 1/5],
         [0, 0, 0, 0, 0, 0, 0, 1/4, 1/4, 1/4, 1/4],
         [0, 0, 0, 0, 0, 0, 0, 0, 1/3, 1/3, 1/3],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 1/2, 1/2],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
         [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],) 


p5 = ([0,1/5,1/5,1/5,1/5,1/5],
      [0,0,1/4,1/4,1/4,1/4],
      [0,0,0,1/3,1/3,1/3],
      [0,0,0,0,1/2,1/2],
      [0,0,0,0,0,1],
      [0,0,0,0,0,0],)

我刚开始使用 Python 中的矩阵,所以我想知道 easiest/most 为用户指定的给定维度生成这些矩阵的有效方法是什么(编辑:我已经导入了 numpy 模块,所以任何利用它的解决方案都将不胜感激。

对于矩阵,我建议使用 numpy。为了得到你想要的,你可以使用:

import numpy as np

def transition_matrix(n):
    arr = np.zeros((n+1, n+1))
    division = 1. / np.linspace(1, n, n)[::-1] # this changes it from 1 / [1,2,3, ... , n-1, n] to 1 / [n, n-1, n-2, ..., 2 ,1] which is the order we want to add the division values

    for i in range(n):
        arr[i, i+1:] = division[i] # fill the array with the division values at row i starting at column i + 1 until the end
    return arr

产生:

[[0.         0.25       0.25       0.25       0.25      ]
 [0.         0.         0.33333333 0.33333333 0.33333333]
 [0.         0.         0.         0.5        0.5       ]
 [0.         0.         0.         0.         1.        ]
 [0.         0.         0.         0.         0.        ]]

n = 4

然而,对于非常大的矩阵,这会变慢,但如果你保持在 1000x1000 以下,你应该没问题。

我尝试了没有循环的答案,对于小于 +/- 80x80 的矩阵,这个答案更快,之后循环实际上更快,因为我相信它每行只计算一个除法。所以使用适合您问题的那个

这里有一个不用循环的 NumPy 方法:

import numpy as np

def make_matrix(n):
    m = np.tri(n + 1, k=-1).T
    m[:-1] /= np.arange(n, 0, -1).reshape(-1, 1)
    return m

# Test
with np.printoptions(precision=3): # For nicer printing
    print(make_matrix(5))
    # [[0.    0.2   0.2   0.2   0.2   0.2  ]
    #  [0.    0.    0.25  0.25  0.25  0.25 ]
    #  [0.    0.    0.    0.333 0.333 0.333]
    #  [0.    0.    0.    0.    0.5   0.5  ]
    #  [0.    0.    0.    0.    0.    1.   ]
    #  [0.    0.    0.    0.    0.    0.   ]]
    print(make_matrix(10))
    # [[0.    0.1   0.1   0.1   0.1   0.1   0.1   0.1   0.1   0.1   0.1  ]
    #  [0.    0.    0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111 0.111]
    #  [0.    0.    0.    0.125 0.125 0.125 0.125 0.125 0.125 0.125 0.125]
    #  [0.    0.    0.    0.    0.143 0.143 0.143 0.143 0.143 0.143 0.143]
    #  [0.    0.    0.    0.    0.    0.167 0.167 0.167 0.167 0.167 0.167]
    #  [0.    0.    0.    0.    0.    0.    0.2   0.2   0.2   0.2   0.2  ]
    #  [0.    0.    0.    0.    0.    0.    0.    0.25  0.25  0.25  0.25 ]
    #  [0.    0.    0.    0.    0.    0.    0.    0.    0.333 0.333 0.333]
    #  [0.    0.    0.    0.    0.    0.    0.    0.    0.    0.5   0.5  ]
    #  [0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    1.   ]
    #  [0.    0.    0.    0.    0.    0.    0.    0.    0.    0.    0.   ]]

如果你不想使用 NumPy,你可以像这样简单地制作一个列表列表:

def make_matrix(n):
    return [[1 / (n - i) if j > i else 0 for j in range(n + 1)] for i in range(n + 1)]

print(*make_matrix(5), sep='\n')
# [0, 0.2, 0.2, 0.2, 0.2, 0.2]
# [0, 0, 0.25, 0.25, 0.25, 0.25]
# [0, 0, 0, 0.3333333333333333, 0.3333333333333333, 0.3333333333333333]
# [0, 0, 0, 0, 0.5, 0.5]
# [0, 0, 0, 0, 0, 1.0]
# [0, 0, 0, 0, 0, 0]