# Taking Python to the Next Level

*
A brief intro to simulating quantum systems with QuTiP.*

With the reincarnation of *Linux Journal*, I thought I'd take this
article through a quantum leap (pun intended) and look at quantum
computing. As was true with the beginning of parallel programming, the next
hurdle in quantum computing is developing algorithms that can do useful
work while harnessing the full potential of this new hardware.

Unfortunately though, most people don't have a handy quantum computer lying around on which they can develop code. The vast majority will need to develop ideas and algorithms on simulated systems, and that's fine for such fundamental algorithm design.

So, let's take look at one of the Python modules available to simulate quantum systems—specifically, QuTiP. For this short article, I'm focusing on the mechanics of how to use the code rather than the theory of quantum computing.

The first step is installing the QuTiP module. On most machines, you can install it with:

```
sudo pip install qutip
```

This should work fine for most people. If you need some latest-and-greatest feature, you always can install QuTiP from source by going to the home page.

Once it's installed, verify that everything worked by starting up a Python instance and entering the following Python commands:

```
>> from qutip import *
>> about()
```

You should see details about the version numbers and installation paths.

The first step is to create a qubit. This is the simplest unit of data to be used for quantum calculations. The following code generates a qubit for two-level quantum systems:

```
>> q1 = basis(2,0)
>> q1
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[ 1.]
[ 0.]]
```

By itself, this object doesn't give you much. The simulation kicks in when you start applying operators to such an object. For example, you can apply the sigma plus operator (which is equivalent to the raising operator for quantum states). You can do this with one of the operator functions:

```
>> q2 = sigmap * q1
>> q2
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[ 0.]
[ 0.]]
```

As you can see, you get the zero vector as a result from the application of this operator.

You can combine multiple qubits into a tensor object. The following code shows how that can work:

```
>> from qutip import *
>> from scipy import *
>> q1 = basis(2, 0)
>> q2 = basis(2,0)
>> print q1
Quantum object: dims = [[2], [1]], shape = [2, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]]
>> print q2
Quantum object: dims = [[2], [1]], shape = [2, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]]
>> print tensor(q1,q2)
Quantum object: dims = [[2, 2], [1, 1]], shape = [4, 1], type = ket
Qobj data =
[[ 1.]
[ 0.]
[ 0.]
[ 0.]]
```

This will couple them together, and they'll be treated as a single object by operators. This lets you start to build up systems of multiple qubits and more complicated algorithms.

More general objects and operators are available when you start to get to even more complicated algorithms. You can create the basic quantum object with the following constructor:

```
>> q = Qobj([[1], [0]])
>> q
Quantum object: dims = [[2], [1]], shape = [2, 1], type = ket
Qobj data =
[[1.0]
[0.0]]
```

These objects have several visible properties, such as the shape and number of dimensions, along with the actual data stored in the object. You can use these quantum objects in regular arithmetic operations, just like any other Python objects. For example, if you have two Pauli operators, sz and sy, you could create a Hamiltonian, like this:

```
>> H = 1.0 * sz + 0.1 * sy
```

You can then apply operations to this compound object. You can get the trace with the following:

```
>> H.tr()
```

In this particular case, you can find the eigen energies for the given
Hamiltonian with the method `eigenenergies()`

:

```
>> H.eigenenergies()
```

Several helper objects also are available to create these quantum objects for
you. The basis constructor used earlier is one of those helpers. There are
also other helpers, such as `fock()`

and `coherent()`

.

Because you'll be dealing with states that are so far outside your usual day-to-day experiences, it may be difficult to understand what is happening within any particular algorithm. Because of this, QuTiP includes a very complete visualization library to help see, literally, what is happening within your code. In order to initialize the graphics libraries, you'll likely want to stick the following code at the top of your program:

```
>> import matplotlib.pyplot as plt
>> import numpy as np
>> from qutip import *
```

From here, you can use the `sphereplot()`

function to generate
three-dimensional spherical plots of orbitals. The
`plot_energy_levels()`

function takes a given quantum object and calculates the associated
energies for the object. Along with the energies, you can plot the
expectation values for a given system with the function
`plot_expectation_values()`

.

I've covered only the barest tip of the proverbial iceberg when it comes to using QuTiP. There is functionality that allows you to model entire quantum systems and see them evolving over time. I hope this introduction sparks your interest in the QuTiP tool if you decide to embark on research in quantum systems and computation.

Joey Bernard has a background in both physics and computer science. This serves him well in his day job as a computational research consultant at the University of New Brunswick. He also teaches computational physics and parallel programming.