Simplifying expression in Dirac notation - sympy

I'm completely new to Sympy and was just playing with it this morning, but I've already run into a problem that I don't know how to handle.
I wrote a simple operator in Dirac notation, |0><0| - |1><1| that flips the sign of |1> components of a vector.
from sympy.physics.quantum import Dagger, OrthogonalKet
from sympy import *
b0, b1 = OrthogonalKet(0), OrthogonalKet(1)
A = b0 * Dagger(b0) - b1 * Dagger(b1) # |0><0| - |1><1|
When I apply it to a vector, it works fine
a, b = symbols("a b")
v = a * b0 + b * b1 # a|0> + b|1>
(A * v).expand() # a|0><0||0> - a|1><1||0> + b|0><0||1> - b|1><1||1>
but I would like to simplify the result to a|0> - b|1>.
With OrthogonalKet, it Sympy can work out the inner products if I set the parentheses correctly
((a*b0) * (Dagger(b0) * b0)).doit() # a|0>
((b*b0) * (Dagger(b0) * b1)).doit() # 0
etc. but the expanded expression seems to have set the parentheses around the outer products
a*|0><0|*|0> - a*|1><1|*|0> + b*|0><0|*|1> - b*|1><1|*|1>
and then the inner products are not simplified. Is there a way to tell it that (|i><j|)|x> = |i>(<j|x>)?

Related

how to work with equations with mathematical constraints on variables in sympy

I try to simplify and solve equations using sympy with mathematical constraints. I didn't find in tutorials in the net how to inform sympy to take into account for those constraints.
I have an example equation (see next code) and I want sympy to take into account for the listed constraints on these variables when working on it. But i didn't succeed to find how to inform sympy about those constraints (limitations / boundaries).
import sympy
D1,D2,D3,A,B,C,d,e,f = sympy.symbols('D1 D2 D3 A B C d e f')
equation = (-A*e + e*(A*d + (1.0 - d)*(D1 + 0.5*D2 + 0.5*D3)) + (1.0 - e)*( D1*d - D1 + 0.5*D2*d - 0.5*D2 + 0.5*D3*d - 0.5*D3 + A**2*(1.0 - d) + 0.5*A*B*(2.0 - 2.0*d) + 0.5*A*C*(2.0 - 2.0*d)))**2
#constraints: my trouble: how to take them into account in simplify, collect, solve?
A+B+C=1
D1+0.5*D2+0.5D3 = f
0.<=D1,D2,D3,A,B,C,d,e,f<=1.
print(sympy.latex(sympy.collect(equation,[f,A]))
thanks for enlightening me.

Simplification of derivative of square using sympy

I'm trying to use sympy to generate equations for non-linear least squares fitting. My goal is to make this quite complex but for the moment, here's a simple case (but not too simple!). It's basically fitting a two dimensional sinusoid to data. Here's the sympy code:
from sympy import *
S, l, m = symbols('S l m', real=True)
u, v = symbols('u v', real=True)
Vobs = symbols('Vobs', complex=True)
Vres = Vobs - S * exp(- 1j * 2 * pi * (u*l+v*m))
J=Vres*conjugate(Vres)
axes = [S, l, m]
grad = derive_by_array(J, axes)
hess = derive_by_array(grad, axes)
One element of the grad term looks like:
- 2.0*I*pi*S*u*(-S*exp(-2.0*I*pi*(l*u + m*v)) + Vobs)*exp(2.0*I*pi*(l*u + m*v)) + 2.0*I*pi*S*u*(-S*exp(2.0*I*pi*(l*u + m*v)) + conjugate(Vobs))*exp(-2.0*I*pi*(l*u + m*v))
What I'd like is to replace the expanded term (-S*exp(-2.0*I*pi*(l*u + m*v)) + Vobs) by Vres and contract the two conjugate terms into the more compact equivalent is:
4.0*pi*S*u*im(Vres*exp(2.0*I*pi*(l*u + m*v)))
I cannot see how to do this with sympy. This problem is bad for the first derivative (grad) but get really out of hand with the second derivative (hess).
First of all, let's not use 1j in SymPy, it's a float and floats are bad for symbolic math. SymPy's imaginary unit is I. So,
Vres = Vobs - S * exp(- I * 2 * pi * (u*l+v*m))
To replace the expression Vres by a symbol, we first need to create such a symbol. I'm going to call it Vres0, but its name will be Vres, so it prints as "Vres" in formulas.
Vres0 = symbols('Vres')
g1 = grad[1].subs(Vres, Vres0).conjugate().subs(Vres, Vres0).conjugate()
The conjugate-substitute-conjugate back is needed because subs doesn't quite recognize the possibility of replacing the conjugate of an expression with the conjugate of the symbol.
Now g1 is
-2*I*pi*S*Vres*u*exp(2*I*pi*(l*u + m*v)) + 2*I*pi*S*u*exp(-2*I*pi*(l*u + m*v))*conjugate(Vres)
and we want to fold the sum of conjugate terms. I use a custom transformation rule for this: the rule fold_conjugates applies to every sum (Add) of two terms (len(f.args) == 2) where the second is a conjugate of the first (f.args[1] == f.args[0].conjugate()). The transformation it performs: replace the sum by twice the real part of first argument (2*re(f.args[0])). Like so:
from sympy.core.rules import Transform
fold_conjugates = Transform(lambda f: 2*re(f.args[0]),
lambda f: isinstance(f, Add) and len(f.args) == 2 and f.args[1] == f.args[0].conjugate())
g = g1.xreplace(fold_conjugates)
Final result: 4*pi*S*u*im(Vres*exp(2*I*pi*(l*u + m*v))).

Calculate distance by comparing different points

I have different locations, and I need to calculate the distance between them:
Location Lat Long Distance
A -20 -50 (A-B)+(A-C)+(A-D)
B -20.3 -51 (B-A)+(B-C)+(B-D)
C -21 -50 (C-A)+(C-B)+(C-D)
D -20.8 -50.2 (D-A)+(D-B)+(D-C)
Would anyone know me?
I'm using this equation to calculate the distance between two points, but I don't know how to calculate between several points.
R = 6373.0
dist_lat=lat2-lat
dist_lon=long2-lon
a= np.sin(dist_lat/2)**2 + np.cos(lat) * np.cos(lat2) * np.sin(dist_lon/2)**2
b= 2 * np.arctan2(np.sqrt(a), np.sqrt(1 - a))
Dist= R * b
this is my first time with python so beware, also I made this rather quickly - it is probably buggy.
Tested on python2.7.
import numpy as np
import itertools as it
# these are the points
points = {
'A' :{'lat':-20 ,'lon':-50}
,'B':{'lat':-20.3 ,'lon':-51}
,'C':{'lat':-21 ,'lon':-50}
,'D':{'lat':-20.8 ,'lon':-50.2}
}
# this calculates the distance beween two points
# basicly your formula wrapped in a function
# - used below
def distance(a, b):
R = 6373.0
dist_lat = a['lat']-b['lat']
dist_lon = a['lon']-b['lon']
x = np.sin(dist_lat/2)**2 + np.cos(b['lat']) * np.cos(a['lat']) * np.sin(dist_lon/2)**2
y = 2 * np.arctan2(np.sqrt(x), np.sqrt(1 - x))
return R * y
distances = {}
# produce the distance beween all combinations
# see: https://docs.python.org/2/library/itertools.html
# - uses above function
for x in it.combinations(points.keys(), 2):
distances[ ''.join(x) ] = distance(points[x[0]],points[x[1]])
# for every starting point
# - filter the distance it is involved in
# - sum
for CH in ('A','B','C','D'):
print CH,' ', sum(dict((key,value) for key, value in distances.iteritems() if CH in key).values())
output:
$ python2.7 test.py
A 6983.4634697
B 9375.21128818
C 5859.5650322
D 9472.23979008

Cannot substitute the constants of integration into the integral of response

Let's use sympy to find the response of a linear system to an external force
from sympy import *
t, w, beta = symbols('t omega beta', positive=1)
x0, v0 = symbols('x0 v0')
x = symbols('x', cls=Function)
homogeneous = diff(x(t), t, 2)/w**2+x(t)
force = sin(beta*w*t)
disp = dsolve(homogeneous-force, x(t)).rhs
display(disp)
constants = solve((disp.subs(t,0)-x0, disp.diff(t).subs(t,0)-v0))
display(constants)
obtaining
sin(beta*omega*t)
C1*sin(omega*t) + C2*cos(omega*t) - -----------------
2
beta - 1
2
beta *v0 + beta*omega - v0
[{C1: --------------------------, C2: x0}]
/ 2 \
omega*\beta - 1/
Now, to complete my solution, I tried to substitute these constant of integration into the general+particular integral
display(disp.subs(constants))
that gives me
sin(beta*omega*t)
C2*sin(omega*t) + C2*cos(omega*t) - -----------------
2
beta - 1
Where have I done a mistake?
The argument of subs should be a dictionary.
What you got from solve as constants is not a dictionary but a one-element list containing a dictionary. Use it as
disp.subs(constants[0])
then the result is
x0*cos(omega*t) - sin(beta*omega*t)/(beta**2 - 1) + (beta**2*v0 + beta*omega - v0)*sin(omega*t)/(omega*(beta**2 - 1))

Simplify algebraic equation in CAS

I want to be able to simplify the ellipse equation:
sqrt((x + c)^2 + y^2) + sqrt((x - c)^2 + y^2) = 2a
into its canonical form:
x^2/a^2 + y^2/(a^2 - c^2) = 1
using CAS. I actually want to know how to do that in sympy, but any other CAS will do.
If it is not possible to do that in one call, then may be by transforming the original equation using operations like "get square of the both sides; move non-radicals (e.g. by enumerating them manually) to the right side; get square of the both sides again; simplify"
unrad will do most of the heavy lifting for you in SymPy:
>>> l # your original expression with the 2a subtracted from the lhs
-2*a + sqrt(y**2 + (-c + x)**2) + sqrt(y**2 + (c + x)**2)
>>> unrad(_)
(-a**4 + a**2*c**2 + a**2*x**2 + a**2*y**2 - c**2*x**2, [], [])
>>> neg_i, dep = _[0].as_independent(x,y)
>>> xpart, ypart = [dep.coeff(i**2) for i in (x,y)]
>>> Eq(-x**2*cancel(xpart/neg_i)-y**2*cancel(ypart/neg_i), neg_i/neg_i)
y**2/(a**2 - c**2) + x**2/a**2 == 1
Subtract the doubled second sqrt from both sides.
Multiply respective sides of the new equation and the original one.
Reduce LHS applying (m+n)(m-n) = m^2 - n^2.
You'll get (if i did it right): -4xc = 4a(a - sqrt(something))
Then: -xc/a = a - sqrt(something)
and: sqrt(something) = a + xc/a
Square both sides and see what happens.
I did it wrong. Should be: 4xc = 4a(a - sqrt(something))
so sqrt(something) = a - xc/a.