How to do dot/cross multiplication of Vectors with Sympy - python

I would like to know how to do
dot multiplication
cross multiplication
add/sub
of vectors with the sympy library. I have tried looking into the official documentation but I have had no luck or It was too complicated. Can anyone help me out on this?
I was trying to do this simple operation
a · b = |a| × |b| × cos(θ)

To do vector dot/cross product multiplication with sympy, you have to import the basis vector object CoordSys3D. Here is a working code example below:
from sympy.vector import CoordSys3D
N = CoordSys3D('N')
v1 = 2*N.i+3*N.j-N.k
v2 = N.i-4*N.j+N.k
v1.dot(v2)
v1.cross(v2)
#Alternately, can also do
v1 & v2
v1 ^ v2
Please note the last 2 lines are not recommended by sympy documentation. It is better to use the methods explicitly. Personally I think this is a matter of preference, however.

You can do it as described here: https://docs.sympy.org/latest/modules/matrices/matrices.html?highlight=cross#sympy.matrices.matrices.MatrixBase.cross
For example:
>>> from sympy import Matrix
>>> M = Matrix([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
>>> v = Matrix([1, 1, 1])
>>> M.row(0).dot(v)
6
>>> M.col(0).dot(v)
12
>>> v = [3, 2, 1]
>>> M.row(0).dot(v)
10

http://docs.sympy.org/0.7.2/modules/physics/mechanics/api/functions.html
There are examples on that doc and some code here. What exactly don't you understand? Maybe, try to be more specific.
The dot multiplication as you write it is explained in the doc with that example:
from sympy.physics.mechanics import ReferenceFrame, Vector, dot
from sympy import symbols
q1 = symbols('q1')
N = ReferenceFrame('N') # so, ||x|| = ||y|| = ||z|| = 1
dot(N.x, N.x)
1 # it is ||N.x||*||N.y||*cos(Nx,Ny)
dot(N.x, N.y)
0 # it is ||N.x||*||N.y||*cos(Nx,Ny)
A = N.orientnew('A', 'Axis', [q1, N.x])
dot(N.y, A.y)
cos(q1)
Also, you might consider doing it with numpy...

numpy is designed for this, it is a clean and fast way to do numerical calculations because it's implemented in C.
In [36]: x = [1, 2, 3]
...: y = [4, 5, 6]
In [37]: import numpy as np
...: print np.dot(x, y)
...: print np.cross(x, y)
...: print np.add(x, y) #np.subtract, etc.
32
[-3 6 -3]
[5 7 9]
There is a discussion on numpy and sympy on google groups.

If you have symbolic vectors and need to use sympy it is actually very simple, just use the cross function as exemplified below:
import sympy as s
a,b,c,x,y,z = s.symbols("a,b,c,x,y,z")
v1 = s.Matrix([a,b,c])
v2 = s.Matrix([x,y,z])
cross_result = v1.cross(v2)
print(cross_result)
With output:
Matrix([
[ b*z - c*y],
[-a*z + c*x],
[ a*y - b*x]])

I had a similar issue, and the method followed was just to put the sympy equations/variables within np.array() and use np.cross().
for example,
np.cross(np.array(M),np.array(N))
where M & N are variables computed using sympy

Related

Numpy - compute all possible differences in an array at fixed distance

Suppose I have an array, and I want to compute differences between elements at a distance Delta. I can use numpy.diff(Array[::Delta-1]), but this will not give all possible differences (from each possible starting point). To get them, I can think of something like this:
for j in xrange(Delta-1):
NewDiff = numpy.diff(Array[j::Delta-1])
if j==0:
Diff = NewDiff
else:
Diff = numpy.hstack((Diff,NewDiff))
But I would be surprised if this is the most efficient way to do it. Any idea from those familiar with the most exoteric functionalities of numpy?
The following function returns a two-dimensional numpy array diff which contains the differences between all possible combinations of a list or numpy array a. For example, diff[3,2] would contain the result of a[3] - a[2] and so on.
def difference_matrix(a):
x = np.reshape(a, (len(a), 1))
return x - x.transpose()
Update
It seems I misunderstood the question and you are only asking for an the differences of array elements which are a certain distance d apart.1)
This can be accomplished as follows:
>>> a = np.array([1,3,7,11,13,17,19])
>>> d = 2
>>> a[d:] - a[:-d]
array([6, 8, 6, 6, 6])
Have a look at the documentation to learn more about this notation.
But, the function for the difference matrix I've posted above shall not be in vain. In fact, the array you're looking for is a diagonal of the matrix that difference_matrix returns.
>>> a = [1,3,7,11,13,17,19]
>>> d = 2
>>> m = difference_matrix(a)
>>> np.diag(m, -d)
array([6, 8, 6, 6, 6])
1) Judging by your comment, this distance d is different than the Delta you seem to be using, with d = Delta - 1, so that the distance between an element and itself is 0, and its distance to the adjacent elements is 1.

python numpy set elements of list by condition

I want to set a specific element of my list to specific value with low overhead.
for example if I have this : a = numpy.array([1,2,3,0,4,0]) I want to change every 0 value to 10; in the end I want to have [1, 2, 3, 10, 4, 10]
in Matlab you can do this easily like a(a==0) = 10, is there any equivalent in numpy?
Remarkably similar to Matlab:
>>> a[a == 0] = 10
>>> a
array([ 1, 2, 3, 10, 4, 10])
There's a really nice "NumPy for Matlab Users" guide at the SciPy website.
I should note, this doesn't work on regular Python lists. NumPy arrays are a different datatype that work a lot more like a Matlab matrix than a Python list in terms of access and math operators.
A little more pythonic way would be like this, I guess:
import numpy
a = numpy.array([1,2,3,0,4,0])
for k,v in enumerate(a):
if v == 0:
a[k] = 10
print a
Even more pythonic way (provided by #mtrw)
[10 if k == 0 else k for k in a]

Can Python perform vectorized operations?

I want to implement the following Matlab code in Python:
x=1:100;
y=20*log10(x);
I tried using Numpy to do this:
y = numpy.zeros(x.shape)
for i in range(len(x)):
y[i] = 20*math.log10(x[i])
But this uses a for loop; is there anyway to do a vectorized operation like in Matlab? I know for some simple math such as division and multiplication, it's possible. But what about other more sophisticated operations like logarithm here?
y = numpy.log10(numpy.arange(1, 101)) * 20
In [30]: numpy.arange(1, 10)
Out[30]: array([1, 2, 3, 4, 5, 6, 7, 8, 9])
In [31]: numpy.log10(numpy.arange(1, 10))
Out[31]:
array([ 0. , 0.30103 , 0.47712125, 0.60205999, 0.69897 ,
0.77815125, 0.84509804, 0.90308999, 0.95424251])
In [32]: numpy.log10(numpy.arange(1, 10)) * 20
Out[32]:
array([ 0. , 6.02059991, 9.54242509, 12.04119983,
13.97940009, 15.56302501, 16.9019608 , 18.06179974, 19.08485019])
Yep, there certainly is.
x = numpy.arange(1, 100)
y = 20 * numpy.log10(x)
Numpy has a lot of built-in array operators like log10. If it's not listed in numpy's documentation and you can't generate it from combining built-in methods, then there's no easy way to do it efficiently. You can implement a C-level function to work on numpy arrays and compile that, but this is a lot more work than one or two lines of Python code.
For your case you almost have the right output already:
y = 20*numpy.log10(x)
You may want to take a look at the Numpy documentation. This is a good place to start:
http://docs.scipy.org/doc/numpy/reference/routines.html
And specifically related to your question:
http://docs.scipy.org/doc/numpy/reference/routines.math.html
If you're not trying to do anything complicated, the original code could be implemented this way as well, without requiring the use of numpy, if I'm not mistaken.
>>> import math
>>> x = range(1, 101)
>>> y = [ 20 * math.log10(z) for z in x ]
Apart from performing vectorized operation using numpy standard vectorized functions, you can also make your custom vectorized function using numpy.vectorize. Here is one example:
>>> def myfunc(a, b):
... "Return a-b if a>b, otherwise return a+b"
... if a > b:
... return a - b
... else:
... return a + b
>>>
>>> vfunc = np.vectorize(myfunc)
>>> vfunc([1, 2, 3, 4], 2)
array([3, 4, 1, 2])
As mentioned in documentation, unlike numpy's standard vectorized functions, this won't improve the performance

Populate numpy matrix from the difference of two vectors

Is it possible to construct a numpy matrix from a function? In this case specifically the function is the absolute difference of two vectors: S[i,j] = abs(A[i] - B[j]). A minimal working example that uses regular python:
import numpy as np
A = np.array([1,3,6])
B = np.array([2,4,6])
S = np.zeros((3,3))
for i,x in enumerate(A):
for j,y in enumerate(B):
S[i,j] = abs(x-y)
Giving:
[[ 1. 3. 5.]
[ 1. 1. 3.]
[ 4. 2. 0.]]
It would be nice to have a construction that looks something like:
def build_matrix(shape, input_function, *args)
where I can pass an input function with it's arguments and retain the speed advantage of numpy.
In addition to what #JoshAdel has suggested, you can also use the outer method of any numpy ufunc to do the broadcasting in the case of two arrays.
In this case, you just want np.subtract.outer(A, B) (Or, rather, the absolute value of it).
While either one is fairly readable for this example, in some cases broadcasting is more useful, while in others using ufunc methods is cleaner.
Either way, it's useful to know both tricks.
E.g.
import numpy as np
A = np.array([1,3,6])
B = np.array([2,4,6])
diff = np.subtract.outer(A, B)
result = np.abs(diff)
Basically, you can use outer, accumulate, reduce, and reduceat with any numpy ufunc such as subtract, multiply, divide, or even things like logical_and, etc.
For example, np.cumsum is equivalent to np.add.accumulate. This means you could implement something like a cumdiv by np.divide.accumulate if you even needed to.
I recommend taking a look into numpy's broadcasting capabilities:
In [6]: np.abs(A[:,np.newaxis] - B)
Out[6]:
array([[1, 3, 5],
[1, 1, 3],
[4, 2, 0]])
http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html
Then you could simply write your function as:
In [7]: def build_matrix(func,args):
...: return func(*args)
...:
In [8]: def f1(A,B):
...: return np.abs(A[:,np.newaxis] - B)
...:
In [9]: build_matrix(f1,(A,B))
Out[9]:
array([[1, 3, 5],
[1, 1, 3],
[4, 2, 0]])
This should also be considerably faster than your solution for larger arrays.

Syntax in Python (.T)

In the help resource for the multivariate normal sampling function in SciPy, they give the following example:
x,y = np.random.multivariate_normal(mean,cov,5000).T
My question is rather basic: what does the final .T actually do?
Thanks a lot, I know it is fairly simple, but it is hard to look in Google for ".T".
The .T accesses the attribute T of the object, which happens to be a NumPy array. The T attribute is the transpose of the array, see the documentation.
Apparently you are creating random coordinates in the plane. The output of multivariate_normal() might look like this:
>>> np.random.multivariate_normal([0, 0], [[1, 0], [0, 1]], 5)
array([[ 0.59589335, 0.97741328],
[-0.58597307, 0.56733234],
[-0.69164572, 0.17840394],
[-0.24992978, -2.57494471],
[ 0.38896689, 0.82221377]])
The transpose of this matrix is:
array([[ 0.59589335, -0.58597307, -0.69164572, -0.24992978, 0.38896689],
[ 0.97741328, 0.56733234, 0.17840394, -2.57494471, 0.82221377]])
which can be conveniently separated in x and y parts by sequence unpacking.
.T is just np.transpose().
Best of luck
Example
import numpy as np
a = [[1, 2, 3]]
b = np.array(a).T # ndarray.T The transposed array. [[1,2,3]] -> [[1][2][3]]
print("a=", a, "\nb=", b)
for i in range(3):
print(" a=", a[0][i]) # prints 1 2 3
for i in range(3):
print(" b=", b[i][0]) # prints 1 2 3

Categories

Resources