Example #1
0
def _decompose_QAA(cmd):
    """ Decompose the Quantum Amplitude Apmplification algorithm as a gate. """
    eng = cmd.engine

    # System-qubit is the first qubit/qureg. Ancilla qubit is the second qubit
    system_qubits = cmd.qubits[0]
    qaa_ancilla = cmd.qubits[1]

    # The Oracle and the Algorithm
    Oracle = cmd.gate.oracle
    A = cmd.gate.algorithm

    # Apply the oracle to invert the amplitude of the good states, S_Chi
    Oracle(eng, system_qubits, qaa_ancilla)

    # Apply the inversion of the Algorithm,
    # the inversion of the aplitude of |0> and the Algorithm

    with Compute(eng):
        with Dagger(eng):
            A(eng, system_qubits)
        All(X) | system_qubits
    with Control(eng, system_qubits[0:-1]):
        Z | system_qubits[-1]
    with CustomUncompute(eng):
        All(X) | system_qubits
        A(eng, system_qubits)
    Ph(math.pi) | system_qubits[0]
Example #2
0
def add_constant_modN(eng, c, N, quint):
    """
    Adds a classical constant c to a quantum integer (qureg) quint modulo N
    using Draper addition and the construction from
    https://arxiv.org/abs/quant-ph/0205095.
    """
    assert (c < N and c >= 0)

    AddConstant(c) | quint

    with Compute(eng):
        SubConstant(N) | quint
        ancilla = eng.allocate_qubit()
        CNOT | (quint[-1], ancilla)
        with Control(eng, ancilla):
            AddConstant(N) | quint

    SubConstant(c) | quint

    with CustomUncompute(eng):
        X | quint[-1]
        CNOT | (quint[-1], ancilla)
        X | quint[-1]
        del ancilla

    AddConstant(c) | quint
Example #3
0
def add_constant_modN(eng, constant, N, quint):  # pylint: disable=invalid-name
    """
    Add a classical constant c to a quantum integer (qureg) quint modulo N using Draper addition.

    This function uses Draper addition and the construction from https://arxiv.org/abs/quant-ph/0205095.
    """
    if constant < 0 or constant > N:
        raise ValueError('Pre-condition failed: 0 <= constant < N')

    AddConstant(constant) | quint

    with Compute(eng):
        SubConstant(N) | quint
        ancilla = eng.allocate_qubit()
        CNOT | (quint[-1], ancilla)
        with Control(eng, ancilla):
            AddConstant(N) | quint

    SubConstant(constant) | quint

    with CustomUncompute(eng):
        X | quint[-1]
        CNOT | (quint[-1], ancilla)
        X | quint[-1]
        del ancilla

    AddConstant(constant) | quint
def _decompose_ucr(cmd, gate_class):
    """
    Decomposition for an uniformly controlled single qubit rotation gate.

    Follows decomposition in arXiv:quant-ph/0407010 section II and
    arXiv:quant-ph/0410066v2 Fig. 9a.

    For Ry and Rz it uses 2**len(ucontrol_qubits) CNOT and also
    2**len(ucontrol_qubits) single qubit rotations.

    Args:
        cmd: CommandObject to decompose.
        gate_class: Ry or Rz
    """
    eng = cmd.engine
    with Control(eng, cmd.control_qubits):
        if not (len(cmd.qubits) == 2 and len(cmd.qubits[1]) == 1):
            raise TypeError("Wrong number of qubits ")
        ucontrol_qubits = cmd.qubits[0]
        target_qubit = cmd.qubits[1]
        if not len(cmd.gate.angles) == 2**len(ucontrol_qubits):
            raise ValueError("Wrong len(angles).")
        if len(ucontrol_qubits) == 0:
            gate_class(cmd.gate.angles[0]) | target_qubit
            return
        angles1 = []
        angles2 = []
        for lower_bits in range(2**(len(ucontrol_qubits) - 1)):
            leading_0 = cmd.gate.angles[lower_bits]
            leading_1 = cmd.gate.angles[lower_bits +
                                        2**(len(ucontrol_qubits) - 1)]
            angles1.append((leading_0 + leading_1) / 2.0)
            angles2.append((leading_0 - leading_1) / 2.0)
        rightmost_cnot = {}
        for i in range(len(ucontrol_qubits) + 1):
            rightmost_cnot[i] = True
        _apply_ucr_n(
            angles=angles1,
            ucontrol_qubits=ucontrol_qubits[:-1],
            target_qubit=target_qubit,
            eng=eng,
            gate_class=gate_class,
            rightmost_cnot=rightmost_cnot,
        )
        # Very custom usage of Compute/CustomUncompute in the following.
        with Compute(cmd.engine):
            CNOT | (ucontrol_qubits[-1], target_qubit)
        _apply_ucr_n(
            angles=angles2,
            ucontrol_qubits=ucontrol_qubits[:-1],
            target_qubit=target_qubit,
            eng=eng,
            gate_class=gate_class,
            rightmost_cnot=rightmost_cnot,
        )
        with CustomUncompute(eng):
            CNOT | (ucontrol_qubits[-1], target_qubit)
def _apply_ucr_n(angles, ucontrol_qubits, target_qubit, eng, gate_class,
                 rightmost_cnot):  # pylint: disable=too-many-arguments
    if len(ucontrol_qubits) == 0:
        gate = gate_class(angles[0])
        if gate != gate_class(0):
            gate | target_qubit
    else:
        if rightmost_cnot[len(ucontrol_qubits)]:
            angles1 = []
            angles2 = []
            for lower_bits in range(2**(len(ucontrol_qubits) - 1)):
                leading_0 = angles[lower_bits]
                leading_1 = angles[lower_bits + 2**(len(ucontrol_qubits) - 1)]
                angles1.append((leading_0 + leading_1) / 2.0)
                angles2.append((leading_0 - leading_1) / 2.0)
        else:
            angles1 = []
            angles2 = []
            for lower_bits in range(2**(len(ucontrol_qubits) - 1)):
                leading_0 = angles[lower_bits]
                leading_1 = angles[lower_bits + 2**(len(ucontrol_qubits) - 1)]
                angles1.append((leading_0 - leading_1) / 2.0)
                angles2.append((leading_0 + leading_1) / 2.0)
        _apply_ucr_n(
            angles=angles1,
            ucontrol_qubits=ucontrol_qubits[:-1],
            target_qubit=target_qubit,
            eng=eng,
            gate_class=gate_class,
            rightmost_cnot=rightmost_cnot,
        )
        # Very custom usage of Compute/CustomUncompute in the following.
        if rightmost_cnot[len(ucontrol_qubits)]:
            with Compute(eng):
                CNOT | (ucontrol_qubits[-1], target_qubit)
        else:
            with CustomUncompute(eng):
                CNOT | (ucontrol_qubits[-1], target_qubit)
        _apply_ucr_n(
            angles=angles2,
            ucontrol_qubits=ucontrol_qubits[:-1],
            target_qubit=target_qubit,
            eng=eng,
            gate_class=gate_class,
            rightmost_cnot=rightmost_cnot,
        )
        # Next iteration on this level do the other cnot placement
        rightmost_cnot[len(
            ucontrol_qubits)] = not rightmost_cnot[len(ucontrol_qubits)]