Import the sho1d.py file as well as the test_sho1d.py file
%load_ext sympy.interactive.ipythonprinting
from sympy import *
from IPython.display import display_pretty
from sympy.physics.quantum import *
from sympy.physics.quantum.sho1d import *
from sympy.physics.quantum.tests.test_sho1d import *
The sympy.interactive.ipythonprinting extension is already loaded. To reload it, use: %reload_ext sympy.interactive.ipythonprinting
Create a raising and lowering operator and make sure they print correctly
ad = RaisingOp('a')
a = LoweringOp('a')
ad
RaisingOp(a)
a
a
print latex(ad)
print latex(a)
a^{\dag} a
display_pretty(ad)
display_pretty(a)
RaisingOp(a)
a
print srepr(ad)
print srepr(a)
RaisingOp(Symbol('a')) LoweringOp(Symbol('a'))
print repr(ad)
print repr(a)
RaisingOp(a) a
Create a simple harmonic state and check its printing
k = SHOKet('k')
b = SHOBra('b')
k
|k>
b
<b|
print pretty(k)
print pretty(b)
❘k⟩ ⟨b❘
print latex(k)
print latex(b)
{\left|k\right\rangle } {\left\langle b\right|}
print srepr(k)
print srepr(b)
SHOKet(Symbol('k')) SHOBra(Symbol('b'))
Take the dagger of the raising and lowering operators. They should return eachother.
Dagger(ad)
a
Dagger(a)
RaisingOp(a)
Check Commutators of the raising and lowering operators
Commutator(ad,a).doit()
-1
Commutator(a,ad).doit()
1
Take a look at the dual states of the bra and ket
k.dual
<k|
b.dual
|b>
Taking the InnerProduct of the bra and ket will return the KroneckerDelta function
InnerProduct(b,k).doit()
KroneckerDelta(k, b)
Take a look at how the raising and lowering operators act on states. We use qapply to apply an operator to a state
qapply(ad*k)
sqrt(k + 1)*|k + 1>
qapply(a*k)
sqrt(k)*|k - 1>
But the states may have an explicit energy level. Let's look at the ground and first excited states
kg = SHOKet(0)
kf = SHOKet(1)
qapply(ad*kg)
|1>
qapply(ad*kf)
sqrt(2)*|2>
qapply(a*kg)
0
qapply(a*kf)
|0>
Notice that akg is 0 and akf is the |0> the ground state.
Let's look at the Number Operator and Hamiltonian Operator
k = SHOKet('k')
ad = RaisingOp('a')
a = LoweringOp('a')
N = NumberOp('N')
H = Hamiltonian('H')
The number operator is simply expressed as ad*a
N().rewrite('a').doit()
RaisingOp(a)*a
The number operator expressed in terms of the position and momentum operators
N().rewrite('xp').doit()
-1/2 + (m**2*omega**2*X**2 + Px**2)/(2*hbar*m*omega)
It can also be expressed in terms of the Hamiltonian operator
N().rewrite('H').doit()
-1/2 + H/(hbar*omega)
The Hamiltonian operator can be expressed in terms of the raising and lowering operators, position and momentum operators, and the number operator
H().rewrite('a').doit()
hbar*omega*(1/2 + RaisingOp(a)*a)
H().rewrite('xp').doit()
(m**2*omega**2*X**2 + Px**2)/(2*m)
H().rewrite('N').doit()
hbar*omega*(1/2 + N)
The raising and lowering operators can also be expressed in terms of the position and momentum operators
ad().rewrite('xp').doit()
sqrt(2)*(m*omega*X - I*Px)/(2*sqrt(hbar)*sqrt(m*omega))
a().rewrite('xp').doit()
sqrt(2)*(m*omega*X + I*Px)/(2*sqrt(hbar)*sqrt(m*omega))
Let's take a look at how the NumberOp and Hamiltonian act on states
qapply(N*k)
k*|k>
Apply the Number operator to a state returns the state times the ket
ks = SHOKet(2)
qapply(N*ks)
2*|2>
qapply(H*k)
hbar*k*omega*|k> + hbar*omega*|k>/2
Let's see how the operators commute with each other
Commutator(N,ad).doit()
RaisingOp(a)
Commutator(N,a).doit()
-a
Commutator(N,H).doit()
0
We can express the operators in NumberOp basis. There are different ways to create a matrix in Python, we will use 3 different ways.
represent(ad, basis=N, ndim=4, format='sympy')
[0, 0, 0, 0] [1, 0, 0, 0] [0, sqrt(2), 0, 0] [0, 0, sqrt(3), 0]
represent(ad, basis=N, ndim=5, format='numpy')
array([[ 0. , 0. , 0. , 0. , 0. ], [ 1. , 0. , 0. , 0. , 0. ], [ 0. , 1.41421356, 0. , 0. , 0. ], [ 0. , 0. , 1.73205081, 0. , 0. ], [ 0. , 0. , 0. , 2. , 0. ]])
represent(ad, basis=N, ndim=4, format='scipy.sparse', spmatrix='lil')
<4x4 sparse matrix of type '<type 'numpy.float64'>' with 3 stored elements in Compressed Sparse Row format>
print represent(ad, basis=N, ndim=4, format='scipy.sparse', spmatrix='lil')
(1, 0) 1.0 (2, 1) 1.41421356237 (3, 2) 1.73205080757
The same can be done for the other operators
represent(a, basis=N, ndim=4, format='sympy')
[0, 1, 0, 0] [0, 0, sqrt(2), 0] [0, 0, 0, sqrt(3)] [0, 0, 0, 0]
represent(N, basis=N, ndim=4, format='sympy')
[0, 0, 0, 0] [0, 1, 0, 0] [0, 0, 2, 0] [0, 0, 0, 3]
represent(H, basis=N, ndim=4, format='sympy')
[hbar*omega/2, 0, 0, 0] [ 0, 3*hbar*omega/2, 0, 0] [ 0, 0, 5*hbar*omega/2, 0] [ 0, 0, 0, 7*hbar*omega/2]
k0 = SHOKet(0)
k1 = SHOKet(1)
b0 = SHOBra(0)
b1 = SHOBra(1)
print represent(k0, basis=N, ndim=5, format='sympy')
[1] [0] [0] [0] [0]
print represent(k1, basis=N, ndim=5, format='sympy')
[0] [1] [0] [0] [0]
print represent(b0, basis=N, ndim=5, format='sympy')
[1, 0, 0, 0, 0]
print represent(b1, basis=N, ndim=5, format='sympy')
[0, 1, 0, 0, 0]