我想在sympy
的帮助下解决非线性方程组。不幸的是,这是我的设置
import sympy
x = sympy.Symbol('x')
f,g,h= sympy.symbols("f g h", cls=sympy.Function)
#here I do some computations to arrive at the equations below
eq1 = 2*f(x)*g(x)-h(x)
eq2 = f(x)**2+h(x)*g(x)
system = [eq1,eq2]
unknowns = [f(x),h(x)]
我想为f(x)
和h(x)
解决这个玩具示例,但sypmy.nonlinsolve(system,unknowns)
不起作用,因为它期望系统和未知系统为symbol
并且不是Function
类型。
有一种简单的方法可以将system
和unknowns
转换为此类型吗?我的意思是,如果上面的代码是
import sympy
x = sympy.Symbol('x')
f,g,h= sympy.symbols("f g h")
#here I do some computations to arrive at the equations below
eq1 = 2*f*g-h
eq2 = f**2+h*g
system = [eq1,eq2]
unknowns = [f,h]
这将完美地运作。如何将f,g,h
转换为此类型?
(使用第二个代码不是一个选项,因为我通过使用区分来得出那些方程式,所以我需要cls=sympy.Function
参数;或者,如果有人知道如何区分symbols
,这样我就可以使用第二个代码版本,这也可以。)
答案 0 :(得分:1)
几种解决方案:
在开发版本(GitHub)中,这开箱即用;它在内部用符号替换函数。
>>> sympy.nonlinsolve(system, unknowns)
{(0, 0), (-2*g(x)**2, -4*g(x)**3)}
solve
在当前版本的SymPy 1.1.1中已经进行了函数符号交换。
sympy.solve(system, unknowns)
返回[(0, 0), (-2*g(x)**2, -4*g(x)**3)]
在开发版本中,替换逻辑被隔离到recast_to_symbols
函数中。
from sympy.solvers.solvers import recast_to_symbols
e, s, d = recast_to_symbols(systems, unknowns)
print(e, s, d)
打印
[2*_X0*g(x) - _X1, _X0**2 + _X1*g(x)] [_X0, _X1] {_X0: f(x), _X1: h(x)}
这里e是新的等式,是新符号,d是用于恢复原始事物的字典。想法是可以使用
sympy.nonlinsolve(e, s).xreplace(d)
获得解决方案。 (实际上,甚至不需要您的示例xreplace
,因为解决方案不包含任何替换的符号。)
如果您不想使用开发版本,一个简单的解决方案是从source on GitHub复制功能:
def recast_to_symbols(eqs, symbols):
"""Return (e, s, d) where e and s are versions of eqs and
symbols in which any non-Symbol objects in symbols have
been replaced with generic Dummy symbols and d is a dictionary
that can be used to restore the original expressions.
Examples
========
>>> from sympy.solvers.solvers import recast_to_symbols
>>> from sympy import symbols, Function
>>> x, y = symbols('x y')
>>> fx = Function('f')(x)
>>> eqs, syms = [fx + 1, x, y], [fx, y]
>>> e, s, d = recast_to_symbols(eqs, syms); (e, s, d)
([_X0 + 1, x, y], [_X0, y], {_X0: f(x)})
The original equations and symbols can be restored using d:
>>> assert [i.xreplace(d) for i in eqs] == eqs
>>> assert [d.get(i, i) for i in s] == syms
"""
from sympy import Dummy, Symbol
from sympy.core.compatibility import iterable
if not iterable(eqs) and iterable(symbols):
raise ValueError('Both eqs and symbols must be iterable')
new_symbols = list(symbols)
swap_sym = {}
for i, s in enumerate(symbols):
if not isinstance(s, Symbol) and s not in swap_sym:
swap_sym[s] = Dummy('X%d' % i)
new_symbols[i] = swap_sym[s]
new_f = []
for i in eqs:
try:
new_f.append(i.subs(swap_sym))
except AttributeError:
new_f.append(i)
swap_sym = {v: k for k, v in swap_sym.items()}
return new_f, new_symbols, swap_sym