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:

```
my_program.apply(CNOT, qbits_reg[0], qbits_reg[1])
my_program.apply(H, qbits_reg[2])
my_program.apply(RZ(np.pi/2.), qbits_reg[0]
```

From this initial gate set, one can also build new gates using control and dagger operations:

```
my_program.apply(PH(np.pi/2).ctrl(), qbits_reg[0], qbits_reg[1])
my_program.apply(RX(np.pi/4).dag(), qbits_reg[0])
```

Of course, controls can be stacked:

```
my_program.apply(PH(np.pi/2).ctrl().ctrl().ctrl(), qbits_reg[0:4])
```

By convention, the outermost control qubit is always the first argument in the `apply()`

method.

```
# Here qbits_reg[0] is the control qbit:
my_program.apply(H.ctrl(), qbits_reg[0], qbits_reg[2])
# And here, qbits_reg[0] and qbits_reg[2] are the controls:
my_program.apply(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)
my_program.apply(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_program.apply(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()
my_routine.apply(H, 0)
my_routine.apply(CNOT, 0, 1)
my_program.apply(my_routine, qbits_reg[0], qbits_reg[1])
# Since QRoutine are Gates, one can control/dagger them
my_program.apply(my_routine.ctrl(), qbits_reg[0:3])
my_program.apply(my_routine.dag(), qbtis_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 1`cc_apply()`

: apply a gate conditionally, depending on the state of a classical bit`cbreak()`

: 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 operations`arithmetic`

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.