Newton-Verfahren im Komplexen

Neue Frage »

Hammala Auf diesen Beitrag antworten »
Newton-Verfahren im Komplexen
Meine Frage:
Hallo, ich müsste das Newton-Verfahren im Komplexen implementieren.
Das Newton-Verfahren klappt im Reellen schon, die Funktion weiß aber nicht, dass z komplex sein soll??? Wie kriege ich das hin?

Und mein zweites Problem ist, dass die Funktion "AbleitungsFunktion" den Rückgabewert diff(Funktion(z),z) haben soll, sonst muss ich immer die Ableitung ausrechnen. Nur dann geht der Newton Algorithmus nicht mehr?

Meine Ideen:
Hier mein Code:

x, y, z, t = symbols('x y z t')

def KomplexeZahl(x,y):
z = complex(x,y)
return z

def Funktion(z):
return z**3 + z - 1

def AbleitungFunktion(z):
return 3*z**2 + 1


#Newton-Verfahren
def Newton(z):
i = 1

while (((Funktion(z)>0.001) or (Funktion(z)<-0.001)) and (i<10)):
if AbleitungFunktion(z) == 0:
return z
z = z - Funktion(z)/AbleitungFunktion(z)
i = i + 1

return z

print(Newton(5+4*j))
chrizke Auf diesen Beitrag antworten »

In Python gibt es die Bibliothek cmath die automatisch importiert ist. Dein Aufruf sieht dann in etwa so aus

code:
1:
2:
3:
print(Newton(complex(5,4)))


Könntest du bitte deinen Code so editieren, dass alle Einrückungen korrekt dargestellt werden? Das ist bei Python ja sehr entscheidend. Nutze dazu bitte den [code] Tag.
 
 
Hammala Auf diesen Beitrag antworten »

ok, danke erst mal!

weißt du vielleicht, warum ich bei "AbleitungsFunktion" den Rückgabewert diff(Funktion(z),z) nicht schreiben darf, da sonst newton nicht mehr stimmt? ich weiß nicht, wo der fehler ist
chrizke Auf diesen Beitrag antworten »

Nein keine Ahnung. Was soll denn die Funktion diff tun? Was ist deren Rückgabewert? Ein paar mehr Infos wären echt hilfreich. Und bitte rück den Code korrekt ein.

Und noch was: Deine Abbruchbedingung der while-Schleife stimmt so nicht. Funktion liefert ja etwas komplexwertiges zurück, das kannst du nicht mit einer Fließkommazahl vergleichen.
Hammala Auf diesen Beitrag antworten »

ok, also diff(...) soll die Ableitung meiner Funktion sein nach z. Das ist glaub ich eine Funktion aus dem Packet sympy. Die Funktion diff leitet auch tatsächlich ab, nur wenn ich
sie in der Newton-Funktion benutz, dann denkt er, dass Funktion(z) eine Zahl ist??? Also ich will die Ableitung nicht selbst ausrechnen.

Die While-Schleife hab ich bisl abgeändert.

Warum ist die letzte print-Anweisung falsch? Der weiß nicht, was j ist (undefined variable)

code:
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
x, y, z, t = symbols('x y z t')

def KomplexeZahl(x,y):
     z = complex(x,y)
     return z

def Funktion(z):
     return z**3 + z - 1

def AbleitungFunktion(z):
     return 3*z**2 + 1              #hier will ich haben: diff(Funktion(z),z)


#Newton-Verfahren
     def Newton(z):
     i = 1

     while ((abs(Funktion(z)-z)>0.001) and (i<10)):
          if AbleitungFunktion(z) == 0:
                 return z
          z = z - Funktion(z)/AbleitungFunktion(z)
          i = i + 1

     return z

print(Newton(5+4*j)) 
chrizke Auf diesen Beitrag antworten »

Also fangen wir mal mit dem Einfachen an:

Zitat:

Warum ist die letzte print-Anweisung falsch? Der weiß nicht, was j ist (undefined variable)

Du hast es schon richtig erkannt und undefined variable sagt es dir ja auch: j ist nicht bekannt als imaginäre Einheit. Deswegen sollst du ja complex(a,b) nehmen um die komplexe Zahl a+ib zu initialisieren, sonst weiß python nicht, dass du dich in einem imaginären Kontext befindest.
EDIT: Ich hab nochmal gegoogelt, du kannst auch komplexe Zahlen ohne complex angeben, das j direkt benutzen, dann darf dort aber kein * stehen, sprich z=3+4j.

Nun zum eigentlichen Problem, der korrekten Verwendung und dem Verständnis von sympy.
Da ich vorher noch nie mit sympy gearbeitet hatte, musste ich mich da jetzt erstmal kurz einlesen und ich lege dir auch nahe, dir mal die zugehörige Dokumentation anzuschauen.

Dazu von vorne. Mit

code:
1:
2:
3:
x, y, z, t = symbols('x y z t')

erzeugst du vier Objekte die jeweils eine Symbolische Funktion darstellen (hier eben die Identität). Wendet man die gängigen Operatoren wie +,-,*,**,/ etc. darauf an oder auch andere Funktionen wie sin, cos, exp etc. ist das Resultat wieder ein Objekt das eine symbolische Funktion repräsentiert.
Um jetzt eine symbolische Funktion auf einen Wert anzuwenden, muss man folgendes tun:

code:
1:
2:
3:
4:
f = z**2+3          # So initialisiert man direkt eine symbolische Funktion
f.subs(z,5).evalf()

Dabei steht subs für "substitute" und bedeutet: Ersetze in der Funktion f jede symbolische Variable z durch 5 und berechne das Ergebnis. Das evalf() musst du anhängen, um Fließkommazahlen zu erhalten.

So nun zum Teil "Warum funktioniert der Code nicht wie er soll":
Das Hauptproblem ist, dass du dich selbst dadurch verwirrst, die Variable z auf zwei unterschiedliche Arten zu benutzen und hoffst, dass python so schlau ist, selber zu erkennen, was du eigentlich gemeint hast.
Das erste Mal, dass z auftaucht, ist als globale symbolische Variable in der ersten Zeile. Soweit kein Problem.
Das nächste Mal in der Funktion KomplexeZahl, welche du aber nie aufrufst –also kannst die Funktion auch ganz weglassen.
Dann benutzt du z wieder in Funktion und zwar als lokalen Parameter. Der hat zwar den gleichen Namen wie deine symbolische Variable zuvor, überdeckt diese aber. Das heißt, hier ist z immer das was du von außen reingibst und das muss nicht zwangsläufig die symbolische Variable z sein. Das hat auch seinen Vorteil, so funktioniert dein Code nämlich auch ohne die Verwendung von sympy, musst aber die Ableitung per Hand hinschreiben (oder dich der diff Funktion aus dem scipy Paket bedienen).
Wenn du nun in diese Funktion einen Wert wie zB 47.11 reingibst, wird die Funktion ausgewertet und eine Zahl zurückgegeben. Wenn du in diese Funktion eine symbolische Variable reingibst, wird eine symbolische Funktion zurückgegeben. Das ist leider ein Nachteil dynamisch typisierter Sprachen wie Python.
Gleiches gilt natürlich auch für die Funktion AbleitungsFunktion.

Dein Problem ist nun, dass Gleiches auch für Newton gilt. Du rufst ja diese Funktion mit einer komplexen bzw. Fließkommazahl auf. Das solltest du auch weiterhin tun, allerdings dann innerhalb von Newton erst die symbolischen Funktionen definieren und den Parameter von Newton nicht z nennen (das überdeckt ja die globale Variable z) sondern vielleicht besser z0 als Startwert, dann ist auch direkt klar, wofür das steht. Und jedes Mal, wenn du einen Wert der symbolischen Funktion bzw. Ableitung brauchst, rufst du darauf dann subs(...).evalf() auf.

Was vielleicht sogar auch geht, ist die ganze Newton-Berechnung auf symbolischen Objekten laufen zu lassen und erst ganz am Ende evalf aufzurufen. Es könnte aber sein, dass du dadurch erheblich Performance-Verluste hast.
Hammala Auf diesen Beitrag antworten »

danke!
nur bei einer sache glaub ich funktionierts noch nicht ganz und zwar gibt er mir, wenn ich diff(Funktion(z)) auswerten will, so wie dus beschrieben hast, eine komplexe zahl von format a+b*I und normalerweise sollte statt I ein j stehen, deswegen kommt dann für print(newton(....)) gar nichts mehr als Ausgabe raus
chrizke Auf diesen Beitrag antworten »

Dafür müsstest du mir jetzt nochmal deine Änderungen zeigen, sonst kann ich nur orakeln.
Hammala Auf diesen Beitrag antworten »

halb so schlimm, hab jettz viel gelernt dabei, danke nochmal!
Neue Frage »
Antworten »



Verwandte Themen

Die Beliebtesten »
Die Größten »
Die Neuesten »