Exercice - Créer un générateur de nombres aléatoires quantiques
Dans cette unité, vous implémentez la deuxième phase de votre générateur de nombres aléatoires quantiques : la combinaison de plusieurs bits aléatoires pour former un plus grand nombre aléatoire. Cette phase s’appuie sur le générateur de bits aléatoires 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 bit aléatoire qui génère un bit aléatoire en plaçant un qubit en superposition et en le mesurant.
Lorsque vous mesurez le qubit, vous obtenez un bit aléatoire, 0 ou 1, avec une probabilité égale de 50 %. La valeur de ce bit est vraiment aléatoire, il n’existe aucun moyen de savoir ce que vous obtenez après la mesure. Mais comment pouvez-vous utiliser ce comportement pour générer des nombres aléatoires plus grands ?
Supposons que vous répétiez le processus quatre fois, ce qui générerait cette suite de chiffres binaires :
$${0, 1, 1, 0}$$
Si vous concaténez (ou combinez) ces bits dans une chaîne binaire, vous pouvez obtenir un nombre plus grand. Dans cet exemple, la séquence de bits ${0110}$ est équivalente à 6 en décimal.
$${0110_{\ binary} \equiv 6_{\ decimal}}$$
Si vous répétez ce processus plusieurs fois, vous pouvez combiner plusieurs bits pour former un grand nombre.
Définir la logique du générateur de nombres aléatoires
Nous allons expliquer à quoi doit ressembler la logique d’un générateur de nombres aléatoires, en utilisant le générateur de bits aléatoires de l’unité précédente :
- Définissez
max
comme le nombre maximal à générer. - Définissez le nombre de bits aléatoires que vous devez générer, en calculant le nombre de bits,
nBits
, dont vous avez besoin pour exprimer des entiers jusqu’àmax
. - 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 3. - Sinon, l’opération est terminée. Retournez le nombre généré sous la forme d’un entier.
À titre d’exemple, nous allons définir max
sur 12. Autrement dit, 12 est le plus grand nombre que vous voulez obtenir à partir du générateur de nombres aléatoires.
Vous avez besoin de ${\lfloor ln(12) / ln(2) + 1 \rfloor}$, ou de 4 bits pour représenter un nombre compris entre 0 et 12. (Pour rester concis, nous n’expliquons pas comment dériver cette équation.)
Mettons que vous générez la chaîne de bits ${1101_{\ binary}}$, qui est équivalente à $ ${13_{\ decimal}}$. 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 équivalente à ${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
Ici, vous développez le fichier Main.qs
pour générer des nombres aléatoires plus grands.
Importer les bibliothèques nécessaires
Vous devez d’abord importer les espaces de noms nécessaires de la bibliothèque standard Q# vers le programme. Le compilateur Q# charge automatiquement de nombreuses fonctions et opérations courantes. Toutefois, pour obtenir le générateur de nombres aléatoires quantiques complet, vous avez besoin de fonctions et d’opérations supplémentaires provenant de deux espaces de noms Q# : Microsoft.Quantum.Math
et Microsoft.Quantum.Convert
.
Copiez et collez les directives import
suivantes en haut de votre fichier Main.qs
:
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
Renommer l’opération Main
en GenerateRandomBit
Pour obtenir le générateur de nombres aléatoires complet, vous allez réutiliser l’opération définie dans l’unité précédente. Toutefois, le nom d’opération Main
est le point d’entrée du programme, et doit être unique. Pour éviter toute confusion, vous devez renommer l’opération Main
en GenerateRandomBit
.
L’opération GenerateRandomBit
doit ressembler à ceci :
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 nombre aléatoire quantique
Ici, vous définissez l’opération GenerateRandomNumberInRange
. Cette opération appelle à plusieurs reprises l’opération GenerateRandomBit
pour générer une chaîne de bits.
Copiez le code suivant, puis collez-le avant l’opération GenerateRandomBit
dans votre fichier Main.qs
:
/// 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;
}
Prenons un moment pour examiner ce nouveau code.
- Vous devez calculer le nombre de bits nécessaires pour exprimer des entiers jusqu’à
max
. La fonctionBitSizeI
de la bibliothèqueMicrosoft.Quantum.Math
convertit un entier en nombre de bits nécessaires pour le représenter. - L’opération
GenerateRandomNumberInRange
utilise une bouclefor
pour générer des nombres aléatoires jusqu’à générer une valeur inférieure ou égale àmax
. La bouclefor
fonctionne exactement de la même façon qu’une bouclefor
dans d’autres langages de programmation. - La variable
bits
est une variable mutable. Une variable mutable peut changer pendant le calcul. Vous devez utiliser la directiveset
pour modifier la valeur d’une variable mutable. - La fonction
ResultArrayAsInt
vient de la bibliothèqueMicrosoft.Quantum.Convert
. Cette fonction convertit la chaîne de bits en un entier positif.
Ajouter un point d’entrée
Enfin, vous ajoutez un point d’entrée au programme. Par défaut, le compilateur Q# recherche une opération Main
, et commence le traitement à partir de ce point, peu importe où il se trouve. L’opération Main
appelle l’opération GenerateRandomNumberInRange
pour générer un nombre aléatoire compris entre 0 et max
. Dans cet exemple, vous définissez la valeur maximale à 100.
Copiez et collez le code suivant dans votre fichier Main.qs
:
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);
}
Programme final
Votre fichier Main.qs
doit se présenter ainsi :
import Microsoft.Quantum.Convert.*;
import Microsoft.Quantum.Math.*;
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);
// 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
Essayons notre nouveau générateur de nombres aléatoires.
- Avant d’exécuter le programme, vous devez définir le profil cible sur Non restreint. Sélectionnez Afficher>Palette de commandes, recherchez QIR, sélectionnez Q# : Définir le profil cible QIR Azure Quantum, puis sélectionnez Q# : Non restreint.
- Pour exécuter votre programme, sélectionnez Exécuter dans la liste des commandes au-dessus de l’opération
Main
, ou appuyez sur Ctrl+F5. Votre sortie s’affiche dans la console de débogage. - Réexécutez le programme pour voir un résultat différent.
Remarque
Si le profil cible n’est pas défini sur Non restreint, vous obtenez une erreur quand vous exécutez le programme.
Félicitations ! Vous savez maintenant comment combiner la logique classique au langage Q# pour créer un générateur de nombres aléatoires quantiques.
Exercice bonus
Tentez de modifier le programme pour exiger également que le nombre aléatoire généré soit supérieur à un nombre minimal (min
), plutôt qu’à zéro.