Symbols for NOT (X), Z, Hadamard, CNOT, and CCNOT gates.
Each type of quantum gate has a graphical symbol for the circuit notation.

Programming

Before quantum computers existed, quantum algorithms were defined either mathematically, in terms of the transitions on quantum states, or using a graphical circuit notation for individual gates. Nowadays, quantum computers can be programmed using a GUI for the graphical notation, an assembly language-like text notation for the equivalent gates, or richer programming languages that may also provide low-level access.

The effects of the gates described earlier are similar to the logic gates we use to build a classical computer, like AND and OR. These days, few people bother designing their own programs for classical computers using those low-level gates. In fact, due to the fixed structure of a classical computer, it is hard to select which gates are used. Instead, we program computers using programming languages that humans can read, which are then turned into instructions for the computer, like ADD or MULTIPLY.

When we construct quantum algorithms, we will use gates. Each gate will operate on one, two or three qubits, and we will apply a sequence of gates to our register to form a complete circuit, an implementation of an algorithm. In most quantum computer implementations, the qubits are stationary, and gates are executed on the qubits where they sit, allowing us to treat them something like low-level computer instructions.

Graphical Notation

Each of the gates discussed back in Step 2.15 has a symbol, shown in the figure at the top of this article. Circuits are composed to run left to right, with a horizontal line for each qubit. The visual resemblance to music has lead IBM to referring to such a diagram as a “score”. IBM’s web-based interface uses drag-and-drop programming with colorful, stylized gate symbols.

This approach can show conditional operation, basing the choice to execute individual gates on the outcome of prior measurements. It is also common to draw circuits in terms of blocks of primitive gates. However, it is inherently difficult to create a loop or complex control structures.

A Simple “Assembly” Language

During my (Van Meter’s) Ph.D. thesis work, I developed a simple “assembly” language that lists gates by name, and the qubits on which they operate by a variable name, rather than a physical location. Other low-level languages might make similar choices, or might more directly specify the unitary transform and might identify qubits by physical location, but the goal and program structure will be similar. One unique feature of my language is that the programmer explicitly specifies which gates may be executed at the same time, denoted by the numeric labels. Other assembly languages depend on the compilation tools to determine this parallelism.

1:      CCNOT A0  B0  C0
        CCNOT A1  B1  C1
        CCNOT A2  B2  C2
2:      CNOT  A1  B1
        CNOT  A2  B2
        CNOT  A3  B3
3:      CCNOT C0  B1  C1
4:      CCNOT C1  B2  C2

One modern tool is OpenQASM, developed by Andrew Cross and others at IBM.

Programming Languages

The notion of quantum programming languages goes back to the earliest days of quantum computing research, but much of the early work was very abstract. Omer’s QCL was one of the first concrete, publicly available languages, and also provided a simple simulator.

Several years ago, the IARPA Quantum Computer Science program resulted in the development of several languages. Quipper (by a team from Dalhousie University, U. Penn, and IAS in Princeton) builds on the Haskell programming language. Scaffold (from a team including Princeton University) is a C-like language. QuaFL (from BBN) is a from-scratch functional language.

Microsoft is now on their second-generation language, known as Q# (Q-sharp).

More recently, efforts have turned toward simple library extensions for the popular programming language Python. QISKit and OpenQASM, for connecting to the IBM machines, looks like this:

# quantum circuit to make an entangled bell state 
bell = Q_program.create_circuit('bell', [qr], [cr])
# H (Hadamard) gate to qubit 0 in the Quantum Register "qr" 
bell.h(qr[0])
# CNOT (Controlled-NOT) gate from qubit 0 to qubit 1
bell.cx(qr[0], qr[1])

Rigetti, a startup company making superconducting quantum computers, has developed PyQuil and the Forest programming environment.

Common Subroutines

Of course, quantum algorithms depend on a number of common building blocks, or subroutines. (Just to confuse things, quantum researchers occasionally call an entire block of gates a “gate”, also.) Some of these build on classical notions of simple circuits such as adders, or are quantum-specific routines such as the quantum Fourier transform (QFT).

The image below is a circuit for adding two eight-qubit registers together. This design, by Vedral, Barenco and Ekert, is based on a classical form of circuit known as a ripple-carry adder, a binary form of the right-to-left method you learned as a child. Extra qubits are used to hold partial, temporary results. The “V” shape comes from the need to disentangle those temporary qubits from the important data qubits, and the severe restriction that the entire block must be unitary, or reversible.

an 8-bit adder

We can expect that such low-level routines will be provided as libraries of functions in programming toolkits, allowing us to compose our own algorithms at a high level of abstraction.

Share this article:

This article is from the free online course:

Understanding Quantum Computers

Keio University