Quantum Programming 101

- Programming, Mathematics

Last revision:

Plasma globe

Are you familiar with programming, but know absolutely nothing about quantum mechanics?

This was exactly my case when the IBM Quantum Experience was announced. For the first time, a quantum computer has been made publicly available, and anybody selected to participate could send programs to it.

I applied. I was selected. And then I had a really rough time attempting to decipher the user guide of the IBM 5Q quantum computer I had access to. The IBM staff tried to ease the learning curve, but I felt that the documentation made a lot of assumptions that a non-physicist do not have, and "intuitive" ideas presented to me (like the Bloch sphere) just confused me even more.

Therefore, I decided to compile below a generic introduction on quantum programming designed for classical programmers to ease their learning curve. I hope it will be useful to you and anybody else you share it to.

Be warned however that quantum programming requires some pretty advanced mathematical knowledge, but as long as you're familiar with probability, binary numbers, complex numbers and linear algebra, you should be fine.

Are you ready? Let's go!

Meet the qubit

The qubit is an extension of the bit. Just like the bit, it returns a value of 0 or 1 when read, and the returned value doesn't change when read multiple times consecutively.

Unlike the bit however, the qubit does not simply store a value of 0 or 1. In fact, its internals cannot be well-defined, as its output is in general dependent on global factors which cannot be fully known. For example, when qubits interact with each other, they may become entangled in a way which causes an operation on one to affect the output of the other regardless of the physical distance between them.

What is possible however is to determine the probability of a qubit returning 0 or 1 based on our partial knowledge of it and all the other qubits it has interacted with during previous operations.

Note that a qubit not guaranteed to return a specific value is said to be in a superposition state.

Probability amplitudes

A probability amplitude is a complex number directly linked to a possible qubits' output combination. The probability of reading a specific output combination is equal to the square of the absolute value of its probability amplitude.

Therefore, the known state of an entire set of qubits can be stored as a vector of all probability amplitudes of this set. By convention, this vector is a column vector ordered from lowest to highest possible binary outputs. Such a vector is called a quantum state.

Here is an example of a quantum state of 2 entangled qubits, along with its output probabilities:

[ a 00 a 01 a 10 a 11 ] = [ i / 2 0 0 i / 2 ] P ( 00 ) = | a 00 | 2 = | i / 2 | 2 = 1 / 2 P ( 01 ) = | a 01 | 2 = | 0 | 2 = 0 P ( 10 ) = | a 10 | 2 = | 0 | 2 = 0 P ( 11 ) = | a 11 | 2 = | i / 2 | 2 = 1 / 2 left [ stack{a_00 # a_01 # a_10 # a_11} right ] = left [ stack{i/sqrt{2} # 0 # 0 # -i/sqrt{2}} right ] newline newline P(00) = {abs{a_00}}^2 = {abs{i/sqrt{2}}}^2 = 1/2 newline P(01) = {abs{a_01}}^2 = {abs{0}}^2 = 0 newline P(10) = {abs{a_10}}^2 = {abs{0}}^2 = 0 newline P(11) = {abs{a_11}}^2 = {abs{-i/sqrt{2}}}^2 = 1/2

Initial state

A standard quantum computer initializes its qubits as independent quantum states with probability amplitudes of 1 for returning 0 and 0 for returning 1:

[ 1 0 ] left [ matrix{1 ## 0} right ]

This effectively causes all qubits to always return 0 if immediately read.

System scaling

Quantum states can be combined as a single quantum state in order to operate on qubits between them. This is done by calculating the Kronecker product of the quantum states:

[ 1 0 ] [ 1 0 ] = [ 1 0 0 0 ] left [ matrix{1 ## 0} right ] otimes left [ matrix{1 ## 0} right ] = left [ matrix{1 ## 0 ## 0 ## 0} right ]

Note that two groups of different qubits sharing a quantum state are entangled if and only if they cannot be described as independent quantum states.

Quantum gates

While classical computers uses logic gates to operate on bits, quantum computers uses quantum gates to operate on qubits. A quantum gate can be represented as a unitary matrix of side length of 2 to the power of the number of qubits it operates on.

The effect of a quantum gate is calculated by multiplying the quantum gate matrix with the quantum state of the qubit set going through it. The result is a new quantum state.

Here is an example of a 1-qubit quantum gate applied on an initial quantum state to make it always return 1:

X = [ 0 1 1 0 ] X [ 1 0 ] = [ 0 1 1 0 ] [ 1 0 ] = [ 0 1 ] X = left [ matrix{0 # 1 ## 1 # 0} right ] newline X left [ matrix{1 ## 0} right ] = left [ matrix{0 # 1 ## 1 # 0} right ] left [ matrix{1 ## 0} right ] = left [ matrix{0 ## 1} right ]

In the case where a quantum gate operates on a subset of the total number of entangled qubits, the Kronecker product can again be used to expand the quantum gate matrix with a 2 by 2 identity matrix per qubit. This allows quantum computers to execute some programs significantly faster on average than what is possible on classical computers, since the execution time to apply a specific quantum gate instruction is constant.

For example, here is a 2-qubit quantum gate that reverses the least significant qubit's output only if the most significant qubit would return 1. It is expanded as a 3-qubit operator in a way that applies the gate on the two most significant qubits. It is then applied on a quantum state that always returns 100 to make it always return 110 instead:

CNOT = [ 1 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 ] ( CNOT I 2 ) [ 0 0 0 0 1 0 0 0 ] = ( [ 1 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 ] [ 1 0 0 1 ] ) [ 0 0 0 0 1 0 0 0 ] = [ 0 0 0 0 0 0 1 0 ] CNOT = left [ matrix{ 1 # 0 # 0 # 0 ## 0 # 1 # 0 # 0 ## 0 # 0 # 0 # 1 ## 0 # 0 # 1 # 0 } right ] newline (CNOT otimes I_2) left [ matrix{ 0 ## 0 ## 0 ## 0 ## 1 ## 0 ## 0 ## 0 } right ] = left ( left [ matrix{ 1 # 0 # 0 # 0 ## 0 # 1 # 0 # 0 ## 0 # 0 # 0 # 1 ## 0 # 0 # 1 # 0 } right ] otimes left [ matrix{ 1 # 0 ## 0 # 1 } right ] right ) left [ matrix{ 0 ## 0 ## 0 ## 0 ## 1 ## 0 ## 0 ## 0 } right ] = left [ matrix{ 0 ## 0 ## 0 ## 0 ## 0 ## 0 ## 1 ## 0 } right ]

Note that a quantum gate's matrix may require a change of basis (through standard linear algebra) if the order of qubits we want to operate on do not match those of the quantum state. This also applies for expanded quantum gate matrices.

Programming

After considering the limitations of the architecture of the quantum computer used, the only thing left is to write a desired quantum program in a compatible programming language, just like any classical program,

Here is an example of a program written in IBM's QASM assembly language:

//IBMQASM 1.1
qreg q,5;
gate h, [[0.7071067811865476,0.7071067811865476],[0.7071067811865476,-0.7071067811865476]];
gate cx, [[1,0,0,0],[0,1,0,0],[0,0,0,1],[0,0,1,0]];
h q[1];
cx q[1], q[2];
measure q[1];
measure q[2];

This example sets two qubits in a popular quantum state (the Bell state) before measuring them. The expected output is 00 with 1/2 probability and 11 with 1/2 probability.

Hardware errors

One major problem in current quantum computers is the instability of qubits, and the process of error injections in a quantum state is called decoherence. In addition, qubit measurement devices also have error biases as well.

Until technology is perfected to reduce these errors to a trivial level, a quantum programmer should take into consideration error probabilities of the computer's architecture, and apply error correction algorithms to its programs when necessary.

Describing a mixed state of probabilities due to these error sources can be done with a density matrix, which is out of scope of this post.

To be continued?

I hope that my explanation was clear enough for you to be able to design your own quantum programs. Quantum programming is a young science so there's still plenty to discover, but you may want to look at some existing quantum algorithms for inspiration.

Special thanks to the entire IBM Quantum staff for introducing me to quantum computers and answering my technical questions!

Bonus content!

bra-ket notation

During my research, I often stumbled on quantum states defined in bra-ket notation. Here is what you should know if you would like to read other sources on the subject.

By definition:

bra : x | ket : | x | 0 = [ 1 0 ] | 1 = [ 0 1 ] | + = 1 2 [ 1 1 ] | = 1 2 [ 1 1 ] | + i = 1 2 [ 1 i ] | i = 1 2 [ 1 i ] x | = | x H = | x ¯ T x | y = x | | y | x | y = | x | y | xy = | x | y bra: left langle x right lline newline ket: left lline x right rangle newline newline left lline 0 right rangle = left [ stack{1 # 0} right ] newline left lline 1 right rangle = left [ stack{0 # 1} right ] newline left lline +{} right rangle = {1} over sqrt{2} left [ stack{1 # 1} right ] newline left lline -{} right rangle = {1} over sqrt{2} left [ stack{1 # -1} right ] newline left lline +i right rangle = {1} over sqrt{2} left [ stack{1 # i} right ] newline left lline -i right rangle = {1} over sqrt{2} left [ stack{1 # -i} right ] newline newline left langle x right lline = {left lline x right rangle}^{H} = {overline{left lline x right rangle}}^T newline left langle x mline y right rangle = left langle x right lline left lline y right rangle newline left lline x right rangle left lline y right rangle = left lline x right rangle otimes left lline y right rangle newline left lline xy right rangle = left lline x right rangle otimes left lline y right rangle

One big advantage of this notation is to be able to perform the following decomposition of any quantum state, which can help designing and analyzing programs:

[ a 0 000 a 0 001 a 0 010 a 0 011 a 1 111 ] = k a k | k left [ stack{a_{0 dotsaxis 000} # a_{0 dotsaxis 001} # a_{0 dotsaxis 010} # a_{0 dotsaxis 011} # dotsvert # a_{1 dotsaxis 111}} right ] = sum from{k} a_k left lline k right rangle

Common quantum gates

Note that the U gate below is an implementation of the universal unitary quantum gate.

X = [ 0 1 1 0 ] Z = [ 1 0 0 1 ] Y = [ 0 i i 0 ] H = 1 2 [ 1 1 1 1 ] S = [ 1 0 0 i ] S = [ 1 0 0 i ] T = [ 1 0 0 1 + i 2 ] T = [ 1 0 0 1 i 2 ] CNOT = [ 1 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0 ] P ( λ ) = [ 1 0 0 e i λ ] RZ ( λ ) = [ e i λ / 2 0 0 e i λ / 2 ] U ( θ , ϕ , λ ) = [ cos ( θ 2 ) e i λ sin ( θ 2 ) e i ϕ sin ( θ 2 ) e i ( λ + ϕ ) cos ( θ 2 ) ] X = left [ matrix{0 # 1 ## 1 # 0} right ] newline Z = left [ matrix{1 # 0 ## 0 # -1} right ] newline Y = left [ matrix{0 # -i ## i # 0} right ] newline H = 1 over { sqrt{2}} left [ matrix{1 # 1 ## 1 # -1} right ] newline S = left [ matrix{1 # 0 ## 0 # i} right ] newline S^† = left [ matrix{1 # 0 ## 0 # -i} right ] newline T = left [ matrix{1 # 0 ## 0 # {1 + i} over sqrt{2}} right ] newline T^† = left [ matrix{1 # 0 ## 0 # {1 - i} over sqrt{2}} right ] newline CNOT = left [ matrix{1 # 0 # 0 # 0 ## 0 # 1 # 0 # 0 ## 0 # 0 # 0 # 1 ## 0 # 0 # 1 # 0} right ] newline newline P(%lambda) = left [ matrix{1 # 0 ## 0 # e^{i %lambda}} right ] newline RZ(%lambda) = left [ matrix{e^{-i %lambda / 2} # 0 ## 0 # e^{i %lambda / 2}} right ] newline U(%theta,%phi,%lambda) = left [ matrix{cos left ( %theta over 2 right ) # -e^{i %lambda} sin left (%theta over 2 right ) ## e^{i %phi} sin left (%theta over 2 right ) # e^{i (%lambda + %phi)} cos left (%theta over 2 right )} right ]

You may also want to refer to the full list of quantum gates supported by the IBM Quantum Experience.

Gate equivalences

Note that 𝜏 = 2𝜋.

XZ = Y T = P ( τ 8 ) T 2 = S T 4 = Z T 6 = S T 7 = T T 8 = I 2 P ( λ ) = e i λ / 2 RZ ( λ ) P ( λ ) = U ( 0,0 , λ ) XZ = Y newline newline T = P(%tau over 8) newline T^2 = S newline T^4 = Z newline T^6 = S^† newline T^7 = T^† newline T^8 = I_2 newline newline P(%lambda) = e^{i %lambda / 2}RZ(%lambda) newline P(%lambda) = U(0,0,%lambda)

Related articles I wrote

Radiating business woman

Essential International Standards and Registries for Web Developers

- Programming, Quality Assurance, Security

The following is a collection of free international standards, registries and references that I collected throughout the years while developing websites and web services. These references, while very precise and technical by their nature, are extremely useful in order to ensure that a specific…

Spaceship flying over active volcanoes

A Universe and World Creation Script for Mongoose Traveller 2nd Edition

- Tabletop RPGs, Programming

The following is a Python script developed by yours truly to generate a sector according to the core rulebook of the Mongoose Traveller 2nd Edition tabletop RPG, exactly as described in the Universe and World Creation chapter. It is designed to describe worlds in human-readable format as much as…

Medusa in fiery scenery

Deep Learning in Python with PyTorch - Tutorial and Demo

- Programming, Mathematics

As I am continuing my personal journey into deep learning research and development, I wanted to try out PyTorch, a machine learning framework with GPU acceleration primarily designed for the Python programming language. However, I couldn't find any good introductory resource online for it. So I read…

Dusty light bulb lying on the floor

Stop! Your Ideas Are Stale!

- Business, Programming

"Everything must be done now. Let's re-use existing proven solutions and build over them so we don't waste time." And thus, people will look at the top 2 or 3 most popular solutions they already know about or can easily find on the Internet, compare them, pick the best one, and maybe add or change…

Lady Justice

Reasonable Doubt as a Game Mechanic

- Game Design, Mathematics

Detective fiction, and particularly whodunits, have been really good at being engaging people in attempting to solving the mystery presented before the final reveal. Video games allows such stories to thrive with a level of interactivity that can directly engage the player in this process as an…

See all of my articles