Numpy 如何在Python中求解未知成员相乘的非线性方程组?

Numpy 如何在Python中求解未知成员相乘的非线性方程组?,numpy,math,scipy,Numpy,Math,Scipy,我有以下非线性方程组: 这与Cholesky的分解非常相似,但不幸的是它不是 我已经找到了非常熟悉的解决方案:但我不知道如何动态设置系统的所有方程 如何在Numpy、Scipy或Python中的任何其他软件包中求解此系统?以下是一个函数,可根据系统中的描述动态设置方程式: import sympy as sp def not_choleskys_decomposition(N): # Initialisation of list of variables. c = []

我有以下非线性方程组:

这与Cholesky的分解非常相似,但不幸的是它不是

我已经找到了非常熟悉的解决方案:但我不知道如何动态设置系统的所有方程

如何在Numpy、Scipy或Python中的任何其他软件包中求解此系统?

以下是一个函数,可根据系统中的描述动态设置方程式:

import sympy as sp

def not_choleskys_decomposition(N):
    # Initialisation of list of variables.
    c = []
    K = []
    for n in range(N + 1):
        c.append(sp.Symbol("c_{}".format(n), real=True))
        K.append(sp.Symbol("K_{}".format(n), real=True))

    # Setup your N+1 equations.
    equations = []
    for n in range(N + 1):
        num_c = N + 1 - n
        c_terms = [c_i * c_j for c_i, c_j in zip(c[:num_c], c[n:][:num_c])]
        lhs = sp.Add(*c_terms)
        equations.append(sp.Eq(lhs, K[n]))
    return equations, c, K
打印验证可使用将数学直接转换为latex的
sympy.latex
函数或
sympy.pprint
函数完成

>>> test, _, _ = not_choleskys_decomposition(4)
>>> for t in test:
...    sp.pprint(t)

c₀⋅c₀ + c₁⋅c₁ + c₂⋅c₂ + c₃⋅c₃ + c₄⋅c₄ = K₀
c₀⋅c₁ + c₁⋅c₂ + c₂⋅c₃ + c₃⋅c₄ = K₁
c₀⋅c₂ + c₁⋅c₃ + c₂⋅c₄ = K₂
c₀⋅c₃ + c₁⋅c₄ = K₃
c₀⋅c₄ = K₄

可以使用属于每个
sympy.Eq
对象的
.subs
方法替换变量:

>>> equations, c_sym, K_sym = not_choleskys_decomposition(4)
>>> dict_replace = {c_sym[0]: 1.0}
>>> new_equation = equations[0].subs(dict_replace)
>>> sympy.pprint(new_equation)

c₁⋅c₂ + 1.0⋅c₁ + c₂⋅c₃ + c₃⋅c₄ = K₁

下面是一个示例函数,用于替换
c
K
的列表

def substitute_sym(equations, sym_list, val_list):
    # Confirm all dimensions are consistent.
    try:
        assert len(equations) == len(sym_list) == len(val_list)
    except AssertionError:
        raise IndexError("Inconsistent dimensions.")

    # Replace c symbols with values in equations.
    substituted_equations = []
    for eq in equations:
        _eq = eq.subs(dict(zip(sym_list, val_list)))
        substituted_equations.append(_eq)

    return substituted_equations
c
上测试它:

K
上测试它:

可以使用
sympy.solvers.solveset.nonlinsolve(系统,*符号)

求解给定的
K
c

如果您选择使用它,我希望这有助于您开始使用
SymPy
。我很少使用它的非线性解算器,所以我不能保证任何超过示例的东西。争论也是相关的,解决问题的人脾气暴躁。您会注意到,对于每个索引,我将
K
替换为
sp.Rational(0.5)
。这样做是为了避免在为某些解算器定义
float
类型时抛出错误。祝你好运

编辑:

还请注意,您不需要在Symphy中使用解算器。我很少这样做。我使用Python中的符号数学包进行LaTeX和方程操作

编辑:

使其与
scipy.optimize.fsolve一起工作

from sympy.utilities.lambdify import lambdify
from scipy.optimize import fsolve


def lambdify_equations_for_solving_c(equations, c_sym, K_sym, K_val):
    f = []
    equations_subbed = substitute_sym(equations, K_sym, K_val)
    for eq in equations_subbed:
        # Note that I reformulate equation into an expression here
        # for determining the roots.
        f.append(lambdify(c_sym, eq.args[0] - eq.args[1]))
    return f


N = 4
equations, c_sym, K_sym = not_choleskys_decomposition(N)
K_vals = [0.1, 0, 0.1, 0, 0]
f = lambdify_equations_for_solving_c(equations, c_sym, K_sym, K_vals)

def fsolve_friendly(p):
    return [_f(*p) for _f in f]

c_sol = fsolve(fsolve_friendly, x0=(0, 0.1, -1.1, 0, 0))
fsolve
返回非收敛结果的警告

/home/ggarrett/anaconda3/envs/sigh/lib/python3.7/site-packages/scipy/optimize/minpack.py:162: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last five Jacobian evaluations.
  warnings.warn(msg, RuntimeWarning)


这是一个完整的答案,说明了如何将方程作为python可调用函数进行求解。解算程序本身就是另一个挑战。

对此我不确定。这些方程是一个多项式系统,所以我想知道关于5次或更高的一般多项式在根方面不可解的问题是否会起作用。也许可以证明,在这个特殊的例子中,所有N都有一个解,但我想我建议在寻找符号解之前先研究这个问题。为我不平衡的回答道歉。我更专注于帮助OP创建方程组。我在我的答案中添加了更多内容,使之能够成为一个函数,并与fsolve一起使用。fsolve的结果并不乐观,但这是我在编程方面能提供的最全面的帮助——数学是另一个。嗯,这是一个有趣的问题。你需要符号解还是数值解?(你解决这个问题的目的是什么?)?
>>> from sympy.solvers.solveset import nonlinsolve
>>> test_solve, c_sym, K_sym = not_choleskys_decomposition(1)
>>> test_replaced = substitute_sym(test_solve, K_sym, [sp.Rational(0.5)] * 2)
>>> solved = nonlinsolve(test_replaced, c_sym)
>>> sp.pprint(solved)

⎧⎛ ⎛                    2⎞                           ⎞  ⎛ ⎛                   
⎪⎜ ⎜       ⎛  √6   √2⋅ⅈ⎞ ⎟ ⎛  √6   √2⋅ⅈ⎞    √6   √2⋅ⅈ⎟  ⎜ ⎜       ⎛  √6   √2⋅ⅈ
⎨⎜-⎜-1 + 2⋅⎜- ── - ────⎟ ⎟⋅⎜- ── - ────⎟, - ── - ────⎟, ⎜-⎜-1 + 2⋅⎜- ── + ────
⎪⎝ ⎝       ⎝  4     4  ⎠ ⎠ ⎝  4     4  ⎠    4     4  ⎠  ⎝ ⎝       ⎝  4     4  
⎩                                                                             

 2⎞                           ⎞  ⎛ ⎛                  2⎞                      
⎞ ⎟ ⎛  √6   √2⋅ⅈ⎞    √6   √2⋅ⅈ⎟  ⎜ ⎜       ⎛√6   √2⋅ⅈ⎞ ⎟ ⎛√6   √2⋅ⅈ⎞  √6   √2⋅
⎟ ⎟⋅⎜- ── + ────⎟, - ── + ────⎟, ⎜-⎜-1 + 2⋅⎜── - ────⎟ ⎟⋅⎜── - ────⎟, ── - ───
⎠ ⎠ ⎝  4     4  ⎠    4     4  ⎠  ⎝ ⎝       ⎝4     4  ⎠ ⎠ ⎝4     4  ⎠  4     4 


 ⎞  ⎛ ⎛                  2⎞                       ⎞⎫
ⅈ⎟  ⎜ ⎜       ⎛√6   √2⋅ⅈ⎞ ⎟ ⎛√6   √2⋅ⅈ⎞  √6   √2⋅ⅈ⎟⎪
─⎟, ⎜-⎜-1 + 2⋅⎜── + ────⎟ ⎟⋅⎜── + ────⎟, ── + ────⎟⎬
 ⎠  ⎝ ⎝       ⎝4     4  ⎠ ⎠ ⎝4     4  ⎠  4     4  ⎠⎪
                                                   ⎭


from sympy.utilities.lambdify import lambdify
from scipy.optimize import fsolve


def lambdify_equations_for_solving_c(equations, c_sym, K_sym, K_val):
    f = []
    equations_subbed = substitute_sym(equations, K_sym, K_val)
    for eq in equations_subbed:
        # Note that I reformulate equation into an expression here
        # for determining the roots.
        f.append(lambdify(c_sym, eq.args[0] - eq.args[1]))
    return f


N = 4
equations, c_sym, K_sym = not_choleskys_decomposition(N)
K_vals = [0.1, 0, 0.1, 0, 0]
f = lambdify_equations_for_solving_c(equations, c_sym, K_sym, K_vals)

def fsolve_friendly(p):
    return [_f(*p) for _f in f]

c_sol = fsolve(fsolve_friendly, x0=(0, 0.1, -1.1, 0, 0))
/home/ggarrett/anaconda3/envs/sigh/lib/python3.7/site-packages/scipy/optimize/minpack.py:162: RuntimeWarning: The iteration is not making good progress, as measured by the 
  improvement from the last five Jacobian evaluations.
  warnings.warn(msg, RuntimeWarning)