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 hardware-efficient particle-conserving ansatz U2 #876

Merged
merged 38 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
4402b4c
Add the ParticleConservingU2 template
soranjh Oct 29, 2020
6b79fc7
Fix import issue
soranjh Oct 29, 2020
e315801
Add enumerate instead of iterating
soranjh Oct 29, 2020
02bf0c6
Add exception unittest
soranjh Oct 30, 2020
14496ed
Add integration and parameters unittests
soranjh Oct 30, 2020
024d1cc
Add operations unittest
soranjh Nov 2, 2020
0a364c4
Run black
soranjh Nov 2, 2020
0a721e8
Add unittest for circuit wires
soranjh Nov 2, 2020
4351a06
Add two sets of parameters to unittest
soranjh Nov 2, 2020
1b40a60
Add a new set of parameters to unittest
soranjh Nov 2, 2020
e27b55f
Merge branch 'master' into hardware-efficient-ansatz-u2
soranjh Nov 4, 2020
38243a2
Add modified image and equations
soranjh Nov 4, 2020
d717eba
Add correction to docstring
soranjh Nov 4, 2020
926b78e
Add unittest and few docstring corrections
soranjh Nov 6, 2020
c7d344e
Remove unused imports
soranjh Nov 6, 2020
cd56154
Merge branch 'master' into hardware-efficient-ansatz-u2
mariaschuld Nov 9, 2020
2bdd90c
Apply suggestions from code review
soranjh Nov 11, 2020
e6ec44f
Run black and correct format
soranjh Nov 11, 2020
bee2b01
Apply suggestions from code review
soranjh Nov 11, 2020
31e7219
Apply suggestions from code review
soranjh Nov 11, 2020
cb874a4
Apply suggestions from code review
soranjh Nov 11, 2020
77e1ef2
Add correction to error message
soranjh Nov 11, 2020
7c0cce7
Add modified images
soranjh Nov 11, 2020
657fba5
Apply suggestions from code review
soranjh Nov 13, 2020
de2fd65
Add gate decomposition test
soranjh Nov 16, 2020
46cc716
Add gate decomposition test
soranjh Nov 16, 2020
9b53c66
Modify gate decomposition test
soranjh Nov 16, 2020
3ba07ab
Correct image dimensions
soranjh Nov 16, 2020
3b6382b
Merge master into the branch and resolve conflicts
soranjh Nov 16, 2020
c169859
Resolve conflicts
soranjh Nov 16, 2020
ca42739
Resolve conflicts
soranjh Nov 16, 2020
66c11a1
Add feature to changelog
soranjh Nov 17, 2020
c3e5fd2
Apply suggestions from code review
soranjh Nov 17, 2020
ad9f59e
Apply suggestions from code review
soranjh Nov 17, 2020
e6afe28
Merge branch 'master' into hardware-efficient-ansatz-u2
soranjh Nov 17, 2020
08ab413
Modify CHANGELOG
soranjh Nov 17, 2020
2da0614
Merge branch 'master' into hardware-efficient-ansatz-u2
soranjh Nov 18, 2020
e3d0eba
Merge branch 'master' into hardware-efficient-ansatz-u2
soranjh Nov 18, 2020
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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
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 @@ -110,6 +110,11 @@ neural network. Note arbitrary templates or operations can also be layered using
:description: BasicEntanglerLayers
:figure: ../_static/templates/layers/basic_entangler.png

.. customgalleryitem::
:link: ../code/api/pennylane.templates.layers.ParticleConservingU2.html
:description: ParticleConservingU2
:figure: ../_static/templates/layers/particle_conserving_u2.png
soranjh marked this conversation as resolved.
Show resolved Hide resolved

.. raw:: html

<div style='clear:both'></div>
Expand Down
58 changes: 58 additions & 0 deletions pennylane/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,64 @@
from pennylane import numpy as np


def particle_conserving_u2_uniform(n_layers, n_wires, low=0, high=2 * pi, seed=None):
r"""Creates a parameter array for :func:`~.ParticleConservingU2`, drawn from a uniform
distribution.
Each parameter is drawn uniformly at random from between ``low`` and ``high``.
soranjh marked this conversation as resolved.
Show resolved Hide resolved
The parameters define the trainable angles entering the Z rotation
:math:`R_\mathrm{z}(\vec{\theta})` and particle-conserving gate :math:`U_{2,\mathrm{ex}}`
implemented by the :func:`~.u2_ex_gate()`.
Args:
n_layers (int): number of layers
n_wires (int): number of qubits
low (float): minimum value of uniform distribution
soranjh marked this conversation as resolved.
Show resolved Hide resolved
high (float): maximum value of uniform distribution
soranjh marked this conversation as resolved.
Show resolved Hide resolved
seed (int): seed used in sampling the parameters, makes function call deterministic
Returns:
array: parameter array
"""

if seed is not None:
np.random.seed(seed)

if n_wires < 2:
raise ValueError(
"The number of qubits must be greater than one; got 'n_wires' = {}".format(n_wires)
)

params = np.random.uniform(low=low, high=high, size=(n_layers, 2 * n_wires - 1))
return params


def particle_conserving_u2_normal(n_layers, n_wires, mean=0, std=0.1, seed=None):
r"""Creates a parameter array for :func:`~.ParticleConservingU2`, drawn from a normal
distribution.
Each parameter is drawn from a normal distribution with ``mean`` and standard deviation ``std``.
The parameters define the trainable angles entering the Z rotation
:math:`R_\mathrm{z}(\vec{\theta})` and particle-conserving gate :math:`U_{2,\mathrm{ex}}`
implemented by the :func:`~.u2_ex_gate()`.
Args:
n_layers (int): number of layers
n_wires (int): number of qubits
mean (float): mean of parameters
std (float): standard deviation of parameters
seed (int): seed used in sampling the parameters, makes function call deterministic
Returns:
array: parameter array
"""

if seed is not None:
np.random.seed(seed)

if n_wires < 2:
raise ValueError(
"The number of qubits must be greater than one; got 'n_wires' = {}".format(n_wires)
)

params = np.random.normal(loc=mean, scale=std, size=(n_layers, 2 * n_wires - 1))
return params


def qaoa_embedding_uniform(n_layers, n_wires, low=0, high=2 * pi, seed=None):
r"""Creates a parameter array for :func:`~.QAOAEmbedding`, drawn from a uniform
distribution.
Expand Down
1 change: 1 addition & 0 deletions pennylane/templates/layers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,4 @@
from .cv_neural_net import CVNeuralNetLayers
from .simplified_two_design import SimplifiedTwoDesign
from .basic_entangler import BasicEntanglerLayers
from .particle_conserving_u2 import ParticleConservingU2
192 changes: 192 additions & 0 deletions pennylane/templates/layers/particle_conserving_u2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Copyright 2018-2020 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 hardware efficient ``ParticleConservingU2`` template.
"""
import pennylane as qml

# pylint: disable-msg=too-many-branches,too-many-arguments,protected-access
from pennylane.templates.decorator import template
from pennylane.ops import CNOT, CRX, RZ
from pennylane.templates.utils import (
check_shape,
get_shape,
)
from pennylane.wires import Wires


def u2_ex_gate(phi, wires=None):
r"""Implement the two-qubit exchange gate :math:`U_{2,\mathrm{ex}}` proposed in
soranjh marked this conversation as resolved.
Show resolved Hide resolved
`arXiv:1805.04340 <https://arxiv.org/abs/1805.04340>`_ to build particle-conserving VQE ansatze
for Quantum Chemistry simulations.

The unitary matrix :math:`U_{2, \mathrm{ex}}` acts on the Hilbert space of two qubits

.. math::

U_{2, \mathrm{ex}}(\phi) = \left(\begin{array}{cccc}
1 & 0 & 0 & 0 \\
0 & \mathrm{cos}(\phi) & -i\;\mathrm{sin}(\phi) & 0 \\
0 & -i\;\mathrm{sin}(\phi) & \mathrm{cos}(\phi) & 0 \\
0 & 0 & 0 & 1 \\
\end{array}\right).

The figure below shows the circuit used to decompose :math:`U_{2, \mathrm{ex}}` in
soranjh marked this conversation as resolved.
Show resolved Hide resolved
elementary gates

|

.. figure:: ../../_static/templates/layers/u2_decomposition.png
:align: center
:width: 60%
:target: javascript:void(0);

|

soranjh marked this conversation as resolved.
Show resolved Hide resolved
Args:
phi (float): angle entering the controlled-RX operator :math:`CRX(2\phi)`
wires (list[Wires]): the two wires ``n`` and ``m`` the circuit acts on
"""

CNOT(wires=wires)
CRX(2 * phi, wires=wires[::-1])
CNOT(wires=wires)


@template
def ParticleConservingU2(weights, wires, init_state=None):
r"""Implements the heuristic VQE ansatz for Quantum Chemistry simulations using the
particle-conserving gate :math:`U_\mathrm{ent}(\vec{\theta}, \vec{\phi})` proposed in
soranjh marked this conversation as resolved.
Show resolved Hide resolved
`arXiv:1805.04340 <https://arxiv.org/abs/1805.04340>`_.

This template prepares :math:`N`-qubit trial states by applying :math:`D` layers of entangler
soranjh marked this conversation as resolved.
Show resolved Hide resolved
block :math:`U_\mathrm{ent}(\vec{\theta}, \vec{\phi})` to the Hartree-Fock state

soranjh marked this conversation as resolved.
Show resolved Hide resolved
.. math::

\vert \Psi(\vec{\theta}, \vec{\phi}) \rangle = \hat{U}^{(D)}_\mathrm{ent}(\vec{\theta}_D,
\vec{\phi}_D) \dots \hat{U}^{(2)}_\mathrm{ent}(\vec{\theta}_2, \vec{\phi}_2)
\hat{U}^{(1)}_\mathrm{ent}(\vec{\theta}_1, \vec{\phi}_1) \vert \mathrm{HF}\rangle,

soranjh marked this conversation as resolved.
Show resolved Hide resolved
where :math:`\hat{U}^{(i)}_\mathrm{ent}(\vec{\theta}_i, \vec{\phi}_i) =
\hat{R}^{(i)}_\mathrm{z}(\vec{\theta}_i) \hat{U}^{(i)}_\mathrm{2,\mathrm{ex}}(\vec{\phi}_i)`
soranjh marked this conversation as resolved.
Show resolved Hide resolved
as shown in the figure below::
soranjh marked this conversation as resolved.
Show resolved Hide resolved

|

.. figure:: ../../_static/templates/layers/particle_conserving_u2.png
:align: center
:width: 60%
:target: javascript:void(0);

|

Each layer contains :math:`N` rotation gates :math:`R_\mathrm{z}(\vec{\theta})` and
:math:`N-1` particle-conserving exchange gates :math:`U_{2,\mathrm{ex}}(\phi)`
that act on pairs of nearest-neighbors qubits. The repeated units across several qubits are
shown in dotted boxes. The unitary matrix representing :math:`U_{2,\mathrm{ex}}(\phi)`
(`arXiv:1805.04340 <https://arxiv.org/abs/1805.04340>`_) is decomposed into its elementary
gates and implemented in the :func:`~.u2_ex_gate` function using PennyLane quantum operations.

|

.. figure:: ../../_static/templates/layers/u2_decomposition.png
:align: center
:width: 60%
:target: javascript:void(0);

soranjh marked this conversation as resolved.
Show resolved Hide resolved
|


Args:
weights (array[float]): Array of weights of shape ``(D, M)`` where ``D`` is the number of
layers and ``M`` = :math:`2N-1` is the total number of rotation ``(N)`` and exchange
soranjh marked this conversation as resolved.
Show resolved Hide resolved
``(N-1)`` gates per layer.
wires (Iterable or Wires): Wires that the template acts on. Accepts an iterable of numbers
or strings, or a Wires object.
init_state (array[int]): Length ``len(wires)`` occupation-number vector representing the
soranjh marked this conversation as resolved.
Show resolved Hide resolved
HF state. ``init_state`` is used to initialize the wires.
soranjh marked this conversation as resolved.
Show resolved Hide resolved

Raises:
ValueError: if inputs do not have the correct format

.. UsageDetails::

Notice that:

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

#. The number of trainable parameters scales with the number of layers :math:`D` as
:math:`D(2N-1)`.

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

.. code-block:: python

import pennylane as qml
from pennylane.templates import ParticleConservingU2

from functools import partial

# Build the electronic Hamiltonian
soranjh marked this conversation as resolved.
Show resolved Hide resolved
h, qubits = qml.qchem.molecular_hamiltonian("h2", "h2.xyz")

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

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

# Define the ansatz
ansatz = partial(ParticleConservingU2, init_state=ref_state)

# Define the cost function
cost_fn = qml.VQECost(ansatz, h, dev)

# Compute the expectation value of 'h' for given set of parameters
soranjh marked this conversation as resolved.
Show resolved Hide resolved
layers = 1
params = qml.init.particle_conserving_u2_normal(layers, qubits)
print(cost_fn(params))
"""

wires = Wires(wires)

layers = weights.shape[0]

if len(wires) < 2:
raise ValueError(
"This template requires the number of qubits to be greater than one;"
" got 'len(wires)' = {}".format(len(wires))
soranjh marked this conversation as resolved.
Show resolved Hide resolved
)

expected_shape = (layers, 2 * len(wires) - 1)
check_shape(
weights,
expected_shape,
msg="'weights' must be of shape {}; got {}".format(expected_shape, get_shape(weights)),
)

nm_wires = [wires.subset([l, l + 1]) for l in range(0, len(wires) - 1, 2)]
nm_wires += [wires.subset([l, l + 1]) for l in range(1, len(wires) - 1, 2)]

qml.BasisState(init_state, wires=wires)

for l in range(layers):

for j, _ in enumerate(wires):
RZ(weights[l, j], wires=wires[j])

for i, wires_ in enumerate(nm_wires):
u2_ex_gate(weights[l, len(wires) + i], wires=wires_)
soranjh marked this conversation as resolved.
Show resolved Hide resolved
6 changes: 5 additions & 1 deletion tests/templates/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,10 @@
{'wires': [0, 1, 2, 3], 's_wires': [[0, 1, 2], [1, 2, 3]],
'd_wires': [[[0, 1], [2, 3]]], 'init_state':np.array([1, 1, 0, 0])},
4),
(qml.templates.ParticleConservingU2,
{'weights': np.array([[0.35172862, 0.60808317, 1.44397231]])},
{'wires': [0, 1], 'init_state': np.array([1, 0])},
2),
]

CV_DIFFABLE_NONDIFFABLE = [(qml.templates.DisplacementEmbedding,
Expand Down Expand Up @@ -184,7 +188,7 @@
# before they are called in a quantum function.
# These templates will be skipped in tests of that nature.

NO_OP_BEFORE = ["AmplitudeEmbedding", "UCCSD"]
NO_OP_BEFORE = ["AmplitudeEmbedding", "UCCSD", "ParticleConservingU2"]

# Each entry to QUBIT_INIT and CV_INIT adds a template with specified inputs to the
# integration tests ``TestIntegrationInitFunctions``
Expand Down
Loading