Tutorial: Implementieren eines Quanten-Zufallszahlengenerators in Q#

Hier erfahren Sie, wie Sie ein einfaches Quantenprogramm in Q# schreiben, das sich die Quantenmechanik zunutze macht, um eine Zufallszahl zu generieren.

In diesem Tutorial wird Folgendes vermittelt:

  • Erstellen eines Q#-Projekts
  • Vorbereiten Ihrer Entwicklungsumgebung für das Schreiben von Quantenprogrammen in Q#
  • Verstehen der Struktur von Q#-Programmen
  • Arbeiten mit Qubits und Superposition, um einen Quanten-Zufallszahlen-Generator zu erstellen

Voraussetzungen

  • Installieren Sie das Quantum Development Kit (QDK) mit Ihrer bevorzugten Sprache und Entwicklungsumgebung. Die Lösung in diesem Tutorial wird in drei verschiedenen Formaten präsentiert:
    • Q# Eigenständige
    • Q# und Python
    • Q# und C #
  • Wenn das QDK bereits installiert ist, vergewissern Sie sich, dass das QDK und ggf. das Python-Q#-Paket auf die neueste Version aktualisiert wurde.

Erstellen eines Q# Projekts

Als Erstes muss ein neues Q#-Projekt erstellt werden. In diesem Tutorial wird die auf Q#-Anwendungen mit VS Code basierende Umgebung verwendet. Sie können aber Ihre bevorzugte IDE verwenden.

So erstellen Sie ein neues Projekt in Visual Studio Code

  1. Wählen Sie Ansicht>Befehlspalette und anschließend Q#: Neues Projekt erstellen aus.
  2. Wählen Sie Standalone console application (Eigenständige Konsolenanwendung) aus.
  3. Wählen Sie einen Speicherort für das Projekt aus, nennen Sie es Qrng, und wählen Sie anschließend Projekt erstellen aus.
  4. Wählen Sie nach erfolgreicher Erstellung des Projekts rechts unten die Option Neues Projekt öffnen... aus.

Dadurch werden zwei Dateien generiert: die Projektdatei qrng.csproj und eine Q# Anwendungsvorlage (Program.qs), die Sie zum Schreiben Ihrer Anwendung verwenden.

Schreiben Sie einen Q# Vorgang

Ersetzen Sie nun den Inhalt der Datei Program.qs durch 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 {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q); 
    }
}

Sehen Sie sich den neuen Code an.

  • Als Erstes wird open verwendet, um die erforderlichen Namespaces aus den Q#-Bibliotheken für die erforderlichen Funktionen und Vorgänge zu öffnen.
  • Sie definieren den SampleQuantumRandomNumberGenerator-Vorgang. Dieser benötigt keine Eingabe und erzeugt einen Wert vom Typ Result. Der Typ Result stellt das Ergebnis einer Messung dar und kann einen von zwei möglichen Werten haben: Zero oder One.
  • Weisen Sie ein einzelnes Qubit mit dem Schlüsselwort use zu.
  • Verwenden Sie die H-Operation (Hadamard), um das Qubit in eine ausgeglichene Superposition zu versetzen.
  • Verwenden Sie die M-Operation, um das Qubit zu messen und den gemessenen Wert (Zero oder One) zurückzugeben.

Wie im Artikel Grundlegendes zu Quantencomputing erklärt, stellt ein Qubit eine Einheit mit Quanteninformationen dar, die sich in Superposition befinden kann. Bei der Messung kann sich ein Qubit entweder im Zustand 0 oder im Zustand 1 befinden. Vor der Messung stellt der Qubitzustand jedoch die Wahrscheinlichkeit dar, mit der bei einer Messung entweder 0 oder 1 gelesen wird. In diesem Beispiel befindet sich das Qubit vor der Messung in einer ausgeglichenen Superposition. Die Wahrscheinlichkeit, 0 oder 1 zu lesen, liegt also jeweils bei 50 Prozent. Diese Wahrscheinlichkeit kann verwendet werden, um Zufallszahlen zu generieren.

Der benutzerdefinierte SampleQuantumRandomNumberGenerator-Vorgang führt den in nativen Q#-Datentyp Qubit ein. Ein Qubit kann nur mit einer use-Anweisung zugeordnet werden. Bei der Zuordnung befindet sich ein Qubit immer im Zustand Zero.

Wenn das Qubit mithilfe der H-Operation in Superposition versetzt und mithilfe der M-Operation gemessen wird, führt jeder Codeaufruf zu einem anderen Ergebniswert.

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. Bei dem durch den Pfeil dargestellten Qubit-Zustand in der folgenden Abbildung ist es beispielsweise wahrscheinlicher, dass sich bei einer Messung der Wert 0 ergibt:

Ein Diagramm, das einen Qubitzustand mit hoher Wahrscheinlichkeit zeigt, dass 0 (null) gemessen wird.

Diese Darstellung kann zur Visualisierung der Aktivitäten des Codes verwendet werden:

  • Beginnen Sie mit einem im Zustand 0 initialisierten Qubit, und wenden Sie eine H-Operation an, um eine gleichmäßige Superposition zu erreichen, bei der die Wahrscheinlichkeit für 0 und 1 jeweils gleich hoch ist.
Ein Diagramm, das die Vorbereitung eines Qubits in Superposition zeigt, indem das Hadamard-Gate angewendet wird.
  • Messen Sie anschließend das Qubit, und speichern Sie die Ausgabe:
Ein Diagramm, das die Messung eines Qubits und das Speichern der Ausgabe zeigt.

Da das Ergebnis der Messung zufällig und die Wahrscheinlichkeit der Messung von 0 oder 1 identisch ist, haben Sie ein vollkommen zufälliges Bit erhalten. Sie können diesen Vorgang mehrmals aufrufen, um ganze Zahlen zu erstellen. Wenn Sie den Vorgang beispielsweise dreimal aufrufen, um drei zufällige Bits zu erhalten, können Sie 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 mehrere zufällige Bits miteinander kombinieren, um einen vollständigen quantenbasierten Zufallszahlengenerator zu erstellen. Sie können Ihr Programm als eigenständige Q#-Anwendung ausführen oder ein Hostprogramm in Python oder .NET verwenden, um Ihren Q#-Code aufzurufen.

Definieren der Logik für den Zufallszahlen-Generator

Definieren Sie zunächst die Logik für einen Zufallszahlengenerator (vorausgesetzt, es ist bereits ein Zufallsbitgenerator vorhanden):

  1. Definieren Sie max als höchste Zahl, die Sie generieren möchten.
  2. Definieren Sie die Anzahl der Zufallsbits, die Sie generieren müssen. Hierzu wird die Anzahl von Bits (numBits) berechnet, die nötig sind, um ganze Zahlen bis zum maximalen Wert (max) ausdrücken zu können.
  3. Generieren Sie eine zufällige Bitfolge mit einer Länge von numBits.
  4. Wenn die Bitfolge eine Zahl darstellt, die größer als max ist, kehren Sie zu Schritt 3 zurück.
  5. Andernfalls ist der Vorgang abgeschlossen. Geben Sie die generierte Zahl als ganze Zahl zurück.

Definieren des Vorgangs

Definieren Sie als Nächstes den Vorgang SampleRandomNumberInRange. Dieser verwendet eine for-Schleife, um den Vorgang SampleQuantumRandomNumberGenerator wiederholt aufzurufen und eine Bitfolge zu erstellen.

Ändern Sie Program.qs, um den neuen Vorgang hinzuzufügen:

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q);           
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }
}

Überprüfen Sie nun den neuen Vorgang.

  • Verwenden Sie für die Berechnung der Anzahl von Bits, die nötig sind, um ganze Zahlen bis max auszudrücken, die Funktion BitSizeI.
  • Der SampleRandomNumberInRange-Vorgang verwendet eine repeat-Schleife zum Generieren von Zufallszahlen, bis eine Zahl generiert wird, die kleiner oder gleich max ist.
  • Die for-Schleife in repeat funktioniert genau wie eine for-Schleife in anderen Programmiersprachen.
  • In diesem Beispiel sind output und bitsänderbare Variablen. Eine änderbare Variable ist eine Variable, die während der Berechnung geändert werden kann. Zum Ändern des Werts einer änderbaren Variablen wird die set-Anweisung verwendet.
  • Die Funktion ResultArrayAsInt konvertiert die Bitfolge in eine positive ganze Zahl.

Das Programm Qrng kann jetzt Zufallszahlen generieren.

Ausführen des Programms für den Zufallszahlengenerator

Verwenden Sie die fertige Version des Q#-Codes:

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit        
        use q = Qubit();  
        // Put the qubit to superposition
        // It now has a 50% chance of being measured 0 or 1  
        H(q);      
        // Measure the qubit value            
        return M(q);           
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }
}

Wählen Sie die Registerkarte für Ihre bevorzugte Programmiersprache und Umgebung aus, und folgen Sie den Anweisungen zum Ausführen oder Aufrufen Ihres Q#-Programms.

Eine eigenständige Q#-Anwendung benötigt einen Einstiegspunkt (EntryPoint), um dem Q#-Compiler mitzuteilen, wo das Programm gestartet werden soll. Fügen Sie Ihrem Q#-Programm Program.qs den folgenden Einstiegspunkt hinzu, um die vollständige Q#-Anwendung zu erstellen:

namespace Qrng {

    open Microsoft.Quantum.Canon;
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Measurement;
    open Microsoft.Quantum.Math;
    open Microsoft.Quantum.Convert;

    operation SampleQuantumRandomNumberGenerator() : Result {
        // Allocate a qubit.
        use q = Qubit();
        // Put the qubit to superposition.
        H(q);
        // It now has a 50% chance of being measured 0 or 1.
        // Measure the qubit value.
        return M(q);
    }

    operation SampleRandomNumberInRange(max : Int) : Int {
        mutable output = 0; 
        repeat {
            mutable bits = []; 
            for idxBit in 1..BitSizeI(max) {
                set bits += [SampleQuantumRandomNumberGenerator()]; 
            }
            set output = ResultArrayAsInt(bits);
        } until (output <= max);
        return output;
    }

    @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, der bzw. die mit dem Attribut @EntryPoint() markiert ist, in einem Simulator oder in einem Ressourcenschätzer aus – 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 im Terminal Folgendes 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

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.

Nächste Schritte

Sehen Sie sich weitere Q#-Tutorials an: