pyquil.api package

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

class pyquil.api.AbstractCompiler(*, quantum_processor: pyquil.quantum_processor._base.AbstractQuantumProcessor, timeout: float, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration])[source]

Bases: abc.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: pyquil.quil.Program) Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.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: pyquil.quil.Program, *, protoquil: Optional[bool] = None) pyquil.quil.Program[source]

Compile an arbitrary quil program according to the ISA of self.quantum_processor.

Parameters
  • program – Arbitrary quil to compile

  • protoquil – Whether to restrict to protoquil (None means defer to server)

Returns

Native quil and compiler metadata

reset() None[source]

Reset the state of the this compiler.

class pyquil.api.BenchmarkConnection(*, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None)[source]

Bases: pyquil.api._abstract_compiler.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: pyquil.quil.Program, pauli_in: pyquil.paulis.PauliTerm) pyquil.paulis.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[pyquil.quilbase.Gate], seed: Optional[int] = None, interleaver: Optional[pyquil.quil.Program] = None) List[pyquil.quil.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, rpcq.messages.ParameterSpec], ro_sources: Dict[pyquil.quilatom.MemoryReference, str], recalculation_table: Dict[rpcq.messages.ParameterAref, Union[Expression, int, float, complex]], _memory: pyquil._memory.Memory)[source]

Bases: object

Encrypted binary, executable on a QPU.

copy() pyquil.api._abstract_compiler.EncryptedProgram[source]

Return a deep copy of this EncryptedProgram.

memory_descriptors: Dict[str, rpcq.messages.ParameterSpec]

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

program: str

String representation of an encrypted Quil program.

recalculation_table: Dict[rpcq.messages.ParameterAref, Union[Expression, int, float, complex]]

A mapping from memory references to the original gate arithmetic.

ro_sources: Dict[pyquil.quilatom.MemoryReference, str]

Readout sources, mapped by memory reference.

write_memory(*, region_name: str, value: Union[int, float, Sequence[int], Sequence[float]], offset: Optional[int] = None) pyquil.api._abstract_compiler.EncryptedProgram[source]
class pyquil.api.EngagementManager(*, client_configuration: qcs_api_client.client._configuration.configuration.QCSClientConfiguration)[source]

Bases: object

Fetches (and caches) engagements for use when accessing a QPU.

Instantiate a new engagement manager.

Parameters

client_configuration – Client configuration, used for refreshing engagements.

get_engagement(*, quantum_processor_id: str, request_timeout: float = 10.0, endpoint_id: Optional[str] = None) qcs_api_client.models.engagement_with_credentials.EngagementWithCredentials[source]

Gets an engagement for the given quantum processor endpoint.

If an engagement was already fetched previously and remains valid, it will be returned instead of creating a new engagement.

Parameters
  • quantum_processor_id – Quantum processor being engaged.

  • request_timeout – Timeout for request, in seconds.

  • endpoint_id – Optional ID of the endpoint to use for engagement. If provided, it must correspond to an endpoint serving the provided Quantum Processor.

Returns

Fetched or cached engagement.

Raises
  • QPUUnavailableError – raised when the QPU is unavailable due, and provides a suggested number of seconds to wait until retrying.

  • QCSHTTPStatusError – raised when creating an engagement fails for a reason that is not due to QPU unavailability.

class pyquil.api.QAM(*args, **kwds)[source]

Bases: abc.ABC, Generic[pyquil.api._qam.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: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]) pyquil.api._qam.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.

abstract get_result(execute_response: pyquil.api._qam.T) pyquil.api._qam.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: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]) pyquil.api._qam.QAMExecutionResult[source]

Run an executable to completion on the QAM.

class pyquil.api.QAMExecutionResult(executable: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program], readout_data: Mapping[str, Union[numpy.ndarray, NoneType]] = <factory>, execution_duration_microseconds: Union[int, NoneType] = None)[source]

Bases: object

executable: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]

The executable corresponding to this result.

execution_duration_microseconds: Optional[int] = None

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

readout_data: Mapping[str, Optional[numpy.ndarray]]

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

class pyquil.api.QCSClientConfiguration(*, profile_name: str, secrets: qcs_api_client.client._configuration.secrets.QCSClientConfigurationSecrets, settings: qcs_api_client.client._configuration.settings.QCSClientConfigurationSettings)[source]

Bases: pydantic.main.BaseModel

A user’s settings and secrets along with a specified profile name.

This class contains a full representation of user specified QCSClientConfigurationSecrets and QCSClientConfigurationSettings, as well as a profile_name which indicates which QCSClientConfigurationSettingsProfile to access within QCSClientConfigurationSettings.profiles.

Typically, clients will simply call QCSClientConfiguration.load, to initialize this class from the specified secrets and settings paths.

Create a new model by parsing and validating input data from keyword arguments.

Raises ValidationError if the input data cannot be parsed to form a valid model.

property auth_server: qcs_api_client.client._configuration.settings.QCSAuthServer

Returns the configured authorization server.

self.profile.auth_server_name serves as key to QCSClientConfigurationSettings.auth_servers.

Returns:

The specified QCSAuthServer.

Raises:
QCSClientConfigurationError: If

QCSClientConfigurationSettings.auth_servers does not have a value for the authorization server name.

property credentials: qcs_api_client.client._configuration.secrets.QCSClientConfigurationSecretsCredentials

Returns the configured QCSClientConfigurationSecretsCredentials

self.profile.credentials_name serves as key to QCSClientConfigurationSecrets.credentials.

Returns:

The specified QCSClientConfigurationSecretsCredentials.

Raises:
QCSClientConfigurationError: If

QCSClientConfigurationSettings.credentials does not have a value for the specified credentials name.

classmethod load(profile_name: Optional[str] = None, settings_file_path: Optional[os.PathLike] = None, secrets_file_path: Optional[os.PathLike] = None) qcs_api_client.client._configuration.configuration.QCSClientConfiguration[source]

Loads a fully specified QCSClientConfiguration from file.

It evaluates attribute values according to the following precedence: argument value > environment variable > default value.

Args:
profile_name: [env: QCS_PROFILE_NAME] The name of the profile

referenced in the fully parsed QCSClientConfigurationSettings.profiles. If the profile name does not exist on QCSClientConfigurationSettings, QCSClientConfiguration.profile will raise an error. The default value is “default”, which may be overridden by QCSClientConfigurationSettings.default_profile_name.

settings_file_path: [env: QCS_SETTINGS_FILE_PATH] The file path

from which to parse QCSClientConfigurationSettings. This file must exist in TOML format. The default value is ~/.qcs/settings.toml.

secrets_file_path: [env: QCS_SECRETS_FILE_PATH] The file path

from which to parse QCSClientConfigurationSecrets. This file must exist in TOML format. The default value is ~/.qcs/secrets.toml.

Returns:

A fully specified QCSClientConfiguration, which QCSAuth may use for adding refreshed OAuth2 access tokens to outgoing HTTP requests.

property profile: qcs_api_client.client._configuration.settings.QCSClientConfigurationSettingsProfile

Returns the configured QCSClientConfigurationSettingsProfile.

self.profile_name serves as key to QCSClientConfigurationSettingsProfile.profiles.

Returns:

The specified QCSClientConfigurationSettingsProfile.

Raises:
QCSClientConfigurationError: If

QCSClientConfigurationSettings.profiles does not have a value for the specified profile name.

profile_name: str
secrets: qcs_api_client.client._configuration.secrets.QCSClientConfigurationSecrets
settings: qcs_api_client.client._configuration.settings.QCSClientConfigurationSettings
class pyquil.api.QCSQuantumProcessor(quantum_processor_id: str, isa: qcs_api_client.models.instruction_set_architecture.InstructionSetArchitecture, noise_model: Optional[pyquil.noise.NoiseModel] = None)[source]

Bases: pyquil.quantum_processor._base.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: Optional[pyquil.noise.NoiseModel]
quantum_processor_id: str
qubit_topology() networkx.classes.graph.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() pyquil.external.rpcq.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 = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None, engagement_manager: Optional[pyquil.api._engagement_manager.EngagementManager] = None, endpoint_id: Optional[str] = None)[source]

Bases: pyquil.api._qam.QAM[pyquil.api._qpu.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 engagement.

  • engagement_manager – Optional engagement manager. If none is provided, a default one will be created.

execute(executable: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]) pyquil.api._qpu.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.

get_result(execute_response: pyquil.api._qpu.QPUExecuteResponse) pyquil.api._qam.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: pyquil.quantum_processor._base.AbstractQuantumProcessor, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None)[source]

Bases: pyquil.api._abstract_compiler.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.

get_calibration_program(force_refresh: bool = False) pyquil.quil.Program[source]

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

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

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: pyquil.quil.Program) Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program][source]

Compile a native quil program to a binary executable.

Parameters

nq_program – Native quil to compile

Returns

An (opaque) binary executable

reset() None[source]

Reset the state of the QPUCompiler.

class pyquil.api.QVM(noise_model: Optional[pyquil.noise.NoiseModel] = None, gate_noise: Optional[Tuple[float, float, float]] = None, measurement_noise: Optional[Tuple[float, float, float]] = None, random_seed: Optional[int] = None, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None)[source]

Bases: pyquil.api._qam.QAM[pyquil.api._qvm.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: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]) pyquil.api._qvm.QVMExecuteResponse[source]

Synchronously execute the input program to completion.

get_result(execute_response: pyquil.api._qvm.QVMExecuteResponse) pyquil.api._qam.QAMExecutionResult[source]

Return the results of execution on the QVM.

Because QVM execution is synchronous, this is a no-op which returns its input.

get_version_info() str[source]

Return version information for the QVM.

Returns

String with version information

class pyquil.api.QVMCompiler(*, quantum_processor: pyquil.quantum_processor._base.AbstractQuantumProcessor, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None)[source]

Bases: pyquil.api._abstract_compiler.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: pyquil.quil.Program) Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.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: pyquil.api._qam.QAM[Any], compiler: pyquil.api._abstract_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: pyquil.experiment._main.Experiment) List[pyquil.experiment._result.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: pyquil.quil.Program, to_native_gates: bool = True, optimize: bool = True, *, protoquil: Optional[bool] = None) Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.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: pyquil.quantum_processor._base.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/v3.5.0/lib/python3.7/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: Union[pyquil.api._abstract_compiler.EncryptedProgram, pyquil.quil.Program]) pyquil.api._qam.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.

Returns

execution result including readout data.

run_experiment(experiment: pyquil.experiment._main.Experiment, memory_map: Optional[Mapping[str, Sequence[Union[int, float]]]] = None) List[pyquil.experiment._result.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: pyquil.quil.Program, trials: int, symm_type: int = 3, meas_qubits: Optional[List[int]] = None) numpy.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.

to_compiler_isa() pyquil.external.rpcq.CompilerISA[source]

Return a CompilerISA for this QuantumComputer’s quantum_processor.

See AbstractQuantumProcessor.to_compiler_isa() for more.

class pyquil.api.WavefunctionSimulator(*, gate_noise: Optional[Tuple[float, float, float]] = None, measurement_noise: Optional[Tuple[float, float, float]] = None, random_seed: Optional[int] = None, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = 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: pyquil.quil.Program, memory_map: Dict[str, List[Union[int, float]]]) pyquil.quil.Program[source]
expectation(prep_prog: pyquil.quil.Program, pauli_terms: Union[pyquil.paulis.PauliSum, List[pyquil.paulis.PauliTerm]], memory_map: Optional[Dict[str, List[Union[int, float]]]] = None) Union[float, numpy.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: pyquil.quil.Program, qubits: Optional[List[int]] = None, trials: int = 1, memory_map: Optional[Dict[str, List[Union[int, float]]]] = None) numpy.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: pyquil.quil.Program, memory_map: Optional[Dict[str, List[Union[int, float]]]] = None) pyquil.wavefunction.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: Optional[bool] = None, noisy: Optional[bool] = None, compiler_timeout: float = 10.0, execution_timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = None, endpoint_id: Optional[str] = None, engagement_manager: Optional[pyquil.api._engagement_manager.EngagementManager] = None) pyquil.api._quantum_computer.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-1-16Q-A-noisy-qvm")
>>> qc = get_qc("Aspen-1-16Q-A", as_qvm=True, noisy=True)

and will construct a simulator of an Aspen-1 lattice with a noise model based on quantum_processor 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-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!

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.

  • engagement_manager – Optional engagement manager. If none is provided, a default one will be created.

Returns

A pre-configured QuantumComputer

pyquil.api.list_quantum_computers(qpus: bool = True, qvms: bool = True, timeout: float = 10.0, client_configuration: Optional[qcs_api_client.client._configuration.configuration.QCSClientConfiguration] = 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[Optional[subprocess.Popen], Optional[subprocess.Popen]]][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_and_measure(prog, trials=10)
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.