I don't understand what indexed objects in sympy are for. The documentation didn't help me understand the concept much.
For instance :
>>> from sympy import symbols, IndexedBase, Idx
>>> M = IndexedBase('M')
>>> i, j = symbols('i j', cls=Idx)
>>> M[i, j]
M[i, j]
What does this code do? What is M[i,j]?
All I understand is that an indexed object gives indices to individual sympy symbols .
I'm looking for a better explanation of indexed objects , along with it's relation to IndexedBase and idx
One-line explanation: they represent a symbolic array of undetermined, possibly infinite, size.
Suppose you want to work with n symbols, how would you do that? Easy enough if n is a given number, like 10. But it's just n, an unspecified integer number. Formulas like that appear in mathematics all the time: "add or multiply (something) over the indices i=1, ..., n".
For example, suppose I have a function in n-dimensional space Rn, such as f(x) = 1/distance(x, 0). The distance is, of course, the square root of the sum of squares of coordinates. And maybe I want to find some partial derivative of f. How to express all of this in SymPy? Like this:
from sympy import *
x = IndexedBase('x')
j, k, n = symbols('j k n', cls=Idx)
f = 1/sqrt(Sum(x[k]**2, (k, 1, n)))
print(f.diff(x[j]))
This computes the derivative of f with respect to the coordinate x[j]. The answer is
-Sum(2*KroneckerDelta(j, k)*x[k], (k, 1, n))/(2*Sum(x[k]**2, (k, 1, n))**(3/2))
which is correct (although perhaps the numerator could be simplified if we assume that j is in the range 1..n).
In the above example, x[j] is the coordinate with index j. In your example, M[i, j] could be the entry of some matrix at position i, j.
M is the name of symbolic array, its class is IndexedBase
i and j are indices of that array, their class is Idx
The above are the classes that you would instantiate yourself. The class of M[i, j] is Indexed but you don't create those objects by using class name, M[i, j] simply does that.
Two recent questions with examples of working with indexed objects:
Create an unknown number of programmatically defined variables
Sum of partial derivatives of a product over a symbolic number of variables
Indexed is primarily used for two use-cases:
Formulas with symbolic subscripts. For example, \sum_{i=1}^n a_i. You could just use Symbol('a_i'), but them the i is not symbolic and in any way related to Symbol('i'). So for instance, Sum(a_i, (i, 1, n)) will just give you n*a_i. Instead IndexedBase('a')[i] represents a different symbol for every value of i, and Sum(IndexedBase('a')[i], (i, 1, n)) effectively represents the above summation.
N-d arrays. This is especially useful for code generation, because the SymPy code printers for languages like C or Fortran will print Indexed objects as array lookups automatically, for instance
>>> a = IndexedBase('a')
>>> i = Idx('i', (1, n))
>>> ccode(a[i])
'a[i]'
>>> fcode(a[i])
' a(i)'
This makes it very easy to write array-based code symbolically using SymPy and generate fast code that computes it.
Related
I want to implement/calculate in python the following algebraic expression
the expression
where Sn is the symmetry group of order n (with n an even positive integer) and Delta is a complex function (I will not define this function explicitly in the code, though) that is symmetric in its arguments, i.e.
condition
With the help of sympy, and studing the sample case n=2, so far I have something like the following:
from sympy import *
from itertools import permutations
i, j = symbols('i j', cls=Idx)
Delta = IndexedBase('Delta')
perm = permutations([1, 2])
L = []
for p in list(perm):
L.append(Delta[p[0], p[1]])
print(sum(L))
which yields
Delta[1, 2] + Delta[2, 1]
How can I implement the symmetry condition on the indices of the symbol Delta, so that the answer must be 2*Delta[1, 2]?
I am trying to learn some methods in order to solve linear systems with Python. I have implemented a sort of these methods. Now I wish I could test them with large and sparse matrices. In order to do that I began to learn about Three Column Representation method cause I noticed that I am expected to reduce my sparse matrix before inputing it in my method. Three Column Representation seems to be simple but I cant figure out how to use its output as an input of my Cholesky method (for example). How do I use its output (a three column array with, values and references) as an input to my method? Do I need to rewrite my Cholesky method?
Here is my Cholesky method: https://raw.githubusercontent.com/angellicacardozo/linear-algebra-methods/master/P03CHOLE.py
Thank you
Maybe this can help you:
For i = 1 To n
For j = 1 To i
Sum = a(i, j)
For k = 1 To j-1
Sum = Sum - a(i, k) * a(j, k)
If i > j Then
a(i, j) = Sum / a(j, j)
Else If Sum > 0 Then
a(i, i) = Sqrt(Sum)
Else
ERROR
I am trying to vectorize the following triple product operation on an N x N array called p below:
for j in range(len(p)):
for k in range(len(p)):
for l in range(len(p)):
h[j, k, l] = p[j, k] * p[k, l] * p[l, j] - p[j, l] * p[l, k] * p[k, j]
I thought numpy.einsum should be of use here, despite that I'm not actually summing over the repeated indices, but I haven't been able to pin it down. Thoughts?
Simply porting over those loop iterators as string notations, we would have an einsum based solution like so -
h = np.einsum('jk,kl,lj->jkl',p,p,p) - np.einsum('jl,lk,kj->jkl',p,p,p)
Being basically an expansion related question (as we are not reducing any axis), we can simply use NumPy broadcasting too by introducing new axes with None/np.newaxis at various places for allowing the expansion, like so -
h = p[...,None]*p*p[:,None,:].T - p[:,None,:]*p.T*p.T[...,None]
I am translating my code from Python to Mathematica. I am trying to define a matrix, whose values depend on a variable chosen by the user, called kappa.
In Python the code looked like that:
def getA(kappa):
matrix = zeros((n, n), float)
for i in range(n):
for j in range(n):
matrix[i][j] = 2*math.cos((2*math.pi/n)*(abs(j-i))*kappa)
n = 5
return matrix
What I have done so far in Mathematica is the following piece of code:
n = 5
getA[kappa_] :=
A = Table[0.0, {n}, {n}];
For[i = 0, i < n, i++,
For[ j = 0, j < n, j++,
A[[i, j]] = 2*Cos[(2*pi/n)*(abs (j - i))*kappa]]];
b = getA[3]
But when I try to evaluate this matrix for a value of kappa equal to 3, I get the following error:
Set::partd: "Part specification A[[i,j]] is longer than depth of object.
How can I fix it?
Try something like this
n = 5;
A = Table[2*Cos[(2 \[Pi]/n) (Abs[ j - i]) \[Kappa]], {i, 1, n}, {j, 1, n}];
b = A /. \[Kappa]->3
I'll leave you to package this into a function if you want to.
You write that you are trying to translate Python into Mathematica; your use of For loops suggests that you are trying to translate to C-in-Mathematica. The first rule of Mathematica club is don't use loops.
Besides that you've made a number of small syntactical errors, such as using abs() where you should have had Abs[] (Mathematica's built-in functions all have names beginning with a capital letter, they wrap their arguments in [ and ], not ( and )), pi is not the name of the value of the ratio of a circle's diameter to its radius (it's called \[Pi]). Note too that I've omitted the multiplication operator which is often not required.
In your particular case, this would be the fastest and the most straightforward solution:
getA[κ_, n_] := ToeplitzMatrix[2 Cos[2 π κ Range[0, n - 1] / n]]
I'm trying to express a summation over an arbitrary (but finite) number of symbols, which I wish to be given by another symbol. For instance, is it possible to say:
N,ci,cj = symbols('N,c_i,c_j')
# pseudocode
k = sum(ci+cj,(ci,0,N),(cj,0,N))
or, more literally,
k = sum(ci+cj, (ci != cj))
My instinct is that it isn't, but I do wish sympy would implement support for it!
UPDATE
It appears sympy offers provisions for indexed variables. Namely:
x = IndexedBase('x')
i,j = symbols('i j',cls=Idx)
however, the you can an error when attempting:
y = Sum(x[i], (i, 0, 2))
Which is:
ValueError: Invalid limits given: ((i, 1, 5),)
You can use a Function, like x = symbols('x', cls=Function) and x(i). Indexed should also work, but it looks like Sum has a bug that disallows Idx. It works if you just use i = symbols('i'), though.