如果我有一个表达式x = Symbol('x')和f1=x**2,我想再加上一些f2,其中f2 = interp1d(t, y)是一个快速插值,我们如何把f2变成一个表达式,这样我就有了类似f = x**2 + f2(x)的东西,这样我就可以把f求值为f.subs(x, some_number)了?由于代码规范的原因,我不能分别计算f1和f2,然后将结果相加,我需要能够将其添加到现有的sympy表达式中,并使用类似.subs()的表达式进行计算
x = Symbol('x')
f1=x**2
f2
f2 = interp1d(t, y)
f = x**2 + f2(x)
f
f.subs(x, some_number)
f1
.subs()
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
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
2条答案
按热度按时间ztmd8pv51#
一种方法,但需要硬编码要在类中调用的函数:
更像是Davide的回答,但有几个修正:
有了它,你就有了:
b09cbbtk2#
一种非常危险的方法是为数值函数创建一个 Package 对象,如下所示: