UFO ET IT

파이썬을 사용하여 한 쌍의 비선형 방정식을 푸는 방법은 무엇입니까?

ufoet 2020. 12. 4. 21:29
반응형

파이썬을 사용하여 한 쌍의 비선형 방정식을 푸는 방법은 무엇입니까?


파이썬을 사용하여 한 쌍의 비선형 방정식 을 푸는 (가장 좋은) 방법은 무엇입니까? (Numpy, Scipy 또는 Sympy)

예 :

  • x + y ^ 2 = 4
  • e ^ x + xy = 3

위의 쌍을 해결하는 코드 스 니펫이 좋습니다.


수치 솔루션의 경우 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))

원하는 경우 사용할 수 sympy nsolve을 .

>>> nsolve([x+y**2-4, exp(x)+x*y-3], [x, y], [1, 1])
[0.620344523485226]
[1.83838393066159]

첫 번째 인수는 방정식 목록이고 두 번째 인수는 변수 목록이며 세 번째 인수는 초기 추측입니다.


이것을 시도해보십시오. 완벽하게 작동 할 것이라고 확신합니다.

    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

참고로. 위에서 언급했듯이 'fsolve'를 'broyden1'로 대체하여 'Broyden 's approximation'을 사용할 수도 있습니다. 효과가있다. 내가 해냈어.

Broyden의 근사가 어떻게 작동하는지 정확히 모르지만 0.02 초가 걸렸습니다.

그리고 Sympy의 기능을 사용하지 않는 것이 좋습니다. <-실제로 편리하지만 속도면에서는 상당히 느립니다. 당신은 볼 것입니다.


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])

openopt 패키지와 NLP 방법을 사용할 수 있습니다. : 그것은 비선형 대수로 구성된 방정식을 해결하기 위해 많은 동적 프로그래밍 알고리즘이
goldenSection, scipy_fminbound, scipy_bfgs, scipy_cg, scipy_ncg, amsg2p, scipy_lbfgsb, scipy_tnc, bobyqa, ralg, ipopt, scipy_slsqp, scipy_cobyla, lincher, algencan, 당신이 선택할 수 있습니다.
후자의 알고리즘 중 일부는 제한된 비선형 프로그래밍 문제를 해결할 수 있습니다. 따라서 다음 과 같은 함수를 사용하여 방정식 시스템을 openopt.NLP ()에 도입 할 수 있습니다 .

lambda x: x[0] + x[1]**2 - 4, np.exp(x[0]) + x[0]*x[1]


IDL에서 결합 된 비선형 방정식 (일반적으로 다항식 및 지수 포함)에 대해 작동하는 Broyden의 방법을 얻었지만 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]

Broyden의 첫 번째 Jacobian 근사를 사용하여 함수의 근을 찾습니다.

이 방법은 "Broyden의 좋은 방법"이라고도합니다.


대안 fsolveroot다음과 같습니다.

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)

이것은 인쇄됩니다

[0.62034452 1.83838393]

그런 다음 확인하면

print(your_funcs(sol.x))

너는 얻는다

[4.4508396968012676e-11, -1.0512035686360832e-11]

솔루션이 올바른지 확인합니다.


짧은 대답 : fsolve 사용

다른 답변에서 언급했듯이 귀하가 제기 한 특정 문제에 대한 가장 간단한 해결책은 다음과 같은 것을 사용하는 것입니다 fsolve.

from scipy.optimize import fsolve
from math import exp

def f(vars):
    x, y = vars
    eq1 = x+y**2-4
    eq2 = exp(x) + x*y - 3
    return [eq1, eq2]

x, y =  fsolve(equations, (1, 1))

print(x, y)

산출:

0.6203445234801195 1.8383839306750887

분석 솔루션?

You say how to "solve" but there are different kinds of solution. Since you mention SymPy I should point out the biggest difference between what this could mean which is between analytic and numeric solutions. The particular example you have given is one that does not have an (easy) analytic solution but other systems of nonlinear equations do. When there are readily available analytic solutions SymPY can often find them for you:

In [29]: from sympy import *                                                                                                                                  

In [30]: x, y = symbols('x, y')                                                                                                                               

In [31]: eq1 = Eq(x+y**2, 4)                                                                                                                                  

In [32]: eq2 = Eq(x**2 + y, 4)                                                                                                                                

In [33]: solve([eq1, eq2], [x, y])                                                                                                                            
Out[33]: 
⎡⎛ ⎛  5   √17⎞ ⎛3   √17⎞    √17   1⎞  ⎛ ⎛  5   √17⎞ ⎛3   √17⎞    1   √17⎞  ⎛ ⎛  3   √13⎞ ⎛√13   5⎞  1   √13⎞  ⎛ ⎛5   √13⎞ ⎛  √13   3⎞  1   √13⎞⎤
⎢⎜-⎜- ─ - ───⎟⋅⎜─ - ───⎟, - ─── - ─⎟, ⎜-⎜- ─ + ───⎟⋅⎜─ + ───⎟, - ─ + ───⎟, ⎜-⎜- ─ + ───⎟⋅⎜─── + ─⎟, ─ + ───⎟, ⎜-⎜─ - ───⎟⋅⎜- ─── - ─⎟, ─ - ───⎟⎥
⎣⎝ ⎝  2    2 ⎠ ⎝2    2 ⎠     2    2⎠  ⎝ ⎝  2    2 ⎠ ⎝2    2 ⎠    2    2 ⎠  ⎝ ⎝  2    2 ⎠ ⎝ 2    2⎠  2    2 ⎠  ⎝ ⎝2    2 ⎠ ⎝   2    2⎠  2    2 ⎠⎦

Note that in this example SymPy finds all solutions and does not need to be given an initial estimate.

Precision of numeric solutions

However most systems of nonlinear equations will not have a suitable analytic solution so using SymPy as above is great when it works but not generally applicable. That is why we end up looking for numeric solutions even though with numeric solutions: 1) We have no guarantee that we have found all solutions or the "right" solution when there are many. 2) We have to provide an initial guess which isn't always easy.

Having accepted that we want numeric solutions something like fsolve will normally do all you need. For this kind of problem SymPy will probably be much slower but it can offer something else which is finding the (numeric) solutions more precisely:

In [50]: from sympy import *                                                                                                                                  

In [51]: x, y = symbols('x, y')                                                                                                                               

In [52]: nsolve([Eq(x+y**2, 4), Eq(exp(x)+x*y, 3)], [x, y], [1, 1])                                                                                           
Out[52]: 
⎡0.620344523485226⎤
⎢                 ⎥
⎣1.83838393066159 ⎦

In [53]: nsolve([Eq(x+y**2, 4), Eq(exp(x)+x*y, 3)], [x, y], [1, 1], prec=50)                                                                                  
Out[53]: 
⎡0.62034452348522585617392716579154399314071550594401⎤
⎢                                                    ⎥
⎣ 1.838383930661594459049793153371142549403114879699 ⎦

참고URL : https://stackoverflow.com/questions/8739227/how-to-solve-a-pair-of-nonlinear-equations-using-python

반응형