Симметричная матрица с NumPy - PullRequest
1 голос
/ 01 июня 2011
from random import *
N = 100
gamma = 0.7
connect = zeros((N,N))

for i in range(N):
    for j in range(i+1):
        if random() < gamma:
            connect[i,j] = 1
            connect[j,i] = 1
        else:
            connect[i,j] = 0
            connect[j,i] = 0

Я пытаюсь создать симметричную матрицу, заполненную нулями и единицами (с вероятностью 0,7). Вот двойная петля for, очень неэффективная ... Я сделаю что-нибудь с numpy, что, я считаю, может значительно ускорить процесс? Кто-нибудь знает, как поступить? Большое спасибо!

1 Ответ

2 голосов
/ 01 июня 2011

Вы можете использовать модуль случайных чисел для генерации случайных векторов и использовать эти векторы для заполнения матрицы.Например:

import numpy as np

N = 100
gamma = 0.7
connect = np.zeros((N,N),dtype=np.int32)

for i in range(0,N):
        dval = np.diag((np.random.random_sample(size=(N-i))<gamma).astype(np.int32),i)
        connect += dval
        if (i>0):
                connect += dval.T

делает это по диагонали, используя numpy.diag, но вы можете сделать это построчно, чтобы собрать верхнюю или нижнюю треугольную часть, а затем использовать сложение для формирования симметричной матрицы.У меня нет ощущения, что это может быть быстрее.


РЕДАКТИРОВАТЬ : На самом деле эта строчная версия примерно в 5 раз быстрее диагональной, что, я думаю, не стоитне удивительно, учитывая используемые им схемы доступа к памяти по сравнению с диагональной сборкой.

N = 100
gamma = 0.7
connect = np.zeros((N,N),dtype=np.int32)

for i in range(0,N):
    rval = (np.random.random_sample(size=(N-i))<gamma).astype(np.int32)
    connect[i,i:] = rval

connect += np.triu(connect,1).T

РЕДАКТИРОВАТЬ 2

Это еще проще иВ 4 раза быстрее, чем приведенная выше строчная версия.Здесь треугольная матрица формируется непосредственно из полной матрицы весов, а затем добавляется к ее транспонированию для получения симметричной матрицы:

N = 100
gamma = 0.7
a=np.triu((np.random.random_sample(size=(N,N))<gamma).astype(np.int32))
connect = a + np.triu(a,1).T

В системе Linux, на которой я ее тестировал, версия 1 занимает около 6,5 миллисекунд,версия 2 занимает около 1,5 миллисекунд, версия 3 - около 450 микросекунд.

...