

# Analog Hamiltonian Simulation
<a name="braket-analog-hamiltonian-simulation"></a>

[Analog Hamiltonian Simulation](https://en.wikipedia.org/wiki/Hamiltonian_simulation) (AHS) is an emerging paradigm in quantum computing that differs significantly from the traditional quantum circuit model. Instead of a sequence of gates, where each circuit acts only on a couple of qubits at a time. An AHS program is defined by the time-dependent and space-dependent parameters of the Hamiltonian in question. The [Hamiltonian of a system](https://en.wikipedia.org/wiki/Hamiltonian_(quantum_mechanics)) encodes its energy levels and the effects of external forces, which together govern the time evolution of its states. For an N-qubit systems, the Hamiltonian can be represented by a 2NX2N square matrix of complex numbers.

Quantum devices capable of performing AHS are designed to closely approximate the time evolution of a quantum system under a custom Hamiltonian by carefully tuning their internal control parameters. Such as, adjusting the amplitude and detuning parameters of a coherent driving field. The AHS paradigm is well-suited for simulating the static and dynamic properties of quantum systems with many interacting particles, such as in condensed matter physics or quantum chemistry. Purpose-built quantum processing units (QPUs), like the [Aquila device](https://aws.amazon.com/braket/quantum-computers/quera/) from QuEra, have been developed to use the power of AHS and tackle problems beyond the reach of conventional digital quantum computing approaches in innovative ways.

**Topics**
+ [Hello AHS: Run your first Analog Hamiltonian Simulation](braket-get-started-hello-ahs.md)
+ [Submit an analog program using QuEra Aquila](braket-quera-submitting-analog-program-aquila.md)

# Hello AHS: Run your first Analog Hamiltonian Simulation
<a name="braket-get-started-hello-ahs"></a>

This section provides information on running your first Analog Hamiltonian Simulation.

**Topics**
+ [Interacting spin chain](#braket-get-started-interacting-spin-chain)
+ [Arrangement](#braket-get-started-arrangement)
+ [Interaction](#braket-get-started-interaction)
+ [Driving field](#braket-get-started-driving-field)
+ [AHS program](#braket-get-started-ahs-program)
+ [Running on local simulator](#braket-get-started-running-local-simulator)
+ [Analyzing simulator results](#braket-get-started-analyzing-simulator-results)
+ [Running on QuEra's Aquila QPU](#braket-get-started-running-aquila-qpu)
+ [Analyzing QPU results](#braket-get-started-analyzing-qpu-results)
+ [Next steps](#braket-get-started-ahs-next)

## Interacting spin chain
<a name="braket-get-started-interacting-spin-chain"></a>

For a canonical example of a system of many interacting particles, let us consider a ring of eight spins (each of which can be in “up” ∣↑⟩ and “down” ∣↓⟩ states). Albeit small, this model system already exhibits a handful of interesting phenomena of naturally occurring magnetic materials. In this example, we will show how to prepare a so-called anti-ferromagnetic order, where consecutive spins point in opposite directions.

![\[Diagram connecting 8 circle nodes that contain inversing up and down arrows.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/AntiFerromagnetic.png)


## Arrangement
<a name="braket-get-started-arrangement"></a>

We will use one neutral atom to stand for each spin, and the “up” and “down” spin states will be encoded in excited Rydberg state and ground state of the atoms, respectively. First, we create the 2-d arrangement. We can program the above ring of spins with the following code.

 **Prerequisites**: You need to pip install the [Braket SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk). (If you are using a Braket hosted notebook instance, this SDK comes pre-installed with the notebooks.) To reproduce the plots, you also need to separately install matplotlib with the shell command `pip install matplotlib`.

```
from braket.ahs.atom_arrangement import AtomArrangement
import numpy as np
import matplotlib.pyplot as plt  # Required for plotting

a = 5.7e-6  # Nearest-neighbor separation (in meters)

register = AtomArrangement()
register.add(np.array([0.5, 0.5 + 1/np.sqrt(2)]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([0.5 + 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5, - 0.5 - 1/np.sqrt(2)]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), - 0.5]) * a)
register.add(np.array([-0.5 - 1/np.sqrt(2), 0.5]) * a)
register.add(np.array([-0.5, 0.5 + 1/np.sqrt(2)]) * a)
```

which we can also plot with

```
fig, ax = plt.subplots(1, 1, figsize=(7, 7))
xs, ys = [register.coordinate_list(dim) for dim in (0, 1)]
ax.plot(xs, ys, 'r.', ms=15)

for idx, (x, y) in enumerate(zip(xs, ys)):
    ax.text(x, y, f" {idx}", fontsize=12)

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[Scatter plot showing points distributed across positive and negative values on both axes.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/PlotNeutralAtoms.png)


## Interaction
<a name="braket-get-started-interaction"></a>

To prepare the anti-ferromagnetic phase, we need to induce interactions between neighboring spins. We use the [van der Waals interaction](https://en.wikipedia.org/wiki/Van_der_Waals_force) for this, which is natively implemented by neutral atom devices (such as the Aquila device from QuEra). Using the spin-representation, the Hamiltonian term for this interaction can be expressed as a sum over all spin pairs (j,k).

![\[Hamiltonian interaction equation showing this this interaction as expressed as a sum over all spin pairs (j,k).\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/HInteraction.png)


Here, nj​=∣↑j​⟩⟨↑j​∣ is an operator that takes the value of 1 only if spin j is in the “up” state, and 0 otherwise. The strength is Vj,k​=C6​/(dj,k​)6, where C6​ is the fixed coefficient, and dj,k​ is the Euclidean distance between spins j and k. The immediate effect of this interaction term is that any state where both spin j and spin k are “up” have elevated energy (by the amount Vj,k​). By carefully designing the rest of the AHS program, this interaction will prevent neighboring spins from both being in the “up” state, an effect commonly known as "Rydberg blockade."

## Driving field
<a name="braket-get-started-driving-field"></a>

At the beginning of the AHS program, all spins (by default) start in their “down” state, they are in a so-called ferromagnetic phase. Keeping an eye on our goal to prepare the anti-ferromagnetic phase, we specify a time-dependent coherent driving field that smoothly transitions the spins from this state to a many-body state where the “up” states are preferred. The corresponding Hamiltonian can be written as

![\[Mathematical equation depicting the calculation of a Hamiltonian drive function.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/HDrive.png)


where Ω(t),ϕ(t),Δ(t) are the time-dependent, global amplitude (aka [Rabi frequency](https://en.wikipedia.org/wiki/Rabi_frequency)), phase, and detuning of the driving field affecting all spins uniformly. Here S−,k​=∣↓k​⟩⟨↑k​∣and S\$1,k​​=(S−,k​)†=∣↑k​⟩⟨↓k​∣ are the lowering and raising operators of spin k, respectively, and nk​=∣↑k​⟩⟨↑k​∣ is the same operator as before. The Ω part of the driving field coherently couples the “down” and the “up” states of all spins simultaneously, while the Δ part controls the energy reward for “up” states.

To program a smooth transition from the ferromagnetic phase to the anti-ferromagnetic phase, we specify the driving field with the following code.

```
from braket.timings.time_series import TimeSeries
from braket.ahs.driving_field import DrivingField

# Smooth transition from "down" to "up" state
time_max = 4e-6  # seconds
time_ramp = 1e-7  # seconds
omega_max = 6300000.0  # rad / sec
delta_start = -5 * omega_max
delta_end = 5 * omega_max

omega = TimeSeries()
omega.put(0.0, 0.0)
omega.put(time_ramp, omega_max)
omega.put(time_max - time_ramp, omega_max)
omega.put(time_max, 0.0)

delta = TimeSeries()
delta.put(0.0, delta_start)
delta.put(time_ramp, delta_start)
delta.put(time_max - time_ramp, delta_end)
delta.put(time_max, delta_end)

phi = TimeSeries().put(0.0, 0.0).put(time_max, 0.0)

drive = DrivingField(
   amplitude=omega,
   phase=phi,
   detuning=delta
)
```

We can visualize the time series of the driving field with the following script.

```
fig, axes = plt.subplots(3, 1, figsize=(12, 7), sharex=True)

ax = axes[0]
time_series = drive.amplitude.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Omega [rad/s]')

ax = axes[1]
time_series = drive.detuning.time_series
ax.plot(time_series.times(), time_series.values(), '.-')
ax.grid()
ax.set_ylabel('Delta [rad/s]')

ax = axes[2]
time_series = drive.phase.time_series
# Note: time series of phase is understood as a piecewise constant function
ax.step(time_series.times(), time_series.values(), '.-', where='post')
ax.set_ylabel('phi [rad]')
ax.grid()
ax.set_xlabel('time [s]')

plt.show()  # This will show the plot below in an ipython or jupyter session
```

![\[Three graphs showing phi, delta, and omega over time. The top subplot shows the growth to just above 6 rads/s where it stays for 4 seconds until it drops back to 0. The middle subplot depicts the associated linear growth of the derivative, and the bottom subplot illustrates a flat line near zero.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/DrivingTimeSeries.png)


## AHS program
<a name="braket-get-started-ahs-program"></a>

The register, the driving field, (and the implicit van der Waals interactions) make up the Analog Hamiltonian Simulation program `ahs_program`.

```
from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation

ahs_program = AnalogHamiltonianSimulation(
   register=register,
   hamiltonian=drive
)
```

## Running on local simulator
<a name="braket-get-started-running-local-simulator"></a>

Since this example is small (less than 15 spins), before running it on an AHS-compatible QPU, we can run it on the local AHS simulator which comes with the Braket SDK. Since the local simulator is available for free with the Braket SDK, this is best practice to ensure that our code can correctly execute.

Here, we can set the number of shots to a high value (say, 1 million) because the local simulator tracks the time evolution of the quantum state and draws samples from the final state; hence, increasing the number of shots, while increasing the total runtime only marginally.

```
from braket.devices import LocalSimulator

device = LocalSimulator("braket_ahs")

result_simulator = device.run(
   ahs_program,
   shots=1_000_000
).result()  # Takes about 5 seconds
```

## Analyzing simulator results
<a name="braket-get-started-analyzing-simulator-results"></a>

We can aggregate the shot results with the following function that infers the state of each spin (which may be “d” for “down”, “u” for “up”, or “e” for empty site), and counts how many times each configuration occurred across the shots.

```
from collections import Counter


def get_counts(result):
    """Aggregate state counts from AHS shot results

    A count of strings (of length = # of spins) are returned, where
    each character denotes the state of a spin (site):
      e: empty site
      u: up state spin
      d: down state spin

    Args:
      result (braket.tasks.analog_hamiltonian_simulation_quantum_task_result.AnalogHamiltonianSimulationQuantumTaskResult)

    Returns
       dict: number of times each state configuration is measured

    """
    state_counts = Counter()
    states = ['e', 'u', 'd']
    for shot in result.measurements:
        pre = shot.pre_sequence
        post = shot.post_sequence
        state_idx = np.array(pre) * (1 + np.array(post))
        state = "".join(map(lambda s_idx: states[s_idx], state_idx))
        state_counts.update((state,))
    return dict(state_counts)


counts_simulator = get_counts(result_simulator)  # Takes about 5 seconds
print(counts_simulator)
```

```
*[Output]*
{'dddddddd': 5, 'dddddddu': 12, 'ddddddud': 15, ...}
```

Here `counts` is a dictionary that counts the number of times each state configuration is observed across the shots. We can also visualize them with the following code.

```
from collections import Counter


def has_neighboring_up_states(state):
    if 'uu' in state:
        return True
    if state[0] == 'u' and state[-1] == 'u':
        return True
    return False


def number_of_up_states(state):
    return Counter(state)['u']


def plot_counts(counts):
    non_blockaded = []
    blockaded = []
    for state, count in counts.items():
        if not has_neighboring_up_states(state):
            collection = non_blockaded
        else:
            collection = blockaded
        collection.append((state, count, number_of_up_states(state)))

    blockaded.sort(key=lambda _: _[1], reverse=True)
    non_blockaded.sort(key=lambda _: _[1], reverse=True)

    for configurations, name in zip((non_blockaded,
                                     blockaded),
                                    ('no neighboring "up" states',
                                     'some neighboring "up" states')):
        plt.figure(figsize=(14, 3))
        plt.bar(range(len(configurations)), [item[1] for item in configurations])
        plt.xticks(range(len(configurations)))
        plt.gca().set_xticklabels([item[0] for item in configurations], rotation=90)
        plt.ylabel('shots')
        plt.grid(axis='y')
        plt.title(f'{name} configurations')
        plt.show()


plot_counts(counts_simulator)
```

![\[Bar chart showing a large number of shots with no neighboring "up" states configurations.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/AHSCounts1.png)


![\[Bar chart showing shots of some neighboring "up" states configurations, with 4 states at 1.0 shots.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/AHSCounts2.png)


From the plots, we can read the following observations the verify that we successfully prepared the anti-ferromagnetic phase.

1. Generally, non-blockaded states (where no two neighboring spins are in the “up” state) are more common than states where at least one pair of neighboring spins are both in “up” states.

1. Generally, states with more "up" excitations are favored, unless the configuration is blockaded.

1. The most common states are indeed the perfect anti-ferromagnetic states `"dudududu"` and `"udududud"`.

1. The second most common states are the ones where there is only 3 “up” excitations with consecutive separations of 1, 2, 2. This shows that the van der Waals interaction has an affect (albeit much smaller) on next-nearest neighbors too.

## Running on QuEra's Aquila QPU
<a name="braket-get-started-running-aquila-qpu"></a>

 **Prerequisites**: Apart from pip installing the Braket [SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk), if you are new to Amazon Braket, make sure that you have completed the necessary [Get Started steps](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started.html).

**Note**  
If you are using a Braket hosted notebook instance, the Braket SDK comes pre-installed with the instance.

With all dependencies installed, we can connect to the Aquila QPU.

```
from braket.aws import AwsDevice

aquila_qpu = AwsDevice("arn:aws:braket:us-east-1::device/qpu/quera/Aquila")
```

To make our AHS program suitable for the QuEra machine, we need to round all values to comply with the levels of precision allowed by the Aquila QPU. (These requirements are governed by the device parameters with “Resolution” in their name. We can see them by executing `aquila_qpu.properties.dict()` in a notebook. For more details of capabilities and requirements of Aquila, see the [Introduction to Aquila](https://github.com/aws/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/01_Introduction_to_Aquila.ipynb) notebook.) We can do this by calling the `discretize` method.

```
discretized_ahs_program = ahs_program.discretize(aquila_qpu)
```

Now we can run the program (running only 100 shots for now) on the Aquila QPU.

**Note**  
Running this program on the Aquila processor will incur a cost. The Amazon Braket SDK includes a [Cost Tracker](https://aws.amazon.com/blogs/quantum-computing/managing-the-cost-of-your-experiments-in-amazon-braket/) that enables customers to set cost limits as well as track their costs in near real-time.

```
task = aquila_qpu.run(discretized_ahs_program, shots=100)

metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: CREATED
```

Due to the large variance of how long a quantum task may take to run (depending on availability windows and QPU utilization), it is a good idea to note down the quantum task ARN, so we can check its status at a later time with the following code snippet.

```
# Optionally, in a new python session
from braket.aws import AwsQuantumTask

SAVED_TASK_ARN = "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef"

task = AwsQuantumTask(arn=SAVED_TASK_ARN)
metadata = task.metadata()
task_arn = metadata['quantumTaskArn']
task_status = metadata['status']

print(f"ARN: {task_arn}")
print(f"status: {task_status}")
```

```
*[Output]*
ARN: arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef
status: COMPLETED
```

Once the status is COMPLETED (which can also be checked from the quantum tasks page of the Amazon Braket [console](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/tasks)), we can query the results with:

```
result_aquila = task.result()
```

## Analyzing QPU results
<a name="braket-get-started-analyzing-qpu-results"></a>

Using the same `get_counts` functions as before, we can compute the counts:

```
counts_aquila = get_counts(result_aquila)
   print(counts_aquila)
```

```
*[Output]*
{'dddududd': 2, 'dudududu': 18, 'ddududud': 4, ...}
```

and plot them with `plot_counts`:

```
plot_counts(counts_aquila)
```

![\[Bar chart showing a large number of shots with no neighboring "up" states configurations.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/QPUPlotCounts1.png)


![\[Bar chart showing shots of some neighboring "up" states configurations, with 4 states at 1.0 shots.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/QPUPlotCounts2.png)


Note that a small fraction of shots have empty sites (marked with “e”). This is due to a 1—2% per atom preparation imperfections of the Aquila QPU. Apart from this, the results match with the simulation within the expected statistical fluctuation due to small number of shots.

## Next steps
<a name="braket-get-started-ahs-next"></a>

Congratulations, you have now run your first AHS workload on Amazon Braket using the local AHS simulator and the Aquila QPU.

To learn more about Rydberg physics, Analog Hamiltonian Simulation and the Aquila device, refer to our [example notebooks](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation).

# Submit an analog program using QuEra Aquila
<a name="braket-quera-submitting-analog-program-aquila"></a>

This page provides a comprehensive documentation about the capabilities of the Aquila machine from QuEra. Details covered here are the following: 

1. The parameterized Hamiltonian simulated by Aquila

1. AHS program parameters

1. AHS result content

1. Aquila capabilities parameter

**Topics**
+ [Hamiltonian](#braket-quera-aquila-device-hamiltonian)
+ [Braket AHS program schema](#braket-quera-ahs-program-schema)
+ [Braket AHS task result schema](#braket-quera-ahs-task-result-schema)
+ [QuEra device properties schema](#braket-quera-device-properties-schema)

## Hamiltonian
<a name="braket-quera-aquila-device-hamiltonian"></a>

The Aquila machine from QuEra simulates the following (time-dependent) Hamiltonian natively:

![\[Mathematical equation with summations representing the Hamiltonian of a system, involving drive, local detuning, and interdot coupling terms.\]](http://docs.aws.amazon.com/braket/latest/developerguide/images/TimeDependentDrivingHamiltonian.png)


**Note**  
Access to local detuning is an [Experimental capability](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html) and is available by request through Braket Direct.

where
+ Hdrive,k​(t)=( 1/2 ​Ω(t)eiϕ(t)S−,k​ \$1 1/2 ​Ω(t)e−iϕ(t) S\$1,k​) \$1 (−Δglobal​(t)nk​),
  + Ω(t) is the time-dependent, global driving amplitude (aka Rabi frequency), in units of (rad / s)
  + ϕ(t) is the time-dependent, global phase, measured in radians
  + S−,k​ and S\$1,k​ are the spin lowering and raising operators of atom k (in the basis \$1↓⟩=\$1g⟩, \$1↑⟩=\$1r⟩, they are S−​=\$1g⟩⟨r\$1, S\$1​=(S−​)†=\$1r⟩⟨g\$1)
  + Δglobal​(t) is the time-dependent, global detuning
  + nk ​is the projection operator on the Rydberg state of atom k (that is, n=\$1r⟩⟨r\$1)
+ Hlocal detuning,k(t)=-Δlocal(t)hknk
  + Δlocal(t) is the time-dependent factor of the local frequency shift, in units of (rad / s)
  + hk is the site-dependent factor, a dimensionless number between 0.0 and 1.0
+ Vvdw,k,l​=C6​/(dk,l​)6nk​nl​,
  + C6​ is the van der Waals coefficient, in units of (rad / s) \$1 (m)^6
  + dk,l ​is the Euclidean distance between atom k and l, measured in meters.

Users have control over the following parameters through the Braket AHS program schema.
+ 2-d atom arrangement (xk​ and yk​ coordinates of each atom k, in units of um), which controls the pairwise atomic distances dk,l​ with k,l=1,2,…N
+ Ω(t), the time-dependent, global Rabi frequency, in units of (rad / s)
+ ϕ(t), the time-dependent, global phase, in units of (rad)
+ Δglobal​(t), the time-dependent, global detuning, in units of (rad / s)
+ Δlocal(t), the time-dependent (global) factor of the magnitude of local detuning, in units of (rad / s)
+ hk, the (static) site-dependent factor of the magnitude of local detuning, a dimensionless number between 0.0 and 1.0

**Note**  
The user cannot control which levels are involved (that is, S−​,S\$1​, n operators are fixed) nor the strength of the Rydberg-Rydberg interaction coefficient (C6​).

## Braket AHS program schema
<a name="braket-quera-ahs-program-schema"></a>

 **braket.ir.ahs.program\$1v1.Program object** (example)

**Note**  
If the [local detuning](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) feature is not enabled for your account, use `localDetuning=[]` in the following example.

```
Program(
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.ir.ahs.program',
        version='1'
    ),
    setup=Setup(
        ahs_register=AtomArrangement(
            sites=[
                [Decimal('0'), Decimal('0')],
                [Decimal('0'), Decimal('4e-6')],
                [Decimal('4e-6'), Decimal('0')]
            ],
            filling=[1, 1, 1]
        )
    ),
    hamiltonian=Hamiltonian(
        drivingFields=[
            DrivingField(
                amplitude=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('15700000.0'), Decimal('15700000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                phase=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                ),
                detuning=PhysicalField(
                    time_series=TimeSeries(
                        values=[Decimal('-54000000.0'), Decimal('54000000.0')],
                        times=[Decimal('0'), Decimal('0.000003')]
                    ),
                    pattern='uniform'
                )
            )
        ],
        localDetuning=[
            LocalDetuning(
                magnitude=PhysicalField(
                    times_series=TimeSeries(
                        values=[Decimal('0'), Decimal('25000000.0'), Decimal('25000000.0'), Decimal('0')],
                        times=[Decimal('0'), Decimal('0.000001'), Decimal('0.000002'), Decimal('0.000003')]
                    ),
                    pattern=Pattern([Decimal('0.8'), Decimal('1.0'), Decimal('0.9')])
                )
            )
        ]
    )
)
```

**JSON** (example)

**Note**  
If the [local detuning](https://docs.aws.amazon.com/braket/latest/developerguide/braket-experimental-capabilities.html#braket-access-local-detuning) feature is not enabled for your account, use `"localDetuning": []` in the following example.

```
{
    "braketSchemaHeader": {
        "name": "braket.ir.ahs.program",
        "version": "1"
    },
    "setup": {
        "ahs_register": {
            "sites": [
                [0E-7, 0E-7], 
                [0E-7, 4E-6],
                [4E-6, 0E-7]
            ],
            "filling": [1, 1, 1]
        }
    },
    "hamiltonian": {
        "drivingFields": [
            {
                "amplitude": {
                    "time_series": {
                        "values": [0.0, 15700000.0, 15700000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "phase": {
                    "time_series": {
                        "values": [0E-7, 0E-7],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                },
                "detuning": {
                    "time_series": {
                        "values": [-54000000.0, 54000000.0],
                        "times": [0E-9, 0.000003000]
                    },
                    "pattern": "uniform"
                }
            }
        ],
        "localDetuning": [
            {
                "magnitude": {
                    "time_series": {
                        "values": [0.0, 25000000.0, 25000000.0, 0.0],
                        "times": [0E-9, 0.000001000, 0.000002000, 0.000003000]
                    },
                    "pattern": [0.8, 1.0, 0.9]
                }
            }
        ]
    }
}
```


**Main fields**  

| Program field | type | description | 
| --- | --- | --- | 
|  setup.ahs\$1register.sites  |  List[List[Decimal]]  |  List of 2-d coordinates where the tweezers trap atoms  | 
|  setup.ahs\$1register.filling  |  List[int]  |  Marks atoms that occupy the trap sites with 1, and empty sites with 0  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.times  |  List[Decimal]  |  time points of driving amplitude, Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.time\$1series.values  |  List[Decimal]  |  values of driving amplitude, Omega(t)  | 
|  hamiltonian.drivingFields[].amplitude.pattern  |  str  |  spatial pattern of driving amplitude, Omega(t); must be 'uniform'  | 
|  hamiltonian.drivingFields[].phase.time\$1series.times  |  List[Decimal]  |  time points of driving phase, phi(t)  | 
|  hamiltonian.drivingFields[].phase.time\$1series.values  |  List[Decimal]  |  values of driving phase, phi(t)  | 
|  hamiltonian.drivingFields[].phase.pattern  |  str  |  spatial pattern of driving phase, phi(t); must be 'uniform'  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.times  |  List[Decimal]  |  time points of driving detuning, Delta\$1global(t)  | 
|  hamiltonian.drivingFields[].detuning.time\$1series.values  |  List[Decimal]  |  values of driving detuning, Delta\$1global(t)  | 
|  hamiltonian.drivingFields[].detuning.pattern  |  str  |  spatial pattern of driving detuning, Delta\$1global(t); must be 'uniform'  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.times  |  List[Decimal]  |  time points of the time-dependent factor of the local detuning magnitude, Delta\$1local(t)  | 
|  hamiltonian.localDetuning[].magnitude.time\$1series.values  |  List[Decimal]  |  values of the time-dependent factor of the local detuning magnitude, Delta\$1local(t)  | 
|  hamiltonian.localDetuning[].magnitude.pattern  |  List[Decimal]  |  site-dependent factor of the local detuning magnitude, h\$1k (values corresponds to sites in setup.ahs\$1register.sites)  | 


**Metadata fields**  

| Program field | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  name of the schema; must be 'braket.ir.ahs.program'  | 
|  braketSchemaHeader.version  |  str  |  version of the schema  | 

## Braket AHS task result schema
<a name="braket-quera-ahs-task-result-schema"></a>

 **braket.tasks.analog\$1hamiltonian\$1simulation\$1quantum\$1task\$1result.AnalogHamiltonianSimulationQuantumTaskResult** (example)

```
AnalogHamiltonianSimulationQuantumTaskResult(
    task_metadata=TaskMetadata(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.task_result.task_metadata',
            version='1'
        ),
        id='arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef',
        shots=2,
        deviceId='arn:aws:braket:us-east-1::device/qpu/quera/Aquila',
        deviceParameters=None,
        createdAt='2022-10-25T20:59:10.788Z',
        endedAt='2022-10-25T21:00:58.218Z',
        status='COMPLETED',
        failureReason=None
    ),
    measurements=[
        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 1, 1]),
            post_sequence=array([0, 1, 1, 1])
        ),

        ShotResult(
            status=<AnalogHamiltonianSimulationShotStatus.SUCCESS: 'Success'>,

            pre_sequence=array([1, 1, 0, 1]),
            post_sequence=array([1, 0, 0, 0])
        )
    ]
)
```

 **JSON** (example)

```
{
    "braketSchemaHeader": {
        "name": "braket.task_result.analog_hamiltonian_simulation_task_result",
        "version": "1"
    },
    "taskMetadata": {
        "braketSchemaHeader": {
            "name": "braket.task_result.task_metadata",
            "version": "1"
        },
        "id": "arn:aws:braket:us-east-1:123456789012:quantum-task/12345678-90ab-cdef-1234-567890abcdef",
        "shots": 2,
        "deviceId": "arn:aws:braket:us-east-1::device/qpu/quera/Aquila",

        "createdAt": "2022-10-25T20:59:10.788Z",
        "endedAt": "2022-10-25T21:00:58.218Z",
        "status": "COMPLETED"

    },
    "measurements": [
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 1, 1],
                "postSequence": [0, 1, 1, 1]
            }
        },
        {
            "shotMetadata": {"shotStatus": "Success"},
            "shotResult": {
                "preSequence": [1, 1, 0, 1],
                "postSequence": [1, 0, 0, 0]
            }
        }
    ],
    "additionalMetadata": {
        "action": {...}
        "queraMetadata": {
            "braketSchemaHeader": {
                "name": "braket.task_result.quera_metadata",
                "version": "1"
            },
            "numSuccessfulShots": 100
        }
    }
}
```


**Main fields**  

| Task result field | type | description | 
| --- | --- | --- | 
|  measurements[].shotResult.preSequence  |  List[int]  |  Pre-sequence measurement bits (one for each atomic site) for each shot: 0 if site is empty, 1 if site is filled, measured before the sequences of pulses that run the quantum evolution  | 
|  measurements[].shotResult.postSequence  |  List[int]  |  Post-sequence measurement bits for each shot: 0 if atom is in Rydberg state or site is empty, 1 if atom is in ground state, measured at the end of the sequences of pulses that run the quantum evolution  | 


**Metadata fields**  

| Task result field | type | description | 
| --- | --- | --- | 
|  braketSchemaHeader.name  |  str  |  name of the schema; must be 'braket.task\$1result.analog\$1hamiltonian\$1simulation\$1task\$1result'  | 
|  braketSchemaHeader.version  |  str  |  version of the schema  | 
|  taskMetadata.braketSchemaHeader.name  |  str  |  name of the schema; must be ‘braket.task\$1result.task\$1metadata'  | 
|  taskMetadata.braketSchemaHeader.version  |  str  |  version of the schema  | 
|  taskMetadata.id  |  str  |  The ID of the quantum task. For AWS quantum tasks, this is the quantum task ARN.  | 
|  taskMetadata.shots  |  int  |  The number of shots for the quantum task  | 
|  taskMetadata.shots.deviceId  |  str  |  The ID of the device on which the quantum task ran. For AWS devices, this is the device ARN.  | 
|  taskMetadata.shots.createdAt  |  str  |  The timestamp of creation; the format must be in ISO-8601/RFC3339 string format YYYY-MM-DDTHH:mm:ss.sssZ. Default is None.  | 
|  taskMetadata.shots.endedAt  |  str  |  The timestamp of when the quantum task ended; the format must be in ISO-8601/RFC3339 string format YYYY-MM-DDTHH:mm:ss.sssZ. Default is None.  | 
|  taskMetadata.shots.status  |  str  |  The status of the quantum task (CREATED, QUEUED, RUNNING, COMPLETED, FAILED). Default is None.  | 
|  taskMetadata.shots.failureReason  |  str  |  The failure reason of the quantum task. Default is None.  | 
|  additionalMetadata.action  |  braket.ir.ahs.program\$1v1.Program  |  (See the [Braket AHS program schema](#braket-quera-ahs-program-schema) section)  | 
|  additionalMetadata.action.braketSchemaHeader.queraMetadata.name  |  str  |  name of the schema; must be 'braket.task\$1result.quera\$1metadata'  | 
|  additionalMetadata.action.braketSchemaHeader.queraMetadata.version  |  str  |  version of the schema  | 
|  additionalMetadata.action.numSuccessfulShots  |  int  |  number of completely successful shots; must be equal to the requested number of shots  | 
|  measurements[].shotMetadata.shotStatus  |  int  |  The status of the shot, (Success, Partial success, Failure); must be "Success"  | 

## QuEra device properties schema
<a name="braket-quera-device-properties-schema"></a>

 **braket.device\$1schema.quera.quera\$1device\$1capabilities\$1v1.QueraDeviceCapabilities** (example)

```
QueraDeviceCapabilities(
    service=DeviceServiceProperties(
        braketSchemaHeader=BraketSchemaHeader(
            name='braket.device_schema.device_service_properties', 
            version='1'
            ), 
            executionWindows=[
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.MONDAY: 'Monday'>, 
                    windowStartHour=datetime.time(1, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.TUESDAY: 'Tuesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.WEDNESDAY: 'Wednesday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.FRIDAY: 'Friday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SATURDAY: 'Saturday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(23, 59, 59)
                ), 
                DeviceExecutionWindow(
                    executionDay=<ExecutionDay.SUNDAY: 'Sunday'>, 
                    windowStartHour=datetime.time(0, 0), 
                    windowEndHour=datetime.time(12, 0)
                )
            ], 
            shotsRange=(1, 1000), 
            deviceCost=DeviceCost(
                price=0.01, 
                unit='shot'
            ), 
            deviceDocumentation=
                DeviceDocumentation(
                    imageUrl='https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png', 
                    summary='Analog quantum processor based on neutral atom arrays', 
                    externalDocumentationUrl='https://www.quera.com/aquila'
                ), 
                deviceLocation='Boston, USA', 
                updatedAt=datetime.datetime(2024, 1, 22, 12, 0, tzinfo=datetime.timezone.utc), 
                getTaskPollIntervalMillis=None
    ), 
    action={
        <DeviceActionType.AHS: 'braket.ir.ahs.program'>: DeviceActionProperties(
                version=['1'], 
                actionType=<DeviceActionType.AHS: 'braket.ir.ahs.program'>
            )
    }, 
    deviceParameters={}, 
    braketSchemaHeader=BraketSchemaHeader(
        name='braket.device_schema.quera.quera_device_capabilities', 
        version='1'
    ), 
    paradigm=QueraAhsParadigmProperties(
        ...
        # See https://github.com/amazon-braket/amazon-braket-schemas-python/blob/main/src/braket/device_schema/quera/quera_ahs_paradigm_properties_v1.py
        ...
    )  
)
```

 **JSON** (example)

```
{
    "service": {
        "braketSchemaHeader": {
            "name": "braket.device_schema.device_service_properties",
            "version": "1"
        },
        "executionWindows": [
            {
                "executionDay": "Monday",
                "windowStartHour": "01:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Tuesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Wednesday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            },
            {
                "executionDay": "Friday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Saturday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "23:59:59"
            },
            {
                "executionDay": "Sunday",
                "windowStartHour": "00:00:00",
                "windowEndHour": "12:00:00"
            }
        ],
        "shotsRange": [
            1,
            1000
        ],
        "deviceCost": {
            "price": 0.01,
            "unit": "shot"
        },
        "deviceDocumentation": {
            "imageUrl": "https://a.b.cdn.console.awsstatic.com/59534b58c709fc239521ef866db9ea3f1aba73ad3ebcf60c23914ad8c5c5c878/a6cfc6fca26cf1c2e1c6.png",
            "summary": "Analog quantum processor based on neutral atom arrays",
            "externalDocumentationUrl": "https://www.quera.com/aquila"
        },
        "deviceLocation": "Boston, USA",
        "updatedAt": "2024-01-22T12:00:00+00:00"
    },
    "action": {
        "braket.ir.ahs.program": {
            "version": [
                "1"
            ],
            "actionType": "braket.ir.ahs.program"
        }
    },
    "deviceParameters": {},
    "braketSchemaHeader": {
        "name": "braket.device_schema.quera.quera_device_capabilities",
        "version": "1"
    },
    "paradigm": {
        ...
        # See Aquila device page > "Calibration" tab > "JSON" page
        ...
    }
}
```


**Service properties fields**  

| Service properties field | type | description | 
| --- | --- | --- | 
|  service.executionWindows[].executionDay  |  ExecutionDay  |  Days of the execution window; must be 'Everyday', 'Weekdays', 'Weekend', 'Monday', 'Tuesday', 'Wednesday', Thursday', 'Friday', 'Saturday' or 'Sunday'  | 
|  service.executionWindows[].windowStartHour  |  datetime.time  |  UTC 24-hour format of the time when the execution window starts  | 
|  service.executionWindows[].windowEndHour  |  datetime.time  |  UTC 24-hour format of the time when the execution window ends  | 
|  service.qpu\$1capabilities.service.shotsRange  |  Tuple[int, int]  |  Minimum and maximum number of shots for the device  | 
|  service.qpu\$1capabilities.service.deviceCost.price  |  float  |  Price of the device in terms of US dollars  | 
|  service.qpu\$1capabilities.service.deviceCost.unit  |  str  |  unit for charging the price, e.g: 'minute', 'hour', 'shot', 'task'  | 


**Metadata fields**  

| Metadata field | type | description | 
| --- | --- | --- | 
|  action[].version  |  str  |  version of the AHS program schema  | 
|  action[].actionType  |  ActionType  |  AHS program schema name; must be 'braket.ir.ahs.program'  | 
|  service.braketSchemaHeader.name  |  str  |  name of the schema; must be 'braket.device\$1schema.device\$1service\$1properties'  | 
|  service.braketSchemaHeader.version  |  str  |  version of the schema  | 
|  service.deviceDocumentation.imageUrl  |  str  |  URL for the image of the device  | 
|  service.deviceDocumentation.summary  |  str  |  brief description on the device  | 
|  service.deviceDocumentation.externalDocumentationUrl  |  str  |  external documentation URL  | 
|  service.deviceLocation  |  str  |  geographic location fo the device  | 
|  service.updatedAt  |  datetime  |  time when the device properties were last updated  | 