-
Notifications
You must be signed in to change notification settings - Fork 586
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add quantum phase estimation template #1095
Merged
Merged
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit
Hold shift + click to select a range
cf4279e
Add basic template
trbromley 929abdf
Include template
trbromley 00102f1
Add to docstrings
trbromley 88665e1
Merge branch 'master' into quantum_phase_estimation
trbromley 15b9ecd
Add note
trbromley ed57ccd
Add to changelog
trbromley c857820
add test
trbromley 5a16220
fix test
trbromley 9938f7a
Add test
trbromley 4026fc3
Fix circuit
trbromley b8378fc
Add test
trbromley 59755cb
Run black on test
trbromley dc5cebf
Add to docstring
trbromley b8d4f9b
Add to docstring:
trbromley 0a42c6b
Update image
trbromley 5389080
Merge branch 'master' into quantum_phase_estimation
trbromley 242edca
Test commit: adding qpe example
DSGuala 4b39d79
Added first attempt at qpe example
DSGuala 27ba692
Merge branch 'quantum_phase_estimation' of github.com:XanaduAI/pennyl…
trbromley e5f9285
Update example
trbromley f9cc5f2
Add to changelog
trbromley 4e1a708
update
trbromley 76fc3d1
Update
trbromley d1b7521
Update
trbromley 1f700a1
Add more efficient version
trbromley 1c66ebd
Fix
trbromley 25f126c
New
trbromley eee7cda
Fix
trbromley eef7c4c
Merge branch 'master' into quantum_phase_estimation
trbromley 8b7d6d2
Improve tests
trbromley 29193dc
Add test
trbromley 2d5abfb
u -> unitary
trbromley af75be2
Update docstring
trbromley 5255248
QPE example: phase_estimated rescale edit
DSGuala 6aa3326
Merge branch 'master' into quantum_phase_estimation
trbromley fc71cc4
Merge branch 'master' into quantum_phase_estimation
trbromley 5187414
Merge branch 'master' into quantum_phase_estimation
trbromley File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
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
Binary file not shown.
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,25 @@ | ||
\documentclass{standalone} | ||
\usepackage{qcircuit} | ||
|
||
\begin{document} | ||
\Qcircuit @C=1em @R=0.5em { | ||
& & & & & & & & &\\ | ||
& & & & \hspace{-0.5cm}\mbox{target wires} & &\\ | ||
\\ | ||
& \qw & \multigate{3}{U^{2^{n - 1}}} & \multigate{3}{U^{2^{n - 2}}} & \qw & \cdots & & \multigate{3}{U} & \qw & \qw \\ | ||
& \qw & \ghost{U^{2^{n - 1}}} & \ghost{U^{2^{n - 2}}} & \qw & \cdots & & \ghost{U} & \qw & \qw \\ | ||
& \qw & \ghost{U^{2^{n - 1}}} & \ghost{U^{2^{n - 2}}} & \qw & \cdots & & \ghost{U} & \qw & \qw \\ | ||
& \qw & \ghost{U^{2^{n - 1}}} & \ghost{U^{2^{n - 2}}} & \qw & \cdots & & \ghost{U} & \qw & \qw \\ | ||
& & & & & & & & &\\ | ||
& & & & & & & & &\\ | ||
& & & & & & & & &\\ | ||
& \gate{H} & \ctrl{-4} & \qw & \qw & \cdots & & \qw & \multigate{4}{QFT^{-1}} & \qw \\ | ||
& \gate{H} & \qw & \ctrl{-5} & \qw & \cdots & & \qw & \ghost{QFT^{-1}} & \qw\\ | ||
& \vdots & & & & \ddots & & & \\ | ||
& & & & & & & &\\ | ||
& \gate{H} \gategroup{10}{1}{17}{10}{.8em}{--}\gategroup{1}{1}{8}{10}{.8em}{--} & \qw & \qw & \qw & \cdots & & \ctrl{-8} & \ghost{QFT^{-1}} & \qw | ||
\\ | ||
& & & \hspace{1.6cm}\mbox{estimation wires} & & & & & & \\ | ||
& & & & & & & & & \\ | ||
} | ||
\end{document} |
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
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
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,123 @@ | ||
# Copyright 2018-2021 Xanadu Quantum Technologies Inc. | ||
|
||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
|
||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
|
||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
""" | ||
Contains the ``QuantumPhaseEstimation`` template. | ||
""" | ||
import pennylane as qml | ||
from pennylane.templates.decorator import template | ||
from pennylane.wires import Wires | ||
|
||
|
||
@template | ||
def QuantumPhaseEstimation(unitary, target_wires, estimation_wires): | ||
r"""Performs the | ||
`quantum phase estimation <https://en.wikipedia.org/wiki/Quantum_phase_estimation_algorithm>`__ | ||
circuit. | ||
|
||
Given a unitary matrix :math:`U`, this template applies the circuit for quantum phase | ||
estimation. The unitary is applied to the qubits specified by ``target_wires`` and :math:`n` | ||
qubits are used for phase estimation as specified by ``estimation_wires``. | ||
|
||
.. figure:: ../../_static/templates/subroutines/qpe.svg | ||
:align: center | ||
:width: 60% | ||
:target: javascript:void(0); | ||
|
||
This circuit can be used to perform the standard quantum phase estimation algorithm, consisting | ||
of the following steps: | ||
|
||
#. Prepare ``target_wires`` in an eigenstate of :math:`U`. If that eigenstate has a | ||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
corresponding eigenvalue :math:`e^{2 \pi i \theta}` with phase :math:`\theta \in [0, 1)`, | ||
this algorithm will measure :math:`\theta`. | ||
#. Apply the ``QuantumPhaseEstimation`` circuit. | ||
#. Measure ``estimation_wires`` using :func:`~.probs`, giving a probability distribution over | ||
measurement outcomes in the computational basis. | ||
#. Find the index of the largest value in the probability distribution and divide that number by | ||
:math:`2^{n}`. This number will be an estimate of :math:`\theta` with an error that decreases | ||
exponentially with the number of qubits :math:`n`. | ||
|
||
Note that if :math:`\theta \in (-1, 0]`, we can estimate the phase by again finding the index | ||
:math:`i` found in step 4 and calculating :math:`\theta \approx \frac{1 - i}{2^{n}}`. The | ||
usage details below give an example of this case. | ||
|
||
Args: | ||
unitary (array): the phase estimation unitary, specified as a matrix | ||
target_wires (Union[Wires, Sequence[int], or int]): the target wires to apply the unitary | ||
estimation_wires (Union[Wires, Sequence[int], or int]): the wires to be used for phase | ||
estimation | ||
|
||
Raises: | ||
QuantumFunctionError: if the ``target_wires`` and ``estimation_wires`` share a common | ||
element | ||
|
||
.. UsageDetails:: | ||
|
||
Consider the matrix corresponding to a rotation from an :class:`~.RX` gate: | ||
|
||
.. code-block:: python | ||
|
||
import pennylane as qml | ||
from pennylane.templates import QuantumPhaseEstimation | ||
from pennylane import numpy as np | ||
|
||
phase = 5 | ||
target_wires = [0] | ||
u = qml.RX(phase, wires=0).matrix | ||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
The ``phase`` parameter can be estimated using ``QuantumPhaseEstimation``. An example is | ||
shown below using a register of five phase-estimation qubits: | ||
|
||
.. code-block:: python | ||
|
||
n_estimation_wires = 5 | ||
estimation_wires = range(1, n_estimation_wires + 1) | ||
|
||
dev = qml.device("default.qubit", wires=n_estimation_wires + 1) | ||
|
||
@qml.qnode(dev) | ||
def circuit(): | ||
# Start in the |+> eigenstate of the unitary | ||
qml.Hadamard(wires=target_wires) | ||
|
||
QuantumPhaseEstimation( | ||
u, | ||
target_wires=target_wires, | ||
estimation_wires=estimation_wires, | ||
) | ||
|
||
return qml.probs(estimation_wires) | ||
|
||
phase_estimated = np.argmax(circuit()) / 2 ** n_estimation_wires | ||
|
||
# Need to rescale phase due to convention of RX gate | ||
phase_estimated = 4 * np.pi * (1 - phase) | ||
""" | ||
|
||
target_wires = Wires(target_wires) | ||
estimation_wires = Wires(estimation_wires) | ||
|
||
if len(Wires.shared_wires([target_wires, estimation_wires])) != 0: | ||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
raise qml.QuantumFunctionError("The target wires and estimation wires must be different") | ||
|
||
unitary_powers = [unitary] | ||
|
||
for _ in range(len(estimation_wires) - 1): | ||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
new_power = unitary_powers[-1] @ unitary_powers[-1] | ||
unitary_powers.append(new_power) | ||
|
||
for wire in estimation_wires: | ||
qml.Hadamard(wire) | ||
qml.ControlledQubitUnitary(unitary_powers.pop(), control_wires=wire, wires=target_wires) | ||
trbromley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
qml.QFT(wires=estimation_wires).inv() |
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
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
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be good to discuss a bit more whether we want to pass the unitary or its generator, i.e., the Hamiltonian. I'm a bit afraid that we're narrowing the scope to how QPE is used in quantum Monte Carlo. But QPE is used in a lot of places, for example in versions of Shor's algorithm, for preparing approximate ground states of Hamiltonians, and more.
Maybe we can compile a list of applications of QPE and that can help guide how best to create a template around it? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like the suggestion about supporting input Hamiltonians, and yes you're right I hadn't been thinking so much in that direction.
So we have the two options for input:
qml.Hamiltonian
, and evolution timet
, and we can do exp(2 pi i H t).For me, the best option would be to have two separate templates, given that the inputs and how they will be dealt with are quite different. In option 2, we'd need to use
ApproxTimeEvolution
, whereas option 1 would directly apply controlled versions of the circuit. In either case, we need access to aqml.control()
transform.For now, we've done option 1 with a matrix-based input. I'm not sure if it's worth supporting a matrix-based version of option 2, since one could just calculate the matrix exponential themselves. On the other hand, users typically have access to a
qml.Hamiltonian
and I couldn't work out how to get the matrix version of that! But withqml.Hamiltonian
I can only see how to do it withqml.control()
.So overall, I totally agree, but think we'd be better to wait for supporting functionality to come online.
One question might be what we call the two options, e.g.,
QuantumPhaseEstimation
orUnitaryPhaseEstimation
?HamiltonianPhaseEstimation
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm happy to wait for more functionality to come online before supporting Hamiltonian inputs. I'm not sure if having two templates is preferable to supporting to different types of arguments, but we can discuss that in the future. Re names: let's also discuss in the future. I like keeping
QuantumPhaseEstimation
for this form of the template