同情中的一般表达替换

时间:2017-07-28 21:13:16

标签: sympy

我有两个单变量函数f(x)g(x),我想用g(x) = y替换f(x)作为某些f2(y)

这是一个有效的简单示例:

In [240]: x = Symbol('x')

In [241]: y = Symbol('y')

In [242]: f = abs(x)**2 + 6*abs(x) + 5

In [243]: g = abs(x)

In [244]: f.subs({g: y})
Out[244]: y**2 + 6*y + 5

但是现在,如果我尝试一个稍微复杂的例子,那就失败了:

In [245]: h = abs(x) + 1

In [246]: f.subs({h: y})
Out[246]: Abs(x)**2 + 6*Abs(x) + 5

是否存在适用于此问题的一般方法?

1 个答案:

答案 0 :(得分:4)

表达式abs(x)**2 + 6*abs(x) + 5实际上并不包含abs(x) + 1,因此无法替代。

可以想象将其更改为abs(x)**2 + 5*(abs(x) + 1) + abs(x),替换结果为abs(x)**2 + 5*y + abs(x)。或者可能将其更改为abs(x)**2 + 6*(abs(x) + 1) - 1,结果为abs(x)**2 + 6*y - 1。还有其他选择。结果应该是什么?

此任务没有通用的方法,因为它不是一个明确定义的任务。

相反,替换f.subs(abs(x), y-1)是一个明确的指令,用y-1替换表达式树中所有出现的abs(x)。它返回6*y + (y - 1)**2 - 1

除了subs之外,SymPy还有一个支持通配符的方法.replace,但我不希望它在这里提供帮助。根据我的经验,它过于急于取代:

>>> a = Wild('a')
>>> b = Wild('b')
>>> f.replace(a*(abs(x) + 1) + b, a*y + b)
5*y/(Abs(x) + 1) + 6*y*Abs(x*y)/(Abs(x) + 1)**2 + (Abs(x*y)/(Abs(x) + 1))**(2*y/(Abs(x) + 1))   

消除变量

没有"消除"在SymPy。可以尝试通过引入另一个变量(例如,

)来使用solve来模拟它
fn = Symbol('fn')
solve([Eq(fn,  f), Eq(abs(x) + 1, y)], [fn, x])

试图解决" fn"和" x",因此" fn"的解决方案是没有x的表达式。 如果有效

事实上,它不适用于abs();在SymPy中没有实现解决绝对值内的东西。这是一种解决方法。

fn, ax = symbols('fn ax')
solve([Eq(fn,  f.subs(abs(x), ax)), Eq(ax + 1, y)], [fn, ax]) 

这会输出[(y*(y + 4), y - 1)],其中第一个词是你想要的; fn的解决方案。

相关问题