生成条件随机矩阵

3
我们如何生成一行和一列之和为1的矩阵。
import numpy as np
import random
class city:

    def  __init__(self):
        self.distance()

    def  distance(self):
        self.A = np.array([[ 0,  10,    20,  30],[10,   0,    25,  20],[20,  25,      0,  15],[30,  20,    15,   0]])
        self.B =(np.random.randint(0, self.A.shape[0], size=self.A.shape[0]) == np.arange(self.A.shape[0]).reshape(-1, 1)).astype(int)
        return self.B

1的总和是多少?请重新表述您的问题,因为不清楚您想要什么。 - filiprem
可能是重复的问题?https://stackoverflow.com/questions/33003153/how-to-generate-a-matrix-with-random-entries-and-with-constraints-on-row-and-col - Roope
只允许正数还是负数也可以? - Krishna
2个回答

2
据我所知,您想要一个随机双随机矩阵(DSM)的生成器。
如果您不需要对生成矩阵的分布进行任何其他限制,则选择的算法似乎仍然是Sinkhorn-Knopp。在这里,我们交替地重新缩放行和列,以使值符合和准则:
def gen_doubly_stochastic(size, max_error=None):
    if max_error is None:
        max_error = 1024 * np.finfo(float).eps

    m = np.matrix(np.random.random((size, size)))
    error = float('Inf')
    while error > max_error:
        m = np.divide(m, m.sum(axis=0), order='C')
        m = np.divide(m, m.sum(axis=1), order='K')

        error = max(
            np.max(np.abs(1 - m.sum(axis=0))),
            np.max(np.abs(1 - m.sum(axis=1)))
        )
    return m

根据原始论文,迭代快速收敛至近似解。此外,人们可以利用任何n x n DSM都可以表示为n个随机置换矩阵的线性组合(参见例如Is there a better way to randomly generate a Doubly Stochastic Matrix)的属性,其中线性系数之和为1。
def gen_doubly_stochastic_permute(size):
    m = np.zeros((size, size))
    I = np.identity(size)

    # n random coefficients
    coeffs = np.random.random(size)
    # enforce coefficient sum == 1
    coeffs /= np.sum(coeffs)

    # index array for identity permutation
    values = np.array(range(0, size))
    for c in coeffs:
        # generate new random permutation in place
        np.random.shuffle(values)
        # add scaled permutation matrix
        m += c * I[values, :]
    return m

0

欢迎来到stackoverflow,亲爱的Davood。
这是我的算法来解决这个问题:
假设我们想要矩阵的维度为4*4(就像图片中看到的那样,请确保观看)

  1. 首先,我们创建四个随机数,使它们的和等于1,放入最上面未填充的行中。
  2. 其次,我们尝试填充最左边的列,下面是上一行已填充的内容,使得该列的总和等于1。

到目前为止,我们已经填充了黄色部分(图片) 在下一次迭代中,橙色部分将被填充。等等。 这是代码(已经测试过了)

picture of algorithm

# RMG.py

import numpy as np
from random import random

class RMG:
    
    def __init__(self, dimension, sum_=1):
        self.dimension = dimension
        self.sum = sum_


    def generate_matrix(self):
        # create a matrix filled with zero s
        row_num = self.dimension
        col_num = self.dimension
        matrix = np.zeros((row_num, col_num))
        for i in range(self.dimension):
            
            matrix[i, i:self.dimension] = \
                self.create_numbers(1-sum(matrix[i, 0:i])
                , self.dimension-i)
            
            if i == self.dimension -1:
                break

            matrix[i+1:self.dimension, i] = \
                self.create_numbers(1-sum(matrix[0:i+1, i]), self.dimension - i - 1)
        return matrix

    @classmethod
    def create_numbers(cls, wanted_sum, count):
        
        result = [random() for i in range(count)]
        diff = wanted_sum - sum(result)
        to_be_added = diff/count
        result = \
            list(
                map(
                    lambda x: x + to_be_added,
                    result
                    )
                )
        # to fix the approximations of float type:
        result[-1] += wanted_sum - sum(result)
        return result

这是在RMGInteger.py中的派生类:

from RMG import RMG
from random import randint


class RMGInteger(RMG):
    
    def __init__(self, dimension, sum_=1):
        super(RMGInteger, self).__init__(dimension, sum)

    @classmethod
    def create_numbers(cls, wanted_sum, count):
        index = randint(0, count-1)
        result = [0 if i!= index else wanted_sum for i in range(count)]
        return result
    

这是要执行的文件:

# main.py

from RMG_Integer import RMGInteger

def main():

    handler = RMGInteger(4, 1)
    matrix = handler.generate_matrix()
    print(matrix)


if __name__ == '__main__':
    main()

# outputs something like this:
# [[1. 0. 0. 0.]
#  [0. 1. 0. 0.]
#  [0. 0. 0. 1.]
#  [0. 0. 1. 0.]]

更新:

根据评论中@Davood提到的内容,代码已经进行了修订。
我编写了一个派生类,它完成相同的工作,但生成的矩阵只包含零或一的值。


你好亲爱的Shahryar。很遗憾,这不是我想要的。我想要以下输出: - Davood
[[0, 1, 0, 0],[0, 0, 1, 0],[1, 0, 0, 0],[0, 0, 0, 1]] - Davood
最后,以数组的形式返回那些值为1的单元格地址。就像这样: - Davood
[(0,1),(1,2),(2,0),(3,3)] - Davood
1
@Davood:你确定吗?在那个例子中,第一行的总和是2 - dhke
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接