C贸digo fuente para qiskit.circuit.library.arithmetic.adders.cdkm_ripple_carry_adder

# This code is part of Qiskit.
# (C) Copyright IBM 2017, 2021.
# 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.

"""Compute the sum of two qubit registers using ripple-carry approach."""

from qiskit.circuit import QuantumCircuit, QuantumRegister, AncillaRegister

from .adder import Adder

[documentos]class CDKMRippleCarryAdder(Adder): r"""A ripple-carry circuit to perform in-place addition on two qubit registers. As an example, a ripple-carry adder circuit that performs addition on two 3-qubit sized registers with a carry-in bit (``kind="full"``) is as follows: .. parsed-literal:: 鈹屸攢鈹鈹鈹鈹鈹鈹 鈹屸攢鈹鈹鈹鈹鈹鈹 cin_0: 鈹2 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹2 鈹 鈹 鈹傗攲鈹鈹鈹鈹鈹鈹鈹 鈹屸攢鈹鈹鈹鈹鈹鈹愨攤 鈹 a_0: 鈹0 鈹溾敜2 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹2 鈹溾敜0 鈹 鈹 鈹傗攤 鈹傗攲鈹鈹鈹鈹鈹鈹鈹 鈹屸攢鈹鈹鈹鈹鈹鈹愨攤 鈹傗攤 鈹 a_1: 鈹 MAJ 鈹溾敜0 鈹溾敜2 鈹溾攢鈹鈹鈹鈹鈹2 鈹溾敜0 鈹溾敜 UMA 鈹 鈹 鈹傗攤 鈹傗攤 鈹 鈹 鈹傗攤 鈹傗攤 鈹 a_2: 鈹 鈹溾敜 MAJ 鈹溾敜0 鈹溾攢鈹鈻犫攢鈹鈹0 鈹溾敜 UMA 鈹溾敜 鈹 鈹 鈹傗攤 鈹傗攤 鈹 鈹 鈹 鈹傗攤 鈹傗攤 鈹 b_0: 鈹1 鈹溾敜 鈹溾敜 MAJ 鈹溾攢鈹鈹尖攢鈹鈹 UMA 鈹溾敜 鈹溾敜1 鈹 鈹斺攢鈹鈹鈹鈹鈹鈹樷攤 鈹傗攤 鈹 鈹 鈹 鈹傗攤 鈹傗敂鈹鈹鈹鈹鈹鈹鈹 b_1: 鈹鈹鈹鈹鈹鈹鈹鈹鈹1 鈹溾敜 鈹溾攢鈹鈹尖攢鈹鈹 鈹溾敜1 鈹溾攢鈹鈹鈹鈹鈹鈹鈹 鈹斺攢鈹鈹鈹鈹鈹鈹樷攤 鈹 鈹 鈹 鈹傗敂鈹鈹鈹鈹鈹鈹鈹 b_2: 鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹1 鈹溾攢鈹鈹尖攢鈹鈹1 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹斺攢鈹鈹鈹鈹鈹鈹樷攲鈹鈹粹攢鈹愨敂鈹鈹鈹鈹鈹鈹鈹 cout_0: 鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 X 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹 鈹斺攢鈹鈹鈹 Here *MAJ* and *UMA* gates correspond to the gates introduced in [1]. Note that in this implementation the input register qubits are ordered as all qubits from the first input register, followed by all qubits from the second input register. Two different kinds of adders are supported. By setting the ``kind`` argument, you can also choose a half-adder, which doesn't have a carry-in, and a fixed-sized-adder, which has neither carry-in nor carry-out, and thus acts on fixed register sizes. Unlike the full-adder, these circuits need one additional helper qubit. The circuit diagram for the fixed-point adder (``kind="fixed"``) on 3-qubit sized inputs is .. parsed-literal:: 鈹屸攢鈹鈹鈹鈹鈹鈹愨攲鈹鈹鈹鈹鈹鈹鈹 鈹屸攢鈹鈹鈹鈹鈹鈹愨攲鈹鈹鈹鈹鈹鈹鈹 a_0: 鈹0 鈹溾敜2 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹2 鈹溾敜0 鈹 鈹 鈹傗攤 鈹傗攲鈹鈹鈹鈹鈹鈹鈹愨攲鈹鈹鈹鈹鈹鈹鈹愨攤 鈹傗攤 鈹 a_1: 鈹 鈹溾敜0 鈹溾敜2 鈹溾敜2 鈹溾敜0 鈹溾敜 鈹 鈹 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹 a_2: 鈹 鈹溾敜 MAJ 鈹溾敜0 鈹溾敜0 鈹溾敜 UMA 鈹溾敜 鈹 鈹 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹 b_0: 鈹1 MAJ 鈹溾敜 鈹溾敜 MAJ 鈹溾敜 UMA 鈹溾敜 鈹溾敜1 UMA 鈹 鈹 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹傗攤 鈹 b_1: 鈹 鈹溾敜1 鈹溾敜 鈹溾敜 鈹溾敜1 鈹溾敜 鈹 鈹 鈹傗敂鈹鈹鈹鈹鈹鈹鈹樷攤 鈹傗攤 鈹傗敂鈹鈹鈹鈹鈹鈹鈹樷攤 鈹 b_2: 鈹 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹1 鈹溾敜1 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹 鈹 鈹 鈹 鈹斺攢鈹鈹鈹鈹鈹鈹樷敂鈹鈹鈹鈹鈹鈹鈹 鈹 鈹 help_0: 鈹2 鈹溾攢鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹鈹2 鈹 鈹斺攢鈹鈹鈹鈹鈹鈹 鈹斺攢鈹鈹鈹鈹鈹鈹 It has one less qubit than the full-adder since it doesn't have the carry-out, but uses a helper qubit instead of the carry-in, so it only has one less qubit, not two. **References:** [1] Cuccaro et al., A new quantum ripple-carry addition circuit, 2004. `arXiv:quant-ph/0410184 <https://arxiv.org/pdf/quant-ph/0410184.pdf>`_ [2] Vedral et al., Quantum Networks for Elementary Arithmetic Operations, 1995. `arXiv:quant-ph/9511018 <https://arxiv.org/pdf/quant-ph/9511018.pdf>`_ """ def __init__( self, num_state_qubits: int, kind: str = "full", name: str = "CDKMRippleCarryAdder" ) -> None: r""" Args: num_state_qubits: The number of qubits in either input register for state :math:`|a\rangle` or :math:`|b\rangle`. The two input registers must have the same number of qubits. kind: The kind of adder, can be ``'full'`` for a full adder, ``'half'`` for a half adder, or ``'fixed'`` for a fixed-sized adder. A full adder includes both carry-in and carry-out, a half only carry-out, and a fixed-sized adder neither carry-in nor carry-out. name: The name of the circuit object. Raises: ValueError: If ``num_state_qubits`` is lower than 1. """ if num_state_qubits < 1: raise ValueError("The number of qubits must be at least 1.") super().__init__(num_state_qubits, name=name) if kind == "full": qr_c = QuantumRegister(1, name="cin") self.add_register(qr_c) else: qr_c = AncillaRegister(1, name="help") qr_a = QuantumRegister(num_state_qubits, name="a") qr_b = QuantumRegister(num_state_qubits, name="b") self.add_register(qr_a, qr_b) if kind in ["full", "half"]: qr_z = QuantumRegister(1, name="cout") self.add_register(qr_z) if kind != "full": self.add_register(qr_c) # build carry circuit for majority of 3 bits in-place # corresponds to MAJ gate in [1] qc_maj = QuantumCircuit(3, name="MAJ") qc_maj.cx(0, 1) qc_maj.cx(0, 2) qc_maj.ccx(2, 1, 0) maj_gate = qc_maj.to_gate() # build circuit for reversing carry operation # corresponds to UMA gate in [1] qc_uma = QuantumCircuit(3, name="UMA") qc_uma.ccx(2, 1, 0) qc_uma.cx(0, 2) qc_uma.cx(2, 1) uma_gate = qc_uma.to_gate() circuit = QuantumCircuit(*self.qregs, name=name) # build ripple-carry adder circuit circuit.append(maj_gate, [qr_a[0], qr_b[0], qr_c[0]]) for i in range(num_state_qubits - 1): circuit.append(maj_gate, [qr_a[i + 1], qr_b[i + 1], qr_a[i]]) if kind in ["full", "half"]: circuit.cx(qr_a[-1], qr_z[0]) for i in reversed(range(num_state_qubits - 1)): circuit.append(uma_gate, [qr_a[i + 1], qr_b[i + 1], qr_a[i]]) circuit.append(uma_gate, [qr_a[0], qr_b[0], qr_c[0]]) self.append(circuit.to_gate(), self.qubits)