Пример #1
0
def run_grover(eng, n, Ox):
    # start in uniform superposition
    x = eng.allocate_qureg(n)
    All(H) | x

    # the auxiliary indicator qbit, prepare it as '|->'
    y = eng.allocate_qubit()
    X | y
    H | y

    # number of iterations we have to run:
    ITER = int(math.pi / 4.0 * math.sqrt(1 << n))
    with Loop(eng, ITER):
        # oracle adds a (-1)-phase to the solution(s)
        Ox(eng, x, y)

        # reflection across uniform superposition
        with Compute(eng):
            All(H) | x
            All(X) | x

        with Control(eng, x[:-1]):  # Z == H-CNOT(x[-1])-H ??
            Z | x[-1]

        Uncompute(eng)

    All(Measure) | x
    Measure | y

    eng.flush()
    return ''.join([str(int(q)) for q in x])
Пример #2
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
Пример #3
0
def lcu_oaa(eng,
            list_of_unitaries,
            coefts,
            ctrl,
            sys,
            ctrl_dim,
            sys_dim,
            rounds=1):
    phi = -1 * math.pi
    for i in range(0, rounds):
        cond_phase(eng, ctrl, sys, phi)
        with Dagger(eng):
            lcu_basic(eng, list_of_unitaries, coefts, ctrl, sys, ctrl_dim,
                      sys_dim)
        size = pow(2, ctrl_dim)
        for l in range(1, size):  # -R flips sign of everything except 00..0
            temp = np.binary_repr(i)
            temp = temp.zfill(ctrl_dim)  # pad with zeros for fixed length bin
        with Compute(eng):
            for j in range(0, ctrl_dim):
                if (int(temp[j]) == 0):
                    X | ctrl[j]
        with Control(eng, ctrl):
            Ph(phi) | sys[0]  # flip sign using any one sys qubit
        Uncompute(eng)
        lcu_basic(eng, list_of_unitaries, coefts, ctrl, sys, ctrl_dim, sys_dim)
        print("Amplitudes of ctrl+sys state after {} rounds of OAA:\n".format(
            int(i) + 1))
        print_amplitudes(eng, ctrl + sys, ctrl_dim + sys_dim)
Пример #4
0
def lcu_controlled_unitary(eng, list_of_U, coefts, ctrl, sys, sys_dim):
    size = len(list_of_U)
    if not size:
        print('Error in lcu - I got an empty list of unitaries!')
    ctrl_dim = math.ceil(math.log(size, 2))

    for i in range(0, size):
        temp = np.binary_repr(i)
        temp = temp.zfill(ctrl_dim)  # pad with zeros for fixed length bin

        with Compute(eng):
            for j in range(0, ctrl_dim):
                if (int(temp[j]) == 0):
                    X | ctrl[j]

        # if unitaries passed are qubitoperator, directly apply them, no unpacking required
        if isinstance(list_of_U[0], QubitOperator):
            with Control(eng, ctrl):
                list_of_U[i] | sys
            Uncompute(eng)

        else:
            with Control(eng, ctrl):
                if (isinstance(coefts[i], complex)):  # can be i, or -1
                    Ph(0.5 * math.pi) | sys[j]  # apply global phase i
                    if (np.sign(-1j * coefts[i]) < 0):
                        Ph(math.pi) | sys[j]  # global phase is actually -i
                elif (np.sign(coefts[i]) < 0):
                    Ph(math.pi) | sys[j]  # apply global phase -1
                for j in range(0, sys_dim):
                    if (list_of_U[i][j] == I):
                        continue
                    list_of_U[i][j] | sys[j]
            Uncompute(eng)
Пример #5
0
def ExecuteGrover(engine, n, oracle):
    x = engine.allocate_qureg(n)

    All(H) | x

    num_it = int(math.pi/4.*math.sqrt(1 << n))

    oracle_out = engine.allocate_qubit()
    X | oracle_out
    H | oracle_out

    with Loop(engine, num_it):
        oracle(engine, x, oracle_out)
        with Compute(engine):
            All(H) | x
            All(X) | x

        with Control(engine, x[0:-1]):
            Z | x[-1]

        Uncompute(engine)

    All(Measure) | x
    Measure | oracle_out

    engine.flush()
    return [int(qubit) for qubit in x]
Пример #6
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
Пример #7
0
def _decompose_CnU(cmd):  # pylint: disable=invalid-name
    """
    Decompose a multi-controlled gate U with n control qubits into a single- controlled U.

    It uses (n-1) work qubits and 2 * (n-1) Toffoli gates for general U and (n-2) work qubits and 2n - 3 Toffoli gates
    if U is an X-gate.
    """
    eng = cmd.engine
    qubits = cmd.qubits
    ctrl_qureg = cmd.control_qubits
    gate = cmd.gate
    n_controls = get_control_count(cmd)

    # specialized for X-gate
    if gate == XGate() and n_controls > 2:
        n_controls -= 1
    ancilla_qureg = eng.allocate_qureg(n_controls - 1)

    with Compute(eng):
        Toffoli | (ctrl_qureg[0], ctrl_qureg[1], ancilla_qureg[0])
        for ctrl_index in range(2, n_controls):
            Toffoli | (
                ctrl_qureg[ctrl_index],
                ancilla_qureg[ctrl_index - 2],
                ancilla_qureg[ctrl_index - 1],
            )
    ctrls = [ancilla_qureg[-1]]

    # specialized for X-gate
    if gate == XGate() and get_control_count(cmd) > 2:
        ctrls += [ctrl_qureg[-1]]
    with Control(eng, ctrls):
        gate | qubits

    Uncompute(eng)
Пример #8
0
def test_quantummultiplication(eng):
    qureg_a = eng.allocate_qureg(3)
    qureg_b = eng.allocate_qureg(3)
    qureg_c = eng.allocate_qureg(7)

    init(eng, qureg_a, 7)
    init(eng, qureg_b, 3)

    MultiplyQuantum | (qureg_a, qureg_b, qureg_c)

    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 1], qureg_a))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0], qureg_b))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 0, 1, 0, 1, 0, 0], qureg_c))

    All(Measure) | qureg_a
    All(Measure) | qureg_b
    All(Measure) | qureg_c

    init(eng, qureg_a, 7)
    init(eng, qureg_b, 3)
    init(eng, qureg_c, 21)

    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 0, 0, 0, 0, 0, 0], qureg_c))
    init(eng, qureg_a, 2)
    init(eng, qureg_b, 3)

    with Compute(eng):
        MultiplyQuantum | (qureg_a, qureg_b, qureg_c)
    Uncompute(eng)

    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 1, 0], qureg_a))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0], qureg_b))
    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 0, 0, 0, 0, 0, 0], qureg_c))
Пример #9
0
def test_quantumdivision(eng):
    qureg_a = eng.allocate_qureg(4)
    qureg_b = eng.allocate_qureg(4)
    qureg_c = eng.allocate_qureg(4)

    init(eng, qureg_a, 10)
    init(eng, qureg_c, 3)

    DivideQuantum | (qureg_a, qureg_b, qureg_c)

    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 0, 0, 0], qureg_a))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0, 0], qureg_b))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0, 0], qureg_c))

    All(Measure) | qureg_a
    All(Measure) | qureg_b
    All(Measure) | qureg_c

    init(eng, qureg_a, 1)  # reset
    init(eng, qureg_b, 3)  # reset

    init(eng, qureg_a, 11)

    with Compute(eng):
        DivideQuantum | (qureg_a, qureg_b, qureg_c)
    Uncompute(eng)

    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0, 1], qureg_a))
    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 0, 0, 0], qureg_b))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 0, 0], qureg_c))

    All(Measure) | qureg_a
    All(Measure) | qureg_b
    All(Measure) | qureg_c
Пример #10
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]
Пример #11
0
def test_control():
    backend = DummyEngine(save_commands=True)
    eng = MainEngine(backend=backend, engine_list=[DummyEngine()])
    qureg = eng.allocate_qureg(2)
    with _control.Control(eng, qureg):
        qubit = eng.allocate_qubit()
        with Compute(eng):
            Rx(0.5) | qubit
        H | qubit
        Uncompute(eng)
    with _control.Control(eng, qureg[0]):
        H | qubit
    eng.flush()
    assert len(backend.received_commands) == 8
    assert len(backend.received_commands[0].control_qubits) == 0
    assert len(backend.received_commands[1].control_qubits) == 0
    assert len(backend.received_commands[2].control_qubits) == 0
    assert len(backend.received_commands[3].control_qubits) == 0
    assert len(backend.received_commands[4].control_qubits) == 2
    assert len(backend.received_commands[5].control_qubits) == 0
    assert len(backend.received_commands[6].control_qubits) == 1
    assert len(backend.received_commands[7].control_qubits) == 0
    assert backend.received_commands[4].control_qubits[0].id == qureg[0].id
    assert backend.received_commands[4].control_qubits[1].id == qureg[1].id
    assert backend.received_commands[6].control_qubits[0].id == qureg[0].id
Пример #12
0
def _decompose_time_evolution_individual_terms(cmd):
    """
    Implements a TimeEvolution gate with a hamiltonian having only one term.

    To implement exp(-i * t * hamiltonian), where the hamiltonian is only one
    term, e.g., hamiltonian = X0 x Y1 X Z2, we first perform local
    transformations to in order that all Pauli operators in the hamiltonian
    are Z. We then implement  exp(-i * t * (Z1 x Z2 x Z3) and transform the
    basis back to the original. For more details see, e.g.,

    James D. Whitfield, Jacob Biamonte & Aspuru-Guzik
    Simulation of electronic structure Hamiltonians using quantum computers,
    Molecular Physics, 109:5, 735-750 (2011).

    or

    Nielsen and Chuang, Quantum Computation and Information.
    """
    assert len(cmd.qubits) == 1
    qureg = cmd.qubits[0]
    eng = cmd.engine
    time = cmd.gate.time
    hamiltonian = cmd.gate.hamiltonian
    assert len(hamiltonian.terms) == 1
    term = list(hamiltonian.terms)[0]
    coefficient = hamiltonian.terms[term]
    check_indices = set()

    # Check that hamiltonian is not identity term,
    # Previous __or__ operator should have apply a global phase instead:
    assert not term == ()

    # hamiltonian has only a single local operator
    if len(term) == 1:
        with Control(eng, cmd.control_qubits):
            if term[0][1] == 'X':
                Rx(time * coefficient * 2.) | qureg[term[0][0]]
            elif term[0][1] == 'Y':
                Ry(time * coefficient * 2.) | qureg[term[0][0]]
            else:
                Rz(time * coefficient * 2.) | qureg[term[0][0]]
    # hamiltonian has more than one local operator
    else:
        with Control(eng, cmd.control_qubits):
            with Compute(eng):
                # Apply local basis rotations
                for index, action in term:
                    check_indices.add(index)
                    if action == 'X':
                        H | qureg[index]
                    elif action == 'Y':
                        Rx(math.pi / 2.) | qureg[index]
                # Check that qureg had exactly as many qubits as indices:
                assert check_indices == set((range(len(qureg))))
                # Compute parity
                for i in range(len(qureg) - 1):
                    CNOT | (qureg[i], qureg[i + 1])
            Rz(time * coefficient * 2.) | qureg[-1]
            # Uncompute parity and basis change
            Uncompute(eng)
def oraculo(eng, x, ctrl):
    with Compute(eng):
        All(NOT) | x[1::2]
    with Control(eng, x):
        NOT | ctrl
    Uncompute(eng)
    return
Пример #14
0
def simple_oracle(eng, system_q, control):
    # This oracle selects the state |1010101> as the one marked
    with Compute(eng):
        All(X) | system_q[1::2]
    with Control(eng, system_q):
        X | control
    Uncompute(eng)
Пример #15
0
def test_inverse_addition_with_control_carry(eng):
    qunum_a = eng.allocate_qureg(4)
    qunum_b = eng.allocate_qureg(4)

    control_bit = eng.allocate_qubit()
    qunum_c = eng.allocate_qureg(2)

    X | qunum_a[1]
    All(X) | qunum_b[0:4]
    X | control_bit
    with Compute(eng):
        with Control(eng, control_bit):
            AddQuantum | (qunum_a, qunum_b, qunum_c)
    Uncompute(eng)

    eng.flush()

    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 1, 0, 0], qunum_a))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1, 1, 1, 1], qunum_b))
    assert 1.0 == pytest.approx(eng.backend.get_probability([1], control_bit))
    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 0], qunum_c))

    All(Measure) | qunum_a
    All(Measure) | qunum_b
    Measure | control_bit
    All(Measure) | qunum_c
Пример #16
0
def _decompose_ccy(cmd):
    """ Decompose CNOT gates. """
    ctrl = cmd.control_qubits
    eng = cmd.engine
    with Compute(eng):
        S | cmd.qubits[0]
    Toffoli | (ctrl[0], ctrl[1], cmd.qubits[0][0])
    Uncompute(eng)
Пример #17
0
def _decompose_cz(cmd):
    """ Decompose CNOT gates. """
    ctrl = cmd.control_qubits
    eng = cmd.engine
    with Compute(eng):
        H | cmd.qubits[0]
    CNOT | (ctrl[0], cmd.qubits[0][0])
    Uncompute(eng)
Пример #18
0
def qnn(eng):

    with Compute(eng):
        qbn(eng)

    oracle(eng)

    Uncompute(eng)
Пример #19
0
def _decompose_swap(cmd):
    """ Decompose (controlled) swap gates. """
    ctrl = cmd.control_qubits
    eng = cmd.engine
    with Compute(eng):
        CNOT | (cmd.qubits[0], cmd.qubits[1])
    with Control(eng, ctrl):
        CNOT | (cmd.qubits[1], cmd.qubits[0])
    Uncompute(eng)
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)
Пример #21
0
def Quantum_Adder(state_a, state_b, eng=engine):
    '''
    parameters
        state_a:(qureg)
        state_b:(qureg)
    '''
    with Compute(eng):
        quantum_fourier_transform(state_a)
    ancillary_add(state_a, state_b)
    Uncompute(eng)
Пример #22
0
def _decompose_rx(cmd):
    """Decompose the Rx gate."""
    qubit = cmd.qubits[0]
    eng = cmd.engine
    angle = cmd.gate.angle

    with Control(eng, cmd.control_qubits):
        with Compute(eng):
            H | qubit
        Rz(angle) | qubit
        Uncompute(eng)
Пример #23
0
def add_minus_sign(eng):

    with Compute(eng):
        quanutm_phase_estimation(eng)

    X | phase_reg[2]
    ControlledGate(
        NOT, 3) | (phase_reg[0], phase_reg[1], phase_reg[2], ancilla_qubit)
    X | phase_reg[2]

    Uncompute(eng)
Пример #24
0
def _decompose_ry(cmd):
    """ Decompose the Ry gate."""
    qubit = cmd.qubits[0]
    eng = cmd.engine
    angle = cmd.gate.angle

    with Control(eng, cmd.control_qubits):
        with Compute(eng):
            Rx(math.pi / 2.) | qubit
        Rz(angle) | qubit
        Uncompute(eng)
Пример #25
0
def diffusion(eng):

    with Compute(eng):
        All(H) | layer1_weight_reg

        All(X) | layer1_weight_reg

    ControlledGate(Z, 2) | (layer1_weight_reg[0], layer1_weight_reg[1],
                            layer1_weight_reg[2])

    Uncompute(eng)
Пример #26
0
def test_constant_addition(eng):
    qunum_a = eng.allocate_qureg(5)
    X | qunum_a[2]
    with Compute(eng):
        AddConstant(5) | (qunum_a)

    Uncompute(eng)

    eng.flush()

    assert 1.0 == pytest.approx(eng.backend.get_probability([0, 0, 1, 0, 0], qunum_a))
Пример #27
0
def _decompose_rz2rx_P(cmd):  # pylint: disable=invalid-name
    """Decompose the Rz using negative angle."""
    # Labelled 'P' for 'plus' because decomposition ends with a Ry(+pi/2)
    qubit = cmd.qubits[0]
    eng = cmd.engine
    angle = cmd.gate.angle

    with Control(eng, cmd.control_qubits):
        with Compute(eng):
            Ry(-math.pi / 2.0) | qubit
        Rx(-angle) | qubit
        Uncompute(eng)
Пример #28
0
def complex_oracle(eng, system_q, control):
    # This oracle selects the subspace |000000>+|111111> as the good one
    with Compute(eng):
        with Control(eng, system_q[0]):
            All(X) | system_q[1:]
        H | system_q[0]
        All(X) | system_q

    with Control(eng, system_q):
        X | control

    Uncompute(eng)
Пример #29
0
def _decompose_rz2rx_M(cmd):
    """ Decompose the Rz using positive angle. """
    # Labelled 'M' for 'minus' because decomposition ends with a Ry(-pi/2)
    qubit = cmd.qubits[0]
    eng = cmd.engine
    angle = cmd.gate.angle

    with Control(eng, cmd.control_qubits):
        with Compute(eng):
            Ry(math.pi / 2.) | qubit
        Rx(angle) | qubit
        Uncompute(eng)
Пример #30
0
def run_grover(eng, n, oracle):
    """
    Runs Grover's algorithm on n qubit using the provided quantum oracle.

    Args:
        eng (MainEngine): Main compiler engine to run Grover on.
        n (int): Number of bits in the solution.
        oracle (function): Function accepting the engine, an n-qubit register,
            and an output qubit which is flipped by the oracle for the correct
            bit string.

    Returns:
        solution (list<int>): Solution bit-string.
    """
    x = eng.allocate_qureg(n)

    # start in uniform superposition
    All(H) | x

    # number of iterations we have to run:
    num_it = int(math.pi / 4. * math.sqrt(1 << n))
    print("Number of iterations we have to run: {}".format(num_it))

    # prepare the oracle output qubit (the one that is flipped to indicate the
    # solution. start in state 1/sqrt(2) * (|0> - |1>) s.t. a bit-flip turns
    # into a (-1)-phase.
    oracle_out = eng.allocate_qubit()
    X | oracle_out
    H | oracle_out

    # run num_it iterations
    with Loop(eng, num_it):
        # oracle adds a (-1)-phase to the solution
        oracle(eng, x, oracle_out)

        # reflection across uniform superposition
        with Compute(eng):
            All(H) | x
            All(X) | x

        with Control(eng, x[0:-1]):
            Z | x[-1]

        Uncompute(eng)

        All(Ph(math.pi / n)) | x

    All(Measure) | x
    Measure | oracle_out

    eng.flush()
    # return result
    return [int(qubit) for qubit in x]