C贸digo fuente para qiskit.circuit.library.n_local.pauli_two_design

# This code is part of Qiskit.
#
# (C) Copyright IBM 2017, 2020.
#
# This code is licensed under the Apache License, Version 2.0. You may
# obtain a copy of this license in the LICENSE.txt file in the root directory
# of this source tree or at http://www.apache.org/licenses/LICENSE-2.0.
#
# Any modifications or derivative works of this code must retain this
# copyright notice, and modified files need to carry a notice indicating
# that they have been altered from the originals.

"""The Random Pauli circuit class."""

from __future__ import annotations
import numpy as np

from qiskit.circuit import QuantumCircuit


from .two_local import TwoLocal


[documentos]class PauliTwoDesign(TwoLocal): r"""The Pauli Two-Design ansatz. This class implements a particular form of a 2-design circuit [1], which is frequently studied in quantum machine learning literature, such as e.g. the investigating of Barren plateaus in variational algorithms [2]. The circuit consists of alternating rotation and entanglement layers with an initial layer of :math:`\sqrt{H} = RY(\pi/4)` gates. The rotation layers contain single qubit Pauli rotations, where the axis is chosen uniformly at random to be X, Y or Z. The entanglement layers is compromised of pairwise CZ gates with a total depth of 2. For instance, the circuit could look like this (but note that choosing a different seed yields different Pauli rotations). .. parsed-literal:: 鈹屸攢鈹鈹鈹鈹鈹鈹鈹鈹鈹愨攲鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈻 鈹屸攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈻 鈹屸攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 q_0: 鈹 RY(蟺/4) 鈹溾敜 RZ(胃[0]) 鈹溾攢鈻犫攢鈹鈹鈹鈹鈻戔攢鈹 RY(胃[4]) 鈹溾攢鈻犫攢鈹鈹鈹鈹鈻戔攢鈹鈹 RZ(胃[8]) 鈹 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹も敎鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 q_1: 鈹 RY(蟺/4) 鈹溾敜 RZ(胃[1]) 鈹溾攢鈻犫攢鈹鈻犫攢鈹鈻戔攢鈹 RY(胃[5]) 鈹溾攢鈻犫攢鈹鈻犫攢鈹鈻戔攢鈹鈹 RX(胃[9]) 鈹 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹も敎鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹屸敶鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 q_2: 鈹 RY(蟺/4) 鈹溾敜 RX(胃[2]) 鈹溾攢鈻犫攢鈹鈻犫攢鈹鈻戔攢鈹 RY(胃[6]) 鈹溾攢鈻犫攢鈹鈻犫攢鈹鈻戔攢鈹 RX(胃[10]) 鈹 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹も敎鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈻 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 q_3: 鈹 RY(蟺/4) 鈹溾敜 RZ(胃[3]) 鈹溾攢鈻犫攢鈹鈹鈹鈹鈻戔攢鈹 RX(胃[7]) 鈹溾攢鈻犫攢鈹鈹鈹鈹鈻戔攢鈹 RY(胃[11]) 鈹 鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹樷敂鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈻 鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈻 鈹斺攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 Examples: .. plot:: :include-source: from qiskit.circuit.library import PauliTwoDesign circuit = PauliTwoDesign(4, reps=2, seed=5, insert_barriers=True) circuit.draw('mpl') References: [1]: Nakata et al., Unitary 2-designs from random X- and Z-diagonal unitaries. `arXiv:1502.07514 <https://arxiv.org/pdf/1502.07514.pdf>`_ [2]: McClean et al., Barren plateaus in quantum neural network training landscapes. `arXiv:1803.11173 <https://arxiv.org/pdf/1803.11173.pdf>`_ """ def __init__( self, num_qubits: int | None = None, reps: int = 3, seed: int | None = None, insert_barriers: bool = False, name: str = "PauliTwoDesign", ): from qiskit.circuit.library import RYGate # pylint: disable=cyclic-import # store a random number generator self._seed = seed self._rng = np.random.default_rng(seed) # store a dict to keep track of the random gates self._gates: dict[int, list[str]] = {} super().__init__( num_qubits, reps=reps, entanglement_blocks="cz", entanglement="pairwise", insert_barriers=insert_barriers, name=name, ) # set the initial layer self._prepended_blocks = [RYGate(np.pi / 4)] self._prepended_entanglement = ["linear"] def _invalidate(self): """Invalidate the circuit and reset the random number.""" self._rng = np.random.default_rng(self._seed) # reset number generator super()._invalidate() def _build_rotation_layer(self, circuit, param_iter, i): """Build a rotation layer.""" layer = QuantumCircuit(*self.qregs) qubits = range(self.num_qubits) # if no gates for this layer were generated, generate them if i not in self._gates.keys(): self._gates[i] = list(self._rng.choice(["rx", "ry", "rz"], self.num_qubits)) # if not enough gates exist, add more elif len(self._gates[i]) < self.num_qubits: num_missing = self.num_qubits - len(self._gates[i]) self._gates[i] += list(self._rng.choice(["rx", "ry", "rz"], num_missing)) for j in qubits: getattr(layer, self._gates[i][j])(next(param_iter), j) # add the layer to the circuit circuit.compose(layer, inplace=True) @property def num_parameters_settable(self) -> int: """Return the number of settable parameters. Returns: The number of possibly distinct parameters. """ return (self.reps + 1) * self.num_qubits