scipy 如何将可调用函数添加到症状表达式

nfeuvbwi  于 2022-11-10  发布在  其他
关注(0)|答案(2)|浏览(107)

如果我有一个表达式x = Symbol('x')f1=x**2,我想再加上一些f2,其中f2 = interp1d(t, y)是一个快速插值,我们如何把f2变成一个表达式,这样我就有了类似f = x**2 + f2(x)的东西,这样我就可以把f求值为f.subs(x, some_number)了?
由于代码规范的原因,我不能分别计算f1f2,然后将结果相加,我需要能够将其添加到现有的sympy表达式中,并使用类似.subs()的表达式进行计算

ztmd8pv5

ztmd8pv51#

一种方法,但需要硬编码要在类中调用的函数:

f2 = lambda t: np.sin(t)

class MyFunc(Function):
    @classmethod
    def eval(cls, arg):
        arg = sympify(arg, strict=True)
        if arg.is_Number:
            return sympify(f2(float(arg)), strict=True)

更像是Davide的回答,但有几个修正:

class FuncWrapper(Symbol):
    """Wraps a python callable as a Basic instance"""
    def __new__(cls, func, name):
        obj = super().__new__(cls, name)
        obj._wrapped = func
        return obj

    @property
    def wrapped(self):
        return self._wrapped

    def _hashable_content(self):
        return (self.wrapped,) # needed for __eq__

    def eval(self, arg):
        if arg.is_Number:
            return sympify(self.wrapped(float(arg)))

    def __call__(self, arg):
        return Call(self, arg)

class Call(Function):
    @classmethod
    def eval(cls, func, arg):
        arg = sympify(arg)

        result = func.eval(arg)
        if result is not None:
            return result

有了它,你就有了:

In [61]: f = FuncWrapper(np.sin, 'f')

In [62]: x + f(x)
Out[62]: x + Call(f, x)

In [63]: _.subs(x, 1)
Out[63]: 1.84147098480790
b09cbbtk

b09cbbtk2#

一种非常危险的方法是为数值函数创建一个 Package 对象,如下所示:

from sympy import *
import numpy as np
var("x")

# symbolic expression

f1 = cos(x)

# numerical function

f2 = lambda t: np.sin(t)

class MyFunc(Expr):
    """Create a symbolic wrapper to a numerical function."""

    def __new__(cls, arg,**kwargs):
        obj = Expr.__new__(cls,**kwargs)
        obj._custom_func = arg
        return obj

    def _subs(self, old, new,**hints):
        return self._custom_func(float(new))

expr = f1 + MyFunc(f2)
expr.subs(x, np.pi/4)

# out: 1.41421356237309

相关问题