# Constructing Operators and States

<h2 style='color:green'>Part #1</h2>

## Load necessary modules

Import statements like these need to be at the top of every notebook you create.


```python
import numpy as np                # Needed to create arrays (vectors and matrices).
import qutip as qt                # the QuTiP library.
import matplotlib.pyplot as plt   # Plotting tools.
%matplotlib inline                
```

## Constructing Operators and States for Two-Level Systems

Start by generating the Pauli spin operators and identity operator for a two-level system. From your favorite QM textbook:

$$
\begin{equation}
\sigma_{x} = \begin{bmatrix}
0 & 1 \\
1 & 0 
\end{bmatrix},
\ \
\sigma_{y} = \begin{bmatrix}
0 & -i \\
i & 0 
\end{bmatrix},
\ \
\sigma_{z} = \begin{bmatrix}
1 & 0 \\
0 & -1 
\end{bmatrix},
\ \ 
I = \begin{bmatrix}
1 & 0 \\
0 & 1 
\end{bmatrix}
\end{equation}
$$


```python
qt.sigmax()
```




Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0\\1.0 & 0.0\\\end{array}\right)\end{equation*}




```python
qt.sigmay()
```




Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & -1.0j\\1.0j & 0.0\\\end{array}\right)\end{equation*}




```python
qt.sigmaz()
```




Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0\\0.0 & -1.0\\\end{array}\right)\end{equation*}




```python
qt.identity(2) # Identity works for any dimension, not just 2.
```




Quantum object: dims = [[2], [2]], shape = (2, 2), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}1.0 & 0.0\\0.0 & 1.0\\\end{array}\right)\end{equation*}



### What implicit assumption did we make when writing down these operators?

We have implicity choosen the z-axis as our preferred basis (representation).  What do the corresponding state vectors look like?


```python
up = qt.basis(2,0) # First number is Hilbert dimension, second labels the state
up
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\0.0\\\end{array}\right)\end{equation*}



If I don't know what the inputs are, then it is always possible to ask for help.


```python
qt.basis?
```


```python
down = qt.basis(2,1)
down
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\1.0\\\end{array}\right)\end{equation*}



Check the action of $\sigma_{z}$ on the states:


```python
qt.sigmaz() * up
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\0.0\\\end{array}\right)\end{equation*}




```python
qt.sigmaz() * down
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\-1.0\\\end{array}\right)\end{equation*}



Of course, given a basis for our Hilbert space, we can form any other state via a linear combination of basis vectors:
$$
\begin{equation}
|\Psi\rangle = a|\uparrow\rangle+b|\downarrow\rangle
\end{equation}
$$


```python
psi = 5*up - 1j*down # Complex numbers in Python written as e.g. 1+3j.
psi
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}5.0\\-1.0j\\\end{array}\right)\end{equation*}



State is not properly normalized.  Can be easily fixed.


```python
psi.unit()
```




Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.981\\-0.196j\\\end{array}\right)\end{equation*}



What's going on here?  See lecture slides for description of the Quantum Object class.

<h2 style='color:green'>Part #2</h2>

## Constructing Operators and States for Oscillators

Unlike two-level systems, oscillators live in a formally infinite Hilbert space.  Therefore we must be careful as to where we truncate the state space for simulation.


#### The truncation of state space can lead to misunderstandings and error, if not accounted for.

A good choice of basis, and the one used by QuTiP is the usual number state $|n\rangle$ (Fock) basis.


```python
N = 5 # Must always specify how large you want the Hilbert space to be.
psi = qt.basis(N,0)
psi
```




Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}1.0\\0.0\\0.0\\0.0\\0.0\\\end{array}\right)\end{equation*}



This is the ground state $|0\rangle$ of the number state basis. To get the $|1\rangle$ state simply do:


```python
qt.basis(N,1)
```




Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\1.0\\0.0\\0.0\\0.0\\\end{array}\right)\end{equation*}



What this shows is that for a given Hilbert size $N$, the corresponding basis vectors go from $n=0 \rightarrow N-1$.


We know that to move up and down the number state basis we need creation and annihiation operators.


```python
a = qt.destroy(N)
a
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 1.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.414 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 1.732 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 2.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}



To build the creation operator we could do `create(N)`, but lets us a `Qobj` method instead:


```python
a.dag() # The 'dag' method creates the dagger (adjoint) of an operator.
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = False\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\1.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.414 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.732 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 2.0 & 0.0\\\end{array}\right)\end{equation*}




```python
a.dag()*psi
```




Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\1.0\\0.0\\0.0\\0.0\\\end{array}\right)\end{equation*}




```python
a.dag()**2 * psi
```




Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\0.0\\1.414\\0.0\\0.0\\\end{array}\right)\end{equation*}



We can also build operators such as the number operator:


```python
a.dag()*a
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 2.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 3.000 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 4.0\\\end{array}\right)\end{equation*}



or we could have just used the builtin number operator function:


```python
qt.num(N)
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 1.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 2.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 3.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 4.0\\\end{array}\right)\end{equation*}



## Building Density Matrices

QuTiP focuses on open quantum systesm, i.e. systems that interact with an environment.  This demands the use of density matrices, rather than state vectors, as the interaction with the environment, in general, produces a mixed state.

Typically, we prepare our system in a given pure state.  The corresponding density matrix would then just be formed by the outer product $|\Psi\rangle\langle \Psi|$.


```python
psi = qt.basis(N,2)
psi
```




Quantum object: dims = [[5], [1]], shape = (5, 1), type = ket\begin{equation*}\left(\begin{array}{*{11}c}0.0\\0.0\\1.0\\0.0\\0.0\\\end{array}\right)\end{equation*}




```python
psi*psi.dag()
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}



We could also use the built in function `ket2dm()` to do the product for us:


```python
qt.ket2dm(psi)
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}



QuTiP has a collection of built in density operators that are commonly used:


```python
qt.fock_dm(N,2)
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 1.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.0\\\end{array}\right)\end{equation*}




```python
qt.coherent_dm(N,alpha=1) #alpha specifies the coherent state amplitude
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.368 & 0.368 & 0.261 & 0.146 & 0.088\\0.368 & 0.368 & 0.261 & 0.146 & 0.088\\0.261 & 0.261 & 0.185 & 0.104 & 0.063\\0.146 & 0.146 & 0.104 & 0.058 & 0.035\\0.088 & 0.088 & 0.063 & 0.035 & 0.021\\\end{array}\right)\end{equation*}



The coherent states represent one example of a situation where the state vector or density matrix is a non-sparse in the Fock basis.  This is because they are generated using a displacement operator using `expm`.


```python
qt.thermal_dm(N,1) #`1` indicates the average number of particles in the thermal state
```




Quantum object: dims = [[5], [5]], shape = (5, 5), type = oper, isherm = True\begin{equation*}\left(\begin{array}{*{11}c}0.516 & 0.0 & 0.0 & 0.0 & 0.0\\0.0 & 0.258 & 0.0 & 0.0 & 0.0\\0.0 & 0.0 & 0.129 & 0.0 & 0.0\\0.0 & 0.0 & 0.0 & 0.065 & 0.0\\0.0 & 0.0 & 0.0 & 0.0 & 0.032\\\end{array}\right)\end{equation*}



These are just simple examples of density matrices.  The more interesting ones comes from doing open-system time-evolution.

3687d3be4fda48411bc16c3373c4ae7f8e86d3e5
ipynb
Jupyter Notebook
notebooks/Constructing_Operators_States.ipynb
nonhermitian/dartmouth_2017
d4b4bcb422f85389228494e3996e4435a071945b
BSD-3-Clause
notebooks/Constructing_Operators_States.ipynb
nonhermitian/dartmouth_2017
d4b4bcb422f85389228494e3996e4435a071945b
BSD-3-Clause
notebooks/Constructing_Operators_States.ipynb
nonhermitian/dartmouth_2017
d4b4bcb422f85389228494e3996e4435a071945b
BSD-3-Clause
Qwen/Qwen-72B
1. YES
2. YES