Friday, June 29, 2012

QuTiP: The First Year

Although the first version of QuTiP wasn't released until July 29, 2011, the Goggle Code repository and website has been officially active for one year now! On this one year anniversary, I thought I would share some of the statistics about QuTiP that have been collected:

# of Downloads: 1,000+
(we lost the ability to keep track with the new webpage layout)
# of Citations: 2
Unique Vistors: 2,036
Total Visits: 9,261
Pages Viewed: 43,253
# of Countries: 74
Number of QuTiP visitors from various cities around the world.

Both Rob and I are quite happy with the way QuTiP has been accepted, and hope that people are finding these tools to be useful.

Monday, June 25, 2012

The Basis of Errors

Numerical simulations are never perfect.  Of course, the fundamental reason for this is the limit set by floating-point numbers.  However, more often than not, it is an error made by the user in coding their problem that leads to the primary source of error in a calculation.  Here, we will look at one such error by considering the dynamics of a driven system composed of two-coupled oscillators.  Here we drive oscillator B with a classical drive, and assume the initial state is both oscillators in the ground state.  The QuTiP code, and resulting plot is given below: 

"""
Driven system of two-coupled harmonic oscillators
"""
from qutip import *
from pylab import *

wa  = 1.0 * 2 * pi   # frequency of system a
wb  = 1.0 * 2 * pi   # frequency of system a
wab = 0.2 * 2 * pi   # coupling frequency
ga = 0.05 * 2 * pi    # dissipation rate of system a
gb = 0.05 * 2 * pi    # dissipation rate of system b
Na = 7              # number of states in system a
Nb = 7              # number of states in system b 
E= 1 * 2 * pi
a = tensor(destroy(Na), qeye(Nb))
b = tensor(qeye(Na), destroy(Nb))
na = a.dag() * a
nb = b.dag() * b
H = wa*na+wb*nb+wab*(a.dag()*b+a*b.dag())+E*(b+b.dag())

# start with both oscillators in ground state
psi0 = tensor(basis(Na), basis(Nb))
#construct collapse operators
c_op_list = []
c_op_list.append(sqrt(ga) * a)
c_op_list.append(sqrt(gb) * b)

tlist = linspace(0, 5, 101)

#run simulation
data1 = mesolve(H,psi0,tlist,c_op_list,[na,nb])

#plot results
plot(tlist,data1.expect[0],'b',tlist,data1.expect[1],'r',lw=2)
xlabel('Time',fontsize=14)
ylabel('Excitations',fontsize=14)
legend(('Oscillator A', 'Oscillator B'))
show()

Fig1: Coupled oscillator evolution.

Now, looking at the plot, we see that the results are what we would expect intuitively from our initial setup.  Since we drive oscillator B, we would expect the number of excitations in B to grow large before the coupling with oscillator A starts to drive energy into this mode.  At later times, we see that the energy goes back and forth.

If this graph was in a publication, chances are it would pass the referees just fine.  Especially if we are like everyone else and do not attach the source code for this plot!  However, the graph above is in fact wrong.  Our model is correct, so qualitatively it gives reasonable answers.  However, quantitatively it is off at some times by over 100%!  So where did we screw up?  In our initial setup, we chose to have N=7 states for both of our resonators.  If we were naive, then looking at the plot, we might assume that this is a big enough Hilbert space since we have at most ~3 excitations in any given oscillator.  Fortunately for us, we paid attention in class, and we remember that an harmonic oscillator driven by a classical drive tends to produce coherent states, and a coherent state has a Poisson distribution over a wide range of number states.  Therefore, in choosing only 7 states, we are in fact chopping off some of the system dynamics.  Since this truncation will be most pronounced when the system has the largest number of excitations. lets look at what a more accurate model with N=10 states gives us at time t=0.50 for oscillator B:
Fig.2: Distribution for oscillator B at t=0.50
overlaid with coherent state distribution.
Blue states are truncated when N=7.

From Fig. 2, we can immediately see the error.  We are effectively ignoring the contributions from the higher modes (blue) of the generated (nearly) coherent state when N=7.  It should not be surprising that the results at later times are not correct.  Including more states (N=10) gives the following results.

Fig 3.: Comparison of dynamics with N=7 and N=10 states.

In this case, the average error is 22.4%, and as alluded to earlier, is over 100% at some time-steps.  We can look at the error between the data for N states vs. N-1 as we increase N:

Fig. 4: Error between data for N and N-1 oscillator states.

We can see that the error begins to level off starting around N=10, where the increase in the number of oscillator states has little effect on the numerics.

The final message: Check to see if the number of states you are using is in fact large enough by visually checking the effect of adding more states, or better yet, plotting the error as a function of system size.  And as always, include your code in your publications.  

Tuesday, June 19, 2012

Why Release Your Source Code?

(and an example)

Science is all about reproducibility.  Twenty to thirty years ago, this usually meant reproducing the experimental results of another group, or verifying a series of calculations from a paper.  With the rapid expansion of computing power, and the push to ever more sophisticated models, these days it is extremely rare to find a paper that does not include some form of computer calculation/simulation.  Yet at the same time, the ability to reproduce simulation results is hampered by the fact that almost no one releases the computer code for their papers. When looking at a simulation plot from one of these papers, you cannot be sure whether the answer presented is in fact valid.  Perhaps they missed a factor of 2, maybe worse? Moreover, in some fields such as cosmology, the output of computer programs provides the only incite into physical processes that are out of reach to experimentalist, thus making the validation of the underlying computer codes a top priority.  However, regardless of the field, the release of numerical codes, along with analytical results, is needed for complete transparency and validation of published research.  Recently, this issue has started to receive some much needed attention.  The latest article came out at the beginning of this year:


highlighting the importance of transparent code, and giving some interesting counter examples that resulted in a number of errors.  Some other related articles can be found here:


In 2010 we started QuTiP with the goal of being a completely open-source, numerical simulation package for quantum mechanics research and education.  Being based on the Python programming language and the SciPy and NumPy packages means that the user has access to every single line of code used in the simulation. Contrast this to the quantum optics toolbox where, although the toolbox itself is open-source, the Matlab code on which it runs is surely not.  The propriety nature of the algorithms used in commercial software provides an additional barrier to scientific reproducibility (not to mention they cost some serious money).

Example: (updated 28/06/12)

We fully encourage QuTiP users to help further the reproducibility of computational science and release their source code in their publications, or possibly submit it to us as a demo.  Here we highlight one such example kindly given to us by Catherine Holloway at the IQC in Waterloo.  From the authors own mouth:

----
This code allows us to compare simulations of QKD to experimental
results, for example, we have done this in these papers:

http://arxiv.org/abs/1109.2519
http://arxiv.org/abs/1007.4495

In addition, this allows us to test how long QKD with entanglement can
go, for example, between the ground and a satellite, with different
configurations of detectors, and for telecommunications optical fiber
links.

We are currently using this simulation to develop a model for the
optimal squeezing parameter for any channel efficiency and background
noise, and the resulting secure key rate and two-fold coincidence
rates for this optimal squeezing parameter. In many real-world
implementations, such as a satellite link, the background count and
loss fluctuate randomly over the course of a link, and being able to
re-adjust the power level of the source (and thus the squeezing
parameter) in real-time based on the current values of efficiency and
background would be a great boon.
----

The QuTiP file is somewhat lengthy so we have attached both html and Python versions as separate links:


The output from this example, giving the key and bit error rates as a function of loss is given below.

Thursday, June 14, 2012

Launchpad PPA for QuTiP releases

Installing QuTiP on Ubuntu just got a lot easier. Using our new PPA on Launchpad, QuTiP and all its dependencies can now be installed using the following commands:
$ sudo add-apt-repository ppa:jrjohansson/qutip-releases
$ sudo apt-get update
$ sudo apt-get install python-qutip
On a desktop/laptop system you'd probably also want to install the package texlive-latex-extra:
$ sudo apt-get install texlive-latex-extra
For subscribers of the qutip-release PPA, new releases of QuTiP will be automatically available through the Ubuntu update manager.
There is also a PPA called qutip-trunk, which provides access to daily builds of the latest development version of QuTiP.