Partager via


Tutoriel : Implémenter un générateur de nombres aléatoires quantique en Q#

Dans ce tutoriel, vous allez apprendre à écrire un programme quantique de base qui Q# tire parti de la nature de la mécanique quantique pour produire un nombre aléatoire.

Ce didacticiel présente les procédures suivantes :

  • Créez un Q# programme.
  • Passez en revue les principaux composants d’un Q# programme.
  • Définir la logique d’un problème.
  • Combiner des opérations classiques et quantiques pour résoudre un problème.
  • Utiliser des qubits et la superposition pour créer un générateur de nombres aléatoires quantiques

Conseil

Si vous souhaitez accélérer votre parcours d’informatique quantique, consultez Code avec Azure Quantum, une fonctionnalité unique du site web Azure Quantum. Ici, vous pouvez exécuter des exemples intégrés Q# ou vos propres Q# programmes, générer du nouveau Q# code à partir de vos invites, ouvrir et exécuter votre code dans VS Code pour le web en un clic et poser des questions à Copilot sur l’informatique quantique.

Prérequis

  • Pour exécuter l’exemple de code dans Copilot dans Azure Quantum :

    • Un compte de messagerie Microsoft (MSA).
  • Pour développer et exécuter l’exemple de code dans Visual Studio Code :

Définir le problème

Les ordinateurs classiques ne produisent pas de nombres aléatoires, mais plutôt des nombres pseudo-aléatoires. Un générateur de nombres pseudo-aléatoires génère une suite déterministe de nombres en fonction d’une valeur initiale, appelée seed. Pour obtenir la meilleure approximation possible des valeurs aléatoires, cette valeur seed est souvent l’heure actuelle de l’horloge du processeur.

Les ordinateurs quantiques, d’autre part, peuvent générer des nombres vraiment aléatoires. Cela est dû au fait que la mesure d’un qubit en superposition est un processus probabiliste. Le résultat de la mesure est aléatoire, il n’existe aucun moyen de prédire le résultat. C’est le principe de base des générateurs de nombres aléatoires quantiques.

Un qubit est une unité d’informations quantiques qui peuvent être en superposition. Quand il est mesuré, un qubit peut uniquement être dans l’état 0 ou dans l’état 1. Toutefois, avant la mesure, l’état du qubit représente la probabilité de lire un état 0 ou 1 avec une mesure.

Pour commencer, prenez un qubit dans un état basique, par exemple zéro. La première étape du générateur de nombres aléatoires consiste à utiliser une opération Hadamard pour placer le qubit dans une superposition égale. La mesure de cet état entraîne un zéro ou un avec une probabilité de 50 % de chaque résultat, un bit vraiment aléatoire.

Il n’existe aucun moyen de savoir ce que vous obtiendrez après la mesure du qubit en superposition, et le résultat est une valeur différente chaque fois que le code est appelé. 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. À l’aide de cette méthode, vous pouvez créer un nombre à utiliser comme mot de passe sécurisé, car vous pouvez être sûr qu’aucun pirate n’a pu déterminer les résultats de la séquence de mesures.

Définir la logique du générateur de nombres aléatoires

Décrivons la logique d’un générateur de nombres aléatoires :

  1. Définissez max comme le nombre maximal à générer.
  2. Définissez le nombre de bits aléatoires à générer. Pour ce faire, calculez le nombre de bits, nBitsvous devez exprimer des entiers jusqu’à max.
  3. Générez une chaîne de bits aléatoires dont la longueur est nBits.
  4. Si la chaîne de bits représente un nombre supérieur à max, revenez à l’étape 3.
  5. 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 souhaitez utiliser comme mot de passe.

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. Nous pouvons utiliser la fonction BitSizeIintégrée, qui prend n’importe quel entier et retourne le nombre de bits requis pour le représenter.

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é.

Le générateur de nombres aléatoires quantiques retourne le numéro 6 comme mot de passe. Dans la pratique, définissez un nombre plus grand comme valeur maximale, car les nombres inférieurs sont faciles à craquer en essayant juste tous les mots de passe possibles. En fait, pour augmenter la difficulté de deviner ou de craquer votre mot de passe, vous pouvez utiliser le code ASCII pour convertir le binaire en texte et générer un mot de passe en utilisant des chiffres, des symboles et un mélange de lettres majuscules et minuscules.

Écrire un générateur de bits aléatoire

La première étape consiste à écrire une Q# opération qui génère un bit aléatoire. Cette opération sera l’un des blocs de construction du générateur de nombres aléatoires.

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

    // Set the qubit into superposition of 0 and 1 using the Hadamard 
    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;
}

Examinons à présent le nouveau code.

  • Vous définissez l’opération GenerateRandomBit, qui ne prend aucune entrée et produit une valeur de type Result. Le type Result représente le résultat d’une mesure et peut avoir deux valeurs : Zero ou One.
  • Vous allouez un qubit unique avec le use mot clé. Lorsqu’il est alloué, un qubit est toujours dans l’état |0〉.
  • Vous utilisez l’opération H pour placer le qubit dans une superposition égale.
  • Vous utilisez l’opération M pour mesurer le qubit, renvoyer la valeur mesurée (Zero ou One).
  • Vous utilisez l’opération Reset pour réinitialiser le qubit à l’état |0〉.

En plaçant le qubit en superposition avec l’opération H et en le mesurant avec l’opération M, le résultat est une valeur différente chaque fois que le code est appelé.

Visualiser le Q# code avec la sphère Bloch

Dans la sphère de Bloch, le pôle nord représente la valeur classique 0 et le pôle sud représente la valeur classique 1. Toute superposition peut être représentée par un point sur la sphère (représentée par une flèche). Plus l’extrémité de la flèche est proche d’un pôle, plus la probabilité est élevée que le qubit soit réduit à la valeur classique attribuée à ce pôle lors de la mesure. Par exemple, l’état du qubit représenté par la flèche dans la figure ci-dessous a une probabilité plus élevée de donner la valeur 0 si vous le mesurez.

Diagramme montrant un état qubit avec une probabilité élevée de mesurer zéro.

Vous pouvez utiliser cette représentation pour visualiser ce que fait le code :

  1. Tout d’abord, commencez par un qubit initialisé dans l’état |0〉 et appliquez une H opération pour créer une superposition égale dans laquelle les probabilités pour 0 et 1 sont identiques.

    Diagramme montrant la préparation d’un qubit en superposition en appliquant la porte hadamard.
  2. Ensuite, mesurez le qubit et enregistrez la sortie :

    Diagramme montrant la mesure d’un qubit et l’enregistrement de la sortie.

Comme le résultat de la mesure est aléatoire et que les probabilités de mesure de 0 et 1 sont identiques, vous avez obtenu un bit complètement aléatoire. Nous pouvons appeler cette opération plusieurs fois pour créer des entiers. Par exemple, si vous appelez l’opération trois fois pour obtenir trois bits aléatoires, vous pouvez générer des nombres de 3 bits aléatoires (c’est-à-dire, un nombre aléatoire compris entre 0 et 7).

Écrire un générateur de nombres aléatoires complet

  1. Tout d’abord, vous devez importer les espaces de noms requis de la Q# bibliothèque standard dans le programme. Le Q# compilateur charge automatiquement de nombreuses fonctions et opérations courantes, mais pour le générateur de nombres aléatoires complet, vous avez besoin de certaines fonctions et opérations supplémentaires à partir de deux Q# espaces de noms : Microsoft.Quantum.Mathet Microsoft.Quantum.Convert.

    import Microsoft.Quantum.Convert.*;
    import Microsoft.Quantum.Math.*;
    
  2. Ensuite, 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.

    /// 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 BitSizeI fonction de l’espace Microsoft.Quantum.Math de noms convertit un entier en nombre de bits nécessaires pour le représenter.
    • L’opération SampleRandomNumberInRange utilise une boucle for pour générer des nombres aléatoires jusqu’à générer une valeur inférieure ou égale à max. La boucle for fonctionne exactement de la même façon qu’une boucle for 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 directive set pour modifier la valeur d’une variable mutable.
    • La ResultArrayAsInt fonction, à partir de l’espace de noms par défaut Microsoft.Quantum.Convert , convertit la chaîne de bits en entier positif.
  3. Enfin, vous ajoutez un point d’entrée au programme. Par défaut, le Q# compilateur recherche une Main opération et commence à y traiter. Elle appelle l’opération GenerateRandomNumberInRange pour générer un nombre aléatoire compris entre 0 et 100.

    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);
    }
    

    La directive let déclare des variables qui ne changent pas pendant le calcul. Ici, vous définissez la valeur maximale sur 100.

    Pour plus d’informations sur l’opération, consultez Points d’entréeMain.

  4. Le code complet du générateur de nombres aléatoires est le suivant :

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 a 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;
}

Exécuter le programme de génération de nombres aléatoires

Vous pouvez exécuter le programme dans Copilot dans Azure Quantum, et dans Visual Studio Code en tant qu’application autonome Q# ou à l’aide d’un programme hôte Python.

Vous pouvez tester votre Q# code avec Le Copilot dans Azure Quantum gratuitement. Tout ce dont vous avez besoin est un compte de messagerie Microsoft (MSA). Pour plus d’informations sur le Copilot dans Azure Quantum, consultez Explorer Azure Quantum.

  1. Ouvrez Copilot dans Azure Quantum dans votre navigateur.

  2. Copiez et collez le code suivant dans l’éditeur de code.

    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);
    }
    
    /// # Summary
    /// 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;
    }
    
    /// # Summary
    /// Generates a random bit.
    operation GenerateRandomBit() : Result {
        // Allocate a qubit.
        use q = Qubit();
    
        // Set the qubit into superposition of 0 and 1 using the Hadamard 
        // operation `H`.
        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;
    
        // Note that Qubit `q` is automatically released at the end of the block.
    }
    
    
  3. Sélectionnez le nombre de captures à exécuter, puis sélectionnez Exécuter.

  4. Les résultats sont affichés dans l’histogramme et dans les champs Résultats .

  5. Sélectionnez Expliquer le code pour inviter Copilot à expliquer le code à vous.

Conseil

À partir de Copilot dans Azure Quantum, vous pouvez ouvrir votre programme dans VS Code pour le web en sélectionnant le bouton du logo VS Code dans le coin droit de l’éditeur de code.

Remarque

Cet extrait de code ne s’exécute actuellement sur aucun matériel targetsAzure Quantum disponible, car l’appelant ResultArrayAsInt nécessite un QPU avec un profil de calcul complet.

Explorez les autres tutoriels Q# :

  • L’inanglement quantique montre comment écrire un Q# programme qui manipule et mesure des qubits et illustre les effets de la superposition et de l’inanglement.
  • L’algorithme de recherche de Grover montre comment écrire un Q# programme qui utilise l’algorithme de recherche de Grover.
  • Quantum Fourier Transforms explore comment écrire un Q# programme qui traite directement des qubits spécifiques.
  • Les katas quantiques sont des tutoriels auto-rythmes et des exercices de programmation visant à enseigner les éléments de l’informatique quantique et Q# de la programmation en même temps.