转换用" cls = sympy.Function"生成的符号参数为普通符号

时间:2018-04-04 09:27:37

标签: type-conversion sympy

我想在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类型。

有一种简单的方法可以将systemunknowns转换为此类型吗?我的意思是,如果上面的代码是

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,这样我就可以使用第二个代码版本,这也可以。)

1 个答案:

答案 0 :(得分:1)

几种解决方案:

使用SymPy的开发版

在开发版本(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)]

从SymPy

的未来借用recast_to_symbols

在开发版本中,替换逻辑被隔离到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