Basic Operations on Quantum Objects¶
First things first¶
Warning
Do not run QuTiP from the installation directory.
To load the qutip modules, we must first call the import statement:
In [1]: from qutip import *
that will load all of the user available functions. Often, we also need to import the NumPy and Matplotlib libraries with:
In [2]: import numpy as np
In [3]: import matplotlib.pyplot as plt
Note that, in the rest of the documentation, functions are written using qutip.module.function() notation which links to the corresponding function in the QuTiP API: Functions. However, in calling import *, we have already loaded all of the QuTiP modules. Therefore, we will only need the function name and not the complete path when calling the function from the interpreter prompt, Python script, or Jupyter notebook.
The quantum object class¶
Introduction¶
The key difference between classical and quantum mechanics lies in the use of operators instead of numbers as variables. Moreover, we need to specify state vectors and their properties. Therefore, in computing the dynamics of quantum systems we need a data structure that is capable of encapsulating the properties of a quantum operator and ket/bra vectors. The quantum object class, qutip.Qobj
, accomplishes this using matrix representation.
To begin, let us create a blank Qobj
:
In [4]: Qobj()
Out[4]:
Quantum object: dims = [[1], [1]], shape = (1, 1), type = bra
Qobj data =
[[ 0.]]
where we see the blank Qobj
object with dimensions, shape, and data. Here the data corresponds to a 1x1dimensional matrix consisting of a single zero entry.
Hint
By convention, Class objects in Python such as Qobj()
differ from functions in the use of a beginning capital letter.
We can create a Qobj
with a user defined data set by passing a list or array of data into the Qobj
:
In [5]: Qobj([[1],[2],[3],[4],[5]])
Out[5]:
Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket
Qobj data =
[[ 1.]
[ 2.]
[ 3.]
[ 4.]
[ 5.]]
Notice how both the dims and shape change according to the input data. Although dims and shape appear to have the same function, the difference will become quite clear in the section on tensor products and partial traces.
Note
If you are running QuTiP from a python script you must use the print
function to view the Qobj attributes.
States and operators¶
Manually specifying the data for each quantum object is inefficient. Even more so when most objects correspond to commonly used types such as the ladder operators of a harmonic oscillator, the Pauli spin operators for a twolevel system, or state vectors such as Fock states. Therefore, QuTiP includes predefined objects for a variety of states:
States  Command (# means optional)  Inputs 

Fock state ket vector  basis(N,#m) /fock(N,#m) 
N = number of levels in Hilbert space, m = level containing excitation (0 if no m given) 
Fock density matrix (outer product of basis)  fock_dm(N,#p) 
same as basis(N,m) / fock(N,m) 
Coherent state  coherent(N,alpha) 
alpha = complex number (eigenvalue) for requested coherent state 
Coherent density matrix (outer product)  coherent_dm(N,alpha) 
same as coherent(N,alpha) 
Thermal density matrix (for n particles)  thermal_dm(N,n) 
n = particle number expectation value 
and operators:
Operators  Command (# means optional)  Inputs 

Charge operator  charge(N,M=N) 
Diagonal operator with entries from M..0..N. 
Commutator  commutator(A, B, kind) 
Kind = ‘normal’ or ‘anti’. 
Diagonals operator  qdiags(N) 
Quantum object created from arrays of diagonals at given offsets. 
Displacement operator (Singlemode)  displace(N,alpha) 
N=number of levels in Hilbert space, alpha = complex displacement amplitude. 
Higher spin operators  jmat(j,#s) 
j = integer or halfinteger representing spin, s = ‘x’, ‘y’, ‘z’, ‘+’, or ‘‘ 
Identity  qeye(N) 
N = number of levels in Hilbert space. 
Lowering (destruction) operator  destroy(N) 
same as above 
Momentum operator  momentum(N) 
same as above 
Number operator  num(N) 
same as above 
Phase operator (Singlemode)  phase(N, phi0) 
Singlemode PeggBarnett phase operator with ref phase phi0. 
Position operator  position(N) 
same as above 
Raising (creation) operator  create(N) 
same as above 
Squeezing operator (Singlemode)  squeeze(N, sp) 
N=number of levels in Hilbert space, sp = squeezing parameter. 
Squeezing operator (Generalized)  squeezing(q1, q2, sp) 
q1,q2 = Quantum operators (Qobj) sp = squeezing parameter. 
SigmaX  sigmax() 

SigmaY  sigmay() 

SigmaZ  sigmaz() 

Sigma plus  sigmap() 

Sigma minus  sigmam() 

Tunneling operator  tunneling(N,m) 
Tunneling operator with elements of the form \(N><N+m + N+m><N\). 
As an example, we give the output for a few of these functions:
In [6]: basis(5,3)
Out[6]:
Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket
Qobj data =
[[ 0.]
[ 0.]
[ 0.]
[ 1.]
[ 0.]]
In [7]: coherent(5,0.50.5j)
Out[7]:
Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket
Qobj data =
[[ 0.77880170+0.j ]
[ 0.389391420.38939142j]
[ 0.000000000.27545895j]
[0.078986170.07898617j]
[0.04314271+0.j ]]
In [8]: destroy(4)
Out[8]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False
Qobj data =
[[ 0. 1. 0. 0. ]
[ 0. 0. 1.41421356 0. ]
[ 0. 0. 0. 1.73205081]
[ 0. 0. 0. 0. ]]
In [9]: sigmaz()
Out[9]:
Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
Qobj data =
[[ 1. 0.]
[ 0. 1.]]
In [10]: jmat(5/2.0,'+')
Out[10]:
Quantum object: dims = [[6], [6]], shape = (6, 6), type = oper, isherm = False
Qobj data =
[[ 0. 2.23606798 0. 0. 0. 0. ]
[ 0. 0. 2.82842712 0. 0. 0. ]
[ 0. 0. 0. 3. 0. 0. ]
[ 0. 0. 0. 0. 2.82842712 0. ]
[ 0. 0. 0. 0. 0. 2.23606798]
[ 0. 0. 0. 0. 0. 0. ]]
Qobj attributes¶
We have seen that a quantum object has several internal attributes, such as data, dims, and shape. These can be accessed in the following way:
In [11]: q = destroy(4)
In [12]: q.dims
Out[12]: [[4], [4]]
In [13]: q.shape
Out[13]: (4, 4)
In general, the attributes (properties) of a Qobj
object (or any Python class) can be retrieved using the Q.attribute notation. In addition to the attributes shown with the print
function, the Qobj
class also has the following:
Property  Attribute  Description 

Data  Q.data 
Matrix representing state or operator 
Dimensions  Q.dims 
List keeping track of shapes for individual components of a multipartite system (for tensor products and partial traces). 
Shape  Q.shape 
Dimensions of underlying data matrix. 
is Hermitian?  Q.isherm 
Is the operator Hermitian or not? 
Type  Q.type 
Is object of type ‘ket, ‘bra’, ‘oper’, or ‘super’? 
For the destruction operator above:
In [14]: q.type
Out[14]: 'oper'
In [15]: q.isherm
Out[15]: False
In [16]: q.data
Out[16]:
<4x4 sparse matrix of type '<class 'numpy.complex128'>'
with 3 stored elements in Compressed Sparse Row format>
The data attribute returns a message stating that the data is a sparse matrix. All Qobj
instances store their data as a sparse matrix to save memory. To access the underlying dense matrix one needs to use the qutip.Qobj.full
function as described below.
Qobj Math¶
The rules for mathematical operations on Qobj
instances are similar to standard matrix arithmetic:
In [17]: q = destroy(4)
In [18]: x = sigmax()
In [19]: q + 5
Out[19]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False
Qobj data =
[[ 5. 1. 0. 0. ]
[ 0. 5. 1.41421356 0. ]
[ 0. 0. 5. 1.73205081]
[ 0. 0. 0. 5. ]]
In [20]: x * x
Out[20]:
Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
Qobj data =
[[ 1. 0.]
[ 0. 1.]]
In [21]: q ** 3
Out[21]:
Quantum object: dims = [[4], [4]], shape = (4, 4), type = oper, isherm = False
Qobj data =
[[ 0. 0. 0. 2.44948974]
[ 0. 0. 0. 0. ]
[ 0. 0. 0. 0. ]
[ 0. 0. 0. 0. ]]
In [22]: x / np.sqrt(2)
Out[22]:
Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True
Qobj data =
[[ 0. 0.70710678]
[ 0.70710678 0. ]]
Of course, like matrices, multiplying two objects of incompatible shape throws an error:
In [23]: q * x

TypeError Traceback (most recent call last)
<ipythoninput23c5138e004127> in <module>()
> 1 q * x
~/anaconda/lib/python3.6/sitepackages/qutip4.3.0.dev0+0c3b404cpy3.6macosx10.9x86_64.egg/qutip/qobj.py in __mul__(self, other)
513
514 else:
> 515 raise TypeError("Incompatible Qobj shapes")
516
517 elif isinstance(other, np.ndarray):
TypeError: Incompatible Qobj shapes
In addition, the logic operators is equal == and is not equal != are also supported.
Functions operating on Qobj class¶
Like attributes, the quantum object class has defined functions (methods) that operate on Qobj
class instances. For a general quantum object Q
:
Function  Command  Description 

Check Hermicity  Q.check_herm() 
Check if quantum object is Hermitian 
Conjugate  Q.conj() 
Conjugate of quantum object. 
Cosine  Q.cosm() 
Cosine of quantum object. 
Dagger (adjoint)  Q.dag() 
Returns adjoint (dagger) of object. 
Diagonal  Q.diag() 
Returns the diagonal elements. 
Diamond Norm  Q.dnorm() 
Returns the diamond norm. 
Eigenenergies  Q.eigenenergies() 
Eigenenergies (values) of operator. 
Eigenstates  Q.eigenstates() 
Returns eigenvalues and eigenvectors. 
Eliminate States  Q.eliminate_states(inds) 
Returns quantum object with states in list inds removed. 
Exponential  Q.expm() 
Matrix exponential of operator. 
Extract States  Q.extract_states(inds) 
Qobj with states listed in inds only. 
Full  Q.full() 
Returns full (not sparse) array of Q’s data. 
Groundstate  Q.groundstate() 
Eigenval & eigket of Qobj groundstate. 
Matrix Element  Q.matrix_element(bra,ket) 
Matrix element <braQket> 
Norm  Q.norm() 
Returns L2 norm for states, trace norm for operators. 
Overlap  Q.overlap(state) 
Overlap between current Qobj and a given state. 
Partial Trace  Q.ptrace(sel) 
Partial trace returning components selected using ‘sel’ parameter. 
Permute  Q.permute(order) 
Permutes the tensor structure of a composite object in the given order. 
Sine  Q.sinm() 
Sine of quantum operator. 
Sqrt  Q.sqrtm() 
Matrix sqrt of operator. 
Tidyup  Q.tidyup() 
Removes small elements from Qobj. 
Trace  Q.tr() 
Returns trace of quantum object. 
Transform  Q.transform(inpt) 
A basis transformation defined by matrix or list of kets ‘inpt’ . 
Transpose  Q.trans() 
Transpose of quantum object. 
Truncate Neg  Q.trunc_neg() 
Truncates negative eigenvalues 
Unit  Q.unit() 
Returns normalized (unit) vector Q/Q.norm(). 
In [24]: basis(5, 3)
Out[24]:
Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket
Qobj data =
[[ 0.]
[ 0.]
[ 0.]
[ 1.]
[ 0.]]
In [25]: basis(5, 3).dag()
Out[25]:
Quantum object: dims = [[1], [5]], shape = (1, 5), type = bra
Qobj data =
[[ 0. 0. 0. 1. 0.]]
In [26]: coherent_dm(5, 1)
Out[26]:
Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True
Qobj data =
[[ 0.36791117 0.36774407 0.26105441 0.14620658 0.08826704]
[ 0.36774407 0.36757705 0.26093584 0.14614018 0.08822695]
[ 0.26105441 0.26093584 0.18523331 0.10374209 0.06263061]
[ 0.14620658 0.14614018 0.10374209 0.05810197 0.035077 ]
[ 0.08826704 0.08822695 0.06263061 0.035077 0.0211765 ]]
In [27]: coherent_dm(5, 1).diag()
Out[27]: array([ 0.36791117, 0.36757705, 0.18523331, 0.05810197, 0.0211765 ])
In [28]: coherent_dm(5, 1).full()
Out[28]:
array([[ 0.36791117+0.j, 0.36774407+0.j, 0.26105441+0.j, 0.14620658+0.j,
0.08826704+0.j],
[ 0.36774407+0.j, 0.36757705+0.j, 0.26093584+0.j, 0.14614018+0.j,
0.08822695+0.j],
[ 0.26105441+0.j, 0.26093584+0.j, 0.18523331+0.j, 0.10374209+0.j,
0.06263061+0.j],
[ 0.14620658+0.j, 0.14614018+0.j, 0.10374209+0.j, 0.05810197+0.j,
0.03507700+0.j],
[ 0.08826704+0.j, 0.08822695+0.j, 0.06263061+0.j, 0.03507700+0.j,
0.02117650+0.j]])
In [29]: coherent_dm(5, 1).norm()
Out[29]: 1.0000000000000004
In [30]: coherent_dm(5, 1).sqrtm()
Out[30]:
Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = False
Qobj data =
[[ 0.36791119 +0.00000000e+00j 0.36774406 +0.00000000e+00j
0.26105440 +0.00000000e+00j 0.14620658 +0.00000000e+00j
0.08826704 +0.00000000e+00j]
[ 0.36774406 +0.00000000e+00j 0.36757705 +3.17312987e11j
0.26093584 +5.80360966e11j 0.14614018 4.24987846e11j
0.08822695 2.33450385e10j]
[ 0.26105440 +0.00000000e+00j 0.26093584 +5.80360966e11j
0.18523332 +1.06147200e10j 0.10374209 7.77296761e11j
0.06263061 4.26977453e10j]
[ 0.14620658 +0.00000000e+00j 0.14614018 4.24987846e11j
0.10374209 7.77296761e11j 0.05810197 +5.69200369e11j
0.03507700 +3.12667872e10j]
[ 0.08826704 +0.00000000e+00j 0.08822695 2.33450385e10j
0.06263061 4.26977453e10j 0.03507700 +3.12667872e10j
0.02117650 +1.71751818e09j]]
In [31]: coherent_dm(5, 1).tr()
Out[31]: 1.0000000000000002
In [32]: (basis(4, 2) + basis(4, 1)).unit()
Out[32]:
Quantum object: dims = [[4], [1]], shape = (4, 1), type = ket
Qobj data =
[[ 0. ]
[ 0.70710678]
[ 0.70710678]
[ 0. ]]