Frage

habe ich ein Problem mit einigen numpy Sachen. Ich brauche eine numpy Array auf eine ungewöhnliche Art und Weise zu verhalten, indem eine Scheibe als Sicht auf die Daten zurückkehr ich in Scheiben geschnitten haben, keine Kopie. So heres ein Beispiel dafür, was ich tun möchte:

sagen, wir haben ein einfaches Array wie folgt:

a = array([1, 0, 0, 0])

Ich mag aufeinanderfolgende Einträge in dem Array aktualisieren (Moving links nach rechts) mit dem vorherigen Eintrag aus der Matrix, unter Verwendung von Syntax wie folgt:

a[1:] = a[0:3]

Dies würde folgendes Ergebnis:

a = array([1, 1, 1, 1])

Oder etwas wie folgt aus:

a[1:] = 2*a[:3]
# a = [1,2,4,8]

Zur weiteren Veranschaulichung möchte ich die folgende Art von Verhalten:

for i in range(len(a)):
    if i == 0 or i+1 == len(a): continue
    a[i+1] = a[i]

Außer, dass ich die Geschwindigkeit der numpy will.

Das Standardverhalten von numpy ist eine Kopie der Scheibe zu nehmen, so, was ich tatsächlich bekommen, ist dies:

a = array([1, 1, 0, 0])

Ich habe bereits dieses Array als Unterklasse der ndarray, so dass ich weitere Änderungen vornehmen kann, wenn es sein muss, ich brauche nur die Scheibe auf der rechten Seite werden ständig aktualisiert, da sie die Scheibe auf der linken aktualisiert Seite.

Bin ich träume oder ist diese Magie möglich?

Update: Das ist alles, weil ich versuche, Gauß-Seidel-Iteration zu verwenden, um ein lineares Algebra Problem zu lösen, mehr oder weniger. Es ist ein besonderer Fall, der harmonischen Funktionen, ich habe versucht, in diese zu vermeiden, zu gehen, weil es ist wirklich nicht notwendig und wahrscheinlich zu verwirren Dinge weiter, aber hier geht.

Der Algorithmus ist dies:

while not converged:
    for i in range(len(u[:,0])):
        for j in range(len(u[0,:])):
            # skip over boundary entries, i,j == 0 or len(u)
            u[i,j] = 0.25*(u[i-1,j] + u[i+1,j] + u[i, j-1] + u[i,j+1])

Richtig? Aber Sie können diese zwei Möglichkeiten, beinhaltet Jacobi jedes Element mit seinen Nachbarn zu aktualisieren, ohne Updates betrachtet haben Sie bereits bis in den while-Schleife Zyklen gemacht, es in Schleifen tun würden Sie das Array kopieren dann einen Array aus dem kopierten Array aktualisieren. Jedoch Gauss-Seidel verwendet Informationen, die Sie bereits für jede der i-1 und j-1 Einträge aktualisiert, so dass keine Notwendigkeit für eine Kopie, soll die Schleife im wesentlichen ‚wissen‘, da das Array nach jedem einzelnen Elemente Update neu bewertet wurde . Das heißt, wir jedes Mal einen Eintrag wie u aufrufen [i-1, j] oder u [i, j-1] die Informationen in der vorherige Schleife berechnet werden da sein.

Ich mag diese langsam und hässlich Situation verschachtelter Schleife ersetzen mit einer schönen sauberen Codezeile numpy Slicing mit:

u[1:-1,1:-1] = 0.25(u[:-2,1:-1] + u[2:,1:-1] + u[1:-1,:-2] + u[1:-1,2:])

Aber das Ergebnis ist Jacobi Iteration, denn wenn man ein Stück nehmen: u [:, - 2,1: -1], um die Daten zu kopieren, damit die Scheibe nicht bekannt, dass Updates gemacht ist. Jetzt numpy noch rechts Schleifen? Es ist nicht parallel sein gerade einen schnelleren Weg zu Schleife, das aussieht wie ein Parallelbetrieb in Python. Ich möchte dieses Verhalten durch Art von Hacking numpy auszubeuten einen Zeiger statt einer Kopie zurückzukehren, wenn ich ein Stück nehmen. Recht? Dann jedes Mal numpy Loops, dass Slice ‚update‘ oder wirklich nur replizieren, was auch immer in der Aktualisierung passiert ist. diese Ich brauche Scheiben des Arrays auf beiden Seiten zu tun Zeiger zu sein.

Wie auch immer, wenn es etwas wirklich sehr kluge Person gibt, die fantastisch, aber ich habe so ziemlich resigniert mich die einzige Antwort auf Glauben zu Schleife in C ist.

War es hilfreich?

Lösung

Späte Antwort, aber das auf Google aufgedreht, damit ich auf das Dokument verweist wahrscheinlich die OP wollte. Ihr Problem ist klar: wenn NumPy Scheiben verwenden, Provisorien geschaffen werden. Wickeln Sie Ihren Code in einem kurzen Anruf zu weave.blitz um loszuwerden, die Provisorien zu bekommen und haben das Verhalten Ihr wollen.

Lesen Sie den weave.blitz Abschnitt PerformancePython Tutorial für weitere Informationen.

Andere Tipps

accumulate ist entworfen, um zu tun, was Sie scheinen zu wollen; das heißt, eine Operation entlang eines Arrays proprigate. Hier ein Beispiel:

from numpy import *

a = array([1,0,0,0])
a[1:] = add.accumulate(a[0:3])
# a = [1, 1, 1, 1]

b = array([1,1,1,1])
b[1:] = multiply.accumulate(2*b[0:3])
# b = [1 2 4 8]

Eine andere Möglichkeit, dies zu tun ist, um explizit das Ergebnis Array als Eingabe-Array angeben. Hier ein Beispiel:

c = array([2,0,0,0])
multiply(c[:3], c[:3], c[1:])
# c = [  2   4  16 256]

Verwenden Sie einfach eine Schleife. Ich kann nicht sofort denken Sie an irgendeiner Weise die Scheibe Betreiber benehmen sich die Art und Weise zu machen, Sie sagen, Sie es haben wollen, mit Ausnahme von vielleicht von numpy des array und zwingende die entsprechende Methode mit irgendeiner Art von Python Voodoo Subklassen ... aber was noch wichtiger ist, sollte die Idee, dass a[1:] = a[0:3] den ersten Wert von a in den nächsten drei Slots kopieren scheint mir völlig unsinnig. Ich stelle mir vor, dass es könnte leicht verwirren alle anderen, die (zumindest die ersten paar Male) auf den Code aussieht.

Es ist nicht die richtige Logik. Ich werde versuchen, Briefe zu verwenden, es zu erklären.

Bild array = abcd mit a, b, c, d als Elemente.
Nun array[1:] Mittel von dem Element in Position 1 (ab 0) auf.
In diesem Fall gilt: bcd und array[0:3] Mittel aus der Zeichenposition in 0 zu den dritten Zeichen oben (die in Position 3-1) in diesem Fall. 'abc'

Schreiben so etwas wie:
array[1:] = array[0:3]

Mittel: ersetzen bcd mit abc

Um die Ausgabe, die Sie wollen, jetzt in Python zu erhalten, sollten Sie so etwas wie verwenden:

a[1:] = a[0]

Es muss etwas mit Zuweisung einer Scheibe zu tun haben. Die Betreiber jedoch, wie Sie vielleicht schon wissen, folgen Ihrem erwartetes Verhalten:

>>> a = numpy.array([1,0,0,0])
>>> a[1:]+=a[:3]
>>> a
array([1, 1, 1, 1])

Wenn Sie bereits Nullen in Ihrem realen Problem, dass Ihr Beispiel der Fall ist, dann löst dies es. Andernfalls an zusätzlich Kosten, stellen Sie sie auf Null entweder durch Null multipliziert oder auf Null zuweisen, (je nachdem, was schneller ist)

edit: Ich hatte einen anderen Gedanken. Sie können dies bevorzugen:

numpy.put(a,[1,2,3],a[:3]) 

Numpy muss überprüft werden, wenn das Ziel-Array die gleiche wie die Eingangsanordnung ist, wenn die setkey Anruf zu tun. Glücklicherweise gibt es Möglichkeiten, um ihn herum. Zuerst habe ich versucht, mit numpy.put statt

In [46]: a = numpy.array([1,0,0,0])

In [47]: numpy.put(a,[1,2,3],a[0:3])

In [48]: a
Out[48]: array([1, 1, 1, 1])

Und dann von der Dokumentation, dass, gab ich flatiters einen Versuch ( a.flat )

In [49]: a = numpy.array([1,0,0,0])

In [50]: a.flat[1:] = a[0:3]

In [51]: a
Out[51]: array([1, 1, 1, 1])

Aber das löst nicht das Problem, das Sie im Sinn hatte,

In [55]: a = np.array([1,0,0,0])

In [56]: a.flat[1:] = 2*a[0:3]

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

Dies schlägt fehl, da die Multiplikation vor der Zuweisung erfolgt ist, nicht parallel, wie Sie möchten.

Numpy wird für die wiederholte Anwendung der gleichen Operation parallel über eine Anordnung gestaltet. Um etwas zu tun mehr kompliziert, es sei denn, Sie zersetzen es in Bezug auf Funktionen wie numpy.cumsum und numpy.cumprod finden können, müssen Sie greifen zu so etwas wie scipy.weave oder Schreiben die Funktion in C (siehe

Sie können einen Blick auf np.lib.stride_tricks haben.

Es gibt einige Informationen in diesem hervorragenden Dia: http://mentat.za.net/numpy/numpy_advanced_slides/

mit stride_tricks am Schlitten starten 29.

Ich bin nicht vollständig auf die Frage klären, obwohl kann so nichts mehr konkret vorschlagen - obwohl ich es wahrscheinlich in cython tun würde, oder Fortran mit f2py oder mit weben. Ich bin gefallen Fortran mehr im Moment, weil durch die Zeit, die Sie in allen erforderlichen Typ Anmerkungen hinzufügen cython Ich denke, es sieht letzten Endes weniger klar als die Fortran.

Es gibt einen Vergleich dieser hier Ansätze:

www. scipy. org / PerformancePython

(kann nicht mehr Links posten, wie ich bin ein neuer Benutzer) mit einem Beispiel, dass ähnelt Ihren Fall.

Am Ende kam ich mit dem gleichen Problem wie Sie. Ich musste zurückgreifen Jacobi Iteration zu verwenden und Weber:

 while (iter_n < max_time_steps):
        expr = "field[1:-1, 1:-1] = (field[2:, 1:-1] "\
                                                      "+ field[:-2, 1:-1]+"\
                                                      "field[1:-1, 2:] +"\
                                                      "field[1:-1, :-2] )/4."                                       

        weave.blitz(expr, check_size=0)

         #Toroidal conditions
        field[:,0] = field[:,self.flow.n_x - 2]
        field[:,self.flow.n_x -1] = field[:,1]

        iter_n = iter_n + 1

Es funktioniert und ist schnell, aber nicht Gauss-Seidel, so kann die Konvergenz ein bisschen schwierig sein. Die einzige Möglichkeit, zu tun Gauss-Seidel als traditionelle Schleife mit Indizes.

Ich würde vorschlagen, cython statt in c von looping. es Macht , einige Phantasie numpy Art und Weise von Ihrem Beispiel zu Arbeit immer eine Menge von Zwischenschritten mit ... aber da Sie wissen, wie es bereits in c zu schreiben, schreiben Sie einfach, dass schnell etwas als cython Funktion und lassen cython Magie den Rest der Arbeit einfach für Sie.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top