如何获得表达式(a [0] * b [0])之类的所有基数(a,b)?

时间:2019-04-25 15:21:10

标签: python sympy

最近,我重新安装了anaconda和sympy。然后,我运行以下示例的相同代码,这给了我错误。 (我之前没有这样的错误)

import sympy as sp
a, b= sp.symbols('a b', cls=sp.IndexedBase)
l= sp.symbols('l', cls=sp.Wild)

def Bfunc(expr,p1,p2):
    if expr.base==p1:return expr.replace(p1[l],0.2*(p2[l]+p1[-l]),map=False, simultaneous=True, exact=True)
    else: return expr.replace(p2[l],0.2*(p1[l]+p2[-l]),map=False, simultaneous=True, exact=True)      

inputstate=a[0]*b[0]
psi0=inputstate.replace(lambda expr: expr.base in [a,b], lambda expr: Bfunc(expr,a,b))

它给了我错误:

enter image description here

问题是 expr.base ,它不能给出基数 a b

让我们看一个非常简单的示例:

import sympy as sp
a, b= sp.symbols('a b', cls=sp.IndexedBase)
l= sp.symbols('l', cls=sp.Wild)    

inputstate=a[0]*b[0]
inputstate.base

错误:

Traceback (most recent call last):

  File "<ipython-input-59-7cc51ba4a4cd>", line 6, in <module>
    inputstate.base

AttributeError: 'Mul' object has no attribute 'base'

如果 inputstate = a [0] ,则 inputstate.base 给您 < em> a

所以我想知道为什么在重新安装sympy和anaconda之后会发生这种错误。还是有任何方法可以提供所有基本列表并修复错误?

如果有人有类似情况,请给我一些提示,这将非常酷。预先谢谢你!

3 个答案:

答案 0 :(得分:2)

您的foo函数在遇到属性错误时返回None,并向replace发出信号,表明该节点不应执行任何操作。当您使用lambda时,没有任何东西可以捕获该错误,因此该过程会引起您的注意。一种选择是更改replace,使其忽略错误并仅跳过节点。但是,这样做的好处是,它提醒您以下事实:您在做某事时会丢失要处理的对象。因此,要使用lambda,您必须帮助其成功识别感兴趣的条款。

>>> L1 = lambda x: x.is_Pow and x.base in [a, b]
>>> inputstate.replace(L1, lambda expr: Bfunc(expr,a,b))
a[0]*b[0]
>>> L2 = lambda x: x.as_base_exp()[0] in [a, b]
>>> inputstate.replace(L1, lambda expr: Bfunc(expr,a,b))
a[0]*b[0]

(我更喜欢L1,因为它使用快速is_Pow测试来知道一个人是否正在处理电源。您的Bfunc假定它正在处理电源,因此L2不适用于所有情况,除非您还修改 it 来处理非战俘案件。)

要回答的一个问题是,您是要针对实际幂还是对幂为1的“幂”。例如,如果要将所有幂的指数提高1,您是否要x*y**2 -> x**2*y**3还是只x*y**3? L1适用于第一种情况,L2适用于第二种情况。

答案 1 :(得分:0)

aIndexedBase,而a[0]Indexed对象,其base is a`:

In [21]: type(a)                                                                
Out[21]: sympy.tensor.indexed.IndexedBase
In [22]: type(a[0])                                                             
Out[22]: sympy.tensor.indexed.Indexed
In [23]: a[0].base                                                              
Out[23]: a

In [25]: inputstate=a[0]*b[0]                                                   
In [26]: inputstate                                                             
Out[26]: a[0]*b[0]
In [27]: type(inputstate)                                                       
Out[27]: sympy.core.mul.Mul

inputstateMul expr对象。它不是Indexed,所以没有基数。

您在sympy的早期版本中是否有“正确”行为的记录,或者文档中有某种更改的证据。它在哪个版本上工作?

您的Bfuncreplace似乎对我有用:

In [51]: ab = inputstate.replace(lambda expr: expr.base in [a,b], lambda expr: Bfunc(expr,a,b))                                                        
In [52]: ab                                                                     
Out[52]: a[0]*b[0]
In [53]: type(ab)                                                               
Out[53]: sympy.core.mul.Mul

我应该看到什么变化?

In [55]: sp.__version__                                                         
Out[55]: '1.3'

如果我通过一个小的函数来更改replace lambda:

In [71]: def foo(expr): 
    ...:     try: 
    ...:         print(expr, expr.base) 
    ...:         return expr.base in [a,b] 
    ...:     except AttributeError: 
    ...:         print(expr) 
    ...:          
    ...:                                                                        
In [72]: ab = inputstate.replace(foo, lambda expr: Bfunc(expr,a,b))             
a
a
0
a[0] a
b
b
0
b[0] b
a[0]*b[0]

似乎replaceexpr的各种元素传递给此函数。诸如此类AttributeError的错误将被忽略。

1.4发行说明包含有关replace及其参数exact的信息。我不知道使用exact=False是否可以解决1.4中的问题(如果不进行评分,我将无法对其进行测试)。

https://docs.sympy.org/latest/modules/core.html#sympy.core.basic.Basic.replace

答案 2 :(得分:0)

让我们说以下代码:

import sympy as sp
a, b= sp.symbols('a b', cls=sp.IndexedBase)
l= sp.symbols('l', cls=sp.Wild)

def Bfunctest(expr,p1,p2):
    if expr.base==p1:return expr.replace(p1[l],0.2*p1[-l],map=False, simultaneous=True, exact=False)
    else: return expr.replace(p2[l],0.2*p2[-l],map=False, simultaneous=True, exact=False)

L1 = lambda expr: expr.is_Pow and expr.base in [a, b]
inputstate=a[1]*b[1]
out=inputstate.replace(L1, lambda expr: Bfunctest(expr,a,b))

输出为a[1]*b[1]而不是0.04*a[-1]*b[-1],这意味着不排除 Bfunctest()

因为inputstate.is_Pow and inputstate.base in [a, b]给您。当您使用inputstate.as_base_exp()[0] in [a, b]时,会出现 False 的情况。因此,不会排除 Bfunctest()