qpe_toolbox.circuit.parametrized_circuits ========================================= .. py:module:: qpe_toolbox.circuit.parametrized_circuits Functions --------- .. autoapisummary:: qpe_toolbox.circuit.parametrized_circuits.one_qubit_layer qpe_toolbox.circuit.parametrized_circuits.two_qubit_nn_layer qpe_toolbox.circuit.parametrized_circuits.two_qubit_rand_layer qpe_toolbox.circuit.parametrized_circuits.generate_brickwall_circuit qpe_toolbox.circuit.parametrized_circuits.generate_rand_circuit qpe_toolbox.circuit.parametrized_circuits.ansatz_circuit qpe_toolbox.circuit.parametrized_circuits.ansatz_circuit_su4 qpe_toolbox.circuit.parametrized_circuits.ansatz_circuit_sym Module Contents --------------- .. py:function:: one_qubit_layer(circ, gate_label, *, param_scaling=1.0, gate_round=None, parametrize=False, rng=None) Apply a single-body gate layer to all qubits of a ``quimb`` :quimb-api:`Circuit`. This function applies the same single-qubit gate to every qubit in the circuit at a specified circuit round. If the gate is parametrized, random parameters are generated using the provided random number generator and shared across all qubits in the layer. :param circ: The quimb circuit to which the layer is applied. :type circ: :quimb-api:`Circuit` :param gate_label: Label identifying the single-body gate to apply (e.g. ``"RX"``). The label must be compatible with :quimb-api:`Circuit.apply_gate`. :type gate_label: str :param param_scaling: Scaling factor for randomly initialized parameters. :type param_scaling: float, default ``1.0`` :param gate_round: Circuit layer at which the gates are applied. :type gate_round: int or None, default ``None`` :param parametrize: Activate the possibility of using the layer as a parametrized Ansatz on some variational scheme. :type parametrize: bool, default ``False`` :param rng: Random number generator for gate parameters. If None a new Generator is initialized. :type rng: :numpy-random:`numpy.random.Generator `, default ``None`` .. rubric:: Notes - The same set of parameters is used for all qubits in the layer. .. py:function:: two_qubit_nn_layer(circ, start, gate_label, *, param_scaling=1.0, gate_round=None, parametrize=False, reverse=False, rng=None) Apply a nearest-neighbor two-body entangling layer to a ``quimb`` :quimb-api:`Circuit`. This function applies a two-qubit entangling gate between nearest neighbors in a brickwork pattern. The starting qubit index determines the parity of the layer. :param circ: The ``quimb`` circuit to which the layer is applied. :type circ: :quimb-api:`Circuit` :param start: Starting qubit index for the nearest-neighbor pattern (typically ``0`` or ``1``). Allows for defining even (0) and odd (1) layers. :type start: int :param gate_label: Label identifying the two-body entangling gate (e.g. ``"CNOT"``). :type gate_label: str :param param_scaling: Scaling factor for randomly initialized parameters. :type param_scaling: float, default ``1.0`` :param gate_round: Gate round index used to tag gates. :type gate_round: int or None, default ``None`` :param parametrize: Activate the possibility of using the layer as a parametrized Ansatz on some variational scheme. :type parametrize: bool, default ``False`` :param reverse: Possibility to invert direction of the layer. Relevant when using controlled gates. :type reverse: bool, default ``False`` :param rng: Random number generator for gate parameters. If None a new Generator is initialized. :type rng: :numpy-random:`numpy.random.Generator `, default ``None`` .. rubric:: Notes - The same parameters are reused for all entangling gates in the layer. - Gates are applied between qubits ``(i, i+1)`` for ``i = start, start+2,`` ... .. py:function:: two_qubit_rand_layer(circ, gate_label, gate_range, gate_prob, *, rng=None, param_scaling=1.0, gate_round=None, parametrize=True, reverse=False) Apply a random two-body entangling layer to a ``quimb`` :quimb-api:`Circuit`. This function applies two-qubit entangling gates between randomly chosen qubit pairs. For each qubit, a partner qubit is selected within a given range, and the entangling gate is applied with a specified probability. :param circ: The quimb circuit to which the layer is applied. :type circ: :quimb-api:`Circuit` :param gate_label: Label identifying the two-body entangling gate. :type gate_label: str :param gate_range: Sets a maximum interaction range ``(gate_range+1)`` for two-body entangling gates, measured in qubit index separation. :type gate_range: int :param gate_prob: Probability threshold controlling whether an entangling gate is applied. A gate is applied if ``rng_prob.random() <= gate_prob``. :type gate_prob: float :param rng: Random number generator for ``gate_range`` and ``gate_prob``. If None a new Generator is initialized. :type rng: :numpy-random:`numpy.random.Generator `, default ``None`` :param param_scaling: Scaling factor for randomly initialized parameters. :type param_scaling: float, default ``1.0`` :param gate_round: Gate round index used to tag gates. :type gate_round: int or None, default ``None`` :param parametrize: Activate the possibility of using the layer as a parametrized Ansatz on some variational scheme. :type parametrize: bool, default ``False`` :param reverse: Possibility to invert direction of the layer. Relevant when using controlled gates. :type reverse: bool, default ``False`` .. rubric:: Notes - The same parameters are reused for all entangling gates in the layer. - Entangling partners are chosen as ``j = i + 1 + Δ``, where ``Δ`` is sampled uniformly from ``[0, gate_range)``. .. py:function:: generate_brickwall_circuit(n_qubits, depth, one_qubit_gate_label, two_qubit_gate_label, *, start_ent=False, param_scaling=1.0, rng=None) Generate a brickwall-structured ``quimb`` :quimb-api:`Circuit`. This function constructs a quantum circuit composed of alternating single-body layers and nearest-neighbor two-body entangling layers arranged in a brickwall pattern. Each circuit layer is assigned a distinct circuit round. Circuit structure (one layer, ``start_ent=False``):: q0 ──[]───●─────── │ q1 ──[]───●───●─── │ q2 ──[]───●───●─── | q3 ──[]───●───●─── | q4 ──[]───●───●─── | q5 ──[]───●─────── <─────────────> first layer where:: [] = single-body gate ●─● = nearest-neighbor entangling gate :param n_qubits: Number of qubits in the circuit. :type n_qubits: int :param depth: Number of circuit layers (identified here with the gate rounds). :type depth: int :param one_qubit_gate_label: Label identifying the single-body gate. :type one_qubit_gate_label: str :param two_qubit_gate_label: Label identifying the two-body entangling gate. :type two_qubit_gate_label: str :param start_ent: If ``True``, each layer starts with the brickwall entangling layer. Otherwise (default ``False``), the single-body layer is applied first. :type start_ent: bool, optional :param param_scaling: Scaling factor for randomly initialized parameters. :type param_scaling: float, default ``1.0`` :param rng: Random number generator used to generate gate parameters. If ``None``, a default generator is created. :type rng: :numpy-random:`numpy.random.Generator `, optional :returns: **circ** -- The generated brickwall quantum circuit. :rtype: :quimb-api:`Circuit` :raises ValueError: If ``one_qubit_gate_label`` does not correspond to a valid single-body gate, or if ``two_qubit_gate_label`` is not a valid two-body gate. .. rubric:: Notes - Separate random number generators are used for single-body and two-body gate parameters to ensure reproducibility and decoupled randomness. - The same gate parameters are reused across all gates within a given layer. .. py:function:: generate_rand_circuit(n_qubits, depth, one_qubit_gate_label, two_qubit_gate_label, two_qubit_gate_range, two_qubit_gate_prob, *, start_ent=False, param_scaling=1.0, rng=None) Generate a random entangling ``quimb`` :quimb-api:`Circuit`. This function constructs a quantum circuit consisting of alternating single-body layers and randomly generated two-body entangling layers. Entangling gates are applied probabilistically between qubits within a finite interaction range. Circuit structure (one layer, ``start_ent=False``):: q0 ──[]───●─────── │ q1 ──[]───●───●─── │ q2 ──[]───●───|─── ^ | | | q3 ──[]───|───●─── | | | two_qubit_gate_range=2 q4 ──[]───|─────── | | | q5 ──[]───●─────── v <─────────────> first layer where:: [] = single-body gate ●─● = entangling gate :param n_qubits: Number of qubits in the circuit. :type n_qubits: int :param depth: Number of circuit layers (rounds). :type depth: int :param one_qubit_gate_label: Label identifying the single-body gate applied at each layer. :type one_qubit_gate_label: str :param two_qubit_gate_label: Label identifying the two-body entangling gate. :type two_qubit_gate_label: str :param two_qubit_gate_range: Sets a maximum interaction range ``(two_qubit_gate_range+1)`` for two-body entangling gates, measured in qubit index separation. :type two_qubit_gate_range: int :param two_qubit_gate_prob: Probability threshold controlling the application of an entangling gate for a given qubit. :type two_qubit_gate_prob: float :param start_ent: If ``True``, each layer starts with the random entangling layer. Otherwise (default ``False``), the single-body layer is applied first. :type start_ent: bool, optional :param param_scaling: Scaling factor for randomly initialized parameters. :type param_scaling: float, default ``1.0`` :param rng: Random number generator to generate gate parameters. If ``None``, a default generator is created. :type rng: :numpy-random:`numpy.random.Generator `, optional :returns: **circ** -- The generated random entangling quantum circuit. :rtype: :quimb-api:`Circuit` :raises ValueError: If ``one_qubit_gate_label`` does not correspond to a valid single-body gate, or if ``two_qubit_gate_label`` is not a valid two-body gate. .. rubric:: Notes - Gate parameters are shared across all gates within the same layer. .. py:function:: ansatz_circuit(n_qubits, depth, *, gate_round=0, param_scaling=1.0, rng=None) Construct an ansatz circuit of single qubit and entangling layers. :param n_qubits: Number of qubits in the circuit. :type n_qubits: int :param depth: Number of repeated ansatz layers. :type depth: int :param gate_round: Starting gate round index. :type gate_round: int, default ``0`` :param param_scaling: Scaling factor for random parameter initialization. :type param_scaling: float, default ``1.0`` :param rng: Random number generator to generate gate parameters. If ``None``, a default generator is created. :type rng: :numpy-random:`numpy.random.Generator `, optional :returns: Parametrized ansatz circuit. :rtype: :quimb-api:`Circuit` .. py:function:: ansatz_circuit_su4(n_qubits, depth, *, gate_round=0, param_scaling=1.0, rng=None) Construct an ansatz circuit using SU(4) two-qubit gates. :param n_qubits: Number of qubits in the cricuit. :type n_qubits: int :param depth: Number of circuit layers. :type depth: int :param gate_round: Starting gate round index. :type gate_round: int, default ``0`` :param param_scaling: Scaling factor for random parameter initialization. :type param_scaling: float, default ``1.0`` :param rng: Random number generator to generate gate parameters. If ``None``, a default generator is created. :type rng: :numpy-random:`numpy.random.Generator `, optional :returns: Parametrized SU(4) ansatz circuit. :rtype: :quimb-api:`Circuit` .. py:function:: ansatz_circuit_sym(n_qubits, depth, *, gate_round=0, param_scaling=1.0, rng=None) Construct a U(1)-symmetry-preserving ansatz circuit. This ansatz uses custom XX+YY gates, RZZ entanglers, and single-qubit Z rotations. :param n_qubits: Number of qubits in the circuit. :type n_qubits: int :param depth: Number of ansatz layers. :type depth: int :param gate_round: Starting gate round index. :type gate_round: int, default ``0`` :param param_scaling: Scaling factor for random parameter initialization. :type param_scaling: float, default ``1.0`` :param rng: Random number generator to generate gate parameters. If ``None``, a default generator is created. :type rng: :numpy-random:`numpy.random.Generator `, optional :returns: Parametrized U(1)-symmetric ansatz circuit. :rtype: :quimb-api:`Circuit`