Can SymPy understand variables that are indexed by a summation index? - sympy

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.

Related

Sympy IndexedBase substitution

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.

Sympy, Matrices of general size, derivatives

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

Sum of Sum, unroll terms

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 in sympy Disable unnecessary parenthesis?

Tell me please, How to forbid to open brackets? For example,
8 * (x + 1) It should be that way, not 8 * x + 8
Using evaluate = False doesn't help
The global evaluate flag will allow you to do this in the most natural manner:
>>> with evaluate(False):
... 8*(x+1)
...
8*(x + 1)
Otherwise, Mul(8, x + 1, evaluate=False) is a lower level way to do this. And conversion from a string (already in that form) is possible as
>>> S('8*(x+1)',evaluate=False)
8*(x + 1)
In general, SymPy will convert the expression to its internal format, which includes some minimal simplifications. For example, sqrt is represented internally as Pow(x,1/2). Also, some reordering of terms may happen.
In your specific case, you could try:
from sympy import factor
from sympy.abc import x, y
y = x + 1
g = 8 * y
g = factor(g)
print(g) # "8 * (x + 1)"
But, if for example you have g = y * y, SymPy will either represent it as a second power ((x + 1)**2), or expand it to x**2 + 2*x + 1.
PS: See also this answer by SymPy's maintainer for some possible workarounds. (It might complicate things later when you would like to evaluate or simplify this expression in other calculations.)
How about sympy.collect_const(sympy.S("8 * (x + 1)"), 8)?
In general you might be interested in some of these expression manipulations: https://docs.sympy.org/0.7.1/modules/simplify/simplify.html

SymPy: evaluate sum of sum

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.