

Die vorliegende Übersetzung wurde maschinell erstellt. Im Falle eines Konflikts oder eines Widerspruchs zwischen dieser übersetzten Fassung und der englischen Fassung (einschließlich infolge von Verzögerungen bei der Übersetzung) ist die englische Fassung maßgeblich.

# Hallo AHS: Führe deine erste analoge Hamilton-Simulation aus
<a name="braket-get-started-hello-ahs"></a>

Dieser Abschnitt enthält Informationen zur Ausführung Ihrer ersten analogen Hamiltonschen Simulation.

**Topics**
+ [Interagierende Spin-Kette](#braket-get-started-interacting-spin-chain)
+ [Anordnung](#braket-get-started-arrangement)
+ [Interaktionen](#braket-get-started-interaction)
+ [Fahrfeld](#braket-get-started-driving-field)
+ [AHS-Programm](#braket-get-started-ahs-program)
+ [Läuft auf einem lokalen Simulator](#braket-get-started-running-local-simulator)
+ [Analysieren der Simulatorergebnisse](#braket-get-started-analyzing-simulator-results)
+ [Läuft auf der Aquila QuEra QPU](#braket-get-started-running-aquila-qpu)
+ [QPU-Ergebnisse analysieren](#braket-get-started-analyzing-qpu-results)
+ [Nächste Schritte](#braket-get-started-ahs-next)

## Interagierende Spin-Kette
<a name="braket-get-started-interacting-spin-chain"></a>

Als kanonisches Beispiel für ein System aus vielen wechselwirkenden Teilchen betrachten wir einen Ring aus acht Spins (von denen sich jeder in den Zuständen „oben“ ↑ und „unten“ ↓⟩ befinden kann). Dieses Modellsystem ist zwar klein, weist aber bereits eine Handvoll interessanter Phänomene natürlich vorkommender magnetischer Materialien auf. In diesem Beispiel werden wir zeigen, wie man eine sogenannte antiferromagnetische Ordnung erzeugt, bei der aufeinanderfolgende Spins in entgegengesetzte Richtungen zeigen.

![Diagramm, das 8 Kreisknoten verbindet, die invertierte Aufwärts- und Abwärtspfeile enthalten.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/AntiFerromagnetic.png)


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

Wir verwenden ein neutrales Atom, das für jeden Spin steht, und die Spinzustände „hoch“ und „runter“ werden jeweils im angeregten Rydberg-Zustand und im Grundzustand der Atome kodiert. Zuerst erstellen wir die 2-D-Anordnung. Wir können den obigen Ring von Spins mit dem folgenden Code programmieren.

 **Voraussetzungen**: Sie müssen das [Braket](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk) SDK per Pip installieren. (Wenn Sie eine von Braket gehostete Notebook-Instanz verwenden, ist dieses SDK zusammen mit den Notebooks vorinstalliert.) Um die Plots zu reproduzieren, müssen Sie matplotlib auch separat mit dem Shell-Befehl installieren. `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)
```

womit wir auch plotten können

```
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
```

![Streudiagramm, das Punkte zeigt, die über positive und negative Werte auf beiden Achsen verteilt sind.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/PlotNeutralAtoms.png)


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

Um die antiferromagnetische Phase vorzubereiten, müssen wir Wechselwirkungen zwischen benachbarten Spins induzieren. Wir nutzen dafür die [Van-der-Waals-Wechselwirkung](https://en.wikipedia.org/wiki/Van_der_Waals_force), die nativ von neutralen Atomgeräten (wie dem Gerät von) implementiert wird. Aquila QuEra Mit Hilfe der Spin-Repräsentation kann der Hamiltonsche Term für diese Wechselwirkung als Summe über alle Spinpaare (j, k) ausgedrückt werden.

![Die Hamiltonsche Wechselwirkungsgleichung zeigt, dass diese Wechselwirkung als Summe aller Spinpaare (j, k) ausgedrückt wird.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/HInteraction.png)


In diesem Fall ist nj=↑ bung↑ j ein j Operator, der den Wert 1 nur annimmt, wenn sich Spin j im Zustand „up“ befindet, andernfalls 0. Die Stärke ist V j,k =C6/(dj,k​) 6, wobei C 6 der feste Koeffizient und d der euklidische Abstand zwischen den Spins j und k j,k ist. Der unmittelbare Effekt dieses Wechselwirkungsterms besteht darin, dass jeder Zustand, in dem sowohl Spin j als auch Spin k „oben“ sind, eine erhöhte Energie (um den Betrag V) aufweist. j,k Durch die sorgfältige Gestaltung des restlichen AHS-Programms wird durch diese Wechselwirkung verhindert, dass sich benachbarte Spins beide im „Up-Zustand“ befinden — ein Effekt, der allgemein als „Rydberg-Blockade“ bekannt ist.

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

Zu Beginn des AHS-Programms beginnen alle Spins (standardmäßig) in ihrem „down“ -Zustand, sie befinden sich in einer sogenannten ferromagnetischen Phase. Mit Blick auf unser Ziel, die antiferromagnetische Phase vorzubereiten, spezifizieren wir ein zeitabhängiges kohärentes Antriebsfeld, das die Spins sanft von diesem Zustand in einen Vielteilchenzustand überführt, in dem der Zustand „oben“ bevorzugt wird. Der entsprechende Hamilton-Operator kann geschrieben werden als

![Mathematische Gleichung, die die Berechnung einer Hamiltonschen Antriebsfunktion darstellt.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/HDrive.png)


wobei Ω (t), φ (t), δ (t) die zeitabhängige globale Amplitude (auch bekannt als [Rabi-Frequenz](https://en.wikipedia.org/wiki/Rabi_frequency)), Phase und Verstimmung des treibenden Feldes sind, die alle Spins gleichmäßig beeinflussen. Hier sind S −,k =↓ k​ bung↑ k und S \+,k =( S−,k) † =↑ k​ Chesinik↓ k die senkenden bzw. anhebenden Operatoren von Spin k, und n k =↑ k ↑ ←↑ k ist derselbe Operator wie zuvor. Der Ω Teil des Antriebsfeldes verbindet kohärent die Zustände „nach unten“ und „nach oben“ aller Spins gleichzeitig, während der Δ-Teil die Energiebelohnung für den Zustand „hoch“ steuert.

Um einen reibungslosen Übergang von der ferromagnetischen Phase zur antiferromagnetischen Phase zu programmieren, spezifizieren wir das treibende Feld mit dem folgenden 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
)
```

Wir können die Zeitreihen des Fahrfeldes mit dem folgenden Skript visualisieren.

```
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
```

![Drei Grafiken, die Phi, Delta und Omega im Zeitverlauf zeigen. Das obere Teildiagramm zeigt das Wachstum auf knapp über 6, rads/s wo es 4 Sekunden lang anhält, bis es wieder auf 0 fällt. Das mittlere Teildiagramm zeigt das damit verbundene lineare Wachstum der Ableitung, und das untere Teildiagramm zeigt eine flache Linie nahe Null.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/DrivingTimeSeries.png)


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

Das Register, das treibende Feld (und die impliziten Van-der-Waals-Interaktionen) bilden das Programm Analoge Hamiltonsche Simulation. `ahs_program`

```
from braket.ahs.analog_hamiltonian_simulation import AnalogHamiltonianSimulation

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

## Läuft auf einem lokalen Simulator
<a name="braket-get-started-running-local-simulator"></a>

Da dieses Beispiel klein ist (weniger als 15 Spins), können wir es vor der Ausführung auf einer AHS-compatible QPU auf dem lokalen AHS-Simulator ausführen, der mit dem Braket-SDK geliefert wird. Da der lokale Simulator mit dem Braket-SDK kostenlos verfügbar ist, ist dies die bewährte Methode, um sicherzustellen, dass unser Code korrekt ausgeführt werden kann.

Hier können wir die Anzahl der Aufnahmen auf einen hohen Wert setzen (z. B. 1 Million), weil der lokale Simulator die zeitliche Entwicklung des Quantenzustands verfolgt und Proben aus dem Endzustand zieht. Dadurch wird die Anzahl der Aufnahmen erhöht, während die Gesamtlaufzeit nur geringfügig erhöht wird.

```
from braket.devices import LocalSimulator

device = LocalSimulator("braket_ahs")

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

## Analysieren der Simulatorergebnisse
<a name="braket-get-started-analyzing-simulator-results"></a>

Wir können die Schussergebnisse mit der folgenden Funktion aggregieren, die den Status jedes Spins ableitet (der „d“ für „runter“, „u“ für „oben“ oder „e“ für leere Stelle sein kann) und zählt, wie oft jede Konfiguration in den Schüssen aufgetreten ist.

```
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, ...}
```

Hier `counts` ist ein Wörterbuch, das zählt, wie oft jede Zustandskonfiguration in den einzelnen Schüssen beobachtet wurde. Wir können sie auch mit dem folgenden Code visualisieren.

```
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)
```

![Balkendiagramm, das eine große Anzahl von Aufnahmen ohne benachbarte „Up-State-Konfigurationen“ zeigt.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/AHSCounts1.png)


![Balkendiagramm mit Aufnahmen einiger benachbarter Konfigurationen mit „Up-Status“, mit 4 Zuständen bei 1,0 Aufnahmen.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/AHSCounts2.png)


Aus den Diagrammen können wir die folgenden Beobachtungen ablesen, die belegen, dass wir die antiferromagnetische Phase erfolgreich vorbereitet haben.

1. Im Allgemeinen sind nicht blockierte Zustände (in denen sich keine zwei benachbarten Spins im „Up“ -Zustand befinden) häufiger als Zustände, in denen sich mindestens ein Paar benachbarter Spins beide im „Up“ -Zustand befinden.

1. Im Allgemeinen werden Zustände mit mehr Erregungen nach oben bevorzugt, es sei denn, die Konfiguration ist blockiert.

1. Die häufigsten Zustände sind in der Tat die perfekten antiferromagnetischen Zustände und. `"dudududu"` `"udududud"`

1. Die zweithäufigsten Zustände sind diejenigen, bei denen es nur 3 „nach oben“ gerichtete Erregungen mit aufeinanderfolgenden Abständen von 1, 2, 2 gibt. Dies zeigt, dass sich die Van-der-Waals-Wechselwirkung auch auf die nächsten Nachbarn auswirkt (wenn auch viel geringer).

## Läuft auf der Aquila QuEra QPU
<a name="braket-get-started-running-aquila-qpu"></a>

 **Voraussetzungen**[: Wenn Sie neu bei Amazon Braket sind, stellen Sie neben der Pip-Installation des [Braket-SDK](https://github.com/aws/amazon-braket-sdk-python#installing-the-amazon-braket-python-sdk) sicher, dass Sie die erforderlichen Schritte für den Einstieg abgeschlossen haben.](https://docs.aws.amazon.com/braket/latest/developerguide/braket-get-started.html)

**Anmerkung**  
Wenn Sie eine von Braket gehostete Notebook-Instance verwenden, ist das Braket-SDK zusammen mit der Instance vorinstalliert.

Wenn alle Abhängigkeiten installiert sind, können wir eine Verbindung zur QPU herstellen. Aquila

```
from braket.aws import AwsDevice

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

Damit unser AHS-Programm für die QuEra Maschine geeignet ist, müssen wir alle Werte runden, um die von der Aquila QPU zulässige Genauigkeit einzuhalten. (Diese Anforderungen werden durch die Geräteparameter bestimmt, deren Name „Auflösung“ enthält. Wir können sie sehen, indem wir sie `aquila_qpu.properties.dict()` in einem Notizbuch ausführen. Weitere Informationen zu den Funktionen und Anforderungen von Aquila finden Sie in der [Einführung in das Aquila-Notizbuch](https://github.com/aws/amazon-braket-examples/blob/main/examples/analog_hamiltonian_simulation/01_Introduction_to_Aquila.ipynb).) Wir können das tun, indem wir die `discretize` Methode aufrufen.

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

Jetzt können wir das Programm (es laufen vorerst nur 100 Schüsse) auf der Aquila QPU ausführen.

**Anmerkung**  
Das Ausführen dieses Programms auf dem Aquila Prozessor ist mit Kosten verbunden. Das Amazon Braket SDK enthält einen [Cost Tracker](https://aws.amazon.com/blogs/quantum-computing/managing-the-cost-of-your-experiments-in-amazon-braket/), mit dem Kunden Kostenlimits festlegen und ihre Kosten nahezu in Echtzeit verfolgen können.

```
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
```

Aufgrund der großen Varianz, wie lange die Ausführung einer Quantenaufgabe dauern kann (abhängig von Verfügbarkeitsfenstern und QPU-Auslastung), ist es eine gute Idee, den ARN der Quantenaufgabe zu notieren, damit wir ihren Status zu einem späteren Zeitpunkt mit dem folgenden Codeausschnitt überprüfen können.

```
# 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
```

Sobald der Status ABGESCHLOSSEN ist (was auch auf der Quantenaufgaben-Seite der Amazon [Braket-Konsole](https://us-east-1.console.aws.amazon.com/braket/home?region=us-east-1#/tasks) überprüft werden kann), können wir die Ergebnisse abfragen mit:

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

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

Mit den gleichen `get_counts` Funktionen wie zuvor können wir die Zählungen berechnen:

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

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

und plotten Sie sie mit`plot_counts`:

```
plot_counts(counts_aquila)
```

![Balkendiagramm, das eine große Anzahl von Aufnahmen ohne benachbarte „Up-Status“ -Konfigurationen zeigt.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/QPUPlotCounts1.png)


![Balkendiagramm mit Aufnahmen einiger benachbarter Konfigurationen mit „Up-Status“, mit 4 Zuständen bei 1,0 Aufnahmen.](http://docs.aws.amazon.com/de_de/braket/latest/developerguide/images/QPUPlotCounts2.png)


Beachten Sie, dass ein kleiner Teil der Aufnahmen leere Bereiche hat (mit „e“ gekennzeichnet). Dies ist auf eine Unvollkommenheit der QPU bei der Präparation pro Atom von 1— 2% zurückzuführen. Aquila Abgesehen davon stimmen die Ergebnisse innerhalb der erwarteten statistischen Fluktuation aufgrund der geringen Anzahl von Schüssen mit der Simulation überein.

## Nächste Schritte
<a name="braket-get-started-ahs-next"></a>

Herzlichen Glückwunsch, Sie haben jetzt Ihren ersten AHS-Workload auf Amazon Braket mit dem lokalen AHS-Simulator und der Aquila QPU ausgeführt.

[Weitere Informationen zur Rydberg-Physik, zur analogen Hamiltonschen Simulation und zum Aquila Gerät finden Sie in unseren Beispiel-Notebooks.](https://github.com/aws/amazon-braket-examples/tree/main/examples/analog_hamiltonian_simulation)