From a6830fb849af733f38a32834c03557c5cb529bda Mon Sep 17 00:00:00 2001 From: Takashi Imamichi Date: Fri, 10 May 2024 18:45:35 +0900 Subject: [PATCH 1/4] fix apply_layout to raise an error with negative or duplicate indices --- qiskit/quantum_info/operators/symplectic/pauli.py | 7 +++++-- .../operators/symplectic/sparse_pauli_op.py | 8 +++++--- .../quantum_info/operators/symplectic/test_pauli.py | 12 ++++++++++++ .../operators/symplectic/test_sparse_pauli_op.py | 12 ++++++++++++ 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/qiskit/quantum_info/operators/symplectic/pauli.py b/qiskit/quantum_info/operators/symplectic/pauli.py index 1ccecc04a6c0..8187c1ee41e6 100644 --- a/qiskit/quantum_info/operators/symplectic/pauli.py +++ b/qiskit/quantum_info/operators/symplectic/pauli.py @@ -736,8 +736,11 @@ def apply_layout( n_qubits = num_qubits if layout is None: layout = list(range(self.num_qubits)) - elif any(x >= n_qubits for x in layout): - raise QiskitError("Provided layout contains indices outside the number of qubits.") + else: + if any(x < 0 or x >= n_qubits for x in layout): + raise QiskitError("Provided layout contains indices outside the number of qubits.") + if len(set(layout)) != len(layout): + raise QiskitError("Provided layout contains duplicate indices.") new_op = type(self)("I" * n_qubits) return new_op.compose(self, qargs=layout) diff --git a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py index dffe5b2396b2..cf51579bef8f 100644 --- a/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py +++ b/qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py @@ -1139,7 +1139,6 @@ def apply_layout( specified will be applied without any expansion. If layout is None, the operator will be expanded to the given number of qubits. - Returns: A new :class:`.SparsePauliOp` with the provided layout applied """ @@ -1159,10 +1158,13 @@ def apply_layout( f"applied to a {n_qubits} qubit operator" ) n_qubits = num_qubits - if layout is not None and any(x >= n_qubits for x in layout): - raise QiskitError("Provided layout contains indices outside the number of qubits.") if layout is None: layout = list(range(self.num_qubits)) + else: + if any(x < 0 or x >= n_qubits for x in layout): + raise QiskitError("Provided layout contains indices outside the number of qubits.") + if len(set(layout)) != len(layout): + raise QiskitError("Provided layout contains duplicate indices.") new_op = type(self)("I" * n_qubits) return new_op.compose(self, qargs=layout) diff --git a/test/python/quantum_info/operators/symplectic/test_pauli.py b/test/python/quantum_info/operators/symplectic/test_pauli.py index 875dd9237810..89324e8212e1 100644 --- a/test/python/quantum_info/operators/symplectic/test_pauli.py +++ b/test/python/quantum_info/operators/symplectic/test_pauli.py @@ -606,6 +606,18 @@ def test_apply_layout_null_layout_invalid_num_qubits(self): with self.assertRaises(QiskitError): op.apply_layout(layout=None, num_qubits=1) + def test_apply_layout_negative_indices(self): + """Test apply_layout with negative indices""" + op = Pauli("IZ") + with self.assertRaises(QiskitError): + op.apply_layout(layout=[-1, 0], num_qubits=3) + + def test_apply_layout_duplicate_indices(self): + """Test apply_layout with duplicate indices""" + op = Pauli("IZ") + with self.assertRaises(QiskitError): + op.apply_layout(layout=[0, 0], num_qubits=3) + if __name__ == "__main__": unittest.main() diff --git a/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py b/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py index 330fd53bc35d..1149ef1f3466 100644 --- a/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py +++ b/test/python/quantum_info/operators/symplectic/test_sparse_pauli_op.py @@ -1179,6 +1179,18 @@ def test_apply_layout_null_layout_invalid_num_qubits(self): with self.assertRaises(QiskitError): op.apply_layout(layout=None, num_qubits=1) + def test_apply_layout_negative_indices(self): + """Test apply_layout with negative indices""" + op = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]) + with self.assertRaises(QiskitError): + op.apply_layout(layout=[-1, 0], num_qubits=3) + + def test_apply_layout_duplicate_indices(self): + """Test apply_layout with duplicate indices""" + op = SparsePauliOp.from_list([("II", 1), ("IZ", 2), ("XI", 3)]) + with self.assertRaises(QiskitError): + op.apply_layout(layout=[0, 0], num_qubits=3) + if __name__ == "__main__": unittest.main() From 931a15b7fec0a10f19fd5cc751cc2eb6140277b4 Mon Sep 17 00:00:00 2001 From: Takashi Imamichi Date: Fri, 10 May 2024 19:19:04 +0900 Subject: [PATCH 2/4] reno --- ...-layout-duplicate-negative-indices-cf5517921fe52706.yaml | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml diff --git a/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml new file mode 100644 index 000000000000..1429887fd31c --- /dev/null +++ b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixed :meth:`~.SparsePauliOp.apply_layout` and :meth:`~.Pauli.apply_layout` + to raise ``QiskitError`` if duplicate indices or negative indices are provided + as part of a layout. From db8143ace90f0efeded6d227beed1d6bcbdffe46 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Fri, 10 May 2024 11:21:45 +0100 Subject: [PATCH 3/4] Fix Sphinx syntax --- ...ly-layout-duplicate-negative-indices-cf5517921fe52706.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml index 1429887fd31c..0fd7f36228f4 100644 --- a/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml +++ b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml @@ -1,6 +1,6 @@ --- fixes: - | - Fixed :meth:`~.SparsePauliOp.apply_layout` and :meth:`~.Pauli.apply_layout` - to raise ``QiskitError`` if duplicate indices or negative indices are provided + Fixed :meth:`.SparsePauliOp.apply_layout` and :meth:`.Pauli.apply_layout` + to raise :exc:`QiskitError` if duplicate indices or negative indices are provided as part of a layout. From bec56678a98b374728ade7e8f316693167e99d09 Mon Sep 17 00:00:00 2001 From: Jake Lishman Date: Fri, 10 May 2024 11:22:36 +0100 Subject: [PATCH 4/4] Fix my own Sphinx lookup problem --- ...pply-layout-duplicate-negative-indices-cf5517921fe52706.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml index 0fd7f36228f4..9fbe0ffd9c79 100644 --- a/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml +++ b/releasenotes/notes/fix-apply-layout-duplicate-negative-indices-cf5517921fe52706.yaml @@ -2,5 +2,5 @@ fixes: - | Fixed :meth:`.SparsePauliOp.apply_layout` and :meth:`.Pauli.apply_layout` - to raise :exc:`QiskitError` if duplicate indices or negative indices are provided + to raise :exc:`.QiskitError` if duplicate indices or negative indices are provided as part of a layout.