跳转至

UnitaryDecomposition

QuICT.qcda.synthesis.unitary_decomposition.UnitaryDecomposition

UnitaryDecomposition(method: str = 'uniformly_rotation', include_phase_gate: bool = False, recursive_basis: int = 2, ancilla: int = 0, opt: bool = False)

Bases: object

Transform a general unitary matrix into CX gates and single qubit gates.

References

[1] Synthesis of Quantum Logic Circuits https://arxiv.org/abs/quant-ph/0406176

[2] Constructive quantum Shannon decomposition from Cartan involutions https://arxiv.org/abs/0806.4015

[3] Minimal Universal Two-qubit Quantum Circuits https://arxiv.org/abs/quant-ph/0308033

[4] Optimal quantum circuits for general two-qubit gates https://arxiv.org/abs/quant-ph/0308006

Examples:

1.use the method of uniformly_rotation by default

>>> from QuICT.qcda.synthesis import UnitaryDecomposition
>>> UD = UnitaryDecomposition()
>>> gates, _ = UD.execute(mat)
2.use the method of diagonal_gate
>>> from QuICT.qcda.synthesis import UnitaryDecomposition
>>> UD = UnitaryDecomposition(method='diagonal_gate')
>>> gates, _ = UD.execute(mat)

Parameters:

  • method (str, default: 'uniformly_rotation' ) –

    chosen method in ['uniformly_rotation', 'diagonal_gate']

  • include_phase_gate (bool, default: False ) –

    Whether to include a phase gate to keep synthesized gate matrix the same as input. If set False, the output gates might have a matrix which has a factor shift to input: np.allclose( * factor, ).

  • recursive_basis (int, default: 2 ) –

    Terminate recursion at which level. It could be set as 1 or 2, which would stop recursion when matrix is 2 or 4, respectively. When set as 2, the final step is done by KAK decomposition. Correctness of this algorithm is never influenced by recursive_basis.

  • ancilla (int, default: 0 ) –

    the number of ancillary qubits when the method is 'diagonal_gate'

  • opt (bool, default: False ) –

    the switch of cnot optimizer when the method is 'diagonal_gate'

Source code in QuICT/qcda/synthesis/unitary_decomposition/unitary_decomposition.py
def __init__(
        self,
        method: str = 'uniformly_rotation',
        include_phase_gate: bool = False,
        recursive_basis: int = 2,
        ancilla: int = 0,
        opt: bool = False
):
    """
    Args:
        method (str, optional): chosen method in ['uniformly_rotation', 'diagonal_gate']
        If you choose the method of 'diagonal_gate', please pay attention to the ancilla and opt.
        include_phase_gate (bool): Whether to include a phase gate to keep synthesized gate matrix the same
            as input. If set False, the output gates might have a matrix which has a factor shift to input:
            np.allclose(<matrix_of_return_gates> * factor, <input_matrix>).
        recursive_basis (int): Terminate recursion at which level. It could be set as 1 or 2, which would stop
            recursion when matrix is 2 or 4, respectively. When set as 2, the final step is done by KAK
            decomposition. Correctness of this algorithm is never influenced by recursive_basis.
        ancilla (int):the number of ancillary qubits when the method is 'diagonal_gate'
        opt (bool): the switch of cnot optimizer when the method is 'diagonal_gate'
    """
    self.include_phase_gate = include_phase_gate
    self.recursive_basis = recursive_basis
    self.method = method
    self.ancilla = ancilla
    self.opt = opt
    if self.method not in ['uniformly_rotation', 'diagonal_gate']:
        self._logger.warn(
            "Only 'uniformly_rotation' and 'diagonal_gate' "
            "methods can decompose unitary matrix. Please choose "
            "the correct method."
        )

execute

execute(mat: ndarray) -> Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]

Parameters:

  • mat (ndarray) –

    Unitary matrix.

Returns:

  • Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]

    Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]: If self.include_phase_gate==False,

  • Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]

    this function returns synthesized gates and a shift factor. Otherwise a tuple like (, None)

  • Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]

    is returned.

Source code in QuICT/qcda/synthesis/unitary_decomposition/unitary_decomposition.py
def execute(self, mat: np.ndarray) -> Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]:
    """
    Args:
        mat (np.ndarray): Unitary matrix.

    Returns:
        Union[Tuple[CompositeGate, None], Tuple[CompositeGate, complex]]: If self.include_phase_gate==False,
        this function returns synthesized gates and a shift factor. Otherwise a tuple like (<gates>, None)
        is returned.
    """
    qubit_num = int(round(np.log2(mat.shape[0])))
    mat = mat.astype(complex)

    """
    After adding KAK diagonal optimization, inner built gates would have a
    leading diagonal gate not decomposed. If our first-level recursion is
    2-bit, using older version of KAK is OK.
    """

    if qubit_num == 2 and self.recursive_basis == 2:
        CKD = CartanKAKDecomposition()
        gates = CKD.execute(mat)
        syn_mat = gates.matrix()
        shift = shift_ratio(mat, syn_mat)
        if self.include_phase_gate:
            gates = add_factor_shift_into_phase(gates, shift)
            return gates, None
        else:
            return gates, shift

    if self.method == 'uniformly_rotation':
        gates, shift = self.inner_utrans_build_gate(
            mat=mat,
            method=self.method,
            recursive_basis=self.recursive_basis,
            keep_left_diagonal=False,
        )

    if self.method == 'diagonal_gate':
        gates, shift = self.inner_utrans_build_gate(
            mat=mat,
            method=self.method,
            recursive_basis=self.recursive_basis,
            keep_left_diagonal=False,
            use_cz_ry=False
        )

    if self.recursive_basis == 2 and self.include_phase_gate:
        gates = add_factor_shift_into_phase(gates, shift)
    if self.include_phase_gate:
        return gates, None
    else:
        return gates, shift