2015-09-01 35 views
7

Desidero generare 10.000 matrici binarie casuali che hanno lo stesso numero di 1s per riga e per colonna come una matrice binaria data.Genera matrice binaria casuale

La matrice è ~ 500 x ~ 10.000. Ci sono circa 2.000.000 di 1s. Non ci sono zero righe o colonne.

Il mio metodo corrente converte la matrice binaria in una matrice di adiacenza bipartita ed esegue 1.000.000 interruttori di bordo casuali per garantire casualità. Questo richiede 13.000 secondi per 1 matrice. Sto codificando in python, usando una versione modificata della funzione double_edge_swap di networkx.

Esiste un modo più efficiente per generare tali matrici?

+2

che stavo cercando il nome di questo problema. È il problema principale della [tomografia discreta] (https://en.wikipedia.org/wiki/Discrete_tomography) "che si occupa della ricostruzione di un'immagine binaria dai suoi linesum orizzontali e verticali" e per il caso di 2 dimensioni (direzioni parallele non parallele a coppie), il problema è in P. Sarebbe interessante sapere che cosa ha bisogno di 10.000 ricostruzioni possibili scelte a caso. –

+0

È necessario specificare se è necessaria una distribuzione particolare, poiché metodi diversi potrebbero fornire distribuzioni leggermente diverse. – Veedrac

+0

Dipende se vuoi migliorare solo efficiente per generare matrici, la buona soluzione sarà chiamata c (funzione per generare matrice da python. – ElConrado

risposta

2

Penso che si possa prima costruire un caso particolare di una tale matrice, e quindi utilizzare numpy.shuffle per rimescolalo:

row_sum = 2 
col_sum = 1 
arr  = np.zeros((5, 10)) 
#generate a special case, with given row_sum and col_sum 
for i in range(row_sum): 
    arr.ravel()[i::arr.shape[1]+row_sum] = 1 
arr 

Out[84]: 
array([[ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.]]) 

np.random.shuffle(arr) 
#np.random.shuffle(arr.T) to shuffle the columns 
arr 
Out[89]: 
array([[ 0., 0., 0., 0., 1., 1., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 0., 0., 1., 1.], 
     [ 0., 0., 1., 1., 0., 0., 0., 0., 0., 0.], 
     [ 0., 0., 0., 0., 0., 0., 1., 1., 0., 0.], 
     [ 1., 1., 0., 0., 0., 0., 0., 0., 0., 0.]]) 

arr.sum(1) #row sums 
Out[90]: array([ 2., 2., 2., 2., 2.]) 

arr.sum(0) #col sums 
Out[91]: array([ 1., 1., 1., 1., 1., 1., 1., 1., 1., 1.]) 
+0

Vorrei anche suggerire di essere un po '_lazy_ se possibile.Possiamo generare una nuova matrice semplicemente definendo una lista di numeri di riga ('[2, 4, 1, 3, 0]' nell'esempio) e andando al 'np.array' a fondo scala se un compito dovrebbe essere fatto, o ad una sorta di _storia di cambiamenti_ (ma non sono sicuro che funzioni con 'numpy' con array di dimensioni dinamiche) – Vovanrock2002

+0

L'array' numpy' dinamico probabilmente non funzionerà, è stato un po 'discusso prima di http://stackoverflow.com/questions/ 6950456/how-to-create-a-dynamic-array. Suppongo che probabilmente si utilizzi 'Fortran' o' C' per l'array dinamico, ma aspetta, non è più una soluzione * pigra * :) –

+2

E se il le righe dicono [6, 5, 6, 4, 6, 7, 4, 5, 4, 4] e le colonne [3, 6, 5, 7, 2, 8, 3, 3, 4, 10] anziché costanti? Anche se tu avessi una soluzione semplicemente mischiando non sempre produrrebbe altri. –