## A GSOC Summary

This blogpost is meant to serve as a repository of links pointing towards the work done on the Quantum Circuits GSOC project.

The project aimed to enhance the QIP module of QuTiP by adding a structure and enhancing the capabilities of circuit simulation as well as adding compatibility with other quantum libraries. While the second half of the project was aimed towards enhancing circuit simulation in the presence of noise, a change of direction was decided upon with the support of the mentors. The latter half then focussed on making important changes to the QuTiP documentation and working on the project to port the QIP sub-module of QuTiP to it’s own repository. This decision was made after exploring the previous idea of improving features related to noise and realizing that it was probably a project suited more to a longer timeframe keeping in mind my level of comfort with the material required and the amount of work required. Furthermore, the alternative tasks of shoring up QuTiP documentation and bootstrapping the new repository required more immediate attention and fit more neatly into the timeframe.

The work can be divided roughly into the following sections:

• Circuit Simulation:
Addition of measurement gates and classical controls to the QubitCircuit class and a simple circuit simulation module (PR #1274, merged).
Consolidated circuit simulation in a new class ExactSimulator for easier use and extension. Also adds a few optimizations for faster simulation (PR #1331, under review).
Added new documentation and organized existing documentation for circuits (PR #117, under review).
Added a notebook covering a tutorial on Quantum Teleportation and giving examples on circuits (PR #108, under review).
Ideas: There is a lot of new features that can now be added to the QIP module especially in terms of making circuit simulation more seamless. For example, the Processor based simulation could be incorporated in the ExactSimulator API structure by extending it. Furthermore, once the PR for ExactSimulator is merged, it would be much easier to make unitary simulation faster by modifying specific sections of the code.

• Quantum Assembly Language Support:
Added support for import from and export to the OpenQASM format. This enables further compatibility with other quantum libraries such as Qiskit and Cirq.
Import .qasm file into Quantum Circuit (PR #1291, merged).
Export Quantum Circuit to .qasm file (PR #1318, merged).
Added notebook with examples and explanations. (PR #111, under review).
Ideas: The QASM import/export modules could have better error reporting. The more immediate task is to add more example notebooks for import/export from other Quantum libraries.

• Enhancements for QuTiP documentation:
The QuTiP documentation was failing to build due to problems with ipython_directive (Issue #103) and there was another suggestion to add sphinx doctests to the documentation (Issue #115).
Addressed both issues by converting ipython code blocks to doctest/testcode/plot code blocks adding capability to test examples in documentation as well as examples in inline documentation. Also fixes the build issue (PRs #120, #1334, under review).
Ideas: Doctest style tests try to match numerical values exactly, however it is not feasible to keep the exact same precision/accuracy each time, therefore it would be easier if all such tests could somehow be matched approximately without changing the code examples visually.
• QIP Repository: I was not able to hit any significant milestones with respect to this task but I did make some inroads. I will continue working on this part of the project and the progress can be tracked at the QIP repository.

GSOC has been an xcellent experience and I would love to thanks my mentors Alex Pitchford, Boxi Li, Nathan Shammah and Neil Lambert for their amazing support and guidance. The experience has acquainted me well with the rigors of OSS and I hope to continue working on QuTiP in the future.

## GSOC: A change in direction.

It is well into the final month of the GSOC project on Quantum Circuits and Noise. Originally, the second half of the project was meant to focus on adding more functionality related to noise in Quantum Circuits. However, on further thought and suggestions by my mentors, we decided that it might be wiser to shift the focus of the project into a different area which I discuss in this post.

In the first week of August, I experimented with optimization of control pulses in the presence of noise. Currently, control pulses are added independently of the noise simulation applied to the driving hamiltonians (and the collapse operators). After getting up to the basics, it was clear that this would be a longer term project for me given my familiarity with the material and the amount of work required.

Simultaneously, I was working on writing documentation for all my previous PR’s related to the QIP module. Since the QuTiP documentation is currently not building due to an issue with ipython directives (related to sphinx). The suggested fix was to move away from ipython directives to doctest and plot(Matplotlib) directives. This would have the additional advantage of running tests on code examples in the user guide and docstrings. It took a bit longer than expected but my new PR addresses these changes.

The main challenges in shifting from ipython directives to doctest directives is that now each code example needed to be properly checked for correctness. Additionally, the documentation for both doctest and plot directives are scarce on examples. This meant that some amount of tinkering was necessary to ensure that every example worked properly. I also wrote up a small guide on how to write future examples which will be added to the upcoming developer’s guide for QuTiP initiated by Jake Lishman. A current concern to address is how to ensure that examples which might change subtly in their outputs over time can be updated for doctest without much effort.

While the aforementioned PR took most of time over the last week, the final couple of weeks for GSOC are dedicated to finishing up a test run for moving the QIP module from QuTiP into a new repository. Updates on the same can be tracked here and I aim to complete most of the work on the same before the end of the project.

## GSOC Updates: Wrapping up Circuits.

It’s been two months since the coding period for GSOC started. During this period, I have been primarily focussing on beefing up the Quantum Circuit features available in the QuTiP package. All the work has been concentrated in the QIP section of the package, a relatively new section with lots of interesting applications. I have already talked about adding measurements, circuit simulation and the ability to read and write circuits from the popular OpenQASM format. The PRs for the last part have are now merged/ready to be merged (#1291, #1318).

Over the past two weeks, I have been focussing on (marginal) efficiency improvements to the circuit simulation module in QuTiP. The PR #1331 is rather near completion. In the meanwhile, I would like to talk about some challenges I faced while working on improving circuit efficiency.

QuTiP is primarily a package that deals with simulating the dynamics of open quantum systems. My project, being focussed on exact circuit simulation, naturally does not play to the strengths of QuTiP. There are other packages which are designed for this task from the ground up. The idea is to make the circuit simulation “fast enough” so that users can play around with non-trivial sized circuits before simulating circuits by driving hamiltonians.

There are two ways to approach circuit simulation. In the first picture, we take the input state and apply the unitaries (corresponding to each gate) sequentially until we obtain the output state. This is no doubt a faster method when our circuit only needs to carry out computations for a few different input states. This is because each multiplication is of a size $2^n \times 2^n$ matrix with a $2^n$ sized vector (the total number of multiplications is equal to the number of gates in the circuit). This is how my first PR approached circuit simulation. Further progress can be made in this picture if we have faster ways of applying particular gates to a state (possibly without expanding it to the full state size).

The second picture arises where we want to pre-compute the unitary implied by the quantum circuit. In this case, we can use the gate_sequence_product function to calculate the circuit unitary. This picture requires significantly more pre-computation (in the worst case, we have to multiply two $2^n \times 2^n$ sized matrices a number of times). However, during circuit simulation, we reduce the number of matrix-vector multiplications to a minimum.

The naive method is (as previously used by gate_sequence_product) to expand each unitary to the full dimension and multiply all the expanded unitaries. For an example, consider the circuit in Figure 1. Each unitary $\mathcal{U}_i$ is first expanded to full dimension ($2^4$ in the example) and then multiplied to produce the result $\mathcal{U}$.

The naive method is obviously inefficient since we only need to expand to the dimension required for multiplication with the adjacent matrix. Furthermore, the expand_operator function can handle tensoring unitaries on disjoint qubits without doing any extra multiplications.

As a result, the improved method tries to perform multiplications on smaller dimensions while doing tensor expansion “lazily”. This tends to reduce the complexity of the resultant matrix multiplications. An example can be found for the same circuit in Figure 2.

At the present moment, this is merely a heuristic improvement. It results in the gate_sequence_product being faster by about 25%. It would be a nice exercise to figure out if this method could be extended to a properly optimized algorithm. Further gains can also be found in improving the underlying speed of multiplication and tensor expansion.

My work on quantum circuits being mostly complete, the last month is supposed to focus on adding more features to noise models and control pulses within the QIP sub-package. I am starting off by experimenting with methods to optimize control pulses for circuit gates in the presence of noise. More updates to follow in the next blog post.

## GSOC Updates: Midway Through.

This blogpost is meant to provide some updates on my project on Quantum Circuits and Noise in QuTiP. It also marks the halfway point of the GSOC timeline. It has been quite a steep but rewarding learning curve.

Last time around, we talked about the new measurements and circuit run functionalities I was adding to QuTiP. I am happy that this functionality has now been merged. One of the things that I am definitely looking forward to is how the functionality is used by others. My limited experience with design leads me to believe that users often use (design-wise) code in ways that developers are bound to miss out on. I would be very interested in getting some feedback on these new features.

The last two weeks have been spent on further additions to Quantum Circuit capabilities for QuTiP. While most of these additions seem elementary, they are essential in building up the framework of the QIP module of QuTiP. This is especially important to increase interest in contributions and usage of the module in the future, especially as it is spun-off into a separate package connected to the QuTiP core package. My work over the last couple of weeks has been divided between the following areas:

1. OpenQASM: Both the QASM input/output functionalities in QuTiP are now mostly finished. Barring review, they are good to go. The respective PRs are #1318 and #1291. While I hope people contribute to improve this functionality in the future, I have to admit that the code behind it is pretty dense. To be quite honest, that is the result of substituting an actual parser for an ad-hoc solution. I would like to note that this also made the code slightly harder to debug.
The only relief in this case is that the functionality is quite simple to test. We can simply export a Quantum Circuit in QuTiP to QASM format and then re-import it back to QuTiP to check if everything works fine. The tricky part is handling export/import of quantum gates since the QASM standard has certain different assumptions (meant more to adhere to QISKIT) than QuTiP. I think the tests do a decent job of covering most bases but only more usage will bring to light any lingering issues.
2. Circuit Capabilities: A central focus of the last week has been improving the efficiency of how we run quantum circuits in QuTiP. The circuit run functionality is quite elementary at the moment. I had a very insightful discussion with Jake Lishman, a fellow GSOC student. Jake has been working on changes to the Qobj data layer of QuTiP and had some very helpful comments that yielded immediate improvements. I have also been working on implementing some custom routines for the QIP module that should enable faster run capabilities whose improvements might also carry-over to other areas.
3. QIP sub-package: Finally, I have been working on porting over the qutip.qip to it’s own package. The first few commits can be found at PR #1. The broad outline I have for the next few days (and eventually deprecating the original module) is:
a. Port over the source code and make qutip-qip discoverable to QuTiP users as a plugin. This part is mostly done.
b. Set up tests and documentation for the new package. The major challenge here is to make both the tests and documentation for the core package and the QIP package play nice with each other.

Over the next week, I plan to complete the rest of the tasks in terms of adding circuit capabilities and move forward with the next part of the project. This will primarily involve adding new features to the noise module in QIP. More details to follow in the next blog post!

## GSOC Updates: End of Phase 1.

It’s been nearly a month since the “official” coding period for the Summer of Code started and it’s been a real delight. Working with QuTiP developers has been very rewarding especially because the community (and my mentors) is so welcoming. The receptiveness to new ideas and (even silly) questions reminding me of more academic environments which is quite nice. In the span of the last month, I have undoubtedly learned a lot about the quirks of git, making pull requests and working with code written by other devs. More important, however, has been incorporating feedback from the mentors (and the wider community) into code and documentation.

For the past couple of weeks, my work has been divided into three areas (more or less):

• Compatibility with OpenQASM: The Quantum Assembly Language (QASM) is an intermediate representation for quantum circuits, meant to abstract away the particulars of different circuit implementations. OpenQASM is supported by the two major quantum circuit simulation packages, Qiskit and Cirq. Over the last two weeks, I have added the ability to read QASM files into quantum circuits in QuTiP (#1291). Not only does this allow QIP sub-package to interface in a substantial way with Qiskit and Cirq, it also allows users to import a host of readymade circuit definitions (read as algorithms) specified as examples in the OpenQASM repository. The next step (already in the works) is to add the corresponding “export to QASM” features.

The primary challenge I faced while writing import code was reading QASM syntax from scratch. While the Qiskit parser for the same uses a lexer and parser to achieve the same effect (taking advantage of the fact that OpenQASM has a language definition), I decided to use a more lightweight approach where we read the syntax in line-by-line. This was possible because the OpenQASM syntax is not all that complicated. I hope to outline some of the details of the implementation and its differences with other implementations in a short future blogpost.

While OpenQASM is probably the most popular such instance of such an “assembly” language, there are a number of others such as cQASM and PyQuil, the numbers increasing by the day as more platforms and packages for quantum circuit simulation pop up. Hopefully as the QIP sub-package gains new capabilities, it can also accommodate more such representations, thereby allowing imports/exports between more packages.
• Refining the Measurements PR (#1274): In my last blog post, I outlined a short guide to measurements in QuTiP as a companion to my PR which stitched together measurement functions in QuTiP and added the capability of projective measurements (and, as a result, measurement gates in the circuit). Some portion of the last week was spent refining the API for measurement, as well as making it more user-friendly. Community feedback was very crucial in this regard with the addition of a number of small but useful changes.
• Last, but certainly not the least, the QuTiP team has planned to spin-off the QIP feature set as an add-on package for the core QuTiP package. Once separated, the QIP package is supposed to act as an optional extension to QuTiP, augmenting it with quantum information processing features. This serves the dual purpose of allowing more focussed development on the QIP features as well as enhancing maintainability of the core QuTiP package. I hope to help this transition with a test-run in the next few weeks. During the last week, we made a number of important decisions with respect to the maintenance of the new package, and I hope to outline them in a future blogpost. This is also meant to set the stage for further spin-offs of packages from QuTiP.

My primary note to myself over the last few weeks has been to budget some time for revisions to code/documentation I add. This is undoubtedly necessary in the development process but not something I paid much attention to before. Thanks for reading!

## An Introduction to Quantum Measurements in QuTiP.

While the QIP module of QuTiP has been evolving to include a lot of new functionality, the ability to measure states has been absent till now. A significant development was the addition of quantum mechanical measurements by Simon Cross. While measurements using hermitian observables are pretty general, the form in which measurements in quantum information are usually specified is directly in terms of the projection operators. More importantly, this also allows measurements to be further generalized to positive-operator valued measurements. The aim of this post is two-fold:

• To provide a basic overview of the different ways to carry out state measurements in QuTiP.
• To provide an idea of the interchangeability and usefulness of the different functions.

Note: The addition of projective measurements can be tracked in PR #1274.

## Observables

Observables in quantum mechanics can be specified by a hermitian operator. We will restrict our discussion to observables with only discrete values. Also, for the sake of brevity, we also restrict ourself to working with only pure states specified by kets. The measurement functions in QuTiP can handle both kets and density matrices.

Associated with a discrete observable $H$ are its eigenstates $\left| q_1 \right>, \hdots, \left| q_n \right>$ and corresponding eigenvalues $q_1, \hdots, q_n$. Let’s consider an example in QuTiP with $\sigma_z$, which measures the z-component of the spin of a spin-½ particle. First, let’s get some imports out of the way!

>>> from qutip import sigmaz, basis, tensor, identity
>>> from qutip.measurement import measure, measurement_statistics
>>> SIGMAZ = sigmaz()
>>> SIGMAZ.eigenstates()
(array([-1.,  1.]),
array([Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[ 0.]
[-1.]],
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[-1.]
[ 0.]]], dtype=object))


Since the eigenvectors of a hermitian operator are orthogonal, given that we have a state of the correct dimension, we can write the state $\left| \psi \right>$ as:

$\left| \psi \right> = \sum_i c_i \left| q_i\right>$

Now, we can calculate the probability of measuring state $\left| q_i \right>$ as $p_i = \left| \left< q_i | \psi \right> \right|^2$. This is precisely the kind of measurement embodied when the measurement_statistics function is supplied with an observable and a ket vector.

>>> state_0 = basis(2, 0)
>>> SIGMAZ = sigmaz()
>>> measurement_statistics(SIGMAZ, state_0)
(array([-1.,  1.]),
array([Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[ 0.]
[-1.]],
Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[-1.]
[ 0.]]], dtype=object),
[0, 1.0])
>>> measure(SIGMAZ, state_0)
(1.0, Quantum object: dims = [[2], [1]], shape = (2, 1), type = ket
Qobj data =
[[-1.]
[ 0.]])


When supplied with the state $\left| 0 \right>$, we obtain that the eigenvalue 1 corresponding to the eigenstate $[[-1], [0]]$ is returned with probability 1 which is what is expected. This can be confirmed by the usage of the measure function.

However, when we only want to measure a few qubits on a state vector representing a number of qubits, it gets a little more complicated. On measurement, we want the measured qubit to collapse to the result while maintaining information about the rest of the qubits. Suppose we want to measure the first qubit in a two-qubit system with the $\sigma_z \otimes I$ observable. In our example below, the two-qubit system is in the state $\left| 0 + \right>$, the first qubit in the “up” state in the $S_z$ basis and the second qubit being in the “up”-state in the $S_x$ basis.

>>> sz_I = tensor(SIGMAZ, identity(2))
>>> state_0plus = tensor(basis(2, 0), 1/(sqrt(2)) * (basis(2, 0)+ basis(2,1)))
>>> measurement_statistics(sz_I, state_0plus)
(array([-1., -1.,  1.,  1.]),
array([Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
[0.]
[1.]
[0.]],
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
[0.]
[0.]
[1.]],
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket
Qobj data =
[[1.]
[0.]
[0.]
[0.]],
Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket
Qobj data =
[[0.]
[1.]
[0.]
[0.]]], dtype=object),
[0, 0, 0.4999999999999999, 0.4999999999999999])


As expected, the hermitian operator is decomposed into two sets of degenerate eigenstates corresponding to the -1 and 1 eigenvalues. We can still obtain the correct outcomes of the first qubit by considering the two eigenstates corresponding to the +1 eigenvalue ($\left| 00 \right>, \left| 01 \right>$, only states with non-zero probability correctly predicting $\left| 0 \right>$ on the first qubit). While we can reconstruct the collapsed state that will be produced if we measure only the first qubit, the eigenstates themselves have lost the information about the second qubit.

Before we understand how to measure a subset of qubits easily, it’s instructive to know more about how general measurements can be.

## POVMs

A generalized measurement can be specified by a collection of positive semi-definite operators $E_i \geq 0$ that satisfy $\sum_i E_i = I$. This form of measurement is also known as positive-operator valued measurements (POVMs). Each $E_i$ is associated with a particular outcome and can be decomposed as $E_i = M_i^{\dagger} M_i$. For a state, we can calculate the probability of measuring a particular outcome as $p_i = \left | \left< \psi | E_i | \psi \right> \right|$ and calculate the post-measurement state as

$\left| \psi \right> \rightarrow \frac{M_i \left| \psi \right>}{\sqrt{p_i}}$

While the operators $E_i$ are enough to calculate the measurement probabilities, a particular decomposition specifying the $M_i's$ is needed to calculate the resultant state.

## PVMs

Projective measurements (PVMs) are just a special case of POVMs in which the measurement operators satisfy the additional property of the $M_i$ being projectors, i.e. $M_i M_j = \delta_{ij} M_i$. With this property, we also get that $E_i = M_i^{\dagger} = M_i$. Both POVMs and PVMs can be handled by the measure and measure_statistics functions by specifying the first argument as the list of $M_i's$.

Now, we are well-equipped to handle measurement on a subset of qubits. We just need to specify the correct projection operators. For our previous example, we can write our hermitian as:

$\sigma_z \otimes I = (-1) * \left| 0 \right> \left< 0 \right | \otimes I + (1) * \left| 1 \right> \left< 1 \right | \otimes I$

Now, we can just plug-in our projection operators into the measurement function to measure on a two qubit system.

>>> zeroid = tensor(ket2dm(basis(2, 0)), identity(2))
>>> oneid = tensor(ket2dm(basis(2, 1)), identity(2))
>>> sZ_I = [zeroid, oneid]
>>> measurement_statistics(sZ_I, state_0plus)
([Quantum object: dims = [[2, 2], [1, 1]], shape = (4, 1), type = ket
Qobj data =
[[0.70710678]
[0.70710678]
[0.        ]
[0.        ]], None], [0.9999999999999998, 0.0])


The state obtained on measurement is $\left| 0+ \right>$ with probability 1, as expected. In this case, the information about the second qubit is still maintained, as required.

While we could specify all projective measurements using hermitian observables, we have seen it is often easier to specify them using the projection operators themselves. This is why both options are available. I hope to add another post on the usefulness of POVMs which generalize projective measurements. A particularly interesting example of their use is that of unambiguous state discrimination.

References:

1. Quantum Physics Notes, JD Cresser.
2. Quantum Computing Lecture Notes, Mohan Sarovar.

## Quantum Circuits and Noise (GSOC 2020)

I am participating in the Google Summer of Code under the NumFOCUS banner. In particular, I will be working on the QuTiP project. With the introduction of the QIP module last year by Boxi Li, QuTiP now has a proper circuits and noise module which I am aim to add more features to. I also aim to increase compatibility with other quantum computation libraries like Qiskit and Cirq. I look forward to working with my mentors at QuTiP and learn more about open systems solvers. You can find my project proposal here.

• #### Boxi 3:23 am on May 17, 2020 Permalink | Reply

Good start! Though last year I merely extended the qip module with a quantum device simulator, “introduction of the qip module” gives me to much credit 🙂
Looking forward to your project!

Like

c
Compose new post
j
Next post/Next comment
k
Previous post/Previous comment
r
Reply
e
Edit
o
Show/Hide comments
t
Go to top
l
Go to login
h
Show/Hide help
shift + esc
Cancel
Sidhant's Blog

Covering complexity, quantum algos and other miscellaneous things.

Ridiculous Recreations

Got to solve them all ...

Create your website with WordPress.com