-
Notifications
You must be signed in to change notification settings - Fork 64
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
639 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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.") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. ") |
Oops, something went wrong.