Seite 1 von 1

Lösung spezieller kubischer Funktion

Verfasst: Donnerstag 17. Juni 2010, 10:23
von F.S.
Hallo zusammen,

erster Beitrag und gleich ein Programmierproblem.... :)
Ich arbeite mit python 2.6 und nutze bei der Programmierung Spyder.

Es geht um die Nullstelle der folgenden kubischen Funktion:

Code: Alles auswählen

def func_v(v, x): 
    return (c1*v**3)+(func_1(v)*c2*(c3+func_3(x[2]))*v)-(c4)
v ist der Wert, den ich bei der Nullstellensuche variieren möchte.
x = [x0,x1,x2] ist ein array mit aktuell 3 Parametern, die während des gesamten Programmverlaufs optimiert werden sollen.
c1,c2,... sind diverse Konstanten, die sich im gesamten Programmverlauf nicht ändern.
func_1 bestimmt einen von v abhängigen Parameter (könnte eventuell auch noch mit in func_v hineingezogen werden, wäre nur etwas unübersichtlicher).

Wäre da nicht der Term "func_3(x[2])", also die Abhängigkeit von einer weiteren Variable, würde folgendes problemlos funktionieren, so habe ich das bisher gemacht:

Code: Alles auswählen

r_v=brentq(func_v, a, b)
(brentq aus scipy.optimize)

Beide Variablen, also v und x[2], variieren zu lassen um eine Nullstelle zu finden wäre jetzt auch kein Problem.

Aber wie schaffe ich es, dass ich den Wert x[2] an die Funktion übergebe, sodass x[2] während der Nullstellensuche konstant bleibt, beim nächsten Aufruf von func_v aber mit einem anderen Wert haben kann?
(ich also func_v z.B. für alle x zwischen 1 und 100 auswerten kann)

Re: Lösung spezieller kubischer Funktion

Verfasst: Sonntag 20. Juni 2010, 06:14
von gkuhl
Hallo und Willkommen im Forum,

du könntest ''lambda'' verwenden:

Code: Alles auswählen

In [78]: def f(x,b):
             return (x - b)**3
   ....: 

In [80]: for b in [-2,0,2]:
             brentq(lambda x: f(x,b), -2, 2)
   ....:     
   ....:     
Out[81]: -2.0
Out[81]: 0.0
Out[81]: 2.0
Grüße
Gerrit

Re: Lösung spezieller kubischer Funktion

Verfasst: Sonntag 20. Juni 2010, 08:27
von Darii
F.S. hat geschrieben:Aber wie schaffe ich es, dass ich den Wert x[2] an die Funktion übergebe, sodass x[2] während der Nullstellensuche konstant bleibt, beim nächsten Aufruf von func_v aber mit einem anderen Wert haben kann?
Ich verstehe nicht was du willst, aber vielleicht ist es das args-Argument was du suchst?

Code: Alles auswählen

r_v=brentq(func_v, a, b, args=(x,))

Re: Lösung spezieller kubischer Funktion

Verfasst: Sonntag 20. Juni 2010, 14:40
von F.S.
@gkuhl:

Danke für der Vorschlag - wird ausprobiert!

Hab selbst nochmal "geforscht":
Eventuell lässt sich das Ganze auch objektorientiert lösen, indem man die augenblickliche Konfiguration in einem Objekt hinterlegt, auf das dann auch aus den einzelnen Funktionen zugegriffen werden kann (lesen wie ändern) .

@Darii:

Danke für die Antwort!
Ich verstehe nicht was du willst, aber vielleicht ist es das args-Argument was du suchst?
Vllt. noch einmal eine Beschreibung meines Problems:
Ich habe diese Funktion, die von x³ und einer weiteren Variable abhängt. Jetzt möchte ich den Wert für x finden, für den meine Funktion 0 wird (Nullstelle) - bei dieser einen gegebenen Variable. Hart eincodieren kann ich die Zahl nicht, da sie beim nächsten Programmdurchlauf anders aussehen wird.
brentq kann nur Funktionen aufrufen, die von 1 Variable abhängen (also kann ich diese zusätzliche Variable nicht beim Funktionsaufruf, Optmierungsallgorithmen optimieren gewöhnlich über allen Variablen.

Mit dieser args-Funktion habe ich bereits ein bißchen herum experimentiert - bin aber dabei zu keinem sinnvollen Ergebnis gekommen. Wie man diese Funktion benutzen müsste und was sie eigentlich genau bewirkt, erschließt sich mir aus der Beschreibung leider nicht ganz:

Code: Alles auswählen

args : tuple containing extra arguments for the function f.
    f is called by apply(f,(x)+args).

Re: Lösung spezieller kubischer Funktion

Verfasst: Sonntag 20. Juni 2010, 15:03
von pillmuncher
args ist keine Funktion, sondern ein Tupel mit Argumenten für den späteren (internen) Aufruf von func_v - dieses wird dann aufgerufen als:

Code: Alles auswählen

func_v((x,) + args)
woraus dann

Code: Alles auswählen

func_v(x, args[0], args[1], ...)
wird. Wenn du also brentq aufrufst, tu das so, wie Darii es gezeigt hat, mit args=(x,), wobei x die Zahl ist, die du zusätzlich übergeben willst, nicht wie bei dir eine Liste von Zahlen. Dann würde das ganze in etwa so aussehen:

Code: Alles auswählen

def func_v(v, n):
    return (c1*v**3)+(func_1(v)*c2*(c3+func_3(n))*v)-(c4)
...                                    # hier ^ nix mehr x[2]
for m in x:
    r_v = brentq(func_v, a, b, args=(m,))
    ... #irgendwas mit r_v anstellen

Re: Lösung spezieller kubischer Funktion

Verfasst: Montag 21. Juni 2010, 17:33
von F.S.
Danke dir!
Die Lösung gefällt mir noch besser als mit dem Lambda - wenn jede Formel ihre eigene Funktion behält, bleibt das Ganze flexibler und übersichtlicher.

Re: Lösung spezieller kubischer Funktion

Verfasst: Mittwoch 23. Juni 2010, 16:52
von F.S.
So, Problem ist gelöst. :D

Letztlich habe ich es über Klassen erledigt, also in der Zeile vor "brentq" den Problemwert func_3(x[2]) berechnet und in der Klasse MeineKlasse als MeineKlasse.wert gespeichert. So ist MeineKlasse.wert aus allen Funktionen aufrufbar und seine Rechenparameter in eine Klasse zu stecken dürfte auch besserer Programmierstil sein, als sie irgendwo im Haupttextblock zu definieren.

Vielen Dank euch nochmal für eure Hilfe, auch wenn ich es letztlich anders gelöst habe!

Re: Lösung spezieller kubischer Funktion

Verfasst: Mittwoch 23. Juni 2010, 19:01
von EyDu
Hallo.
F.S. hat geschrieben:So ist MeineKlasse.wert aus allen Funktionen aufrufbar und seine Rechenparameter in eine Klasse zu stecken dürfte auch besserer Programmierstil sein, als sie irgendwo im Haupttextblock zu definieren.
Klassen an unangebrachten Stellen ist nicht unbedingt besser ;-) Dariis und pillmunchers Lösungen scheinen mir hier der richtige Weg, als Alternative bietet sich noch "functools.partial" an. Und wenn du schon Klassen benutzt, dann doch richtig und nicht über ein "wert"-Argument. Schau dir mal die "__call__"-Methode an.

Sebastian