Funktion plotten mit MatPlotLib

mit matplotlib, NumPy, pandas, SciPy, SymPy und weiteren mathematischen Programmbibliotheken.
Antworten
Lappeninpython
User
Beiträge: 7
Registriert: Samstag 14. Juli 2018, 13:10

Hallo liebe Community,

wie mein Benutzername schon sagt tauge ich nichts in Python und ich hoffe das ihr mir durch dieses Dilemma helfen könnt.

Nach langer harter arbeit hab ich eine etwas längere Funktion definieren müssen, zusammengefasst geht es um ein Eigenwertproblem (Quantenmechanik). Nun habe ich in dieser Funktion einen Parameter der minimiert werden soll, ich würde gerne diese Funktion durch Matplotlib plotten.

Zum Code :
def EIGENH(ALPHA):
.
längerer Code der zusammengefasst nur zwei Matrizen (H und N) bestimmen soll in abhägigkeit von ALPHA
.
.
EIG = eigvalsh(H,N) # Lösung des allgemeinen Eigenwertproblems
result = EIG[0] # EIG[0] greift auf den ersten Eigenwert zu
return result


X = np.linspace(0.01, 2, 20, endpoint=True)
F = EIGENH(X)
plt.plot(X,F)
plt.show()

"als fehler bekomme ich:

raise ValueError('expected square matrix')

ValueError: expected square matrix"

Dieser Fehler schon auf wenn ich mit 1x1 matritzen arbeite.
Bestimme ich beispielweise EIGENH(0.7) ,EIGENH(1.5) gibt es keine Probleme und die Funktion macht/printet was man erwartet. Vermute das Problem liegt an der übergabe von "X" an "F" ?


Wenn jemand eine Idee hat welchen dummen Fehler ich gemacht hab, wäre ich sehr dankbar :?:

Lieben Gruß,
Lappen in Python
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Mir ist bei der Beschreibung nicht klar *wo* der Fehler auftritt. Bitte immer den kompletten Traceback zeigen und nicht nur die letzte Zeile. Kommt der Fehler überhaupt vom `plot()` oder wird der von irgend etwas in `EIGENH()` ausgelöst?

Was ist eine „Übergabe von "X" nach "F"“? Von Übergabe spricht man eigentlich nur bei Funktions- oder Methodenaufrufen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Lappeninpython
User
Beiträge: 7
Registriert: Samstag 14. Juli 2018, 13:10

Vielen dank für die rasche Antwort :)

@Was ist eine „Übergabe von "X" nach "F"“? Von Übergabe spricht man eigentlich nur bei Funktions- oder Methodenaufrufen.
vielleicht sollte ich bei meinen Formulierungen aufpassen, damit meinte ich das wenn F die werte aus X nimmt und auswerten möchte mit der Funktion EIGENH(ALPHA), aber vielleicht sollte man diese Aussage einfach ignorieren da ich wenig Ahnung hab.

nebenbei Benutze ich Python 3.6 in Spyder vielleicht hilft das.
jetzt zum vollen Traceback:


File "C:\Users\kken\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 705, in runfile
execfile(filename, namespace)

File "C:\Users\kken\Anaconda3\lib\site-packages\spyder\utils\site\sitecustomize.py", line 102, in execfile
exec(compile(f.read(), filename, 'exec'), namespace)

File "C:/Users/kken/Desktop/Python Bachelor/Testen.py", line 243, in <module>
F = EIGENH(X)

File "C:/Users/kken/Desktop/Python Bachelor/Testen.py", line 235, in EIGENH
EIG = eigvalsh(H,N)

File "C:\Users\kken\Anaconda3\lib\site-packages\scipy\linalg\decomp.py", line 764, in eigvalsh
check_finite=check_finite)

File "C:\Users\kken\Anaconda3\lib\site-packages\scipy\linalg\decomp.py", line 331, in eigh
raise ValueError('expected square matrix')

ValueError: expected square matrix
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Wenn man den Aufruf über den Traceback also verfolgt, dann ist die Zeile ``EIG = eigvalsh(H,N)`` das letzte was noch in Deinem Programm liegt. Also ist entweder `H` oder `N` keine quadratische Matrix. Jetzt musst Du herausfinden welche, und warum. Den Code hast Du ja im Beitrag ausgelassen.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Lappeninpython
User
Beiträge: 7
Registriert: Samstag 14. Juli 2018, 13:10

X = np.linspace(0.01, 2, 20, endpoint=True)
F = EIGENH(X)
plt.plot(X,F)
plt.show()

Wenn ich das richtig verstehe sollte die Teil des Codes folgendermaßen funktionieren:
X wird ein Array aus 20 elementen
F wertet einfach für jedes element in X die Funktion EIGENH aus
und dies sollte in gegeneinander aufgetragen werden ?
wenn ich jetzt werte aus X direkt ausrechne bsp. mit print(EIGENH(0.01), EIGENH(2)) gibt es keinerlei Probleme mit meiner Funktion EIGENH
aus dem Grund kann ich mir überhaupt nicht erklären wie die Matritzen nicht Quadratisch sein sollen, diese werden durch:
n=(D**3)
l=(D**3)
H = [0]*n
N = [0]*n
for i in range (n):
H = [0] *l
N = [0] *l
außerhalb der Funktion EIGENH generiert ?
Wärend des Fehlers ist D=1 womit H und N 1x1 Matritzen sein müssten :/
Lappeninpython
User
Beiträge: 7
Registriert: Samstag 14. Juli 2018, 13:10

Habe es Mal auf eine andere Art versucht:

Code: Alles auswählen

X = np.linspace(0.05, 2, 20, endpoint=true)
F = [0]*20
for xs in X:
    i=0
    F[i]=EIGENH(xs)
    i=i+1
plt.plot(X,F)
plt.show()
print(EIGENH(0.01), EIGENH(1))
bekomme folgendes Ergebnis:
https://ibb.co/d9s4Go

-0.809158152291122, -19.745438865782695
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Lappeninpython: `F` wertet gar nichts aus, `F` ist der Name an den das Ergebnis vom `EIGENH()`-Aufruf gebunden wird. Wenn es denn eines gäbe im vorliegenden Fall, denn `EIGENH()` bricht ja mit einer Ausnahme ab.

Der Code hier ist zum einen sehr „unpythonisch“ und wenn man mit Numpy & Co zu tun hat auch sehr ineffizient:

Code: Alles auswählen

H = [0]*n
N = [0]*n
for i in range (n):
    H[i] = [0] *l
    N[i] = [0] *l
Unpythonisch weil man keine Listen mit Platzhaltern erstellt um die gleich danach durch die tatsächlichen Werte zu ersetzen. Es ist auch etwas verwirrend warum Zahlen (0) durch Listen ersetzt werden. In Python baut man die Listen gleich mit den richtigen Werten auf, ohne den Zwischenschritt mit irgendwelchen Dummywerten. Syntaktisch ist das die „list comprehension“ sehr praktisch.

In reinem Python wäre das also:

Code: Alles auswählen

H = [[0] * l for _ in range(n)]
N = [[0] * l for _ in range(n)]
Aber wir haben hier ja Numpy & Co und das verwendet man ja wegen der Arrays und um sich Schleifen in Python-Code zu ersparen. Also mit Numpy:

Code: Alles auswählen

H = numpy.zeros((n, l))
N = numpy.zeros((n, l))
Warum werden die ausserhalb der Funktion erzeugt? Das macht doch keinen Sinn zwei gleich grosse Konstante 2D-Arrays mit Nullwerten zu haben und die an `eigvalsh()` zu übergeben‽

Und ob die Deiner Meinung nach quadratisch sein *müssten* ist eigentlich egal, denn Fakt ist, das sie das beim Aufruf von `eigvalsh()` in `EIGENH()` definitiv nicht sind. Mindestens einer der beiden Namen ist an der Stelle und zu dem Zeitpunkt nicht mehr an eine quadratische Matrix gebunden. Du musst mindestens einen der beiden Namen also irgendwo vorher an etwas anderes binden.

An der Stelle sollte man vielleicht mal anmerken das auf Modulebene nur Konstanten, Funktionen, und Klassen definiert werden sollten und alles was eine Funktion oder Methode ausser Konstanten benötigt, sollte als Argument übergeben werden. Funktionen schreibt man am besten so, das sie wie mathematische Funktionen keine Seiteneffekte haben, also nichts an den Argumenten ändern und neue Werte zurückgeben. Wenn man das alles nicht macht, kann man sich bei manchen Fehlern die Suche nach der Ursache echt schwer machen, weil man keine Funktion einzeln betrachten und testen kann, sondern immer das gesamte Programm im Blick haben muss, weil alles irgendwie mit allem anderen zusammenhängen könnte.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

Also bei mir geht "endpoint=true" nicht, True muss Gross geschrieben werden
Deine Schleife ist nicht das was du willst,
du setzt jedesmal i=0 also für alle xs in X: F[0] = deine EIGENH()
du möchtest:

Code: Alles auswählen

for i, xs in enumerate(X):
    F[i] = EIGENH(xs)
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
ThomasL
User
Beiträge: 1366
Registriert: Montag 14. Mai 2018, 14:44
Wohnort: Kreis Unna NRW

achja, mir fällt gerade ein, es gibt in Numpy eine Methode fromiter(), solltest du dir mal anschauen
https://docs.scipy.org/doc/numpy/refere ... miter.html
Ich bin Pazifist und greife niemanden an, auch nicht mit Worten.
Für alle meine Code Beispiele gilt: "There is always a better way."
https://projecteuler.net/profile/Brotherluii.png
Benutzeravatar
__blackjack__
User
Beiträge: 13004
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Man möchte an der Stelle `F` gar nicht mit sinnlosen Nullwerten vorbelegen wo man dann hinterher einen Index braucht um darauf zuzugreifen:

Code: Alles auswählen

F = list(map(EIGENH, X))
Aber auch das möchte man nicht wenn man Numpy & Co verwendet. Und da offensichtlich leicht die Übersicht verloren gegangen ist an was welche Namen zu welchem Zeitpunkt gebunden sind, kann man eh keinem Ergebnis vertrauen bis man das geklärt hat.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
Lappeninpython
User
Beiträge: 7
Registriert: Samstag 14. Juli 2018, 13:10

@thomasL , danke das ist mir auch aufgefallen beim betrachten des Problem. Nun sieht der Plot auch aus wie ich es möchte :)
Ebenfalls vielen dank für den Link ich werde mir diesen sofort mal anschauen.

@Blackjack ich kann verstehen das dir meine Art und Weise zu programmieren wehtut beim anschauen, ich musste mir leider in kurzer Zeit alles das ganze irgendwie zum laufen bringen. Vielen dank für die Optimierungsratschläge ich werde versuchen das ganze so gut wie es geht umzusetzen.

leider verstehe ich nicht wieso ich mit dem Umweg über ein Array auf das "richtige" Ergebnis komme:
https://ibb.co/b3xMWo
ich werde wohl noch einbisschen damit rumhantieren müssen.
Antworten