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(Sampling simulation, 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):

[1]:
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()
[2]:
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 QURI Part’s Sampling Backend tutorial.

Qubit mapping#

Here, we explain some details you need to know when you use the devices provided by Bracket. Following the code in the Sampling Backend tutorial, we consider the following qubit mapping sampling.

[5]:
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)
{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:

[9]:
# 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.BraketTranspiler 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.