Creating a circuit
As described in the tutorial, a circuit can be created in two ways:
- from a cQASM string, or
- by using the circuit builder in Python.
Consider the following example quantum program written in the cQASM language:
1. from a cQASM string
Here we demonstrate how a circuit can be created from a cQASM string,
using the Circuit.from_string
method with the above example program as an input argument:
from opensquirrel import Circuit
circuit = Circuit.from_string(
"""
// Version statement
version 3.0
// Qubit register declaration
qubit[3] q
// Bit register declaration
bit[2] b
// Qubit register initialization (with SGMQ notation)
init q
// Single-qubit gates
Ry(pi / 2) q[0]
X q[0]
// Two-qubit gate
CNOT q[0], q[2]
// Control instruction (with SGMQ notation)
barrier q
// Measure instruction (with SGMQ notation)
b[0, 1] = measure q[0, 2]
"""
)
print(circuit)
The Circuit.from_string
method invokes OpenSquirrel's reader which uses the
libQASM parser to parse the input program.
Some important things to note about how OpenSquirrel reads the input cQASM string: the OpenSquirrel reader
- ignores any comments; they are simply not registered during the parsing phase,
- combines all logical (qu)bit registers into a single virtual (qu)bit register
with identifiers
q
andb
, signifying the qubit and bit registers, respectively, - unpacks any SGMQ notation as separate consecutive statements,
- evaluates complex expressions (e.g.,
pi/2
becomes1.5707963
), and - normalizes the values of the parameters for the rotation angle \(\theta\) and phase \(\phi\) to within the range \(\left(-\pi, \pi \right]\).
Regarding the latter point, when using the inverse or power gate modifiers,
the modifier is applied first and only then are the values of the parameters normalized, e.g.,
pow(1/2).Rx(3 * pi)
becomes Rx(-pi / 2)
, instead of Rx(pi / 2)
.
OpenSquirrel's native tongue is cQASM
The OpenSquirrel reader only accepts quantum programs written in
cQASM.
The same applies to OpenSquirrel's writer, i.e.,
the string representation of a circuit
is in cQASM.
Nonetheless, using exporter passes one can export to
circuit to a different language, e.g.,
quantify-scheduler Schedule
or cQASM 1.0.
One can now proceed to apply compilation passes to the circuit
object.
2. by using the circuit builder
Circuits can also be defined using Python functionalities,
via the circuit builder, as shown below.
For this, the user will first need to import the CircuitBuilder
from opensquirrel
.
import math
from opensquirrel import CircuitBuilder
builder = CircuitBuilder(qubit_register_size=3, bit_register_size=2)
builder.init(0).init(1).init(2)
builder.Ry(0, math.pi / 2)
builder.X(0)
builder.CNOT(0, 2)
builder.barrier(0).barrier(1).barrier(2)
builder.measure(0, 0).measure(1, 2)
circuit = builder.to_circuit()
print(circuit)
Note that the representation of the printed circuit is the same as the one obtained from the cQASM string above.
The real power of the circuit builder lies in that fact that it can be used in combination with the functionalities available in Python to create your circuit:
from opensquirrel import CircuitBuilder
qreg_size = 10
builder = CircuitBuilder(qubit_register_size=qreg_size)
for qubit_index in range(0, qreg_size, 2):
builder.H(qubit_index)
circuit = builder.to_circuit()
For instance, you can straightforwardly generate a quantum fourier transform (QFT) circuit as follows:
from opensquirrel import CircuitBuilder
qreg_size = 5
builder = CircuitBuilder(qubit_register_size=qreg_size)
for qubit_index in range(qreg_size):
builder.H(qubit_index)
for control_index in range(qubit_index + 1, qreg_size):
target_index = qubit_index
k = control_index - target_index + 1
builder.CRk(control_index, target_index, k)
circuit_qft = builder.to_circuit()
print(circuit_qft)
One can now proceed to apply compilation passes to the circuit
object.