Repository: Qiskit/qiskit

Issue:
support `Pauli.delete([])`
### Environment

- **Qiskit Terra version**: 0.25.1


### What is happening?

`Pauli` and `PauliList` have a method `delete` to delete elements (qubits from a Pauli; Paulis or qubits from a PauliList).

This method accepts a list specifying the indices to delete. However, it raises an error when the list is empty. It would be helpful for programmatic use of `delete` if an empty-list (empty iterable) would instead delete nothing, i.e. return a copy of the original Pauli/PauliList object. This would also be in line with the behavior of `np.delete()`, which is expected here since Paulis are built on, and nominally act like, numpy arrays.

### How can we reproduce the issue?

```
import qiskit.quantum_info as qi
```
Case 1:
```
p = qi.Pauli('XYZ')
p.delete([])
```
Case 2:
```
pl = qi.PauliList(['XYZ','ZIX'])
pl.delete([])
```
Case 3:
```
pl = qi.PauliList(['XYZ','ZIX'])
pl.delete([], qubit=True)
```

### What should happen?

Do not raise an error. Return a copy of the original object.

### Any suggestions?

_No response_


Discussion:
This seems sensible to me - I think there's quite a lot of places within `quantum_info` that don't quite have correct handling for the empty list, and I'm generally in favour of giving them the expected behaviour.
This seems like a rather easy thing to fix. If there's no rush, I can look into it next week.
Sounds good to me, thanks!

Resolving patch:
diff --git a/qiskit/quantum_info/operators/symplectic/pauli.py b/qiskit/quantum_info/operators/symplectic/pauli.py
--- a/qiskit/quantum_info/operators/symplectic/pauli.py
+++ b/qiskit/quantum_info/operators/symplectic/pauli.py
@@ -363,6 +363,8 @@ def delete(self, qubits: int | list) -> Pauli:
         """
         if isinstance(qubits, (int, np.integer)):
             qubits = [qubits]
+        if len(qubits) == 0:
+            return Pauli((self._z, self._x, self.phase))
         if max(qubits) > self.num_qubits - 1:
             raise QiskitError(
                 "Qubit index is larger than the number of qubits "
diff --git a/qiskit/quantum_info/operators/symplectic/pauli_list.py b/qiskit/quantum_info/operators/symplectic/pauli_list.py
--- a/qiskit/quantum_info/operators/symplectic/pauli_list.py
+++ b/qiskit/quantum_info/operators/symplectic/pauli_list.py
@@ -376,7 +376,8 @@ def delete(self, ind: int | list, qubit: bool = False) -> PauliList:
         """
         if isinstance(ind, int):
             ind = [ind]
-
+        if len(ind) == 0:
+            return PauliList.from_symplectic(self._z, self._x, self.phase)
         # Row deletion
         if not qubit:
             if max(ind) >= len(self):
diff --git a/qiskit/quantum_info/operators/symplectic/pauli_table.py b/qiskit/quantum_info/operators/symplectic/pauli_table.py
--- a/qiskit/quantum_info/operators/symplectic/pauli_table.py
+++ b/qiskit/quantum_info/operators/symplectic/pauli_table.py
@@ -281,7 +281,8 @@ def delete(self, ind: int | list, qubit: bool = False) -> PauliTable:
         """
         if isinstance(ind, (int, np.integer)):
             ind = [ind]
-
+        if len(ind) == 0:
+            return PauliTable(self._array)
         # Row deletion
         if not qubit:
             if max(ind) >= self.size:


Test patch:
diff --git a/test/python/quantum_info/operators/symplectic/test_pauli.py b/test/python/quantum_info/operators/symplectic/test_pauli.py
--- a/test/python/quantum_info/operators/symplectic/test_pauli.py
+++ b/test/python/quantum_info/operators/symplectic/test_pauli.py
@@ -224,6 +224,8 @@ def test_insert(self):
     def test_delete(self):
         """Test delete method"""
         pauli = Pauli("IXYZ")
+        pauli = pauli.delete([])
+        self.assertEqual(str(pauli), "IXYZ")
         pauli = pauli.delete([0, 2])
         self.assertEqual(str(pauli), "IY")
 
diff --git a/test/python/quantum_info/operators/symplectic/test_pauli_list.py b/test/python/quantum_info/operators/symplectic/test_pauli_list.py
--- a/test/python/quantum_info/operators/symplectic/test_pauli_list.py
+++ b/test/python/quantum_info/operators/symplectic/test_pauli_list.py
@@ -1495,6 +1495,10 @@ def test_unique(self):
 
     def test_delete(self):
         """Test delete method."""
+        with self.subTest(msg="no rows"):
+            pauli = PauliList(["XX", "ZZ"])
+            self.assertEqual(pauli.delete([]), pauli)
+
         with self.subTest(msg="single row"):
             for j in range(1, 6):
                 pauli = PauliList([j * "X", j * "Y"])
@@ -1508,6 +1512,10 @@ def test_delete(self):
                 self.assertEqual(pauli.delete([1, 2]), PauliList(j * "X"))
                 self.assertEqual(pauli.delete([0, 1]), PauliList(j * "Z"))
 
+        with self.subTest(msg="no qubits"):
+            pauli = PauliList(["XX", "ZZ"])
+            self.assertEqual(pauli.delete([], qubit=True), pauli)
+
         with self.subTest(msg="single qubit"):
             pauli = PauliList(["IIX", "iIYI", "ZII"])
             value = pauli.delete(0, qubit=True)
diff --git a/test/python/quantum_info/operators/symplectic/test_pauli_table.py b/test/python/quantum_info/operators/symplectic/test_pauli_table.py
--- a/test/python/quantum_info/operators/symplectic/test_pauli_table.py
+++ b/test/python/quantum_info/operators/symplectic/test_pauli_table.py
@@ -1136,6 +1136,10 @@ def test_unique(self):
 
     def test_delete(self):
         """Test delete method."""
+        with self.subTest(msg="no rows"):
+            pauli = PauliTable.from_labels(["XX", "YY"])
+            self.assertEqual(pauli.delete([]), pauli)
+
         with self.subTest(msg="single row"):
             for j in range(1, 6):
                 with self.assertWarns(DeprecationWarning):
@@ -1151,6 +1155,10 @@ def test_delete(self):
                     self.assertEqual(pauli.delete([1, 2]), PauliTable(j * "X"))
                     self.assertEqual(pauli.delete([0, 1]), PauliTable(j * "Z"))
 
+        with self.subTest(msg="no rows"):
+            pauli = PauliTable.from_labels(["XX", "YY"])
+            self.assertEqual(pauli.delete([], qubit=True), pauli)
+
         with self.subTest(msg="single qubit"):
             with self.assertWarns(DeprecationWarning):
                 pauli = PauliTable.from_labels(["IIX", "IYI", "ZII"])