Создание симметричных матриц в Numpy
Я пытаюсь создать симметричные матрицы в numpy. В частности, эти матрицы должны иметь записи случайных мест, и в каждой записи содержимое может быть случайным. Вдоль главной диагонали нас не интересует, что там есть, поэтому я тоже рандомизировал их.
Подход, который я принял, состоит в том, чтобы сначала сгенерировать nxn всю нулевую матрицу и просто петлю по индексам матриц. Однако, учитывая, что рассмотрение цикла является относительно дорогостоящим в python, мне интересно, могу ли я получить то же самое, не используя python для циклов.
Есть ли какие-то вещи, встроенные в numpy, которые позволяют мне более эффективно выполнять мою задачу?
Вот мой текущий код:
import numpy as np
import random
def empty(x, y):
return x*0
b = np.fromfunction(empty, (n, n), dtype = int)
for i in range(0, n):
for j in range(0, n):
if i == j:
b[i][j] = random.randrange(-2000, 2000)
else:
switch = random.random()
random.seed()
if switch > random.random():
a = random.randrange(-2000, 2000)
b[i][j] = a
b[j][i] = a
else:
b[i][j] = 0
b[j][i] = 0
Ответы
Ответ 1
Вы могли бы просто сделать что-то вроде:
import numpy as np
N = 100
b = np.random.random_integers(-2000,2000,size=(N,N))
b_symm = (b + b.T)/2
Где вы можете выбрать любой дистрибутив в np.random
или эквивалентном scipy-модуле.
Обновление:. Если вы пытаетесь построить графические структуры, обязательно проверьте пакет networkx:
http://networkx.lanl.gov
который имеет ряд встроенных подпрограмм для построения графиков:
http://networkx.lanl.gov/reference/generators.html
Также, если вы хотите добавить некоторое количество случайно помещенных нулей, вы всегда можете генерировать случайный набор индексов и заменять значения нулем.
Ответ 2
Мне лучше:
a = np.random.rand(N, N)
m = np.tril(a) + np.tril(a, -1).T
потому что в этом случае все элементы матрицы имеют одно и то же распределение (равномерное в этом случае).
Ответ 3
Если вы не против иметь нули по диагонали, вы можете использовать следующий фрагмент:
def random_symmetric_matrix(n):
_R = np.random.uniform(-1,1,n*(n-1)/2)
P = np.zeros((n,n))
P[np.triu_indices(n, 1)] = _R
P[np.tril_indices(n, -1)] = P.T[np.tril_indices(n, -1)]
return P
Обратите внимание, что вам нужно только генерировать n * (n-1)/2 случайные величины из-за симметрии.
Ответ 4
Я использую следующую функцию, чтобы сделать матрицу симметричной как по вертикали, так и по горизонтали:
def make_sym(a):
w, h = a.shape
a[w - w // 2 :, :] = np.flipud(a[:w // 2, :])
a[:, h - h // 2:] = np.fliplr(a[:, :h // 2])
Проверьте, как это работает:
>>> m = (np.random.rand(10, 10) * 10).astype(np.int)
>>> make_sym(m)
>>> m
array([[2, 7, 5, 7, 7, 7, 7, 5, 7, 2],
[6, 3, 9, 3, 6, 6, 3, 9, 3, 6],
[1, 4, 6, 7, 2, 2, 7, 6, 4, 1],
[9, 2, 7, 0, 8, 8, 0, 7, 2, 9],
[5, 5, 6, 1, 9, 9, 1, 6, 5, 5],
[5, 5, 6, 1, 9, 9, 1, 6, 5, 5],
[9, 2, 7, 0, 8, 8, 0, 7, 2, 9],
[1, 4, 6, 7, 2, 2, 7, 6, 4, 1],
[6, 3, 9, 3, 6, 6, 3, 9, 3, 6],
[2, 7, 5, 7, 7, 7, 7, 5, 7, 2]])
Ответ 5
Здесь есть элегантный ответ, который дает матрицу, в которой все записи следуют одному и тому же распределению. Однако этот ответ отбрасывает (n-1)*n/2
случайные числа без их использования.
Если вы хотите, чтобы все значения следовали одному и тому же распределению, генерировали их все сразу и генерировали только те, которые вы собираетесь использовать, то вы можете выполнить следующее:
>>> import numpy as np
>>> n = 5
>>> r = np.random.rand(n**2)
>>> sym = np.zeros((n,n))
>>> for i in range(n):
... t = i*(i+1)//2
... sym[i,0:i+1] = r[t:t+i+1]
... sym[0:i,i] = r[t:t+i]
...
>>> print(sym)
[[0.03019945 0.30679756 0.85722724 0.78498237 0.56146757]
[0.30679756 0.46276869 0.45104513 0.28677046 0.10779794]
[0.85722724 0.45104513 0.62193894 0.86898652 0.11543257]
[0.78498237 0.28677046 0.86898652 0.13929717 0.45309959]
[0.56146757 0.10779794 0.11543257 0.45309959 0.5671571 ]]
Идея здесь состоит в том, чтобы следовать номерам треangularьников, чтобы узнать, сколько элементов из случайного вектора уже использовалось ранее. Учитывая это значение t
, заполните текущую строку до диагонали включительно и текущий столбец до (но не включая) диагонали.