From 1d3e7ca686b47adf14ce906a1694f8943a619f78 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Sat, 26 Oct 2019 22:00:52 +1100 Subject: [PATCH 1/9] method to check third party packages; lazy-loading of qiskit --- qctrlopencontrols/exceptions/exceptions.py | 76 +++++++++++++++++++++ qctrlopencontrols/qiskit/__init__.py | 3 + qctrlopencontrols/qiskit/quantum_circuit.py | 27 ++++++-- qctrlopencontrols/utility/__init__.py | 13 ++++ qctrlopencontrols/utility/check_packages.py | 53 ++++++++++++++ tests/test_qiskit_sequence.py | 3 +- 6 files changed, 167 insertions(+), 8 deletions(-) create mode 100644 qctrlopencontrols/utility/__init__.py create mode 100644 qctrlopencontrols/utility/check_packages.py diff --git a/qctrlopencontrols/exceptions/exceptions.py b/qctrlopencontrols/exceptions/exceptions.py index c68c6d98..72d8493e 100644 --- a/qctrlopencontrols/exceptions/exceptions.py +++ b/qctrlopencontrols/exceptions/exceptions.py @@ -57,3 +57,79 @@ def __init__(self, description, arguments, extras=None): for key in self.extras: self.message += '\n' + str(key) + '=' + repr(self.extras[key]) super(ArgumentsValueError, self).__init__(self.message) + + +class PackageVersionMismatchError(QctrlError): + """Exception raised when the version of required third party packages found but is + below the minimum required. + + Parameters + ---------- + description : string + Description of the why the error is raised. + arguments : dict + Dictionary that contains the package name, required minimum version. + extras : dict, optional + Other variables, such as the version found in the system, + that may be relevant to the error. Defaults to None. + """ + + def __init__(self, description, arguments, extras=None): + self.description = description + self.arguments = arguments + self.extras = extras + self.message = self.description + + for key in self.arguments: + self.message += '\n' + str(key) + '=' + repr(self.arguments[key]) + if extras is not None: + for key in self.extras: + self.message += '\n' + str(key) + '=' + repr(self.extras[key]) + super(PackageVersionMismatchError, self).__init__(self.message) + + +class PackageNotFoundError(QctrlError): + """Exception raised when the required third party packages is not found. + + Parameters + ---------- + description : string + Description of the why the error is raised. + arguments : dict + Dictionary that contains the package name and the required minimum version. + extras : dict, optional + Other variables that may be relevant to the error. Defaults to None. + """ + + def __init__(self, description, arguments, extras=None): + self.description = description + self.arguments = arguments + self.extras = extras + self.message = self.description + + for key in self.arguments: + self.message += '\n' + str(key) + '=' + repr(self.arguments[key]) + if extras is not None: + for key in self.extras: + self.message += '\n' + str(key) + '=' + repr(self.extras[key]) + super(PackageNotFoundError, self).__init__(self.message) + + +class PackageImportError(QctrlError): + """Exception raised when a package cannot be imported. + + Parameters + ---------- + description : string + Description of the why the error is raised. + package_name : string, optional + The name of the package that could not be imported. Defaults to None. + """ + def __init__(self, description, package_name=None): + self.description = description + self.package_name = package_name + self.message = self.description + + if package_name: + self.message += '\n' + 'package' + '=' + repr(self.arguments[package_name]) + super(PackageImportError, self).__init__(self.message) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index a2b61496..46850731 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -11,3 +11,6 @@ # 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. + +# Minimum Qiskit version required +qiskit_minimum_version = '0.10.0' diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index ca348cab..27354af7 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -20,13 +20,11 @@ import numpy as np -from qiskit import ( - QuantumRegister, ClassicalRegister, QuantumCircuit) -from qiskit.qasm import pi - -from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence -from ..exceptions.exceptions import ArgumentsValueError from ..globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) +from ..qiskit import qiskit_minimum_version +from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence +from ..exceptions.exceptions import ArgumentsValueError, PackageImportError +from ..utility.check_packages import check_package def convert_dds_to_qiskit_quantum_circuit( @@ -75,6 +73,12 @@ def convert_dds_to_qiskit_quantum_circuit( ------ ArgumentsValueError If any of the input parameters are invalid + PackageNotFoundError + If Qiskit is not found + PackageVersionMismatchError + If the required minimum version of Qiskit is not found + PackageImportError + If Qiskit cannot be imported Notes ----- @@ -97,6 +101,17 @@ def convert_dds_to_qiskit_quantum_circuit( any offset. """ + check_package('qiskit-terra', qiskit_minimum_version) + + try: + from qiskit import ( + QuantumRegister, ClassicalRegister, QuantumCircuit) + from qiskit.qasm import pi + except ImportError: + raise PackageImportError( + 'Error while trying to import Qiskit.' + ) + if dynamic_decoupling_sequence is None: raise ArgumentsValueError('No dynamic decoupling sequence provided.', {'dynamic_decoupling_sequence': dynamic_decoupling_sequence}) diff --git a/qctrlopencontrols/utility/__init__.py b/qctrlopencontrols/utility/__init__.py new file mode 100644 index 00000000..a2b61496 --- /dev/null +++ b/qctrlopencontrols/utility/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL 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. diff --git a/qctrlopencontrols/utility/check_packages.py b/qctrlopencontrols/utility/check_packages.py new file mode 100644 index 00000000..09f91ce1 --- /dev/null +++ b/qctrlopencontrols/utility/check_packages.py @@ -0,0 +1,53 @@ +# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL 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. + +""" +Module with helper methods to check for third party packages. +""" + +import pkg_resources +from pkg_resources import DistributionNotFound +from packaging.version import parse + + +from qctrlopencontrols.exceptions.exceptions import ( + PackageVersionMismatchError, + PackageNotFoundError) + + +def check_package(package_name, minimum_package_version): + """Checks if the specified package and its minimum version + exists. + + Parameters + --------- + package_name: str + The name of the package + minimum_package_version: str + The minimum version of the package + """ + + try: + found_version = pkg_resources.get_distribution(package_name).version + if parse(found_version) < parse(minimum_package_version): + raise PackageVersionMismatchError( + 'Minimum version of the {} package not found.'.format(package_name), + {'package name': package_name, + 'minimum package version': minimum_package_version}, + extras={'version found': found_version}) + except DistributionNotFound: + raise PackageNotFoundError( + 'Package {} not found.'.format(package_name), + {'package name': package_name, + 'minimum package version': minimum_package_version}) diff --git a/tests/test_qiskit_sequence.py b/tests/test_qiskit_sequence.py index e58ca8f1..c11ecd0b 100644 --- a/tests/test_qiskit_sequence.py +++ b/tests/test_qiskit_sequence.py @@ -14,7 +14,7 @@ """ =================================== -Tests converstion to Qiskit Circuit +Tests conversion to Qiskit Circuit =================================== """ @@ -127,6 +127,5 @@ def test_identity_operation(): _check_circuit_unitary(True, _multiplier, 'fixed duration unitary') - if __name__ == '__main__': pass From 16f737db2b62e310802b1649a5885235fa6e7c52 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Sat, 26 Oct 2019 22:16:41 +1100 Subject: [PATCH 2/9] linted --- qctrlopencontrols/exceptions/exceptions.py | 2 +- qctrlopencontrols/qiskit/__init__.py | 8 +++++++- qctrlopencontrols/qiskit/quantum_circuit.py | 4 ++-- qctrlopencontrols/utility/check_packages.py | 7 +++++++ 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/qctrlopencontrols/exceptions/exceptions.py b/qctrlopencontrols/exceptions/exceptions.py index 72d8493e..dd075304 100644 --- a/qctrlopencontrols/exceptions/exceptions.py +++ b/qctrlopencontrols/exceptions/exceptions.py @@ -131,5 +131,5 @@ def __init__(self, description, package_name=None): self.message = self.description if package_name: - self.message += '\n' + 'package' + '=' + repr(self.arguments[package_name]) + self.message += '\n' + 'package' + '=' + repr(self.package_name) super(PackageImportError, self).__init__(self.message) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 46850731..3d295c90 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -12,5 +12,11 @@ # See the License for the specific language governing permissions and # limitations under the License. +""" +============== +qiskit module +============== +""" + # Minimum Qiskit version required -qiskit_minimum_version = '0.10.0' +QISKIT_MINIMUM_VERSION = '0.10.0' diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 27354af7..fbaa98b1 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -21,7 +21,7 @@ import numpy as np from ..globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -from ..qiskit import qiskit_minimum_version +from ..qiskit import QISKIT_MINIMUM_VERSION from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError, PackageImportError from ..utility.check_packages import check_package @@ -101,7 +101,7 @@ def convert_dds_to_qiskit_quantum_circuit( any offset. """ - check_package('qiskit-terra', qiskit_minimum_version) + check_package('qiskit-terra', QISKIT_MINIMUM_VERSION) try: from qiskit import ( diff --git a/qctrlopencontrols/utility/check_packages.py b/qctrlopencontrols/utility/check_packages.py index 09f91ce1..b28dfda6 100644 --- a/qctrlopencontrols/utility/check_packages.py +++ b/qctrlopencontrols/utility/check_packages.py @@ -36,6 +36,13 @@ def check_package(package_name, minimum_package_version): The name of the package minimum_package_version: str The minimum version of the package + + Raises + ------ + PackageNotFoundError + If the required package is not found. + PackageVersionMismatchError + If the version of the package is found but lower than the minimum required. """ try: From aa92b77972b49105770c2cd8e5cf1cb83cd47bbb Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Sat, 26 Oct 2019 22:24:23 +1100 Subject: [PATCH 3/9] check_package location moved to base --- .../{utility => base}/check_packages.py | 0 qctrlopencontrols/qiskit/quantum_circuit.py | 2 +- qctrlopencontrols/utility/__init__.py | 13 ------------- 3 files changed, 1 insertion(+), 14 deletions(-) rename qctrlopencontrols/{utility => base}/check_packages.py (100%) delete mode 100644 qctrlopencontrols/utility/__init__.py diff --git a/qctrlopencontrols/utility/check_packages.py b/qctrlopencontrols/base/check_packages.py similarity index 100% rename from qctrlopencontrols/utility/check_packages.py rename to qctrlopencontrols/base/check_packages.py diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index fbaa98b1..7ce9426a 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -24,7 +24,7 @@ from ..qiskit import QISKIT_MINIMUM_VERSION from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError, PackageImportError -from ..utility.check_packages import check_package +from ..base.check_packages import check_package def convert_dds_to_qiskit_quantum_circuit( diff --git a/qctrlopencontrols/utility/__init__.py b/qctrlopencontrols/utility/__init__.py deleted file mode 100644 index a2b61496..00000000 --- a/qctrlopencontrols/utility/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL 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. From 221312f60adbfad0ab9e77295212510ccfe3438f Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Sat, 26 Oct 2019 22:49:21 +1100 Subject: [PATCH 4/9] minor improvements --- qctrlopencontrols/qiskit/quantum_circuit.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 7ce9426a..1cd73e29 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -180,8 +180,8 @@ def convert_dds_to_qiskit_quantum_circuit( if offset_distance < 0: raise ArgumentsValueError( - "Offsets cannot be placed properly. Spacing between the rotations" - "is smaller than the time required to perform the rotation. Provide" + "Offsets cannot be placed properly. Spacing between the rotations " + "is smaller than the time required to perform the rotation. Provide " "a longer dynamic decoupling sequence or shorted gate time.", {'dynamic_decoupling_sequence': dynamic_decoupling_sequence, 'gate_time': gate_time}) @@ -192,14 +192,11 @@ def convert_dds_to_qiskit_quantum_circuit( quantum_circuit.barrier(quantum_registers[qubit]) # pylint: disable=no-member time_covered += gate_time - x_rotation = rabi_rotation * np.cos(azimuthal_angle) - y_rotation = rabi_rotation * np.sin(azimuthal_angle) - z_rotation = detuning_rotation - - rotations = np.array([x_rotation, y_rotation, z_rotation]) - zero_pulses = np.isclose(rotations, 0.0).astype(np.int) - nonzero_pulse_counts = 3 - np.sum(zero_pulses) - if nonzero_pulse_counts > 1: + rotations = np.array([rabi_rotation * np.cos(azimuthal_angle), + rabi_rotation * np.sin(azimuthal_angle), + detuning_rotation]) + zero_pulse_count = np.sum(np.isclose(rotations, 0.0).astype(np.int)) + if zero_pulse_count < 2: raise ArgumentsValueError( 'Open Controls support a sequence with one ' 'valid rotation at any offset. Found a sequence ' @@ -212,7 +209,7 @@ def convert_dds_to_qiskit_quantum_circuit( ) for qubit in target_qubits: - if nonzero_pulse_counts == 0: + if zero_pulse_count == 3: quantum_circuit.u3( 0., 0., 0., # pylint: disable=no-member quantum_registers[qubit]) From a92a08964d3e220146805853296c601a1c0542f9 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 28 Oct 2019 10:51:37 +1100 Subject: [PATCH 5/9] minor change in docstring --- qctrlopencontrols/base/check_packages.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/qctrlopencontrols/base/check_packages.py b/qctrlopencontrols/base/check_packages.py index b28dfda6..a719076b 100644 --- a/qctrlopencontrols/base/check_packages.py +++ b/qctrlopencontrols/base/check_packages.py @@ -27,8 +27,8 @@ def check_package(package_name, minimum_package_version): - """Checks if the specified package and its minimum version - exists. + """Checks if the specified third party package and its minimum version + is available. Parameters --------- From 289dfe5d5558fe41baaf39e4beb67eb27b5fa03f Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 28 Oct 2019 10:54:06 +1100 Subject: [PATCH 6/9] version constant made specific from qiskit to qiskit-terra --- qctrlopencontrols/qiskit/__init__.py | 2 +- qctrlopencontrols/qiskit/quantum_circuit.py | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 3d295c90..298cc281 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -19,4 +19,4 @@ """ # Minimum Qiskit version required -QISKIT_MINIMUM_VERSION = '0.10.0' +QISKIT_TERRA_MINIMUM_VERSION = '0.10.0' diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index 1cd73e29..d4f2a3f1 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -21,7 +21,7 @@ import numpy as np from ..globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -from ..qiskit import QISKIT_MINIMUM_VERSION +from ..qiskit import QISKIT_TERRA_MINIMUM_VERSION from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError, PackageImportError from ..base.check_packages import check_package @@ -101,7 +101,7 @@ def convert_dds_to_qiskit_quantum_circuit( any offset. """ - check_package('qiskit-terra', QISKIT_MINIMUM_VERSION) + check_package('qiskit-terra', QISKIT_TERRA_MINIMUM_VERSION) try: from qiskit import ( @@ -109,7 +109,7 @@ def convert_dds_to_qiskit_quantum_circuit( from qiskit.qasm import pi except ImportError: raise PackageImportError( - 'Error while trying to import Qiskit.' + 'Error while trying to import qiskit-terra.' ) if dynamic_decoupling_sequence is None: From 3dc4d35b1ee4f6d447a81588dc237bc375bcf122 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 28 Oct 2019 12:14:54 +1100 Subject: [PATCH 7/9] reduced the required minimum version of qiskit-terra --- qctrlopencontrols/qiskit/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index 298cc281..d981b217 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -19,4 +19,4 @@ """ # Minimum Qiskit version required -QISKIT_TERRA_MINIMUM_VERSION = '0.10.0' +QISKIT_TERRA_MINIMUM_VERSION = '0.8.2' From f329aebfe2337954428185544242461fe45c70aa Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 28 Oct 2019 12:24:34 +1100 Subject: [PATCH 8/9] reverted changes not related to lazy-loading --- qctrlopencontrols/qiskit/quantum_circuit.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index d4f2a3f1..fec757ab 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -180,8 +180,8 @@ def convert_dds_to_qiskit_quantum_circuit( if offset_distance < 0: raise ArgumentsValueError( - "Offsets cannot be placed properly. Spacing between the rotations " - "is smaller than the time required to perform the rotation. Provide " + "Offsets cannot be placed properly. Spacing between the rotations" + "is smaller than the time required to perform the rotation. Provide" "a longer dynamic decoupling sequence or shorted gate time.", {'dynamic_decoupling_sequence': dynamic_decoupling_sequence, 'gate_time': gate_time}) @@ -192,11 +192,14 @@ def convert_dds_to_qiskit_quantum_circuit( quantum_circuit.barrier(quantum_registers[qubit]) # pylint: disable=no-member time_covered += gate_time - rotations = np.array([rabi_rotation * np.cos(azimuthal_angle), - rabi_rotation * np.sin(azimuthal_angle), - detuning_rotation]) - zero_pulse_count = np.sum(np.isclose(rotations, 0.0).astype(np.int)) - if zero_pulse_count < 2: + x_rotation = rabi_rotation * np.cos(azimuthal_angle) + y_rotation = rabi_rotation * np.sin(azimuthal_angle) + z_rotation = detuning_rotation + + rotations = np.array([x_rotation, y_rotation, z_rotation]) + zero_pulses = np.isclose(rotations, 0.0).astype(np.int) + nonzero_pulse_counts = 3 - np.sum(zero_pulses) + if nonzero_pulse_counts > 1: raise ArgumentsValueError( 'Open Controls support a sequence with one ' 'valid rotation at any offset. Found a sequence ' @@ -209,7 +212,7 @@ def convert_dds_to_qiskit_quantum_circuit( ) for qubit in target_qubits: - if zero_pulse_count == 3: + if nonzero_pulse_counts == 0: quantum_circuit.u3( 0., 0., 0., # pylint: disable=no-member quantum_registers[qubit]) From 3c9a7ae705520d136d61567abe89ec8197f7cc82 Mon Sep 17 00:00:00 2001 From: Rajib Chakravorty Date: Mon, 28 Oct 2019 21:02:48 +1100 Subject: [PATCH 9/9] removed unnecessary exception definitions and check_package method; simply moved the imports of the libraries inside the relevant methods --- qctrlopencontrols/base/check_packages.py | 60 ---------------- qctrlopencontrols/cirq/circuit.py | 6 +- qctrlopencontrols/cirq/schedule.py | 10 +-- qctrlopencontrols/exceptions/exceptions.py | 76 --------------------- qctrlopencontrols/pyquil/program.py | 10 +-- qctrlopencontrols/qiskit/__init__.py | 9 --- qctrlopencontrols/qiskit/quantum_circuit.py | 23 ++----- 7 files changed, 17 insertions(+), 177 deletions(-) delete mode 100644 qctrlopencontrols/base/check_packages.py diff --git a/qctrlopencontrols/base/check_packages.py b/qctrlopencontrols/base/check_packages.py deleted file mode 100644 index a719076b..00000000 --- a/qctrlopencontrols/base/check_packages.py +++ /dev/null @@ -1,60 +0,0 @@ -# Copyright 2019 Q-CTRL Pty Ltd & Q-CTRL 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. - -""" -Module with helper methods to check for third party packages. -""" - -import pkg_resources -from pkg_resources import DistributionNotFound -from packaging.version import parse - - -from qctrlopencontrols.exceptions.exceptions import ( - PackageVersionMismatchError, - PackageNotFoundError) - - -def check_package(package_name, minimum_package_version): - """Checks if the specified third party package and its minimum version - is available. - - Parameters - --------- - package_name: str - The name of the package - minimum_package_version: str - The minimum version of the package - - Raises - ------ - PackageNotFoundError - If the required package is not found. - PackageVersionMismatchError - If the version of the package is found but lower than the minimum required. - """ - - try: - found_version = pkg_resources.get_distribution(package_name).version - if parse(found_version) < parse(minimum_package_version): - raise PackageVersionMismatchError( - 'Minimum version of the {} package not found.'.format(package_name), - {'package name': package_name, - 'minimum package version': minimum_package_version}, - extras={'version found': found_version}) - except DistributionNotFound: - raise PackageNotFoundError( - 'Package {} not found.'.format(package_name), - {'package name': package_name, - 'minimum package version': minimum_package_version}) diff --git a/qctrlopencontrols/cirq/circuit.py b/qctrlopencontrols/cirq/circuit.py index 8595946e..215b8451 100644 --- a/qctrlopencontrols/cirq/circuit.py +++ b/qctrlopencontrols/cirq/circuit.py @@ -20,14 +20,12 @@ import numpy as np -import cirq - from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError from ..globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -def convert_dds_to_cirq_circuit( +def convert_dds_to_cirq_circuit( #pylint: disable=too-many-locals dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, @@ -93,6 +91,8 @@ def convert_dds_to_cirq_circuit( any offset. """ + import cirq + if dynamic_decoupling_sequence is None: raise ArgumentsValueError('No dynamic decoupling sequence provided.', {'dynamic_decoupling_sequence': dynamic_decoupling_sequence}) diff --git a/qctrlopencontrols/cirq/schedule.py b/qctrlopencontrols/cirq/schedule.py index 88df4c10..689dd6e8 100644 --- a/qctrlopencontrols/cirq/schedule.py +++ b/qctrlopencontrols/cirq/schedule.py @@ -20,13 +20,11 @@ import numpy as np -import cirq - from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError -def convert_dds_to_cirq_schedule( +def convert_dds_to_cirq_schedule( #pylint: disable=too-many-locals dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, @@ -87,6 +85,8 @@ def convert_dds_to_cirq_schedule( any offset. """ + import cirq + if dynamic_decoupling_sequence is None: raise ArgumentsValueError('No dynamic decoupling sequence provided.', {'dynamic_decoupling_sequence': dynamic_decoupling_sequence}) @@ -146,8 +146,8 @@ def convert_dds_to_cirq_schedule( nonzero_pulse_counts = 3 - np.sum(zero_pulses) if nonzero_pulse_counts > 1: raise ArgumentsValueError( - 'Open Controls support a sequence with one ' - 'valid pulse at any offset. Found sequence ' + 'Open Controls support a sequence with one' + 'valid pulse at any offset. Found sequence' 'with multiple rotation operations at an offset.', {'dynamic_decoupling_sequence': str(dynamic_decoupling_sequence), 'offset': dynamic_decoupling_sequence.offsets[op_idx], diff --git a/qctrlopencontrols/exceptions/exceptions.py b/qctrlopencontrols/exceptions/exceptions.py index dd075304..c68c6d98 100644 --- a/qctrlopencontrols/exceptions/exceptions.py +++ b/qctrlopencontrols/exceptions/exceptions.py @@ -57,79 +57,3 @@ def __init__(self, description, arguments, extras=None): for key in self.extras: self.message += '\n' + str(key) + '=' + repr(self.extras[key]) super(ArgumentsValueError, self).__init__(self.message) - - -class PackageVersionMismatchError(QctrlError): - """Exception raised when the version of required third party packages found but is - below the minimum required. - - Parameters - ---------- - description : string - Description of the why the error is raised. - arguments : dict - Dictionary that contains the package name, required minimum version. - extras : dict, optional - Other variables, such as the version found in the system, - that may be relevant to the error. Defaults to None. - """ - - def __init__(self, description, arguments, extras=None): - self.description = description - self.arguments = arguments - self.extras = extras - self.message = self.description - - for key in self.arguments: - self.message += '\n' + str(key) + '=' + repr(self.arguments[key]) - if extras is not None: - for key in self.extras: - self.message += '\n' + str(key) + '=' + repr(self.extras[key]) - super(PackageVersionMismatchError, self).__init__(self.message) - - -class PackageNotFoundError(QctrlError): - """Exception raised when the required third party packages is not found. - - Parameters - ---------- - description : string - Description of the why the error is raised. - arguments : dict - Dictionary that contains the package name and the required minimum version. - extras : dict, optional - Other variables that may be relevant to the error. Defaults to None. - """ - - def __init__(self, description, arguments, extras=None): - self.description = description - self.arguments = arguments - self.extras = extras - self.message = self.description - - for key in self.arguments: - self.message += '\n' + str(key) + '=' + repr(self.arguments[key]) - if extras is not None: - for key in self.extras: - self.message += '\n' + str(key) + '=' + repr(self.extras[key]) - super(PackageNotFoundError, self).__init__(self.message) - - -class PackageImportError(QctrlError): - """Exception raised when a package cannot be imported. - - Parameters - ---------- - description : string - Description of the why the error is raised. - package_name : string, optional - The name of the package that could not be imported. Defaults to None. - """ - def __init__(self, description, package_name=None): - self.description = description - self.package_name = package_name - self.message = self.description - - if package_name: - self.message += '\n' + 'package' + '=' + repr(self.package_name) - super(PackageImportError, self).__init__(self.message) diff --git a/qctrlopencontrols/pyquil/program.py b/qctrlopencontrols/pyquil/program.py index 52e18a29..ee611a02 100644 --- a/qctrlopencontrols/pyquil/program.py +++ b/qctrlopencontrols/pyquil/program.py @@ -20,17 +20,13 @@ import numpy as np -from pyquil import Program -from pyquil.gates import I, RX, RY, RZ, MEASURE -from pyquil.quil import Pragma - from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence from ..exceptions.exceptions import ArgumentsValueError from ..globals import ( FIX_DURATION_UNITARY, INSTANT_UNITARY) -def convert_dds_to_pyquil_program( +def convert_dds_to_pyquil_program( #pylint: disable=too-many-locals dynamic_decoupling_sequence, target_qubits=None, gate_time=0.1, @@ -93,6 +89,10 @@ def convert_dds_to_pyquil_program( any offset. """ + from pyquil import Program + from pyquil.gates import I, RX, RY, RZ, MEASURE + from pyquil.quil import Pragma + if dynamic_decoupling_sequence is None: raise ArgumentsValueError('No dynamic decoupling sequence provided.', {'dynamic_decoupling_sequence': dynamic_decoupling_sequence}) diff --git a/qctrlopencontrols/qiskit/__init__.py b/qctrlopencontrols/qiskit/__init__.py index d981b217..a2b61496 100644 --- a/qctrlopencontrols/qiskit/__init__.py +++ b/qctrlopencontrols/qiskit/__init__.py @@ -11,12 +11,3 @@ # 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. - -""" -============== -qiskit module -============== -""" - -# Minimum Qiskit version required -QISKIT_TERRA_MINIMUM_VERSION = '0.8.2' diff --git a/qctrlopencontrols/qiskit/quantum_circuit.py b/qctrlopencontrols/qiskit/quantum_circuit.py index d4f2a3f1..5cd7e88d 100644 --- a/qctrlopencontrols/qiskit/quantum_circuit.py +++ b/qctrlopencontrols/qiskit/quantum_circuit.py @@ -21,10 +21,8 @@ import numpy as np from ..globals import (FIX_DURATION_UNITARY, INSTANT_UNITARY) -from ..qiskit import QISKIT_TERRA_MINIMUM_VERSION from ..dynamic_decoupling_sequences.dynamic_decoupling_sequence import DynamicDecouplingSequence -from ..exceptions.exceptions import ArgumentsValueError, PackageImportError -from ..base.check_packages import check_package +from ..exceptions.exceptions import ArgumentsValueError def convert_dds_to_qiskit_quantum_circuit( @@ -73,12 +71,6 @@ def convert_dds_to_qiskit_quantum_circuit( ------ ArgumentsValueError If any of the input parameters are invalid - PackageNotFoundError - If Qiskit is not found - PackageVersionMismatchError - If the required minimum version of Qiskit is not found - PackageImportError - If Qiskit cannot be imported Notes ----- @@ -101,16 +93,9 @@ def convert_dds_to_qiskit_quantum_circuit( any offset. """ - check_package('qiskit-terra', QISKIT_TERRA_MINIMUM_VERSION) - - try: - from qiskit import ( - QuantumRegister, ClassicalRegister, QuantumCircuit) - from qiskit.qasm import pi - except ImportError: - raise PackageImportError( - 'Error while trying to import qiskit-terra.' - ) + from qiskit import ( + QuantumRegister, ClassicalRegister, QuantumCircuit) + from qiskit.qasm import pi if dynamic_decoupling_sequence is None: raise ArgumentsValueError('No dynamic decoupling sequence provided.',