2012-05-29 12 views
13

Próbuję generować symetryczne macierze w numpy. W szczególności te macierze mają mieć losowe pozycje, a w każdym wpisie zawartość może być losowa. Wzdłuż głównej przekątnej nie jesteśmy zainteresowani tym, co tam są, więc też je randomizowałem.Generowanie symetrycznych macierzy w Numpy

Podejście, które podjąłem, polega na wygenerowaniu macierzy zerowej i zerowej na wskaźnikach macierzy. Jednak biorąc pod uwagę biorąc pod uwagę pętli jest stosunkowo drogie w Pythona, zastanawiam się, czy mogę osiągnąć to samo bez używania Pythona dla pętli.

Czy jest kilka rzeczy wbudowanych w numpy, które pozwalają mi skuteczniej osiągnąć mój cel?

Tu jest mój bieżący kod:

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 

Odpowiedz

18

Można po prostu zrobić coś takiego:

import numpy as np 

N = 100 
b = np.random.random_integers(-2000,2000,size=(N,N)) 
b_symm = (b + b.T)/2 

którym można wybrać niezależnie od jej dystrybucji chcesz w module scipy np.random lub równoważnej.

Aktualizacja: Jeśli próbujesz budować struktury wykres podobny, na pewno sprawdzić pakiet NetworkX:

http://networkx.lanl.gov

który posiada szereg wbudowanych procedur do budowania wykresów:

http://networkx.lanl.gov/reference/generators.html

Również jeśli chcesz dodać kilka losowo umieszczonych zer, zawsze możesz wygenerować losowy zestaw indeksów i zamień wartości na zero.

+0

Dziękujemy! To jest skuteczne rozwiązanie. Czy jest jakiś sposób, aby uzyskać losowe zera w miejscach? Ta macierz ma reprezentować rodzaj macierzy sąsiedztwa dla wykresu, więc preferowane jest posiadanie macierzy z losowo rozmieszczonymi zerami. – Ryan

+4

@Ryan: Czy obchodzi cię, jaki rodzaj dystrybucji mają losowe wpisy? Jeśli dodasz 'b + b.T', otrzymasz nierównomierną dystrybucję skoncentrowaną wokół 0. – unutbu

+0

Weryfikuję niektóre właściwości macierzy.Jest to bardziej wysiłek, aby dostarczyć przekonujących dowodów na pewne własności matematyczne, więc rozkład tutaj nie jest tak ważny. W każdym razie dzięki! – Ryan

13

Lepiej Należy:

a = np.random.rand(N, N) 
m = np.tril(a) + np.tril(a, -1).T 

, ponieważ w tym przypadku wszystkie elementy osnowy są z sam rozkład (jednolite w tym przypadku).

+0

To bardzo elegancki sposób na utrzymanie tej samej dystrybucji! – Arash

0

Jeśli nie przeszkadza konieczności zer na przekątnej można użyć następującego fragmentu:

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 

pamiętać, że tylko trzeba wygenerować n * (n-1)/2 zmiennych losowych ze względu na symetria.

0

używam następującą funkcję aby symetryczny matrycy zarówno pionowo jak i poziomo:

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]) 

Niech sprawdzić, jak to działa:

>>> 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]]) 
Powiązane problemy