Sampling on Braket's real quantum computers
Here we introduce the Braket backends and some Braket specific features QURI Parts provide
Prerequisite
This section requires topics described in previous sections(Samplers, Sampling estimation and Sampling Backends), so you need to read them before this section.
In this section, we use Amazon Braket as the platform with real quantum computers. In order to use Braket devices provided on AWS, you need to have an AWS account and enable Braket service. Please see Amazon Braket Documentation for details. In this section, instead, we use the local simulator included in Amazon Braket SDK, which does not require an AWS account. The Braket devices provided on AWS and the local simulator have the same interface, you can simply replace them each other.
QURI Parts modules used in this tutorial: quri-parts-circuit
, quri-parts-core
and quri-parts-braket
. You can install them as follows:
!pip install "quri-parts[braket]"
The BraketSamplingBackend
How to create a SamplingBackend
object depends on the used backend. For Braket devices, you can create a BraketSamplingBackend
by passing a braket.devices.Device
object (provided by Amazon Braket SDK):
from braket.aws import AwsDevice
from braket.devices import LocalSimulator
# A device for QPU provided on AWS
# device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-2")
# A device for the local simulator
device = LocalSimulator()
from quri_parts.braket.backend import BraketSamplingBackend
# Create a SamplingBackend with the device
backend = BraketSamplingBackend(device)
With the sampling backend we just created, we can run the exact codes as in the Sampling Backend and Sampler section of the Sampling backend tutorial.
Qubit mapping
Here, we explain some details you need to know when you use the devices provided by Braket. Following the code in the Sampling Backend tutorial, we consider the following qubit mapping sampling.
from numpy import pi
from quri_parts.circuit import QuantumCircuit
from quri_parts.core.sampling import create_sampler_from_sampling_backend
circuit = QuantumCircuit(4)
circuit.add_X_gate(0)
circuit.add_H_gate(1)
circuit.add_Y_gate(2)
circuit.add_CNOT_gate(1, 2)
circuit.add_RX_gate(3, pi/4)
backend = BraketSamplingBackend(device, qubit_mapping={0: 3, 1: 2, 2: 0, 3: 1})
sampler = create_sampler_from_sampling_backend(backend)
sampling_result = sampler(circuit, 1000)
print(sampling_result)
#output
{3: 432, 5: 425, 11: 79, 13: 64}
The result looks similar to one with no qubit mapping, since the measurement result from the device is mapped backward so that it is interpreted in terms of the original qubit indices.
You may notice that the above mapping is a permutation of the original qubit indices and device qubits with indices larger than 3 are not involved. The reason for choosing such a mapping is to avoid an error of LocalSimulator
: the LocalSimulator
does not accept non-contiguous qubit indices. On the other hand, the qubit mapping feature of the SamplingBackend
accepts such a mapping, as shown below.
When you apply qubit mapping to devices provided on AWS, you will need to enable manual qubit allocation by passing disable_qubit_rewiring=True to the device. You can specify such an argument (i.e. keyword arguments for run
method of a braket.devices.Device
object) via run_kwargs
argument of the BraketSamplingBackend
object:
# Commented out because it requires an access to a real device on AWS
# device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Aspen-M-2")
# backend = BraketSamplingBackend(
# device,
# qubit_mapping={0: 10, 1: 13, 2: 17, 3: 21},
# run_kwargs={"disable_qubit_rewiring": True},
# )
# sampler = create_sampler_from_sampling_backend(backend)
# sampling_result = sampler(circuit, 1000)
# print(sampling_result)
Circuit transpilation before execution
The transpilation performed by default depends on the backend; in the case of BraketSamplingBackend
, it uses quri_parts.braket.circuit.BraketSetTranspiler
for all devices, and also performs some device-specific transpilation defined in quri_parts.braket.backend.transpiler
. It is possible to change the former one (device-independent transpilation) by supplying circuit_transpiler
argument to BraketSamplingBackend
.