Esempio n. 1
0
def test_qpu_run():
    config = PyquilConfig()
    if config.qpu_url and config.qpu_compiler_url:
        g = nx.Graph()
        g.add_node(0)
        device = NxDevice(g)

        qc = QuantumComputer(
            name="pyQuil test QC",
            qam=QPU(endpoint=config.qpu_url, user="******"),
            device=device,
            compiler=QPUCompiler(
                quilc_endpoint=config.quilc_url,
                qpu_compiler_endpoint=config.qpu_compiler_url,
                device=device,
            ),
        )
        bitstrings = qc.run_and_measure(program=Program(X(0)), trials=1000)
        assert bitstrings[0].shape == (1000, )
        assert np.mean(bitstrings[0]) > 0.8
        bitstrings = qc.run(qc.compile(Program(X(0))))
        assert bitstrings.shape == (0, 0)
    else:
        pytest.skip(
            "QPU or compiler-server not available; skipping QPU run test.")
Esempio n. 2
0
def test_qpu_reengage_when_invalid():
    config = PyquilConfig()
    engagement = Engagement(
        server_public_key=b"abc123",
        client_public_key=b"abc123",
        client_secret_key=b"abc123",
        expires_at=9999999999.0,
        qpu_endpoint="tcp://fake.qpu:50053",
        qpu_compiler_endpoint="tcp://fake.compiler:5555",
    )

    assert engagement.is_valid()

    session = get_session(config=config)
    config._engagement_requested = True
    config.get_engagement = lambda: engagement

    qpu = QPU(session=session)

    assert qpu._client_engagement is None
    assert qpu._get_client_auth_config() is not None
    assert qpu._client_engagement is engagement

    # By expiring the previous engagement, we expect QPU to attempt to re-engage
    engagement.expires_at = 0.0
    assert not engagement.is_valid()

    new_engagement = Engagement(
        server_public_key=b"abc12345",
        client_public_key=b"abc12345",
        client_secret_key=b"abc12345",
        expires_at=9999999999.0,
        qpu_endpoint="tcp://fake.qpu:50053",
        qpu_compiler_endpoint="tcp://fake.compiler:5555",
    )

    config.get_engagement = lambda: new_engagement

    new_auth_config = qpu._get_client_auth_config()
    assert new_auth_config is not None
    assert new_auth_config.client_public_key == new_engagement.client_public_key
    assert qpu._client_engagement is new_engagement

    new_engagement.expires_at = 0.0
    config.get_engagement = lambda: None

    assert qpu._get_client_auth_config() is None
Esempio n. 3
0
def test_qpu_run(forest: ForestConnection):
    devices = get_devices(async_endpoint=forest.async_endpoint, api_key=forest.api_key,
                          user_id=forest.user_id, as_dict=True)

    for name, dev in devices.items():
        if not dev.is_online:
            continue

        # TODO: gh-372. No way to query whether a device is available for running
        pytest.xfail("Please fix after gh-372")
        qpu = QPU(connection=forest, device_name=name)
        bitstrings = qpu.run(
            quil_program=Program(X(0), MEASURE(0, 0)),
            classical_addresses=[0],
            trials=1000,
        )
        assert bitstrings.shape == (1000, 1)
        assert np.mean(bitstrings) > 0.8
Esempio n. 4
0
def test_run_expects_executable():
    # https://github.com/rigetti/pyquil/issues/740

    # This test might need some more knowledgeable eyes. Not sure how
    # to best mock a qpu.
    qc = get_qc('1q-qvm')
    qc.qam = QPU(endpoint='tcp://not-needed:00000', user="******")

    p = Program(X(0))
    with pytest.raises(TypeError):
        result = qc.run(p)
Esempio n. 5
0
def mock_qpu():
    return QPU(endpoint='tcp://not-needed:00000', user="******")
Esempio n. 6
0
def test_qpu_does_not_engage_without_session():
    qpu = QPU(endpoint="tcp://fake.qpu:50052")

    assert qpu._get_client_auth_config() is None
Esempio n. 7
0
def test_qpu_not_engaged_error():
    with pytest.raises(ValueError):
        QPU()
Esempio n. 8
0
def get_qc(name: str,
           *,
           as_qvm: bool = None,
           noisy: bool = None,
           connection: ForestConnection = None):
    """
    Get a quantum computer.

    A quantum computer is an object of type :py:class:`QuantumComputer` and can be backed
    either by a QVM simulator ("Quantum/Quil Virtual Machine") or a physical Rigetti QPU ("Quantum
    Processing Unit") made of superconducting qubits.

    You can choose the quantum computer to target through a combination of its name and optional
    flags. There are multiple ways to get the same quantum computer. The following are equivalent::

        >>> qc = get_qc("8Q-Agave-noisy-qvm")
        >>> qc = get_qc("8Q-Agave", as_qvm=True, noisy=True)

    and will construct a simulator of the 8q-agave chip with a noise model based on device
    characteristics. We also provide a means for constructing generic quantum simulators that
    are not related to a given piece of Rigetti hardware::

        >>> qc = get_qc("9q-generic-qvm")
        >>> qc = get_qc("9q-generic", as_qvm=True)

    Redundant flags are acceptable, but conflicting flags will raise an exception::

        >>> qc = get_qc("9q-generic-qvm") # qc is fully specified by its name
        >>> qc = get_qc("9q-generic-qvm", as_qvm=True) # redundant, but ok
        >>> qc = get_qc("9q-generic-qvm", as_qvm=False) # Error!

    Use :py:func:`list_quantum_computers` to retrieve a list of known qc names.

    This method is provided as a convenience to quickly construct and use QVM's and QPU's.
    Power users may wish to have more control over the specification of a quantum computer
    (e.g. custom noise models, bespoke topologies, etc.). This is possible by constructing
    a :py:class:`QuantumComputer` object by hand. Please refer to the documentation on
    :py:class:`QuantumComputer` for more information.

    :param name: The name of the desired quantum computer. This should correspond to a name
        returned by :py:func:`list_quantum_computers`. Names ending in "-qvm" will return
        a QVM. Names ending in "-noisy-qvm" will return a QVM with a noise model. Otherwise,
        we will return a QPU with the given name.
    :param as_qvm: An optional flag to force construction of a QVM (instead of a QPU). If
        specified and set to ``True``, a QVM-backed quantum computer will be returned regardless
        of the name's suffix
    :param noisy: An optional flag to force inclusion of a noise model. If
        specified and set to ``True``, a quantum computer with a noise model will be returned
        regardless of the name's suffix. The noise model for QVM's based on a real QPU
        is an empirically parameterized model based on real device noise characteristics.
        The generic QVM noise model is simple T1 and T2 noise plus readout error. See
        :py:func:`decoherance_noise_with_asymmetric_ro`.
    :param connection: An optional :py:class:ForestConnection` object. If not specified,
        the default values for URL endpoints, ping time, and status time will be used. Your
        user id and API key will be read from ~/.pyquil_config. If you deign to change any
        of these parameters, pass your own :py:class:`ForestConnection` object.
    :return:
    """
    if connection is None:
        connection = ForestConnection()

    name, as_qvm, noisy = _parse_name(name, as_qvm, noisy)

    if name == '9q-generic':
        if not as_qvm:
            raise ValueError(
                "The device '9q-generic' is only available as a QVM")

        nineq_square = nx.convert_node_labels_to_integers(
            nx.grid_2d_graph(3, 3))
        nineq_device = NxDevice(topology=nineq_square)
        if noisy:
            noise_model = decoherance_noise_with_asymmetric_ro(
                nineq_device.get_isa())
        else:
            noise_model = None

        return QuantumComputer(name='9q-generic-qvm',
                               qam=QVM(connection=connection,
                                       noise_model=noise_model),
                               device=nineq_device)

    # At least based off a real device.
    device = get_devices(as_dict=True)[name]

    if not as_qvm:
        if noisy is not None and noisy:
            warnings.warn(
                "You have specified `noisy=True`, but you're getting a QPU. This flag "
                "is meant for controling noise models on QVMs.")
        return QuantumComputer(name=name,
                               qam=QPU(device_name=name,
                                       connection=connection),
                               device=device)

    if noisy:
        noise_model = device.noise_model
        name = "{name}-noisy-qvm".format(name=name)
    else:
        noise_model = None
        name = "{name}-qvm".format(name=name)

    return QuantumComputer(name=name,
                           qam=QVM(connection=connection,
                                   noise_model=noise_model),
                           device=device)
Esempio n. 9
0
def test_qpu_not_engaged_error():
    with pytest.raises(RuntimeError):
        qpu = QPU(None)