pytket-quantinuum#
pytket-quantinuum
is an extension to pytket
that allows pytket
circuits to
be executed on Quantinuum’s quantum devices.
pytket-quantinuum
is available for Python 3.9, 3.10 and 3.11, on Linux, MacOS
and Windows. To install, run:
pip install pytket-quantinuum
Note
Using the QuantinuumBackend
requires a Quantinuum account.
The user will be prompted for their login credentials when making API calls such as calling the process_circuits
method or querying backend_info
.
Web Interface: https://um.qapi.quantinuum.com/
Devices#
The pytket-quantinuum extension allows the user to access the following quantum devices, emulators and syntax checkers. These backends can be initialised by passing the device name as a string to the QuantinuumBackend
class. The available devices are:
H1-1
,H2-1
: Quantum devices, submit specifically toH1-1
orH2-1
by using the device name.H1-1E
,H2-1E
: Device-specific emulators ofH1-1
andH2-1
. These emulators run remotely on servers and require credentials.H1-1SC
,H2-1SC
: Device-specific syntax checkers. These check compilation of a quantum circuit against device-specific instructions, and return status “completed” if the syntax is correct (along with the H-Series Quantum Credits (HQCs)), or status “failed” if the syntax is incorrect (along with the error).
There are also optional initialisation parameters label
(for naming circuits), group
(identifier for a collection of jobs) and simulator
(see below).
The H-series devices and emulators produce shots-based results and therefore require measurements. It is also possible to use a stabilizer simulator by specifying simulator='stabilizer'
. This option may be preferable for simulating Clifford circuits.
By default the emulators use noise models based on the real devices. It is possible to perform a noiseless simulation by specifying noisy_simulation=False
.
For examples demonstrating the QuantinuumBackend
see the example notebooks .
Default Compilation#
Every Backend
in pytket has its own default_compilation_pass
method.
This method applies a sequence of optimisations to a circuit depending on the value of an optimisation_level
parameter.
This default compilation will ensure that the circuit meets all the constraints required to run on the Backend
.
The default pass can be applied in place as follows
from pytket import Circuit
from pytket.extensions.quantinuum import QuantinuumBackend
circ = Circuit(2).H(0).CX(0, 1).CZ(0, 1)
backend = QuantinuumBackend('H1-1E')
# Compile the circuit in place. The optimisation level is set to 2 by default.
backend.default_compilation_pass().apply(circ)
Alternatively the default pass can be applied using the get_compiled_circuit
method.
compiled_circ = backend.get_compiled_circuit(circ)
The passes applied by different levels of optimisation are specified in the table below.
optimisation_level = 0 |
optimisation_level = 1 |
optimisation_level = 2 [1] |
---|---|---|
self.rebase_pass [2] |
||
self.rebase_pass [2] |
self.rebase_pass [2] |
|
[1] If no value is specified then
optimisation_level
defaults to a value of 2.[2]
self.rebase_pass
is a rebase that converts the circuit to the Quantinuum native gate set (e.g. {Rz, PhasedX, ZZMax, ZZPhase}).[3]
FullPeepholeOptimise
has the argumenttarget_2qb_gate=OpType.TK2
.[4]
auto_squash_pass
has argumentsauto_squash_pass({OpType.PhasedX, OpType.Rz})
Note
If optimisation_level = 0
the device constraints are solved but no additional optimisation is applied. Setting optimisation_level = 1
applies some light optimisations to the circuit. More intensive optimisation is applied by level 2 at the expense of increased runtime.
Note
The pass ZZPhaseToRz
is left out of optimisation_level=2
as the passes applied by FullPeepholeOptimise
will already cover these optimisations.
Target Two-Qubit Gate#
Backends may offer several alternatives as the native two-qubit gate: the
current possibilities are ZZMax
, ZZPhase
and TK2
. The set of
supported gates may be queried using the
QuantinuumBackend.two_qubit_gate_set
property. Each device also has a
default two-qubit gate, which may be queried using the
QuantinuumBackend.default_two_qubit_gate
property. Currently, the default
two-qubit gate for all devices is ZZPhase
.
The default compilation pass and rebase pass will target the default gate by
default. This may be overridden using the method
QuantinuumBackend.set_compilation_config_target_2qb_gate()
or by passing a
QuantinuumBackendCompilationConfig
when constructing the backend.
If desired, backends may be allowed to rebase to a different two-qubit gate
judged to have better fidelity before being run. The default is to run with the
gate provided in the submitted circuit, but this behaviour may be overridden
using the optional allow_2q_gate_rebase
argument to process_circuit()
,
process_circuits()
or submit_program()
.
Device Predicates#
Circuits must satisfy the following predicates in order to run on the QuantinuumBackend
.
NoSymbolsPredicate: Parameterised gates must have numerical parameters when the circuit is executed.
GateSetPredicate: To view supported Ops run
QuantinuumBackend.backend_info.gate_set
.MaxNQubitsPredicate:
H1-1
,H1-1E
andH1-1SC
all support a maximum of 20 qubits. TheH2-1
,H2-1E
andH2-1SC
support a maximum of 32 qubits.
Job Statuses#
When using the Quantinuum Backend
to run circuits there are several possible circuit statuses.
queued - The job has been queued but has not yet been run.
running - The circuit is currently being run on the device/emulator.
completed - The job has finished.
failed - The job has failed.
cancelling - The job is in the process of being cancelled.
cancelled - The job has been cancelled.
The status of the job can be checked with by using the circuit_status
method. To cancel a job simply use the cancel
method and supply the job handle as a parameter.
Additional Backend Capabilities#
The Quantinuum Backend
has a cost
method. This calculates the cost (in HQCs) required to execute the circuit for the specified number of shots.
Every Quantinuum Backend
supports mid-circuit measurements and fast classical feedforward.
The process_circuits
method for the QuantinuumBackend accepts the following additional keyword arguments.
postprocess
: boolean flag to allow classical postprocessing.noisy_simulation
: boolean flag to specify whether the simulator should perform noisy simulation with an error model (default value isTrue
).group
: string identifier of a collection of jobs, can be used for usage tracking.
For the Quantinuum Backend
, process_circuits
returns a ResultHandle
object containing a job_id
and a postprocessing ( ppcirc
) circuit if there is one.
The logout()
method clears stored JSON web tokens and the user will have to sign in again to access the Quantinuum API.
Partial Results Retrieval#
The QuantinuumBackend
also supports giving the user partial results from unfinished jobs.
This can be done as follows.
from pytket.extensions.quantinuum import QuantinuumBackend
# Submit circuit to QuantinuumBackend
backend = QuantinuumBackend('H1-1')
compiled_circ = backend.get_compiled_circuit(circ) # circ defined elsewhere
handle = backend.process_circuit(compiled_circ, n_shots=3000)
# Retrieve partial shots:counts from the handle of an unfinished job
partial_result, job_status = backend.get_partial_result(handle)
print(partial_result.get_counts())
This feature has a number of potential use cases.
Firstly partial results can be used to diagnose potential faults with submitted jobs. For instance if the partial results look worse than expected this could indicate a bug in the submitted circuit(s). If this is the case the user may want to cancel the job to avoid using machine time and resubmit once the issue is resolved. If partial results indicate that a job is taking longer run than anticipated then the user can cancel the job and consider redesigning their experiment.
Also partial results enable users to quickly validate basic execution for very large jobs which may take days to complete.
Leakage Gadget Detection#
When running circuits on the :py:class:QuantinuumBackend, one source of error is “leakage”, where with some small probability a qubit will experience leakage into electronic states outside the qubit subspace. When this occurs, none of the remaining gates in the circuit will have any effect and so this leads to erroneous results.
Such leakage errors can be detected at the circuit level by running a special circuit gadget between a data qubit and an ancilla qubit. We can then discard shots where a leakage error is detected using prune_shots_detected_as_leaky()
.
For a more detailed explanation we refer to Eliminating Leakage Errors in Hyperfine Qubits by D. Hayes, D. Stack, B. Bjork, A. C. Potter, C. H. Baldwin and R. P. Stutz and the corresponding notebook tutorial.
Batching#
Quantinuum backends (except syntax checkers) support batching of jobs (circuits). To create a batch of jobs, users submit the first job, then signal that subsequent jobs should be added to the same batch using the handle of the first. The backend queue management system will start the batch as soon as the first job reaches the front of the queue and ensure subsequent batch jobs are run one after the other, until the end of the batch is reached or there are no new jobs added to the batch for ~1 min (at which point the batch expires and any subsequent jobs will be added to the standard queue).
The standard process_circuits
method no
longer batches by default. To use batching first start the batch with
start_batch
, which has a similar interface to process_circuit
but with
an extra first argument max_batch_cost:
h1 = backend.start_batch(max_batch_cost=300, circuit=circuit, n_shots=100)
Add to the batch with subsequent calls of add_to_batch
which takes as first
argument the handle of the first job of the batch, and has the optional keyword
argument batch_end to signal the end of a batch (default False).
h2 = backend.add_to_batch(h1, circuit_2, n_shots=100)
h3 = backend.add_to_batch(h1, circuit_3, n_shots=100, batch_end=True)
The batch feature on Quantinuum systems gives users the ability to create “ad-hoc” reservations. Circuits submitted together in a batch will run at one time. The benefit to users is that once a batch hits the front of the queue, jobs in a batch will run uninterrupted until they are completed.
Once a batch is submitted, jobs can continue to be added to the batch, ending either when the user signifies the end of a batch or after 1 minute of inactivity. Batches cannot exceed the maximum limit of 500 H-System Quantum Credits (HQCs) total.
If the total HQCs for jobs in a batch hit this limit or a smaller limit set by the user, those jobs will not be cancelled. Instead, they will continue to run as regular jobs in the queue instead of as a batch.
- API documentation
Language
QuantinuumAPI
QuantinuumAPIOffline
QuantinuumBackend
QuantinuumBackend.__init__()
QuantinuumBackend.add_to_batch()
QuantinuumBackend.available_devices()
QuantinuumBackend.cancel()
QuantinuumBackend.circuit_status()
QuantinuumBackend.cost()
QuantinuumBackend.cost_estimate()
QuantinuumBackend.default_compilation_pass()
QuantinuumBackend.device_state()
QuantinuumBackend.get_compilation_config()
QuantinuumBackend.get_jobid()
QuantinuumBackend.get_partial_result()
QuantinuumBackend.get_ppcirc_rep()
QuantinuumBackend.get_result()
QuantinuumBackend.get_results_selection()
QuantinuumBackend.get_results_width()
QuantinuumBackend.login()
QuantinuumBackend.logout()
QuantinuumBackend.process_circuits()
QuantinuumBackend.rebase_pass()
QuantinuumBackend.set_compilation_config_allow_implicit_swaps()
QuantinuumBackend.set_compilation_config_target_2qb_gate()
QuantinuumBackend.start_batch()
QuantinuumBackend.submit_program()
QuantinuumBackend.backend_info
QuantinuumBackend.default_two_qubit_gate
QuantinuumBackend.required_predicates
QuantinuumBackend.two_qubit_gate_set
QuantinuumBackendCompilationConfig
QuantinuumConfig
set_quantinuum_config()
get_detection_circuit()
get_leakage_gadget_circuit()
prune_shots_detected_as_leaky()
- Changelog
- 0.26.0 (November 2023)
- 0.25.0 (October 2023)
- 0.24.0 (October 2023)
- 0.23.0 (September 2023)
- 0.22.0 (September 2023)
- 0.21.0 (September 2023)
- 0.20.0 (August 2023)
- 0.19.0 (August 2023)
- 0.18.0 (July 2023)
- 0.17.0 (June 2023)
- 0.16.0 (May 2023)
- 0.15.0 (April 2023)
- 0.14.0 (March 2023)
- 0.13.0 (January 2023)
- 0.12.0 (December 2022)
- 0.11.0 (November 2022)
- 0.10.0 (November 2022)
- 0.9.0 (October 2022)
- 0.8.0 (September 2022)
- 0.7.0 (August 2022)
- 0.6.0 (July 2022)
- 0.5.0 (July 2022)
- 0.4.0 (June 2022)
- 0.3.1 (May 2022)
- 0.3.0 (May 2022)
- 0.2.0 (April 2022)
- 0.1.2 (April 2022)
- 0.1.1 (March 2022)
- 0.1.0 (March 2022)
pytket documentation:
Links: