From 8b2f6bd83ce8839c3efcb24d784dbb5f888db307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Elena=20Pe=C3=B1a=20Tapia?= <57907331+ElePT@users.noreply.github.com> Date: Wed, 8 Jan 2025 18:48:39 +0100 Subject: [PATCH 1/3] Close previous figures in docs plots. (#13635) --- qiskit/circuit/library/grover_operator.py | 6 +++--- qiskit/circuit/library/n_local/efficient_su2.py | 2 +- qiskit/circuit/library/n_local/excitation_preserving.py | 2 +- qiskit/circuit/library/n_local/n_local.py | 8 ++++---- qiskit/circuit/library/n_local/real_amplitudes.py | 6 +++--- qiskit/transpiler/__init__.py | 2 +- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/qiskit/circuit/library/grover_operator.py b/qiskit/circuit/library/grover_operator.py index d55a59249a3d..8b6aeaf2db8c 100644 --- a/qiskit/circuit/library/grover_operator.py +++ b/qiskit/circuit/library/grover_operator.py @@ -118,7 +118,7 @@ def grover_operator( .. plot:: :include-source: - :context: + :context: close-figs oracle = QuantumCircuit(1) oracle.z(0) # the qubit state |1> is the good state @@ -133,7 +133,7 @@ def grover_operator( .. plot:: :include-source: - :context: + :context: close-figs oracle = QuantumCircuit(4) oracle.z(3) @@ -150,7 +150,7 @@ def grover_operator( .. plot:: :include-source: - :context: + :context: close-figs from qiskit.quantum_info import Statevector, DensityMatrix, Operator diff --git a/qiskit/circuit/library/n_local/efficient_su2.py b/qiskit/circuit/library/n_local/efficient_su2.py index c9589a22c9fa..954e74a3d296 100644 --- a/qiskit/circuit/library/n_local/efficient_su2.py +++ b/qiskit/circuit/library/n_local/efficient_su2.py @@ -85,7 +85,7 @@ def efficient_su2( .. plot:: :include-source: - :context: + :context: close-figs circuit = efficient_su2(4, su2_gates=["rx", "y"], entanglement="circular", reps=1) circuit.draw("mpl") diff --git a/qiskit/circuit/library/n_local/excitation_preserving.py b/qiskit/circuit/library/n_local/excitation_preserving.py index b2fd3f0cdc43..3623834f2b6d 100644 --- a/qiskit/circuit/library/n_local/excitation_preserving.py +++ b/qiskit/circuit/library/n_local/excitation_preserving.py @@ -71,7 +71,7 @@ def excitation_preserving( .. plot:: :include-source: - :context: + :context: close-figs from qiskit.circuit.library import excitation_preserving diff --git a/qiskit/circuit/library/n_local/n_local.py b/qiskit/circuit/library/n_local/n_local.py index 8c0b4d285086..a714a4699737 100644 --- a/qiskit/circuit/library/n_local/n_local.py +++ b/qiskit/circuit/library/n_local/n_local.py @@ -161,7 +161,7 @@ def n_local( .. plot:: :include-source: - :context: + :context: close-figs circuit = n_local(3, ["ry", "rz"], "cz", "full", reps=1, insert_barriers=True) circuit.draw("mpl") @@ -170,7 +170,7 @@ def n_local( .. plot:: :include-source: - :context: + :context: close-figs circuit = n_local(4, [], "cry", reps=2) circuit.draw("mpl") @@ -179,7 +179,7 @@ def n_local( .. plot:: :include-source: - :context: + :context: close-figs entangler_map = [[0, 1], [2, 0]] circuit = n_local(3, "x", "crx", entangler_map, reps=2) @@ -191,7 +191,7 @@ def n_local( .. plot: :include-source: - :context: + :context: close-figs def entanglement(layer_index): if layer_index % 2 == 0: diff --git a/qiskit/circuit/library/n_local/real_amplitudes.py b/qiskit/circuit/library/n_local/real_amplitudes.py index 572cc036ad73..79d85db5b603 100644 --- a/qiskit/circuit/library/n_local/real_amplitudes.py +++ b/qiskit/circuit/library/n_local/real_amplitudes.py @@ -78,21 +78,21 @@ def real_amplitudes( .. plot:: :include-source: - :context: + :context: close-figs ansatz = real_amplitudes(3, entanglement="full", reps=2) # it is the same unitary as above ansatz.draw("mpl") .. plot:: :include-source: - :context: + :context: close-figs ansatz = real_amplitudes(3, entanglement="linear", reps=2, insert_barriers=True) ansatz.draw("mpl") .. plot:: :include-source: - :context: + :context: close-figs ansatz = real_amplitudes(4, reps=2, entanglement=[[0,3], [0,2]], skip_unentangled_qubits=True) ansatz.draw("mpl") diff --git a/qiskit/transpiler/__init__.py b/qiskit/transpiler/__init__.py index 7924d4034aef..b5c64bc95a95 100644 --- a/qiskit/transpiler/__init__.py +++ b/qiskit/transpiler/__init__.py @@ -620,7 +620,7 @@ ['id', 'rz', 'sx', 'x', 'cx', 'measure', 'delay'] - .. plot: + .. plot:: :include-source: from qiskit.circuit import QuantumCircuit From 682cf3b7887d88d187164ec5dc723874c4e1c294 Mon Sep 17 00:00:00 2001 From: Hank Greenburg Date: Wed, 8 Jan 2025 10:04:34 -0800 Subject: [PATCH 2/3] build: update hashbrown to fix security vuln (#13622) --- Cargo.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 74ef042e64d3..133299e5a34a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -558,9 +558,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -581,7 +581,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown 0.15.0", + "hashbrown 0.15.2", "rayon", ] From 408741ca1ae4d291f6ae12d3f419ecd841ad8b39 Mon Sep 17 00:00:00 2001 From: aeddins-ibm <60495383+aeddins-ibm@users.noreply.github.com> Date: Wed, 8 Jan 2025 10:25:11 -0800 Subject: [PATCH 3/3] Fix phase of `pauli_list.insert(..., qubit=True)` for length-1 `pauli_list` (#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 #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 --------- Co-authored-by: Jake Lishman --- .../operators/symplectic/pauli_list.py | 16 ++++++++-------- ...paulilist-length1-phase-688d0e3a64ec9a9f.yaml | 6 ++++++ .../operators/symplectic/test_pauli_list.py | 9 +++++++++ 3 files changed, 23 insertions(+), 8 deletions(-) create mode 100644 releasenotes/notes/fix-paulilist-length1-phase-688d0e3a64ec9a9f.yaml diff --git a/qiskit/quantum_info/operators/symplectic/pauli_list.py b/qiskit/quantum_info/operators/symplectic/pauli_list.py index af2a0ed9407f..8e23b6f31a87 100644 --- a/qiskit/quantum_info/operators/symplectic/pauli_list.py +++ b/qiskit/quantum_info/operators/symplectic/pauli_list.py @@ -451,16 +451,14 @@ def insert(self, ind: int, value: PauliList, qubit: bool = False) -> PauliList: f"Index {ind} is greater than number of qubits" f" in the PauliList ({self.num_qubits})" ) - if len(value) == 1: - # Pad blocks to correct size - value_x = np.vstack(size * [value.x]) - value_z = np.vstack(size * [value.z]) - value_phase = np.vstack(size * [value.phase]) - elif len(value) == size: + if len(value) == size: # Blocks are already correct size value_x = value.x value_z = value.z - value_phase = value.phase + elif len(value) == 1: + # Pad blocks to correct size + value_x = np.vstack(size * [value.x]) + value_z = np.vstack(size * [value.z]) else: # Blocks are incorrect size raise QiskitError( @@ -471,7 +469,7 @@ def insert(self, ind: int, value: PauliList, qubit: bool = False) -> PauliList: # Build new array by blocks z = np.hstack([self.z[:, :ind], value_z, self.z[:, ind:]]) x = np.hstack([self.x[:, :ind], value_x, self.x[:, ind:]]) - phase = self.phase + value_phase + phase = self.phase + value.phase return PauliList.from_symplectic(z, x, phase) @@ -1131,6 +1129,8 @@ def from_symplectic( Returns: PauliList: the constructed PauliList. """ + if isinstance(phase, np.ndarray) and np.ndim(phase) > 1: + raise ValueError(f"phase should be at most 1D but has {np.ndim(phase)} dimensions.") base_z, base_x, base_phase = cls._from_array(z, x, phase) return cls(BasePauli(base_z, base_x, base_phase)) diff --git a/releasenotes/notes/fix-paulilist-length1-phase-688d0e3a64ec9a9f.yaml b/releasenotes/notes/fix-paulilist-length1-phase-688d0e3a64ec9a9f.yaml new file mode 100644 index 000000000000..a1a59708003c --- /dev/null +++ b/releasenotes/notes/fix-paulilist-length1-phase-688d0e3a64ec9a9f.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixed a bug that caused :meth:`.PauliList.insert` with ``qubit=True`` to produce a `phase` + attribute with the wrong shape when the original object was length 1. + Fixed `#13623 `__. diff --git a/test/python/quantum_info/operators/symplectic/test_pauli_list.py b/test/python/quantum_info/operators/symplectic/test_pauli_list.py index 8c96f63c4ddf..9abc473dc333 100644 --- a/test/python/quantum_info/operators/symplectic/test_pauli_list.py +++ b/test/python/quantum_info/operators/symplectic/test_pauli_list.py @@ -1560,6 +1560,15 @@ def test_insert(self): value1 = pauli.insert(1, insert) self.assertEqual(value1, target1) + # Insert single column to length-1 PauliList: + with self.subTest(msg="length-1, single-column, single-val"): + pauli = PauliList(["X"]) + insert = PauliList(["Y"]) + target0 = PauliList(["YX"]) + value0 = pauli.insert(1, insert, qubit=True) + self.assertEqual(value0, target0) + self.assertEqual(value0.phase.shape, (1,)) + # Insert single column pauli = PauliList(["X", "Y", "Z", "-iI"]) for i in ["I", "X", "Y", "Z", "iY"]: