web-dev-qa-db-fra.com

Comment résoudre une paire d'équations non linéaires en utilisant Python?

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

55
AIB

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))
61
HYRY

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. 

27
Krastanov

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. 

2
Dane Lee
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])
2
Victor

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:

http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.broyden1.html#scipy.optimize.broyden1

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».

1
Kevin H

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.

0
Cleb