2017-02-01 8 views
1

Ich versuche, die 'Macht' einer Python-Liste/Matrix mit numpy zu bekommen. Meine einzige aktuelle Arbeitslösung ist eine iterative Funktion np.dot():Numpy 2D Array - Power Of - Keine Antwort?

def matr_power(matrix, power): 
    matrix_a = list(matrix) 
    matrix_b = list(matrix) 
    for i in range(0, power-1): 
     matrix_a = np.dot(matrix_a, matrix_b) 
    return matrix_a 

Diese arbeitet für meine Bedürfnisse, aber ich bin mir bewusst, es ist wahrscheinlich nicht die effizienteste Methode.

Ich habe versucht, meine Liste in ein numpy Array zu konvertieren, Power-Operationen darauf auszuführen, und dann zurück zu einer Liste, damit es in der Form verwendbar ist, die ich brauche. Die Konvertierungen scheinen zu passieren, aber die Leistungsberechnung nicht.

while (foo != bar): 
    matr_x = np.asarray(matr_a) 
    matr_y = matr_x ** n 
    matr_out = matr_y.tolist() 
    n += 1 
    # Other code here to output certain results 

Das Problem ist, die Matrix in ein Array umgewandelt wird, wie erwartet, aber, wenn die Stromoperation durchgeführt (**) matr_y endet als die gleichen wie matr_x als ob keine Berechnung jemals durchgeführt wurde. Ich habe versucht, np.power(matr_y, n) und einige andere Lösungen in verwandten Fragen zu Stack Overflow gefunden.

Ich habe versucht, die numpy Dokumentation zu verwenden, aber (entweder ich missverstehe es, oder) es bestätigt nur, dass dies wie erwartet funktionieren sollte.

Beim Überprüfen der Debugging-Konsole in PyCharm scheint alles in Ordnung zu sein (alle Matrizen/Listen/Arrays werden wie erwartet konvertiert), außer dass die Berechnung matr_x ** i nie berechnet wird (oder sonst nie ingespeichert wird).


Antwort

Obwohl es möglich ist, mit dem Operator eine ** numpy Matrix zu verwenden, die beste Lösung mit numpy der linalg matrix_power Verfahren numpy Arrays (wie numpy Matrizen veraltet sind) in Kombination zu verwenden ist.

matr_x = np.array(mat_a) 
matr_y = np.linalg.matrix_power(matr_x, path_length) 
work_matr = matr_y.tolist() 

Es ist nun auch klar, dass die Funktion von ** wird elementweise früher entdeckt hatte, wurde möglicherweise ich eine Adjazenzmatrix mit (nur Nullen und Einsen) nicht.

+1

Für numpy Arrays '**' Handlungen * elementweise *. –

+0

Okay danke, aber Power (matr_y, i) scheint auch nicht so zu funktionieren wie ich es erwartet habe, ist das auch elementweise? Iteriert durch np.dot() meine einzige Option? – Matchoo

+0

Ja, "Macht" ist auch elementweise, wie in der ersten Zeile seines Docstrings erklärt. :) –

Antwort

1

Es gibt (mindestens) zwei Möglichkeiten zur Berechnung der Leistung einer Matrix numpy ohne mehrere Anrufe zu dot Verwendung:

Zum Beispiel

In [38]: a 
Out[38]: 
array([[0, 1, 0], 
     [1, 0, 1], 
     [0, 1, 0]]) 

In [39]: np.linalg.matrix_power(a, 2) 
Out[39]: 
array([[1, 0, 1], 
     [0, 2, 0], 
     [1, 0, 1]]) 

In [40]: np.linalg.matrix_power(a, 3) 
Out[40]: 
array([[0, 2, 0], 
     [2, 0, 2], 
     [0, 2, 0]]) 

In [41]: m = np.matrix(a) 

In [42]: m ** 2 
Out[42]: 
matrix([[1, 0, 1], 
     [0, 2, 0], 
     [1, 0, 1]]) 

In [43]: m ** 3 
Out[43]: 
matrix([[0, 2, 0], 
     [2, 0, 2], 
     [0, 2, 0]]) 
+1

Matthew, wenn Sie nicht sicher sind, welches Sie verwenden sollen. Hier ist eine Art der [offiziellen Position] (http://stackoverflow.com/a/20964252/7207392) zu diesem Thema. –

+1

@Matthew Ich verlinkte das nur für den Fall, dass Sie zwischen den beiden vollkommen feinen Lösungen, die Warren angeboten hat, hin und her gerissen waren. Persönlich stimme ich zu, dass die "Matrix" -Klasse nicht genug bietet, um die Verwirrung auszugleichen, die sie verursacht. Also würde ich mit "linalg.matrix_power" gehen. Wenn Sie jemals selbst eine effiziente Integer-Potenzroutine programmieren müssen: Sie können viele Multiplikationen speichern, indem Sie Ihren Operanden (M, M^2, M^4, M^8 ...) wiederholt quadrieren und dann diejenigen multiplizieren, deren Bit in die binäre Repräsentation des Exponenten wird gesetzt. –

+0

@PaulPanzer das klingt wirklich interessant, aber ich bin ein wenig verwirrt, wie das funktioniert. Irgendeine Chance, die du erweitern oder mit einer kurzen Erklärung verknüpfen kannst? – Matchoo

1

Antwort Warren ist vollkommen gut.

Auf spezielle Anfrage des OP erkläre ich kurz, wie man einen effizienten ganzzahligen Potenzoperator von Hand erstellt.

Ich weiß nicht, wie dieser Algorithmus heißt, aber es funktioniert so: Angenommen, Sie wollen X^35 berechnen. Wenn Sie das naiv tun, kostet es Sie 34 Multiplikationen. Aber Sie können viel besser als das tun. Schreibe X^35 = X^32 x X^2 x X. Was du hier gemacht hast, ist das Produkt entsprechend der Binärdarstellung von 35 zu teilen, die 100011 ist.Nun, X^32 zu berechnen ist eigentlich billig, weil man nur immer wieder (5 mal) Quadrat X braucht um dorthin zu kommen. Also insgesamt brauchen Sie nur 7 Multiplikationen, viel besser als 34.

In Code:

def my_power(x, n): 
    out = None 
    p = x 
    while True: 
     if n % 2 == 1: 
      if out is None: 
       out = p 
      else: 
       out = out @ p # this requires a fairly up-to-date python 
           # if yours is too old use np.dot instead 
      if n == 1: 
       return out 
     n //= 2 
     p = p @ p