Tutorial: Implementieren eines Quanten-Zufallszahlengenerators in Q#

Ein einfaches Beispiel für einen Quantenalgorithmus, der in Q# geschrieben ist, ist ein Quanten-Zufallszahlengenerator. Für diesen Algorithmus wird das Prinzip der Quantenmechanik genutzt, um eine Zufallszahl zu generieren.

Voraussetzungen

Schreiben Sie einen Q# Vorgang

Q# Vorgangscode

  1. Ersetzen Sie den Inhalt der Datei „Program.qs“ durch den folgenden Code:
namespace Qrng {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    operation SampleQuantumRandomNumberGenerator() : Result {
        use q = Qubit();   // Allocate a qubit.
        H(q);              // Put the qubit to superposition. It now has a 50% chance of being 0 or 1.
        return MResetZ(q); // Measure the qubit value.
    }
}

Wie im Artikel Grundlegendes zu Quantencomputing erklärt, stellt ein Qubit eine Einheit mit Quanteninformationen dar, die sich in einem Superpositionszustand befinden kann. Für ein Qubit kann sich bei einer Messung nur 0 oder 1 ergeben. Vor dem Messen stellt der Qubitzustand jedoch die Wahrscheinlichkeit des Lesens von entweder 0 oder 1 bei einer Messung dar. Dieser Wahrscheinlichkeitszustand wird als Überlagerung bezeichnet. Wir können diese Wahrscheinlichkeit verwenden, um Zufallszahlen zu generieren.

In unserer Operation Q# führen wir den Datentyp Qubit ein, der native in Q# ist. Wir können Qubit nur mit einer use-Anweisung zuordnen. Nach der Zuordnung befindet sich ein Qubit immer im Zustand Zero.

Mit der Operation H können wir das Qubit in den Zustand der Überlagerung versetzen. Zum Messen eines Qubits und Lesen seines Werts verwenden Sie die intrinsische Operation M.

Indem wir das Qubit in den Zustand der Überlagerung versetzen und die Messung durchführen, ergibt sich bei jedem Codeaufruf ein anderer Wert als Ergebnis.

Wenn die Zuordnung für ein Qubit aufgehoben wird, muss es explizit zurück in den Zustand Zero versetzt werden. Andernfalls wird vom Simulator ein Laufzeitfehler gemeldet. Eine einfache Möglichkeit, dies zu erreichen, ist das Aufrufen von Reset.

Visualisieren des Codes mit der Bloch-Kugel

Bei der Bloch-Kugel steht der Nordpol für den klassischen Wert 0 und der Südpol für den klassischen Wert 1. Jede Überlagerung kann durch einen Punkt auf der Kugel dargestellt werden (per Pfeil). Je näher sich das Ende des Pfeils an einem der Pole befindet, desto höher ist die Wahrscheinlichkeit, dass das Qubit bei einer Messung auf den klassischen Wert zurückfällt, der dem Pol zugeordnet ist. Der unten durch den roten Pfeil dargestellte Qubit-Zustand verfügt beispielsweise über eine höhere Wahrscheinlichkeit, dass sich bei einer Messung der Wert 0 ergibt.

A qubit state with a high probability of measuring zero

Wir können diese Darstellung verwenden, um die Aktivitäten des Codes zu visualisieren:

  • Wir beginnen mit einem im Zustand 0 initialisierten Qubit und wenden H an, um eine Überlagerung zu erstellen, bei der die Wahrscheinlichkeiten für 0 und 1 gleich hoch sind.
Preparing a qubit in superposition
  • Anschließend messen wir das Qubit und speichern die Ausgabe:
Measuring a qubit and saving the output

Da das Ergebnis der Messung völlig zufällig ist, erhalten wir ein zufälliges Bit. Wir können diesen Vorgang mehrmals aufrufen, um ganze Zahlen zu erstellen. Wenn wir den Vorgang beispielsweise dreimal aufrufen, um drei zufällige Bits zu erhalten, können wir zufällige 3-Bit-Zahlen erstellen (also eine Zufallszahl zwischen 0 und 7).

Erstellen eines vollständigen Zufallszahlengenerators

Sie verfügen nun über einen Q# Vorgang, der zufällige Bits generiert, und können damit einen vollständigen Quanten-Zufallszahlengenerator erstellen. Wir können eine Q# Anwendung oder ein Hostprogramm verwenden.

Zum Erstellen der vollständigen Q# Anwendung fügen Sie den folgenden Einstiegspunkt zu Ihrem Q# Programm hinzu:

namespace Qrng {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    operation SampleQuantumRandomNumberGenerator() : Result {
        use q = Qubit();   // Allocate a qubit.
        H(q);              // Put the qubit to superposition. It now has a 50% chance of being 0 or 1.
        return MResetZ(q); // Measure the qubit value.
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable bits = new Result[0];
        for idxBit in 1..BitSizeI(max) {
            set bits += [SampleQuantumRandomNumberGenerator()];
        }
        let sample = ResultArrayAsInt(bits);
        return sample > max
               ? SampleRandomNumberInRange(max)
               | sample;
    }
    @EntryPoint()
    operation SampleRandomNumber() : Int {
        let max = 50;
        Message($"Sampling a random number between 0 and {max}: ");
        return SampleRandomNumberInRange(max);
    }
}

Das Programm führt den Vorgang oder die Funktion aus, die mit dem @EntryPoint() Attribut auf einem Simulator oder Ressourcenschätzer markiert ist, je nach Projektkonfiguration und Befehlszeilenoptionen.

Drücken Sie in Visual Studio einfach STRG+F5, um das Skript auszuführen.

Erstellen Sie in VS Code erstmalig die Datei „Program.qs“, indem Sie Folgendes im Terminal eingeben:

dotnet build

Bei nachfolgenden Ausführungen muss diese Datei nicht erneut erstellt werden. Geben Sie für die Ausführung den folgenden Befehl ein, und drücken Sie die EINGABETASTE:

dotnet run --no-build