【问题标题】:How to generate a matrix with random entries and with constraints on row and columns?如何生成具有随机条目且对行和列有约束的矩阵?
【发布时间】:2023-04-01 21:04:01
【问题描述】:

如何生成一个矩阵,其条目是介于 0 和 1 之间的随机实数,并带有附加约束:每行的总和必须小于或等于 1,每列的总和必须小于或等于到一个。

例子:

matrix = [0.3, 0.4, 0.2;
          0.7, 0.0, 0.3; 
          0.0, 0.5, 0.1]

【问题讨论】:

  • Matlab? Python?朱莉娅?哪一个?
  • 我没有偏好。起初,我只输入了matrix,但后来我说我应该标记一种编程语言。我应该只保留一个吗?
  • 嗯,你可能需要一个算法,所以你可能会放弃它们。不管怎样,你现在有一个 python 和一个 matlab 解决方案,所以你现在应该坚持下去。
  • 感谢您的建议。

标签: python matlab matrix julia


【解决方案1】:

如果您想要一个均匀分布并满足这些约束的矩阵,您可能需要一个拒绝方法。在 Matlab 中是:

n = 3;
done = false;
while ~done
    matrix = rand(n);
    done = all(sum(matrix,1)<=1) & all(sum(matrix,2)<=1);
end

请注意,对于大型 n,这会很慢。

【讨论】:

  • 只需注意 OPs 标签:也许你应该提到这不是 C++ ;)
  • 另一种选择是按元素生成数据元素,生成matrix(i,j)=rand()*(1-sum(matrix(i,1:j-1)) 和列相同...
  • 糟糕。多种语言。已编辑。关于以这种方式生成:生成的分布在矩阵空间上不会是均匀的。再说一次,不确定 OP 是否想要制服
【解决方案2】:

如果您正在寻找 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)

【讨论】:

  • @LuisMendo - NumPy 是从 MATLAB 过渡的最简单方法:D Divakar 会告诉你!我也在写一个没有它的解决方案。
  • 我知道,我知道...总有一天... :-)
【解决方案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-1k2-1 出现索引问题。

请注意,正如@LuisMendo 所指出的,这将具有与拒绝方法不同的分布。但是,如果您的约束不考虑分布,这也可以(这将为您提供一次运行的矩阵)。

【讨论】:

  • 但是如果累计总和超过1,那(1-max(...))会给出负数吗?
  • @LuisMendo,如果我没记错的话,它不能。这就是为什么这一代如此复杂:你将每个元素限制在 0 和 1 之间——“行/列中先前人的总和”
  • 啊,我明白了。是的,我同意
猜你喜欢
  • 1970-01-01
  • 2023-04-08
  • 1970-01-01
  • 2013-07-25
  • 2014-04-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-05
相关资源
最近更新 更多