Quel est le meilleur moyen de résoudre une paire d'équations non linéaires utilisant Python. (Numpy, Scipy ou Sympy)
par exemple:
- x + y ^ 2 = 4
- e ^ x + xy = 3
Un extrait de code qui résout la paire ci-dessus sera formidable
pour une solution numérique, vous pouvez utiliser fsolve:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html#scipy.optimize.fsolve
from scipy.optimize import fsolve
import math
def equations(p):
x, y = p
return (x+y**2-4, math.exp(x) + x*y - 3)
x, y = fsolve(equations, (1, 1))
print equations((x, y))
Si vous préférez sympy, vous pouvez utiliser nsolve .
>>> nsolve([x+y**2-4, exp(x)+x*y-3], [x, y], [1, 1])
[0.620344523485226]
[1.83838393066159]
Le premier argument est une liste d'équations, le second est une liste de variables et le troisième est une supposition initiale.
Essayez celui-ci, je vous assure que cela fonctionnera parfaitement.
import scipy.optimize as opt
from numpy import exp
import timeit
st1 = timeit.default_timer()
def f(variables) :
(x,y) = variables
first_eq = x + y**2 -4
second_eq = exp(x) + x*y - 3
return [first_eq, second_eq]
solution = opt.fsolve(f, (0.1,1) )
print(solution)
st2 = timeit.default_timer()
print("RUN TIME : {0}".format(st2-st1))
->
[ 0.62034452 1.83838393]
RUN TIME : 0.0009331008900937708
FYI. Comme mentionné ci-dessus, vous pouvez également utiliser «approximation de Broyden» en remplaçant «fsolve» par «broyden1». Ça marche. Je l'ai fait.
Je ne sais pas exactement comment fonctionne l'approximation de Broyden, mais cela a pris 0,02 s.
Et je vous recommande de ne pas utiliser les fonctions de Sympy <- pratique en effet, mais en termes de vitesse, elle est assez lente. Tu verras.
from scipy.optimize import fsolve
def double_solve(f1,f2,x0,y0):
func = lambda x: [f1(x[0], x[1]), f2(x[0], x[1])]
return fsolve(func,[x0,y0])
def n_solve(functions,variables):
func = lambda x: [ f(*x) for f in functions]
return fsolve(func, variables)
f1 = lambda x,y : x**2+y**2-1
f2 = lambda x,y : x-y
res = double_solve(f1,f2,1,0)
res = n_solve([f1,f2],[1.0,0.0])
La méthode de Broyden a fonctionné pour les équations non linéaires couplées (impliquant généralement des polynômes et des exponentielles) en IDL, mais je ne l'ai pas essayée en Python:
scipy.optimize.broyden1
scipy.optimize.broyden1(F, xin, iter=None, alpha=None, reduction_method='restart', max_rank=None, verbose=False, maxiter=None, f_tol=None, f_rtol=None, x_tol=None, x_rtol=None, tol_norm=None, line_search='armijo', callback=None, **kw)[source]
Trouvez la racine d’une fonction en utilisant la première approximation jacobienne de Broyden.
Cette méthode est également connue sous le nom de «bonne méthode de Broyden».
Une alternative à fsolve
est root
:
import numpy as np
from scipy.optimize import root
def your_funcs(X):
x, y = X
# all RHS have to be 0
f = [x + y**2 - 4,
np.exp(x) + x * y - 3]
return f
sol = root(your_funcs, [1.0, 1.0])
print(sol.x)
Cela va imprimer
[0.62034452 1.83838393]
Si vous vérifiez alors
print(your_funcs(sol.x))
vous obtenez
[4.4508396968012676e-11, -1.0512035686360832e-11]
confirmant que la solution est correcte.