2015-09-01 17 views
7

Ich möchte 10.000 zufällige Binärmatrizen generieren, die die gleiche Anzahl von 1s pro Zeile und pro Spalte als eine gegebene binäre Matrix haben.Generate Random Binary Matrix

Die Matrix ist ~ 500 x ~ 10.000. Es gibt ungefähr 2.000.000 1s. Es gibt keine null Zeilen oder Spalten.

Meine aktuelle Methode konvertiert die binäre Matrix in eine zweigeteilte Adjazenzmatrix und führt 1.000.000 Random-Rand-Schalter aus, um die Zufälligkeit zu gewährleisten. Dies dauert 13.000 Sekunden für 1 Matrix. Ich kodiere in Python, benutze eine modifizierte Version der Funktion double_edge_swap von NetworkX.

Gibt es eine effizientere Möglichkeit, solche Matrizen zu generieren?

+2

ich für den Namen dieses Problems gesucht. Es ist das Hauptproblem der [diskreten Tomographie] (https://en.wikipedia.org/wiki/Discrete_tomography) "die sich mit der Rekonstruktion eines binären Bildes aus seinen horizontalen und vertikalen Linien" und für den Fall von 2 Dimensionen (paarweise nicht parallele Gitterrichtungen), das Problem liegt in P. Es wäre interessant zu wissen, was 10.000 zufällig gewählte mögliche Rekonstruktionen benötigt. –

+0

Sie sollten angeben, ob Sie eine bestimmte Verteilung benötigen, da verschiedene Methoden leicht unterschiedliche Verteilungen ergeben können. – Veedrac

+0

Es hängt davon ab, ob Sie nur effizient für das Generieren von Matrizen verbessern wollen. Die gute Lösung ist Aufruf c (Funktion für generate matrix from python. – ElConrado

Antwort

2

Ich glaube, Sie können zunächst einen Sonderfall einer solchen Matrix aufzubauen, und dann numpy.shuffle verwenden, um mische es:

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

Ich würde auch vorschlagen, ein bisschen _lazy_ wenn möglich zu sein. Wir können eine neue Matrix erzeugen, indem wir einfach definieren eine Liste von Reihennummern ('[2, 4, 1, 3, 0]' 'im Beispiel) und zum vollständigen' np.array' gehen, wenn eine Zuweisung gemacht werden soll, oder zu einer Art _history of changes_ (aber ich bin mir nicht sicher, ob es für 'numpy' okay ist mit dynamischen Arrays zu arbeiten.) – Vovanrock2002

+0

Dynamisches' numpy' Array wird wahrscheinlich nicht funktionieren, es wurde vor http://stackoverflow.com/questions/ diskutiert 6950456/how-to-create-a-dynamic-array.Ich denke, man geht wahrscheinlich für 'Fortran' oder' C' für dynamisches Array.aber warten Sie, das ist nicht mehr eine * faul * Lösung, :) –

+2

Was ist, wenn Zeilen sind sagen [6, 5, 6, 4, 6, 7, 4, 5, 4, 4] und die Spalten [3, 6, 5, 7, 2, 8, 3, 3, 4, 10] statt Konstanten? Selbst wenn Sie nur eine Lösung hätten, würde das einfache Mischen nicht immer andere hervorbringen. –