Newton-Verfahren

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
reyungoo
User
Beiträge: 9
Registriert: Samstag 22. August 2009, 10:13

Hallo Forum,
ich versuche gerade die Nullstellen einer Funktion mit dem
Newton-Verfahren zu bestimmen. Habe bei scipy das Packet
optimize gefunden.
Habe mir die Funktion definiert:

Code: Alles auswählen

def q(x):
    return cos(x) + b*e**x -a
und erhalte mit

Code: Alles auswählen

print scipy.optimize.newton(q, 1, maxiter=100)
das gewünschte Ergebnis. Mein Problem ist aber, dass
ich gerne das ganze automatisiert durchspielen möchte mit
verschiedenen Werten von a und b. Habe die in Frage kommenden
a und b in jeweils ein array gesteckt. Wenn ich diese arrays
in obige Funktion einsetze und Newton berechnen lasse kommt
ein Fehler:
if q1 == q0:
ValueError: The truth value of an array with more than one
element is ambiguous. Use a.any() or a.all()

Hier weiß ich dann nicht mehr weiter. Was mache ich falsch?
Wie geht es richtig?


Gruß
Niko
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

reyungoo hat geschrieben:Mein Problem ist aber, dass
ich gerne das ganze automatisiert durchspielen möchte mit
verschiedenen Werten von a und b.
Mit welchem Ziel? Wenn Du Parameter fitten möchtest, solltest Du Die Funktion entsprechend umstellen und die Fitroutinen verwenden.

Ansonsten: Iteriere einfach über die Parameter a und b, wenn sie Listen / ndarrays sind.

Und warum diese Fehlermeldung kommt: Wie soll eine Funktion, die einen Parameter akzeptiert für mehrere optimiert werden? Wenn Du q entsprechend anpasst und optimize.fsolve verwendest, hast Du mehr Erfolg - wenn auch nicht mit Newton. ;-).

HTH
Christian
reyungoo
User
Beiträge: 9
Registriert: Samstag 22. August 2009, 10:13

Danke für die Antwort,
ersteinmal das ganze dient nur der Spielerei, zugegebenermaßen
stelle ich mich da nicht wirklich geschickt an. Bin, was Programmieren angeht, noch zu unbeholfen.
Ansonsten: Iteriere einfach über die Parameter a und b, wenn sie Listen / ndarrays sind.
das heißt for-Schleife verwenden? Aber wo verwende ich sie?
Ich hab's mit ersteinmal einem Paramter versucht mit:

Code: Alles auswählen

for i in a:
    scipy.optimize.newton(q, 1, maxiter=100)
a ist eine Liste mit vier Einträgen.

Dann kommt Fehlermeldung:
TypeError: unsupported operand type(s) for /: 'list' and 'int'

vielleicht noch ein letzter Tipp, bevor ich es ganz lasse?

Gruß
Niko
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Am besten du zeigst mal einen kompletten, lauffähigen Code. Mir scheint es so, als ob du einige grundlegenden Dinge noch nicht richtig verstanden hast. Bei deiner Funktion solltest du alle Parameter (a,b,x) übergehen:

Code: Alles auswählen

def q(x,a,b):
    return cos(x) + b*e**x - a
Alternativ ist das mit ``lambda`` auch machbar:

Code: Alles auswählen

q = lambda x,a,b: cos(x) + b*e**x - a
Grundsätzlich solltest du Code auf Modulebene nur schreiben, wenn er auch beim importieren ausgeführt werden soll. Es empfiehlt sich daher die folgende Programmstruktur zu verwenden:

Code: Alles auswählen

def main():
    ...

if __name__ == '__main__':
    main()
Wird das Programm direkt ausgeführt ist die Bedinung ``True``, beim Importieren aber ``False``, weil ``__name__`` dann den Modulnamen enthält.

Grüße
Gerrit
reyungoo
User
Beiträge: 9
Registriert: Samstag 22. August 2009, 10:13

Am besten du zeigst mal einen kompletten, lauffähigen Code.
Es gibt keinen lauffähigen Code, mehr als das was ich geschrieben habe existiert nicht.
Mir scheint es so, als ob du einige grundlegenden Dinge noch nicht richtig verstanden hast.
Ich bin voll deiner Meinung. Ich dachte ich könnte das schnell lösen und fertig. Aber das funktioniert so nicht.
Danke trotzdem

Gruß
Niko
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Mhh, ja. Ich sehe gerade das ``newton`` nur Funktionen mit einem Argument erlaubt. Da geht was ich im Sinn hatte also garnicht. Schau dir mal den folgenden Code an:

Code: Alles auswählen

from scipy.optimize import newton
from numpy import cos

def main():
    for a in xrange(10):
        func = lambda x: cos(a*x -  x**2)
        print newton(func, 10)       
            
if __name__ == '__main__':
    main()
Grüße
Gerrit
ms4py
User
Beiträge: 1178
Registriert: Montag 19. Januar 2009, 09:37

Willst du vielleicht so etwas:
http://www.scipy.org/Cookbook/FittingData
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

ice2k3 hat geschrieben:Willst du vielleicht so etwas:
http://www.scipy.org/Cookbook/FittingData
Wenn er die Nullstelle sucht, wird er das wohl nicht wollen.
Benutzeravatar
gkuhl
User
Beiträge: 600
Registriert: Dienstag 25. November 2008, 18:03
Wohnort: Hong Kong

Wenn ich ihn richtig verstanden habe, geht es ihm wohl eher darum die Sprache kennen zu lernen. Wenn du aber NumPy, SciPy und Matplotlib verwenden möchtest, solltest du vorher aber auf jeden Fall das Python Tutorial durchgearbeitet haben.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

... und wenn man gkhul's und mein erstes Kommentar zusammenschmeisst, kann man auch - eben ohne Newton - die Nullstellen für eine Armada von Parametern finden.
Benutzeravatar
hendrikS
User
Beiträge: 420
Registriert: Mittwoch 24. Dezember 2008, 22:44
Wohnort: Leipzig

Mal auf die Schnelle ohne Scipy:

Code: Alles auswählen

#Newton Raphson demo

from math import sin, cos, exp

def q(x, a, b):
  return cos(x) + b * exp(x) - a

def dq(x, b):
  return - sin(x) + b * exp(x)

maxiter = 20
x = 0 #startwert

for i in xrange(maxiter):
    x -= q(x,3,5)/dq(x,5)

print "%.12f"%x
Benutzeravatar
str1442
User
Beiträge: 520
Registriert: Samstag 31. Mai 2008, 21:13

@gkuhl: Die Funktion muss man nicht in der Schleife neu erzeugen, denn das "a" wird nicht in die Funktion sozusagen "eingemeißelt". Bei Aufruf greift die Funktion nur auf das nichtlokale a zu, welches sich eben zwischen den Aufrufen verändert:

Code: Alles auswählen

>>> func = lambda x: x + a
>>> 
>>> for a in xrange(10):
...   func(1)
... 
1
2
3
4
5
6
7
8
9
10
@OP Definiere dir doch einfach eine Funktion mit x, a und b als Parametern und benutze functools.partial(), um in der Schleife die Funktion zu einer Funktion mit einem Argument / einer unären Funktion umzuwandeln.
Antworten