

# Running your quantum tasks with Amazon Braket
<a name="braket-using"></a>

Braket provides secure, on-demand access to different types of quantum computers. You have access to gate-based quantum computers from AQT, IonQ, IQM, and Rigetti, as well as an Analog Hamiltonian Simulator from QuEra. You also have no upfront commitment, and no need to procure access through individual providers.
+ The [Amazon Braket Console](https://console.aws.amazon.com/braket/home) provides device information and status to help you create, manage, and monitor your resources and quantum tasks.
+ Submit and run quantum tasks through the [Amazon Braket Python SDK](https://github.com/aws/amazon-braket-sdk-python), as well as through the console. The SDK is accessible through preconfigured Amazon Braket notebooks.
+ The [Amazon Braket API](https://docs.aws.amazon.com/braket/latest/APIReference/Welcome.html) is accessible through the Amazon Braket Python SDK and notebooks. You can make calls directly to the API if you are building applications that work with quantum computing programmatically.

The examples throughout this section demonstrate how you can work with the Amazon Braket API directly using the Amazon Braket Python SDK along with the [AWS Python SDK for Braket (Boto3)](https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/braket.html).

 **More about the Amazon Braket Python SDK** 

To work with the Amazon Braket Python SDK, first install the AWS Python SDK for Braket (Boto3) so that you can communicate with the AWS API. You can think of the Amazon Braket Python SDK as a convenient wrapper around Boto3 for quantum customers.
+ Boto3 contains interfaces you need to tap into the AWS API. (Note that Boto3 is a large Python SDK that talks to the AWS API. Most AWS services support a Boto3 interface.)
+ The Amazon Braket Python SDK contains software modules for circuits, gates, devices, result types, and other parts of a quantum task. Each time you create a program, you import the modules you need for that quantum task.
+ The Amazon Braket Python SDK is accessible through notebooks, which are pre-loaded with all of the modules and dependencies you need for running quantum tasks.
+ You can import modules from the Amazon Braket Python SDK into any Python script if you do not wish to work with notebooks.

After you have [installed Boto3](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/quickstart.html), an overview of steps for creating a quantum task through the Amazon Braket Python SDK resembles the following:

1. (Optionally) Open your notebook.

1. Import the SDK modules you need for your circuits.

1. Specify a QPU or simulator.

1. Instantiate the circuit.

1. Run the circuit.

1. Collect the results.

The examples in this section show details of each step.

For more examples, see the [Amazon Braket Examples](https://github.com/aws/amazon-braket-examples) repository on GitHub.

**Topics**
+ [Submitting quantum tasks to QPUs](braket-submit-tasks.md)
+ [Running multiple programs](braket-batching-tasks.md)
+ [When will my quantum task run?](braket-task-when.md)
+ [Working with reservations](braket-reservations.md)
+ [Error mitigation techniques](braket-error-mitigation.md)

# Submitting quantum tasks to QPUs
<a name="braket-submit-tasks"></a>

Amazon Braket provides access to several devices that can run quantum tasks. You can submit quantum tasks individually or you can set up [quantum task batching](https://docs.aws.amazon.com/braket/latest/developerguide/braket-batching-tasks.html).

 **Quantum processing units (QPUs)** 

You can submit quantum tasks to QPUs at any time, but the task runs within certain availability windows that are displayed on the **Devices** page of the Amazon Braket console. You can retrieve the results of the quantum task with the quantum task ID, which is introduced in the next section.
+  ** AQT IBEX-Q1 ** : `arn:aws:braket:eu-north-1::device/qpu/aqt/Ibex-Q1` 
+  ** IonQ Forte-1 ** : `arn:aws:braket:us-east-1::device/qpu/ionq/Forte-1` 
+  ** IonQ Forte-Enterprise-1 ** : `arn:aws:braket:us-east-1::device/qpu/ionq/Forte-Enterprise-1` 
+  ** IQM Garnet ** : `arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet` 
+  ** IQM Emerald ** : `arn:aws:braket:eu-north-1::device/qpu/iqm/Emerald` 
+  ** QuEra Aquila ** : `arn:aws:braket:us-east-1::device/qpu/quera/Aquila` 
+  ** Rigetti Ankaa-3 ** : `arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3` 
+  ** Rigetti Cepheus-1-108Q ** : `arn:aws:braket:us-west-1::device/qpu/rigetti/Cepheus-1-108Q` 

**Note**  
You can cancel quantum tasks in the `CREATED` state for QPUs and on-demand simulators. You can cancel quantum tasks in the `QUEUED` state on a best-effort basis for on-demand simulators and QPUs. Note that QPU `QUEUED` quantum tasks are unlikely to be cancelled successfully during QPU availability windows.

**Topics**
+ [AQT](#braket-qpu-partner-aqt)
+ [IonQ](#braket-qpu-partner-ionq)
+ [IQM](#braket-qpu-partner-iqm)
+ [Rigetti](#braket-qpu-partner-rigetti)
+ [QuEra](#braket-qpu-partner-quera)
+ [Example: Submitting a quantum task to a QPU](braket-submit-to-qpu.md)
+ [Inspecting compiled circuits](braket-compiled-circuits-inspecting.md)

## AQT
<a name="braket-qpu-partner-aqt"></a>

AQT's IBEX-Q1 QPU is based on a crystal of 40Ca\$1 ions in a macroscopic radio frequency trap sitting in ultra-high vacuum chamber. The device runs at room temperature and fits into two 19-inch datacenter compatible racks.

High-fidelity gates are enabled by the low heating rates of the trap and the use of a direct optical transition for qubit rotation. The qubit transition is driven by a narrow linewidth laser with a very high relative frequency stability. The qubits also feature efficient state preparation and readout through optical shelfing. All-to-all connectivity is achieved by the long-range Coulomb interaction in the ion crystal. Single-ion addressing and readout are achieved by use of a high numerical aperture lens.

The AQT device support the following quantum gates.

```
'ccnot', 'cnot', 'cphaseshift', 'cphaseshift00', 'cphaseshift01', 'cphaseshift10', 'cswap', 'swap', 'iswap', 'pswap', 'ecr', 'cy', 'cz', 'xy', 'xx', 'yy', 'zz', 'h', 'i', 'phaseshift', 'rx', 'ry', 'rz', 's', 'si', 't', 'ti', 'v', 'vi', 'x', 'y', 'z', 'prx'
```

With verbatim compilation, the AQT device supports the following native gates.

```
'prx', 'xx', 'rz'
```

**Note**  
The following describes equivalent gates between AQT native gates and Amazon Braket:  
The AQT Mølmer-Sørensen (MS or RXX) gate corresponds to Braket's `'xx'` gate
The AQT R gate corresponds to Braket's `'prx'` gate
The `'rz'` gate naming is the same

## IonQ
<a name="braket-qpu-partner-ionq"></a>

IonQ offers gate-based QPUs based on ion trap technology. IonQ's trapped ion QPUs are built on a chain of trapped 171Yb\$1 ions that are spatially confined by means of a microfabricated surface electrode trap within a vacuum chamber.

IonQ devices support the following quantum gates.

```
'x', 'y', 'z', 'rx', 'ry', 'rz', 'h', 'cnot', 's', 'si', 't', 'ti', 'v', 'vi', 'xx', 'yy', 'zz', 'swap'
```

With verbatim compilation, the IonQ QPUs support the following native gates.

```
'gpi', 'gpi2', 'ms'
```

If you only specify two phase parameters when using the native MS gate, a fully- entangling MS gate runs. A fully-entangling MS gate always performs a π/2 rotation. To specify a different angle and run a partially-entangling MS gate, you specify the desired angle by adding a third parameter. For more information, see the [ braket.circuits.gate module](https://amazon-braket-sdk-python.readthedocs.io/en/latest/_apidoc/braket.circuits.gate.html).

These native gates can only be used with verbatim compilation. To learn more about verbatim compilation, see [Verbatim Compilation](https://docs.aws.amazon.com/braket/latest/developerguide/braket-constructing-circuit.html#verbatim-compilation).

## IQM
<a name="braket-qpu-partner-iqm"></a>

IQM quantum processors are universal gate-model devices based on superconducting transmon qubits. The IQM Garnet is a 20-qubit device, while IQM Emerald is a 54-qubit device. Both these devices use a square lattice topology, also known as a Crystal lattice topology.

The IQM devices support the following quantum gates.

```
"ccnot", "cnot", "cphaseshift", "cphaseshift00", "cphaseshift01", "cphaseshift10", "cswap", "swap", "iswap", "pswap", "ecr", "cy", "cz", "xy", "xx", "yy", "zz", "h", "i", "phaseshift", "rx", "ry", "rz", "s", "si", "t", "ti", "v", "vi", "x", "y", "z"
```

With verbatim compilation, the IQM devices support the following native gates.

```
'cz', 'prx'
```



## Rigetti
<a name="braket-qpu-partner-rigetti"></a>

Rigetti quantum processors are universal, gate-model machines based on all-tunable superconducting qubits.
+ The Ankaa-3 system is an 84-qubit device that utilizes scalable multi-chip technology.
+ The Cepheus-1-108Q system is a 108-qubit device that utilizes scalable multi-chip technology.

The Rigetti device supports the following quantum gates.

```
'cz', 'xy', 'ccnot', 'cnot', 'cphaseshift', 'cphaseshift00', 'cphaseshift01', 'cphaseshift10', 'cswap', 'h', 'i', 'iswap', 'phaseshift', 'pswap', 'rx', 'ry', 'rz', 's', 'si', 'swap', 't', 'ti', 'x', 'y', 'z'
```

With verbatim compilation, Ankaa-3 supports the following native gates.

```
'rx', 'rz', 'iswap'
```

 Rigetti superconducting quantum processors can run the 'rx' gate with only the angles of ±π/2 or ±π.

Pulse-level control is available on the Rigetti devices, which support a set of predefined frames of the following types for the Ankaa-3 system.

```
`flux_tx`, `charge_tx`, `readout_rx`, `readout_tx`
```

The Ankaa-3 device has a maximum limit of 20,000 gates per circuit. Circuits that exceed this limit are rejected with a validation error. This is a fixed limit that cannot be increased. The gate count refers to the compiled circuit, which may differ from the gate count of the original uncompiled circuit. To estimate the compiled gate count before submitting to the QPU, you can use verbatim compilation locally or transpile your circuit to the native gate set (`rx`, `rz`, `iswap`).

## QuEra
<a name="braket-qpu-partner-quera"></a>

QuEra offers neutral-atom based devices that can run Analog Hamiltonian Simulation (AHS) quantum tasks. These special-purpose devices faithfully reproduce the time-dependent quantum dynamics of hundreds of simultaneously interacting qubits.

One can program these devices in the paradigm of Analog Hamiltonian Simulation by prescribing the layout of the qubit register and the temporal and spatial dependence of the manipulating fields. Amazon Braket provides utilities to construct such programs through the AHS module of the python SDK, `braket.ahs`.

For more information, see the [Analog Hamiltonian Simulation example notebooks](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation) or the [Submit an analog program using QuEra's Aquila](braket-quera-submitting-analog-program-aquila.md) page.

# Example: Submitting a quantum task to a QPU
<a name="braket-submit-to-qpu"></a>

Amazon Braket allows you to run a quantum circuit on a QPU device. The following example shows how to submit a quantum task to Rigetti or IonQ devices.

 **Choose the Rigetti Ankaa-3 device, then look at the associated connectivity graph** 

```
# import the QPU module
from braket.aws import AwsDevice
# choose the Rigetti device
device = AwsDevice("arn:aws:braket:us-west-1::device/qpu/rigetti/Ankaa-3")

# take a look at the device connectivity graph
device.properties.dict()['paradigm']['connectivity']
```

```
{'fullyConnected': False,
 'connectivityGraph': {'0': ['1', '7'],
  '1': ['0', '2', '8'],
  '2': ['1', '3', '9'],
  '3': ['2', '4', '10'],
  '4': ['3', '5', '11'],
  '5': ['4', '6', '12'],
  '6': ['5', '13'],
  '7': ['0', '8', '14'],
  '8': ['1', '7', '9', '15'],
  '9': ['2', '8', '10', '16'],
  '10': ['3', '9', '11', '17'],
  '11': ['4', '10', '12', '18'],
  '12': ['5', '11', '13', '19'],
  '13': ['6', '12', '20'],
  '14': ['7', '15', '21'],
  '15': ['8', '14', '22'],
  '16': ['9', '17', '23'],
  '17': ['10', '16', '18', '24'],
  '18': ['11', '17', '19', '25'],
  '19': ['12', '18', '20', '26'],
  '20': ['13', '19', '27'],
  '21': ['14', '22', '28'],
  '22': ['15', '21', '23', '29'],
  '23': ['16', '22', '24', '30'],
  '24': ['17', '23', '25', '31'],
  '25': ['18', '24', '26', '32'],
  '26': ['19', '25', '33'],
  '27': ['20', '34'],
  '28': ['21', '29', '35'],
  '29': ['22', '28', '30', '36'],
  '30': ['23', '29', '31', '37'],
  '31': ['24', '30', '32', '38'],
  '32': ['25', '31', '33', '39'],
  '33': ['26', '32', '34', '40'],
  '34': ['27', '33', '41'],
  '35': ['28', '36', '42'],
  '36': ['29', '35', '37', '43'],
  '37': ['30', '36', '38', '44'],
  '38': ['31', '37', '39', '45'],
  '39': ['32', '38', '40', '46'],
  '40': ['33', '39', '41', '47'],
  '41': ['34', '40', '48'],
  '42': ['35', '43', '49'],
  '43': ['36', '42', '44', '50'],
  '44': ['37', '43', '45', '51'],
  '45': ['38', '44', '46', '52'],
  '46': ['39', '45', '47', '53'],
  '47': ['40', '46', '48', '54'],
  '48': ['41', '47', '55'],
  '49': ['42', '56'],
  '50': ['43', '51', '57'],
  '51': ['44', '50', '52', '58'],
  '52': ['45', '51', '53', '59'],
  '53': ['46', '52', '54'],
  '54': ['47', '53', '55', '61'],
  '55': ['48', '54', '62'],
  '56': ['49', '57', '63'],
  '57': ['50', '56', '58', '64'],
  '58': ['51', '57', '59', '65'],
  '59': ['52', '58', '60', '66'],
  '60': ['59'],
  '61': ['54', '62', '68'],
  '62': ['55', '61', '69'],
  '63': ['56', '64', '70'],
  '64': ['57', '63', '65', '71'],
  '65': ['58', '64', '66', '72'],
  '66': ['59', '65', '67'],
  '67': ['66', '68'],
  '68': ['61', '67', '69', '75'],
  '69': ['62', '68', '76'],
  '70': ['63', '71', '77'],
  '71': ['64', '70', '72', '78'],
  '72': ['65', '71', '73', '79'],
  '73': ['72', '80'],
  '75': ['68', '76', '82'],
  '76': ['69', '75', '83'],
  '77': ['70', '78'],
  '78': ['71', '77', '79'],
  '79': ['72', '78', '80'],
  '80': ['73', '79', '81'],
  '81': ['80', '82'],
  '82': ['75', '81', '83'],
  '83': ['76', '82']}}
```

The preceding dictionary `connectivityGraph` lists the neighboring qubits for each qubit in the Rigetti device.

 **Choose the IonQ Forte-Enterprise-1 device** 

For the IonQ Forte-Enterprise-1 device, the `connectivityGraph` is empty, as shown in the following example, because the device offers *all-to-all* connectivity. Therefore, a detailed `connectivityGraph` is not needed.

```
# or choose the IonQ Forte-Enterprise-1 device
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Forte-Enterprise-1")

# take a look at the device connectivity graph
device.properties.dict()['paradigm']['connectivity']
```

```
{'fullyConnected': True, 'connectivityGraph': {...}}
```

As shown in the following example, you have the option to adjust the shots (default=1000), the `poll_timeout_seconds` (default = 432000 = 5 days), the `poll_interval_seconds` (default = 1), and the location of the S3 bucket (`s3_location`) where your results will be stored if you choose to specify a location other than the default bucket.

```
my_task = device.run(circ, s3_location = 'amazon-braket-my-folder', shots=100, poll_timeout_seconds = 100, poll_interval_seconds = 10)
```

The IonQ and Rigetti devices compile the provided circuit into their respective native gate sets automatically, and they map the abstract qubit indices to physical qubits on the respective QPU.

**Note**  
QPU devices have limited capacity. You can expect longer wait times when capacity is reached.

 Amazon Braket can run QPU quantum tasks within certain availability windows, but you can still submit quantum tasks any time (24/7) because all corresponding data and metadata are stored reliably in the appropriate S3 bucket. As shown in the next section, you can recover your quantum task using `AwsQuantumTask` and your unique quantum task ID.

# Inspecting compiled circuits
<a name="braket-compiled-circuits-inspecting"></a>

When a quantum circuit needs to be run on a hardware device, such as a quantum processing unit (QPU), the circuit must first be compiled into an acceptable format that the device can understand and process. For example, transpiling the high-level quantum circuit down to the specific native gates supported by the target QPU hardware. Inspecting the actual compiled output of the quantum circuit can be extremely useful for debugging and optimization purposes. This knowledge can help identify potential issues, bottlenecks, or opportunities for improving the performance and efficiency of the quantum application. You can view and analyze the compiled output of your quantum circuits for both Rigetti and IQM quantum computing devices using the code provided below. 

```
task = AwsQuantumTask(arn=task_id, aws_session=session)
# After the task has finished running
task_result = task.result()
compiled_circuit = task_result.get_compiled_circuit()
```

**Note**  
Currently, viewing the compiled circuit output for IonQ devices is not supported.

# Running multiple programs
<a name="braket-batching-tasks"></a>

Amazon Braket offers two approaches for running multiple quantum programs efficiently: Program sets and quantum task batching.

**Program sets** are the preferred way to run workloads with multiple programs. They allow you to package multiple programs into a single Amazon Braket quantum task. Program sets provides [performance improvements](https://aws.amazon.com/blogs/quantum-computing/amazon-braket-introduces-program-sets-enabling-customers-to-run-quantum-programs-up-to-24x-faster/) and cost savings compared to submitting programs individually, especially when the number of program executions approaches 100. 

Currently, IQM and Rigetti devices support program sets. Before submitting program sets to QPUs, it is recommend to [test on the Amazon Braket Local Simulator](https://docs.aws.amazon.com/braket/latest/developerguide/braket-send-to-local-simulator.html) first. To check whether a device supports program sets, you can view the [device's properties](https://github.com/amazon-braket/amazon-braket-examples/blob/main/examples/braket_features/Getting_Devices_and_Checking_Device_Properties.ipynb) using Amazon Braket SDK or view the device page in [Amazon Braket Console](https://console.aws.amazon.com/braket/).

The following example shows how to run a program set.

```
from math import pi
from braket.devices import LocalSimulator
from braket.program_sets import ProgramSet
from braket.circuits import Circuit

program_set = ProgramSet([
    Circuit().h(0).cnot(0,1),
    Circuit().rx(0, pi/4).ry(1, pi/8).cnot(1,0),
    Circuit().t(0).t(1).cz(0,1).s(0).cz(1,2).s(1).s(2),
])

device = LocalSimulator()
result = device.run(program_set, shots=300).result()
print(result[0][0].counts)  # The result of the first program in the program set
```

To learn more about different ways of constructing a program set (For example, construct a program set from many observables or parameters with a single program) and retrieving program set results, see the [program sets](https://docs.aws.amazon.com/braket/latest/developerguide/braket-constructing-circuit.html#braket-program-set) section in the *Amazon Braket Developer Guide* and the [program sets folder](https://github.com/amazon-braket/amazon-braket-examples/tree/main/examples/braket_features/program_sets) in the Braket examples Github repository.

**Quantum task batching** is available on every Amazon Braket device. Batching is especially useful for quantum tasks you run on the on-demand simulators (SV1, DM1 or TN1) because they can process multiple quantum tasks in parallel. Batching allows you to launch quantum tasks in parallel. For example, if you wish to make a calculation that requires 10 quantum tasks and the programs in those quantum tasks are independent of each other, it is recommended to use task batching. Use quantum task batching when running workloads with multiple programs on a device that does not support program sets.

The following example shows how to run a batch of quantum tasks.

```
from braket.circuits import Circuit
from braket.devices import LocalSimulator

bell = Circuit().h(0).cnot(0, 1)
circuits = [bell for _ in range(5)]

device = LocalSimulator()
batch = device.run_batch(circuits, shots=100)
print(batch.results()[0].measurement_counts)  # The result of the first quantum task in the batch
```

For more specific information about batching, see the [Amazon Braket examples](https://github.com/amazon-braket/amazon-braket-examples) on GitHub.

**Topics**
+ [About program set and costs](#braket-program-sets-costs)
+ [About quantum task batching and costs](#braket-batching-costs)
+ [Quantum task batching and PennyLane](#braket-batching-pennylane)
+ [Task batching and parametrized circuits](#braket-batching-parametrized-circuits)

## About program set and costs
<a name="braket-program-sets-costs"></a>

Program sets efficiently run multiple quantum programs by packaging up to 100 programs or parameter sets into a single quantum task. With program sets, you pay only one per-task fee plus per-shot fees based on the total shots across all programs, significantly reducing costs compared to submitting programs individually. This approach is particularly beneficial for workloads with many programs and with low number of shots per program. Program sets are currently supported on IQM and Rigetti devices, as well as the Amazon Braket Local Simulator. 

For more information, see the [Program sets](https://docs.aws.amazon.com/braket/latest/developerguide/braket-constructing-circuit.html#braket-program-set) section for detailed implementation steps, best practices, and code examples.

## About quantum task batching and costs
<a name="braket-batching-costs"></a>

A few caveats to keep in mind regarding quantum task batching and billing costs:
+ By default, quantum task batching retries all time out or fail quantum tasks 3 times.
+ A batch of long running quantum tasks, such as 34 qubits for SV1, can incur large costs. Be sure to double check the `run_batch` assignment values carefully before you start a batch of quantum tasks. We do not recommend using TN1 with `run_batch`.
+  TN1 can incur costs for failed rehearsal phase tasks (see [the TN1 description](https://docs.aws.amazon.com/braket/latest/developerguide/braket-devices.html#braket-simulator-tn1) for more information). Automatic retries can add to the cost and so we recommend setting the number of 'max\$1retries' on batching to 0 when using TN1 (see [Quantum Task Batching, Line 186](https://github.com/aws/amazon-braket-sdk-python/blob/4c7c3b28e5a17b8f0cddf94377b7734fcbe2ebfc/src/braket/aws/aws_quantum_task_batch.py#L186)).

## Quantum task batching and PennyLane
<a name="braket-batching-pennylane"></a>

Take advantage of batching when you're using PennyLane on Amazon Braket by setting `parallel = True` when you instantiate an Amazon Braket device, as shown in the following example.

```
import pennylane as qml

# Define the number of wires (qubits) you want to use
wires = 2  # For example, using 2 qubits

# Define your S3 bucket 
my_bucket = "amazon-braket-s3-demo-bucket"
my_prefix = "pennylane-batch-output"
s3_folder = (my_bucket, my_prefix)

device = qml.device("braket.aws.qubit", 
                    device_arn="arn:aws:braket:::device/quantum-simulator/amazon/sv1", 
                    wires=wires, 
                    s3_destination_folder=s3_folder, 
                    parallel=True)
```

For more information about batching with PennyLane, see [Parallelized optimization of quantum circuits](https://github.com/aws/amazon-braket-examples/blob/main/examples/pennylane/1_Parallelized_optimization_of_quantum_circuits/1_Parallelized_optimization_of_quantum_circuits.ipynb).

## Task batching and parametrized circuits
<a name="braket-batching-parametrized-circuits"></a>

When submitting a quantum task batch that contains parametrized circuits, you can either provide an `inputs` dictionary, which is used for all quantum tasks in the batch, or a `list` of input dictionaries, in which case the `i`-th dictionary is paired with the `i`-th task, as shown in the following example.

```
from braket.circuits import Circuit, FreeParameter, Observable
from braket.aws import AwsQuantumTaskBatch, AwsDevice

# Define your quantum device
device = AwsDevice("arn:aws:braket:::device/quantum-simulator/amazon/sv1")

# Create the free parameters
alpha = FreeParameter('alpha')
beta = FreeParameter('beta')

# Create two circuits
circ_a = Circuit().rx(0, alpha).ry(1, alpha).cnot(0, 2).xx(0, 2, beta)
circ_a.variance(observable=Observable.Z(), target=0)

circ_b = Circuit().rx(0, alpha).rz(1, alpha).cnot(0, 2).zz(0, 2, beta)
circ_b.expectation(observable=Observable.Z(), target=2)

# Use the same inputs for both circuits in one batch
tasks = device.run_batch([circ_a, circ_b], inputs={'alpha': 0.1, 'beta': 0.2})

# Or provide each task its own set of inputs
inputs_list = [{'alpha': 0.3, 'beta': 0.1}, {'alpha': 0.1, 'beta': 0.4}]

tasks = device.run_batch([circ_a, circ_b], inputs=inputs_list)
```

You can also prepare a list of input dictionaries for a single parametric circuit and submit them as a quantum task batch. If there is N input dictionaries in the list, the batch contains N quantum task. The `i`-th quantum task corresponds to the circuit executed with `i`-th input dictionary. 

```
from braket.circuits import Circuit, FreeParameter

# Create a parametric circuit
circ = Circuit().rx(0, FreeParameter('alpha'))

# Provide a list of inputs to execute with the circuit
inputs_list = [{'alpha': 0.1}, {'alpha': 0.2}, {'alpha': 0.3}]

tasks = device.run_batch(circ, inputs=inputs_list, shots=100)
```

# When will my quantum task run?
<a name="braket-task-when"></a>

When you submit a circuit, Amazon Braket sends it to the device you specify. Quantum Processing Unit (QPU) and on-demand simulator quantum tasks are queued and processed in the order they are received. The time required to process your quantum task after you submit it varies depending on the number and complexity of tasks submitted by other Amazon Braket customers and the availability of the QPU selected.

**Topics**
+ [QPU availability windows and status](#braket-qpu-availability)
+ [Queue visibility](#braket-queue-visibility)
+ [Set up email or SMS notifications](status-change-notifications-in-email-or-sms.md)

## QPU availability windows and status
<a name="braket-qpu-availability"></a>

QPU availability varies from device to device.

In the **Devices** page of the Amazon Braket console, you can see the current and upcoming availability windows and device status. Additionally, each device page shows individual queue depths for quantum tasks and hybrid jobs. 

A device is considered *offline* if is not available to customers, regardless of availability window. For example, it could be offline due to scheduled maintenance, upgrades, or operational issues.

## Queue visibility
<a name="braket-queue-visibility"></a>

Before submitting a quantum task or hybrid job, you can view how many quantum tasks or hybrid jobs are in front of you by checking device queue depth.

**Queue depth**

Queue depth refers to the number of quantum tasks and hybrid jobs queued for a particular device. A device's quantum task and hybrid job queue count are accessible through the Braket Software Development Kit (SDK) or Amazon Braket Management Console. 

1. *Task queue depth* refers to the total number of quantum tasks currently waiting to run in normal priority.

1. *Priority task queue depth* refers to the total number of submitted quantum tasks waiting to run through Amazon Braket Hybrid Jobs. These tasks run before standalone tasks.

1. *Hybrid jobs queue depth* refers to the total number of hybrid jobs currently queued on a device. Quantum tasks submitted as part of a hybrid job have priority, and are aggregated in the Priority Task Queue.

Customers wishing to view queue depth through the Braket SDK can modify the following code snippet to get the queue position of their quantum task or hybrid job: 

```
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Forte-Enterprise-1")

# returns the number of quantum tasks queued on the device 
print(device.queue_depth().quantum_tasks)
{<QueueType.NORMAL: 'Normal'>: '0', <QueueType.PRIORITY: 'Priority'>: '0'}


# returns the number of hybrid jobs queued on the device
print(device.queue_depth().jobs)
'3'
```

Submitting a quantum task or hybrid job to a QPU may result in your workload being in a `QUEUED` state. Amazon Braket provides customers visibility into their quantum task and hybrid job queue position. 

**Queue position**

Queue position refers to the current position of your quantum task or hybrid job within a respective device queue. It can be obtained for quantum tasks or hybrid jobs through the Braket Software Development Kit (SDK) or Amazon Braket Management Console. 

Customers wishing to view queue position through the Braket SDK can modify the following code snippet to get the queue position of their quantum task or hybrid job: 

```
# choose the device to run your circuit 
device = AwsDevice("arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet")
 
#execute the circuit 
task = device.run(bell, s3_folder, shots=100)

# retrieve the queue position information
print(task.queue_position().queue_position)
    
# Returns the number of Quantum Tasks queued ahead of you
'2'
        

from braket.aws import AwsQuantumJob

job = AwsQuantumJob.create(
    "arn:aws:braket:eu-north-1::device/qpu/iqm/Garnet",
    source_module="algorithm_script.py",
    entry_point="algorithm_script:start_here",
    wait_until_complete=False
)

# retrieve the queue position information
print(job.queue_position().queue_position)
'3' # returns the number of hybrid jobs queued ahead of you
```

# Set up email or SMS notifications
<a name="status-change-notifications-in-email-or-sms"></a>

Amazon Braket sends events to Amazon EventBridge when the availability of a QPU changes or when the state of your quantum task changes. Follow these steps to receive device and quantum task status change notifications by email or SMS message:

1. Create an Amazon SNS topic and a subscription to email or SMS. Availability of email or SMS depends on your Region. For more information, see [Getting started with Amazon SNS](https://docs.aws.amazon.com/sns/latest/dg/sns-getting-started.html) and [Sending SMS messages](https://docs.aws.amazon.com/sns/latest/dg/sns-mobile-phone-number-as-subscriber.html).

1. Create a rule in EventBridge that triggers the notifications to your SNS topic. For more information, see [Monitoring Amazon Braket with Amazon EventBridge](braket-monitor-eventbridge.md).

## (Optional) Set up SNS notifications
<a name="braket-sns-notifications"></a>

You can set up notifications through the Amazon Simple Notification Service (SNS) so that you receive an alert when your Amazon Braket quantum task is complete. Active notifications are useful if you expect a long wait time; for example, when you submit a large quantum task or when you submit a quantum task outside of a device's availability window. If you do not want to wait for the quantum task to complete, you can set up an SNS notification.

An Amazon Braket notebook walks you through the setup steps. For more information, see [the Amazon Braket examples on GitHub](https://github.com/aws/amazon-braket-examples) and, specifically, [the example notebook for setting up notifications](https://github.com/aws/amazon-braket-examples/tree/main/examples/braket_features).

# Working with reservations
<a name="braket-reservations"></a>

Reservations give you exclusive access to the quantum device of your choice. You can schedule a reservation at your convenience, so you know exactly when your workload starts and ends execution. Reservations are available in 1-hour increments for all Braket devices and can be cancelled up to 48 hours in advance, at no additional charge. We recommend queuing quantum tasks and hybrid jobs for an upcoming reservation in advance, using your Braket Direct Reservation ARN, or submitting workloads during your reservation.

The cost of dedicated device access is based on the duration of your reservation, regardless of how many quantum tasks and hybrid jobs you run on the quantum processing unit (QPU). An updated list of quantum computers available for reservations can be found on our [pricing page](https://aws.amazon.com/braket/pricing/) or via the [Amazon Braket management console](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/devices). 

**Note**  
In a reservation, there are no [gateshot](braket-terms.md#gateshot-limit-term) limits. Additionally, for IonQ devices, the minimum shot count for [Error mitigation](https://docs.aws.amazon.com/braket/latest/developerguide/braket-error-mitigation.html) tasks is reduced to 500 (vs. 2500 for on-demand).

 **When to use a reservation** 

Leveraging reservation access provides you the convenience and predictability of knowing exactly when your quantum workload starts and ends execution. Compared to submitting tasks and hybrid jobs on-demand, you do not have wait in a queue with other customer tasks. Because you have exclusive access to the device during your reservation, only your workloads run on the device for the entirety of the reservation.

We recommend using on-demand access for the design and prototyping phase of your research, enabling quick and cost-efficient iteration of your algorithms. Once you are ready to produce final experiment results, consider scheduling a device reservation at your convenience to ensure that you can meet project or publication deadlines. We also recommend using reservations when you desire task execution during specific times, such as when you're running a live demo or workshop on a quantum computer.

**Topics**
+ [How to create a reservation](braket-create-a-reservation.md)
+ [Running quantum tasks during a reservation](braket-run-quantum-task-with-reservation.md)
+ [Running hybrid jobs during a reservation](braket-run-hybrid-jobs-with-reservation.md)
+ [What happens at the end of your reservation](braket-end-of-reservation.md)
+ [Cancel or reschedule an existing reservation](braket-cancel-reservation.md)

# How to create a reservation
<a name="braket-create-a-reservation"></a>

To create a reservation, contact the Braket team by following these steps:

1. Open the Amazon Braket console.

1. Choose **Braket Direct** in the left pane, and then in the **Reservations** section, choose **Reserve device **.

1. Select the **Device** that you would like to reserve.

1. Provide your contact information including **Name** and **Email**. Be sure to provide a valid email address that you regularly check.

1. Under **Tell us about your workload**, provide any details about the workload to run using your reservation. For example, desired reservation length, relevant constraints, or desired schedule.

After you submit the form, you receive an email from the Braket team with the next steps. Once your reservation is confirmed, you will receive the reservation ARN through your email. You will need the to use the reservation ARN to create reservation tasks. Tasks created without the reservation ARN will be submitted to the regular on-demand queue and will NOT run during your reservation.

**Note**  
Your reservation is only confirmed once you receive the reservation ARN.

Reservations are available in minimum 1-hour increments and certain devices might have additional reservation length constraints (including minimum and maximum reservation durations). The Braket team shares any relevant information with you prior to confirming the reservation.

The Braket team will contact you through your email to arrange a 30-minute session with a Braket expert.

# Running quantum tasks during a reservation
<a name="braket-run-quantum-task-with-reservation"></a>

After obtaining a valid reservation ARN from [Create a reservation](https://docs.aws.amazon.com/braket/latest/developerguide/braket-reservations.html#braket-create-a-reservation), you can create quantum tasks to run during the reservation. Quantum tasks and hybrid jobs submitted with a reservation ARN will not show up in a device queue. Tasks submitted before reservation start time will remain in the `QUEUED` state until your reservation begins. 

**Note**  
Reservations are AWS account and device-specific. Only the AWS account that created the reservation can use your reservation ARN.   
During a reservation, both reservation and regular tasks can be created. To verify that a created Braket quantum task is associated with a reservation, check the “Reservation ARN” field on the page of the quantum task in the Braket console, or query the same field in the task metadata using the SDK. The rest of this page describes how to specify which tasks are associated to the reseravation. 

You can create quantum tasks using Python SDKs such as [Braket](https://docs.aws.amazon.com/braket/latest/developerguide/braket-references.html), [https://github.com/NVIDIA/cuda-quantum](https://github.com/NVIDIA/cuda-quantum), [https://github.com/amazon-braket/amazon-braket-pennylane-plugin-python](https://github.com/amazon-braket/amazon-braket-pennylane-plugin-python), [https://github.com/qiskit-community/qiskit-braket-provider](https://github.com/qiskit-community/qiskit-braket-provider), or directly with boto3 ([Working with Boto3](https://docs.aws.amazon.com/braket/latest/developerguide/braket-using-boto3.html)). To use reservations, you must have version [v1.79.0](https://github.com/amazon-braket/amazon-braket-sdk-python/releases/tag/v1.79.0) or higher of the [Amazon Braket Python SDK](https://github.com/amazon-braket/amazon-braket-sdk-python). You can update to the latest Braket SDK, Qiskit provider and PennyLane plugin with the following code. 

```
pip install --upgrade amazon-braket-sdk amazon-braket-pennylane-plugin qiskit-braket-provider
```

**Run tasks with the `DirectReservation` context manager**

The recommended way to run a task within your scheduled reservation is to use the `DirectReservation` context manager. By specifying your target device and reservation ARN, the context manager ensures that all tasks created within the Python `with` statement are run with exclusive access to the device. 

First, define a quantum circuit and the device. Then use the reservation context and run the task. **Ensure that your entire workload is run inside the `with` block; anything run outside the scope of the `with` block will not be associated with your reservation\$1**

```
from braket.aws import AwsDevice, DirectReservation
from braket.circuits import Circuit
from braket.devices import Devices

bell = Circuit().h(0).cnot(0, 1)
device = AwsDevice(Devices.IonQ.ForteEnterprise1)

# run the circuit in a reservation
with DirectReservation(device, reservation_arn="<my_reservation_arn>"):
    task = device.run(bell, shots=100)
```

You can create quantum tasks in a reservation using CUDA-Q, PennyLane, and Qiskit plugins, as long as the `DirectReservation` context is active while creating quantum tasks. For example, with the Qiskit-Braket provider, you can run tasks as follows.

```
from braket.devices import Devices
from braket.aws import DirectReservation
from qiskit import QuantumCircuit
from qiskit_braket_provider import BraketProvider


qc = QuantumCircuit(2)
qc.h(0)
qc.cx(0, 1)

qpu = BraketProvider().get_backend("Forte Enterprise 1")

# run the circuit in a reservation
with DirectReservation(Devices.IonQ.ForteEnterprise1, reservation_arn="<my_reservation_arn>"):
    qpu_task = qpu.run(qc, shots=10)
```

Similarly, the following code runs a circuit during a reservation using the Braket-PennyLane plugin.

```
from braket.devices import Devices
from braket.aws import DirectReservation
import pennylane as qml


dev = qml.device("braket.aws.qubit", device_arn=Devices.IonQ.ForteEnterprise1.value, wires=2, shots=10)

@qml.qnode(dev)
def bell_state():
    qml.Hadamard(wires=0)
    qml.CNOT(wires=[0, 1])
    return qml.probs(wires=[0, 1])

# run the circuit in a reservation
with DirectReservation(Devices.IonQ.ForteEnterprise1, reservation_arn="<my_reservation_arn>"):
    probs = bell_state()
```

**Manually setting the reservation context**

Alternatively, you can manually set the reservation context with the following code.

```
# set reservation context 
reservation_context = DirectReservation(device, reservation_arn="<my_reservation_arn>").start()

# run circuit during reservation
task = device.run(bell, shots=100)
```

This is ideal for Jupyter notebooks where the context can be run in the first cell and all subsequent tasks will run in the reservation.

**Note**  
The cell containing the `.start()` call should *only be run once*. 

To switch back to the on-demand mode: Restart the Jupyter notebook, or call the following to change the context back to on-demand mode.

```
reservation_context.stop()  # unset reservation context 
```

**Note**  
 Reservations have a pre-determined start and end time (see [Create a reservation](https://docs.aws.amazon.com/braket/latest/developerguide/braket-reservations.html#braket-create-a-reservation)). The `reservation_context.start()` and `reservation_context.stop()` methods **do not begin or terminate a reservation**. Instead, while the context is active, any quantum tasks that you create will be associated with your reservation, and will run only during your scheduled reservation. The reservation context has no effect on the scheduled reservation time. 

**Explicitly pass the reservation ARN when creating task**

Another way to create tasks during a reservation is to explicitly pass the reservation ARN when calling `device.run()`. 

```
task = device.run(bell, shots=100, reservation_arn="<my_reservation_arn>")
```

This method directly associates the quantum task with the reservation ARN, ensuring it runs during the reserved period. For this option, add the reservation ARN to each task you plan to run during a reservation. However, note that when using third-party libraries such as Qiskit or PennyLane, it may be difficult to ensure that submitted tasks are using the correct reservation ARN. For this reason, using the DirectReservation context manager is recommended. 

When directly using boto3, pass the reservation ARN as an association when creating a task.

```
import boto3

braket_client = boto3.client("braket")


kwargs["associations"] = [
    {
        "arn": "<my_reservation_arn>",
        "type": "RESERVATION_TIME_WINDOW_ARN",
    }
]

response = braket_client.create_quantum_task(**kwargs)
```

# Running hybrid jobs during a reservation
<a name="braket-run-hybrid-jobs-with-reservation"></a>

Once you have a Python function to run as a hybrid job, you can run the hybrid job in a reservation by passing the `reservation_arn` keyword argument. All the tasks within the hybrid job use the reservation ARN. Importantly, the hybrid job with `reservation_arn` *only spins up the classical compute once your reservation starts*. 

**Note**  
A hybrid job running during a reservation *only successfully runs* quantum tasks on the reserved device. Attempting to use a different on-demand Braket device will result in an error. If you need to run tasks on both an on-demand simulator and the reserved device within the same hybrid job, use `DirectReservation` instead.

The following code demonstrates how to run a hybrid job during a reservation.

```
from braket.aws import AwsDevice
from braket.devices import Devices
from braket.jobs import get_job_device_arn, hybrid_job

@hybrid_job(device=Devices.IonQ.ForteEnterprise1, reservation_arn="<my_reservation_arn>")
def example_hybrid_job():
    # declare AwsDevice within the hybrid job
    device = AwsDevice(get_job_device_arn())
    bell = Circuit().h(0).cnot(0, 1)
    
    task = device.run(bell, shots=10)
```

For hybrid jobs that use a Python script (see the section on [Creating your first Hybrid Job](https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs-first.html) in the developer guide), you can run them within the reservation by passing the `reservation_arn` keyword argument when creating the job.

```
from braket.aws import AwsQuantumJob 
from braket.devices import Devices

job = AwsQuantumJob.create( 
    Devices.IonQ.ForteEnterprise1,
    source_module="algorithm_script.py", 
    entry_point="algorithm_script:start_here",
    reservation_arn="<my_reservation_arn>"
)
```

# What happens at the end of your reservation
<a name="braket-end-of-reservation"></a>

After your reservation ends, you no longer have dedicated access to the device. Any remaining workloads that are queued with this reservation are automatically canceled.

**Note**  
Any job that was in `RUNNING` status when the reservation ends is canceled. We recommend using [checkpoints to save and restart](https://docs.aws.amazon.com/braket/latest/developerguide/braket-jobs-checkpoints.html) jobs at your convenience.

An ongoing reservation, such as after reservation start and before reservation end, can't be extended because each reservation represents standalone dedicated device access. For example, two back-to-back reservations are considered separate and any pending tasks from the first reservation are automatically canceled. They do not resume in the second reservation.

**Note**  
Reservations represent dedicated device access for your AWS account. Even if the device remains idle, no other customers can use it. Therefore, you are charged for the length of the reserved time, regardless of the utilized time.

# Cancel or reschedule an existing reservation
<a name="braket-cancel-reservation"></a>

You can cancel your reservation no less than 48 hours before the scheduled reservation start time. To cancel, respond to the reservation confirmation email you received with your cancellation request.

To reschedule, you have to cancel your existing reservation, and then create a new one.

# Error mitigation techniques
<a name="braket-error-mitigation"></a>

Quantum error mitigation is a set of techniques aimed at reducing the effects of errors in quantum computers. 

Quantum devices are subject to environmental noise that degrades the quality of computations performed. While fault-tolerant quantum computing promises a solution to this problem, current quantum devices are limited by the number of qubits and relatively high error rates. To combat this in the near-term, researchers are investigating methods to improve the accuracy of noisy quantum computation. This approach, known as *quantum error mitigation*, involves using various techniques to extract the best signal from noisy measurement data.

**Topics**
+ [Error mitigation techniques on IonQ devices](error-mitigation-ionq.md)

# Error mitigation techniques on IonQ devices
<a name="error-mitigation-ionq"></a>

Error mitigation involves running multiple physical circuits and combining their measurements to give an improved result.

**Note**  
For all IonQ's devices: When using an on-demand model, there is a 1 Million [gateshot](braket-terms.md#gateshot-limit-term) limit, and a minimum of 2500 shots for [Error mitigation](https://docs.aws.amazon.com/braket/latest/developerguide/braket-error-mitigation.html) tasks. For a direct reservation, there is no gateshot limit, and a minimum of 500 shots for Error mitigation tasks.

## Debiasing
<a name="error-mitigation-ionq-debiasing"></a>

IonQ devices features an error mitigation method called *debiasing*. 

Debiasing maps a circuit into multiple variants that act on different qubit permutations or with different gate decompositions. This reduces the effect of systematic errors such as gate over-rotations or a single faulty qubit by using different implementations of a circuit that could otherwise bias measurement results. This comes at the expense of extra overhead to calibrate multiple qubits and gates.

For more information on debiasing, see [Enhancing quantum computer performance through symmetrization](https://arxiv.org/abs/2301.07233).

**Note**  
Using debiasing requires a minimum of 2500 shots.

You can run a quantum task with debiasing on an IonQ device using the following code:

```
from braket.aws import AwsDevice
from braket.circuits import Circuit
from braket.error_mitigation import Debias

# choose an IonQ device
device = AwsDevice("arn:aws:braket:us-east-1::device/qpu/ionq/Forte-Enterprise-1")
circuit = Circuit().h(0).cnot(0, 1)

task = device.run(circuit, shots=2500, device_parameters={"errorMitigation": Debias()})

result = task.result()
print(result.measurement_counts)
>>> {"00": 1245, "01": 5, "10": 10 "11": 1240} # result from debiasing
```

When the quantum task is complete, you can see the measurement probabilities and any result types from the quantum task. The measurement probabilities and counts from all variants are aggregated into a single distribution. Any result types specified in the circuit, such as expectation values, are computed using the aggregate measurement counts.

## Sharpening
<a name="error-mitigation-ionq-sharpening"></a>

You can also access measurement probabilities computed with a different post-processing strategy called *sharpening*. Sharpening compares the results of each variant and discards inconsistent shots, favoring the most likely measurement outcome across variants. For more information, see [Enhancing quantum computer performance through symmetrization](https://arxiv.org/abs/2301.07233). 

Importantly, sharpening assumes the form of the output distribution to be sparse with few high-probability states and many zero-probability states. It may distort the probability distribution if this assumption is not valid. 

You can access the probabilities from a sharpened distribution in the `additional_metadata` field on the `GateModelTaskResult` in the Braket Python SDK. Note that sharpening does not return the measurement counts, but instead returns a re-normalized probability distribution. The following code snippet shows how to access the distribution after sharpening.

```
print(result.additional_metadata.ionqMetadata.sharpenedProbabilities)
>>> {"00": 0.51, "11": 0.549} # sharpened probabilities
```