SymPy替换方法与Wild无法正确识别指数

时间:2018-04-23 22:12:06

标签: python sympy

我使用SymPy来识别和替换模式,并且效果很好。例如:

import sympy as sym
mu = sym.symbols('mu')

a=sym.Wild('a')
b=sym.Wild('b')
c=sym.Wild('c')

现在

I1=36*sym.exp(12)*mu**2
I1.replace(c*sym.exp(b)*mu**a,a,exact=True)

返回2.但是当我试图识别简单的电源功能时,我有这个:

I2=36*mu**2
I2.replace(c*mu**a,a,exact=True)

返回36.奇怪的结果,但是:

I2.replace(c*mu**a,c,exact=True)
I2.replace(c*mu**a,a*c,exact=True)

也会返回36。 然后我发现了下一个:

I2.replace(c*b**a,a,exact=True)
1
I2.replace(c*b**a,b,exact=True)
mu
I2.replace(c*b**a,c,exact=True)
1

所以为什么同情这样做,如果它是一个bug我可以让它以某种方式工作。我当然在等待这个结果:

I2.replace(c*b**a,a,exact=True)
2

下一个例子是

I2=12*mu**2 
I2.match(c*mu**2)
{c_: 12}

I2.replace(c*mu**2,c)
12*(1/mu)**(2/mu**2)/mu**2

我使用python 3.6.5和sympy 1.1.1。

1 个答案:

答案 0 :(得分:0)

匹配

要识别模式,请使用match方法:

I2.match(c*b**a)  # {a_: 2, c_: 36}
I2.match(c*mu**a)   #  {a_: 2, b_: mu, c_: 36}

可以从字典中检索特定值:I2.match(c*b**a)[a]返回2。

替换

使用replace的方法存在问题,因为SymPy可能会找到子表达式并替换它们,而忽略了更大的结构。例如,

I2.replace(c*mu**a, sym.sin(a) + sym.cos(c), exact=True) 

返回36*(cos(1) + sin(1))**2。在这里,我们看到mu本身与模式a=1c=1匹配,并被替换为。

您的示例也是如此:子表达式mu1*mu**1匹配,并替换为1,而36*1**2为36。

可以通过从Wild 的可能值中排除1来避免这种情况:

>>> a = sym.Wild('a', exclude=[1])
>>> c = sym.Wild('c', exclude=[1])
>>> I2.replace(c*mu**a, a, exact=True)
2

exact=True标志确保“只有在匹配模式中出现的每个Wild收到非零值时匹配才会成功”,这仍然允许值为1.具体排除1个修复那。

I2=12*mu**2的示例中,替换I2.replace(c*mu**2, c)找到了多个匹配项。例如,指数2与模式匹配,因为2 = (2/mu**2) * mu**2其中括号中的表达式被视为c。为防止这种情况,请指明c不应包含mu:

>>> c=sym.Wild('c', exclude=[mu])
>>> I2.replace(c*mu**2, c)
12