6.3 Nichtlineare Gleichungssysteme
Gleichungssysteme sind dann nichtlinear, wenn die Unbekannten x und y als Produkt x ⋅ y, als Potenzen xn und yn oder als Exponenten ax und by vorkommen. Auch wenn für Kombinationen linearer und trigonometrischer Terme die Nullstellen bestimmt werden sollen, handelt es sich um ein nichtlineares Problem.
Nichtlineare Gleichungssysteme sind erheblich schwieriger zu lösen als lineare Systeme. Es gibt keine einfachen Methoden, mit denen überprüft werden kann, ob sie überhaupt lösbar sind und wie viele Lösungen sie haben. Sie lassen sich nicht in der Form Ax = b formulieren. Nichtlineare Systeme können eine, unendlich viele oder keine Lösung haben.
Nichtlineare Gleichungen können Sie mit der SciPy-Funktion fsolve() oder mit der SymPy-Methode nonlinsolve() lösen. Im Gegensatz zur SciPy- Funktion verlangt die SymPy-Methode keine Vorgaben für Startwerte.
Wir wollen das nichtlineare Gleichungssystem


lösen, in dem die Quadrate der Unbekannten x1 und x2 vorkommen. Es handelt sich also um zwei Normalparabeln. Näherungswerte für die Schnittpunkte der beiden Parabeln können aus Abbildung 6.3 abgelesen werden.
Als Startwerte für die vier Lösungen können die x, y-Koordinaten (–2,6|–1,5), (–1,9|1,9), (1,5|2,6) und (–2,7|–2,8) gewählt werden.
Abbildung 6.3 Schnittpunkte zwischen zwei Parabeln
6.3.1 Lösung mit SciPy
Getestet werden soll, ob die SciPy-Funktion fsolve() auch in der Lage ist, eine etwas komplexere Gleichung mit zwei quadratischen Funktionstermen zu lösen. Die Startwerte werden diesmal in eine Liste start=[-3,-2],[-2,2],[1,3],[2,-3] aus Ganzzahlen gespeichert. Wenn die Funktion fsolve() innerhalb einer for-Schleife mit diesen Startwerten aufgerufen wird, dann berechnet das Programm alle vier Lösungsvektoren (siehe Listing 6.17):
01 #17_scipy_nichtlinear.py
02 from scipy.optimize import fsolve
03 def f(x):
04 x1,x2=x
05 f1= x1**2 + x2 - 5
06 f2=-x1 + x2**2-5
07 return [f1,f2]
08 print("Lösungsvektoren")
09 start=[-3,-2],[-2,2],[1,3],[2,-3]
10 for k in start:
11 print(fsolve(f,[k]))
Listing 6.17 Lösung mit SciPy
Ausgabe
Lösungsvektoren
[-2.56155281 -1.56155281]
[-1.79128785 1.79128785]
[ 1.56155281 2.56155281]
[ 2.79128785 -2.79128785]
Analyse
Neu an dem SciPy-Programm ist, dass der vollständige Lösungsvektor berechnet wird. Zeile 09 legt die vier Startwerte fest.
Innerhalb der for-Schleife (Zeilen 10 und 11) berechnet die SciPy-Funktion fsolve() die vier Komponenten des Lösungsvektors.
6.3.2 Lösung mit SymPy
Mit SymPy ist der Programmieraufwand geringer, wenn nur die exakten Werte der Lösungen von Interesse sind. Sollen jedoch die Ergebnisse in Gleitpunktzahlen ausgegeben werden, dann steigt der Aufwand erheblich an, weil mit der Methode L.args [i][j] (Zeilen 09 bis 12 in Listing 6.18) auf jedes einzelne Element der SymPy-Datenstruktur FiniteSet() zugegriffen werden muss und die SymPy-Methode N() die einzelnen numerischen Werte der Lösungen berechnen muss. Wenn Sie den Kommentar in Zeile 07 entfernen, dann gibt das Programm auch die genauen Lösungen aus. Allerdings sind diese Werte nicht besonders anschaulich.
01 #18_sympy_nichtlinear.py
02 from sympy import symbols, nonlinsolve, N
03 x1,x2=symbols('x1,x2')
04 f1= x1**2+ x2 -5
05 f2=-x1 + x2**2-5
06 L=nonlinsolve([f1,f2],[x1,x2])
07 #print(L)
08 print(" x1 \t x2")
09 print("(%3.3f | %3.3f)" %(N(L.args[0][0]),N(L.args[0][1])))
10 print("(%3.3f | %3.3f)" %(N(L.args[1][0]),N(L.args[1][1])))
11 print("(%3.3f | %3.3f)" %(N(L.args[2][0]),N(L.args[2][1])))
12 print("(%3.3f | %3.3f)" %(N(L.args[3][0]),N(L.args[3][1])))
Listing 6.18 Lösung mit SymPy
Ausgabe
x1 x2
(-1.791 | 1.791)
(-2.562 | -1.562)
( 1.562 | 2.562)
( 2.791 | -2.791)
Analyse
Die mit der SymPy-Methode nonlinsolve() berechneten Lösungen stimmen mit den von der SciPy-Funktion fsolve() berechneten Werten überein.
Die SymPy-Methode nonlinsolve() hat im Vergleich zur SciPy-Funktion fsolve() den Nachteil, dass bei der numerischen Ausgabe der Aufwand mit zunehmender Anzahl der Gleichungen steigt.