Skip to content

Commit

Permalink
Merge 196be45 into 5d604ff
Browse files Browse the repository at this point in the history
  • Loading branch information
purva-thakre authored Jul 5, 2021
2 parents 5d604ff + 196be45 commit 41d708b
Show file tree
Hide file tree
Showing 9 changed files with 639 additions and 0 deletions.
37 changes: 37 additions & 0 deletions doc/source/_apidoc/qutip_qip.decompositions.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
qutip\_qip.decompositions package
=================================

Submodules
----------

qutip\_qip.decompositions.decompositions\_extras module
-------------------------------------------------------

.. automodule:: qutip_qip.decompositions.decompositions_extras
:members:
:undoc-members:
:show-inheritance:

qutip\_qip.decompositions.general\_decompositions module
--------------------------------------------------------

.. automodule:: qutip_qip.decompositions.general_decompositions
:members:
:undoc-members:
:show-inheritance:

qutip\_qip.decompositions.single\_decompositions module
-------------------------------------------------------

.. automodule:: qutip_qip.decompositions.single_decompositions
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

.. automodule:: qutip_qip.decompositions
:members:
:undoc-members:
:show-inheritance:
9 changes: 9 additions & 0 deletions doc/source/_apidoc/qutip_qip.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Subpackages

qutip_qip.algorithms
qutip_qip.compiler
qutip_qip.decompositions
qutip_qip.device
qutip_qip.operations
qutip_qip.transpiler
Expand Down Expand Up @@ -72,6 +73,14 @@ qutip\_qip.qubits module
:undoc-members:
:show-inheritance:

qutip\_qip.version module
-------------------------

.. automodule:: qutip_qip.version
:members:
:undoc-members:
:show-inheritance:

Module contents
---------------

Expand Down
7 changes: 7 additions & 0 deletions src/qutip_qip/decompositions/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from qutip_qip.decompositions.general_decompositions import (check_input,
check_input_shape, convert_qobj_gate_to_array, extract_global_phase)

from qutip_qip.decompositions.single_decompositions import (_ZYZ_rotation, _ZXZ_rotation, _rotation_matrices_dictionary,
ABC_decomposition, decompose_to_rotation_matrices)

from qutip_qip.decompositions.decompositions_extras import (decomposed_gates_to_circuit, matrix_of_decomposed_gates)
35 changes: 35 additions & 0 deletions src/qutip_qip/decompositions/decompositions_extras.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from qutip_qip.decompositions.general_decompositions import (check_input,
check_input_shape, convert_qobj_gate_to_array)

from qutip_qip.decompositions.single_decompositions import (_ZYZ_rotation, _ZXZ_rotation, _rotation_matrices_dictionary, decompose_to_rotation_matrices, ABC_decomposition)
from qutip.qobj import Qobj
from qutip_qip.operations import *
from qutip_qip.circuit import QubitCircuit, Gate
from numpy import pi
import numpy as np

def decomposed_gates_to_circuit(decomposed_gate,num_of_qubits):
"""This function takes the input from a decomposition function and creates
a circuit diagram.
"""
# as decomposed_gate contains information about targets/control, there's no
# additional input of target here.
# In addition, there's no check if the gates are valid for number of qubits
# because this is done in a decomposition function before output.
if isinstance(decomposed_gate,tuple) == True:
q_circuit = QubitCircuit(num_of_qubits, reverse_states=False)
for i in decomposed_gate:
q_circuit.add_gate(i)
return(q_circuit)
else:
raise TypeError("Input is not a tuple of gates.")

def matrix_of_decomposed_gates(quantum_circuit):
"""Evaluates all the gates in the circuit.
"""
if isinstance(quantum_circuit, QubitCircuit) == True:
gate_list = quantum_circuit.propagators()
matrix_of_all_gates = gate_sequence_product(gate_list)
return(matrix_of_all_gates)
else:
raise TypeError("Input is not of type QubitCircuit.")
122 changes: 122 additions & 0 deletions src/qutip_qip/decompositions/general_decompositions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
import numpy as np
import cmath

from qutip.qobj import Qobj

class MethodError(Exception):
"""When invalid method is chosen, this error is raised.
"""
pass

class GateError(Exception):
"""When chosen method cannot be applied to the input gate, this error
is raised.
"""
pass

def check_input(input_gate):
"""Verifies input is a valid quantum gate.
Parameters
----------
input_gate : :class:`qutip.Qobj`
The matrix that's supposed to be decomposed should be a Qobj.
Returns
-------
bool
If the input is a valid quantum gate matrix, returns "True".
In the case of "False" being returned, this function will ensure no
decomposition scheme can proceed.
"""
# check if input is a qobj
qobj_check = isinstance(input_gate,Qobj)
if qobj_check == False:
raise TypeError("The input matrix is not a Qobj.")
else:
# check if input is square and a unitary
input_shape = input_gate.shape
# check if input is 1 row and 1 column matrix
if input_shape[0]==1:
raise ValueError("A 1-D Qobj is not a valid quantum gate.")
# check if the input is a rectangular matrix
if input_shape[0] != input_shape[1]:
raise ValueError("Input is not a square matrix.")
else:
unitary_check = Qobj.check_isunitary(input_gate)
return unitary_check


def check_input_shape(input_gate, num_of_qubits):
"""Check if the shape of input gate is valid to act on input number of qubits
If :math:`n` is the number of qubits in the circuit then a valid quantum gate
acting on these qubits must be of dimension :math:`2^n \\times 2^n`.
Parameters
----------
input_gate : :class:`qutip.Qobj`
The matrix that's supposed to be decomposed should be a Qobj.
num_of_qubits : int
Number of qubits in the circuit.
Returns
-------
bool
Returns "True" if the shape of input gate is valid to act on the number
of qubits in the circuit.
"""
input_check_bool = check_input(input_gate)
if input_check_bool == True:
input_shape = input_gate.shape
return input_shape[0] == 2**num_of_qubits
else:
raise ValueError("Input is not unitary.")


def convert_qobj_gate_to_array(input_gate):
"""Converts a valid unitary quantum gate to a numpy array.
Parameters
----------
input_gate : :class:`qutip.Qobj`
The matrix that's supposed to be decomposed should be a Qobj.
Returns
-------
input_gate : `np.array`
The input is returned as a converted numpy array.
"""
input_check_bool = check_input(input_gate)
if input_check_bool == True:
input_to_array = Qobj.full(input_gate)
try:
isinstance(input_to_array, np.ndarray)
except: # Not sure if this error has to be included. If an error occurs,
# then it ought to covered in the main qutip module.
raise ConversionError("Input Qobj could not be converted to a numpy array.")
return(input_to_array)
else:
raise ValueError("Input is not unitary.")


def extract_global_phase(input_gate, num_of_qubits):
""" Extracts some common constant from all the elements of the matrix. The output
is retuned in the complex exponential form.
Parameters
----------
input_gate : :class:`qutip.Qobj`
The matrix that's supposed to be decomposed should be a Qobj.
"""
if check_input_shape(input_gate, num_of_qubits) == True:
input_array = convert_qobj_gate_to_array(input_gate)
determinant_of_input = np.linalg.det(input_array)
global_phase_angle = cmath.phase(determinant_of_input)
global_phase_angle = global_phase_angle/(2**num_of_qubits)
return(global_phase_angle)
else:
raise GateError("Gate shape does not match to the number of qubits in the circuit. ")
Loading

0 comments on commit 41d708b

Please sign in to comment.