From fb01b4d52d3a3288fac88bad397135c3963cc8d1 Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Tue, 8 Jun 2021 09:59:09 -0500 Subject: [PATCH 1/7] input type --- src/qutip_qip/circuit.py | 2 +- src/qutip_qip/decompositions/__init__.py | 33 ++++++ .../decompositions/decompositions.py | 106 ++++++++++++++++++ tests/qasm_files/test_decompositions.py | 32 ++++++ 4 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 src/qutip_qip/decompositions/__init__.py create mode 100644 src/qutip_qip/decompositions/decompositions.py create mode 100644 tests/qasm_files/test_decompositions.py diff --git a/src/qutip_qip/circuit.py b/src/qutip_qip/circuit.py index f2d9415ab..08d425231 100644 --- a/src/qutip_qip/circuit.py +++ b/src/qutip_qip/circuit.py @@ -262,7 +262,7 @@ def add_measurement(self, measurement, targets=None, index=None, Parameters ---------- name: string - Measurement name. If name is an instance of `Measuremnent`, + Measurement name. If name is an instance of `Measurement`, parameters are unpacked and added. targets: list Gate targets diff --git a/src/qutip_qip/decompositions/__init__.py b/src/qutip_qip/decompositions/__init__.py new file mode 100644 index 000000000..22152d5cd --- /dev/null +++ b/src/qutip_qip/decompositions/__init__.py @@ -0,0 +1,33 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### +from .decompositions import * diff --git a/src/qutip_qip/decompositions/decompositions.py b/src/qutip_qip/decompositions/decompositions.py new file mode 100644 index 000000000..865fdb55b --- /dev/null +++ b/src/qutip_qip/decompositions/decompositions.py @@ -0,0 +1,106 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### +import numbers +from collections.abc import Iterable +from itertools import product, chain +from functools import partial, reduce +from operator import mul + +import warnings +import inspect +from copy import deepcopy + +import numpy as np +import scipy.sparse as sp + +from qutip import (Qobj, identity, qeye, sigmax, sigmay, sigmaz) + +# Converts a Qobj or Gate Object to an array +def convert_obj_to_array(input_object): + if input_object is None: + raise ValueError("A Qobj or Gate instance must be provided.") + if isinstance(input_object,Qobj) is True: + input_object = input_object.full() + elif isinstance(input_object,Gate) is True: + input_object = input_object # this function needs to be defined + else: + raise TypeError("Accepted input type is either a Qobj or a Gate instance.") + +# Convert an array to Qobj or Gate instance +def convert_array_to_obj(input_array, object_type): + if input_array is None: + raise ValueError("An array must be provided for conversion.") + if object_type is None: + raise ValueError("A Qobj or Gate instance must be provided.") + if object_type == 'Qobj': + input_array = Qobj(input_array) + elif object_type == 'Gate': + input_array = Gate(input_array) # this function needs to be defined + else: + raise TypeError("Specified object type is not a Qobj or Gate instance.") + + + + +class Decomposition: + """Representation of some decomposition function. + """ + + def __init__(self, scheme_name, input_array): + """ + Create a decomposition with specified parameters. + """ + + self.scheme_name = scheme_name + self.input_array = input_array + + # list of decomposition schemes - names to be changed as methods are added + decomposition_schemes = ['scheme1','scheme2'] + + # Check is a valid input decomposition scheme is provided + if scheme_name is None: + raise NameError("Decomposition scheme name must be provided.") + elif scheme_name not in decomposition_schemes: + raise AttributeError("Not a valid decomposition scheme. You could define your own decomposition function via user_defined_decomposition. ") + + # Check if input gate's matrix is of a valid type. If not then converter + # function tries to convert Qobj / Gate Object to an array + if isinstance(input_array, np.array) is False: + try: + convert_obj_to_array(input_array) + else: + raise AssertionError("Input gate should be input as an array, Qobj"+ + " or Gate instance.") + input_array = convert_obj_to_array(input_array) + + return scheme_name(input_array) diff --git a/tests/qasm_files/test_decompositions.py b/tests/qasm_files/test_decompositions.py new file mode 100644 index 000000000..b75172757 --- /dev/null +++ b/tests/qasm_files/test_decompositions.py @@ -0,0 +1,32 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### From 49a3fbfde4cfe9d89762af41a7cee5cff7f9005d Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Wed, 9 Jun 2021 10:14:28 -0500 Subject: [PATCH 2/7] add files and folders --- .../decompositions/decompositions.py | 106 ------------------ .../decompositions/general_decompositions.py | 2 +- .../single_qubit_decompositions.py | 32 ++++++ tests/test_general_decompositions.py | 32 ++++++ tests/test_single_qubit_decompositions.py | 32 ++++++ 5 files changed, 97 insertions(+), 107 deletions(-) delete mode 100644 src/qutip_qip/decompositions/decompositions.py rename tests/qasm_files/test_decompositions.py => src/qutip_qip/decompositions/general_decompositions.py (95%) create mode 100644 src/qutip_qip/decompositions/single_qubit_decompositions.py create mode 100644 tests/test_general_decompositions.py create mode 100644 tests/test_single_qubit_decompositions.py diff --git a/src/qutip_qip/decompositions/decompositions.py b/src/qutip_qip/decompositions/decompositions.py deleted file mode 100644 index 865fdb55b..000000000 --- a/src/qutip_qip/decompositions/decompositions.py +++ /dev/null @@ -1,106 +0,0 @@ -# This file is part of QuTiP: Quantum Toolbox in Python. -# -# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# 1. Redistributions of source code must retain the above copyright notice, -# this list of conditions and the following disclaimer. -# -# 2. Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names -# of its contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A -# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -############################################################################### -import numbers -from collections.abc import Iterable -from itertools import product, chain -from functools import partial, reduce -from operator import mul - -import warnings -import inspect -from copy import deepcopy - -import numpy as np -import scipy.sparse as sp - -from qutip import (Qobj, identity, qeye, sigmax, sigmay, sigmaz) - -# Converts a Qobj or Gate Object to an array -def convert_obj_to_array(input_object): - if input_object is None: - raise ValueError("A Qobj or Gate instance must be provided.") - if isinstance(input_object,Qobj) is True: - input_object = input_object.full() - elif isinstance(input_object,Gate) is True: - input_object = input_object # this function needs to be defined - else: - raise TypeError("Accepted input type is either a Qobj or a Gate instance.") - -# Convert an array to Qobj or Gate instance -def convert_array_to_obj(input_array, object_type): - if input_array is None: - raise ValueError("An array must be provided for conversion.") - if object_type is None: - raise ValueError("A Qobj or Gate instance must be provided.") - if object_type == 'Qobj': - input_array = Qobj(input_array) - elif object_type == 'Gate': - input_array = Gate(input_array) # this function needs to be defined - else: - raise TypeError("Specified object type is not a Qobj or Gate instance.") - - - - -class Decomposition: - """Representation of some decomposition function. - """ - - def __init__(self, scheme_name, input_array): - """ - Create a decomposition with specified parameters. - """ - - self.scheme_name = scheme_name - self.input_array = input_array - - # list of decomposition schemes - names to be changed as methods are added - decomposition_schemes = ['scheme1','scheme2'] - - # Check is a valid input decomposition scheme is provided - if scheme_name is None: - raise NameError("Decomposition scheme name must be provided.") - elif scheme_name not in decomposition_schemes: - raise AttributeError("Not a valid decomposition scheme. You could define your own decomposition function via user_defined_decomposition. ") - - # Check if input gate's matrix is of a valid type. If not then converter - # function tries to convert Qobj / Gate Object to an array - if isinstance(input_array, np.array) is False: - try: - convert_obj_to_array(input_array) - else: - raise AssertionError("Input gate should be input as an array, Qobj"+ - " or Gate instance.") - input_array = convert_obj_to_array(input_array) - - return scheme_name(input_array) diff --git a/tests/qasm_files/test_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py similarity index 95% rename from tests/qasm_files/test_decompositions.py rename to src/qutip_qip/decompositions/general_decompositions.py index b75172757..1debd8ee7 100644 --- a/tests/qasm_files/test_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -3,7 +3,7 @@ # Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. # All rights reserved. # -# Redistribution and use in source and binary forms, with or without +# Redistribution and use in sourc e and binary forms, with or without # modification, are permitted provided that the following conditions are # met: # diff --git a/src/qutip_qip/decompositions/single_qubit_decompositions.py b/src/qutip_qip/decompositions/single_qubit_decompositions.py new file mode 100644 index 000000000..1debd8ee7 --- /dev/null +++ b/src/qutip_qip/decompositions/single_qubit_decompositions.py @@ -0,0 +1,32 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in sourc e and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### diff --git a/tests/test_general_decompositions.py b/tests/test_general_decompositions.py new file mode 100644 index 000000000..1debd8ee7 --- /dev/null +++ b/tests/test_general_decompositions.py @@ -0,0 +1,32 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in sourc e and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### diff --git a/tests/test_single_qubit_decompositions.py b/tests/test_single_qubit_decompositions.py new file mode 100644 index 000000000..1debd8ee7 --- /dev/null +++ b/tests/test_single_qubit_decompositions.py @@ -0,0 +1,32 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in sourc e and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### From d48e75d373e7ee835137c61f2fb6a1855f10d198 Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Fri, 11 Jun 2021 13:35:46 -0500 Subject: [PATCH 3/7] normalize matrix --- src/qutip_qip/decompositions/__init__.py | 2 +- .../decompositions/general_decompositions.py | 29 +++++++++++++++++++ tests/test_general_decompositions.py | 24 +++++++++++++++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/src/qutip_qip/decompositions/__init__.py b/src/qutip_qip/decompositions/__init__.py index 22152d5cd..9f551f7ee 100644 --- a/src/qutip_qip/decompositions/__init__.py +++ b/src/qutip_qip/decompositions/__init__.py @@ -30,4 +30,4 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### -from .decompositions import * +from qutip_qip.decompositions.general_decompositions import normalize_matrix diff --git a/src/qutip_qip/decompositions/general_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py index 1debd8ee7..5f3e8c4b6 100644 --- a/src/qutip_qip/decompositions/general_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -30,3 +30,32 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### + +import numpy as np + +def normalize_matrix(input_array)-> np.array: + """ Checks if the input gate's array is normalized or not. If not, makes + sure the input has been normalized. + + Args: + input_array : Matrix of a gate in array form. + """ + if not isinstance(input_array, np.ndarray): + raise TypeError("Not a valid input : A Numpy input array must be provided.") + + + if isinstance(input_array, np.ndarray): + if input_array.size==0: + raise ValueError("An empty array was provided as input.") + + if input_array.shape[0] != input_array.shape[1]: + raise ValueError("Input is not a valid matrix gate. Provided array" + + " does not have the same number of rows and columns.") + + if np.linalg.det(input_array) != 1: + norm_factor = float(1/np.linalg.det(input_array))**0.5 + input_array = np.around(norm_factor*input_array,5) + else: + input_array = input_array + + return(input_array) diff --git a/tests/test_general_decompositions.py b/tests/test_general_decompositions.py index 1debd8ee7..329bca623 100644 --- a/tests/test_general_decompositions.py +++ b/tests/test_general_decompositions.py @@ -30,3 +30,27 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### +import numpy as np +import pytest +from qutip_qip.decompositions.general_decompositions import normalize_matrix +from qutip import Qobj + +def test_normalize_matrix_valid_input(): + """ Test output when a valid input is provided. + """ + M = np.array([[1, 2], [3, 4]]) + normalized_M = normalize_matrix(M) + calculated_M = np.array([[0.+0.70711j, 0.+1.41421j],[0.+2.12132j, 0.+2.82843j]]) + assert np.array_equal(calculated_M, normalized_M) + +@pytest.mark.parametrize("invalid_input", (Qobj([[1],[2],[3],[4],[5]]),(1,2))) +def test_normalize_matrix_invalid_input(invalid_input): + """ Test error when Qobj array is provided as input. + """ + with pytest.raises(TypeError, match="Not a valid input : A Numpy input array must be provided."): + normalize_matrix(invalid_input) + +def test_normalize_matrix_empty_array(): + """When an empty array is provided as input.""" + with pytest.raises(ValueError, match="An empty array was provided as input."): + normalize_matrix(np.array([])) From e4aa0f25328c83094d9c2b0addf3e1a89439827b Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Fri, 11 Jun 2021 15:00:01 -0500 Subject: [PATCH 4/7] update tests --- .../decompositions/general_decompositions.py | 7 ++++--- tests/test_general_decompositions.py | 12 ++++++++++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/qutip_qip/decompositions/general_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py index 5f3e8c4b6..ad3502e4f 100644 --- a/src/qutip_qip/decompositions/general_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -48,9 +48,10 @@ def normalize_matrix(input_array)-> np.array: if input_array.size==0: raise ValueError("An empty array was provided as input.") - if input_array.shape[0] != input_array.shape[1]: - raise ValueError("Input is not a valid matrix gate. Provided array" + - " does not have the same number of rows and columns.") + input_matrix_rows = input_array.shape[0] + input_matrix_columns = input_array.shape[1] + if input_matrix_rows !=input_matrix_columns: + raise ValueError("Input must be a square matrix to be a valid gate.") if np.linalg.det(input_array) != 1: norm_factor = float(1/np.linalg.det(input_array))**0.5 diff --git a/tests/test_general_decompositions.py b/tests/test_general_decompositions.py index 329bca623..582c917d9 100644 --- a/tests/test_general_decompositions.py +++ b/tests/test_general_decompositions.py @@ -38,8 +38,7 @@ def test_normalize_matrix_valid_input(): """ Test output when a valid input is provided. """ - M = np.array([[1, 2], [3, 4]]) - normalized_M = normalize_matrix(M) + normalized_M = normalize_matrix(np.array([[1, 2], [3, 4]])) calculated_M = np.array([[0.+0.70711j, 0.+1.41421j],[0.+2.12132j, 0.+2.82843j]]) assert np.array_equal(calculated_M, normalized_M) @@ -54,3 +53,12 @@ def test_normalize_matrix_empty_array(): """When an empty array is provided as input.""" with pytest.raises(ValueError, match="An empty array was provided as input."): normalize_matrix(np.array([])) + + +def test_normalize_matrix_non_square_matrix(): + """Test error is raised when row number and column number of Matrix + are mismatched.""" + with pytest.raises(ValueError, match="Input must be a square matrix to be a valid gate."): + normalize_matrix(np.array([[1,4,3]])) + normalize_matrix(np.array([[1]])) + normalize_matrix(np.array([[1, 2], [3, 4],[5,6]])) From 72055f9e44284c5f50c6c534c8f9f02ae5148078 Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Fri, 11 Jun 2021 15:46:46 -0500 Subject: [PATCH 5/7] add check unitary --- src/qutip_qip/decompositions/__init__.py | 2 +- .../decompositions/general_decompositions.py | 19 ++++++++++++++++++- tests/test_general_decompositions.py | 14 ++++++++++---- 3 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/qutip_qip/decompositions/__init__.py b/src/qutip_qip/decompositions/__init__.py index 9f551f7ee..4ddf6e7d9 100644 --- a/src/qutip_qip/decompositions/__init__.py +++ b/src/qutip_qip/decompositions/__init__.py @@ -30,4 +30,4 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ############################################################################### -from qutip_qip.decompositions.general_decompositions import normalize_matrix +from qutip_qip.decompositions.general_decompositions import normalize_matrix, check_unitary diff --git a/src/qutip_qip/decompositions/general_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py index ad3502e4f..db6282abf 100644 --- a/src/qutip_qip/decompositions/general_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -37,6 +37,9 @@ def normalize_matrix(input_array)-> np.array: """ Checks if the input gate's array is normalized or not. If not, makes sure the input has been normalized. + This function will also check if the input is a valid array and a valid + quantum gate. + Args: input_array : Matrix of a gate in array form. """ @@ -54,9 +57,23 @@ def normalize_matrix(input_array)-> np.array: raise ValueError("Input must be a square matrix to be a valid gate.") if np.linalg.det(input_array) != 1: - norm_factor = float(1/np.linalg.det(input_array))**0.5 + norm_factor = float(1/np.abs(np.linalg.det(input_array)))**0.5 input_array = np.around(norm_factor*input_array,5) else: input_array = input_array return(input_array) + +# note this function is defined for qobj, re-defined here for a numpy array. +def check_unitary(input_array)-> bool: + """Checks if the input matrix is unitary or not. + """ + input_array = normalize_matrix(input_array) + identity_matrix = np.eye(input_array.shape[0]) + input_array_dagger = input_array.conj().T + check_unitary_left = np.allclose(identity_matrix, np.dot(input_array_dagger,input_array)) + check_unitary_right = np.allclose(identity_matrix, np.dot(input_array,input_array_dagger)) + if check_unitary_left != check_unitary_right: + print("Unitary product assertions do not match.") + check_unitary = check_unitary_left + return(check_unitary) diff --git a/tests/test_general_decompositions.py b/tests/test_general_decompositions.py index 582c917d9..c8e5b02a2 100644 --- a/tests/test_general_decompositions.py +++ b/tests/test_general_decompositions.py @@ -32,15 +32,16 @@ ############################################################################### import numpy as np import pytest -from qutip_qip.decompositions.general_decompositions import normalize_matrix +from qutip_qip.decompositions.general_decompositions import normalize_matrix, check_unitary from qutip import Qobj -def test_normalize_matrix_valid_input(): - """ Test output when a valid input is provided. +def test_normalize_matrix_valid_input_not_unitary(): + """ Test output when a valid input is provided which is not a unitary. """ normalized_M = normalize_matrix(np.array([[1, 2], [3, 4]])) - calculated_M = np.array([[0.+0.70711j, 0.+1.41421j],[0.+2.12132j, 0.+2.82843j]]) + calculated_M = np.array([[0.70711, 1.41421],[2.12132, 2.82843]]) assert np.array_equal(calculated_M, normalized_M) + assert check_unitary(calculated_M) == False @pytest.mark.parametrize("invalid_input", (Qobj([[1],[2],[3],[4],[5]]),(1,2))) def test_normalize_matrix_invalid_input(invalid_input): @@ -62,3 +63,8 @@ def test_normalize_matrix_non_square_matrix(): normalize_matrix(np.array([[1,4,3]])) normalize_matrix(np.array([[1]])) normalize_matrix(np.array([[1, 2], [3, 4],[5,6]])) + +def test_check_unitary(): + """Tests if input is correctly idenitified as unitary. """ + input_array = np.array([[1+1j,1-1j],[1-1j,1+1j]]) + assert check_unitary(input_array) == True From 9ea0504dde9784f04741893d68ebc9541769a975 Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Fri, 11 Jun 2021 16:17:15 -0500 Subject: [PATCH 6/7] zero determinant --- src/qutip_qip/decompositions/converters.py | 34 +++++++++++++++++++ .../decompositions/general_decompositions.py | 7 ++-- tests/test_general_decompositions.py | 7 ++++ 3 files changed, 46 insertions(+), 2 deletions(-) create mode 100644 src/qutip_qip/decompositions/converters.py diff --git a/src/qutip_qip/decompositions/converters.py b/src/qutip_qip/decompositions/converters.py new file mode 100644 index 000000000..5cf8fc919 --- /dev/null +++ b/src/qutip_qip/decompositions/converters.py @@ -0,0 +1,34 @@ +# This file is part of QuTiP: Quantum Toolbox in Python. +# +# Copyright (c) 2011 and later, Paul D. Nation and Robert J. Johansson. +# All rights reserved. +# +# Redistribution and use in sourc e and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# 3. Neither the name of the QuTiP: Quantum Toolbox in Python nor the names +# of its contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A +# PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +############################################################################### + +# add functions to convert from numpy array to Qobj or Gate class object. diff --git a/src/qutip_qip/decompositions/general_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py index db6282abf..d796f1f88 100644 --- a/src/qutip_qip/decompositions/general_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -57,6 +57,8 @@ def normalize_matrix(input_array)-> np.array: raise ValueError("Input must be a square matrix to be a valid gate.") if np.linalg.det(input_array) != 1: + if np.linalg.det(input_array) ==0: + raise ZeroDivisionError("Determinant of matrix =0.") norm_factor = float(1/np.abs(np.linalg.det(input_array)))**0.5 input_array = np.around(norm_factor*input_array,5) else: @@ -64,7 +66,8 @@ def normalize_matrix(input_array)-> np.array: return(input_array) -# note this function is defined for qobj, re-defined here for a numpy array. +# Note this function is defined for qobj, re-defined here for a numpy array. +# Accessing individual elements of Qobj array could be problematic. def check_unitary(input_array)-> bool: """Checks if the input matrix is unitary or not. """ @@ -74,6 +77,6 @@ def check_unitary(input_array)-> bool: check_unitary_left = np.allclose(identity_matrix, np.dot(input_array_dagger,input_array)) check_unitary_right = np.allclose(identity_matrix, np.dot(input_array,input_array_dagger)) if check_unitary_left != check_unitary_right: - print("Unitary product assertions do not match.") + raise ArithmeticError("Unitary product assertions do not match.") check_unitary = check_unitary_left return(check_unitary) diff --git a/tests/test_general_decompositions.py b/tests/test_general_decompositions.py index c8e5b02a2..a5f541dc2 100644 --- a/tests/test_general_decompositions.py +++ b/tests/test_general_decompositions.py @@ -64,6 +64,13 @@ def test_normalize_matrix_non_square_matrix(): normalize_matrix(np.array([[1]])) normalize_matrix(np.array([[1, 2], [3, 4],[5,6]])) +def test_normalize_matrix_zero_determinant(): + """Check if function tries to divide by 0 norm factor. + """ + with pytest.raises(ZeroDivisionError, match="Determinant of matrix =0."): + normalize_matrix(np.array([[0, 0], [0, 0]])) + + def test_check_unitary(): """Tests if input is correctly idenitified as unitary. """ input_array = np.array([[1+1j,1-1j],[1-1j,1+1j]]) From d7adb868b2110adde03ed16f3d23590282671c1d Mon Sep 17 00:00:00 2001 From: Purva Thakre Date: Fri, 11 Jun 2021 21:14:23 -0500 Subject: [PATCH 7/7] global phase start --- .../decompositions/general_decompositions.py | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/qutip_qip/decompositions/general_decompositions.py b/src/qutip_qip/decompositions/general_decompositions.py index d796f1f88..d3eb445cd 100644 --- a/src/qutip_qip/decompositions/general_decompositions.py +++ b/src/qutip_qip/decompositions/general_decompositions.py @@ -41,7 +41,7 @@ def normalize_matrix(input_array)-> np.array: quantum gate. Args: - input_array : Matrix of a gate in array form. + input_array : Matrix of a gate in Numpy array form. """ if not isinstance(input_array, np.ndarray): raise TypeError("Not a valid input : A Numpy input array must be provided.") @@ -70,6 +70,9 @@ def normalize_matrix(input_array)-> np.array: # Accessing individual elements of Qobj array could be problematic. def check_unitary(input_array)-> bool: """Checks if the input matrix is unitary or not. + + Args: + input_array : Matrix of a gate in Numpy array form. """ input_array = normalize_matrix(input_array) identity_matrix = np.eye(input_array.shape[0]) @@ -80,3 +83,15 @@ def check_unitary(input_array)-> bool: raise ArithmeticError("Unitary product assertions do not match.") check_unitary = check_unitary_left return(check_unitary) + +def extract_global_phase(input_array): + """Express input array as a product of some global phase factor and a special + unitary matrix array (returned in the form of a list containing `phasegate` + and some other special unitary array). + + Args: + input_array : Matrix of a gate in Numpy array form. + """ + if check_unitary == True: + input_array = normalize_matrix(input_array) +