在SymPy中用求和表达式中的符号代替

时间:2017-04-11 20:17:44

标签: python sympy

我想在求和中使用次数符号并打印已计算的表达式,但是当我尝试这样做时我会收到错误。

正确的方法是什么?这有可能吗?

我用这种方式创建了一个求和表达式:

>>> from sympy import *
>>> from sympy.interactive import printing
>>> printing.init_printing()
>>> n = symbols('n', integer=True, positive=True)
>>> i = Idx('i', (1, n))
>>> d = IndexedBase('d')
>>> s = Sum(d[i], i)
>>> s
  n       
 ___      
 ╲        
  ╲   d[i]
  ╱       
 ╱        
 ‾‾‾      
i = 1

当我尝试替换n时,它给了我" TypeError:无法确定Relational"的真值。

>>> s.subs(n, 5)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/core/basic.py", line 902, in subs
    rv = rv._subs(old, new, **kwargs)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/core/cache.py", line 95, in wrapper
    retval = func(*args, **kwargs)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/core/basic.py", line 1014, in _subs
    rv = self._eval_subs(old, new)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/expr_with_limits.py", line 341, in _eval_subs
    return self.func(func, *limits)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/summations.py", line 155, in __new__
    obj = AddWithLimits.__new__(cls, function, *symbols, **assumptions)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/expr_with_limits.py", line 368, in __new__
    limits, orientation = _process_limits(*symbols)
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/expr_with_limits.py", line 59, in _process_limits
    if V[0].upper is not None and not bool(nlim[1] <= V[0].upper):
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/core/relational.py", line 195, in __nonzero__
    raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational

当我尝试替换d时,会产生另一个错误。

>>> i = Idx('i', (1, 5))
>>> s = Sum(d[i], i)                     
>>> s
  5       
 ___      
 ╲        
  ╲   d[i]
  ╱       
 ╱        
 ‾‾‾      
i = 1
>>> s.subs(d, range(1, 6))
  5                     
 ___                    
 ╲                      
  ╲   [1, 2, 3, 4, 5][i]
  ╱                     
 ╱                      
 ‾‾‾                    
i = 1
>>> s.subs(d, range(1, 6)).doit()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/summations.py", line 189, in doit
    newf = eval_sum(f, (i, a, b))
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/concrete/summations.py", line 824, in eval_sum
    if i not in f.free_symbols:
  File "/home/artem/prog/dev/my_slot/env/local/lib/python2.7/site-packages/sympy/core/basic.py", line 494, in free_symbols
    return set().union(*[a.free_symbols for a in self.args])
AttributeError: 'list' object has no attribute 'free_symbols'

1 个答案:

答案 0 :(得分:2)

似乎SymPy中存在一个错误。我已经开了an issue了。

解决方法是指定Sum而非Idx的限制:

>>> i = Idx('i')
>>> s = Sum(d[i], (i, 1, n))
>>> s.subs(n, 5)
Sum(d[i], (i, 1, 5))
>>> s.subs(n, 5).doit()
d[1] + d[2] + d[3] + d[4] + d[5]

IndexedBase替换为列表是另一个issue。以下是解决方法:

>>> l = range(6)
>>> s.subs(n, 5).doit().replace(Indexed, lambda i, j: Indexed(i, j) if i != d else l[j])
15
>>>

请注意,您的原始文件不起作用,因为它在范围内使用基于1的索引,但Python使用基于0的索引,因此您需要像我一样增加范围,或者修改总和从0到n - 1。