-
Notifications
You must be signed in to change notification settings - Fork 188
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
213 additions
and
0 deletions.
There are no files selected for viewing
Binary file added
BIN
+54.7 KB
_static/demo_thumbnails/large_demo_thumbnails/thumbnail_large_qsvt_hardware.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+53.6 KB
_static/demo_thumbnails/opengraph_demo_thumbnails/OGthumbnail_qsvt_hardware.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+31.7 KB
_static/demo_thumbnails/regular_demo_thumbnails/thumbnail_qsvt_hardware.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
{ | ||
"title": "How to implement QSVT on hardware", | ||
"authors": [ | ||
{ | ||
"username": "KetPuntoG" | ||
} | ||
], | ||
"dateOfPublication": "2024-09-18T00:00:00+00:00", | ||
"dateOfLastModification": "2024-09-18T00:00:00+00:00", | ||
"categories": [ | ||
"Algorithms", | ||
"Quantum Computing", | ||
"How-to" | ||
], | ||
"tags": [], | ||
"previewImages": [ | ||
{ | ||
"type": "thumbnail", | ||
"uri": "/_static/demo_thumbnails/regular_demo_thumbnails/thumbnail_qsvt_hardware.png" | ||
}, | ||
{ | ||
"type": "large_thumbnail", | ||
"uri": "/_static/demo_thumbnails/large_demo_thumbnails/thumbnail_large_qsvt_hardware.png" | ||
} | ||
], | ||
"seoDescription": "Learn how to implement QSVT on hardware.", | ||
"doi": "", | ||
"canonicalURL": "/qml/demos/tutorial_qsvt_hardware", | ||
"references": [ | ||
], | ||
"basedOnPapers": [], | ||
"referencedByPapers": [], | ||
"relatedContent": [ | ||
{ | ||
"type": "demonstration", | ||
"id": "tutorial_intro_qsvt", | ||
"weight": 1.0 | ||
}, | ||
{ | ||
"type": "demonstration", | ||
"id": "tutorial_apply_qsvt", | ||
"weight": 1.0 | ||
} | ||
|
||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
r"""How to implement QSVT on hardware | ||
======================================= | ||
The :doc:`quantum singular value transform (QSVT) </demos/tutorial_intro_qsvt>` | ||
is a quantum algorithm that allows us to perform polynomial | ||
transformations on matrices or operators, and it is rapidly becoming | ||
a go-to algorithm for :doc:`quantum application research </demos/tutorial_apply_qsvt>` | ||
in the `ISQ era <https://pennylane.ai/blog/2023/06/from-nisq-to-isq/>`__. | ||
In this how-to guide, we will show how we can implement the QSVT | ||
subroutine in a hardware-compatible way, taking your application research | ||
to the next level. | ||
.. figure:: ../_static/demo_thumbnails/opengraph_demo_thumbnails/OGthumbnail_qsvt_hardware.png | ||
:align: center | ||
:width: 50% | ||
:target: javascript:void(0) | ||
Calculating angles | ||
------------------ | ||
Our goal is to apply a polynomial transformation to a given Hamiltonian, i.e., :math:`p(\mathcal{H})`. To achieve this, we must consider the two | ||
fundamental components of the QSVT algorithm: | ||
- **Projection angles**: A list of angles that will determine the coefficients of the polynomial to be applied. | ||
- **Block encoding**: The strategy used to encode the Hamiltonian. We will use the :doc:`linear combinations of unitaries <demos/tutorial_lcu_blockencoding>` approach via the PennyLane :class:`~.qml.PrepSelPrep` operation. | ||
Calculating angles is not a trivial task, but there are tools such as `pyqsp <https://github.com/ichuang/pyqsp/tree/master/pyqsp>`_ that do the job for us. | ||
For instance, to find the angles to apply the polynomial :math:`p(x) = -x + \frac{x^3}{2}+ \frac{x^5}{2}`, we can run this code: | ||
.. code-block:: python | ||
from pyqsp.angle_sequence import QuantumSignalProcessingPhases | ||
import numpy as np | ||
# Define the polynomial, the coefficients are in the order of the polynomial degree. | ||
poly = np.array([0,-1, 0, 0.5, 0 , 0.5]) | ||
ang_seq = QuantumSignalProcessingPhases(poly, signal_operator="Wx") | ||
The angles obtained after execution are as follows: | ||
""" | ||
|
||
ang_seq = [ | ||
-1.5115007723754004, | ||
0.6300762184670975, | ||
0.8813995564082947, | ||
-2.2601930971815003, | ||
3.7716688720568885, | ||
0.059295554419495855, | ||
] | ||
|
||
###################################################################### | ||
# We use these angles to apply the polynomial transformation. | ||
# However, we are not finished yet: these angles have been calculated following the "Wx" | ||
# convention [#unification]_, while :class:`~.qml.PrepSelPrep` follows a different one. Moreover, the angles obtained in the | ||
# context of QSP (the ones given by ``pyqsp``) are not the same as the ones we have to use in QSVT. That is why | ||
# we must transform the angles: | ||
|
||
import numpy as np | ||
|
||
|
||
def convert_angles(angles): | ||
num_angles = len(angles) | ||
update_vals = np.zeros(num_angles) | ||
|
||
update_vals[0] = 3 * np.pi / 4 - (3 + len(angles) % 4) * np.pi / 2 | ||
update_vals[1:-1] = np.pi / 2 | ||
update_vals[-1] = -np.pi / 4 | ||
|
||
return angles + update_vals | ||
|
||
|
||
angles = convert_angles(ang_seq) | ||
print(angles) | ||
|
||
###################################################################### | ||
# Using these angles, we can now start working with the template. | ||
# | ||
# QSVT on hardware | ||
# ----------------- | ||
# | ||
# The :class:`~.qml.QSVT` template expects two inputs. The first one is the block encoding operator, :class:`~.qml.PrepSelPrep`, | ||
# and the second one is a set of projection operators, :class:`~.qml.PCPhase`, that encode the angles properly. | ||
# We will see how to apply them later, but first let's define | ||
# a Hamiltonian and manually apply the polynomial of interest: | ||
|
||
import pennylane as qml | ||
from numpy.linalg import matrix_power as mpow | ||
|
||
coeffs = np.array([0.2, -0.7, -0.6]) | ||
coeffs /= np.linalg.norm(coeffs, ord=1) # Normalize the coefficients | ||
|
||
obs = [qml.X(3), qml.X(3) @ qml.Z(4), qml.Z(3) @ qml.Y(4)] | ||
|
||
H = qml.dot(coeffs, obs) | ||
|
||
H_mat = qml.matrix(H, wire_order=[3, 4]) | ||
|
||
# We calculate p(H) = -H + 0.5 * H^3 + 0.5 * H^5 | ||
H_poly = -H_mat + 0.5 * mpow(H_mat, 3) + 0.5 * mpow(H_mat, 5) | ||
|
||
print(np.round(H_poly, 4)) | ||
|
||
###################################################################### | ||
# Now that we know what the target result is, let's see how to apply the polynomial with a quantum circuit instead. | ||
# We start by defining the proper input operators for the :class:`~.qml.QSVT` template. | ||
|
||
# We need |log2(len(coeffs))| = 2 control wires to encode the Hamiltonian | ||
control_wires = [1, 2] | ||
block_encode = qml.PrepSelPrep(H, control=control_wires) | ||
|
||
projectors = [ | ||
qml.PCPhase(angles[i], dim=2 ** len(H.wires), wires=control_wires + H.wires) | ||
for i in range(len(angles)) | ||
] | ||
|
||
|
||
dev = qml.device("default.qubit") | ||
|
||
@qml.qnode(dev) | ||
def circuit(): | ||
|
||
qml.Hadamard(0) | ||
qml.ctrl(qml.QSVT, control=0, control_values=[1])(block_encode, projectors) | ||
qml.ctrl(qml.adjoint(qml.QSVT), control=0, control_values=[0])(block_encode, projectors) | ||
qml.Hadamard(0) | ||
|
||
return qml.state() | ||
|
||
|
||
matrix = qml.matrix(circuit, wire_order=[0] + control_wires + H.wires)() | ||
print(np.round(matrix[: 2 ** len(H.wires), : 2 ** len(H.wires)], 4)) | ||
|
||
###################################################################### | ||
# The matrix obtained using QSVT is the same as the one obtained by applying the polynomial | ||
# directly to the Hamiltonian! That means the circuit is encoding :math:`p(\mathcal{H})` correctly. | ||
# The great advantage of this approach is that all the building blocks used in the circuit can be | ||
# decomposed into basic gates easily, allowing this circuit | ||
# to be easily executed on hardware devices with PennyLane. | ||
# | ||
# Please also note that QSVT encodes the desired polynomial :math:`p(\mathcal{H})` as well as | ||
# a polynomial :math:`i q(\mathcal{H})`. To isolate :math:`p(\mathcal{H})`, we have used an auxiliary qubit and considered that | ||
# the sum of a complex number and its conjugate gives us twice its real part. We | ||
# recommend :doc:`this demo </demos/tutorial_apply_qsvt>` to learn more about the structure | ||
# of the circuit. | ||
# | ||
# Conclusion | ||
# ---------- | ||
# In this brief how-to we demonstrated applying QSVT on a sample Hamiltonian. Note that the algorithm is sensitive to | ||
# the block-encoding method, so please make sure that the projection angles are converted to the proper format. | ||
# This how-to serves as a guide for running your own workflows and experimenting with more advanced Hamiltonians and polynomial functions. | ||
# | ||
# References | ||
# ---------- | ||
# | ||
# .. [#unification] | ||
# | ||
# John M. Martyn, Zane M. Rossi, Andrew K. Tan, Isaac L. Chuang. | ||
# "A Grand Unification of Quantum Algorithms". | ||
# `arXiv preprint arXiv:2105.02859 <https://arxiv.org/abs/2105.02859>`__. | ||
# | ||
# About the author | ||
# ---------------- | ||
# |