.. _introducing_v4: ===================== Introducing pyQuil v4 ===================== The 4.0 major release of pyQuil moves the foundation of program parsing, manipulation, compilation, and execution into Rigetti's latest generation of SDKs written in Rust. This comes with improved performance, stronger type safety, better error messages, and access to exciting new features. As a first step, read through the :doc:`changes` to get an overview of what's new. Pay special attention to the breaking changes you may need to accommodate. In the rest of this introduction, we'll expand on some of the key changes and new features. ******************* Parameters & memory ******************* In order to provide more flexibility when executing parameterized Programs, the execution methods on ``QAM``, ``QVM``, ``QPU`` and the like now accept an optional ``memory_map`` keyword parameter. This parameter is defined as a mapping of a memory region's name to a sequence of values that will be used to initialize that memory region before executing the program. This replaces the ability to use the write_memory method on a Program. Here is an example of how you might use a memory map in practice: .. code:: python from pyquil.api import get_qc from pyquil.gates import RZ from pyquil.quil import Program qc = get_qc("Ankaa-9Q-1") program = Program() theta = program.declare("theta", "REAL") program += RZ(theta, 0) exe = qc.compile(program) # Previously, we would've used program.write_memory(region_name="theta", value=0.0) memory_map = {"theta": [0.0]} result = qc.run(exe, memory_map=memory_map) The ``MemoryMap`` type is defined as ``Mapping[str, Union[Sequence[int], Sequence[float]]``. Note that the values mapped to a memory region must always be a sequence. This is different from ``write_memory`` which would allow writing an atomic value to a region of length 1. ********************************* QCS Gateway and execution options ********************************* The QCS Gateway is a new service that provides on-demand access to a QPU. See the `Gateway documentation`_ for more information on what it is and why you might find it useful. .. _Gateway documentation: https://docs.rigetti.com/qcs/guides/qcs-gateway In pyQuil v4, Gateway is enabled by default and it is generally recommended to keep it on. However, if you have a use case for sending your job to the QPU directly, you can use the new ``ExecutionOptions`` and ``ConnectionStrategy`` classes to configure your request: .. code:: python from pyquil.api import get_qc, ExecutionOptionsBuilder, ConnectionStrategy from pyquil.quil import Program qc = get_qc("Ankaa-9Q-1") program = Program() exe = qc.compile(program) # Use an ``ExecutionOptionsBuilder`` to build a custom ``ExecutionOptions`` execution_options_builder = ExecutionOptionsBuilder() execution_options_builder.connection_strategy = ConnectionStrategy.direct_access() execution_options = execution_options_builder.build() # Option 1: Override execution options on a per-request basis. result = qc.run(exe, execution_options=execution_options) # Option 2: Sets the default options for all execution requests where no execution_options parameter is provided. result = qc.qam.execution_options = execution_options .. _accessing_raw_execution_data: **************************** Accessing raw execution data **************************** In previous versions of pyQuil, readout data was always returned as a mapping of memory regions to rectangular matrices that contained one value per memory reference, per shot. However, it shouldn't be assumed that readout data will always fit this shape. For example, programs that reuse qubits or use dynamic control flow can emit a different amount of values per shot, breaking the assumption that readout data will contain one value for each memory reference per shot. In these cases, it's better to rely on the author of the program to wrangle the data into the shape they expect, so we've made it possible to access raw readout data. .. note:: You can learn more about how QPU readout data works in the `QCS documentation `_ In v4, readout data continues to be accessible in the same way as before, but if the readout data generated by your program doesn't fit a rectangular matrix, a ``RegisterMatrixConversionError`` will be raised. In this case, you should use the ``get_raw_readout_data`` method to access the raw data and build the data structure you need. .. warning:: It's possible to have a program that results in a rectangular matrix of readout data, but have more than one value per memory reference per shot due to qubit reuse. In these cases, a ``RegisterMatrixConversionError`` will _not_ be raised, since the resulting matrix would be valid for some number of shots. It's important to be aware of this possibility, and to still use ``get_raw_readout_data`` if that possibility is a concern. .. code:: python import numpy as np from pyquil.api import RegisterMatrixConversionError def process_raw_data(raw_data) -> np.ndarray: # Process the data into a matrix that makes sense for your # program ... result = qc.run(exe) try: matrix = result.get_register_map() except RegisterMatrixConversionError: matrix = process_raw_data(result.get_raw_readout_data()) Using the new QPU Compiler Backend ---------------------------------- Rigetti's next-generation QPU compiler is accessible through pyQuil v4. This backend is required for Ankaa-family QPUs and can be configured with the new :py:class:`~pyquil.api.QPUCompilerAPIOptions` class. This class is a type alias of ``qcs-sdk-python``'s ``TranslationOptions``. See its `API documentation `_ for more information on all the available parameters. .. TODO: When qcs-sdk-python has live documentation, we should setup intersphinx so it can be linked to directly. .. code:: python from pyquil.api import get_qc, QPUCompilerAPIOptions from pyquil.quil import Program program = Program() qc = get_qc("Ankaa-9Q-1") api_options = QPUCompilerAPIOptions() api_options.v2( passive_reset_delay_seconds=0.0002 ) # Option 1: Apply to all compiled programs qc.compiler.api_options = api_options # Option 2: Apply to one specific compilation qc.compiler.native_quil_to_executable(program, api_options=api_options)