pyquil.api package

Sub-package for facilitating connections to the QVM / QPU.

class pyquil.api.AbstractCompiler(*, quantum_processor: AbstractQuantumProcessor, timeout: float, client_configuration: QCSClient | None = None, quilc_client: QuilcClient | None = None)[source]

Bases: ABC

The abstract interface for a compiler.

get_version_info() Dict[str, Any][source]

Return version information for this compiler and its dependencies.

Returns:

Dictionary of version information.

abstract native_quil_to_executable(nq_program: Program, **kwargs: Any) EncryptedProgram | Program[source]

Compile a native quil program to a binary executable.

Parameters:

nq_program – Native quil to compile

Returns:

An (opaque) binary executable

quil_to_native_quil(program: Program, *, protoquil: bool | None = None) Program[source]

Convert a Quil program into native Quil, which is supported for execution on a QPU.

reset() None[source]

Reset the state of the this compiler.

transpile_qasm_2(qasm: str) Program[source]

Transpile a QASM 2.0 program string to Quil, returning the result as a :py:class:~`pyquil.quil.Program`

class pyquil.api.BenchmarkConnection(*, timeout: float = 10.0, client_configuration: QCSClient | None = None)[source]

Bases: AbstractBenchmarker

Represents a connection to a server that generates benchmarking data.

Client to communicate with the benchmarking data endpoint.

Parameters:
  • timeout – Time limit for requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

apply_clifford_to_pauli(clifford: Program, pauli_in: PauliTerm) PauliTerm[source]

Given a circuit that consists only of elements of the Clifford group, return its action on a PauliTerm.

In particular, for Clifford C, and Pauli P, this returns the PauliTerm representing CPC^{dagger}.

Parameters:
  • clifford – A Program that consists only of Clifford operations.

  • pauli_in – A PauliTerm to be acted on by clifford via conjugation.

Returns:

A PauliTerm corresponding to clifford * pauli_in * clifford^{dagger}

generate_rb_sequence(depth: int, gateset: Sequence[Gate], seed: int | None = None, interleaver: Program | None = None) List[Program][source]

Construct a randomized benchmarking experiment on the given qubits, decomposing into gateset. If interleaver is not provided, the returned sequence will have the form

C_1 C_2 … C_(depth-1) C_inv ,

where each C is a Clifford element drawn from gateset, C_{< depth} are randomly selected, and C_inv is selected so that the entire sequence composes to the identity. If an interleaver G (which must be a Clifford, and which will be decomposed into the native gateset) is provided, then the sequence instead takes the form

C_1 G C_2 G … C_(depth-1) G C_inv .

The JSON response is a list of lists of indices, or Nones. In the former case, they are the index of the gate in the gateset.

Parameters:
  • depth – The number of Clifford gates to include in the randomized benchmarking experiment. This is different than the number of gates in the resulting experiment.

  • gateset – A list of pyquil gates to decompose the Clifford elements into. These must generate the clifford group on the qubits of interest. e.g. for one qubit [RZ(np.pi/2), RX(np.pi/2)].

  • seed – A positive integer used to seed the PRNG.

  • interleaver – A Program object that encodes a Clifford element.

Returns:

A list of pyquil programs. Each pyquil program is a circuit that represents an element of the Clifford group. When these programs are composed, the resulting Program will be the randomized benchmarking experiment of the desired depth. e.g. if the return programs are called cliffords then sum(cliffords, Program()) will give the randomized benchmarking experiment, which will compose to the identity program.

class pyquil.api.EncryptedProgram(program: str, memory_descriptors: Dict[str, ParameterSpec], ro_sources: Dict[MemoryReference, str], recalculation_table: List[str])[source]

Bases: object

Encrypted binary, executable on a QPU.

copy() EncryptedProgram[source]

Return a deep copy of this EncryptedProgram.

memory_descriptors: Dict[str, ParameterSpec]

Descriptors for memory executable’s regions, mapped by name.

program: str

String representation of an encrypted Quil program.

recalculation_table: List[str]

A mapping from memory references to the original gate arithmetic.

ro_sources: Dict[MemoryReference, str]

Readout sources, mapped by memory reference.

class pyquil.api.ExecutionOptions

Bases: object

api_options
static builder()
connection_strategy
static default()
timeout_seconds
class pyquil.api.QAM[source]

Bases: ABC, Generic[T]

Quantum Abstract Machine: This class acts as a generic interface describing how a classical computer interacts with a live quantum computer.

abstract execute(executable: EncryptedProgram | Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None, **kwargs: Any) T[source]

Run an executable on a QAM, returning a handle to be used to retrieve results.

Parameters:
  • executable – The executable program to be executed by the QAM.

  • memory_map – A mapping of memory regions to a list containing the values to be written into that memory region for the run.

abstract execute_with_memory_map_batch(executable: EncryptedProgram | Program, memory_maps: Iterable[Mapping[str, Sequence[int] | Sequence[float]]], **kwargs: Any) List[T][source]

Execute a QuantumExecutable with one or more memory_maps, returning handles to be used to retrieve results.

How these programs are batched and executed is determined by the executor. See their respective documentation for details.

Returns a list of handles that can be used to fetch results with QAM#get_result.

abstract get_result(execute_response: T) QAMExecutionResult[source]

Retrieve the results associated with a previous call to QAM#execute.

Parameters:

execute_response – The return value from a call to execute.

run(executable: EncryptedProgram | Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None, **kwargs: Any) QAMExecutionResult[source]

Run an executable to completion on the QAM.

class pyquil.api.QAMExecutionResult(executable: pyquil.api._abstract_compiler.EncryptedProgram | pyquil.quil.Program, data: qcs_sdk.ExecutionData)[source]

Bases: object

data: ExecutionData

The ExecutionData returned from the job. Consider using QAMExecutionResult#register_map or QAMExecutionResult#raw_readout_data to get at the data in a more convenient format.

executable: EncryptedProgram | Program

The executable corresponding to this result.

property execution_duration_microseconds: float | None

Duration job held exclusive hardware access. Defaults to None when information is not available.

get_memory_values() Mapping[str, MemoryValues][source]

Get the final memory values for any memory region that was both read from and written to during execution. This method will only return the final value in memory after the job has completed. Because of this, memory values should not be used to get readout data. Instead, use get_register_map() or get_raw_readout_data().

get_raw_readout_data() RawQVMReadoutData | RawQPUReadoutData[source]

Get the raw result data. This will be a flattened structure derived from qcs_sdk.qvm.QVMResultData or qcs_sdk.qpu.QPUResultData depending on where the job was run. See their respective documentation for more information on the data format.

This property should be used when running programs that use features like mid-circuit measurement and dynamic control flow on a QPU, since they can produce irregular result shapes that don’t necessarily fit in a rectangular matrix. If the program was run on a QVM, or doesn’t use those features, consider using the register_map property instead.

get_register_map() Dict[str, ndarray | None][source]

A mapping of a register name (ie. “ro”) to a np.ndarray containing the values for the register.

Raises a RegisterMatrixConversionError if the inner execution data for any of the registers would result in a jagged matrix. QPU result data is captured per measure, meaning a value is returned for every measure to a memory reference, not just once per shot. This is often the case in programs that re-use qubits or dynamic control flow, where measurements to the same memory reference might occur multiple times in a shot, or be skipped conditionally. In these cases, building a matrix with one value per memory reference, per shot would necessitate making assumptions about the data that could skew the data in undesirable ways. Instead, it’s recommended to manually build a matrix from the QPUResultData available on the raw_readout_data property.

Warning

An exception will _not_ be raised if the result data happens to fit a rectangular matrix, since it’s possible the register map is valid for some number of shots. Users should be aware of this possibility, especially when running programs that utilize qubit reuse or dynamic control flow.

property readout_data: Mapping[str, ndarray | None]

Readout data returned from the QAM, keyed on the name of the readout register or post-processing node.

class pyquil.api.QCSClient(tokens=None, api_url=None, auth_server=None, grpc_api_url=None, quilc_url=None, qvm_url=None)

Bases: object

api_url
grpc_api_url
static load(profile_name=None)
static load_async(profile_name=None)
quilc_url
qvm_url
class pyquil.api.QCSQuantumProcessor(quantum_processor_id: str, isa: InstructionSetArchitecture, noise_model: NoiseModel | None = None)[source]

Bases: AbstractQuantumProcessor

An AbstractQuantumProcessor initialized with an InstructionSetArchitecture returned from the QCS API. Notably, this class is able to serialize a CompilerISA based on the architecture instructions.

Initialize a new QCSQuantumProcessor.

Parameters:
  • quantum_processor_id – The id of the quantum processor.

  • isa – The QCS API InstructionSetArchitecture.

  • noise_model – An optional NoiseModel for configuring a noisy quantum_processor on the QVM.

noise_model: NoiseModel | None
quantum_processor_id: str
qubit_topology() Graph[source]

The connectivity of qubits in this quantum_processor given as a NetworkX graph.

qubits() List[int][source]

A sorted list of qubits in the quantum_processor topology.

to_compiler_isa() CompilerISA[source]

Construct an ISA suitable for targeting by compilation. This will raise an exception if the requested ISA is not supported by the quantum_processor.

class pyquil.api.QPU(*, quantum_processor_id: str, priority: int = 1, timeout: float | None = 30.0, client_configuration: QCSClient | None = None, endpoint_id: str | None = None, execution_options: ExecutionOptions | None = None)[source]

Bases: QAM[QPUExecuteResponse]

A connection to the QPU.

Parameters:
  • quantum_processor_id – Processor to run against.

  • priority – The priority with which to insert jobs into the QPU queue. Lower integers correspond to higher priority.

  • timeout – Time limit for requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

  • endpoint_id – Optional endpoint ID to be used for execution.

  • execution_options – The ExecutionOptions to use when executing a program. If provided, the options take precedence over the timeout and endpoint_id parameters.

cancel(execute_response: QPUExecuteResponse) None[source]

Cancel a job that has yet to begin executing.

This action is not atomic, and will attempt to cancel a job even if it cannot be cancelled. A job can be cancelled only if it has not yet started executing.

Cancellation is not guaranteed, as it is based on job state at the time of cancellation, and is completed on a best effort basis. This method will raise a QpuApiError if the job could not be cancelled.

Execution_response:

The response object returned from the execute method.

Raises:

QpuApiError – If there was a problem cancelling the job

execute(executable: EncryptedProgram | Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None, execution_options: ExecutionOptions | None = None, **__: Any) QPUExecuteResponse[source]

Enqueue a job for execution on the QPU. Returns a QPUExecuteResponse, a job descriptor which should be passed directly to QPU.get_result to retrieve results.

Param:
execution_options: An optional ExecutionOptions enum that can be used

to configure how the job is submitted and retrieved from the QPU. If unset, an appropriate default will be used.

execute_with_memory_map_batch(executable: EncryptedProgram | Program, memory_maps: Iterable[Mapping[str, Sequence[int] | Sequence[float]]], execution_options: ExecutionOptions | None = None, **__: Any) List[QPUExecuteResponse][source]

Execute a compiled program on a QPU with multiple sets of memory_maps.

See the documentation of qcs_sdk.qpu.api.submit_with_parameter_batch for more information.

Parameters:
  • program – The EncryptedProgram to execute.

  • memory_maps – A list containing one or more mappings of symbols to their desired values.

  • execution_options – The ExecutionOptions to use.

Returns:

A list of responses with a length and order corresponding to the memory_maps given.

get_result(execute_response: QPUExecuteResponse) QAMExecutionResult[source]

Retrieve results from execution on the QPU.

property quantum_processor_id: str

ID of quantum processor targeted.

class pyquil.api.QPUCompiler(*, quantum_processor_id: str, quantum_processor: AbstractQuantumProcessor, timeout: float = 10.0, client_configuration: QCSClient | None = None, api_options: TranslationOptions | None = None, quilc_client: QuilcClient | None = None)[source]

Bases: AbstractCompiler

Client to communicate with the compiler and translation service.

Instantiate a new QPU compiler client.

Parameters:
  • quantum_processor_id – Processor to target.

  • quantum_processor – Quantum processor to use as compilation target.

  • timeout – Time limit for requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

  • api_options – Options to pass to the QPU compiler API. See qcs-sdk-python for details.

api_options: TranslationOptions | None
get_calibration_program(force_refresh: bool = False) Program[source]

Get the Quil-T calibration program associated with the underlying QPU.

This will return a cached reference of the calibration program if present. Otherwise (or if forcing a refresh), it will fetch and store the calibration program from the QCS API.

Note that the returned program is a reference, meaning if you modify it directly, you will be updating the cached version, and future calls to this function will return your modified reference. If you want to update the program without impacting the cached version, you should make a copy of the returned program using Program.copy()

A calibration program contains a number of DEFCAL, DEFWAVEFORM, and DEFFRAME instructions. In sum, those instructions describe how a Quil-T program should be translated into analog instructions for execution on hardware.

Parameters:

force_refresh – Whether or not to fetch a new calibration program before returning.

Returns:

A Program object containing the calibration definitions.

native_quil_to_executable(nq_program: Program, *, api_options: TranslationOptions | None = None, **kwargs: Any) EncryptedProgram | Program[source]

Convert a native Quil program into an executable binary which can be executed by a QPU.

If api_options is provided, it overrides the options set on self.

reset() None[source]

Reset the state of the QPUCompiler.

pyquil.api.QPUCompilerAPIOptions

alias of TranslationOptions

class pyquil.api.QVM(noise_model: NoiseModel | None = None, gate_noise: Tuple[float, float, float] | None = None, measurement_noise: Tuple[float, float, float] | None = None, random_seed: int | None = None, timeout: float = 10.0, client: QVMClient | None = None)[source]

Bases: QAM[QVMExecuteResponse]

A virtual machine that classically emulates the execution of Quil programs.

Parameters:
  • noise_model – A noise model that describes noise to apply when emulating a program’s execution.

  • gate_noise – A tuple of three numbers [Px, Py, Pz] indicating the probability of an X, Y, or Z gate getting applied to each qubit after a gate application or reset. The default value of None indicates no noise.

  • measurement_noise – A tuple of three numbers [Px, Py, Pz] indicating the probability of an X, Y, or Z gate getting applied before a measurement. The default value of None indicates no noise.

  • random_seed – A seed for the QVM’s random number generators. Either None (for an automatically generated seed) or a non-negative integer.

  • timeout – Time limit for requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

connect() None[source]
execute(executable: EncryptedProgram | Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None, **__: Any) QVMExecuteResponse[source]

Synchronously execute the input program to completion.

execute_with_memory_map_batch(executable: EncryptedProgram | Program, memory_maps: Iterable[Mapping[str, Sequence[int] | Sequence[float]]], **__: Any) List[QVMExecuteResponse][source]

Executes a single program on the QVM with multiple memory maps.

This method is a convenience wrapper around QVM#execute and isn’t more efficient than making multiple seperate requests to the QVM.

get_result(execute_response: QVMExecuteResponse) QAMExecutionResult[source]

Return the results of execution on the QVM.

get_version_info() str[source]

Return version information for the QVM.

Returns:

String with version information

class pyquil.api.QVMCompiler(*, quantum_processor: AbstractQuantumProcessor, timeout: float = 10.0, client_configuration: QCSClient | None = None, quilc_client: QuilcClient | None = None)[source]

Bases: AbstractCompiler

Client to communicate with the compiler.

Client to communicate with compiler.

Parameters:
  • quantum_processor – Quantum processor to use as compilation target.

  • timeout – Number of seconds to wait for a response from the client.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

native_quil_to_executable(nq_program: Program, **kwargs: Any) EncryptedProgram | Program[source]

Compile a native quil program to a binary executable.

Parameters:

nq_program – Native quil to compile

Returns:

An (opaque) binary executable

class pyquil.api.QuantumComputer(*, name: str, qam: QAM[Any], compiler: AbstractCompiler, symmetrize_readout: bool = False)[source]

Bases: object

A quantum computer for running quantum programs.

A quantum computer has various characteristics like supported gates, qubits, qubit topologies, gate fidelities, and more. A quantum computer also has the ability to run quantum programs.

A quantum computer can be a real Rigetti QPU that uses superconducting transmon qubits to run quantum programs, or it can be an emulator like the QVM with noise models and mimicked topologies.

Parameters:
  • name – A string identifying this particular quantum computer.

  • qam – A quantum abstract machine which handles executing quantum programs. This dispatches to a QVM or QPU.

  • symmetrize_readout – Whether to apply readout error symmetrization. See run_symmetrized_readout() for a complete description.

calibrate(experiment: Experiment) List[ExperimentResult][source]

Perform readout calibration on the various multi-qubit observables involved in the provided Experiment.

Parameters:

experiment – The Experiment to calibrate readout error for.

Returns:

A list of ExperimentResult objects that contain the expectation values that correspond to the scale factors resulting from symmetric readout error.

compile(program: Program, to_native_gates: bool = True, optimize: bool = True, *, protoquil: bool | None = None) EncryptedProgram | Program[source]

A high-level interface to program compilation.

Compilation currently consists of two stages. Please see the AbstractCompiler docs for more information. This function does all stages of compilation.

Right now both to_native_gates and optimize must be either both set or both unset. More modular compilation passes may be available in the future.

Additionally, a call to compile also calls the reset method if one is running on the QPU. This is a bit of a sneaky hack to guard against stale compiler connections, but shouldn’t result in any material hit to performance (especially when taking advantage of parametric compilation for hybrid applications).

Parameters:
  • program – A Program

  • to_native_gates – Whether to compile non-native gates to native gates.

  • optimize – Whether to optimize the program to reduce the number of operations.

  • protoquil – Whether to restrict the input program to and the compiled program to protoquil (executable on QPU). A value of None means defer to server.

Returns:

An executable binary suitable for passing to QuantumComputer.run().

property quantum_processor: AbstractQuantumProcessor

The quantum processor associated with this quantum computer.

qubit_topology() <module 'networkx.classes.graph' from '/home/docs/checkouts/readthedocs.org/user_builds/pyquil/envs/latest/lib/python3.10/site-packages/networkx/classes/graph.py'>[source]

Return a NetworkX graph representation of this QuantumComputer’s quantum_processor’s qubit connectivity.

See AbstractQuantumProcessor.qubit_topology() for more.

qubits() List[int][source]

Return a sorted list of this QuantumComputer’s quantum_processor’s qubits

See AbstractQuantumProcessor.qubits() for more.

run(executable: EncryptedProgram | Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None, **kwargs: Any) QAMExecutionResult[source]

Run a quil executable. All parameters in the executable must have values applied using Program#write_memory.

Parameters:
  • executable – The program to run, previously compiled as needed for its target QAM.

  • memory_map – A mapping of memory regions to a list containing the values to be written into that memory region for the run.

Returns:

execution result including readout data.

run_experiment(experiment: Experiment, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None) List[ExperimentResult][source]

Run an Experiment on a QVM or QPU backend. An Experiment is composed of:

  • A main Program body (or ansatz).

  • A collection of ExperimentSetting objects, each of which encodes a particular state preparation and measurement.

  • A SymmetrizationLevel for enacting different readout symmetrization strategies.

  • A number of shots to collect for each (unsymmetrized) ExperimentSetting.

Because the main Program is static from run to run of an Experiment, we can leverage our platform’s Parametric Compilation feature. This means that the Program can be compiled only once, and the various alterations due to state preparation, measurement, and symmetrization can all be realized at runtime by providing a memory_map. Thus, the steps in the experiment method are as follows:

  1. Generate a parameterized program corresponding to the Experiment (see the Experiment.generate_experiment_program() method for more details on how it changes the main body program to support state preparation, measurement, and symmetrization).

  1. Compile the parameterized program into a parametric (binary) executable, which contains declared variables that can be assigned at runtime.

  2. For each ExperimentSetting in the Experiment, we repeat the following:

    1. Build a collection of memory maps that correspond to the various state preparation, measurement, and symmetrization specifications.

    2. Run the parametric executable on the QVM or QPU backend, providing the memory map to assign variables at runtime.

    3. Extract the desired statistics from the classified bitstrings that are produced by the QVM or QPU backend, and package them in an ExperimentResult object.

  1. Return the list of ExperimentResult objects.

This method is extremely useful shorthand for running near-term applications and algorithms, which often have this ansatz + settings structure.

Parameters:
  • experiment – The Experiment to run.

  • memory_map – A dictionary mapping declared variables / parameters to their values. The values are a list of floats or integers. Each float or integer corresponds to a particular classical memory register. The memory map provided to the experiment method corresponds to variables in the main body program that we would like to change at runtime (e.g. the variational parameters provided to the ansatz of the variational quantum eigensolver).

Returns:

A list of ExperimentResult objects containing the statistics gathered according to the specifications of the Experiment.

run_symmetrized_readout(program: Program, trials: int, symm_type: int = 3, meas_qubits: List[int] | None = None) ndarray[source]

Run a quil program in such a way that the readout error is made symmetric. Enforcing symmetric readout error is useful in simplifying the assumptions in some near term error mitigation strategies, see measure_observables for more information.

The simplest example is for one qubit. In a noisy quantum_processor, the probability of accurately reading the 0 state might be higher than that of the 1 state; due to e.g. amplitude damping. This makes correcting for readout more difficult. In the simplest case, this function runs the program normally (trials//2) times. The other half of the time, it will insert an X gate prior to any MEASURE instruction and then flip the measured classical bit back. Overall this has the effect of symmetrizing the readout error.

The details. Consider preparing the input bitstring |i> (in the computational basis) and measuring in the Z basis. Then the Confusion matrix for the readout error is specified by the probabilities

p(j|i) := Pr(measured = j | prepared = i ).

In the case of a single qubit i,j in [0,1] then: there is no readout error if p(0|0) = p(1|1) = 1. the readout error is symmetric if p(0|0) = p(1|1) = 1 - epsilon. the readout error is asymmetric if p(0|0) != p(1|1).

If your quantum computer has this kind of asymmetric readout error then qc.run_symmetrized_readout will symmetrize the readout error.

The readout error above is only asymmetric on a single bit. In practice the confusion matrix on n bits need not be symmetric, e.g. for two qubits p(ij|ij) != 1 - epsilon for all i,j. In these situations a more sophisticated means of symmetrization is needed; and we use orthogonal arrays (OA) built from Hadamard matrices.

The symmetrization types are specified by an int; the types available are: -1 – exhaustive symmetrization uses every possible combination of flips 0 – trivial that is no symmetrization 1 – symmetrization using an OA with strength 1 2 – symmetrization using an OA with strength 2 3 – symmetrization using an OA with strength 3 In the context of readout symmetrization the strength of the orthogonal array enforces the symmetry of the marginal confusion matrices.

By default a strength 3 OA is used; this ensures expectations of the form <b_k . b_j . b_i> for bits any bits i,j,k will have symmetric readout errors. Here expectation of a random variable x as is denote <x> = sum_i Pr(i) x_i. It turns out that a strength 3 OA is also a strength 2 and strength 1 OA it also ensures <b_j . b_i> and <b_i> have symmetric readout errors for any bits b_j and b_i.

Parameters:
  • program – The program to run symmetrized readout on.

  • trials – The minimum number of times to run the program; it is recommend that this number should be in the hundreds or thousands. This parameter will be mutated if necessary.

  • symm_type – the type of symmetrization

  • meas_qubits – An advanced feature. The groups of measurement qubits. Only these qubits will be symmetrized over, even if the program acts on other qubits.

Returns:

A numpy array of shape (trials, len(ro-register)) that contains 0s and 1s.

run_with_memory_map_batch(executable: EncryptedProgram | Program, memory_maps: Iterable[Mapping[str, Sequence[int] | Sequence[float]]], **kwargs: Any) List[QAMExecutionResult][source]

Run a QuantumExecutable with one or more memory_maps, returning a list of results corresponding to the length and order of the given MemoryMaps.

How these programs are batched and executed is determined by the executor. See their respective documentation for details.

Returns a list of QAMExecutionResult, which can be used to fetch results in QAM#get_result.

to_compiler_isa() CompilerISA[source]

Return a CompilerISA for this QuantumComputer’s quantum_processor.

See AbstractQuantumProcessor.to_compiler_isa() for more.

class pyquil.api.WavefunctionSimulator(*, gate_noise: Tuple[float, float, float] | None = None, measurement_noise: Tuple[float, float, float] | None = None, random_seed: int | None = None, timeout: float = 10.0, client_configuration: QCSClient | None = None)[source]

Bases: object

A simulator that propagates a wavefunction representation of a quantum state.

Parameters:
  • gate_noise – A tuple of three numbers [Px, Py, Pz] indicating the probability of an X, Y, or Z gate getting applied to each qubit after a gate application or reset.

  • measurement_noise – A tuple of three numbers [Px, Py, Pz] indicating the probability of an X, Y, or Z gate getting applied before a measurement.

  • random_seed – A seed for the simulator’s random number generators. Either None (for an automatically generated seed) or a non-negative integer.

  • timeout – Time limit for requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

static augment_program_with_memory_values(quil_program: Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]]) Program[source]
expectation(prep_prog: Program, pauli_terms: PauliSum | List[PauliTerm], memory_map: Dict[str, List[int | float]] | None = None) float | ndarray[source]

Calculate the expectation value of Pauli operators given a state prepared by prep_program.

If pauli_terms is a PauliSum then the returned value is a single float, otherwise the returned value is an array of values, one for each PauliTerm in the list.

Note

If your program contains measurements or noisy gates, this method may not do what you want. If the execution of quil_program is non-deterministic then the final wavefunction from which the expectation value is calculated only represents a stochastically generated sample and the wavefunctions returned by different wavefunction calls will generally be different.

Parameters:
  • prep_prog – A program that prepares the state on which we measure the expectation.

  • pauli_terms – A Pauli representation of a quantum operator.

  • memory_map

    An assignment of classical registers to values, representing an initial state for the QAM’s classical memory.

    This is expected to be of type Dict[str, List[Union[int, float]]], where the keys are memory region names and the values are arrays of initialization data.

Returns:

Either a float or array floats depending on pauli_terms.

run_and_measure(quil_program: Program, qubits: List[int] | None = None, trials: int = 1, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None) ndarray[source]

Run a Quil program once to determine the final wavefunction, and measure multiple times.

Alternatively, consider using wavefunction and calling sample_bitstrings on the resulting object.

For a large wavefunction and a low-medium number of trials, use this function. On the other hand, if you’re sampling a small system many times you might want to use Wavefunction.sample_bitstrings.

Note

If your program contains measurements or noisy gates, this method may not do what you want. If the execution of quil_program is non-deterministic then the final wavefunction from which the returned bitstrings are sampled itself only represents a stochastically generated sample and the outcomes sampled from different run_and_measure calls generally sample different bitstring distributions.

Parameters:
  • quil_program – The program to run and measure

  • qubits – An optional list of qubits to measure. The order of this list is respected in the returned bitstrings. If not provided, all qubits used in the program will be measured and returned in their sorted order.

  • trials (int) – Number of times to sample from the prepared wavefunction.

  • memory_map

    An assignment of classical registers to values, representing an initial state for the QAM’s classical memory.

    This is expected to be of type Dict[str, List[Union[int, float]]], where the keys are memory region names and the values are arrays of initialization data.

Returns:

An array of measurement results (0 or 1) of shape (trials, len(qubits))

wavefunction(quil_program: Program, memory_map: Mapping[str, Sequence[int] | Sequence[float]] | None = None) Wavefunction[source]

Simulate a Quil program and return the wavefunction.

Note

If your program contains measurements or noisy gates, this method may not do what you want. If the execution of quil_program is non-deterministic then the final wavefunction only represents a stochastically generated sample and the wavefunctions returned by different wavefunction calls will generally be different.

Parameters:
  • quil_program – A Quil program.

  • memory_map

    An assignment of classical registers to values, representing an initial state for the QAM’s classical memory.

    This is expected to be of type Dict[str, List[Union[int, float]]], where the keys are memory region names and the values are arrays of initialization data.

Returns:

A Wavefunction object representing the state of the QVM.

pyquil.api.get_qc(name: str, *, as_qvm: bool | None = None, noisy: bool | None = None, compiler_timeout: float = 30.0, execution_timeout: float = 30.0, client_configuration: QCSClient | None = None, endpoint_id: str | None = None, quilc_client: QuilcClient | None = None, qvm_client: QVMClient | None = None) QuantumComputer[source]

Get a quantum computer.

A quantum computer is an object of type 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("Aspen-M-3-qvm")  
>>> qc = get_qc("Aspen-M-3", as_qvm=True)  

and will construct a simulator of an Aspen-M-3 lattice. 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-square-qvm")
>>> qc = get_qc("9q-square", as_qvm=True)

Finally, you can get request a QVM with “no” topology of a given number of qubits (technically, it’s a fully connected graph among the given number of qubits) with:

>>> qc = get_qc("5q-qvm") # or "6q-qvm", or "34q-qvm", ...

These less-realistic, fully-connected QVMs will also be more lenient on what types of programs they will run. Specifically, you do not need to do any compilation. For the other, realistic QVMs you must use qc.compile() or qc.compiler.native_quil_to_executable() prior to qc.run().

The Rigetti QVM must be downloaded from https://www.rigetti.com/forest and run as a server alongside your python program. To use pyQuil’s built-in QVM, replace all "-qvm" suffixes with "-pyqvm":

>>> qc = get_qc("5q-pyqvm")

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

>>> qc = get_qc("9q-square-qvm") # qc is fully specified by its name
>>> qc = get_qc("9q-square-qvm", as_qvm=True) # redundant, but ok
>>> qc = get_qc("9q-square-qvm", as_qvm=False) # Error!
Traceback (most recent call last):
ValueError: The provided qc name indicates you are getting a QVM, but you have specified `as_qvm=False`

Use 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 QuantumComputer object by hand. Please refer to the documentation on QuantumComputer for more information.

Parameters:
  • name – The name of the desired quantum computer. This should correspond to a name returned by list_quantum_computers(). Names ending in “-qvm” will return a QVM. Names ending in “-pyqvm” will return a PyQVM. Names ending in “-noisy-qvm” will return a QVM with a noise model. Otherwise, we will return a QPU with the given name.

  • 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

  • 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 generic QVM noise model is simple T1 and T2 noise plus readout error. See decoherence_noise_with_asymmetric_ro(). Note, we currently do not support noise models based on QCS hardware; a value of True` will result in an error if the requested QPU is a QCS hardware QPU.

  • compiler_timeout – Time limit for compilation requests, in seconds.

  • execution_timeout – Time limit for execution requests, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded. For more information on setting up QCS credentials, see documentation for using the QCS CLI: [https://docs.rigetti.com/qcs/guides/using-the-qcs-cli#configuring-credentials].

  • endpoint_id – Optional quantum processor endpoint ID, as used in the QCS API Docs.

Returns:

A pre-configured QuantumComputer

pyquil.api.list_quantum_computers(qpus: bool = True, qvms: bool = True, timeout: float = 10.0, client_configuration: QCSClient | None = None) List[str][source]

List the names of available quantum computers

Parameters:
  • qpus – Whether to include QPUs in the list.

  • qvms – Whether to include QVMs in the list.

  • timeout – Time limit for request, in seconds.

  • client_configuration – Optional client configuration. If none is provided, a default one will be loaded.

pyquil.api.local_forest_runtime(*, host: str = '127.0.0.1', qvm_port: int = 5000, quilc_port: int = 5555, use_protoquil: bool = False) Iterator[Tuple[Popen | None, Popen | None]][source]

A context manager for local QVM and QUIL compiler.

You must first have installed the qvm and quilc executables from the forest SDK. [https://www.rigetti.com/forest]

This context manager will ensure that the designated ports are not used, start up qvm and quilc proccesses if possible and terminate them when the context is exited. If one of the ports is in use, a RuntimeWarning will be issued and the qvm/quilc process won’t be started.

Note

Only processes started by this context manager will be terminated on exit, no external process will be touched.

>>> from pyquil import get_qc, Program
>>> from pyquil.gates import CNOT, Z
>>> from pyquil.api import local_forest_runtime
>>>
>>> qvm = get_qc('9q-square-qvm')
>>> prog = Program(Z(0), CNOT(0, 1))
>>>
>>> with local_forest_runtime():  
>>>     results = qvm.run(prog)   
Parameters:
  • host – Host on which qvm and quilc should listen on.

  • qvm_port – Port which should be used by qvm.

  • quilc_port – Port which should be used by quilc.

  • use_protoquil – Restrict input/output to protoquil.

Warning

If use_protoquil is set to True language features you need may be disabled. Please use it with caution.

Raises:

FileNotFoundError: If either executable is not installed.

Returns:

The returned tuple contains two subprocess.Popen objects for the qvm and the quilc processes. If one of the designated ports is in use, the process won’t be started and the respective value in the tuple will be None.