qiskit/test/python/circuit/test_diagonal_gate.py

106 lines
3.7 KiB
Python

# This code is part of Qiskit.
#
# (C) Copyright IBM 2019, 2023.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.
"""Diagonal gate tests."""
import unittest
import numpy as np
from qiskit import QuantumCircuit, assemble
from qiskit import QiskitError
from qiskit.compiler import transpile
from qiskit.circuit.library.generalized_gates import DiagonalGate
from qiskit.quantum_info.operators.predicates import matrix_equal
from qiskit.quantum_info import Operator
from test import QiskitTestCase # pylint: disable=wrong-import-order
class TestDiagonalGate(QiskitTestCase):
"""
Diagonal gate tests.
"""
def test_diag_gate(self):
"""Test diagonal gates."""
for phases in [
[0, 0],
[0, 0.8],
[0, 0, 1, 1],
[0, 1, 0.5, 1],
(2 * np.pi * np.random.rand(2**3)).tolist(),
(2 * np.pi * np.random.rand(2**4)).tolist(),
(2 * np.pi * np.random.rand(2**5)).tolist(),
]:
with self.subTest(phases=phases):
diag = [np.exp(1j * ph) for ph in phases]
num_qubits = int(np.log2(len(diag)))
qc = QuantumCircuit(num_qubits)
gate = DiagonalGate(diag)
qc.append(gate, qc.qubits)
# Decompose the gate
qc = transpile(qc, basis_gates=["u1", "u3", "u2", "cx", "id"], optimization_level=0)
# Simulate the decomposed gate
unitary = Operator(qc)
unitary_desired = _get_diag_gate_matrix(diag)
self.assertTrue(matrix_equal(unitary, unitary_desired, ignore_phase=False))
def test_mod1_entries(self):
"""Test that diagonal raises if entries do not have modules of 1."""
from qiskit.quantum_info.operators.predicates import ATOL_DEFAULT, RTOL_DEFAULT
with self.assertRaises(QiskitError):
DiagonalGate([1, 1 - 2 * ATOL_DEFAULT - RTOL_DEFAULT])
def test_npcomplex_params_conversion(self):
"""Verify diagonal gate converts numpy.complex to complex."""
# ref: https://github.com/Qiskit/qiskit-aer/issues/696
diag = np.array([1 + 0j, 1 + 0j])
qc = QuantumCircuit(1)
gate = DiagonalGate(diag)
qc.append(gate, [0])
params = qc.data[0].operation.params
self.assertTrue(
all(isinstance(p, complex) and not isinstance(p, np.number) for p in params)
)
with self.assertWarns(DeprecationWarning):
# REMOVE this assertion (not the full test) once ASSEMBLE is removed.
qobj = assemble(qc)
params = qobj.experiments[0].instructions[0].params
self.assertTrue(
all(isinstance(p, complex) and not isinstance(p, np.number) for p in params)
)
def test_repeat(self):
"""Test the repeat() method."""
for phases in [
[0, 0],
np.array([0, 0.8, 1, 0]),
(2 * np.pi * np.random.rand(2**3)).tolist(),
]:
with self.subTest(phases=phases):
diag = [np.exp(1j * ph) for ph in phases]
gate = DiagonalGate(diag)
operator = Operator(gate)
self.assertTrue(np.allclose(Operator(gate.repeat(2)), operator @ operator))
def _get_diag_gate_matrix(diag):
return np.diagflat(diag)
if __name__ == "__main__":
unittest.main()