MyQLM provides different tools and approaches to design your own quantum circuits.
The main component is a Python library for building quantum circuits, called PyAQASM (Python + Atos QASM).
The following picture gives an overview of the circuit generation process from the PyAQASM library.

Quantum circuits can be stored under two formats:
in a serialized format (.circ) - it is under this format that circuits are sent to simulation or optimization services, when command-line tools are used
as .aqasm text files (human readable)
Therefore, there are two ways to generate a .circ file from a Program
instance by:
directly generating a
Circuit
instance and serializing it (right path in the figure)exporting your program to an .aqasm text file (human readable text format), and compiling it using the command-line tool aqasm2circ (left path in the figure)
Since the core of the QLM is purely based on Python, serialization is NOT a mandatory step, and is here only to facilitate advanced applications. Usually the Circuit
objects are directly fed to QPUs via a Python interface (see documentation of qat-core for examples).
If you still need a text format to describe your quantum circuits, please refer to the AQASM section : The AQASM format.
Writing quantum circuits
The pyAQASM library (qat.lang.AQASM
) provides a high-level interface to design quantum circuits.
The central class of this library is Program
. This class provides an interface to build and generate a Circuit
object.
from qat.lang.AQASM import Program
my_program = Program()
Allocating qubit and classical registers:
Qubit registers are allocated by the Program using the qalloc()
method.
qbits_reg = my_program.qalloc(10)
Similarly, registers that hold classical bits can be allocated using the calloc()
method.
cbits_reg = my_program.calloc(10)
Quantum gates
Native gates, controls and daggers
The pyAQASM library provides a basic gate set to write your programs. Their names are rather self-explanatory:
Constant gates: X, Y, Z, H, S, T, CNOT, CCNOT, CSIGN, SWAP, SQRTSWAP, ISWAP
Parametrized gates: RX, RY, RZ, PH (phase shift)
(The mathematical definition of these gates is given in The AQASM format.)
These gates can be applied to the qubits from the qubit register:
CNOT(qbits_reg[0], qbits_reg[1])
H(qbits_reg[2])
RZ(np.pi/2.)(qbits_reg[0]
From this initial gate set, one can also build new gates using control and dagger operations:
PH(np.pi/2).ctrl()(qbits_reg[0], qbits_reg[1])
RX(np.pi/4).dag()(qbits_reg[0])
Of course, controls can be stacked:
PH(np.pi/2).ctrl().ctrl().ctrl()(qbits_reg[0:4])
By convention, the outermost control qubit is always the first argument in when calling a gate.
# Here qbits_reg[0] is the control qbit:
H.ctrl()(qbits_reg[0], qbits_reg[2])
# And here, qbits_reg[0] and qbits_reg[2] are the controls:
H.ctrl().ctrl()(qbits_reg[0], qbits_reg[2], qbits_reg[9])
Defining new parametrized gates: Abstract Gates
One might want to define new family of gates parametrized by some angle, or even by some vector (think about state preparation for instance). This can be done through the AbstractGate
class.
Your code would look like this:
# A new 1-qbit gate parametrized by 2 angles
C = AbstractGate("C", [float, float], arity=1)
C(np.pi/2, np.pi/4)(qbits_reg[0])
Of course, you can also provide a way to generate the matrix corresponding to the gate:
def c_matrix(theta, phi):
return np.cos(theta/2) * I - 1j * np.sin(theta/2) * (np.cos(phi) * X + np.sin(phi) * Y)
C = AbstractGate("C", [float, float],
arity=1,
matrix_generator=c_matrix)
The resulting circuit contains the matrix and can be simulated on most of the available simulators in the QLM.
Custom gates
Warning
Custom gates are deprecated. Consider using constant valued
AbstractGate
instead (defined in
the previous section).
PyAQASM offers the possibility to define your own gates from a matrix. This is done via the CustomGate
class.
mat = np.array([[-1, 0], [0, 1]])
my_minus_z = CustomGate(mat)
my_minus_z(qbits_reg[0])
Quantum routines
PyAQASM provides a structure to describe subcircuits that can then be used as quantum gates.
This interface is provided by the QRoutine
object.
Inside these routines, qubits are inexistant: a routine is just a gate, thus it only knows about the incoming/outgoing wires. Wires are referred to using integers. The arity of the routine is updated dynamically depending on the used wires.
my_routine = QRoutine()
wires = my_routine.new_wires(2)
H(wires[0])
CNOT(wires)
my_routine(qbits_reg[0], qbits_reg[1])
# Since QRoutine are Gates, one can control/dagger them
my_routine.ctrl()(qbits_reg[0:3])
my_routine.dag()(qbits_reg[0:2])
Other operations
The Program
structure supports various instructions:
measure()
: measure a qubit during the computation (not to be used for final measurements)reset()
: reset a qubit or classical bit: it consists in measuring the qubit, and applying a bit flip (X gate) if the outcome is 1cc_apply()
: apply a gate conditionally, depending on the state of a classical bitcbreak()
: interrupt the computation depending on a condition on a set of classical bits
Quantum routine librairies
Some submodules of the pyAQASM library provide high-level routines or algorithms:
qftarith
provides QFT-based implementation of various arithmetic operations (including QFT itself)classarith
provides carry-arithmetic operationsarithmetic
provides a unified interface for all arithmetic operations
Generating the circuit
Once you are satisfied with your Program
, it can be exported to a circuit format that can be simulated. This is done using the to_circ()
method.
This method has parameters and can be fine-tuned to meet your needs. Please refer to the source code documentation for more information.
Exporting the circuit
The Program
object can also be exported to a human-readable AQASM format.
This is done using the export()
method.
More advanced usage
Please refer to section Advanced programming using pyAQASM for more features.