我们如何生成具有总和为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
答案 0 :(得分:2)
据我所知,您需要一个生成随机doubly stochastic matrices(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
答案 1 :(得分:0)
欢迎来到stackoverflow亲爱的达沃德。
这是我解决此问题的算法:
假设我们希望矩阵的尺寸为4 * 4(就像图片中看到的一样,请务必注意)
到目前为止,我们已经填充了黄色部分(图片) 在下一次迭代中,将填充橙色部分。等等。 这是代码(已经过测试)
# 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提到的内容,对代码进行了修改。
我写了一个派生类,它执行相同的工作,但生成的矩阵只有零个或一个值。