So programmieren Sie einen Quantencomputer - Teil 2

Schlachtschiffe mit Quantenmessungen

IBM Research https://www.flickr.com/photos/ibm_research_zurich/33072160062/

Dieser Artikel hat aus gutem Grund 'Teil 2' im Titel. Es gab einen Teil 1, in dem wir uns mit den Grundlagen des Schreibens und Ausführens von Quantenprogrammen befassten.

Ich gehe davon aus, dass Sie mindestens die erste Hälfte davon gelesen haben, bevor Sie hierher kommen.

Das meiste Programmierwissen, das Sie für dieses Tutorial benötigen, wurde beim letzten Mal behandelt. Dieser Artikel konzentriert sich hauptsächlich auf einige Dinge, die wir mit diesen Befehlen tun können.

Wie man Qubits betrachtet

In Programmen haben wir Variablen. Irgendwann müssen wir sie uns ansehen.

Dies könnte am Ende des Programms sein, wenn wir das Ergebnis erhalten. Dies kann auch während des Programms geschehen, wenn wir die Variable als Teil einer bedingten Anweisung verwenden. In jedem Fall passiert viel. Und wenn Nicht-Quantenvariablen programmiert werden, ist dies ein ziemlich unauffälliger Prozess.

Dies liegt daran, dass Nicht-Quantenvariablen bestimmte Werte haben. Ein Blick auf sie sagt uns oder anderen Teilen des Programms nur, was der Wert ist. An der Variablen selbst ändert sich nichts.

Dies gilt nicht für Quantenvariablen, die unbestimmte Werte haben können. Sie können sich in einer sogenannten Quantenüberlagerung befinden, die es ihnen ermöglicht, mehrere widersprüchliche Werte gleichzeitig zu halten.

Wenn wir sie betrachten, müssen sie all diese Fremdheit aufgeben. Sie sind gezwungen, einen bestimmten Wert anzunehmen und uns dann zu sagen, was dieser Wert ist. Da dies nicht nur ein passiver Prozess ist, muss er sorgfältig abgewogen werden. Und es braucht einen Namen. Wir nennen es Messung.

In diesem Artikel werden wir einige Eigenschaften der Messung untersuchen. Wir werden es auch als Grundlage für eine Spielmechanik verwenden und genau sehen, wie man es auf einem Quantencomputer programmiert. Am Ende werden wir eine neue Version von Schlachtschiffen haben.

Abbildung der Welt eines Qubits

Bevor wir wirklich anfangen, Qubits zu messen, sollten wir versuchen, ihre Welt ein wenig besser zu verstehen. Der beste Weg, ein Qubit zu visualisieren, ist die Verwendung einer Kugel. Jeder mögliche Qubit-Zustand entspricht einem Punkt auf der Oberfläche dieser Kugel.

Die Zustände 0 und 1 sind völlig unterschiedlich, völlig unzusammenhängend. Sie sind die Gegensätze voneinander. Sie werden daher auf gegenüberliegenden Seiten der Kugel leben. Wir setzen normalerweise 0 am Nordpol und 1 am Süden.

Lassen Sie uns einen Punkt auswählen, der irgendwo entlang des Äquators gleich weit voneinander entfernt ist. Es kann überall sein, wo Sie möchten. Wir nennen es +. Warum +? Warum nicht?

Der + Zustand hat auch ein Gegenteil, so unterschiedlich wie 0 von 1. Dies lebt auf der gegenüberliegenden Seite, die auch ein Punkt entlang des Äquators sein wird. Wir werden diesen Zustand nennen -.

Mit den jetzt definierten Punkten 0, 1, + und - bitten einige weitere Punkte um unsere Aufmerksamkeit. Dies sind diejenigen, die zwischen 0 und 1 äquidistant und zwischen + und - äquidistant sind. Wir werden diese ↻ und ↺ nennen. Warum? Weil ich einmal einen Typen gesehen habe, der den Da Vinci Code nicht geschrieben hat, und es hat mir gefallen.

Wir haben jetzt die Welt des Qubits mit sechs Punkten abgebildet. Dies sind keineswegs die einzigen, die wir jemals verwenden werden. Sie sind einfach die Orientierungspunkte, an denen wir navigieren werden.

Ein Qubit messen

Bei jeder Messung bitten wir einfach ein Qubit, zwischen zwei entgegengesetzten Punkten auf der Kugel zu wählen.

Das klassische Beispiel ist für unser Lieblingspaar entgegengesetzter Zustände: 0 und 1. Wir bitten das Qubit, zwischen den beiden zu wählen. Wenn es sich bereits im Zustand 0 befand, wird es auf 0 gesetzt. Ein Qubit in Zustand 1 ergibt in ähnlicher Weise das Ergebnis 1. Für jeden anderen Zustand ist das Ergebnis zufällig, wobei die nächstgelegene Option die wahrscheinlichste ist.

Am Äquator ist es eine 50/50-Chance. Wenn also unser Zustand + oder - war und wir dann fragen, ob er 0 oder 1 ist, muss er mit gleicher Wahrscheinlichkeit den einen oder anderen auswählen.

Die auf 0 und 1 basierende Messung hat einige Namen. Wir können es aus offensichtlichen Gründen eine 0/1-Messung nennen. Es wird auch als Z-Basismessung bezeichnet, da die Zustände 0 und 1 eine besondere Beziehung zu einer Operation namens z haben. Mehr zu dieser Geschichte ein anderes Mal.

Die nächstbeliebteste Art der Messung ist die für + und -. Ich nenne dies eine +/- Messung, aber Sie können auch sehen, dass es sich um eine X-Basismessung handelt. Es funktioniert genauso wie zuvor, jedoch nur für + und - anstelle von 0 und 1. Wenn Sie also mit einem Qubit im Zustand + beginnen und diese Messung durchführen, erhalten Sie das Ergebnis +. Wenn Sie jedoch mit 0 beginnen und dieselbe Frage stellen, wird diese zufällig ausgewählt.

Wir haben auch ein Maß für die seltsamen Pfeilsachen. Dies wird als Y-Basismessung bezeichnet. Niemand mag Y-Basismessungen.

Ein bisschen ist nur ein bisschen, auch wenn es ein Quant ist

Die Messung von Nichtquantenobjekten ist ein passiver Prozess. Es sagt Ihnen, was das Objekt tut, aber es ändert es in keiner Weise. Das Messen von Quantensachen ist sehr unterschiedlich. Quantenmessungen ändern nicht nur unser Wissen über die Variablen. Sie ändern die Variablen selbst.

Angenommen, Sie haben ein Qubit im Status + und fragen dann, ob es 0 oder 1 ist. Wenn es Ihnen ein zufälliges Ergebnis liefert, werden Sie nicht nur abgespeist. Es sagt dir keinen Unsinn, weil du die falsche Frage gestellt hast. Sobald es Ihnen ein Ergebnis gibt, bleibt es dabei. Der Wert ändert sich, um die Antwort wiederzugeben. Wenn es Ihnen 0 sagt, wird es für immer 0 sein (oder bis Sie sich zumindest wieder damit anlegen). Es wird vergessen, dass es jemals + war.

Dies bedeutet, dass ein Qubit nur bei einer einzigen Messung von seinem Ergebnis überzeugt sein kann. Wenn es definitiv weiß, ob es 0 oder 1 ist, ist es völlig unsicher, ob es + oder - ist, und es ist auch völlig unsicher, ob es ↻ oder ↺ ist. Ein Qubit hat nur eine begrenzte Sicherheit, die durch das Heisenbergsche Unsicherheitsprinzip begrenzt wird.

Dies bedeutet, dass wir immer nur einen Versuch bekommen, Informationen von einem Qubit zu erhalten. Sobald wir ein einzelnes binäres Ergebnis extrahiert haben, ist alles vergessen, was das Qubit jemals vor der Messung wusste. Es erinnert sich nur an das Ergebnis, das es uns gegeben hat. Und so können wir trotz der unendlichen Anzahl möglicher Qubit-Zustände immer nur ein einziges Informationsbit extrahieren. Deshalb betrachten wir es eher als die Quantenversion eines Bits als als einen Quantenfloat oder einen Quanten-3-Vektor usw.

Die Spielmechanik

Wir werden eine Schlachtschiffvariante machen, bei der es zwei Arten von Angriffen geben wird: Bomben und Torpedos. Es wird nur ein erfolgreicher Angriff benötigt, um ein Schiff zu versenken, aber ein erfolgreicher Angriff ist nicht immer so einfach. Einige Schiffe haben eine so gute Verteidigung gegen Flugzeuge, dass keine Bombe jemals in ihre Nähe kommen wird. Andere sind großartig darin, Torpedos abzuwehren.

Um dies auf einem normalen Computer zu implementieren, könnten wir zwei boolesche Variablen für jedes Schiff definieren. Einer würde uns sagen, ob das Schiff immun gegen Bomben ist, der andere gegen Torpedos. Diese können dann bei Angriffen überprüft werden, um festzustellen, ob das Schiff sinkt oder nicht.

Wenn dies die Implementierung wäre, die wir verwenden, wäre es theoretisch möglich, dass ein Schiff gegen beide Arten von Angriffen immun ist. Dies wäre ein schlechtes Spieldesign, da es für einen Spieler unmöglich ist, zu gewinnen. Eine gute Umsetzung müsste verhindern, dass es unzerstörbare Schiffe gibt.

Eine Möglichkeit, solche Schiffe nicht zu bauen, sind ein paar einfache Codezeilen. Das ist jedoch nicht wirklich unser Stil. Stattdessen werden wir es mit der Quantenmechanik beheben!

Insbesondere werden wir versuchen, diese beiden Booleschen Werte zu einem einzigen Qubit zusammenzufassen. Da sie nicht ganz passen, erhalten wir ein interessantes Quantenverhalten. Dies wird dem Spiel ein interessantes Gameplay hinzufügen und verhindern, dass ein Schiff unzerstörbar wird.

Wir werden dies implementieren, indem wir einen Bombenangriff mit einer 0/1-Messung verknüpfen. Wenn wir das Ergebnis 1 erhalten, sagen wir, dass das Schiff gesunken ist. Für 0 schließen wir, dass das Schiff immun gegen Bombenangriffe ist. Für Torpedos führen wir stattdessen eine +/- Messung durch, wobei - Zerstörung und + Immunität impliziert.

Diese Methode macht es einem Schiff unmöglich, gegen beide Angriffsarten definitiv immun zu sein. Wenn wir herausfinden, dass ein feindliches Schiff immun gegen Bomben ist (dh sein Zustand ist 0), wissen wir, dass es in Bezug auf Torpedos (das Ergebnis einer +/- Messung) völlig unsicher sein muss. Da ein Bombenangriff sicherlich scheitern würde, sollten wir als nächstes mit Torpedos angreifen.

Es könnte sich dann herausstellen, dass der Torpedoangriff fehlschlägt (der Zustand wird nach der +/- Messung +). Das Schiff würde entscheiden, dass es definitiv immun gegen sie ist, und jeder weitere Torpedoangriff würde fehlschlagen. Aber nicht alle Hoffnung ist verloren. Durch die Gewissheit über Torpedos ist es über Bomben unsicher geworden. Ein Angriff mit ihnen als nächstes (eine 0/1-Messung) könnte zum Sieg führen.

Wenn der Bombenangriff nicht erfolgreich ist, kehren wir zu Torpedos zurück und so weiter. Die beste Taktik ist es, weiter zwischen den beiden zu wechseln, bis das Schiff schließlich sinkt.

Wir werden die Schiffe als unsicher über ihre Immunität gegen beide Angriffe starten. Dies kann durch Initialisieren des Qubits in einem der Y-Basiszustände erfolgen. Lass uns gehen für ↻. Dies ist tatsächlich ein Zustand, den wir in Teil 1 getroffen haben, nämlich u3 (0,5 * pi, 0,0) 0, also wissen wir bereits, wie man es macht.

Umgang mit kurzlebigen Qubits

Die Implementierung des Spiels auf einem Quantenprozessor wird nicht so einfach sein, wie wir vielleicht hoffen. Wir werden uns alle Probleme ansehen, die uns in den Weg kommen, und sehen, wie wir sie umgehen können.

Angenommen, ein Schiff wird von einer Bombe angegriffen und überlebt. In der nächsten Runde wird es dann von einem Torpedo getroffen.

Wenn das Spiel auf einem normalen Computer ausgeführt und mit normalen Bits simuliert würde, wäre die Implementierung recht einfach. Das Schiff wird zu Beginn des Spiels initialisiert und wartet dann im Speicher, bis der Spieler entscheidet, was er damit machen soll. Sobald der Spieler eine Bombe sendet, werden die entsprechenden Operationen angewendet, um festzustellen, ob sie zerstört wurde. Wenn es überlebt, wartet es erneut bis zum nächsten Angriff.

Das wird bei uns nicht funktionieren. Qubits können nicht herum sitzen und auf menschliche Zeitskalen warten. Ein paar Sekunden sind mehr als genug Zeit, um sie zum Absturz zu bringen und zu brennen, zumindest mit der aktuellen Technologie.

Die Alternative besteht darin, jedes Mal, wenn ein Angriff ausgeführt wird, einen neuen Quantenprozess auszuführen. Der erste Job wird mit dem Status ↻ initialisiert, sodass die Ergebnisse sowohl für eine 0/1-Messung (Bombenangriff) als auch für eine +/- Messung (Torpedoangriff) zufällig sind. Das Ergebnis der Messung wird dann aufgezeichnet und auf dem normalen Computer gespeichert. Wenn der nächste Angriff erfolgt, wird ein weiterer Job erstellt, um zu sehen, was passiert. Es wird mit dem Ergebnis der letzten Messung initialisiert und fährt fort.

+/- Messung durchführen

Bisher habe ich eine ganze Menge Wörter geschrieben, aber keine einzige Codezeile. Lassen Sie uns zunächst daran erinnern, wie eine 0/1-Messung im QASM-Code implementiert ist.

messen Sie q [0] -> c [0];

Die Rolle von c [0] ist hier wichtig für einen erneuten Besuch. Es ist die Ausgabe des Messprozesses. Es ist das normale Bit, auf dem das Messergebnis gespeichert ist. Bei einer 0/1-Messung ist das Ergebnis 0 oder 1.

Dies ist alles ziemlich einfach für eine 0/1-Messung. Aber es sind +/- Messungen, die wir uns gerade ansehen. Wie bekommen wir die Informationen aus einem von ihnen?

Wir wollen das Ergebnis weiterhin in einem normalen Bit c [0] speichern. Da es ein normales Bit ist, kennt es die seltsamen Zustände + und - nicht. Es kennt nur normale Binärdateien. Wir geben daher das Ergebnis + als c [0] = 0 und - als c [0] = 1 an. Die Tatsache, dass diese genauso aussehen wie die Ergebnisse einer 0/1-Messung, ist kein Problem. Wie in jedem Computerprogramm sollten wir wissen, was wir programmiert haben, und daher sollten wir wissen, wie die Ergebnisse zu interpretieren sind.

Jetzt wissen wir, wie wir die Ergebnisse aus einer +/- Messung herausholen können. Aber wir haben noch nicht herausgefunden, wie man das tatsächlich macht. Das liegt daran, dass wir hinterhältig sein müssen. Wir müssen den Prozess, der 0/1 Messungen durchführt, hacken und stattdessen eine +/- Messung durchführen.

Der Schlüssel zu unserem Hack ist eine Operation namens Hadamard. Das Anwenden auf ein Qubit q [0] im QASM-Code sieht folgendermaßen aus.

hq [0];

Der Befehl, den wir in Python verwenden, um diese Zeile zu einer QASM-Datei namens gridScript hinzuzufügen, lautet

gridScript.h (q [0])

Der Hadamard bewirkt, dass Z-Basiszustände gegen X-Basiszustände ausgetauscht werden und umgekehrt. Es ist eine Drehung der Kugel, die die Umdrehungen eines Qubit-Zustands 0 in ein + und + in 0 verschiebt. In ähnlicher Weise wird 1 nach - und umgekehrt gedreht.

Dies bedeutet, dass wir die Geschichte, die wir über ein Qubit in Form von 0 und 1 vor dem Hadamard erzählen können, mit + und - danach erzählen müssen. Und jede Geschichte von + und - wird eine von 0 und 1.

Genau das brauchen wir. Dies bedeutet, dass eine +/- Messung an einem Qubit q [0] mit dem folgenden QASM-Code durchgeführt werden kann.

hq [0]; messen Sie q [0] -> c [0]; hq [0];

Um zu sehen, warum dies funktioniert, gehen wir einige Beispiele durch. Das Qubit q [0] beginnt in jedem neu deklariert und befindet sich daher in seinem Standardanfangswert von 0.

Beispiel Null:

messen Sie q [0] -> c [0];

Das Qubit beginnt im Zustand 0. Es wird gefragt, ob es 0 oder 1 ist, und teilt c [0] die Antwort mit. Das Ergebnis ist immer c [0] = 0.

Beispiel Eins:

xq [0];
messen Sie q [0] -> c [0];

Das Qubit beginnt im Zustand 0 und wird dann auf 1 gedreht. Es wird dann gefragt, ob es 0 oder 1 ist. Es antwortet immer mit 1.

Beispiel +:

hq [0];
messen Sie q [0] -> c [0];

Das Qubit beginnt im Zustand 0 und wird sofort auf + gedreht. Es wird dann gefragt, ob sein Status 0 oder 1 ist. Es wählt zufällig den einen oder anderen aus und sein Status wird mit der Antwort aktualisiert.

Jetzt haben wir ein paar triviale Beispiele gemacht. Lassen Sie uns etwas Komplexeres machen.

Beispiel ++:

hq [0];
hq [0]; messen Sie q [0] -> c [0]; hq [0];

Das Qubit beginnt im Zustand 0 und wird dann auf + gedreht. Danach gibt es zwei gleichwertige Möglichkeiten, wie wir die Geschichte fortsetzen können.

Eine ist zu sagen, dass die drei letzten Linien zusammen eine +/- Messung durchführen. Sie fragen das Qubit, ob es + oder - ist. Für + geben sie das Ergebnis c [0] = 0 zurück und für - geben sie c [0] = 1 zurück. Da das Qubit in diesem Beispiel mit dem Zustand + in die Messung geht, wird es immer als + gemessen. Es kommt daher aus der Messung noch in diesem Zustand heraus.

Für die andere Geschichte betrachten wir die Auswirkungen der Zeilen einzeln. Der zweite Hadamard macht den Effekt des ersten rückgängig und dreht so das Qubit zurück in den Zustand 0. Es wird dann gefragt, ob sein Zustand 0 oder 1 ist, und antwortet daher immer mit 0. Ein weiterer Hadamard dreht ihn erneut auf +.

Beide Geschichten stimmen in den beobachtbaren Effekten überein. Sie stimmen zu, dass der Ausgang c [0] immer 0 sein wird, und sie stimmen zu, dass der Qubit-Zustand am Ende + sein wird. Sie sind sich einfach nicht einig darüber, wie es passiert ist. Beide Interpretationen sind gleichermaßen gültig.

Wenn Sie möchten, dass ein Jargon auf Wikipedia nachschlägt, sind dies Beispiele für die Schrödinger- und Heisenberg-Bilder der Quantenmechanik.

Beispiel +1:

xq [0];
hq [0]; messen Sie q [0] -> c [0]; hq [0];

Hier ist ein weiteres Beispiel, für das wir zwei gleichwertige Geschichten haben. Wir können sagen, dass q [0] als 0 beginnt und dann auf 1 gedreht wird. Dies wird dann um 0 gedreht - bevor eine 0/1-Messung durchgeführt wird. Es entscheidet zufällig über das eine oder andere, gibt die Ausgabe c [0] = 0 oder c [0] = 1 und lässt seinen Zustand entsprechend aktualisieren. Wenn es 0 ist, dreht der letzte Hadamard es auf +. Andernfalls wird es als - enden.

Alternativ könnte man sagen, dass das Qubit nach dem Drehen auf 1 eine +/- Messung durchläuft. Es entscheidet zufällig zwischen diesen beiden Optionen und gibt die Ausgabe c [0] = 0 für + und c [0] = 0 für -. Der Status wird entsprechend aktualisiert und endet entweder im Status + oder -.

Auch diese beiden Geschichten sind gleichermaßen gültig und stimmen in allen beobachtbaren Effekten überein. Wenn wir an die drei Zeilen denken wollen

hq [0]; messen Sie q [0] -> c [0]; hq [0];

Als +/- Messung steht es uns frei, dies zu tun. Wenn wir es uns als Hadamard vorstellen wollen, gefolgt von einer 0/1-Messung, gefolgt von einem Hadamard, ist das auch in Ordnung.

Es gibt eine wichtige Sache zu beachten, bevor wir weitermachen. Mit der IBM API können wir derzeit nichts mit einem Qubit tun, nachdem wir es gemessen haben. Dies ist keine allgemeine Regel für Quantencomputer. Normalerweise erwarten wir, dass wir Qubits so lange messen und manipulieren können, wie wir möchten. Aber wir können es im Moment nicht tun.

Das bereitet uns keine Probleme. Da Qubits ohnehin nicht herumsitzen können, während Spieler Entscheidungen treffen, müssen wir den Status bereits nach jeder Messrunde vollständig neu erstellen. Der zweite Hadamard wird im nächsten Job effektiv auftauchen und auf die wiedergeborene Version des Staates einwirken.

Alle anderen möglichen Messungen können durch ähnliche Hacks erreicht werden. Wir müssen nur einige Operationen im Voraus ausführen, um unsere alternative Messung aufzurufen, und dann (sofern die API dies zulässt) die entgegengesetzten Operationen unmittelbar danach ausführen.

Umgang mit Fehlern

Die derzeitige Quantentechnologie ist nicht perfekt. Die Qubits tun nicht immer das, was sie sollten. Wenn Ihr Qubit 0 ist und Sie eine 0/1-Messung durchführen, sollte das Ergebnis immer 0 sein. Immer. Bei aktuellen Quantengeräten besteht jedoch die Möglichkeit, dass es 1 ist. Dies könnte daran liegen, dass sich eine x-Operation eingeschlichen hat, während wir nicht gesucht haben. Es könnte sein, dass die Messung uns anlügt. Ereignisse wie diese sind selten, aber sie passieren.

Es gibt zwei Möglichkeiten, wie wir mit den Fehlern umgehen können. Eine ist, sie zu ignorieren. Wir können sie in die Erzählung des Spiels schreiben. Es gibt große Stürme auf dem Meer. Diese führen manchmal dazu, dass ein Schiff durch einen Angriff zerstört wird, selbst wenn es immun ist. Oder einen Angriff überleben, der ihn hätte zerstören sollen.

Die zweite Möglichkeit, mit Fehlern umzugehen, besteht darin, zu versuchen, deren Auswirkungen zu beseitigen. Wenn viele Qubits verfügbar wären, könnten wir dies mit einer Quantenfehlerkorrektur tun. Leider ist das noch ein paar Jahre entfernt.

Stattdessen machen wir einige Statistiken. Dafür brauchen wir Wahrscheinlichkeiten, die wir erhalten, indem wir jeden Job mehrmals ausführen und sehen, wie oft jedes mögliche Ergebnis auftritt.

Im geräuschlosen Fall wären die Wahrscheinlichkeiten alle 0%, 100% oder 50%. Ein Ergebnis ist entweder unmöglich (wie das Erhalten einer 1, wenn der Zustand 0 ist), sicher (wie das Erhalten einer +, wenn der Zustand + ist) oder völlig zufällig (wie das Erhalten einer 0, wenn der Zustand + ist).

Lärm wird diese ein bisschen durcheinander bringen. Wenn wir eine 0/1-Messung einer 0 durchführen, stellen wir möglicherweise fest, dass das Ergebnis 0 nur in 98% der Fälle auftritt, wobei 2% stattdessen für 1 gehen. Um dies zu korrigieren, werden wir etwas ziemlich Willkürliches tun. Wir werden entscheiden, dass etwas mit einer Wahrscheinlichkeit von weniger als 5% niemals hätte passieren dürfen. Alles mit einer Wahrscheinlichkeit von mehr als 95% sollte sicher sein.

Alles zusammenfügen

Dieser Artikel behandelt die allgemeinen Aspekte der Spielmechanik für diese Version von Schlachtschiffen und deren Implementierung mit einem Quantencomputer. Anstatt hier alle Details durchzugehen, lasse ich das für die Kommentare im eigentlichen Quellcode.

Wenn Sie der Meinung sind, dass etwas näher erläutert werden muss, lassen Sie es mich bitte wissen.