From ac41fb24ebd0ddefb14ed64ff0e950baab562511 Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Wed, 8 Jul 2020 13:11:50 -0400 Subject: [PATCH 01/29] [WIP] Add pasqal device (#31) * adding basic pasqal device * using base simulator and removing qubit worries * adding tests * changes * merge master and fix travis issue * linting * change version * Update pennylane_cirq/pasqal_device.py Co-authored-by: Josh Izaac * Update pennylane_cirq/pasqal_device.py Co-authored-by: Josh Izaac * Update pennylane_cirq/pasqal_device.py Co-authored-by: Josh Izaac Co-authored-by: Josh Izaac --- pennylane_cirq/__init__.py | 1 + pennylane_cirq/pasqal_device.py | 51 +++++++++++++++++++++ requirements.txt | 3 +- setup.py | 3 +- tests/test_pasqal_device.py | 80 +++++++++++++++++++++++++++++++++ 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 pennylane_cirq/pasqal_device.py create mode 100644 tests/test_pasqal_device.py diff --git a/pennylane_cirq/__init__.py b/pennylane_cirq/__init__.py index b076787..8aaf44e 100644 --- a/pennylane_cirq/__init__.py +++ b/pennylane_cirq/__init__.py @@ -16,6 +16,7 @@ =============== """ from .simulator_device import SimulatorDevice, MixedStateSimulatorDevice +from .pasqal_device import PasqalDevice from .ops import BitFlip, PhaseFlip, PhaseDamp, AmplitudeDamp, Depolarize from ._version import __version__ diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py new file mode 100644 index 0000000..1e280f5 --- /dev/null +++ b/pennylane_cirq/pasqal_device.py @@ -0,0 +1,51 @@ +# Copyright 2018 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. +# pylint: disable=too-many-arguments +""" +This module provides the ``PasqalDevice`` from Cirq. +""" +from cirq import pasqal + +from .simulator_device import SimulatorDevice + + +class PasqalDevice(SimulatorDevice): + r"""Cirq Pasqal device for PennyLane. + + Args: + wires (int): the number of wires to initialize the device with + shots (int): Number of circuit evaluations/random samples used + to estimate expectation values of observables. Shots need + to be >= 1. In analytic mode, shots indicates the number of entries + that are returned by ``device.sample``. + analytic (bool): indicates whether expectation values and variances should + be calculated analytically + qubits (List[cirq.ThreeDGridQubit]): A list of Cirq ThreeDGridQubits that are used + as wires. If not specified, the ThreeDGridQubits are put in a linear + arrangement along the first coordinate axis, + i.e., ``(0,0,0), (1,0,0), (2,0,0)``, etc. + control_radius (float): The maximum distance between qubits for a controlled + gate. Distance is measured in units of the ``ThreeDGridQubit`` indices. + """ + name = "Cirq Pasqal device for PennyLane" + short_name = "cirq.pasqal" + + def __init__(self, wires, shots=1000, analytic=True, qubits=None, control_radius=1.0): + + if not qubits: + qubits = [pasqal.ThreeDGridQubit(wire, 0, 0) for wire in range(wires)] + self.control_radius = float(control_radius) + if self.control_radius < 0: + raise ValueError("The control_radius must be a non-negative real number.") + super().__init__(wires, shots, analytic, qubits) diff --git a/requirements.txt b/requirements.txt index da6c1ca..200c37e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,4 @@ pennylane>=0.9 -cirq>=0.7 +google-api-core[grpc]<=1.14.0 +git+https://github.com/lhenriet/Cirq.git numpy~=1.16 diff --git a/setup.py b/setup.py index 5d520f2..5a78f14 100644 --- a/setup.py +++ b/setup.py @@ -35,7 +35,8 @@ "license": "Apache License 2.0", "packages": ["pennylane_cirq"], "entry_points": {"pennylane.plugins": ["cirq.simulator = pennylane_cirq:SimulatorDevice", - "cirq.mixedsimulator = pennylane_cirq:MixedStateSimulatorDevice"],}, + "cirq.mixedsimulator = pennylane_cirq:MixedStateSimulatorDevice", + "cirq.pasqal = pennylane_cirq:PasqalDevice"],}, # Place a one line description here. This will be shown by pip "description": "PennyLane plugin for Cirq", "long_description": open("README.rst").read(), diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py new file mode 100644 index 0000000..ca66e65 --- /dev/null +++ b/tests/test_pasqal_device.py @@ -0,0 +1,80 @@ +# Copyright 2018 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 PasqalDevice +""" +import pytest + +import pennylane as qml +from pennylane_cirq import PasqalDevice, SimulatorDevice +from cirq.pasqal import ThreeDGridQubit + + +class TestDeviceIntegration: + """Tests that the SimulatorDevice integrates well with PennyLane""" + + def test_device_loading(self): + """Tests that the cirq.pasqal device is properly loaded""" + + dev = qml.device("cirq.pasqal", wires=2) + + assert dev.num_wires == 2 + assert len(dev.qubits) == 2 + assert dev.shots == 1000 + assert dev.short_name == "cirq.pasqal" + assert dev.analytic == True + assert dev.control_radius == 1.0 + assert dev.qubits == [ThreeDGridQubit(0, 0, 0), ThreeDGridQubit(1, 0, 0)] + assert isinstance(dev, SimulatorDevice) + + +class TestDevice: + """Unit tests for the PasqalDevice""" + + def test_device_creation(self): + """Tests that the cirq.pasqal device is properly created""" + + dev = PasqalDevice(wires=2, shots=123, control_radius=5.0) + + assert dev.num_wires == 2 + assert len(dev.qubits) == 2 + assert dev.shots == 123 + assert dev.short_name == "cirq.pasqal" + assert dev.analytic == True + assert dev.control_radius == 5.0 + assert dev.qubits == [ThreeDGridQubit(0, 0, 0), ThreeDGridQubit(1, 0, 0)] + assert isinstance(dev, SimulatorDevice) + + @pytest.mark.parametrize( + "coord_idxs", + [ + [(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0)], + [(0, 0, 0), (0, 0, 1), (0, 1, 0), (0, 1, 1)], + [(1, 2, 3), (3, 2, 1), (0, 0, 0), (-1, -1, -10)], + ], + ) + def test_device_creation(self, coord_idxs): + """Tests that ThreeDGridQubits can be passed as an argument""" + + qubits = [ThreeDGridQubit(*idxs) for idxs in coord_idxs] + dev = PasqalDevice(wires=4, qubits=qubits) + + assert dev.qubits == qubits + + def test_control_radius_negative_exception(self): + """Tests that an exception is raised when the supplied control_radius parameter + is a negative real number""" + + with pytest.raises(ValueError, match="must be a non-negative real number"): + dev = PasqalDevice(wires=2, shots=123, control_radius=-5.0) From 92872e2ea50df700d16d8e8a3c03f6797bf47451 Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Fri, 10 Jul 2020 12:31:42 -0400 Subject: [PATCH 02/29] Update branch (#33) * Update requirements.txt * Update requirements.txt * Update requirements.txt * Update pasqal_device.py * Update test_pasqal_device.py Co-authored-by: Josh Izaac --- pennylane_cirq/pasqal_device.py | 2 +- requirements.txt | 2 +- tests/test_pasqal_device.py | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index 1e280f5..63a78d7 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -44,7 +44,7 @@ class PasqalDevice(SimulatorDevice): def __init__(self, wires, shots=1000, analytic=True, qubits=None, control_radius=1.0): if not qubits: - qubits = [pasqal.ThreeDGridQubit(wire, 0, 0) for wire in range(wires)] + qubits = [pasqal.ThreeDQubit(wire, 0, 0) for wire in range(wires)] self.control_radius = float(control_radius) if self.control_radius < 0: raise ValueError("The control_radius must be a non-negative real number.") diff --git a/requirements.txt b/requirements.txt index 200c37e..260a9bf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pennylane>=0.9 google-api-core[grpc]<=1.14.0 -git+https://github.com/lhenriet/Cirq.git +git+https://github.com/lhenriet/Cirq.git@pasqal_new numpy~=1.16 diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index ca66e65..aae18fe 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -18,7 +18,7 @@ import pennylane as qml from pennylane_cirq import PasqalDevice, SimulatorDevice -from cirq.pasqal import ThreeDGridQubit +from cirq.pasqal import ThreeDQubit class TestDeviceIntegration: @@ -35,7 +35,7 @@ def test_device_loading(self): assert dev.short_name == "cirq.pasqal" assert dev.analytic == True assert dev.control_radius == 1.0 - assert dev.qubits == [ThreeDGridQubit(0, 0, 0), ThreeDGridQubit(1, 0, 0)] + assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(1, 0, 0)] assert isinstance(dev, SimulatorDevice) @@ -53,7 +53,7 @@ def test_device_creation(self): assert dev.short_name == "cirq.pasqal" assert dev.analytic == True assert dev.control_radius == 5.0 - assert dev.qubits == [ThreeDGridQubit(0, 0, 0), ThreeDGridQubit(1, 0, 0)] + assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(1, 0, 0)] assert isinstance(dev, SimulatorDevice) @pytest.mark.parametrize( @@ -65,9 +65,9 @@ def test_device_creation(self): ], ) def test_device_creation(self, coord_idxs): - """Tests that ThreeDGridQubits can be passed as an argument""" + """Tests that ThreeDQubits can be passed as an argument""" - qubits = [ThreeDGridQubit(*idxs) for idxs in coord_idxs] + qubits = [ThreeDQubit(*idxs) for idxs in coord_idxs] dev = PasqalDevice(wires=4, qubits=qubits) assert dev.qubits == qubits From 3270b3af66a46e725ec0894b7dd62945e0a67ab2 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 14:27:44 -0400 Subject: [PATCH 03/29] change coords --- doc/xanadu_theme/static/jquery.min.map | 0 doc/xanadu_theme/static/js/bootstrap.min.js | 0 pennylane_cirq/pasqal_device.py | 4 +++- 3 files changed, 3 insertions(+), 1 deletion(-) mode change 100755 => 100644 doc/xanadu_theme/static/jquery.min.map mode change 100755 => 100644 doc/xanadu_theme/static/js/bootstrap.min.js diff --git a/doc/xanadu_theme/static/jquery.min.map b/doc/xanadu_theme/static/jquery.min.map old mode 100755 new mode 100644 diff --git a/doc/xanadu_theme/static/js/bootstrap.min.js b/doc/xanadu_theme/static/js/bootstrap.min.js old mode 100755 new mode 100644 diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index 63a78d7..fa58d8a 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -44,7 +44,9 @@ class PasqalDevice(SimulatorDevice): def __init__(self, wires, shots=1000, analytic=True, qubits=None, control_radius=1.0): if not qubits: - qubits = [pasqal.ThreeDQubit(wire, 0, 0) for wire in range(wires)] + # a linear chain in 3D with x coords uniform between 0 and 1 + max_pos = len(wires) + qubits = [pasqal.ThreeDQubit(wire / max_pos, 0, 0) for wire in range(wires)] self.control_radius = float(control_radius) if self.control_radius < 0: raise ValueError("The control_radius must be a non-negative real number.") From a083d432e3e4ab589cecec4fe983d01796fac425 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 14:30:42 -0400 Subject: [PATCH 04/29] fix --- pennylane_cirq/pasqal_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index fa58d8a..38f90ad 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -45,7 +45,7 @@ def __init__(self, wires, shots=1000, analytic=True, qubits=None, control_radius if not qubits: # a linear chain in 3D with x coords uniform between 0 and 1 - max_pos = len(wires) + max_pos = wires qubits = [pasqal.ThreeDQubit(wire / max_pos, 0, 0) for wire in range(wires)] self.control_radius = float(control_radius) if self.control_radius < 0: From bf27941012c39b52d25edee9b574f2757adddb6b Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 14:52:33 -0400 Subject: [PATCH 05/29] proper attaching of pasqal device --- pennylane_cirq/cirq_device.py | 6 +++++- pennylane_cirq/pasqal_device.py | 17 +++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index c8ebc03..346a246 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -72,6 +72,7 @@ def __init__(self, wires, shots, analytic, qubits=None): super().__init__(wires, shots, analytic) self.circuit = None + self.cirq_device = None device_wires = self.map_wires(self.wires) @@ -149,7 +150,10 @@ def reset(self): # pylint: disable=missing-function-docstring super().reset() - self.circuit = cirq.Circuit() + if self.cirq_device: + self.circuit = cirq.Circuit(self.cirq_device) + else: + self.circuit = cirq.Circuit() @property def observables(self): diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index 38f90ad..f4a7189 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -25,6 +25,8 @@ class PasqalDevice(SimulatorDevice): Args: wires (int): the number of wires to initialize the device with + control_radius (float): The maximum distance between qubits for a controlled + gate. Distance is measured in units of the ``ThreeDGridQubit`` indices. shots (int): Number of circuit evaluations/random samples used to estimate expectation values of observables. Shots need to be >= 1. In analytic mode, shots indicates the number of entries @@ -33,21 +35,20 @@ class PasqalDevice(SimulatorDevice): be calculated analytically qubits (List[cirq.ThreeDGridQubit]): A list of Cirq ThreeDGridQubits that are used as wires. If not specified, the ThreeDGridQubits are put in a linear - arrangement along the first coordinate axis, - i.e., ``(0,0,0), (1,0,0), (2,0,0)``, etc. - control_radius (float): The maximum distance between qubits for a controlled - gate. Distance is measured in units of the ``ThreeDGridQubit`` indices. + arrangement along the first coordinate axis, separated by a distance of + ``control_radius / 2``. + i.e., ``(0,0,0), (control_radius/2,0,0), (control_radius,0,0)``, etc. """ name = "Cirq Pasqal device for PennyLane" short_name = "cirq.pasqal" - def __init__(self, wires, shots=1000, analytic=True, qubits=None, control_radius=1.0): + def __init__(self, wires, control_radius, shots=1000, analytic=True, qubits=None): if not qubits: - # a linear chain in 3D with x coords uniform between 0 and 1 - max_pos = wires - qubits = [pasqal.ThreeDQubit(wire / max_pos, 0, 0) for wire in range(wires)] + qubits = [pasqal.ThreeDQubit(wire * control_radius / 2, 0, 0) + for wire in range(wires)] self.control_radius = float(control_radius) if self.control_radius < 0: raise ValueError("The control_radius must be a non-negative real number.") + self.cirq_device = pasqal.PasqalVirtualDevice(self.control_radius, qubits) super().__init__(wires, shots, analytic, qubits) From 06388714f675d95e2a48001eae993b58a494bdc0 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 19:17:43 -0400 Subject: [PATCH 06/29] debugging --- pennylane_cirq/cirq_device.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index 346a246..98969e2 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,6 +32,7 @@ ~~~~~~~~~~~~ """ import abc +from collections import OrderedDict import cirq import numpy as np import pennylane as qml @@ -69,24 +70,30 @@ class CirqDevice(QubitDevice, abc.ABC): short_name = "cirq.base_device" def __init__(self, wires, shots, analytic, qubits=None): - super().__init__(wires, shots, analytic) - - self.circuit = None - self.cirq_device = None - device_wires = self.map_wires(self.wires) + if type(wires) == int: + num_wires = wires + elif type(wires) == qml.Wires: + num_wires = len(wires) + else: + raise ValueError() if qubits: - if wires != len(qubits): + if num_wires != len(qubits): raise qml.DeviceError( "The number of given qubits and the specified number of wires have to match. Got {} wires and {} qubits.".format( wires, len(qubits) ) ) - - self.qubits = qubits else: - self.qubits = [cirq.LineQubit(wire) for wire in device_wires.labels] + qubits = [cirq.LineQubit(idx) for idx in range(num_wires)] + + self.qubits = sorted(qubits) + + super().__init__(wires, shots, analytic) + + self.circuit = None + self.cirq_device = None # Add inverse operations self._inverse_operation_map = {} From bc4385ff89b07a7f235b201e891e2b0109a19799 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 19:24:10 -0400 Subject: [PATCH 07/29] cleanup and explanation --- pennylane_cirq/cirq_device.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index 98969e2..ada2f66 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,7 +32,7 @@ ~~~~~~~~~~~~ """ import abc -from collections import OrderedDict +from collections import Iterable import cirq import numpy as np import pennylane as qml @@ -71,12 +71,10 @@ class CirqDevice(QubitDevice, abc.ABC): def __init__(self, wires, shots, analytic, qubits=None): - if type(wires) == int: - num_wires = wires - elif type(wires) == qml.Wires: - num_wires = len(wires) - else: - raise ValueError() + if not isinstance(wires, Iterable): + # interpret wires as the number of consecutive wires + wires = range(wires) + num_wires = len(wires) if qubits: if num_wires != len(qubits): @@ -88,6 +86,8 @@ def __init__(self, wires, shots, analytic, qubits=None): else: qubits = [cirq.LineQubit(idx) for idx in range(num_wires)] + # cirq orders the subsystems based on a total order defined on qubits. + # For consistency, this plugin uses that same total order self.qubits = sorted(qubits) super().__init__(wires, shots, analytic) From db54ef3bbd3e93f9e44ed321b8467d47bed53aa0 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 19:27:55 -0400 Subject: [PATCH 08/29] updates for failing tests --- tests/test_pasqal_device.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index aae18fe..29e9b18 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -27,7 +27,8 @@ class TestDeviceIntegration: def test_device_loading(self): """Tests that the cirq.pasqal device is properly loaded""" - dev = qml.device("cirq.pasqal", wires=2) + control_radius = 1.0 + dev = qml.device("cirq.pasqal", wires=2, control_radius=1.0) assert dev.num_wires == 2 assert len(dev.qubits) == 2 @@ -35,7 +36,7 @@ def test_device_loading(self): assert dev.short_name == "cirq.pasqal" assert dev.analytic == True assert dev.control_radius == 1.0 - assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(1, 0, 0)] + assert dev.qubits == sorted([ThreeDQubit(0, 0, 0), ThreeDQubit(control_radius / 2, 0, 0)]) assert isinstance(dev, SimulatorDevice) @@ -68,9 +69,9 @@ def test_device_creation(self, coord_idxs): """Tests that ThreeDQubits can be passed as an argument""" qubits = [ThreeDQubit(*idxs) for idxs in coord_idxs] - dev = PasqalDevice(wires=4, qubits=qubits) + dev = PasqalDevice(wires=4, qubits=qubits, control_radius=3) - assert dev.qubits == qubits + assert dev.qubits == sorted(qubits) def test_control_radius_negative_exception(self): """Tests that an exception is raised when the supplied control_radius parameter From 5e895f59fb4f8cc5c9bdfe50e13014897b4776cb Mon Sep 17 00:00:00 2001 From: co9olguy Date: Fri, 14 Aug 2020 19:29:23 -0400 Subject: [PATCH 09/29] updating requirements to master branch of cirq --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 260a9bf..ed41bed 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ pennylane>=0.9 google-api-core[grpc]<=1.14.0 -git+https://github.com/lhenriet/Cirq.git@pasqal_new +git+https://github.com/quantumlib/Cirq.git@master numpy~=1.16 From b6aae21e7f84e90d5d8935b614928ca3ff751322 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Sat, 15 Aug 2020 15:20:30 -0400 Subject: [PATCH 10/29] ordering test upgrades --- tests/test_cirq_device.py | 23 +++++++++++++++++------ tests/test_pasqal_device.py | 33 +++++++++++++++++++++++++++------ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/tests/test_cirq_device.py b/tests/test_cirq_device.py index 02fb3e6..6fbf724 100644 --- a/tests/test_cirq_device.py +++ b/tests/test_cirq_device.py @@ -51,8 +51,8 @@ def test_default_init_of_qubits(self): assert dev.qubits[1] == cirq.LineQubit(1) assert dev.qubits[2] == cirq.LineQubit(2) - def test_outer_init_of_qubits(self): - """Tests that giving qubits as parameters to CirqDevice works.""" + def test_outer_init_of_qubits_ordered(self): + """Tests that giving qubits as parameters to CirqDevice works when the qubits are already ordered consistently with Cirq's convention.""" qubits = [ cirq.GridQubit(0, 0), @@ -63,10 +63,21 @@ def test_outer_init_of_qubits(self): dev = CirqDevice(4, 100, False, qubits=qubits) assert len(dev.qubits) == 4 - assert dev.qubits[0] == cirq.GridQubit(0, 0) - assert dev.qubits[1] == cirq.GridQubit(0, 1) - assert dev.qubits[2] == cirq.GridQubit(1, 0) - assert dev.qubits[3] == cirq.GridQubit(1, 1) + assert dev.qubits == qubits + + def test_outer_init_of_qubits_unordered(self): + """Tests that giving qubits as parameters to CirqDevice works when the qubits are not ordered consistently with Cirq's convention.""" + + qubits = [ + cirq.GridQubit(0, 1), + cirq.GridQubit(1, 0), + cirq.GridQubit(0, 0), + cirq.GridQubit(1, 1), + ] + + dev = CirqDevice(4, 100, False, qubits=qubits) + assert len(dev.qubits) == 4 + assert dev.qubits == sorted(qubits) def test_outer_init_of_qubits_error(self): """Tests that giving the wrong number of qubits as parameters to CirqDevice raises an error.""" diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index 29e9b18..045db1b 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -43,20 +43,41 @@ def test_device_loading(self): class TestDevice: """Unit tests for the PasqalDevice""" - def test_device_creation(self): + @pytest.mark.parametrize( + "control_radius", [1.0, 2.0, 99.99] + ) + def test_device_creation(self, control_radius): """Tests that the cirq.pasqal device is properly created""" - dev = PasqalDevice(wires=2, shots=123, control_radius=5.0) + dev = PasqalDevice(wires=2, shots=123, control_radius=control_radius) assert dev.num_wires == 2 assert len(dev.qubits) == 2 assert dev.shots == 123 assert dev.short_name == "cirq.pasqal" assert dev.analytic == True - assert dev.control_radius == 5.0 - assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(1, 0, 0)] + assert dev.control_radius == control_radius + assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(control_radius / 2, 0, 0)] assert isinstance(dev, SimulatorDevice) + @pytest.mark.parametrize( + "coord_idxs", + [ + [(0, 0, 0), (1, 0, 0), (2, 0, 0), (3, 0, 0)], + [(0, 0, 0), (0, 0, 1), (0, 1, 1), (1, 1, 1)], + [(-1, -1, -1000), (1, 2, 3), (3, 2, 3), (3, 3, 3)], + ], + ) + def test_device_creation_threeDqubits_ordered(self, coord_idxs): + """Tests that a PasqalDevice can be properly instantiated with ThreeDQubits that are ordered following Cirq's convention.""" + + qubits = [ThreeDQubit(*idxs) for idxs in coord_idxs] + print(qubits) + print(sorted(qubits)) + dev = PasqalDevice(wires=4, qubits=qubits, control_radius=3) + + assert dev.qubits == qubits + @pytest.mark.parametrize( "coord_idxs", [ @@ -65,8 +86,8 @@ def test_device_creation(self): [(1, 2, 3), (3, 2, 1), (0, 0, 0), (-1, -1, -10)], ], ) - def test_device_creation(self, coord_idxs): - """Tests that ThreeDQubits can be passed as an argument""" + def test_device_creation_threeDqubits_unordered(self, coord_idxs): + """Tests that a PasqalDevice can be properly instantiated with ThreeDQubits that are not ordered following Cirq's convention.""" qubits = [ThreeDQubit(*idxs) for idxs in coord_idxs] dev = PasqalDevice(wires=4, qubits=qubits, control_radius=3) From 493322c69b3ff0f537000e50077047a47145dad8 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Sat, 15 Aug 2020 17:03:21 -0400 Subject: [PATCH 11/29] fixing more edge cases --- pennylane_cirq/cirq_device.py | 24 +++++++++++--- pennylane_cirq/pasqal_device.py | 2 +- tests/test_cirq_device.py | 57 +++++++++++++++++++++++++++++++++ tests/test_pasqal_device.py | 3 +- 4 files changed, 79 insertions(+), 7 deletions(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index ada2f66..953dd02 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,12 +32,13 @@ ~~~~~~~~~~~~ """ import abc -from collections import Iterable +from collections import Iterable, OrderedDict import cirq import numpy as np import pennylane as qml from pennylane import QubitDevice from pennylane.operation import Operation +from pennylane.wires import Wires from ._version import __version__ from .cirq_operation import CirqOperation @@ -52,9 +53,14 @@ class CirqDevice(QubitDevice, abc.ABC): or strings (``['ancilla', 'q1', 'q2']``). shots (int): Number of circuit evaluations/random samples used to estimate expectation values of observables. Shots need to be >= 1. - qubits (List[cirq.Qubit]): a list of Cirq qubits that are used - as wires. The wire number corresponds to the index in the list. - By default, an array of ``cirq.LineQubit`` instances is created. + qubits (List[cirq.Qubit]): A list of Cirq qubits that are used + as wires. By default, an array of ``cirq.LineQubit`` instances is created. + Wires are mapped to qubits using Cirq's internal mechanism for ordering + qubits. For example, if ``wires=2`` and ``qubits=[q1, q2]``, with + ``q1>q2``, then the wire indices 0 and 1 are mapped to q2 and q1, respectively. + If the user provides their own wire labels, e.g., ``wires=["alice", "bob"]``, and the + qubits are the same as the previous example, then "alice" would map to qubit q2 + and "bob" would map to qubit q1. """ name = "Cirq Abstract PennyLane plugin baseclass" @@ -88,6 +94,7 @@ def __init__(self, wires, shots, analytic, qubits=None): # cirq orders the subsystems based on a total order defined on qubits. # For consistency, this plugin uses that same total order + self._unsorted_qubits = qubits self.qubits = sorted(qubits) super().__init__(wires, shots, analytic) @@ -158,7 +165,7 @@ def reset(self): super().reset() if self.cirq_device: - self.circuit = cirq.Circuit(self.cirq_device) + self.circuit = cirq.Circuit(device=self.cirq_device) else: self.circuit = cirq.Circuit() @@ -237,3 +244,10 @@ def apply(self, operations, **kwargs): # Diagonalize the given observables for operation in rotations: self._apply_operation(operation) + + def define_wire_map(self, wires): + cirq_order = np.argsort(self._unsorted_qubits) + consecutive_wires = Wires(cirq_order) + + wire_map = zip(wires, consecutive_wires) + return OrderedDict(wire_map) diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index f4a7189..d740ba8 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -50,5 +50,5 @@ def __init__(self, wires, control_radius, shots=1000, analytic=True, qubits=None self.control_radius = float(control_radius) if self.control_radius < 0: raise ValueError("The control_radius must be a non-negative real number.") - self.cirq_device = pasqal.PasqalVirtualDevice(self.control_radius, qubits) super().__init__(wires, shots, analytic, qubits) + self.cirq_device = pasqal.PasqalVirtualDevice(self.control_radius, qubits) diff --git a/tests/test_cirq_device.py b/tests/test_cirq_device.py index 6fbf724..b830bb2 100644 --- a/tests/test_cirq_device.py +++ b/tests/test_cirq_device.py @@ -19,6 +19,7 @@ import cirq import pennylane as qml +from pennylane.wires import Wires import pytest import numpy as np @@ -96,6 +97,62 @@ def test_outer_init_of_qubits_error(self): dev = CirqDevice(3, 100, False, qubits=qubits) +class TestCirqDeviceIntegration: + """Integration tests for Cirq devices""" + + def test_outer_init_of_qubits_with_wire_number(self): + """Tests that giving qubits as parameters to CirqDevice works when the user provides a number of wires.""" + + unordered_qubits = [ + cirq.GridQubit(0, 1), + cirq.GridQubit(1, 0), + cirq.GridQubit(0, 0), + cirq.GridQubit(1, 1), + ] + + dev = qml.device("cirq.simulator", wires=4, qubits=unordered_qubits) + assert len(dev.qubits) == 4 + assert dev.qubits == sorted(unordered_qubits) + + def test_outer_init_of_qubits_with_wire_label_strings(self): + """Tests that giving qubits as parameters to CirqDevice works when the user also provides custom string wire labels.""" + + unordered_qubits = [ + cirq.GridQubit(0, 1), + cirq.GridQubit(1, 0), + cirq.GridQubit(0, 0), + cirq.GridQubit(1, 1), + ] + print(sorted(unordered_qubits)) + + user_labels = ["alice", "bob", "charlie", "david"] + sort_order = [2,0,1,3] + + dev = qml.device("cirq.simulator", wires=user_labels, qubits=unordered_qubits) + assert len(dev.qubits) == 4 + assert dev.qubits == sorted(unordered_qubits) + assert all(dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order)) + + def test_outer_init_of_qubits_with_wire_label_ints(self): + """Tests that giving qubits as parameters to CirqDevice works when the user also provides custom integer wire labels.""" + + unordered_qubits = [ + cirq.GridQubit(0, 1), + cirq.GridQubit(1, 0), + cirq.GridQubit(0, 0), + cirq.GridQubit(1, 1), + ] + print(sorted(unordered_qubits)) + + user_labels = [-1,1,66,0] + sort_order = [2,0,1,3] + + dev = qml.device("cirq.simulator", wires=user_labels, qubits=unordered_qubits) + assert len(dev.qubits) == 4 + assert dev.qubits == sorted(unordered_qubits) + assert all(dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order)) + + @pytest.fixture(scope="function") def cirq_device_1_wire(shots): """A mock instance of the abstract Device class""" diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index 045db1b..574f5a4 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -18,7 +18,7 @@ import pennylane as qml from pennylane_cirq import PasqalDevice, SimulatorDevice -from cirq.pasqal import ThreeDQubit +from cirq.pasqal import ThreeDQubit, PasqalVirtualDevice class TestDeviceIntegration: @@ -59,6 +59,7 @@ def test_device_creation(self, control_radius): assert dev.control_radius == control_radius assert dev.qubits == [ThreeDQubit(0, 0, 0), ThreeDQubit(control_radius / 2, 0, 0)] assert isinstance(dev, SimulatorDevice) + assert isinstance(dev.cirq_device, PasqalVirtualDevice) @pytest.mark.parametrize( "coord_idxs", From 3f91da118a59a73e0a1c40ebabe3df88d6983b5c Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Sat, 15 Aug 2020 17:05:17 -0400 Subject: [PATCH 12/29] Update pennylane_cirq/cirq_device.py --- pennylane_cirq/cirq_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index 953dd02..69b2907 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -63,7 +63,7 @@ class CirqDevice(QubitDevice, abc.ABC): and "bob" would map to qubit q1. """ - name = "Cirq Abstract PennyLane plugin baseclass" + name = "Cirq Abstract PennyLane plugin base class" pennylane_requires = ">=0.11.0" version = __version__ author = "Xanadu Inc" From 83d52f0fb40b00f01089c05d3334a0fb372473fc Mon Sep 17 00:00:00 2001 From: co9olguy Date: Sat, 15 Aug 2020 17:24:02 -0400 Subject: [PATCH 13/29] removing print --- tests/test_cirq_device.py | 2 -- tests/test_pasqal_device.py | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/test_cirq_device.py b/tests/test_cirq_device.py index b830bb2..2b21030 100644 --- a/tests/test_cirq_device.py +++ b/tests/test_cirq_device.py @@ -123,7 +123,6 @@ def test_outer_init_of_qubits_with_wire_label_strings(self): cirq.GridQubit(0, 0), cirq.GridQubit(1, 1), ] - print(sorted(unordered_qubits)) user_labels = ["alice", "bob", "charlie", "david"] sort_order = [2,0,1,3] @@ -142,7 +141,6 @@ def test_outer_init_of_qubits_with_wire_label_ints(self): cirq.GridQubit(0, 0), cirq.GridQubit(1, 1), ] - print(sorted(unordered_qubits)) user_labels = [-1,1,66,0] sort_order = [2,0,1,3] diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index 574f5a4..d2aa50a 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -73,8 +73,6 @@ def test_device_creation_threeDqubits_ordered(self, coord_idxs): """Tests that a PasqalDevice can be properly instantiated with ThreeDQubits that are ordered following Cirq's convention.""" qubits = [ThreeDQubit(*idxs) for idxs in coord_idxs] - print(qubits) - print(sorted(qubits)) dev = PasqalDevice(wires=4, qubits=qubits, control_radius=3) assert dev.qubits == qubits From e3703c0b171612b533b2543149571deb1f165210 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Sat, 15 Aug 2020 17:58:20 -0400 Subject: [PATCH 14/29] make identity gates local --- pennylane_cirq/simulator_device.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pennylane_cirq/simulator_device.py b/pennylane_cirq/simulator_device.py index ba617d8..9791659 100644 --- a/pennylane_cirq/simulator_device.py +++ b/pennylane_cirq/simulator_device.py @@ -132,9 +132,10 @@ def apply(self, operations, **kwargs): # pylint: disable=missing-function-docstring super().apply(operations, **kwargs) - # We apply an identity gate to all wires, otherwise Cirq would ignore + # We apply identity gates to all wires, otherwise Cirq would ignore # wires that are not acted upon - self.circuit.append(cirq.IdentityGate(len(self.qubits))(*self.qubits)) + for q in self.qubits: + self.circuit.append(cirq.IdentityGate(1)(q)) if self.analytic: self._result = self._simulator.simulate(self.circuit, initial_state=self._initial_state) From 779ae957f7eb8a5282dc190741744a1ff858b521 Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Thu, 8 Oct 2020 11:11:40 -0400 Subject: [PATCH 15/29] Update pennylane_cirq/cirq_device.py Co-authored-by: Josh Izaac --- pennylane_cirq/cirq_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index ebabc50..5b29842 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,7 +32,7 @@ ~~~~~~~~~~~~ """ import abc -from collections import Iterable, OrderedDict +from collections.abc import Iterable, OrderedDict import cirq import numpy as np import pennylane as qml From df0447f1a84bc097f4f923da39331c24a3dfd54a Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 11:16:02 -0400 Subject: [PATCH 16/29] imports --- pennylane_cirq/cirq_device.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index 5b29842..20acdc2 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,7 +32,8 @@ ~~~~~~~~~~~~ """ import abc -from collections.abc import Iterable, OrderedDict +from collections.abc import Iterable +from collections import OrderedDict import cirq import numpy as np import pennylane as qml From b3692dea7cf42a1185e73e6fa58caf6f2d51a65d Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 11:31:21 -0400 Subject: [PATCH 17/29] black --- pennylane_cirq/pasqal_device.py | 3 +-- tests/test_cirq_device.py | 14 +++++++++----- tests/test_pasqal_device.py | 4 +--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/pennylane_cirq/pasqal_device.py b/pennylane_cirq/pasqal_device.py index d740ba8..6e3f07f 100644 --- a/pennylane_cirq/pasqal_device.py +++ b/pennylane_cirq/pasqal_device.py @@ -45,8 +45,7 @@ class PasqalDevice(SimulatorDevice): def __init__(self, wires, control_radius, shots=1000, analytic=True, qubits=None): if not qubits: - qubits = [pasqal.ThreeDQubit(wire * control_radius / 2, 0, 0) - for wire in range(wires)] + qubits = [pasqal.ThreeDQubit(wire * control_radius / 2, 0, 0) for wire in range(wires)] self.control_radius = float(control_radius) if self.control_radius < 0: raise ValueError("The control_radius must be a non-negative real number.") diff --git a/tests/test_cirq_device.py b/tests/test_cirq_device.py index 2b21030..7233aec 100644 --- a/tests/test_cirq_device.py +++ b/tests/test_cirq_device.py @@ -125,12 +125,14 @@ def test_outer_init_of_qubits_with_wire_label_strings(self): ] user_labels = ["alice", "bob", "charlie", "david"] - sort_order = [2,0,1,3] + sort_order = [2, 0, 1, 3] dev = qml.device("cirq.simulator", wires=user_labels, qubits=unordered_qubits) assert len(dev.qubits) == 4 assert dev.qubits == sorted(unordered_qubits) - assert all(dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order)) + assert all( + dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order) + ) def test_outer_init_of_qubits_with_wire_label_ints(self): """Tests that giving qubits as parameters to CirqDevice works when the user also provides custom integer wire labels.""" @@ -142,13 +144,15 @@ def test_outer_init_of_qubits_with_wire_label_ints(self): cirq.GridQubit(1, 1), ] - user_labels = [-1,1,66,0] - sort_order = [2,0,1,3] + user_labels = [-1, 1, 66, 0] + sort_order = [2, 0, 1, 3] dev = qml.device("cirq.simulator", wires=user_labels, qubits=unordered_qubits) assert len(dev.qubits) == 4 assert dev.qubits == sorted(unordered_qubits) - assert all(dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order)) + assert all( + dev.map_wires(Wires(label)) == Wires(idx) for label, idx in zip(user_labels, sort_order) + ) @pytest.fixture(scope="function") diff --git a/tests/test_pasqal_device.py b/tests/test_pasqal_device.py index d2aa50a..bc47102 100644 --- a/tests/test_pasqal_device.py +++ b/tests/test_pasqal_device.py @@ -43,9 +43,7 @@ def test_device_loading(self): class TestDevice: """Unit tests for the PasqalDevice""" - @pytest.mark.parametrize( - "control_radius", [1.0, 2.0, 99.99] - ) + @pytest.mark.parametrize("control_radius", [1.0, 2.0, 99.99]) def test_device_creation(self, control_radius): """Tests that the cirq.pasqal device is properly created""" From 63d51993de3a370e299f492277ec241fca03ce44 Mon Sep 17 00:00:00 2001 From: Josh Izaac Date: Thu, 8 Oct 2020 23:50:55 +0800 Subject: [PATCH 18/29] Update format.yml --- .github/workflows/format.yml | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index 299bdde..01c8f21 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -5,9 +5,22 @@ on: jobs: black: runs-on: ubuntu-latest + steps: - - uses: actions/checkout@v1 - - name: Black Code Formatter - uses: lgeiger/black-action@v1.0.1 - with: - args: "-l 100 pennylane_cirq/ --check" + - name: Cancel Previous Runs + uses: styfle/cancel-workflow-action@0.4.1 + with: + access_token: ${{ github.token }} + + - name: Set up Python + uses: actions/setup-python@v2 + with: + python-version: 3.8 + + - name: Install dependencies + run: pip install black + + - uses: actions/checkout@v2 + + - name: Run Black + run: black -l 100 pennylane_cirq/ --check From f6b5f136d0c6e6c93167974ef28a5a90a9541928 Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Thu, 8 Oct 2020 11:58:30 -0400 Subject: [PATCH 19/29] Update pennylane_cirq/cirq_device.py Co-authored-by: Josh Izaac --- pennylane_cirq/cirq_device.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_cirq/cirq_device.py b/pennylane_cirq/cirq_device.py index 20acdc2..cb7fc8d 100644 --- a/pennylane_cirq/cirq_device.py +++ b/pennylane_cirq/cirq_device.py @@ -32,7 +32,7 @@ ~~~~~~~~~~~~ """ import abc -from collections.abc import Iterable +from collections.abc import Iterable # pylint: disable=no-name-in-module from collections import OrderedDict import cirq import numpy as np From 37a7afa1d7687921bfd1276cee363261a889b1cf Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 12:11:24 -0400 Subject: [PATCH 20/29] blacker --- pennylane_cirq/cirq_operation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pennylane_cirq/cirq_operation.py b/pennylane_cirq/cirq_operation.py index 9d17b52..6a7e50b 100644 --- a/pennylane_cirq/cirq_operation.py +++ b/pennylane_cirq/cirq_operation.py @@ -37,7 +37,7 @@ class CirqOperation: """A helper class that wraps the native Cirq operations and provides an - interface for parametrization and application.""" + interface for parametrization and application.""" def __init__(self, parametrization): """Initializes the CirqOperation From 104dada3ae090af05a3035cf1ca19a94c2e490b7 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 12:14:48 -0400 Subject: [PATCH 21/29] fixes --- doc/xanadu_theme/static/jquery.min.map | 0 doc/xanadu_theme/static/js/bootstrap.min.js | 0 setup.py | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 doc/xanadu_theme/static/jquery.min.map mode change 100644 => 100755 doc/xanadu_theme/static/js/bootstrap.min.js diff --git a/doc/xanadu_theme/static/jquery.min.map b/doc/xanadu_theme/static/jquery.min.map old mode 100644 new mode 100755 diff --git a/doc/xanadu_theme/static/js/bootstrap.min.js b/doc/xanadu_theme/static/js/bootstrap.min.js old mode 100644 new mode 100755 diff --git a/setup.py b/setup.py index 0d55e47..5051edc 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ # Requirements should be as minimal as possible. # Avoid pinning, and use minimum version numbers # only where required. -requirements = ["pennylane>=0.11", "cirq"] +requirements = ["pennylane>=0.11", "cirq>=0.9"] info = { "name": "PennyLane-Cirq", From 093b99f91863c7ef6de3a0cf551e18e4f7c88446 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 12:30:08 -0400 Subject: [PATCH 22/29] docs --- doc/devices/pasqal.rst | 33 +++++++++++++++++++++++++++++++++ doc/index.rst | 8 +++++++- 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 doc/devices/pasqal.rst diff --git a/doc/devices/pasqal.rst b/doc/devices/pasqal.rst new file mode 100644 index 0000000..31e3575 --- /dev/null +++ b/doc/devices/pasqal.rst @@ -0,0 +1,33 @@ +Pasqal Device +============= + +You can instantiate a simulator for Pasqal's neutral-atom devices in PennyLane as follows: + +.. code-block:: python + + import pennylane as qml + + dev = qml.device("cirq.pasqal", wires=2, control_radius=1.5) + +This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane. +The Pasqal device supports the unique features of Pasqal's quantum computing hardware provided via Cirq, namely +the ``ThreeDQubit`` and the notion of a ``control_radius``. + +.. code-block:: python + + from cirq.pasqal import ThreeDQubit + qubits = [ThreeDQubit(x, y, z) + for x in range(2) + for y in range(2) + for z in range(2)] + dev = qml.device("cirq.pasqal", control_radius = 2., qubits=qubits, wires=len(qubits)) + + @qml.qnode(dev) + def circuit(x): + qml.RX(x, wires=[0]) + qml.CNOT(wires=[0, 1]) + return qml.expval(qml.PauliZ(wires=1)) + + circuit(0.3) + +For more details about Pasqal devices, consult the `Cirq docs `_. diff --git a/doc/index.rst b/doc/index.rst index 0d40fec..c9cc208 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -31,7 +31,13 @@ Currently, PennyLane-Cirq provides two Cirq devices for PennyLane: :name: 'cirq.mixedsimulator' :description: Cirq's density matrix simulator backend. :link: devices/mixed_simulator.html - + + +.. devicegalleryitem:: + :name: 'cirq.pasqal' + :description: Simulator for Pasqal's neutral atom devices. + :link: devices/pasqal.html + .. raw:: html
From aad2488f7d8c1afd84c52967312d9b338e121f29 Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 12:34:39 -0400 Subject: [PATCH 23/29] more dox --- doc/devices/pasqal.rst | 4 +++- doc/index.rst | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/doc/devices/pasqal.rst b/doc/devices/pasqal.rst index 31e3575..d756399 100644 --- a/doc/devices/pasqal.rst +++ b/doc/devices/pasqal.rst @@ -9,8 +9,10 @@ You can instantiate a simulator for Pasqal's neutral-atom devices in PennyLane a dev = qml.device("cirq.pasqal", wires=2, control_radius=1.5) + This device can then be used just like other devices for the definition and evaluation of QNodes within PennyLane. -The Pasqal device supports the unique features of Pasqal's quantum computing hardware provided via Cirq, namely + +The Pasqal device supports unique features of Pasqal's quantum computing hardware provided via Cirq, namely the ``ThreeDQubit`` and the notion of a ``control_radius``. .. code-block:: python diff --git a/doc/index.rst b/doc/index.rst index c9cc208..7d5cb8c 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -32,7 +32,6 @@ Currently, PennyLane-Cirq provides two Cirq devices for PennyLane: :description: Cirq's density matrix simulator backend. :link: devices/mixed_simulator.html - .. devicegalleryitem:: :name: 'cirq.pasqal' :description: Simulator for Pasqal's neutral atom devices. @@ -71,6 +70,7 @@ and simply replace ``'default.qubit'`` with the ``'cirq.simulator'`` device: devices/simulator devices/mixed_simulator + devices/pasqal .. toctree:: :maxdepth: 1 From a1d543225d319b138320d6171dd64287f66fce8a Mon Sep 17 00:00:00 2001 From: co9olguy Date: Thu, 8 Oct 2020 12:37:53 -0400 Subject: [PATCH 24/29] the --- doc/devices/mixed_simulator.rst | 4 ++-- doc/devices/simulator.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/devices/mixed_simulator.rst b/doc/devices/mixed_simulator.rst index 55a3080..d62cab9 100644 --- a/doc/devices/mixed_simulator.rst +++ b/doc/devices/mixed_simulator.rst @@ -1,5 +1,5 @@ -The Mixed Simulator Device -========================== +Mixed Simulator Device +====================== You can instantiate the mixed-state simulator device in PennyLane as follows: diff --git a/doc/devices/simulator.rst b/doc/devices/simulator.rst index 09466d6..7ad6859 100644 --- a/doc/devices/simulator.rst +++ b/doc/devices/simulator.rst @@ -1,5 +1,5 @@ -The Simulator device -==================== +Simulator device +================ You can instantiate the device in PennyLane as follows: From 8a4547cd325285d0ee370478013dd353122ce9da Mon Sep 17 00:00:00 2001 From: Josh Izaac Date: Fri, 9 Oct 2020 00:49:15 +0800 Subject: [PATCH 25/29] Update tests.yml --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b3e87ad..0be2a45 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,7 +40,7 @@ jobs: run: python -m pytest tests --cov=pennylane_cirq --cov-report=term-missing --cov-report=xml -p no:warnings --tb=native - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1.0.7 + uses: codecov/codecov-action@v1 with: file: ./.coverage @@ -79,6 +79,6 @@ jobs: pl-device-test --device=cirq.mixedsimulator --tb=short --skip-ops --analytic=False --shots=20000 - name: Upload coverage to Codecov - uses: codecov/codecov-action@v1.0.7 + uses: codecov/codecov-action@v1 with: file: ./coverage.xml From 22fd5709f242167e4d85ac9898cb3c5a5569c331 Mon Sep 17 00:00:00 2001 From: Nathan Killoran Date: Thu, 8 Oct 2020 12:54:51 -0400 Subject: [PATCH 26/29] Update doc/devices/pasqal.rst Co-authored-by: Josh Izaac --- doc/devices/pasqal.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/devices/pasqal.rst b/doc/devices/pasqal.rst index d756399..4093956 100644 --- a/doc/devices/pasqal.rst +++ b/doc/devices/pasqal.rst @@ -32,4 +32,8 @@ the ``ThreeDQubit`` and the notion of a ``control_radius``. circuit(0.3) +Note that if not specified, ``ThreeDGridQubits`` are automatically arranged in a linear +arrangement along the first coordinate axis, separated by a distance of ``control_radius / 2``. +That is, ``(0, 0, 0), (control_radius/2, 0, 0), (control_radius, 0, 0)``. + For more details about Pasqal devices, consult the `Cirq docs `_. From 33c9a06aa3c8cfe5b5f081e1e0f12bae75030d50 Mon Sep 17 00:00:00 2001 From: Josh Izaac Date: Fri, 9 Oct 2020 00:56:36 +0800 Subject: [PATCH 27/29] Update tests.yml --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 0be2a45..075028b 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -42,7 +42,7 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: - file: ./.coverage + file: ./.coverage.xml integration-tests: runs-on: ubuntu-latest From d28563c9d48ff2735a6feb96a85b4d04f2920b80 Mon Sep 17 00:00:00 2001 From: Josh Izaac Date: Fri, 9 Oct 2020 01:00:52 +0800 Subject: [PATCH 28/29] Update tests.yml --- .github/workflows/tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 075028b..720a6b3 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -42,7 +42,7 @@ jobs: - name: Upload coverage to Codecov uses: codecov/codecov-action@v1 with: - file: ./.coverage.xml + file: ./coverage.xml integration-tests: runs-on: ubuntu-latest From c3973ff2512593d66b9568a7a535327b85f1f492 Mon Sep 17 00:00:00 2001 From: Josh Izaac Date: Fri, 9 Oct 2020 01:02:29 +0800 Subject: [PATCH 29/29] Update tests.yml --- .github/workflows/tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 720a6b3..cb2bb80 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -73,10 +73,10 @@ jobs: - name: Run tests run: | - pl-device-test --device=cirq.simulator --tb=short --skip-ops --analytic=True - pl-device-test --device=cirq.simulator --tb=short --skip-ops --analytic=False --shots=20000 - pl-device-test --device=cirq.mixedsimulator --tb=short --skip-ops --analytic=True - pl-device-test --device=cirq.mixedsimulator --tb=short --skip-ops --analytic=False --shots=20000 + pl-device-test --device=cirq.simulator --tb=short --skip-ops --analytic=True --cov=pennylane_cirq --cov-report=xml + pl-device-test --device=cirq.simulator --tb=short --skip-ops --analytic=False --shots=20000 --cov=pennylane_cirq --cov-report=xml + pl-device-test --device=cirq.mixedsimulator --tb=short --skip-ops --analytic=True --cov=pennylane_cirq --cov-report=xml + pl-device-test --device=cirq.mixedsimulator --tb=short --skip-ops --analytic=False --shots=20000 --cov=pennylane_cirq --cov-report=xml - name: Upload coverage to Codecov uses: codecov/codecov-action@v1