Python 如何获取表达式(如(a[0]*b[0])的所有基(a,b)?

Python 如何获取表达式(如(a[0]*b[0])的所有基(a,b)?,python,sympy,Python,Sympy,最近我重新安装了水蟒和sympy。然后我运行与下面相同的代码,这会给我带来错误。(我以前没有这样的错误) 它给了我一个错误: 问题是expr.base,它不能给出basea或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 错误: Tr

最近我重新安装了水蟒和sympy。然后我运行与下面相同的代码,这会给我带来错误。(我以前没有这样的错误)

它给了我一个错误:

问题是expr.base,它不能给出baseab

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

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'

回溯(最近一次呼叫最后一次):
文件“”,第6行,在
inputstate.base
AttributeError:“Mul”对象没有属性“base”
如果inputstate=a[0],则inputstate.base将为您提供a

所以我想知道为什么在我重新安装sympy和anaconda之后会发生这样的错误。或者有没有办法给出所有基本列表并修复错误


如果有人有类似的情况,如果你能给我一些提示,那就太酷了。提前谢谢你

a
是一个
索引数据库
a[0]
是一个
索引的
对象,其
基是
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
inputstate
Mul
expr
对象。它没有索引,因此没有基础

您是否在早期版本的
symphy
中有“正确”行为的记录,或文档中有某种更改的证据。它在什么版本中工作

您的
Bfunc
replace
似乎适合我:

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'

如果我用一个小功能更改
替换
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]
似乎
replace
expr
的各种元素传递给此函数。忽略诸如此
AttributeError
之类的错误

1.4发行说明中有一些关于
replace
及其
exact
参数的内容。我想知道使用
exact=False
可以修复1.4中的问题(如果不取消升级,我无法测试)


当遇到属性错误时,您的
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不会适用于所有情况,除非您也修改它以处理非电源情况。)


要回答的一个问题是,您是希望以实际功率为目标,还是以指数为1的“功率”为目标。例如,如果您想将所有幂的指数提高1,您是想要
x*y**2->x**2*y**3
还是仅仅
x*y**3
?L1适用于第一种情况,L2适用于第二种情况。

假设以下代码:

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()
不被排除


因为[a,b]
中的inputstate.is\u Pow和inputstate.base给出了False。在[a,b]
中使用
inputstate.as\u base\u exp()[0]时会发生这种情况,这会给出False。因此不会排除
Bfunctest()

谢谢!我没有以前的行为记录。但在早期版本中运行
inputstate.replace(lambda expr:expr.base in[a,b],lambda expr:Bfunc(expr,a,b))
时没有错误,但现在给出了错误。代码是一样的,我什么也没做。我很困惑…它似乎在1.13上为我运行,但我不知道我应该寻求什么更改。重新安装和更新后,我的sp版本现在是
1.4
。非常感谢!我卸载sympy并安装早期版本“1.3”。代码工作正常,没有错误。但是我仍然没有得到更新所改变的内容。虽然我改变了
exact=False
,但在1.4版本中,代码仍然给出了错误。我将查找1.4发行说明。你帮了我很多。非常感谢:)@hpauljLet的说法是
test1=a[0]**2
test1.is_Pow
给了你真实的信息
test1=a[0]*b[0]
test1.is\u Pow
给出的是False。另外,如果我在[a,b]
中运行
test1=a[0]*b[0]+b[2]*b[2]
test1.is_Pow和test1.base,则结果为False。所有这些都意味着函数
Bfunc(expr,a,b)
不会被排除在外,这不是我想要的。您能给出一个您希望看到的输入案例的输出示例吗?我在L1/L2示例中显示,对于您提供的
inputstate
,没有引发任何错误……但它也没有做任何事情。确定:在
L1
Bfunc
中,将
expr.base
更改为
expr.base
;第一个底数为
Pow
的底数,第二个底数为
索引的
的底数(即您要传递的内容)。此外,在
Bfunc
中设置
exact=False
,所有这些都应该可以工作:
(a[0]**2.替换(L1,lambda expr:Bfunc(expr,a,b))->(0.2*a[0]+0.2*b[0])**2
事实上
exact=True
在1个符号上失败是一个错误,并且在的问题页面已经更新以反映这一点。但这仅适用于
a[0]之类的情况**2
,如果我使用
a[1]*b[1]
或更复杂的表达式,例如
a[1]*b[1]+a[2]+b[3]
,这将不起作用,因为
expr.is\u Pow
给出了False。
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))