Подтвердить что ты не робот

Как решить пару нелинейных уравнений с использованием Python?

Каков наилучший способ решения пары нелинейных уравнений с использованием Python. (Numpy, Scipy или Sympy)

например:

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

Фрагмент кода, который решает вышеупомянутую пару, будет отличным

4b9b3361

Ответ 2

Если вы предпочитаете sympy, вы можете использовать nsolve.

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

Первый аргумент - это список уравнений, второй - список переменных, а третий - исходное предположение.

Ответ 3

Попробуйте это, я заверяю вас, что он будет работать отлично.

    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. как упоминалось выше, вы также можете использовать "приближение Бройдена", заменив "fsolve" на "broyden1". Оно работает. Я сделал это.

Я точно не знаю, как работает приближение Бройдена, но это заняло 0,02 с.

И я рекомендую вам не использовать функции Sympy < - удобно, но с точки зрения скорости это довольно медленно. Ты увидишь.

Ответ 4

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

Ответ 5

Вы можете использовать пакет 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]

Ответ 6

Я получил метод Бройдена для работы с связанными нелинейными уравнениями (как правило, с участием многочленов и экспонент) в IDL, но я не пробовал его в 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]

Найти корень функции, используя первое приближение Я. Я. Брайденса.

Этот метод также известен как "хороший метод Бройденса".

Ответ 7

Альтернативой fsolve является 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)

Это напечатает

[0.62034452 1.83838393]

Если вы затем проверите

print(your_funcs(sol.x))

вы получаете

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

подтверждая правильность решения.

Ответ 8

Краткий ответ: используйте 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

Аналитические решения?

Вы говорите, как "решить", но есть разные варианты решения. Поскольку вы упоминаете SymPy, я должен указать на самое большое различие между тем, что это может означать, а именно между аналитическими и числовыми решениями. Конкретный пример, который вы привели, не имеет (простого) аналитического решения, как другие системы нелинейных уравнений. Когда есть доступные аналитические решения, SymPY часто может найти их для вас:

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 ⎠⎦

Обратите внимание, что в этом примере SymPy находит все решения и не требует предварительной оценки.

Точность числовых решений

Однако большинство систем нелинейных уравнений не будет иметь подходящего аналитического решения, поэтому использование SymPy, как описано выше, прекрасно, когда оно работает, но не всегда применимо. Вот почему мы в конечном итоге ищем числовые решения, хотя и с числовыми решениями: 1) У нас нет гарантии, что мы нашли все решения или "правильное" решение, когда их много. 2) Мы должны предоставить первоначальное предположение, которое не всегда легко.

Приняв, что нам нужны числовые решения, что-то вроде fsolve, как правило, сделает все, что вам нужно. Для такого рода проблем SymPy, вероятно, будет намного медленнее, но он может предложить что-то еще, что более точно находит (числовые) решения:

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 ⎦