如何生成特定形式的 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]
我正在使用马尔可夫链解决问题,为此我需要生成一个 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]