I need to evaluate the expression using SymPy:
I expect to obtain something like
The problem is the code
import sympy as sy
n,i,j = sy.symbols('n i j', integer=True)
a = sy.Function('a')
print sy.Sum(sy.Sum(a(j), (j,1,i)), (i, 1, n)).doit()
prints just the double sum
Sum(a(j), (j, 1, i), (i, 1, n))
The answer you are trying to obtain is not correct. The inner summation variable is j, which is used in a(j), so the inner sum can't be computed further, and, i is the upper limit of the inner sum, so the outer sum can't be computed further either.
The summation that gives the answer you want is Sum(a(i), (j,i,n), (i, 1, n)), i.e.,
n n
___ ___
╲ ╲
╲ ╲ a(i)
╱ ╱
╱ ╱
‾‾‾ ‾‾‾
i = 1 j = i
which SymPy computes if you call doit(). By the way, note that you can create a double sum with a single call to Sum, by passing the outer limits as further arguments.
Related
I am a bit confused how to use Indexed objects in Sympy. Suppose I have the following setup:
from sympy import *
x = IndexedBase('x')
i = Idx('i')
s = Sum(x[i], (i, 0, 5))
s
Output:
5
___
╲
╲
╱ x[i]
╱
‾‾‾
i = 0
Which ofcourse is equal to
x[0] + x[1] + x[2] + x[3] + x[4] + x[5]
By doing s.doit(). Now, how do I substitute x with some range? I expected the following to work:
s.subs(x, list(range(6)))
But it does not do anything it would seem. However s.doit().subs(x[0], 0) works, but it will only substitute 1 element. Is it not intended to substitute IndexedBase with some list?
When using SymPy, there is one thing to always keep in mind: the only objects SymPy operates on is SymPy's object. Consider this example:
expr = x + 3
r = expr.subs(x, 2)
print(r, type(r))
5 <class 'sympy.core.numbers.Integer'>
Here, we passed a int number to subs, but SymPy internally converted it to an Integer number. Then, it performed the addition, producing the Integer number 5.
There are occasions in which the input parameter cannot be converted to something SymPy can understand. Your example is one such occasion. Let's use sympify (or its alias S) to verify how your list is going to be converted to a SymPy object:
l = list(range(6))
c = sympify(l)
type(c)
# out: list
As we can see, SymPy is unable to convert an object of type list, hence it is unable to use it. In short, this is the reason your code doesn't produce the correct output.
However, let's try the same trick with a tuple:
c = sympify(tuple(l))
type(c)
# out: Tuple
Here, SymPy converted a Python object of type tuple to a SymPy object of type Tuple. Now, the substitution should produce the correct result:
s.doit().subs(x, tuple(l))
# out: 15
Here are the most common SymPy objects the support iteration: Tuple, Matrix, Array.
I'm not sure if the following is possible. I tried looking at the docs, but see a lot of physics stuff and not quite what I want.
Is it possible to be like matrixcalculus.org, and specify say a general matrix Q of shape (m,n), x, a vector of shape n, and do this kind of calculation. Rather than limiting it to a set number of dimensions and specifying each element individually
You can use MatrixSymbol:
In [5]: n = Symbol('n')
In [6]: Q = MatrixSymbol('Q', n, n)
In [7]: x = MatrixSymbol('x', n, 1)
In [8]: f = x.T # Q # x
In [9]: f
Out[9]:
T
x ⋅Q⋅x
In [10]: diff(f, x)
Out[10]:
T
Q⋅x + Q ⋅x
If you substitute a concrete value for n then as_explicit can give you the expanded result:
In [11]: diff(f, x).subs(n, 2).as_explicit()
Out[11]:
⎡2⋅Q₀₀⋅x₀₀ + Q₀₁⋅x₁₀ + Q₁₀⋅x₁₀⎤
⎢ ⎥
⎣Q₀₁⋅x₀₀ + Q₁₀⋅x₀₀ + 2⋅Q₁₁⋅x₁₀⎦
https://docs.sympy.org/latest/modules/matrices/expressions.html
I'm especting something like the following:
>>> Sum(x[i,j],(j, i+1, 3), (i, 1, 3)).doit()
x[1,2] + x[1,3] + x[2,3]
But instead I get:
>>> Sum(x[i,j],(j, i+1, 3), (i, 1, 3)).doit()
Sum(x[i,j],(j, i+1, 3), (i, 1, 3))
Anybody knows how to make the first one?
I'm not looking for a solution like the following:
>>> sum(x[i,j] for i in range(1,4) for j in range(i,4))
x[1,2] + x[1,3] + x[2,3]
This is intended for computing drift forces where the number of combinations is way bigger and the inside term is more complex, but I need away to get it without the summation form.
How to use Sympy to check calculations step by step, for instance that the 2 formulas below are equal?
from sympy import IndexedBase, Sum, symbols
i, n = symbols('i n', integer=True)
a = IndexedBase('a')
Sum(a[i], (i, 0, n - 1)) + a[n]
Sum(a[i], (i, 0, n))
The simplify function is used to check whether two expressions are equal.
from sympy import IndexedBase, Sum, symbols, simplify
i, n = symbols('i n', integer=True)
a = IndexedBase('a')
#to check calculations
n=5
x=Sum(a[i], (i, 0, n - 1)).doit() + a[n].doit()
y=Sum(a[i], (i, 0, n)).doit()
print x,y
#To check functions are equal
if simplify(x-y) == 0:
print "The two functions are equal"
I have an equation that is of the form (in LaTeX syntax):
\sum_{k=0}^{K-1} a_k = 0
a_k is "a subscript k", one of a list of variables that I'm setting up a system of linear equations in. I would like to be able to express this equation to SymPy in as compact of a way as possible. It seems like I would want to use its Sum() function to express the summation, but I'm not sure how to tell it that on term k in the sum, a_k refers to the k-th symbol.
Is this possible, for instance if I set up a list of symbols like this?
a = [sympy.symbols('a' + str(i)) for i in xrange(K)]
Do you mean something like this?
In [1]: a = IndexedBase("a")
In [2]: Sum(a[k], (k, 0, K-1))
Out[2]:
K - 1
___
╲
╲ a[k]
╱
╱
‾‾‾
k = 0
IndexedBase are supposed to create a variable that needs to specify an index each time it is used. If the indices are different, the variables should be considered different (e.g. a[k] vs a[j]).
In case your summation has known limits (i.e. non literal), you may expand it:
In [3]: Sum(a[k], (k, 0, 10))
Out[3]:
10
___
╲
╲ a[k]
╱
╱
‾‾‾
k = 0
In [4]: Sum(a[k], (k, 0, 10)).doit()
Out[4]: a[0] + a[1] + a[2] + a[3] + a[4] + a[5] + a[6] + a[7] + a[8] + a[9] + a[10]
Unfortunately, not all of SymPy's algorithms support IndexedBase objects completely. Replacement with a Symbol is advised in such cases.