diff --git a/qiskit/circuit/gate.py b/qiskit/circuit/gate.py index 37fd19e202..2f1c096682 100644 --- a/qiskit/circuit/gate.py +++ b/qiskit/circuit/gate.py @@ -97,7 +97,10 @@ class Gate(Instruction): return self.power(exponent) def _return_repeat(self, exponent: float) -> "Gate": - return Gate(name=f"{self.name}*{exponent}", num_qubits=self.num_qubits, params=self.params) + gate = Gate(name=f"{self.name}*{exponent}", num_qubits=self.num_qubits, params=[]) + gate.validate_parameter = self.validate_parameter + gate.params = self.params + return gate def control( self, diff --git a/releasenotes/notes/fix_11990-8551c7250207fc76.yaml b/releasenotes/notes/fix_11990-8551c7250207fc76.yaml new file mode 100644 index 0000000000..68912403cd --- /dev/null +++ b/releasenotes/notes/fix_11990-8551c7250207fc76.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes an error when calling the method :meth:`.UnitaryGate.repeat`. + Refer to `#11990 `_ for more + details. \ No newline at end of file diff --git a/test/python/circuit/library/test_linear_function.py b/test/python/circuit/library/test_linear_function.py index a3df1e9664..b7756faa7a 100644 --- a/test/python/circuit/library/test_linear_function.py +++ b/test/python/circuit/library/test_linear_function.py @@ -502,6 +502,19 @@ class TestLinearFunctions(QiskitTestCase): self.assertEqual(Clifford(qc_to_linear_function), qc_to_clifford) self.assertEqual(qc_to_linear_function, LinearFunction(qc_to_clifford)) + @data(2, 3) + def test_repeat_method(self, num_qubits): + """Test the repeat() method.""" + rng = np.random.default_rng(127) + for num_gates, seed in zip( + [0, 5, 5 * num_qubits], rng.integers(100000, size=10, dtype=np.uint64) + ): + # create a random linear circuit + linear_circuit = random_linear_circuit(num_qubits, num_gates, seed=seed) + operator = Operator(linear_circuit) + linear_function = LinearFunction(linear_circuit) + self.assertTrue(Operator(linear_function.repeat(2)), operator @ operator) + if __name__ == "__main__": unittest.main() diff --git a/test/python/circuit/library/test_permutation.py b/test/python/circuit/library/test_permutation.py index 30d504d7dc..a2ec59431f 100644 --- a/test/python/circuit/library/test_permutation.py +++ b/test/python/circuit/library/test_permutation.py @@ -104,6 +104,12 @@ class TestPermutationGate(QiskitTestCase): expected_inverse_perm = PermutationGate([3, 0, 5, 1, 4, 2]) self.assertTrue(np.array_equal(inverse_perm.pattern, expected_inverse_perm.pattern)) + def test_repeat(self): + """Test the ``repeat`` method.""" + pattern = [2, 4, 1, 3, 0] + perm = PermutationGate(pattern) + self.assertTrue(np.allclose(Operator(perm.repeat(2)), Operator(perm) @ Operator(perm))) + class TestPermutationGatesOnCircuit(QiskitTestCase): """Tests for quantum circuits containing permutations.""" diff --git a/test/python/circuit/test_diagonal_gate.py b/test/python/circuit/test_diagonal_gate.py index de8d53e12d..bb92599995 100644 --- a/test/python/circuit/test_diagonal_gate.py +++ b/test/python/circuit/test_diagonal_gate.py @@ -83,6 +83,19 @@ class TestDiagonalGate(QiskitTestCase): 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) diff --git a/test/python/circuit/test_gate_definitions.py b/test/python/circuit/test_gate_definitions.py index 950b0c478e..914ac8bab9 100644 --- a/test/python/circuit/test_gate_definitions.py +++ b/test/python/circuit/test_gate_definitions.py @@ -54,6 +54,8 @@ from qiskit.circuit.library import ( CZGate, RYYGate, PhaseGate, + PauliGate, + UCPauliRotGate, CPhaseGate, UGate, CUGate, @@ -184,6 +186,18 @@ class TestGateDefinitions(QiskitTestCase): self.assertTrue(len(decomposed_circuit) > len(circuit)) self.assertTrue(Operator(circuit).equiv(Operator(decomposed_circuit), atol=1e-7)) + def test_pauligate_repeat(self): + """Test `repeat` method for `PauliGate`.""" + gate = PauliGate("XYZ") + operator = Operator(gate) + self.assertTrue(np.allclose(Operator(gate.repeat(2)), operator @ operator)) + + def test_ucpaulirotgate_repeat(self): + """Test `repeat` method for `UCPauliRotGate`.""" + gate = UCPauliRotGate([0.3, 0.5], "X") + operator = Operator(gate) + self.assertTrue(np.allclose(Operator(gate.repeat(2)), operator @ operator)) + @ddt class TestStandardGates(QiskitTestCase): diff --git a/test/python/circuit/test_hamiltonian_gate.py b/test/python/circuit/test_hamiltonian_gate.py index 60fb1e9a90..e65e2f07ba 100644 --- a/test/python/circuit/test_hamiltonian_gate.py +++ b/test/python/circuit/test_hamiltonian_gate.py @@ -62,6 +62,12 @@ class TestHamiltonianGate(QiskitTestCase): ham.adjoint().to_matrix(), np.transpose(np.conj(ham.to_matrix())) ) + def test_repeat(self): + """test repeat operation""" + ham = HamiltonianGate(np.array([[1, 0.5 + 4j], [0.5 - 4j, -0.2]]), np.pi * 0.143) + operator = Operator(ham) + self.assertTrue(np.allclose(Operator(ham.repeat(2)), operator @ operator)) + class TestHamiltonianCircuit(QiskitTestCase): """Hamiltonian gate circuit tests.""" diff --git a/test/python/circuit/test_initializer.py b/test/python/circuit/test_initializer.py index 2507fbc6c1..990df5755d 100644 --- a/test/python/circuit/test_initializer.py +++ b/test/python/circuit/test_initializer.py @@ -473,6 +473,16 @@ class TestInitialize(QiskitTestCase): vec = Statevector(qc) self.assertTrue(vec == Statevector(desired_vector)) + def test_repeat(self): + """Test the repeat() method.""" + desired_vector = np.array([0.5, 0.5, 0.5, 0.5]) + initialize = Initialize(desired_vector) + qr = QuantumRegister(2) + qc = QuantumCircuit(qr) + qc.append(initialize.repeat(2), qr) + statevector = Statevector(qc) + self.assertTrue(np.allclose(statevector, desired_vector)) + class TestInstructionParam(QiskitTestCase): """Test conversion of numpy type parameters.""" diff --git a/test/python/circuit/test_isometry.py b/test/python/circuit/test_isometry.py index 35ff639ced..ff497c76f4 100644 --- a/test/python/circuit/test_isometry.py +++ b/test/python/circuit/test_isometry.py @@ -133,6 +133,21 @@ class TestIsometry(QiskitTestCase): result = Operator(qc) np.testing.assert_array_almost_equal(result.data, np.identity(result.dim[0])) + @data( + np.eye(2, 2), + random_unitary(2, seed=297102).data, + np.eye(4, 4), + random_unitary(4, seed=123642).data, + random_unitary(8, seed=568288).data, + ) + def test_isometry_repeat(self, iso): + """Tests for the repeat of isometries from n to n qubits""" + iso_gate = Isometry(iso, 0, 0) + + op = Operator(iso_gate) + op_double = Operator(iso_gate.repeat(2)) + np.testing.assert_array_almost_equal(op @ op, op_double) + if __name__ == "__main__": unittest.main() diff --git a/test/python/circuit/test_uc.py b/test/python/circuit/test_uc.py index 87541d349c..0277c4afb4 100644 --- a/test/python/circuit/test_uc.py +++ b/test/python/circuit/test_uc.py @@ -100,6 +100,13 @@ class TestUCGate(QiskitTestCase): self.assertTrue(np.allclose(unitary_desired, unitary)) + def test_repeat(self): + """test repeat operation""" + gates = [random_unitary(2, seed=seed).data for seed in [124435, 876345, 687462, 928365]] + + uc = UCGate(gates, up_to_diagonal=False) + self.assertTrue(np.allclose(Operator(uc.repeat(2)), Operator(uc) @ Operator(uc))) + def _get_ucg_matrix(squs): return block_diag(*squs) diff --git a/test/python/circuit/test_unitary.py b/test/python/circuit/test_unitary.py index 63edbdaffb..6ab4a93c3f 100644 --- a/test/python/circuit/test_unitary.py +++ b/test/python/circuit/test_unitary.py @@ -67,6 +67,11 @@ class TestUnitaryGate(QiskitTestCase): uni = UnitaryGate([[0, 1j], [-1j, 0]]) self.assertTrue(numpy.array_equal(uni.adjoint().to_matrix(), uni.to_matrix())) + def test_repeat(self): + """test repeat operation""" + uni = UnitaryGate([[1, 0], [0, 1j]]) + self.assertTrue(numpy.array_equal(Operator(uni.repeat(2)), Operator(uni) @ Operator(uni))) + class TestUnitaryCircuit(QiskitTestCase): """Matrix gate circuit tests."""