2012-05-29 47 views
13

Estoy tratando de generar matrices simétricas en numpy. Específicamente, estas matrices deben tener entradas de lugares aleatorios, y en cada entrada los contenidos pueden ser aleatorios. A lo largo de la diagonal principal, no nos preocupamos por las entidades que están ahí, así que también las aleatoricé.Generando Matrices Simétricas en Numpy

El enfoque que he tomado es generar primero una matriz nxn all zero y simplemente recorrer los índices de las matrices. Sin embargo, teniendo en cuenta que el bucle es relativamente caro en Python, me pregunto si puedo lograr lo mismo sin usar bucles de pitón.

¿Hay algunas cosas integradas en numpy que me permitan alcanzar mi objetivo de manera más eficiente?

Aquí está mi código actual:

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 

Respuesta

18

Se podía hacer algo como:

import numpy as np 

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

Donde se puede elegir cualquier distribución que desea en el módulo de scipy np.random o equivalente.

Actualización: Si usted está tratando de construir estructuras gráfico-como, sin duda la salida el paquete NetworkX:

http://networkx.lanl.gov

que tiene una serie de rutinas incorporadas para construir gráficos:

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

Además, si desea añadir algún número de ceros colocados al azar, siempre se puede generar un conjunto aleatorio de índices y reemplaza los valores con cero.

+0

Gracias! Esa es una solución eficiente. Sin embargo, ¿hay alguna manera de que pueda colocar ceros en lugares al azar? Se supone que esta matriz representa un tipo de matriz de adyacencia para un gráfico, por lo que es preferible tener una matriz con cero distribuidos aleatoriamente. – Ryan

+4

@Ryan: ¿Te importa qué tipo de distribución tienen las entradas aleatorias? Si agrega 'b + b.T', obtendrá una distribución no uniforme concentrada alrededor de 0. – unutbu

+0

Estoy verificando algunas propiedades de las matrices.Es más un esfuerzo para proporcionar evidencia convincente de algunas propiedades matemáticas, por lo que la distribución aquí no es tan importante. ¡Gracias! – Ryan

13

que será mejor do:

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

porque en este caso todos los elementos de una matriz son de misma distribución (uniforme en este caso).

+0

¡Es una forma muy elegante de mantener la misma distribución! – Arash

0

Si no te importa tener ceros en la diagonal se podría utilizar el siguiente fragmento:

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 

Tenga en cuenta que sólo es necesario para generar n (n-1)/2 variables aleatorias debido a la * simetría.

0

estoy usando la siguiente función para hacer una matriz simétrica tanto vertical como horizontalmente:

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

Deje comprobar como funciona:

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