pytket.backends

Contents

pytket.backends#

Contains Backend abstract class and associated methods. In pytket a Backend represents an interface between pytket and a quantum device or simulator. Different backends are defined in the various pytket extension modules and inherit from the core pytket Backend class.

There are several example notebooks on pytket Backends. If you are interested in developing your own Backend or pytket extension then see the creating backends tutorial.

Notebook tutorials specific to the QuantinuumBackend can be found here.

See also the Running on backends section of the pytket user manual.

Backends for connecting to devices and simulators directly from pytket

pytket.backends.backend#

class pytket.backends.Backend[source]#

This abstract class defines the structure of a backend as something that can run quantum circuits and produce output as at least one of shots, counts, state, or unitary

__init__() None[source]#
classmethod available_devices(**kwargs: Any) List[BackendInfo][source]#

Retrieve all available devices as a list of BackendInfo objects, including device name, architecture, supported gate set, gate errors, and other hardware-specific information.

Returns:

A list of BackendInfo objects describing available devices.

Return type:

List[BackendInfo]

cancel(handle: ResultHandle) None[source]#

Cancel a job.

Parameters:

handle (ResultHandle) – handle to job

Raises:

NotImplementedError – If backend does not support job cancellation

abstract circuit_status(handle: ResultHandle) CircuitStatus[source]#

Return a CircuitStatus reporting the status of the circuit execution corresponding to the ResultHandle

abstract default_compilation_pass(optimisation_level: int = 2) BasePass[source]#

A suggested compilation pass that will will, if possible, produce an equivalent circuit suitable for running on this backend.

At a minimum it will ensure that compatible gates are used and that all two- qubit interactions are compatible with the backend’s qubit architecture. At higher optimisation levels, further optimisations may be applied.

This is a an abstract method which is implemented in the backend itself, and so is tailored to the backend’s requirements.

Parameters:

optimisation_level (int, optional) –

The level of optimisation to perform during compilation.

  • Level 0 does the minimum required to solves the device constraints, without any optimisation.

  • Level 1 additionally performs some light optimisations.

  • Level 2 (the default) adds more computationally intensive optimisations that should give the best results from execution.

Returns:

Compilation pass guaranteeing required predicates.

Return type:

BasePass

empty_cache() None[source]#

Manually empty the result cache on the backend.

get_compiled_circuit(circuit: Circuit, optimisation_level: int = 2) Circuit[source]#

Return a single circuit compiled with default_compilation_pass(). See Backend.get_compiled_circuits().

get_compiled_circuits(circuits: Sequence[Circuit], optimisation_level: int = 2) List[Circuit][source]#

Compile a sequence of circuits with default_compilation_pass() and return the list of compiled circuits (does not act in place).

As well as applying a degree of optimisation (controlled by the optimisation_level parameter), this method tries to ensure that the circuits can be run on the backend (i.e. successfully passed to process_circuits()), for example by rebasing to the supported gate set, or routing to match the connectivity of the device. However, this is not always possible, for example if the circuit contains classical operations that are not supported by the backend. You may use valid_circuit() to check whether the circuit meets the backend’s requirements after compilation. This validity check is included in process_circuits() by default, before any circuits are submitted to the backend.

If the validity check fails, you can obtain more information about the failure by iterating through the predicates in the required_predicates property of the backend, and running the verify() method on each in turn with your circuit.

Parameters:
  • circuits – The circuits to compile.

  • optimisation_level (int, optional) – The level of optimisation to perform during compilation. See default_compilation_pass() for a description of the different levels (0, 1 or 2). Defaults to 2.

Returns:

Compiled circuits.

Return type:

List[Circuit]

get_result(handle: ResultHandle, **kwargs: int | float | str | None) BackendResult[source]#

Return a BackendResult corresponding to the handle.

Use keyword arguments to specify parameters to be used in retrieving results. See specific Backend derived class for available parameters, from the following list:

  • timeout: maximum time to wait for remote job to finish

  • wait: polling interval between remote calls to check job status

Parameters:

handle (ResultHandle) – handle to results

Returns:

Results corresponding to handle.

Return type:

BackendResult

get_results(handles: Iterable[ResultHandle], **kwargs: int | float | str | None) List[BackendResult][source]#

Return results corresponding to handles.

Parameters:

handles – Iterable of handles

Returns:

List of results

Keyword arguments are as for get_result, and apply to all jobs.

pop_result(handle: ResultHandle) Dict[str, Any] | None[source]#

Remove cache entry corresponding to handle from the cache and return.

Parameters:

handle (ResultHandle) – ResultHandle object

Returns:

Cache entry corresponding to handle, if it was present

Return type:

Optional[ResultCache]

process_circuit(circuit: Circuit, n_shots: int | None = None, valid_check: bool = True, **kwargs: int | float | str | None) ResultHandle[source]#

Submit a single circuit to the backend for running. See Backend.process_circuits().

abstract process_circuits(circuits: Sequence[Circuit], n_shots: int | Sequence[int] | None = None, valid_check: bool = True, **kwargs: int | float | str | None) List[ResultHandle][source]#

Submit circuits to the backend for running. The results will be stored in the backend’s result cache to be retrieved by the corresponding get_<data> method.

If the postprocess keyword argument is set to True, and the backend supports the feature (see supports_contextual_optimisation()), then contextual optimisatioons are applied before running the circuit and retrieved results will have any necessary classical postprocessing applied. This is not enabled by default.

Use keyword arguments to specify parameters to be used in submitting circuits See specific Backend derived class for available parameters, from the following list:

  • seed: RNG seed for simulators

  • postprocess: if True, apply contextual optimisations

Note: If a backend is reused many times, the in-memory results cache grows indefinitely. Therefore, when processing many circuits on a statevector or unitary backend (whose results may occupy significant amounts of memory), it is advisable to run Backend.empty_cache() after each result is retrieved.

Parameters:
  • circuits (Sequence[Circuit]) – Circuits to process on the backend.

  • n_shots (Optional[Union[int, Iterable[int]], optional) – Number of shots to run per circuit. Optionally, this can be a list of shots specifying the number of shots for each circuit separately. None is to be used for state/unitary simulators. Defaults to None.

  • valid_check (bool, optional) – Explicitly check that all circuits satisfy all required predicates to run on the backend. Defaults to True

Returns:

Handles to results for each input circuit, as an interable in the same order as the circuits.

Return type:

List[ResultHandle]

abstract rebase_pass() BasePass[source]#

A single compilation pass that when run converts all gates in a Circuit to an OpType supported by the Backend (ignoring architecture constraints).

Returns:

Compilation pass that converts gates to primitives supported by Backend.

Return type:

BasePass

run_circuit(circuit: Circuit, n_shots: int | None = None, valid_check: bool = True, **kwargs: int | float | str | None) BackendResult[source]#

Submits a circuit to the backend and returns results

Parameters:
Returns:

Result

This is a convenience method equivalent to calling Backend.process_circuit() followed by Backend.get_result(). Any additional keyword arguments are passed on to Backend.process_circuit() and Backend.get_result().

run_circuits(circuits: Sequence[Circuit], n_shots: int | Sequence[int] | None = None, valid_check: bool = True, **kwargs: int | float | str | None) List[BackendResult][source]#

Submits circuits to the backend and returns results

Parameters:
Returns:

List of results

This is a convenience method equivalent to calling Backend.process_circuits() followed by Backend.get_results(). Any additional keyword arguments are passed on to Backend.process_circuits() and Backend.get_results().

valid_circuit(circuit: Circuit) bool[source]#

Checks that the circuit satisfies all of required_predicates.

Parameters:

circuit (Circuit) – The circuit to check.

Returns:

Whether or not all of required_predicates are satisfied.

Return type:

bool

property backend_info: BackendInfo | None#

Retrieve all Backend properties in a BackendInfo object, including device architecture, supported gate set, gate errors and other hardware-specific information.

Returns:

The BackendInfo describing this backend if it exists.

Return type:

Optional[BackendInfo]

property expectation_allows_nonhermitian: bool#

If expectations are supported, is the operator allowed to be non-Hermitan?

property persistent_handles: bool#

Whether the backend produces ResultHandle objects that can be reused with other instances of the backend class.

abstract property required_predicates: List[Predicate]#

The minimum set of predicates that a circuit must satisfy before it can be successfully run on this backend.

Returns:

Required predicates.

Return type:

List[Predicate]

property supports_contextual_optimisation: bool#

Does this backend support contextual optimisation?

See process_circuits().

property supports_counts: bool#

Does this backend support counts result retrieval via backendresult.BackendResult.get_counts().

property supports_density_matrix: bool#

Does this backend support density matrix retrieval via get_density_matrix.

property supports_expectation: bool#

Does this backend support expectation value calculation for operators.

property supports_shots: bool#

Does this backend support shot result retrieval via backendresult.BackendResult.get_shots().

property supports_state: bool#

Does this backend support statevector retrieval via backendresult.BackendResult.get_state().

property supports_unitary: bool#

Does this backend support unitary retrieval via backendresult.BackendResult.get_unitary().

pytket.backends.resulthandle#

ResultHandle class

class pytket.backends.resulthandle.ResultHandle(*args: int | float | complex | str | bool | bytes)[source]#

Object to store multidimensional identifiers for a circuit sent to a backend for execution.

Initialisation arguments must be hashable basic types.

Note that a ResultHandle may be either persistent or transient, depending on the backend: consult the pytket.backends.Backend.persistent_handles property to determine this.

classmethod from_str(string: str) ResultHandle[source]#

Construct ResultHandle from string (output from str())

Raises:

ValueError – If string format is invalid

Returns:

Instance of ResultHandle

Return type:

ResultHandle

pytket.backends.backendresult#

BackendResult class and associated methods.

class pytket.backends.backendresult.BackendResult(*, q_bits: Sequence[Qubit] | None = None, c_bits: Sequence[Bit] | None = None, counts: Counter[OutcomeArray] | None = None, shots: OutcomeArray | None = None, state: Any | None = None, unitary: Any | None = None, density_matrix: Any | None = None, ppcirc: Circuit | None = None)[source]#

Encapsulate generic results from pytket Backend instances.

In the case of a real quantum device or a shots-based simulator a BackendResult will typically be a collection of measurements (shots and counts).

Results can also be the output of ideal simulations of circuits. These can take the form of statevectors, unitary arrays or density matrices.

Parameters:
  • q_bits – Sequence of qubits.

  • c_bits – Sequence of classical bits.

  • counts – The counts in the result.

  • shots – The shots in the result.

  • state – The resulting statevector (from a statevector simulation).

  • unitary – The resulting unitary operator (from a unitary simulation).

  • density_matrix – The resulting density matrix (from a density-matrix simulator).

  • ppcirc – If provided, classical postprocessing to be applied to all measured results (i.e. shots and counts).

classmethod from_dict(res_dict: Dict[str, Any]) BackendResult[source]#
Construct BackendResult object from JSON serializable dictionary

representation, as generated by BackendResult.to_dict.

Returns:

Instance of BackendResult constructed from dictionary.

Return type:

BackendResult

get_bitlist() List[Bit][source]#

Return list of Bits in internal storage order.

Raises:

AttributeError – BackendResult does not include a Bits list.

Returns:

Sorted list of Bits.

Return type:

List[Bit]

get_counts(cbits: Sequence[Bit] | None = None, basis: BasisOrder = BasisOrder.ilo, ppcirc: Circuit | None = None) Counter[Tuple[int, ...]][source]#

Return counts of outcomes if available.

Parameters:
  • cbits (Optional[Sequence[Bit]], optional) – ordered subset of Bits, returns all results by default, defaults to None

  • basis – Toggle between ILO (increasing lexicographic order of bit ids) and DLO (decreasing lexicographic order) for column ordering if cbits is None. Defaults to BasisOrder.ilo.

  • ppcirc – Classical post-processing circuit to apply to measured results

Raises:

InvalidResultType – Counts are not available

Returns:

Counts of outcomes

Return type:

Counter[Tuple(int)]

get_debug_info() Dict[str, float][source]#

Calculate the success rate of each assertion averaged across shots.

Each assertion in pytket is decomposed into a sequence of transformations and measurements. An assertion is successful if and only if all its associated measurements yield the correct results.

Returns:

The debug results as a map from assertion to average success rate.

Return type:

Dict[str, float]

get_density_matrix(qbits: Sequence[Qubit] | None = None, basis: BasisOrder = BasisOrder.ilo) ndarray[source]#

Return density_matrix if available.

Parameters:
  • qbits (Optional[Sequence[Qubit]], optional) – permutation of Qubits, defaults to None

  • basis – Toggle between ILO (increasing lexicographic order of qubit ids) and DLO (decreasing lexicographic order) for column ordering if qbits is None. Defaults to BasisOrder.ilo.

Raises:

InvalidResultType – Statevector not available

Returns:

density_matrix, (complex 2-D numpy array)

Return type:

np.ndarray

get_distribution(units: Sequence[UnitID] | None = None) Dict[Tuple[int, ...], float][source]#

Calculate an exact or approximate probability distribution over outcomes.

If the exact statevector is known, the exact probability distribution is returned. Otherwise, if measured results are available the distribution is estimated from these results.

This method is deprecated. Please use get_empirical_distribution() or get_probability_distribution() instead.

Parameters:

units (Optional[Sequence[UnitID]], optional) – Optionally provide the Qubits or Bits to marginalise the distribution over, defaults to None

Returns:

A distribution as a map from bitstring to probability.

Return type:

Dict[Tuple[int, …], float]

get_empirical_distribution(bits: Sequence[Bit] | None = None) EmpiricalDistribution[Tuple[int, ...]][source]#

Convert to a pytket.utils.distribution.EmpiricalDistribution where the observations are sequences of 0s and 1s.

Parameters:

bits – Optionally provide the Bit s over which to marginalize the distribution.

Returns:

A distribution where the observations are sequences of 0s and 1s.

get_probability_distribution(qubits: Sequence[Qubit] | None = None, min_p: float = 0.0) ProbabilityDistribution[Tuple[int, ...]][source]#

Convert to a pytket.utils.distribution.ProbabilityDistribution where the possible outcomes are sequences of 0s and 1s.

Parameters:
  • qubits – Optionally provide the Qubit s over which to marginalize the distribution.

  • min_p – Optional probability below which to ignore values (for example to avoid spurious values due to rounding errors in statevector computations). Default 0.

Returns:

A distribution where the possible outcomes are tuples of 0s and 1s.

get_qbitlist() List[Qubit][source]#

Return list of Qubits in internal storage order.

Raises:

AttributeError – BackendResult does not include a Qubits list.

Returns:

Sorted list of Qubits.

Return type:

List[Qubit]

get_result(request_ids: Sequence[UnitID] | None = None, basis: BasisOrder = BasisOrder.ilo, ppcirc: Circuit | None = None) StoredResult[source]#
Retrieve all results, optionally according to a specified UnitID ordering

or subset.

Parameters:
  • request_ids (Optional[Sequence[UnitID]], optional) – Ordered set of either Qubits or Bits for which to retrieve results, defaults to None in which case all results are returned. For statevector/unitary/density_matrix results some permutation of all qubits must be requested. For measured results (shots/counts), some subset of the relevant bits must be requested.

  • basis – Toggle between ILO (increasing lexicographic order of bit ids) and DLO (decreasing lexicographic order) for column ordering if request_ids is None. Defaults to BasisOrder.ilo.

  • ppcirc – Classical post-processing circuit to apply to measured results

Raises:
  • ValueError – Requested UnitIds (request_ids) contain a mixture of qubits and bits.

  • RuntimeError – Classical bits not set.

  • ValueError – Requested (Qu)Bit not in result.

  • RuntimeError – “Qubits not set.”

  • ValueError – For state/unitary/density_matrix results only a permutation of all qubits can be requested.

Returns:

All stored results corresponding to requested IDs.

Return type:

StoredResult

get_shots(cbits: Sequence[Bit] | None = None, basis: BasisOrder = BasisOrder.ilo, ppcirc: Circuit | None = None) ndarray[source]#

Return shots if available.

Parameters:
  • cbits (Optional[Sequence[Bit]], optional) – ordered subset of Bits, returns all results by default, defaults to None

  • basis – Toggle between ILO (increasing lexicographic order of bit ids) and DLO (decreasing lexicographic order) for column ordering if cbits is None. Defaults to BasisOrder.ilo.

  • ppcirc – Classical post-processing circuit to apply to measured results

Raises:

InvalidResultType – Shot results are not available

Returns:

2D array of readouts, each row a separate outcome and each column a bit value.

Return type:

np.ndarray

The order of the columns follows the order of cbits, if provided.

get_state(qbits: Sequence[Qubit] | None = None, basis: BasisOrder = BasisOrder.ilo) ndarray[source]#

Return statevector if available.

Parameters:
  • qbits (Optional[Sequence[Qubit]], optional) – permutation of Qubits, defaults to None

  • basis – Toggle between ILO (increasing lexicographic order of qubit ids) and DLO (decreasing lexicographic order) for column ordering if qbits is None. Defaults to BasisOrder.ilo.

Raises:

InvalidResultType – Statevector not available

Returns:

Statevector, (complex 1-D numpy array)

Return type:

np.ndarray

get_unitary(qbits: Sequence[Qubit] | None = None, basis: BasisOrder = BasisOrder.ilo) ndarray[source]#

Return unitary if available.

Parameters:
  • qbits (Optional[Sequence[Qubit]], optional) – permutation of Qubits, defaults to None

  • basis – Toggle between ILO (increasing lexicographic order of qubit ids) and DLO (decreasing lexicographic order) for column ordering if qbits is None. Defaults to BasisOrder.ilo.

Raises:

InvalidResultType – Statevector not available

Returns:

Unitary, (complex 2-D numpy array)

Return type:

np.ndarray

to_dict() Dict[str, Any][source]#
Generate a dictionary serialized representation of BackendResult,

suitable for writing to JSON.

Returns:

JSON serializable dictionary.

Return type:

Dict[str, Any]

property contains_measured_results: bool#

Whether measured type results (shots or counts) are stored

property contains_state_results: bool#

Whether state type results (state vector or unitary or density_matrix) are stored

class pytket.backends.backendresult.StoredResult(counts: Counter[OutcomeArray] | None = None, shots: OutcomeArray | None = None, state: ndarray | None = None, unitary: ndarray | None = None, density_matrix: ndarray | None = None)[source]#

NamedTuple with optional fields for all result types.

counts: Counter[OutcomeArray] | None#

Alias for field number 0

density_matrix: ndarray | None#

Alias for field number 4

shots: OutcomeArray | None#

Alias for field number 1

state: ndarray | None#

Alias for field number 2

unitary: ndarray | None#

Alias for field number 3

pytket.backends.status#

Status classes for circuits submitted to backends.

class pytket.backends.status.CircuitStatus(status: StatusEnum, message: str = '', error_detail: str | None = None, completed_time: datetime | None = None, queued_time: datetime | None = None, submitted_time: datetime | None = None, running_time: datetime | None = None, cancelled_time: datetime | None = None, error_time: datetime | None = None, queue_position: int | None = None)[source]#

The status of a circuit along with an optional description.

Optionally can also include extra fields such as: * Detailed error information. * Timestamps for changes in status. * Queue position.

classmethod from_dict(dic: Dict[str, Any]) CircuitStatus[source]#

Construct from JSON serializable dictionary.

to_dict() Dict[str, Any][source]#

Return JSON serializable dictionary representation.

cancelled_time: datetime | None#

Alias for field number 7

completed_time: datetime | None#

Alias for field number 3

error_detail: str | None#

Alias for field number 2

error_time: datetime | None#

Alias for field number 8

message: str#

Alias for field number 1

queue_position: int | None#

Alias for field number 9

queued_time: datetime | None#

Alias for field number 4

running_time: datetime | None#

Alias for field number 6

status: StatusEnum#

Alias for field number 0

submitted_time: datetime | None#

Alias for field number 5

enum pytket.backends.status.StatusEnum(value)[source]#

Enumeration for the possible status of a circuit submitted to a backend.

Valid values are as follows:

COMPLETED = <StatusEnum.COMPLETED: 'Circuit has completed. Results are ready.'>#
QUEUED = <StatusEnum.QUEUED: 'Circuit is queued.'>#
SUBMITTED = <StatusEnum.SUBMITTED: 'Circuit has been submitted.'>#
RUNNING = <StatusEnum.RUNNING: 'Circuit is running.'>#
RETRYING = <StatusEnum.RETRYING: 'Circuit is being retried.'>#
CANCELLING = <StatusEnum.CANCELLING: 'Cancellation has been requested.'>#
CANCELLED = <StatusEnum.CANCELLED: 'Circuit has been cancelled.'>#
ERROR = <StatusEnum.ERROR: 'Circuit has errored. Check CircuitStatus.message for error message.'>#

pytket.backends.backendinfo#

BackendInfo class: additional information on Backends

class pytket.backends.backendinfo.BackendInfo(name: str, device_name: str | None, version: str, architecture: ~pytket.architecture.Architecture | ~pytket.architecture.FullyConnected | None, gate_set: ~typing.Set[~pytket.circuit.OpType], n_cl_reg: int | None = None, supports_fast_feedforward: bool = False, supports_reset: bool = False, supports_midcircuit_measurement: bool = False, all_node_gate_errors: ~typing.Dict[~pytket.unit_id.Node, ~typing.Dict[~pytket.circuit.OpType, float]] | None = None, all_edge_gate_errors: ~typing.Dict[~typing.Tuple[~pytket.unit_id.Node, ~pytket.unit_id.Node], ~typing.Dict[~pytket.circuit.OpType, float]] | None = None, all_readout_errors: ~typing.Dict[~pytket.unit_id.Node, ~typing.List[~typing.List[float]]] | None = None, averaged_node_gate_errors: ~typing.Dict[~pytket.unit_id.Node, float] | None = None, averaged_edge_gate_errors: ~typing.Dict[~typing.Tuple[~pytket.unit_id.Node, ~pytket.unit_id.Node], float] | None = None, averaged_readout_errors: ~typing.Dict[~pytket.unit_id.Node, float] | None = None, misc: ~typing.Dict[str, ~typing.Any] = <factory>)[source]#

Stores various properties of a Backend.

This provides all device information useful for compilation.

Parameters:
  • name – Class name of the backend.

  • device_name – Name of the device.

  • version – Pytket-extension version installed when creating object.

  • architecture – Optional device connectivity.

  • gate_set – Set of supported gate types.

  • n_cl_reg – number of classical registers supported.

  • supports_fast_feedforward – Flag for hardware support of fast feedforward.

  • supports_reset – Flag for hardware support of reset operation

  • supports_midcircuit_meas – Flag for hardware support of midcircuit measurement.

  • all_node_gate_errors – Dictionary between architecture Node and error rate for different single qubit operations.

  • all_edge_gate_errors – Dictionary between architecture couplings and error rate for different two-qubit operations.

  • all_readout_errors – Dictionary between architecture Node and uncorrelated single qubit readout errors (2x2 readout probability matrix).

  • averaged_node_gate_errors – Dictionary between architecture Node and averaged error rate for all single qubit operations.

  • averaged_edge_gate_errors – Dictionary between architecture couplings and averaged error rate for all two-qubit operations.

  • averaged_readout_errors – Dictionary between architecture Node and averaged readout errors.

  • misc – key-value map with further provider-specific information (must be JSON-serializable)

add_misc(key: str, val: Any) None[source]#

Add a new entry in BackendInfo’s dictionary of additional information.

Parameters:
  • key (str) – Key to store and retrieve value.

  • val – Value to be stored.

classmethod from_dict(d: Dict[str, Any]) BackendInfo[source]#

Construct BackendInfo object from JSON serializable dictionary representation, as generated by BackendInfo.to_dict.

Returns:

Instance of BackendInfo constructed from dictionary.

Return type:

BackendInfo

get_misc(key: str) Any[source]#

Retrieve information stored in Backend’s additional information store

Parameters:

key (str) – Key to retrieve value.

Raises:

KeyError – There is no value stored with the given key.

Returns:

The value stored at the given key.

to_dict() Dict[str, Any][source]#

Generate a dictionary serialized representation of BackendInfo, suitable for writing to JSON.

Returns:

JSON serializable dictionary.

Return type:

Dict[str, Any]

property n_nodes: int#

Number of nodes in the architecture of the device. Returns 0 if the architecture field is not provided.

Returns:

Number of nodes.

Return type:

int

property nodes: List[Node]#

List of device nodes of the backend. Returns empty list if the architecture field is not provided.

Returns:

List of nodes.

Return type:

List[Node]