Exercice Partie 2 : créer un générateur de nombres aléatoires quantiques
Dans cette unité, vous implémentez la deuxième partie de votre générateur de nombres aléatoires quantiques. Vous combinez plusieurs bits aléatoires pour former un plus grand nombre aléatoire. Cette partie s’appuie sur le générateur de bits aléatoire que vous avez déjà créé dans l’unité précédente.
Combiner plusieurs bits aléatoires pour former un plus grand nombre
Dans l’unité précédente, vous avez créé un générateur de bits aléatoire qui place un qubit dans un état de superposition, puis mesure ce qubit pour générer une valeur de bit aléatoire de 0 ou 1, chacune avec 50% probabilité. La valeur de ce bit est vraiment aléatoire, il n’existe aucun moyen de savoir à l’avance quel sera le résultat de la mesure. Mais comment pouvez-vous utiliser ce comportement pour générer des nombres aléatoires plus grands ?
Si vous répétez le processus quatre fois, vous pouvez générer cette séquence de chiffres binaires :
$${0, 1, 1, 0}$$
Si vous combinez ces bits en chaîne de bits, vous pouvez former un nombre plus grand. Dans cet exemple, la séquence de bits ${0110}$ en binaire équivaut au nombre 6 en décimal.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Pour générer un nombre aléatoire arbitrairement important, répétez simplement ce processus plusieurs fois. Ensuite, combinez tous les bits en nombre binaire et convertissez ce nombre binaire en nombre décimal.
Définir la logique du générateur de nombres aléatoires
Avant d’écrire votre code Q#, nous allons décrire la logique pour générer un nombre aléatoire :
- Définissez
maxcomme nombre décimal maximal que vous souhaitez générer. - Déterminez le nombre de bits aléatoires,
nBitsqui sont requis pour générermax. - Générez une chaîne de bits aléatoires dont la longueur est
nBits. - Si la chaîne de bits représente un nombre supérieur
maxà , revenez à l’étape précédente. - Sinon, l’opération est terminée. Retourne le nombre généré sous forme d’entier décimal.
Par exemple, définissons max la valeur 12. Autrement dit, 12 est le plus grand nombre que votre générateur de nombres aléatoires doit générer.
Utilisez l’équation suivante pour déterminer le nombre de bits requis pour représenter le nombre 12 en binaire :
$${\lfloor ln(12) / ln(2) + 1 \rfloor}$$
Selon cette équation, vous avez besoin de 4 bits pour représenter un nombre compris entre 0 et 12.
Par exemple, supposons que vous générez un bit aléatoire quatre fois et obtenez la chaîne de bits ${1101_{\ binary}}$. Cette valeur en binaire est égale à 13 en décimale. Comme 13 est supérieur à 12, vous devez répéter le processus.
Ensuite, vous générez la chaîne de bits ${0110_{\binary}}$, qui est égale à ${6_{\ decimal}}$. Étant donné que 6 est inférieur à 12, le processus est terminé.
Votre générateur de nombres aléatoires quantiques renvoie le nombre 6.
Créer un générateur de nombres aléatoires complet dans Q#
Ici, vous développez le Main.qs fichier de la leçon précédente pour générer votre générateur de nombres aléatoires.
Importer les bibliothèques nécessaires
Tout d’abord, importez les espaces de noms de la bibliothèque standard Q# qui contiennent les fonctions et les opérations dont vous avez besoin pour écrire votre programme. Le compilateur Q# charge automatiquement de nombreuses fonctions et opérations courantes. Mais pour le générateur de nombres aléatoires quantiques, vous avez besoin de certaines fonctions et opérations supplémentaires à partir de deux espaces de noms Q# : Microsoft.Quantum.Math et Microsoft.Quantum.Convert.
Copiez et collez les directives suivantes import au début de votre Main.qs fichier :
import Std.Convert.*;
import Std.Math.*;
Remarque
Vous pouvez utiliser Std au lieu de Microsoft.Quantum pour importer des fonctions et des opérations à partir de la bibliothèque standard.
Renommer l’opération Main en GenerateRandomBit
Le programme générateur de nombres aléatoires utilise l’opération Main que vous avez écrite dans l’unité précédente pour générer un bit aléatoire. Renommez l’opération Main pour GenerateRandomBit que cette opération ait un nom plus descriptif et n’est pas le point d’entrée du programme.
Copiez et collez le code suivant dans 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;
}
Définir l’opération de générateur de nombres aléatoires
Créez une opération appelée GenerateRandomNumberInRange. Cette opération appelle à plusieurs reprises l’opération GenerateRandomBit pour générer une chaîne de bits.
Copiez le code suivant et placez-le directement avant l’opération GenerateRandomBit dans votre Main.qs fichier :
/// 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;
}
Voici une vue d’ensemble du code dans GenerateRandomNumberInRange:
- Appelez la
BitSizeIfonction de laStd.Mathbibliothèque pour calculer le nombre de bits nécessaires pour représenter l’entier stocké dansmax. - Utilisez une
forboucle pour générer un nombre de bits aléatoires égaux ànBits. Appelez votreGenerateRandomBitopération pour générer les bits aléatoires. - Dans la
forboucle, utilisez l’instructionsetpour mettre à jour labitsvariable avec chaque nouveau bit aléatoire. La variablebitsest une variable mutable, ce qui signifie que la valeur debitspeut changer pendant le calcul. - Appelez la fonction
ResultArrayAsIntde la bibliothèqueStd.Convertpour convertir le tableau de bits dansbitsen entier positif stocké danssample. - Dans l’instruction
return, vérifiez sisampleest supérieur àmax. Sisampleest supérieur àmax, appelezGenerateRandomNumberInRangeà nouveau et recommencez. Sinon, retournez le nombre aléatoire stocké danssample.
Ajouter un point d’entrée
Enfin, ajoutez une opération de point d’entrée à votre code afin que le compilateur puisse exécuter votre programme. Par défaut, le compilateur Q# recherche une Main opération et utilise Main comme point d’entrée, quel que soit l’emplacement Main de votre fichier. Ici, l’opération Main définit une valeur pour max et appelle l’opération GenerateRandomNumberInRange pour générer un nombre aléatoire compris entre 0 et max.
Par exemple, pour générer un nombre aléatoire compris entre 0 et 100, copiez le code suivant dans votre Main.qs fichier :
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);
}
Programme final
Voici le code Q# complet de votre programme dans 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;
}
Exécuter le programme
Essayez votre nouveau générateur de nombres aléatoires quantiques !
Pour exécuter votre programme, choisissez le code lens Exécuter dans la liste des commandes au-dessus de l'opération Main. Ou appuyez sur Ctrl + F5. La sortie s’affiche dans la console de débogage. Exécutez le programme plusieurs fois et notez comment le résultat change.
Félicitations ! Vous avez créé un générateur de nombres quantiques vraiment aléatoires en Q#.
Exercice bonus
Essayez de modifier le programme afin qu’il exige également que le nombre aléatoire généré soit supérieur à un nombre positif minimal, minau lieu de zéro.