Quantum process tomography (QPT) is a useful technique for characterizing experimental implementations of quantum gates involving a small number of qubits. Recently, QPT has been used in a number of beautiful experiments with for example superconducting qubits [Bialczak2010][Dewes2012], nuclear spins [Steger2012], NV-centers [Fuchs2012], ion traps [Riebe2006], just to mention a few.

QPT can also be a useful theoretical tool, which can give insight in how a gate transforms states, and be used to study how noise or other imperfections deteriorate a gate. Whereas a fidelity or distance measure can give a single number that indicates how far from ideal a gate is, a quantum process tomography analysis can give detailed information about exactly what kind of errors various imperfections introduce.

In QuTiP, we have recently added support for computing and visualizing quantum process tomography matrices. Here we give a simple example that demonstrates these new functions for a few common one, two and three qubit gates. The gates in this example are all available in QuTiP's gate module.

```
"""
Plot the process tomography matrices for some 1, 2, and 3-qubit qubit gates.
"""
from qutip import *
gate_list = [['C-NOT', cnot()],
['SWAP', swap()],
['$i$SWAP', iswap()],
['$\sqrt{i\mathrm{SWAP}}$', sqrtiswap()],
['S-NOT', snot()],
['$\pi/2$ phase gate', phasegate(pi/2)],
['Toffoli', toffoli()],
['Fredkin', fredkin()]]
# loop though the gate list and plot the gates
for gate in gate_list:
name = gate[0]
U_psi = gate[1]
N = len(U_psi.dims[0]) # number of qubits
# create a superoperator for the density matrix
# transformation rho = U_psi * rho_0 * U_psi.dag()
U_rho = spre(U_psi) * spost(U_psi.dag())
# operator basis for the process tomography
op_basis = [[qeye(2), sigmax(), sigmay(), sigmaz()] for i in range(N)]
# labels for operator basis
op_label = [["i", "x", "y", "z"] for i in range(N)]
# calculate the chi matrix
chi = qpt(U_rho, op_basis)
# visualize the chi matrix
qpt_plot_combined(chi, op_label, name)
show()
```

These figures are all examples of ideal quantum gates. To illustrate how the quality of a gate can deteriorate due to interaction between the qubits and their environment, let's consider a simple but experimentally realizable implementation of the two-qubit iSWAP gate. One way of implementing this gate is to produce the interaction Hamiltonian $H = g\left(\sigma_x\otimes\sigma_x + \sigma_y\otimes\sigma_y\right)$, and turn on this interaction for a period of time $T=\pi/4g$ [Schuch2003] [Steffen2006]. In the absence of noise and other imperfections, this procedure results in an ideal iSWAP gate to be applied to the two qubits. With QuTiP, we can easily simulate this process, and additionally study how and to what extent the gate deteriorates due to dissipation, imperfect switching of the interaction, detuning, etc. The following code demonstrates how to do this kind of analysis using QuTiP.

```
"""
Plot the process tomography matrix for a 2-qubit iSWAP gate.
"""
from qutip import *
g = 1.0 * 2 * pi # coupling strength
g1 = 0.75 # relaxation rate
g2 = 0.25 # dephasing rate
n_th = 1.5 # bath temperature
T = pi/(4*g)
H = g * (tensor(sigmax(), sigmax()) + tensor(sigmay(), sigmay()))
psi0 = tensor(basis(2,1), basis(2,0))
c_ops = []
# qubit 1 collapse operators
sm1 = tensor(sigmam(), qeye(2))
sz1 = tensor(sigmaz(), qeye(2))
c_ops.append(sqrt(g1 * (1+n_th)) * sm1)
c_ops.append(sqrt(g1 * n_th) * sm1.dag())
c_ops.append(sqrt(g2) * sz1)
# qubit 2 collapse operators
sm2 = tensor(qeye(2), sigmam())
sz2 = tensor(qeye(2), sigmaz())
c_ops.append(sqrt(g1 * (1+n_th)) * sm2)
c_ops.append(sqrt(g1 * n_th) * sm2.dag())
c_ops.append(sqrt(g2) * sz2)
# process tomography basis
op_basis = [[qeye(2), sigmax(), sigmay(), sigmaz()]] * 2
op_label = [["i", "x", "y", "z"]] * 2
# dissipative gate
U_diss = propagator(H, T, c_ops)
chi = qpt(U_diss, op_basis)
qpt_plot_combined(chi, op_label)
# ideal gate
U_psi = (-1j * H * T).expm()
U_ideal = spre(U_psi) * spost(U_psi.dag())
chi = qpt(U_ideal, op_basis)
qpt_plot_combined(chi, op_label)
show()
```

The code produces the following figures (the ideal iSWAP gate to the left, the dissipative one to the right):

Note: the quantum process tomography functions were added after the 2.0 release, so to run these examples you need to get the latest development version of QuTiP from the SVN repository. Alternatively, if you prefer to stay on the official release (recommended for stability), you can download this file and put it in the same directory as the example code and add "from qpt import *" at the top of the example files (just below the line "from qutip import *").