Esempio n. 1
0
def test_param_prog_p1_barbell():
    test_graph = [(0, 1)]
    p = 1
    with patch('grove.pyqaoa.maxcut_qaoa.api', spec=qvm_mod):
        inst = maxcut_qaoa(test_graph, steps=p)

        param_prog = inst.get_parameterized_program()
        trial_prog = param_prog([1.2, 3.4])
        result_prog = Program().inst([
            H(0),
            H(1),
            X(0),
            PHASE(1.7)(0),
            X(0),
            PHASE(1.7)(0),
            CNOT(0, 1),
            RZ(3.4)(1),
            CNOT(0, 1),
            H(0),
            RZ(-2.4)(0),
            H(0),
            H(1),
            RZ(-2.4)(1),
            H(1)
        ])
        trial_prog == result_prog
Esempio n. 2
0
def bell_ckt_gd():
    ckt = Program()
    theta_0 = ckt.declare('theta_0', memory_type='REAL')
    theta_1 = ckt.declare("theta_1", memory_type='REAL')
    x_theta = ckt.declare("x_theta", memory_type='REAL')
    ro = ckt.declare('ro', memory_type='BIT', memory_size=2)
    ckt += RX(x_theta, 1)
    ckt += RZ(x_theta, 1)
    ckt += RX(-1 * x_theta, 1)

    ckt += RX(theta_0, 0)
    ckt += RZ(theta_0, 0)

    ckt += RX(x_theta, 0)
    ckt += RZ(theta_1, 0)
    ckt += RX(-1 * x_theta, 0)

    ckt += CZ(1, 0)

    ckt += RX(x_theta, 0)
    ckt += RZ(-1 * theta_1, 0)
    ckt += RX(-1 * x_theta, 0)

    ckt += MEASURE(0, ro[0])
    ckt.wrap_in_numshots_loop(1000)
    return ckt
Esempio n. 3
0
def diffusion_operator(qubits):
    """Constructs the (Grover) diffusion operator on qubits, assuming they are ordered from most
    significant qubit to least significant qubit.

    The diffusion operator is the diagonal operator given by(1, -1, -1, ..., -1).

    :param qubits: A list of ints corresponding to the qubits to operate on. The operator
                   operates on bistrings of the form |qubits[0], ..., qubits[-1]>.
    """
    p = pq.Program()

    if len(qubits) == 1:
        p.inst(H(qubits[0]))
        p.inst(Z(qubits[0]))
        p.inst(H(qubits[0]))

    else:
        p.inst(map(X, qubits))
        p.inst(H(qubits[-1]))
        p.inst(RZ(-np.pi)(qubits[0]))
        p += n_qubit_control(qubits[:-1], qubits[-1], np.array([[0, 1], [1, 0]]), "NOT")
        p.inst(RZ(-np.pi)(qubits[0]))
        p.inst(H(qubits[-1]))
        p.inst(map(X, qubits))
    return p
Esempio n. 4
0
    def get_decoupling_sequence(self,
                                gate: Gate,
                                dd_pulse_time: float = None) -> "Program":
        if isinstance(gate, Gate):
            angle = None

            if gate.name == "RZ":
                combined_gate = RZ
                angle, = gate.params
                angle += pi
            else:
                combined_gate = get_combined_gate(
                    *get_combined_gate_representation(gate.name, 'Z',
                                                      gate.params))

            if len(gate.qubits) != 1:
                p = Program(RY(pi, gate.qubits[0]), RY(pi, gate.qubits[1]),
                            RZ(pi, gate.qubits[0]), RZ(pi, gate.qubits[1]),
                            RY(pi, gate.qubits[0]), RY(pi, gate.qubits[1]))

            else:
                p = Program(RY(pi, *gate.qubits), RZ(pi, *gate.qubits),
                            RY(pi, *gate.qubits))

            seq = set_gate_time(p, dd_pulse_time)
            GZ = combined_gate(
                angle, *gate.qubits) if angle is not None else combined_gate(
                    *gate.qubits)
            GZ = gates_with_time(GZ.name, GZ.params, GZ.qubits)
            GZ.dd = False
            seq += GZ

            return seq
Esempio n. 5
0
def prepare_state_on_bloch_sphere(qubit: int, theta: float, phi: float):
    r"""
    Returns a program which prepares the given qubit in the state (theta, phi) on the bloch sphere,
    assuming the initial state `|0>` where (theta=0, phi=0).

    Theta and phi are the usual polar coordinates, given in radians. Theta is the angle of the
    state from the +Z axis, or zero state, and phi is the rotation angle from the XZ plane.
    Equivalently, the state

    .. math::

        \alpha |0> + \beta |1>

    in these coordinates has, up to some global phase factored out,

    .. math::

        \alpha = \cos(\theta/2)
        e^{i \phi} = \rm{Im}[\beta]

    where :math:`\rm{Im}[\beta]=` ``beta.imag``

    See https://en.wikipedia.org/wiki/Qubit#Bloch_sphere_representation for more information.

    :param qubit: the qubit to prepare in the given state
    :param theta: azimuthal angle given in radians
    :param phi: polar angle given in radians
    :return: a program preparing the qubit in the specified state, implemented in native gates
    """
    prep = Program()
    prep += RX(pi / 2, qubit)
    prep += RZ(theta, qubit)
    prep += RX(-pi / 2, qubit)
    prep += RZ(phi, qubit)
    return prep
Esempio n. 6
0
def prepare_state_on_bloch_sphere(qubit: int, theta: float, phi: float):
    """
    Returns a program which prepares the given qubit in the state (theta, phi) on the bloch sphere,
    assuming the initial state |0> where (theta=0, phi=0).

    Theta and phi are the usual polar coordinates, given in radians. Theta is the angle of the
    state from the +Z axis, or zero state, and phi is the rotation angle from the XZ plane.
    Equivalently, the state
        alpha |0> + beta |1>
    in these coordinates has alpha = cos(theta/2) and e^(i*phi) = beta.imag, modulo some global
    phase.

    See https://en.wikipedia.org/wiki/Qubit#Bloch_sphere_representation for more information.

    :param qubit: the qubit to prepare in the given state
    :param theta: azimuthal angle given in radians
    :param phi: polar angle given in radians
    :return: a program preparing the qubit in the specified state, implemented in native gates
    """
    prep = Program()
    prep += RX(pi / 2, qubit)
    prep += RZ(theta, qubit)
    prep += RX(-pi / 2, qubit)
    prep += RZ(phi, qubit)
    return prep
Esempio n. 7
0
def decomposed_diffusion_program(qubits):
    """
    Constructs the diffusion operator used in Grover's Algorithm, acted on both sides by an
    a Hadamard gate on each qubit. Note that this means that the matrix representation of this
    operator is diag(1, -1, ..., -1). In particular, this decomposes the diffusion operator, which
    is a :math:`2**{len(qubits)}\times2**{len(qubits)}` sparse matrix, into
     :math:`\mathcal{O}(len(qubits)**2) single and two qubit gates.

    See C. Lavor, L.R.U. Manssur, and R. Portugal (2003) `Grover's Algorithm: Quantum Database
    Search`_ for more information.

    .. _`Grover's Algorithm: Quantum Database Search`: https://arxiv.org/abs/quant-ph/0301079

    :param qubits: A list of ints corresponding to the qubits to operate on.
                   The operator operates on bistrings of the form
                   ``|qubits[0], ..., qubits[-1]>``.
    """
    program = pq.Program()
    if len(qubits) == 1:
        program.inst(Z(qubits[0]))
    else:
        program.inst([X(q) for q in qubits])
        program.inst(H(qubits[-1]))
        program.inst(RZ(-np.pi, qubits[0]))
        program += (ControlledProgramBuilder().with_controls(
            qubits[:-1]).with_target(qubits[-1]).with_operation(
                X_GATE).with_gate_name(X_GATE_LABEL).build())
        program.inst(RZ(-np.pi, qubits[0]))
        program.inst(H(qubits[-1]))
        program.inst([X(q) for q in qubits])
    return program
Esempio n. 8
0
def diffusion_program(qubits):
    """Constructs the diffusion operator used in Grover's Algorithm, acted on both sides by an
     a Hadamard gate on each qubit. Note that this means that the matrix representation of this
     operator is diag(1, -1, ..., -1).

    See C. Lavor, L.R.U. Manssur, and R. Portugal (2003) `Grover's Algorithm: Quantum Database
    Search`_ for more information.

    .. _`Grover's Algorithm: Quantum Database Search`: https://arxiv.org/abs/quant-ph/0301079

    :param qubits: A list of ints corresponding to the qubits to operate on.
                   The operator operates on bistrings of the form
                   |qubits[0], ..., qubits[-1]>.
    """
    diffusion_program = pq.Program()

    if len(qubits) == 1:
        diffusion_program.inst(Z(qubits[0]))
    else:
        diffusion_program.inst([X(q) for q in qubits])
        diffusion_program.inst(H(qubits[-1]))
        diffusion_program.inst(RZ(-np.pi)(qubits[0]))
        diffusion_program += (ControlledProgramBuilder()
                              .with_controls(qubits[:-1])
                              .with_target(qubits[-1])
                              .with_operation(X_GATE)
                              .with_gate_name("NOT").build())
        diffusion_program.inst(RZ(-np.pi)(qubits[0]))
        diffusion_program.inst(H(qubits[-1]))
        diffusion_program.inst([X(q) for q in qubits])
    return diffusion_program
Esempio n. 9
0
def ansatz(params, prog_in=program_initialization):
    """
    Create a maximally expressive 2-qubit quantum circuit with minimal amount of parameters (15 rotations)
    """
    prog_out = prog_in.copy()

    prog_out += RZ(params[0], 1)

    prog_out += CNOT(0, 1)

    prog_out += RZ(params[1], 0)
    prog_out += RX(params[2], 0)
    prog_out += RZ(params[3], 0)

    prog_out += RZ(params[4], 1)
    prog_out += RX(params[5], 1)
    prog_out += RZ(params[6], 1)

    prog_out += CNOT(0, 1)

    prog_out += RX(params[7], 0)
    prog_out += RZ(params[8], 1)

    prog_out += CNOT(0, 1)

    prog_out += RZ(params[9], 0)
    prog_out += RX(params[10], 0)
    prog_out += RZ(params[11], 0)

    prog_out += RZ(params[12], 1)
    prog_out += RX(params[13], 1)
    prog_out += RZ(params[14], 1)

    return prog_out
Esempio n. 10
0
def _T(q: QubitLike, dagger: bool = False) -> Program:
    """
    A T in terms of RZ(theta)
    """
    if dagger:
        return Program(RZ(-np.pi / 4, q))
    else:
        return Program(RZ(np.pi / 4, q))
Esempio n. 11
0
def _T(q1, dagger=False):
    """
    A T in terms of RZ(theta)
    """
    if dagger:
        return Program(RZ(-np.pi / 4, q1))
    else:
        return Program(RZ(np.pi / 4, q1))
def test_exponentiate_commuting_pauli_sum():
    q = QubitPlaceholder.register(8)
    pauli_sum = PauliSum(
        [PauliTerm('Z', q[0], 0.5),
         PauliTerm('Z', q[1], 0.5)])
    prog = Program().inst(RZ(1., q[0])).inst(RZ(1., q[1]))
    result_prog = exponentiate_commuting_pauli_sum(pauli_sum)(1.)
    assert address_qubits(prog) == address_qubits(result_prog)
Esempio n. 13
0
def parameterized_euler_rotations(
    qubits: Sequence[int],
    *,
    prefix: str,
    suffix_alpha: str = 'alpha',
    suffix_beta: str = 'beta',
    suffix_gamma: str = 'gamma',
) -> Program:
    """
    Given a number of qubits (n), build a ``Program`` containing a ZXZXZ-decomposed gate on each
    qubit, where each ``RZ`` is parameterized by declared values with labels given by the "prefix"
    and "suffix" arguments. Put more plainly, the resulting Quil program on n qubits is:

        RZ(alpha_label[0]) 0
        RX(pi/2) 0
        RZ(beta_label[0]) 0
        RX(-pi/2) 0
        RZ(gamma_label[0]) 0

        ...

        RZ(alpha_label[n-1]) n-1
        RX(pi/2) n-1
        RZ(beta_label[0]) n-1
        RX(-pi/2) n-1
        RZ(gamma_label[n-1]) n-1

    :param qubits: The number of qubits (n).
    :param prefix: The prefix for the declared memory region labels. For example, if the prefix
        is "preparation" and the alpha, beta, and gamma suffixes are left as default, the labels
        would be "preparation_alpha", "preparation_beta", and "preparation_gamma".
    :param suffix_alpha: The suffix for the "alpha" memory region label, which corresponds to the
        first (rightmost) ``Z`` in the ZXZXZ decomposition. Defaults to "alpha".
    :param suffix_beta: The suffix for the "beta" memory region label, which corresponds to the
        second (middle) ``Z`` in the ZXZXZ decomposition. Defaults to "beta".
    :param suffix_gamma: The suffix for the "gamma" memory region label, which corresponds to the
        last (leftmost) ``Z`` in the ZXZXZ decomposition. Defaults to "gamma".
    :return: A ``Program`` containing a 3 parameterized ``RZ``s and 2 fixed ``RX``s per qubit.
    """
    alpha_label = f'{prefix}_{suffix_alpha}'
    beta_label = f'{prefix}_{suffix_beta}'
    gamma_label = f'{prefix}_{suffix_gamma}'

    p = Program()

    alpha = p.declare(alpha_label, 'REAL', len(qubits))
    beta = p.declare(beta_label, 'REAL', len(qubits))
    gamma = p.declare(gamma_label, 'REAL', len(qubits))

    for idx, q in enumerate(qubits):
        p += RZ(alpha[idx], q)
        p += RX(np.pi / 2, q)
        p += RZ(beta[idx], q)
        p += RX(-np.pi / 2, q)
        p += RZ(gamma[idx], q)

    return p
Esempio n. 14
0
def add_gate_program_grover4(p, gate):
    erase = [
        '(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '-'
    ]
    gate_data = gate.split(' ')
    name_gate = gate_data[0]
    for char in erase:
        name_gate = name_gate.replace(char, '')

    if name_gate == 'H':
        p.inst(RZ(pi / 2, int(gate_data[1])), RX(pi / 2, int(gate_data[1])),
               RZ(pi / 2, int(gate_data[1])))
    if name_gate == 'X':
        p.inst(RZ(pi / 2, int(gate_data[1])), RX(pi / 2, int(gate_data[1])),
               RZ(pi, int(gate_data[1])), RX(-pi / 2, int(gate_data[1])),
               RZ(-pi / 2, int(gate_data[1])))
    if name_gate == 'CNOT':
        p.inst(RZ(pi / 2, int(gate_data[2])), RX(pi / 2, int(gate_data[2])),
               CZ(int(gate_data[1]), int(gate_data[2])),
               RX(-pi / 2, int(gate_data[2])), RZ(-pi / 2, int(gate_data[2])))
    if name_gate == 'RZ':
        angle = float(gate_data[0].replace('RZ(', '').replace(')', ''))
        p.inst(RZ(-pi / 8, int(gate_data[1])))
    if name_gate == 'PHASE':
        angle = float(gate_data[0].replace('PHASE(', '').replace(')', ''))
        p.inst(RZ(0.19634954084936207, int(gate_data[1])))
    return p
Esempio n. 15
0
def test_compile_with_quilt_calibrations(compiler):
    device_name = "test_device"
    mock_url = "http://mock-qpu-compiler"

    config = PyquilConfig(TEST_CONFIG_PATHS)
    session = get_session(config=config)
    mock_adapter = requests_mock.Adapter()
    session.mount("http://", mock_adapter)

    headers = {
        # access token from ./data/user_auth_token_valid.json.
        "Authorization": "Bearer secret"
    }
    mock_adapter.register_uri(
        "POST",
        f"{mock_url}/devices/{device_name}/get_version_info",
        status_code=200,
        json={},
        headers=headers,
    )

    mock_adapter.register_uri(
        "POST",
        f"{mock_url}/devices/{device_name}/native_quilt_to_binary",
        status_code=200,
        json=SIMPLE_RESPONSE,
        headers=headers,
    )

    device = Device(name="not_actually_device_name",
                    raw={
                        "device_name": device_name,
                        "isa": DUMMY_ISA_DICT
                    })
    compiler = QPUCompiler(
        quilc_endpoint=session.config.quilc_url,
        qpu_compiler_endpoint=mock_url,
        device=device,
        session=session,
    )

    program = simple_program()
    q = FormalArgument("q")
    defn = DefCalibration(
        "H", [], [q],
        [RZ(math.pi / 2, q),
         RX(math.pi / 2, q),
         RZ(math.pi / 2, q)])
    cals = [defn]
    program._calibrations = cals
    # this should more or less pass through
    compilation_result = compiler.quil_to_native_quil(program, protoquil=True)
    assert compilation_result.calibrations == cals
    assert program.calibrations == cals
    assert compilation_result == program
Esempio n. 16
0
def _RX(angle: AngleLike, q: QubitLike) -> Program:
    """
    A RX in terms of native RX(+-pi/2) and RZ gates.
    """
    p = Program()
    p += RZ(pi / 2, q)
    p += RX(pi / 2, q)
    p += RZ(angle, q)
    p += RX(-pi / 2, q)
    p += RZ(-pi / 2, q)
    return p
Esempio n. 17
0
def rotation(a, b, c, wire):
    r"""Arbitrary one-qubit rotation using three Euler angles.

    Args:
        a, b, c (float): rotation angles
        wire (int): wire the rotation acts on

    Returns:
        list: Ry and Rz matrix operators acting on each wire
    """
    return [RZ(a, wire), RY(b, wire), RZ(c, wire)]
Esempio n. 18
0
def _RX(angle: float, q: int) -> Program:
    """
    A RX in terms of native RX(+-pi/2) and RZ gates.
    """
    p = Program()
    p += RZ(pi / 2, q)
    p += RX(pi / 2, q)
    p += RZ(angle, q)
    p += RX(-pi / 2, q)
    p += RZ(-pi / 2, q)
    return p
Esempio n. 19
0
def test_compile_with_quilt_calibrations(compiler: QPUCompiler):
    program = simple_program()
    q = FormalArgument("q")
    defn = DefCalibration("H", [], [q], [RZ(math.pi / 2, q), RX(math.pi / 2, q), RZ(math.pi / 2, q)])
    cals = [defn]
    program._calibrations = cals
    # this should more or less pass through
    compilation_result = compiler.quil_to_native_quil(program, protoquil=True)
    assert compilation_result.calibrations == cals
    assert program.calibrations == cals
    assert compilation_result == program
Esempio n. 20
0
def test_parameterized_single_qubit_measurement_basis():
    p = Program()
    alpha = p.declare("measurement_alpha", "REAL", 2)
    beta = p.declare("measurement_beta", "REAL", 2)
    gamma = p.declare("measurement_gamma", "REAL", 2)
    for idx, q in enumerate(range(2)):
        p += RZ(alpha[idx], q)
        p += RX(np.pi / 2, q)
        p += RZ(beta[idx], q)
        p += RX(-np.pi / 2, q)
        p += RZ(gamma[idx], q)
    assert parameterized_single_qubit_measurement_basis([0, 1]).out() == p.out()
def arbitraryGate(Q, t):
    """
    Return pyQuil program which applie a gate defined by dictionary `Q` to 
    target qubit `t`.
    
    In Rieffel and Polak, they show that an arbitrary single-qubit
    transformation can be uniquely defined by four real numbers. This function
    uses the same convention, naming these numbers `alpha`, `beta`, `delta`, 
    and `gamma`, and using a dictionary `Q` to hold each number indexed by the 
    same name. 
    
    Parameters
    ----------
    Q: dictionary
        Holds the four angles `alpha`, `beta`, `delta`, and `gamma` used to
        specify a single-qubit transformation by the Rieffel and Polak
        convention. These angles are indexed by their names.
        
    t: list
        Length-1 list holding the qubit location of target qubit t.
        
    Returns
    -------
    p: pyquil Program
        Program which executes the arbitrary single-qubit transformation.
    """

    if len(t) is not 1:
        raise Exception("target qubit t must have length 1")

    if 'alpha' in Q:
        alpha = Q['alpha']
    else:
        alpha = 0
    if 'beta' in Q:
        beta = Q['beta']
    else:
        beta = 0
    if 'delta' in Q:
        delta = Q['delta']
    else:
        delta = 0
    if 'gamma' in Q:
        gamma = Q['gamma']
    else:
        gamma = 0

    p = Program(RZ(-2 * gamma, t[0]), RY(-2 * beta, t[0]),
                RZ(-2 * (alpha + delta), t[0]), PHASE(2 * delta, t[0]))

    return p
Esempio n. 22
0
def rus(inputs, w, b):
    in_reg = list()
    for i in inputs:
        in_reg.append(i)
    an_reg = list()
    an_reg.append(QubitPlaceholder())
    an_reg.append(QubitPlaceholder())
    # Gates and classical memory preparation
    prep_pq = Program()
    acl_ro = prep_pq.declare('acl_{}_ro'.format(an_reg[0]), 'BIT', 1)
    # Rotation gates
    rot_linear_pq = Program()
    for i in range(len(w)):
        rot_linear_pq += CRY(w[i])(in_reg[i], an_reg[0])
    rot_linear_pq += RY(b, an_reg[0])
    rot_pq = Program()
    rot_pq += rot_linear_pq
    rot_pq += CY(an_reg[0], an_reg[1])
    rot_pq += RZ(-np.pi / 2, an_reg[0])
    rot_pq += rot_linear_pq
    # Ancilla bit measurement
    pq = Program()
    pq += prep_pq
    pq += rot_pq
    pq += MEASURE(an_reg[0], acl_ro)
    # Repeated circuit
    rep_pq = Program()
    # rep_pq += RESET(reg[1])
    rep_pq += RY(-np.pi / 2, an_reg[1])
    rep_pq += rot_pq
    rep_pq += MEASURE(an_reg[0], acl_ro)

    pq.while_do(acl_ro, rep_pq)
    return pq, an_reg[1]
Esempio n. 23
0
def rus_single(input, theta):
    reg = list()
    reg.append(input)
    reg.append(QubitPlaceholder())
    reg.append(QubitPlaceholder())
    # Gates and classical memory preparation
    prep_pq = Program()
    prep_pq += dg_cry
    prep_pq += dg_cy
    acl_ro = prep_pq.declare('acl_ro', 'BIT', 1)
    # Rotation gates
    rot_pq = Program()
    rot_pq += CRY(2 * theta)(reg[0], reg[1])
    rot_pq += CY(reg[1], reg[2])
    rot_pq += RZ(-np.pi / 2, reg[1])
    rot_pq += CRY(2 * theta)(reg[0], reg[1])
    # Ancilla bit measurement
    pq = Program()
    pq += prep_pq
    pq += rot_pq
    pq += MEASURE(reg[1], acl_ro)
    # Repeated circuit
    rep_pq = Program()
    # rep_pq += RESET(reg[1])
    rep_pq += RY(-np.pi / 2, reg[2])
    rep_pq += rot_pq
    rep_pq += MEASURE(reg[1], acl_ro)

    pq.while_do(acl_ro, rep_pq)
    return pq, reg[2]
Esempio n. 24
0
def test_exponentiate_bp1_XZ():
    # testing change of basis position 1
    generator = PauliTerm("Z", 0, 1.0) * PauliTerm("X", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst([H(1), CNOT(0, 1), RZ(2.0, 1), CNOT(0, 1), H(1)])
    assert prog == result_prog
Esempio n. 25
0
def test_exponentiate_2():
    # testing general 2-circuit
    generator = PauliTerm("Z", 0, 1.0) * PauliTerm("Z", 1, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(CNOT(0, 1)).inst(RZ(2.0, 1)).inst(CNOT(0, 1))
    assert prog == result_prog
Esempio n. 26
0
def test_exponentiate_1():
    # test rotation of single qubit
    generator = PauliTerm("Z", 0, 1.0)
    para_prog = exponential_map(generator)
    prog = para_prog(1)
    result_prog = Program().inst(RZ(2.0, 0))
    assert prog == result_prog
Esempio n. 27
0
def generate_parametric_cz_phase_ramsey_program(qcid: int,
                                                other_qcid: int) -> Program:
    """
    Generate a single CZ phase Ramsey experiment at a given phase.

    :param qcid: The qubit to move around the Bloch sphere and measure the incurred RZ on.
    :param other_qcid: The other qubit that constitutes a two-qubit pair along with `qcid`.
    :param phase: The phase kick to supply after playing the CZ pulse on the equator.
    :param num_shots: The number of shots to average over for the data point.
    :return: A parametric Program for performing a CZ Ramsey experiment.
    """
    program = Program()
    # NOTE: only need readout register for `qcid` not `other_qcid` since `other_qcid` is only
    #       needed to identify which CZ gate we're using
    ro = program.declare('ro', 'BIT', 1)
    theta = program.declare('theta', 'REAL')

    # go to the equator
    program += Program(RX(np.pi / 2, qcid))
    # apply the CZ gate - note that CZ is symmetric, so the order of qubits doesn't matter
    program += Program(CZ(qcid, other_qcid))
    # go to |1> after a phase kick
    program += Program(RZ(theta, qcid), RX(np.pi / 2, qcid))

    program += MEASURE(qcid, ro[0])

    return program
Esempio n. 28
0
def RSWAP(qubits) -> Program:
    i = qubits[0]
    j = qubits[1]
    RSWAP_program = Program()
    RSWAP_program.inst(CNOT(i, j))
    RSWAP_program.inst(H(i))
    RSWAP_program.inst(RZ(np.pi / 4, i))
    RSWAP_program.inst(RZ(-np.pi / 4, j))
    RSWAP_program.inst(CNOT(j, i))
    RSWAP_program.inst(RZ(-np.pi / 4, i))
    RSWAP_program.inst(H(i))
    RSWAP_program.inst(CNOT(i, j))
    RSWAP_program.inst(RZ(np.pi / 2, j))
    RSWAP_program.inst(RZ(-np.pi / 2, i))

    return RSWAP_program
Esempio n. 29
0
def _readout_group_parameterized_bitstring(qubits: Sequence[int], do_measure: bool = True) \
                                                                                    -> Program:
    """
    Produces a parameterized program for the given group of qubits, where each qubit is prepared
    in the 0 or 1 state depending on the parameterization specified at run-time.

    See also _readout_group_bitstring which produces a non-parameterized program that prepares
    and measures a single pre-specified bitstring on the given qubits. Parameterization allows
    for a single program to measure each bitstring (specified at run-time) and speeds up
    the collective measurements of all bitstring for a group of qubits. Note that the program
    produced by _readout_group_bitstring does not execute any gates when preparing 0 on a
    particular qubit and executes only one gate to prepare 1; meanwhile, this method produces a
    program which executes three gates for either preparation on each qubit.

    :param qubits: labels of qubits on which some bitstring will be prepared and, perhaps, measured
    :param do_measure: dictates whether to measure the qubits after preparing the bitstring;
        false in estimate_joint_active_reset_confusion which only uses state-prep
    :return: a parameterized program capable of measuring any bitstring on the given qubits
    """
    program = Program()
    ro = []
    if do_measure:
        ro = program.declare('ro', memory_type='BIT', memory_size=len(qubits))
    target = program.declare('target',
                             memory_type='REAL',
                             memory_size=len(qubits))
    for idx, qubit in enumerate(qubits):
        program += RX(pi / 2, qubit)
        program += RZ(target[idx], qubit)
        program += RX(-pi / 2, qubit)
        if do_measure:
            program += MEASURE(qubit, ro[idx])
    return program
Esempio n. 30
0
def test_get_qvm_noise_supported_gates_from_aspen8_isa(
        qcs_aspen8_quantum_processor, noise_model_dict):
    gates = _get_qvm_noise_supported_gates(
        qcs_aspen8_quantum_processor.to_compiler_isa())

    for q in range(len(qcs_aspen8_quantum_processor._isa.architecture.nodes)):
        if q not in ASPEN_8_QUBITS_NO_RX:
            for g in [
                    RX(np.pi / 2, q),
                    RX(-np.pi / 2, q),
                    RX(np.pi, q),
                    RX(-np.pi, q),
            ]:
                assert g in gates
        if q not in ASPEN_8_QUBITS_NO_RZ:
            assert RZ(THETA, q) in gates

    for edge in qcs_aspen8_quantum_processor._isa.architecture.edges:
        if (
                edge.node_ids[0],
                edge.node_ids[1],
        ) in ASPEN_8_EDGES_NO_CZ:
            continue
        assert CZ(edge.node_ids[0], edge.node_ids[1]) in gates
        assert CZ(edge.node_ids[1], edge.node_ids[0]) in gates