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

[QAOA] Adds Built-In Mixer Hamiltonians #712

Merged
merged 48 commits into from
Jul 30, 2020
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
fe68f61
qaoa
Lucaman99 Jul 15, 2020
b66960b
mixer
Lucaman99 Jul 16, 2020
bc2db2d
stuff
Lucaman99 Jul 16, 2020
bfa7d91
changes
Lucaman99 Jul 16, 2020
9c606d7
qaoa
Lucaman99 Jul 16, 2020
9097b13
qaoa
Lucaman99 Jul 17, 2020
80c548b
qaoa
Lucaman99 Jul 17, 2020
2f550bc
black and pylint
Lucaman99 Jul 17, 2020
be28a71
changes
Lucaman99 Jul 17, 2020
15b482a
edit
Lucaman99 Jul 17, 2020
0502072
qaoa
Lucaman99 Jul 17, 2020
f2d8ead
qaoa changes
Lucaman99 Jul 17, 2020
78576d2
edits
Lucaman99 Jul 17, 2020
02e9a35
black
Lucaman99 Jul 17, 2020
82e9f14
small changes
Lucaman99 Jul 17, 2020
6c7bebb
changes
Lucaman99 Jul 17, 2020
68f67dd
change
Lucaman99 Jul 17, 2020
bec5da5
Apply suggestions from code review
Lucaman99 Jul 20, 2020
0e06206
qaoa
Lucaman99 Jul 20, 2020
942b553
qaoa
Lucaman99 Jul 20, 2020
bd4b469
edit
Lucaman99 Jul 20, 2020
9d232e4
changes
Lucaman99 Jul 20, 2020
3366148
Update pennylane/qaoa/qaoa.py
Lucaman99 Jul 20, 2020
aabc2b6
Update pennylane/qaoa/qaoa.py
Lucaman99 Jul 20, 2020
31bae00
yes
Lucaman99 Jul 21, 2020
ffc59bd
yes
Lucaman99 Jul 21, 2020
a0ae217
edit
Lucaman99 Jul 22, 2020
57b6e67
changes
Lucaman99 Jul 22, 2020
aff659a
edit
Lucaman99 Jul 22, 2020
ab2f4b8
small edit
Lucaman99 Jul 22, 2020
948d93f
Merge branch 'master' into mixers-new
josh146 Jul 23, 2020
097010c
changes
Lucaman99 Jul 24, 2020
138d210
edit
Lucaman99 Jul 24, 2020
74f07d6
edit
Lucaman99 Jul 24, 2020
a9b70a2
edit
Lucaman99 Jul 24, 2020
488d5ed
Merge branch 'master' into mixers-new
trbromley Jul 24, 2020
f5162cd
changes
Lucaman99 Jul 24, 2020
8a96459
wires
Lucaman99 Jul 27, 2020
f6c4251
Update pennylane/qaoa/mixers.py
Lucaman99 Jul 30, 2020
82dc93e
Update pennylane/qaoa/mixers.py
Lucaman99 Jul 30, 2020
b49a828
edit
Lucaman99 Jul 30, 2020
4a3350c
Merge branch 'master' into mixers-new
Lucaman99 Jul 30, 2020
04e67d5
changes
Lucaman99 Jul 30, 2020
8b11d46
edit
Lucaman99 Jul 30, 2020
202d92d
edit
Lucaman99 Jul 30, 2020
3b7f673
re-run tests
Lucaman99 Jul 30, 2020
3f9a401
small edit
Lucaman99 Jul 30, 2020
e852132
Merge branch 'master' into mixers-new
Lucaman99 Jul 30, 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
9 changes: 9 additions & 0 deletions doc/code/qml_qaoa.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
qml.qaoa
========

.. currentmodule:: pennylane.qaoa

.. automodapi:: pennylane.qaoa
:no-heading:
:no-inheritance-diagram:
:no-inherited-members:
1 change: 1 addition & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -214,3 +214,4 @@ PennyLane is **free** and **open source**, released under the Apache License, Ve
code/qml_variable
code/qml_wires
code/qml_beta
code/qml_qaoa
18 changes: 18 additions & 0 deletions pennylane/qaoa/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Copyright 2018-2020 Xanadu Quantum Technologies Inc.
Lucaman99 marked this conversation as resolved.
Show resolved Hide resolved

# 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"""
This module contains functionality to construct QAOA workflows in PennyLane
"""

from .mixers import *
79 changes: 79 additions & 0 deletions pennylane/qaoa/mixers.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# 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"""
This file contains built-in functions for constructing QAOA mixer Hamiltonians.
"""
import networkx as nx
import pennylane as qml


def x_mixer(n):
r"""Creates a basic Pauli-X mixer Hamiltonian.

This Hamiltonian is defined as:

.. math:: H_M \ = \ \displaystyle\sum_{i} X_{i},

where :math:`i` ranges over all wires, and :math:`X_i`
denotes the Pauli-X operator on the :math:`i`-th wire.
This is the mixer that was used in the `original QAOA
paper <https://arxiv.org/abs/1411.4028>`__.
Lucaman99 marked this conversation as resolved.
Show resolved Hide resolved


Args:
n (int): The number of wires on which the Hamiltonian is applied

Lucaman99 marked this conversation as resolved.
Show resolved Hide resolved
Returns:
Hamiltonian: Mixer Hamiltonian
"""

wires = range(n)

coeffs = [1 for w in wires]
obs = [qml.PauliX(w) for w in wires]

return qml.Hamiltonian(coeffs, obs)


def xy_mixer(graph):
r"""Creates a generalized SWAP/XY mixer Hamiltonian.

This mixer Hamiltonian is defined as:

.. math:: H_M \ = \ \frac{1}{2} \displaystyle\sum_{(i, j) \in E(G)} X_i X_j \ + \ Y_i Y_j,

for some graph :math:`G`. :math:`X_i` and :math:`Y_i` denote the Pauli-X and Pauli-Y operators on the :math:`i`-th
wire respectively. This mixer was first presented in `this paper <https://arxiv.org/abs/1709.03489>`__.
Lucaman99 marked this conversation as resolved.
Show resolved Hide resolved

Args:
graph (nx.Graph): A graph defining the pairs of wires on which each term of the Hamiltonian acts.

Returns:
Hamiltonian: Mixer Hamiltonian
"""

if not isinstance(graph, nx.Graph):
raise ValueError(
"Input graph must be a nx.Graph object, got {}".format(type(graph).__name__)
)

edges = graph.edges
coeffs = 2 * [0.5 for e in edges]

obs = []
for node1, node2 in edges:
obs.append(qml.PauliX(node1) @ qml.PauliX(node2))
obs.append(qml.PauliY(node1) @ qml.PauliY(node2))

return qml.Hamiltonian(coeffs, obs)
136 changes: 136 additions & 0 deletions tests/test_qaoa.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
# 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.
"""
Unit tests for the :mod:`pennylane.qaoa` submodule.
"""
import pytest
import numpy as np
import pennylane as qml
from pennylane import qaoa
from networkx import Graph


#####################################################

graph = Graph()
graph.add_nodes_from([0, 1, 2])
graph.add_edges_from([(0, 1), (1, 2)])

non_consecutive_graph = Graph([(0, 4), (3, 4), (2, 1), (2, 0)])


class TestMixerHamiltonians:
"""Tests that the mixer Hamiltonians are being generated correctly"""

def test_x_mixer_output(self):
Copy link
Contributor

Choose a reason for hiding this comment

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

Might be nice to have a test for non-consecutive wires

Copy link
Contributor

Choose a reason for hiding this comment

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

How about adding a parametrize over this function that tries two cases, one with consecutive and one with non-consecutive wires?

"""Tests that the output of the Pauli-X mixer is correct"""

num_wires = 4
mixer_hamiltonian = qaoa.x_mixer(num_wires)

mixer_coeffs = mixer_hamiltonian.coeffs
mixer_ops = [i.name for i in mixer_hamiltonian.ops]
mixer_wires = [i.wires[0] for i in mixer_hamiltonian.ops]

assert mixer_coeffs == [1, 1, 1, 1]
assert mixer_ops == ["PauliX", "PauliX", "PauliX", "PauliX"]
assert mixer_wires == [0, 1, 2, 3]

def test_xy_mixer_type_error(self):
"""Tests that the XY mixer throws the correct error"""

graph = [(0, 1), (1, 2)]

with pytest.raises(ValueError, match=r"Input graph must be a nx.Graph object, got list"):
output = qaoa.xy_mixer(graph)

@pytest.mark.parametrize(
("graph", "target_hamiltonian"),
[
(
Graph([(0, 1), (1, 2), (2, 3)]),
qml.Hamiltonian(
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[
qml.PauliX(0) @ qml.PauliX(1),
qml.PauliY(0) @ qml.PauliY(1),
qml.PauliX(1) @ qml.PauliX(2),
qml.PauliY(1) @ qml.PauliY(2),
qml.PauliX(2) @ qml.PauliX(3),
qml.PauliY(2) @ qml.PauliY(3),
],
),
),
(
Graph((np.array([0, 1]), np.array([1, 2]), np.array([2, 0]))),
qml.Hamiltonian(
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[
qml.PauliX(0) @ qml.PauliX(1),
qml.PauliY(0) @ qml.PauliY(1),
qml.PauliX(0) @ qml.PauliX(2),
qml.PauliY(0) @ qml.PauliY(2),
qml.PauliX(1) @ qml.PauliX(2),
qml.PauliY(1) @ qml.PauliY(2),
],
),
),
(
graph,
qml.Hamiltonian(
[0.5, 0.5, 0.5, 0.5],
[
qml.PauliX(0) @ qml.PauliX(1),
qml.PauliY(0) @ qml.PauliY(1),
qml.PauliX(1) @ qml.PauliX(2),
qml.PauliY(1) @ qml.PauliY(2),
],
),
),
(
non_consecutive_graph,
qml.Hamiltonian(
[0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5, 0.5],
[
qml.PauliX(0) @ qml.PauliX(4),
qml.PauliY(0) @ qml.PauliY(4),
qml.PauliX(0) @ qml.PauliX(2),
qml.PauliY(0) @ qml.PauliY(2),
qml.PauliX(4) @ qml.PauliX(3),
qml.PauliY(4) @ qml.PauliY(3),
qml.PauliX(2) @ qml.PauliX(1),
qml.PauliY(2) @ qml.PauliY(1),
],
),
),
],
)
def test_xy_mixer_output(self, graph, target_hamiltonian):
"""Tests that the output of the XY mixer is correct"""

print(graph.edges)

mixer_hamiltonian = qaoa.xy_mixer(graph)

mixer_coeffs = mixer_hamiltonian.coeffs
mixer_ops = [i.name for i in mixer_hamiltonian.ops]
mixer_wires = [i.wires for i in mixer_hamiltonian.ops]

target_coeffs = target_hamiltonian.coeffs
target_ops = [i.name for i in target_hamiltonian.ops]
target_wires = [i.wires for i in target_hamiltonian.ops]

assert mixer_coeffs == target_coeffs
assert mixer_ops == target_ops
assert mixer_wires == target_wires