Übung: Erstellen eines Quanten-Zufallszahlen-Generators

Abgeschlossen

In dieser Einheit implementieren Sie die zweite Phase des Quanten-Zufallszahlen-Generators: die Kombination mehrerer Zufallsbits, um eine größere Zufallszahl zu bilden. Diese Phase baut auf dem Zufallsbit-Generator auf, den Sie bereits erstellt haben. In dieser Phase müssen Sie ein wenig klassischen Code schreiben.

Kann ich klassischen Code in Q# schreiben?

Ja, das ist möglich. Quantencomputer führen spezielle Aufgaben aus. Sie werden Quantencomputer nicht für alle Aufgaben verwenden, da in der Regel ein herkömmlicher Computer völlig ausreicht.

Genau wie bei einer GPU (Graphics Processing Unit) oder anderer spezieller Hardware werden Sie einen Quantencomputer für Aufgaben verwenden, für die er besonders geeignet ist. In diesem Fall möchten Sie rein zufällige Bits generieren.

Aus diesem Grund können Sie mit Q# auch klassischen Code schreiben, der Programmiersprachen ähnelt, die Sie bereits kennen.

Im Folgenden wird beschrieben, wie Sie mithilfe der Q#-Features einen vollständigen Zufallszahlen-Generator erstellen.

Definieren der Logik für den Zufallszahlen-Generator

Sehen wir uns an, wie die Logik eines Zufallszahlengenerators aussehen sollte, vorausgesetzt, der zufällige Bitgenerator, der in der vorherigen Einheit erstellt wurde, ist vorhanden:

  1. Definieren Sie max als höchste Zahl, die Sie generieren möchten.
  2. Definieren Sie die Anzahl zufälliger Bits, die Sie generieren müssen, indem Sie berechnen, wie viele Bits, nBits, Sie benötigen, um ganze Zahlen bis zu max auszudrücken.
  3. Generieren Sie eine zufällige Bitzeichenfolge, die nBits lang ist.
  4. Wenn die Bitzeichenfolge eine Zahl größer als max darstellt, kehren Sie zu Schritt 3 zurück.
  5. Andernfalls ist der Vorgang abgeschlossen. Geben Sie die generierte Zahl als ganze Zahl zurück.

Legen Sie zum Beispiel max auf 12 fest. Das heißt, 12 ist die größte Zahl, die Sie aus dem Zufallszahlengenerator abrufen möchten.

Sie benötigen ${\lfloor ln(12) / ln(2) + 1 \rfloor}$ gleich 4 Bits, um eine Zahl zwischen 0 und 12 darzustellen. (Aus Platzgründen überspringen wir die Ableitung dieser Gleichung.)

Angenommen, Sie generieren die Bitzeichenfolge ${1101_{\ binary}}$, dann entspricht dies ${13_{\ decimal}}$. Da 13 größer als 12 ist, wiederholen Sie den Vorgang.

Als Nächstes generieren Sie die Bitzeichenfolge ${0110_{\ binary}}$, dies entspricht ${6_{\ decimal}}$. Da 6 kleiner als 12 ist, ist der Prozess abgeschlossen.

Der Zufallszahlengenerator gibt die Zahl 6 zurück.

Erstellen eines vollständigen Zufallszahlengenerators

Hier erweitern Sie die RandomNumberGenerator.qs-Datei, um größere Zufallszahlen zu erstellen.

Hinzufügen der erforderlichen Bibliotheken

Für den vollständigen Zufallszahlen-Generator müssen drei weitere Q#-Bibliotheken eingeschlossen werden: Microsoft.Quantum.Math, Microsoft.Quantum.Intrinsic und Microsoft.Quantum.Convert. Fügen Sie die folgenden open-Direktiven wie folgt zu RandomNumberGenerator.qs hinzu:

namespace QuantumRandomNumberGenerator {
open Microsoft.Quantum.Convert;
open Microsoft.Quantum.Intrinsic;
open Microsoft.Quantum.Math;

// The rest of the code goes here.

}

Definieren des zufälligen Quantenzahlenvorgangs

Hier definieren Sie den GenerateRandomNumberInRange-Vorgang. Mit diesem Vorgang wird der GenerateRandomBit-Vorgang wiederholt aufgerufen, um eine Bitzeichenfolge zu erstellen.

Ändern Sie RandomNumberGenerator.qs wie folgt:

namespace QuantumRandomNumberGenerator {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;

    /// Generates a random number between 0 and `max`.
    operation GenerateRandomNumberInRange(max : Int) : Int {
        // Determine the number of bits needed to represent `max` and store it
        // in the `nBits` variable. Then generate `nBits` random bits which will
        // represent the generated random number.
        mutable bits = [];
        let nBits = BitSizeI(max);
        for idxBit in 1..nBits {
            set bits += [GenerateRandomBit()];
        }
        let sample = ResultArrayAsInt(bits);

        // Return random number if it is within the requested range.
        // Generate it again if it is outside the range.
        return sample > max ? GenerateRandomNumberInRange(max) | sample;
    }
}

Sehen Sie sich den neuen Code noch einmal an.

  • Sie müssen die Anzahl der Bits berechnen, die erforderlich sind, um ganze Zahlen bis zu maxausdrücken. Die BitSizeI-Funktion aus der Microsoft.Quantum.Math-Bibliothek konvertiert eine ganze Zahl in die Anzahl der Bits, die erforderlich sind, um sie darzustellen.
  • Der GenerateRandomNumberInRange-Vorgang verwendet eine for-Schleife zum Generieren von Zufallszahlen, bis eine Zahl generiert wird, die kleiner oder gleich max ist. Die for-Schleife funktioniert genauso wie eine for-Schleife in anderen Programmiersprachen.
  • Die Variable bits ist eine veränderbare Variable. Eine änderbare Variable ist eine Variable, die während der Berechnung geändert werden kann. Verwenden Sie die set-Direktive, um den Wert einer änderbaren Variablen zu ändern.
  • Die ResultArrayAsInt-Funktion stammt aus der Microsoft.Quantum.Convert-Bibliothek. Mit dieser Funktion wird die Bitzeichenfolge in eine positive ganze Zahl konvertiert.

Definieren des Einstiegspunkts

Das Programm kann jetzt Zufallszahlen generieren. Im Folgenden definieren Sie den Einstiegspunkt für Ihr Programm.

RandomNumberGenerator.qs-Datei wie folgt ändern:

namespace QuantumRandomNumberGenerator {
    open Microsoft.Quantum.Convert;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Math;

    @EntryPoint()
    operation Main() : Int {
        let max = 100;
        Message($"Sampling a random number between 0 and {max}: ");

        // Generate random number in the 0..max range.
        return GenerateRandomNumberInRange(max);
    }

    /// Generates a random number between 0 and `max`.
    operation GenerateRandomNumberInRange(max : Int) : Int {
        // Determine the number of bits needed to represent `max` and store it
        // in the `nBits` variable. Then generate `nBits` random bits which will
        // represent the generated random number.
        mutable bits = [];
        let nBits = BitSizeI(max);
        for idxBit in 1..nBits {
            set bits += [GenerateRandomBit()];
        }
        let sample = ResultArrayAsInt(bits);

        // Return random number if it is within the requested range.
        // Generate it again if it is outside the range.
        return sample > max ? GenerateRandomNumberInRange(max) | sample;
    }

    operation GenerateRandomBit() : Result {
        // Allocate a qubit.
        use q = Qubit();

        // Set the qubit into superposition of 0 and 1 using the Hadamard operation
        H(q);

        // At this point the qubit `q` has 50% chance of being measured in the
        // |0〉 state and 50% chance of being measured in the |1〉 state.
        // Measure the qubit value using the `M` operation, and store the
        // measurement value in the `result` variable.
        let result = M(q);

        // Reset qubit to the |0〉 state.
        // Qubits must be in the |0〉 state by the time they are released.
        Reset(q);

        // Return the result of the measurement.
        return result;
    }
}

Mit der let-Direktive werden Variablen deklariert, die während der Berechnung nicht geändert werden. Zu Lernzwecken wird der Höchstwert hier auf 100 festgelegt.

Hinweis

Dieser Codeausschnitt wird derzeit nicht auf allen verfügbaren Azure Quantum-Hardwarezielen ausgeführt, da das aufrufbare ResultArrayAsInt eine QPU mit vollständigem Berechnungsprofil erfordert.

Ausführen des Programms

Testen Sie den neuen Zufallszahlen-Generator.

  1. Bevor Sie das Programm ausführen, müssen Sie das Zielprofil auf Uneingeschränkt festlegen. Wählen Sie Ansicht -> Befehlspalette, suchen Sie nach QIR, wählen Sie Q# aus: Legen Sie das Azure Quantum QIR-Zielprofil fest und wählen Sie dann Q#: uneingeschränkt aus.
  2. Wenn Sie Ihr Programm lokal im integrierten Simulator einem Testlauf unterziehen möchten, klicken Sie auf Ausführen in der Liste der Befehle unter @EntryPoint() oder drücken Sie STRG+F5. Die Ausgabe wird in der Debugkonsole angezeigt.
  3. Führen Sie das Programm erneut aus, um ein anderes Ergebnis anzuzeigen.

Hinweis

Wenn das Zielprofil nicht auf Uneingeschränkt festgelegt ist, wird beim Ausführen des Programms eine Fehlermeldung angezeigt.

Herzlichen Glückwunsch! Nun wissen Sie, wie klassische Logik mit Q# kombiniert werden kann, um einen Quanten-Zufallszahlen-Generator zu erstellen.

Zusatzübung

Ändern Sie das Programm so, dass die generierte Zufallszahl größer als die Mindestzahl min statt null ist.