|
| 1 | +r""" |
| 2 | +How to estimate the resource cost of QSVT |
| 3 | +========================================= |
| 4 | +
|
| 5 | +The Quantum Singular Value Transformation (QSVT) is a versatile algorithm that is applicable to a wide range of |
| 6 | +problems, including unstructured search, Hamiltonian simulation, matrix inversion, and many more [#chuang2021]_. |
| 7 | +PennyLane makes it easy to build circuits and experiment with QSVT using the :func:`~.pennylane.qsvt` function. |
| 8 | +For more information on how to use PennyLane's QSVT functionality checkout our other demos: |
| 9 | +
|
| 10 | +- `Intro to QSVT <tutorial_intro_qsvt>`_ |
| 11 | +- `QSVT in Practice <tutorial_apply_qsvt>`_ |
| 12 | +- `How to implement QSVT on hardware <tutorial_qsvt_hardware>`_ |
| 13 | +
|
| 14 | +It's important to understand the quantum resource cost of the QSVT algorithm for a variety of system sizes. |
| 15 | +Fortunately, PennyLane's resource :mod:`~.pennylane.estimator` module makes that easy, even if the QSVT problem |
| 16 | +you're interested in is too big to simulate right now. If you are new to resource estimation in PennyLane or need |
| 17 | +a quick refresher, checkout this demo on `how to use PennyLane for Resource Estimation <re_how_to_use_pennylane_for_resource_estimation>`_. |
| 18 | +
|
| 19 | +.. figure:: ../_static/demo_thumbnails/opengraph_demo_thumbnails/pennylane-demo-resource-estimation-qsvt-open-graph.png |
| 20 | + :align: center |
| 21 | + :width: 70% |
| 22 | + :target: javascript:void(0) |
| 23 | +
|
| 24 | +In this demo, you will learn how to use PennyLane's :mod:`~.pennylane.estimator` module to easily estimate the |
| 25 | +cost of QSVT. There are two ways of doing so: the Executable workflow and the Estimator workflow. The |
| 26 | +Estimator workflow involves expressing our QSVT circuit using :mod:`~.pennylane.estimator` operators. This |
| 27 | +workflow scales for *any* system size, has a simpler UI and produces tighter resource estimates. For users |
| 28 | +who have already built a standard PennyLane circuit, the Executable workflow allows for resource estimation |
| 29 | +with only one extra line of code. |
| 30 | +
|
| 31 | +Estimating the cost of QSVT |
| 32 | +--------------------------- |
| 33 | +Let's estimate the cost of performing a quintic (5th degree) polynomial transformation to the matrix |
| 34 | +:math:`A`: |
| 35 | +
|
| 36 | +.. math:: |
| 37 | +
|
| 38 | + A = \begin{bmatrix} |
| 39 | + 0.1 & 0.0 & 0.3 & 0.2 \\ |
| 40 | + 0.0 & -0.1 & 0.2 & -0.3 \\ |
| 41 | + 0.3 & 0.2 & -0.1 & 0.0 \\ |
| 42 | + 0.2 & -0.3 & 0.0 & 0.1 \\ |
| 43 | + \end{bmatrix}, |
| 44 | +
|
| 45 | +
|
| 46 | +This particular matrix can be expressed as a linear combination of unitaries (LCU) :math:`A = 0.1 \cdot Z_{0}Z_{1} + 0.2 \cdot X_{0}X_{1} + 0.3 \cdot X_{0}Z_{1}`. |
| 47 | +The LCU representation is crucial for building the **block encoding** operator using the standard method of LCUs. |
| 48 | +For a recap on this technique, see our demo on `linear combination of unitaries and block encodings <tutorial_lcu_blockencoding>`_. |
| 49 | +""" |
| 50 | + |
| 51 | +import pennylane as qml |
| 52 | + |
| 53 | +A = 0.1 * (qml.Z(0) @ qml.Z(1)) + 0.2 * (qml.X(0) @ qml.X(1)) + 0.3 * (qml.X(0) @ qml.Z(1)) |
| 54 | + |
| 55 | +print(qml.matrix(A, wire_order=[0, 1])) |
| 56 | + |
| 57 | +############################################################################## |
| 58 | +# Resources from an Executable Workflow |
| 59 | +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 60 | +# |
| 61 | +# Suppose we already had a PennyLane circuit which used QSVT to apply the quintic polynomial transformation to |
| 62 | +# :math:`A`. We can obtain the resource estimate with only a couple of lines of code with |
| 63 | +# `estimate() <https://docs.pennylane.ai/en/stable/code/api/pennylane.estimator.estimate.estimate.html>`_. |
| 64 | +# |
| 65 | + |
| 66 | +import pennylane.numpy as qnp |
| 67 | +import pennylane.estimator as qre |
| 68 | + |
| 69 | +## --- QSVT Workflow: --- |
| 70 | +num_terms = len(A) |
| 71 | +num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms))) |
| 72 | +encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)] |
| 73 | + |
| 74 | +poly = (0, 0, 0, 0, 0, 1) # f(x) = x^5 |
| 75 | +def circ(): |
| 76 | + qml.qsvt(A, poly, encoding_wires=encoding_wires) |
| 77 | + return |
| 78 | + |
| 79 | +## --- Resource Estimation: --- |
| 80 | +gs = {"X", "Y", "Z", "S", "T", "Hadamard", "CNOT", "Toffoli"} |
| 81 | +resources = qre.estimate(circ, gate_set=gs)() |
| 82 | +print(resources) |
| 83 | + |
| 84 | +############################################################################## |
| 85 | +# This works well for small systems. For larger system sizes, we can use some of the other functionalities |
| 86 | +# from the :mod:`~.pennylane.estimator` module that are designed for scale to estimate the cost of QSVT. |
| 87 | +# |
| 88 | +# Resources from an Estimator Workflow |
| 89 | +# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ |
| 90 | +# The LCU representation of :math:`A` is efficiently stored using the |
| 91 | +# :class:`~.pennylane.estimator.compact_hamiltonian.PauliHamiltonian` class. This produces a compact object |
| 92 | +# specifically for resource estimation. The block encoding operator is built with the |
| 93 | +# `ChangeOpBasis <https://docs.pennylane.ai/en/stable/code/api/pennylane.estimator.ops.ChangeOpBasis.html>`_ |
| 94 | +# class which uses the compute-uncompute pattern to implement the |
| 95 | +# :math:`\text{Prep}^{\dagger} \circ \text{Select} \circ \text{Prep}` operator. |
| 96 | +# |
| 97 | +# The resources for `QSVT <https://docs.pennylane.ai/en/stable/code/api/pennylane.estimator.templates.QSVT.html>`_ |
| 98 | +# can then be obtained using this block encoding. Note that these operators are specifically designed for resource |
| 99 | +# estimation and are *not supported* for execution or simulation in a circuit. |
| 100 | + |
| 101 | +## --- LCU representation of A: --- |
| 102 | +lcu_A = qre.PauliHamiltonian( |
| 103 | + num_qubits=2, |
| 104 | + pauli_terms={"ZZ": 1, "XX": 1, "XZ": 1}, |
| 105 | +) # represents A = 0.1*ZZ + 0.2*XX + 0.3*XZ |
| 106 | +num_terms = lcu_A.num_terms |
| 107 | +num_qubits = lcu_A.num_qubits |
| 108 | + |
| 109 | +## --- Block Encoding operator: --- |
| 110 | +num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms))) |
| 111 | +encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)] |
| 112 | +lcu_wires = [f"t_{i}" for i in range(num_qubits)] |
| 113 | + |
| 114 | +Prep = qre.QubitUnitary( # Prep the coeffs of the LCU |
| 115 | + num_encoding_wires, |
| 116 | + wires=encoding_wires, |
| 117 | +) |
| 118 | + |
| 119 | +Select = qre.SelectPauli( # Select over ops in the LCU |
| 120 | + lcu_A, |
| 121 | + wires=lcu_wires + encoding_wires, |
| 122 | +) |
| 123 | + |
| 124 | +BlockEncoding = qre.ChangeOpBasis(Prep, Select) # Prep ○ Sel Prep^t |
| 125 | + |
| 126 | +## --- QSVT operator: --- |
| 127 | +qsvt_op = qre.QSVT( |
| 128 | + block_encoding=BlockEncoding, |
| 129 | + encoding_dims=(4, 4), # The shape of matrix A |
| 130 | + poly_deg=5, # quintic |
| 131 | +) |
| 132 | + |
| 133 | +## --- Resource Estimation: --- |
| 134 | +gs = {"X", "Y", "Z", "S", "T", "Hadamard", "CNOT", "Toffoli"} |
| 135 | +resources = qre.estimate(qsvt_op, gate_set=gs) |
| 136 | +print(resources) |
| 137 | + |
| 138 | +############################################################################## |
| 139 | +# Representing the QSVT workflow like this allows us to easily perform resource estimation larger system sizes |
| 140 | +# without any computational overheads. Let's extend this example to a **50 qubit** system with an LCU of **2000 |
| 141 | +# terms** and a **100th degree** polynomial transformation. Notice how simple it is to update the code |
| 142 | +# and obtain the cost of this larger system: |
| 143 | + |
| 144 | +## --- LCU representation of A: --- |
| 145 | +lcu_A = qre.PauliHamiltonian( |
| 146 | + num_qubits=50, |
| 147 | + pauli_terms={"ZZ": 250, "XX": 750, "XZ": 1000}, |
| 148 | +) # 2000 terms ! |
| 149 | +num_terms = lcu_A.num_terms |
| 150 | +num_qubits = lcu_A.num_qubits |
| 151 | + |
| 152 | +## --- Block Encoding operator: --- |
| 153 | +num_encoding_wires = int(qnp.ceil(qnp.log2(num_terms))) |
| 154 | +encoding_wires = [f"e_{i}" for i in range(num_encoding_wires)] |
| 155 | +lcu_wires = [f"t_{i}" for i in range(num_qubits)] |
| 156 | + |
| 157 | +Prep = qre.QROMStatePreparation( # Efficient Prep for large systems |
| 158 | + num_encoding_wires, |
| 159 | + wires=encoding_wires, |
| 160 | +) |
| 161 | + |
| 162 | +Select = qre.SelectPauli( # Select over ops in the LCU |
| 163 | + lcu_A, |
| 164 | + wires=lcu_wires + encoding_wires, |
| 165 | +) |
| 166 | + |
| 167 | +BlockEncoding = qre.ChangeOpBasis(Prep, Select) # Prep ○ Sel Prep^t |
| 168 | + |
| 169 | +## --- QSVT operator: --- |
| 170 | +qsvt_op = qre.QSVT( |
| 171 | + block_encoding=BlockEncoding, |
| 172 | + encoding_dims=(2**50, 2**50), # The shape of matrix A |
| 173 | + poly_deg=100, |
| 174 | +) |
| 175 | + |
| 176 | +## --- Resource Estimation: --- |
| 177 | +gs = {"X", "Y", "Z", "S", "T", "Hadamard", "CNOT", "Toffoli"} |
| 178 | +resources = qre.estimate(qsvt_op, gate_set=gs) |
| 179 | +print(resources) |
| 180 | + |
| 181 | +############################################################################## |
| 182 | +# With PennyLane's resource estimation functionality we can analyze the cost of QSVT workflows for large |
| 183 | +# system sizes consisting of hundreds of qubits and millions of gates! |
| 184 | +# |
| 185 | +# Conclusion |
| 186 | +# ---------- |
| 187 | +# In this demo, you learned how to use PennyLane's :mod:`~.pennylane.estimator` module to determine the |
| 188 | +# resource requirements for **QSVT**. Now that you are armed with these tools for resource estimation, |
| 189 | +# I challenge you to find another problem where polynomial transformations may be helpful, and figure out: |
| 190 | +# what are the logical resource requirements of solving this on a quantum computer? |
| 191 | +# |
| 192 | +# References |
| 193 | +# ---------- |
| 194 | +# |
| 195 | +# .. [#chuang2021] |
| 196 | +# |
| 197 | +# John M. Martyn, Zane M. Rossi, Andrew K. Tan, and Isaac L. Chuang, |
| 198 | +# "A Grand Unification of Quantum Algorithms" |
| 199 | +# `arxiv.2105.02859 <https://arxiv.org/abs/2105.02859>`__, 2021. |
| 200 | +# |
0 commit comments