Skip to content
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 template to prepare quantum states of molecules using the excitation operations #1383

Merged
merged 39 commits into from
Jun 10, 2021
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
6cbfbe9
Add new template AllSinglesDoubles
agran2018 Jun 2, 2021
1f08079
Add unit tests
agran2018 Jun 2, 2021
29a38ad
Import the template in __init__.py
agran2018 Jun 2, 2021
7ee1c3f
Add docstrings
agran2018 Jun 3, 2021
d171b07
Modify docstrings
agran2018 Jun 3, 2021
d5a672b
Merge branch 'master' into template-excitation-operations
agran2018 Jun 3, 2021
ebf688c
Black unit tests file
agran2018 Jun 3, 2021
4b388c7
Modify the docstrings
agran2018 Jun 3, 2021
0982ae8
Update CHANGELOG.md
agran2018 Jun 3, 2021
15cd191
Fix the order of the template arguments in the docstring
agran2018 Jun 3, 2021
33f5208
Add template to the documentation
agran2018 Jun 3, 2021
d5609bf
Fix name of the template in templates.rst
agran2018 Jun 3, 2021
a8428f8
Apply suggestions from code review
agran2018 Jun 7, 2021
901536a
Apply suggestions from code review
agran2018 Jun 7, 2021
d4ff316
Modify docstrings according to suggestions
agran2018 Jun 7, 2021
acb89c7
Merge branch 'template-excitation-operations' of github.com:PennyLane…
agran2018 Jun 7, 2021
4523ebb
Polish docstrings
agran2018 Jun 7, 2021
eb9b7ba
Add example to the CHANGELOG.md file
agran2018 Jun 7, 2021
3326044
Merge branch 'master' into template-excitation-operations
agran2018 Jun 7, 2021
42358a8
Modify the example in the CHANGELOG.md
agran2018 Jun 7, 2021
00f576d
Polish docstring
agran2018 Jun 7, 2021
99daea1
Apply suggestions from code review
agran2018 Jun 8, 2021
b1604dd
Apply suggestions from code review
agran2018 Jun 8, 2021
20ed330
Merge branch 'master' into template-excitation-operations
mariaschuld Jun 9, 2021
2e22598
Apply suggestions from code review
agran2018 Jun 9, 2021
39b236c
Update .github/CHANGELOG.md
agran2018 Jun 9, 2021
c1f24d0
Add 'shape' method
agran2018 Jun 9, 2021
f618d6a
Add new test cases
agran2018 Jun 9, 2021
eb1d909
Modify 'shape' function
agran2018 Jun 9, 2021
3ad3935
Merge branch 'master' into template-excitation-operations
agran2018 Jun 9, 2021
270764e
Simplify shape method
agran2018 Jun 9, 2021
4082bb3
Merge branch 'template-excitation-operations' of github.com:PennyLane…
agran2018 Jun 9, 2021
548af4c
Apply suggestions from code review
agran2018 Jun 10, 2021
768f7a3
Apply suggestions from code review
agran2018 Jun 10, 2021
824758d
Merge branch 'master' into template-excitation-operations
agran2018 Jun 10, 2021
132b638
Update shape function and add corresponding unit tests
agran2018 Jun 10, 2021
7798409
Apply suggestions from code review
agran2018 Jun 10, 2021
4a07399
Revert "Apply suggestions from code review"
agran2018 Jun 10, 2021
74b4a57
Merge branch 'master' into template-excitation-operations
agran2018 Jun 10, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .github/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,44 @@

<h3>New features since last release</h3>

* Adds the new template `AllSinglesDoubles` to prepare quantum states of molecules
using the `SingleExcitation` and `DoubleExcitation` operations.
The new template reduces significantly the number of operations
and the depth of the quantum circuit with respect to the traditional UCCSD
unitary.
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved
[(#1383)](https://github.com/PennyLaneAI/pennylane/pull/1383)

For example, consider the case of two particles and four qubits.
First, we define the Hartree-Fock initial state and generate all
possible single and double excitations.

```python
import pennylane as qml
from pennylane import numpy as np

electrons = 2
qubits = 4

hf_state = qml.qchem.hf_state(electrons, qubits)
singles, doubles = qml.qchem.excitations(electrons, qubits)
```
Now we can use the template ``AllSinglesDoubles`` to define the
quantum circuit,

```python
from pennylane.templates import AllSinglesDoubles

wires = range(qubits)

@qml.qnode(dev)
def circuit(weights, hf_state, singles, doubles):
AllSinglesDoubles(weights, wires, hf_state, singles, doubles)
return qml.expval(qml.PauliZ(0))

params = np.random.normal(0, np.pi, len(singles) + len(doubles))
circuit(params, hf_state, singles=singles, doubles=doubles)
agran2018 marked this conversation as resolved.
Show resolved Hide resolved
```

* The `quantum_monte_carlo` transform has been added, allowing an input circuit to be transformed
into the full quantum Monte Carlo algorithm.
[(#1316)](https://github.com/PennyLaneAI/pennylane/pull/1316)
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions doc/introduction/templates.rst
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,11 @@ of other templates.
:description: QuantumMonteCarlo
:figure: ../_static/templates/subroutines/qmc.svg

.. customgalleryitem::
:link: ../code/api/pennylane.templates.subroutines.AllSinglesDoubles.html
:description: AllSinglesDoubles
:figure: ../_static/templates/subroutines/all_singles_doubles.png

.. raw:: html

<div style='clear:both'></div>
Expand Down
1 change: 1 addition & 0 deletions pennylane/templates/subroutines/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,4 @@
from .permute import Permute
from .qpe import QuantumPhaseEstimation
from .qmc import QuantumMonteCarlo
from .all_singles_doubles import AllSinglesDoubles
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved
204 changes: 204 additions & 0 deletions pennylane/templates/subroutines/all_singles_doubles.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# 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.
r"""
Contains the AllSinglesDoubles template.
"""
# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access
import numpy as np
import pennylane as qml
from pennylane.operation import Operation, AnyWires
from pennylane.ops import BasisState


class AllSinglesDoubles(Operation):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I somehow like the name :)

r"""Builds a quantum circuit to prepare correlated states of molecules
by applying all :class:`~.pennylane.SingleExcitation` and
:class:`~.pennylane.DoubleExcitation` operations to
the initial Hartree-Fock state.

The template initializes the :math:`n`-qubit system to encode
the input Hartree-Fock state and applies the particle-conserving
:class:`~.pennylane.SingleExcitation` and
:class:`~.pennylane.DoubleExcitation` operations which are implemented as
`Givens rotations <https://en.wikipedia.org/wiki/Givens_rotation>`_ that act
on the subspace of two and four qubits, respectively. The total number of
excitation gates and the indices of the qubits they act on are obtained
using the :func:`~.excitations` function.

For example, the quantum circuit for the case of two electrons and six qubits
is sketched in the figure below:

|

.. figure:: ../../_static/templates/subroutines/all_singles_doubles.png
:align: center
:width: 70%
:target: javascript:void(0);

|

In this case, we have four single and double excitations that preserve the total-spin
projection of the Hartree-Fock state. The :class:`~.pennylane.SingleExcitation` gate
:math:`G` act on the qubits ``[0, 2], [0, 4], [1, 3], [1, 5]`` as indicated by the
squares, while the :class:`~.pennylane.DoubleExcitation` operation :math:`G^{(2)}` is
applied to the qubits ``[0, 1, 2, 3], [0, 1, 2, 5], [0, 1, 2, 4], [0, 1, 4, 5]``.

The resulting unitary conserves the number of particles and prepares the
:math:`n`-qubit system in a superposition of the initial Hartree-Fock state and
other states encoding multiply-excited configurations.

Args:
weights (tensor_like): size ``(len(singles) + len(doubles),)`` tensor containing the
angles entering the :class:`~.pennylane.SingleExcitation` and
:class:`~.pennylane.DoubleExcitation` operations, in that order
wires (Iterable): wires that the template acts on
hf_state (array[int]): Length ``len(wires)`` occupation-number vector representing the
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved
Hartree-Fock state. ``hf_state`` is used to initialize the wires.
singles (Sequence[Sequence]): sequence of lists with the indices of the two qubits
the :class:`~.pennylane.SingleExcitation` operations act on
doubles (Sequence[Sequence]): sequence of lists with the indices of the four qubits
the :class:`~.pennylane.DoubleExcitation` operations act on

.. UsageDetails::

Notice that:

#. The number of wires has to be equal to the number of spin orbitals included in
ixfoduap marked this conversation as resolved.
Show resolved Hide resolved
the active space.

#. The single and double excitations can be generated with the function
:func:`~.excitations`. See example below.

An example of how to use this template is shown below:

.. code-block:: python

import pennylane as qml
import numpy as np

electrons = 2
qubits = 4

# Define the HF state
hf_state = qml.qchem.hf_state(electrons, qubits)

# Generate all single and double excitations
singles, doubles = qml.qchem.excitations(electrons, qubits)

# Define the device
dev = qml.device('default.qubit', wires=qubits)

wires = range(qubits)

@qml.qnode(dev)
def circuit(weights, hf_state, singles, doubles):
qml.templates.AllSinglesDoubles(weights, wires, hf_state, singles, doubles)
return qml.expval(qml.PauliZ(0))

# Evaluate the QNode for a given set of parameters
params = np.random.normal(0, np.pi, len(singles) + len(doubles))
circuit(params, hf_state, singles=singles, doubles=doubles)
"""

num_params = 1
num_wires = AnyWires
par_domain = "A"

def __init__(self, weights, wires, hf_state, singles=None, doubles=None, do_queue=True):

if len(wires) < 2:
raise ValueError(
"The number of qubits (wires) can not be less than 2; got len(wires) = {}".format(
len(wires)
)
)

if not singles and not doubles:
raise ValueError(
"'singles' and 'doubles' lists can not be both empty; got singles = {}, doubles = {}".format(
singles, doubles
)
)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's still a matter of taste, but we are trying to keep the checks to an absolute minimum, because they are used in every qnode call...

My thinking is that we should check tensor dimensions (since this is an annoying error to see), and things that are theoretically tricky. So if this check is something a user with a look at the docs can get right, maybe we should delete it?

Non-blocking comment though

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. My concern in removing this check is that the user may want to call this template without passing singles and doubles. In this case, the template will not raise an error, will only prepare the HF state and numbers will come out (even though the state the user is preparing is trivial). I vote to keep it :-).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that not a evaluates to True if a=None, interesting!


if doubles is not None:
for d_wires in doubles:
if len(d_wires) != 4:
raise ValueError(
"Expected entries of 'doubles' to be of size 4; got {} of length {}".format(
d_wires, len(d_wires)
)
)

if singles is not None:
for s_wires in singles:
if len(s_wires) != 2:
raise ValueError(
"Expected entries of 'singles' to be of size 2; got {} of length {}".format(
s_wires, len(s_wires)
)
)

weights_shape = qml.math.shape(weights)
exp_shape = self.shape(singles, doubles)
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved
if weights_shape != exp_shape:
raise ValueError(f"'weights' tensor must be of shape {exp_shape}; got {weights_shape}.")

# we can extract the numpy representation here since hf_state can never be differentiable
self.hf_state = qml.math.toarray(hf_state)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice! I need to get used to using qml.math

self.singles = singles
self.doubles = doubles

if hf_state.dtype != np.dtype("int"):
raise ValueError(f"Elements of 'hf_state' must be integers; got {hf_state.dtype}")

super().__init__(weights, wires=wires, do_queue=do_queue)

def expand(self):

weights = self.parameters[0]

with qml.tape.QuantumTape() as tape:

BasisState(self.hf_state, wires=self.wires)

for i, d_wires in enumerate(self.doubles):
qml.DoubleExcitation(weights[len(self.singles) + i], wires=d_wires)

for j, s_wires in enumerate(self.singles):
qml.SingleExcitation(weights[j], wires=s_wires)

return tape

@staticmethod
def shape(singles, doubles):
r"""Returns the shape of the tensor containing the circuit parameters.
agran2018 marked this conversation as resolved.
Show resolved Hide resolved

Args:
singles (Sequence[Sequence]): sequence of lists with the indices of the two qubits
the :class:`~.pennylane.SingleExcitation` operations act on
doubles (Sequence[Sequence]): sequence of lists with the indices of the four qubits
the :class:`~.pennylane.DoubleExcitation` operations act on

Returns:
tuple(int): shape of the tensor containing the circuit parameters
"""
if singles is None:
if doubles is not None:
agran2018 marked this conversation as resolved.
Show resolved Hide resolved
shape_ = (len(doubles),)
elif doubles is None:
shape_ = (len(singles),)
else:
shape_ = (len(singles) + len(doubles),)

return shape_
mariaschuld marked this conversation as resolved.
Show resolved Hide resolved
Loading