Skip to content

Commit 408741c

Browse files
Fix phase of pauli_list.insert(..., qubit=True) for length-1 pauli_list (Qiskit#13624)
* switch order of if-clauses `len(value) == 1` is the simplest case, and is also the case where the problematic clause `len(value) == size` fails. This commit switches the order, so we check for `len(value) == 1` first. This ensures that when the `len(value) == size` clause runs, we know that `size != 1`, avoiding the bug in Qiskit#13623. * add test * Simplify `value.phase` broadcasting Here, `phase` should be a 1D array. `np.vstack()` docs say explicitly output will be at least 2D, so we should not use that to create `phase`. The intent of using `np.vstack()` was essentially to broadcast `phase` to properly add to `self.phase`. But, this happens automatically and correctly if we just add as-is. So this commit simplifies the code accordingly. * Verify that `phase` is 1D in `from_symplectic()` Verifying the input arg `phase`, since otherwise `from_symplectic()` will silently create PauliLists with malformed `phase` attributes (i.e. not 1D). Zero-dimensional is OK (e.g. `phase` defaults to `0`) since that can broadcast per the shape of the `z` and `x` arrays. * remove vestigial line * lint * release note * Update releasenotes/notes/fix-paulilist-length1-phase-688d0e3a64ec9a9f.yaml Co-authored-by: Jake Lishman <[email protected]> --------- Co-authored-by: Jake Lishman <[email protected]>
1 parent 682cf3b commit 408741c

File tree

3 files changed

+23
-8
lines changed

3 files changed

+23
-8
lines changed

qiskit/quantum_info/operators/symplectic/pauli_list.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -451,16 +451,14 @@ def insert(self, ind: int, value: PauliList, qubit: bool = False) -> PauliList:
451451
f"Index {ind} is greater than number of qubits"
452452
f" in the PauliList ({self.num_qubits})"
453453
)
454-
if len(value) == 1:
455-
# Pad blocks to correct size
456-
value_x = np.vstack(size * [value.x])
457-
value_z = np.vstack(size * [value.z])
458-
value_phase = np.vstack(size * [value.phase])
459-
elif len(value) == size:
454+
if len(value) == size:
460455
# Blocks are already correct size
461456
value_x = value.x
462457
value_z = value.z
463-
value_phase = value.phase
458+
elif len(value) == 1:
459+
# Pad blocks to correct size
460+
value_x = np.vstack(size * [value.x])
461+
value_z = np.vstack(size * [value.z])
464462
else:
465463
# Blocks are incorrect size
466464
raise QiskitError(
@@ -471,7 +469,7 @@ def insert(self, ind: int, value: PauliList, qubit: bool = False) -> PauliList:
471469
# Build new array by blocks
472470
z = np.hstack([self.z[:, :ind], value_z, self.z[:, ind:]])
473471
x = np.hstack([self.x[:, :ind], value_x, self.x[:, ind:]])
474-
phase = self.phase + value_phase
472+
phase = self.phase + value.phase
475473

476474
return PauliList.from_symplectic(z, x, phase)
477475

@@ -1131,6 +1129,8 @@ def from_symplectic(
11311129
Returns:
11321130
PauliList: the constructed PauliList.
11331131
"""
1132+
if isinstance(phase, np.ndarray) and np.ndim(phase) > 1:
1133+
raise ValueError(f"phase should be at most 1D but has {np.ndim(phase)} dimensions.")
11341134
base_z, base_x, base_phase = cls._from_array(z, x, phase)
11351135
return cls(BasePauli(base_z, base_x, base_phase))
11361136

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
fixes:
3+
- |
4+
Fixed a bug that caused :meth:`.PauliList.insert` with ``qubit=True`` to produce a `phase`
5+
attribute with the wrong shape when the original object was length 1.
6+
Fixed `#13623 <https://github.com/Qiskit/qiskit/issues/13623>`__.

test/python/quantum_info/operators/symplectic/test_pauli_list.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1560,6 +1560,15 @@ def test_insert(self):
15601560
value1 = pauli.insert(1, insert)
15611561
self.assertEqual(value1, target1)
15621562

1563+
# Insert single column to length-1 PauliList:
1564+
with self.subTest(msg="length-1, single-column, single-val"):
1565+
pauli = PauliList(["X"])
1566+
insert = PauliList(["Y"])
1567+
target0 = PauliList(["YX"])
1568+
value0 = pauli.insert(1, insert, qubit=True)
1569+
self.assertEqual(value0, target0)
1570+
self.assertEqual(value0.phase.shape, (1,))
1571+
15631572
# Insert single column
15641573
pauli = PauliList(["X", "Y", "Z", "-iI"])
15651574
for i in ["I", "X", "Y", "Z", "iY"]:

0 commit comments

Comments
 (0)