Übung, Teil 2: Erstellen eines Quanten-Zufallszahlengenerators
In dieser Einheit implementieren Sie den zweiten Teil Ihres Quanten-Zufallszahlengenerators. Sie kombinieren mehrere zufällige Bits, um eine größere Zufallszahl zu bilden. Dieser Teil baut auf dem zufälligen Bitgenerator auf, den Sie bereits in der vorherigen Einheit erstellt haben.
Kombinieren mehrerer zufälliger Bits, um eine größere Zahl zu bilden
In der vorherigen Einheit haben Sie einen zufälligen Bitgenerator erstellt, der ein Qubit in einen Superpositionszustand versetzt und dann den Qubit misst, um einen zufälligen Bitwert von 0 oder 1 zu generieren, jeweils mit 50% Wahrscheinlichkeit. Der Wert dieses Bits ist wirklich zufällig, es gibt keine Möglichkeit, vorab zu wissen, was das Messergebnis sein wird. Aber wie können Sie dieses Verhalten verwenden, um größere Zufallszahlen zu generieren?
Wenn Sie den Vorgang viermal wiederholen, können Sie diese Sequenz von binären Ziffern generieren:
${0, 1, 1, 0}$$
Wenn Sie diese Bits in einer Bitzeichenfolge kombinieren, können Sie eine größere Zahl bilden. In diesem Beispiel entspricht die Bitsequenz ${0110}$ in der Binärdatei der Zahl 6 im Dezimalzeichen.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Um eine willkürlich große Zufallszahl zu generieren, wiederholen Sie diesen Vorgang mehrmals. Kombinieren Sie dann alle Bits in eine binäre Zahl, und konvertieren Sie diese binäre Zahl in eine Dezimalzahl.
Definieren der Logik für den Zufallszahlen-Generator
Bevor Sie ihren Q#-Code schreiben, skizzieren wir die Logik zum Generieren einer Zufallszahl:
- Definieren Sie
maxdie maximale Dezimalzahl, die Sie generieren möchten. - Bestimmen Sie die Anzahl zufälliger Bits,
nBitsdie zum Generierenmaxerforderlich sind. - Generieren Sie eine zufällige Bitzeichenfolge, die
nBitslang ist. - Wenn die Bitzeichenfolge eine Zahl größer als
maxdarstellt, fahren Sie mit dem vorherigen Schritt fort. - Andernfalls ist der Vorgang abgeschlossen. Gibt die generierte Zahl als dezimale ganze Zahl zurück.
Definieren wir max beispielsweise als 12. Das heißt, 12 ist die größte Zahl, die der Zufallszahlengenerator ausgeben soll.
Verwenden Sie die folgende Formel, um die Anzahl der Bits zu bestimmen, die erforderlich sind, um die Zahl 12 in der Binärdatei darzustellen:
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
Gemäß dieser Gleichung benötigen Sie 4 Bit, um eine Zahl zwischen 0 und 12 darzustellen.
Angenommen, Sie generieren ein zufälliges Bit viermal und erhalten die Bitzeichenfolge ${1101_{\ binary}}$. Dieser Wert in der Binärdatei ist gleich 13 in dezimal. Da 13 größer als 12 ist, wiederholen Sie den Vorgang.
Als Nächstes generieren Sie die Bitzeichenfolge ${0110_{\ binary}}$, die ${6_{\ dezimal}}$ entspricht. Da 6 kleiner als 12 ist, ist der Prozess abgeschlossen.
Der Zufallszahlengenerator gibt die Zahl 6 zurück.
Erstellen eines vollständigen Zufallszahlengenerators in Q#
Hier erweitern Sie die Main.qs Datei aus der vorherigen Lektion, um ihren Zufallszahlengenerator zu erstellen.
Importieren der erforderlichen Bibliotheken
Importieren Sie zunächst die Namespaces aus der Q#-Standardbibliothek, die die Funktionen und Vorgänge enthalten, die Sie zum Schreiben des Programms benötigen. Der Q#-Compiler lädt viele gängige Funktionen und Vorgänge automatisch. Für den Quanten-Zufallszahlengenerator benötigen Sie jedoch einige zusätzliche Funktionen und Vorgänge aus zwei Q#-Namespaces: Microsoft.Quantum.Math und Microsoft.Quantum.Convert.
Kopieren Sie die folgenden import Direktiven, und fügen Sie sie am Anfang der Main.qs Datei ein:
import Std.Convert.*;
import Std.Math.*;
Hinweis
Sie können Std anstelle von Microsoft.Quantum verwenden, um Funktionen und Operationen aus der Standardbibliothek zu importieren.
Umbenennen des Main-Vorgangs in GenerateRandomBit
Das Zufallszahlengeneratorprogramm verwendet die von Ihnen im vorherigen Abschnitt geschriebene Main Operation, um ein zufälliges Bit zu generieren. Benennen Sie den Main Vorgang so um, dass dieser Vorgang GenerateRandomBit einen aussagekräftigeren Namen hat und nicht der Einstiegspunkt für das Programm ist.
Kopieren Sie den folgenden Code, und fügen Sie ihn in Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation GenerateRandomBit() : Result {
// Allocate a qubit.
use q = Qubit();
// Set the qubit into superposition of 0 and 1 using the Hadamard
H(q);
// Measure the qubit and store the result.
let result = M(q);
// Reset qubit to the |0〉 state.
Reset(q);
// Return the result of the measurement.
return result;
}
Definieren des Zufallszahlengeneratorvorgangs
Erstellen Sie einen neuen Vorgang namens GenerateRandomNumberInRange. Mit diesem Vorgang wird der GenerateRandomBit-Vorgang wiederholt aufgerufen, um eine Bitzeichenfolge zu erstellen.
Kopieren Sie den folgenden Code und platzieren Sie ihn direkt vor der GenerateRandomBit Operation in Ihrer Main.qs Datei.
/// 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's within the requested range.
// Generate it again if it's outside the range.
return sample > max ? GenerateRandomNumberInRange(max) | sample;
}
Hier ist eine Übersicht über den Code in GenerateRandomNumberInRange:
- Rufen Sie die
BitSizeI-Funktion aus derStd.Math-Bibliothek auf, um die Anzahl der Bits zu berechnen, die erforderlich sind, um die ganze Zahl darzustellen, die inmaxgespeichert ist. - Verwenden Sie eine
forSchleife, um eine Anzahl zufälliger Bits zu generieren, die gleich sindnBits. Rufen Sie denGenerateRandomBitVorgang auf, um die zufälligen Bits zu generieren. - Innerhalb der
for-Schleife verwenden Sie dieset-Anweisung, um die Variablebitsmit jedem zufälligen neuen Bit zu aktualisieren. Die Variablebitsist eine veränderbare Variable, was bedeutet, dass sich der Wertbitswährend der Berechnung ändern kann. - Rufen Sie die
ResultArrayAsInt-Funktion aus derStd.Convert-Bibliothek auf, um das Array von Bits inbitsin eine positive ganze Zahl zu konvertieren, die insamplegespeichert wird. - Überprüfen Sie in der
return-Anweisung, obsamplegrößer alsmaxist. Wennsamplegrößer alsmaxist, rufen Sie erneut aufGenerateRandomNumberInRange, und beginnen Sie erneut. Geben Sie andernfalls die Zufallszahl zurück, die insamplegespeichert ist.
Hinzufügen eines Einstiegspunkts
Fügen Sie schließlich ihrem Code einen Einstiegspunktvorgang hinzu, damit der Compiler das Programm ausführen kann. Standardmäßig sucht der Q#-Compiler nach einer Main-Operation und verwendet Main als den Einstiegspunkt, unabhängig davon, wo sich Main in Ihrer Datei befindet. Hier weist der Main-Vorgang einen Wert für max zu und führt den GenerateRandomNumberInRange-Vorgang aus, um eine Zufallszahl zwischen 0 und max zu generieren.
Um beispielsweise eine Zufallszahl zwischen 0 und 100 zu generieren, kopieren Sie den folgenden Code in Ihre Main.qs Datei:
operation Main() : Int {
let max = 100;
Message($"Generating a random number between 0 and {max}: ");
// Generate random number in the 0..max range.
return GenerateRandomNumberInRange(max);
}
Endgültiges Programm
Hier sehen Sie den vollständigen Q#-Code für Ihr Programm in Main.qs:
import Std.Convert.*;
import Std.Math.*;
operation Main() : Int {
let max = 100;
Message($"Generating 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's within the requested range.
// Generate it again if it's 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);
// 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.
Reset(q);
// Return the result of the measurement.
return result;
}
Ausführen des Programms
Probieren Sie Ihren neuen Quanten-Zufallszahlengenerator aus!
Wenn Sie Ihr Programm ausführen möchten, wählen Sie das Codeobjektiv "Ausführen" aus der Liste der Befehle oberhalb des Main Vorgangs aus. Oder drücken Sie STRG+F5. Die Ausgabe wird in der Debugging-Konsole angezeigt. Führen Sie das Programm mehrmals aus, und beachten Sie, wie sich das Ergebnis ändert.
Glückwunsch! Sie haben einen wirklich zufälligen Quantenzahlengenerator in Q# erstellt.
Zusatzübung
Versuchen Sie, das Programm so zu ändern, dass auch die generierte Zufallszahl größer als einige minimale positive Zahl minanstelle von Null sein muss.