Creating MBQC Circuits

Measurement-based quantum computation is a paradigm of quantum computation that uses single qubit measurements to perform universal quantum computation [1]. It is equivalent to the standard gate-based model. The main difference is that the gates are not explicitly applied to the qubits, but rather a big resource (entangled) state is prepared and logical information flows through the system by measuring the qubits of the resource state.

MBQC Circuits

In mentpy we can simulate an MBQC circuit by using the MBQCircuit class.

In [1]: gs = mp.GraphState()

In [2]: gs.add_edges_from([(0, 1), (1, 2), (2, 3), (3, 4)])

In [3]: mbcirc = mp.MBQCircuit(gs, input_nodes=[0], output_nodes=[4])

In [4]: mp.draw(mbcirc)
Out[4]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/1d_cluster.png

This circuit is designed to implement a single qubit gate on the input qubit, with qubits measured in a left-to-right sequence. We can use this circuit to implement a teleportation from qubit 0 to qubit 4 by measuring qubits \(0\), \(1\), \(2\), and \(3\) in the \(X\) basis.

Ment Operators

To specify the measurement angles, we can use the Measurement (or its alias Ment) operator at each qubit position. The Measurement object is characterized by an angle and a measurement plane, which can be “XY”, “XZ”, or “YZ” (“X”, “Y”, and “Z” are also accepted), determining the basis in which the qubit is measured. The angle can be specified or set to None. If not provided, it will be treated as a trainable parameter.

Note

At the moment, only the “XY”, “X”, and “Y” measurement planes are supported.

In [5]: mbcirc[0] = mp.Ment('X')

In [6]: mbcirc[1] = mp.Ment('XY')

In [7]: mbcirc[2] = mp.Ment(0.5, 'XY')

In [8]: mbcirc[3] = mp.Ment('X')

In [9]: mp.draw(mbcirc, label='planes')
Out[9]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/1d_cluster_measure.png

We can define the same circuit when creating the MBQCircuit object with the measurements argument:

In [10]: measurements = {0: mp.Ment('X'), 1: mp.Ment('XY'), 2: mp.Ment(0.5, 'XY'), 3: mp.Ment('X')}

In [11]: mbcirc = mp.MBQCircuit(gs, input_nodes=[0], output_nodes=[4], measurements=measurements)

In [12]: mp.draw(mbcirc, label='arrows')
Out[12]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/1d_cluster_measure2.png

The default measurement basis can be specified with the default_measurement kwarg. By default, it is set to \(XY\), but we can change it to any other Ment object. Let’s see an example:

In [13]: mbcirc = mp.MBQCircuit(gs, input_nodes=[0], output_nodes=[4],
   ....:                        measurements={1: mp.Ment('XY')},
   ....:                        default_measurement=mp.Ment('X'))
   ....: 

In [14]: print(mbcirc[0]) # Not specified in the constructor
Ment(0, X)

In [15]: print(mbcirc[1]) # Specified in the constructor
Ment(θ, XY)

In [16]: print(mbcirc[2].matrix()) # Matrix of the measurement operator
[[0 1]
 [1 0]]

We can concatenate two MBQC circuits with the merge(), hstack(), or vstack() functions.

In [17]: new_circ = mp.merge(mbcirc, mbcirc, along=[(4,0)])  # specify nodes to merge

In [18]: mp.draw(new_circ, label='angles')
Out[18]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/merge_mbqc.png
In [19]: new_circ = mp.hstack((mbcirc, mbcirc))

In [20]: mp.draw(new_circ, label='planes')
Out[20]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/hstack_mbqc.png
In [21]: new_circ = mp.vstack((mbcirc, mbcirc))

In [22]: mp.draw(new_circ, label='arrows')
Out[22]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/vstack_mbqc.png

Templates

To use pre-defined MBQC circuits, we can use the templates module, which contains some common MBQC circuits. For example, we can create a grid cluster state with the grid_cluster() function.

In [23]: grid_cluster = mp.templates.grid_cluster(3, 5)

In [24]: linear_cluster = mp.templates.linear_cluster(4)

In [25]: grid_and_linear = mp.merge(grid_cluster, linear_cluster, along=[(9,0)])

In [26]: mp.draw(grid_and_linear)
Out[26]: (<Figure size 800x300 with 1 Axes>, <Axes: >)
savefig/template_merge.png

Finally, if you want to know the set of gates that the MBQC circuit you have created implements, you can use the utils.calculate_lie_algebra(). This function returns the lie algebra \(\mathfrak{g}\) that the circuit implements, which can be used to calculate the set of gates using the exponential map \(\{e^{i \theta \mathfrak{g}} \mid \theta \in \mathbb{R} \}\).

In [27]: ops = mp.utils.calculate_lie_algebra(grid_cluster)

In [28]: print(len(ops))
64

In [29]: ops[:3]
Out[29]: 
IIZ
IIX
IXZ

Lie algebras are a powerful tool for studying QML models. It has been shown that, for a given model, the size of the Lie algebra is related to the phenomenon of barren plateaus [2] [3].

References