如何生成矩阵,其条目是0到1之间的随机实数,包括附加约束:每行的总和必须小于或等于1,每列的总和必须小于或等于一个。
示例:
matrix = [0.3, 0.4, 0.2;
0.7, 0.0, 0.3;
0.0, 0.5, 0.1]
答案 0 :(得分:7)
如果您希望矩阵均匀分布并满足这些约束,则可能需要拒绝方法。在Matlab中它将是:
n = 3;
done = false;
while ~done
matrix = rand(n);
done = all(sum(matrix,1)<=1) & all(sum(matrix,2)<=1);
end
请注意,对于较大的n
,这会很慢。
答案 1 :(得分:5)
如果您正在寻找Python方式,这只是Luis Mendo的拒绝方法的转录。为简单起见,我将使用NumPy:
import numpy as np
n = 3
done = False
while not done:
matrix = np.random.rand(n,n)
done = np.all(np.logical_and(matrix.sum(axis=0) <= 1, matrix.sum(axis=1) <= 1))
如果您没有NumPy,那么您可以生成2D矩阵作为列表列表:
import random
n = 3
done = False
while not done:
# Create matrix as a list of lists
matrix = [[random.random() for _ in range(n)] for _ in range(n)]
# Compute the row sums and check for each to be <= 1
row_sums = [sum(matrix[i]) <= 1 for i in range(n)]
# Compute the column sums and check for each to be <= 1
col_sums = [sum([matrix[j][i] for j in range(n)]) <= 1 for i in range(n)]
# Only quit of all row and column sums are less than 1
done = all(row_sums) and all(col_sums)
答案 2 :(得分:3)
拒绝方法肯定会给你一个统一的解决方案,但生成一个好的矩阵可能需要很长时间,特别是如果你的矩阵很大。因此,另一种但更繁琐的方法是生成每个元素,使得每个方向的总和只能为1。为此,您始终在0 和余数之间生成一个新元素,直到1 :
n = 3
matrix = zeros(n+1); %dummy line in first row/column
for k1=2:n+1
for k2=2:n+1
matrix(k1,k2)=rand()*(1-max(sum(matrix(k1,1:k2-1)),sum(matrix(1:k1-1,k2))));
end
end
matrix = matrix(2:end,2:end)
这有点棘手,因为对于每个元素,你检查行和和列之和直到该点,并使用两者中较大的一个来生成一个新元素(为了在两个方向上保持低于1的总和) )。出于实际原因,我在开头用零行和列填充矩阵,以避免使用k1-1
和k2-1
编制索引问题。
请注意,正如@LuisMendo指出的那样,这将作为拒绝方法具有不同的分布。但是如果你的约束不考虑分布,那么这也可以做到(这将为你提供一次运行的矩阵)。