Skip to content

Commit

Permalink
Fix {Pauli,SparsePauliOp}.apply_layout to raise an error with negativ…
Browse files Browse the repository at this point in the history
…e or duplicate indices (#12385) (#12386)

* fix apply_layout to raise an error with negative or duplicate indices

* reno

* Fix Sphinx syntax

* Fix my own Sphinx lookup problem

---------

Co-authored-by: Jake Lishman <[email protected]>
(cherry picked from commit fe275a0)

Co-authored-by: Takashi Imamichi <[email protected]>
  • Loading branch information
mergify[bot] and t-imamichi authored May 10, 2024
1 parent a938606 commit 70eae3c
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 5 deletions.
7 changes: 5 additions & 2 deletions qiskit/quantum_info/operators/symplectic/pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
8 changes: 5 additions & 3 deletions qiskit/quantum_info/operators/symplectic/sparse_pauli_op.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
"""
Expand All @@ -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)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
fixes:
- |
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.
12 changes: 12 additions & 0 deletions test/python/quantum_info/operators/symplectic/test_pauli.py
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Original file line number Diff line number Diff line change
Expand Up @@ -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()

0 comments on commit 70eae3c

Please sign in to comment.