Tutoriel : Explorer l’intrication avec Q#

Ce tutoriel explique comment écrire un programme Q# qui manipule et mesure des qubits, puis montre les effets de la superposition et de l’intrication. Vous préparez deux qubits dans un état quantique spécifique, découvrez comment opérer sur des qubits avec Q# pour modifier leur état et démontrer les effets de la superposition et de l’intrication. Vous créez votre Q# programme pièce par pièce pour introduire des états, des opérations et des mesures de qubit.

Notes

Le Kit de développement Microsoft Quantum (QDK classique) ne sera plus pris en charge après le 30 juin 2024. Si vous êtes un développeur QDK existant, nous vous recommandons de passer au nouveau Kit de développement Azure Quantum (QDK moderne) pour continuer à développer des solutions quantiques. Pour plus d’informations, consultez Migrer votre Q# code vers le QDK moderne.

Voici quelques concepts clés à comprendre avant de commencer :

  • Alors que les bits classiques contiennent une seule valeur binaire 0 ou 1, l’état d’un qubit peut se trouver dans une superposition de deux états quantiques, 0 et 1. Chaque état quantique possible est associé à une amplitude de probabilité.
  • Le fait de mesurer un qubit produit un résultat binaire avec une certaine probabilité et modifie l’état du qubit hors superposition.
  • Plusieurs qubits peuvent être enchevêtrés de sorte qu’ils ne peuvent pas être décrits indépendamment les uns des autres. Autrement dit, tout ce qui se passe sur un qubit dans une paire intriquée se produit également sur l’autre qubit.

Ce didacticiel vous montre comment effectuer les opérations suivantes :

  • Créez des Q# opérations pour initialiser un qubit à l’état souhaité.
  • Mettre un qubit en superposition.
  • Intriquer une paire de qubits.
  • Mesurez un qubit et observez les résultats.

Conseil

Si vous souhaitez accélérer votre parcours d’informatique quantique, case activée 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 un nouveau Q# code à partir de vos invites, ouvrir et exécuter votre code dans VS Code pour le web en un seul clic, et poser des questions à Copilot sur l’informatique quantique.

Prérequis

Pour exécuter l’exemple de code dans Copilot pour Azure Quantum, vous avez besoin des éléments suivants :

  • Un compte de messagerie Microsoft (MSA).

Pour plus d’informations sur Copilot, consultez Explorer Azure Quantum.

Initialiser un qubit à un état connu

La première étape consiste à définir une opération Q# qui initialise un qubit sur un état connu. Cela peut être appelé pour définir un qubit à un état classique, ce qui signifie que, lorsqu’il est mesuré, il retourne Zero 100 % du temps ou retourne One 100 % du temps. La mesure d’un qubit retourne un Q# type Result, qui ne peut avoir qu’une valeur de Zero ou One.

Ouvrez Copilot pour Azure Quantum et copiez le code suivant dans la fenêtre de l’éditeur de code. Ne cliquez pas encore sur Exécuter . Vous exécuterez le code plus loin dans le tutoriel.

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

L’exemple de code introduit deux opérations standard, M et X, qui transforment l’état d’un qubit.

L'opération SetQubitState :

  1. Prend deux paramètres : un type Result, nommé desired, qui représente l’état souhaité pour que le qubit soit dans (Zero ou One) et un type Qubit.
  2. Effectue une opération de mesure, M, qui mesure l’état du qubit (Zero ou One) et compare le résultat à la valeur spécifiée dans desired.
  3. Si la mesure ne correspond pas à la valeur comparée, elle exécute une opération X qui retourne l’état du qubit à l’emplacement où les probabilités d’une mesure retournent Zero et One sont inversées. De cette façon, SetQubitState place toujours le qubit cible à l’état souhaité.

Écrire une opération de test pour tester l’état Bell

Ensuite, pour montrer l’effet de l’opération SetQubitState, créez une autre opération nommée TestBellState. Cette opération alloue deux qubits, appelle SetQubitState pour définir le premier qubit sur un état connu, puis mesure les qubits pour afficher les résultats.

Copiez le code suivant dans la fenêtre de l’éditeur de code, sous l’opération SetQubitState .

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Dans le code, les count variables et initial sont définies 1000 sur et One respectivement. Cela initialise le premier qubit à One et mesure chaque qubit 1 000 fois.

L’opération TestBellState :

  1. Définit des variables pour le compteur et l’état initial du qubit.
  2. Appelle l’instruction use pour initialiser deux qubits.
  3. Effectue une boucle pour les itérations count. Pour chaque boucle, elle
    1. appelle SetQubitState pour définir une valeur spécifiée initial sur le premier qubit ;
    2. appelle une nouvelle fois SetQubitState pour définir le deuxième qubit sur un état Zero ;
    3. utilise l’opération M pour mesurer chaque qubit ;
    4. stocke le nombre de mesures pour chaque qubit qui retourne One.
  4. Une fois la boucle terminée, elle appelle une nouvelle fois SetQubitState pour réinitialiser les qubits à un état connu (Zero) afin de permettre à d’autres utilisateurs d’allouer les qubits dans un état connu. C’est ce qu’exige l’instruction use.
  5. Enfin, il utilise la fonction pour imprimer les Message résultats dans les fenêtres de sortie Copilot avant de retourner les résultats.

Exécuter le code dans Copilot pour Azure Quantum

Avant de passer aux procédures de superposition et d’intrication, vous pouvez tester le code jusqu’à ce point pour voir l’initialisation et la mesure des qubits.

Pour exécuter le code en tant que programme autonome, le Q# compilateur dans copilot doit savoir démarrer le programme. Pour ce faire, ajoutez un @EntryPoint() qui précède directement l’opération que vous souhaitez exécuter en Q# premier. Par exemple, dans ce cas, est l’opération TestBellState .

Notes

@EntryPoint() est nécessaire uniquement pour les programmes Q# autonomes. Lors de l’exécution d’un Q# programme dans jupyter notebooks ou de l’appel d’un Q# programme à partir d’un fichier hôte Python, il n’est pas obligatoire et génère une erreur si elle est incluse.

Ajoutez l’opération @EntryPoint() juste avant TestBellState et votre Q# programme doit maintenant ressembler à ceci :

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Copiez et collez l’exemple de code complet dans la fenêtre de code Copilot pour Azure Quantum , définissez la diapositive du nombre de captures sur « 1 », puis cliquez sur Exécuter. Les résultats sont affichés dans l’histogramme et dans les champs Résultats .

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Comme les qubits n’ont pas encore été manipulés, ils ont conservé leurs valeurs initiales : le premier qubit retourne One chaque fois et le deuxième qubit retourne Zero.

Si vous modifiez la valeur de initial et Zero réexécutez le programme, vous devez observer que le premier qubit retourne Zero également à chaque fois.

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 0
Q2 - Ones: 1000

Mettre un qubit en superposition

Actuellement, les qubits dans le programme sont tous dans un état classique, autrement dit, 1 ou 0. Vous le savez parce que le programme initialise les qubits sur un état connu et que vous n’avez pas ajouté de processus pour les manipuler. Avant d’enchevêtrer les qubits, vous placez le premier qubit dans un état de superposition, où une mesure du qubit retourne Zero environ 50 % du temps et One environ 50 % du temps. Conceptuellement, le qubit peut être considéré comme ayant une probabilité égale de mesurer Zero ou One.

Pour mettre un qubit en superposition, Q# fournit l’opération H ou Hadarmard. Rappelez-vous l’opération X de la procédure Initialiser un qubit vers un état connu précédemment, qui a fait basculer un qubit de 0 à 1 (ou vice versa) ; l’opération H retourne le qubit à mi-chemin dans un état de probabilités égales de Zero ou One. Quand il est mesuré, un qubit en superposition doit retourner approximativement un nombre égal de résultats Zero et One.

Modifiez le code de l’opération TestBellState en réinitialisant la valeur One initiale sur et en insérant une ligne pour l’opération H :

for test in 1..count {
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        H(q1);                // Add the H operation after initialization and before measurement

        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2); 
        ...

Maintenant, lorsque vous exécutez le programme, vous pouvez voir les résultats du premier qubit dans la superposition.

Q1 - Zeros: 523            // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Chaque fois que vous exécutez le programme, les résultats du premier qubit varient légèrement, mais se rapprochent de 50 % de One et 50 % de Zero, tandis que les résultats du deuxième qubit restent Zero en permanence.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

L’initialisation du premier qubit à Zero retourner des résultats similaires.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Notes

En déplaçant le curseur dans Copilot pour Azure Quantum et en augmentant le nombre de captures, vous pouvez voir comment les résultats de superposition varient légèrement sur la distribution des clichés.

Intriquer deux qubits

Comme mentionné précédemment, les qubits intriqués sont connectés de façon à ne pas pouvoir être décrits indépendamment les uns des autres. Autrement dit, toute opération sur un qubit se produit également sur le qubit intriqué. Cela vous permet de connaître l’état résultant d’un qubit sans le mesurer, simplement en mesurant l’état de l’autre qubit. (Cet exemple utilise deux qubits, mais vous pouvez intriquer trois qubits ou plus).

Pour activer l’intrication, Q# fournit l’opération CNOT, qui correspond à Controlled-NOT. Le résultat de l’exécution de cette opération sur deux qubits consiste à inverser le second qubit si le premier correspond à One.

Ajoutez l’opération CNOT à votre programme immédiatement après l’opération H. Votre programme complet doit ressembler à ceci :

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = Zero;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
        
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Maintenant, lorsque vous exécutez le programme, vous devez voir quelque chose comme :

Q1 - Zeros: 502           // results will vary
Q1 - Ones: 498
Q2 - Zeros: 502
Q2 - Ones: 498

Notez que les statistiques du premier qubit n’ont pas changé (il existe toujours une probabilité d’environ 50/50 d’une Zero mesure ou après One une mesure), mais les résultats de mesure pour le deuxième qubit sont toujours les mêmes que ceux du premier qubit, quel que soit le nombre de fois où vous exécutez le programme. L’opération CNOT a intriqué les deux qubits de sorte que ce qui arrive à l’un arrive également à l’autre.

Prérequis

Pour développer et exécuter l’exemple de code dans votre environnement de développement local :

Créer un Q# fichier

  1. Ouvrez Visual Studio Code et sélectionnez Fichier > Nouveau fichier texte pour créer un fichier.
  2. Enregistrez le fichier sous le nom CreateBellStates.qs. Ce fichier contient le Q# code de votre programme.

Initialiser un qubit à un état connu

La première étape consiste à définir une opération Q# qui initialise un qubit sur un état connu. Vous pouvez appeler cette méthode pour définir un qubit sur un état classique, ce qui signifie qu’il retourne Zero 100 % du temps ou One 100 % du temps. Zero et One sont des valeurs Q# qui représentent les deux seuls résultats possibles d’une mesure de qubit.

Ouvrez CreateBellStates.qs et copiez le code suivant :

   namespace Bell {
       open Microsoft.Quantum.Intrinsic;
       open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }
   }

L’exemple de code introduit deux opérations standard, M et X, qui transforment l’état d’un qubit.

L'opération SetQubitState :

  1. Prend deux paramètres : un type Result, nommé desired, qui représente l’état souhaité pour que le qubit soit dans (Zero ou One) et un type Qubit.
  2. Effectue une opération de mesure, M, qui mesure l’état du qubit (Zero ou One) et compare le résultat à la valeur spécifiée dans desired.
  3. Si la mesure ne correspond pas à la valeur comparée, elle exécute une opération X qui retourne l’état du qubit à l’emplacement où les probabilités d’une mesure retournent Zero et One sont inversées. De cette façon, SetQubitState place toujours le qubit cible à l’état souhaité.

Écrire une opération de test pour tester l’état Bell

Ensuite, pour montrer l’effet de l’opération SetQubitState, créez une autre opération nommée TestBellState. Cette opération alloue deux qubits, appelle SetQubitState pour définir le premier qubit à un état connu, puis mesure les qubits pour voir les résultats.

Ajoutez l’opération suivante à votre fichier CreateBellStates.qs après l’opération SetQubitState :

operation TestBellState() : (Int, Int, Int, Int) {
    mutable numOnesQ1 = 0;
    mutable numOnesQ2 = 0;
    let count = 1000;
    let initial = One;

    // allocate the qubits
    use (q1, q2) = (Qubit(), Qubit());   
    for test in 1..count {
        SetQubitState(initial, q1);
        SetQubitState(Zero, q2);
        
        // measure each qubit
        let resultQ1 = M(q1);            
        let resultQ2 = M(q2);           

        // Count the number of 'Ones' returned:
        if resultQ1 == One {
            set numOnesQ1 += 1;
        }
        if resultQ2 == One {
            set numOnesQ2 += 1;
        }
    }

    // reset the qubits
    SetQubitState(Zero, q1);             
    SetQubitState(Zero, q2);
    

    // Display the times that |0> is returned, and times that |1> is returned
    Message($"Q1 - Zeros: {count - numOnesQ1}");
    Message($"Q1 - Ones: {numOnesQ1}");
    Message($"Q2 - Zeros: {count - numOnesQ2}");
    Message($"Q2 - Ones: {numOnesQ2}");
    return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

}

Dans le code, les count variables et initial sont définies 1000 sur et One respectivement. Cela initialise le premier qubit à One et mesure chaque qubit 1 000 fois.

L’opération TestBellState :

  1. accepte deux paramètres : count, le nombre d’exécutions d’une mesure, et initial, l’état souhaité pour initialiser le qubit.
  2. Appelle l’instruction use pour initialiser deux qubits.
  3. Effectue une boucle pour les itérations count. Pour chaque boucle, elle
    1. appelle SetQubitState pour définir une valeur spécifiée initial sur le premier qubit ;
    2. appelle une nouvelle fois SetQubitState pour définir le deuxième qubit sur un état Zero ;
    3. utilise l’opération M pour mesurer chaque qubit ;
    4. stocke le nombre de mesures pour chaque qubit qui retourne One.
  4. Une fois la boucle terminée, elle appelle une nouvelle fois SetQubitState pour réinitialiser les qubits à un état connu (Zero) afin de permettre à d’autres utilisateurs d’allouer les qubits dans un état connu. C’est ce qu’exige l’instruction use.
  5. Enfin, elle utilise la fonction Message pour afficher un message dans la console avant de retourner les résultats.

Exécuter le code

Avant de passer aux procédures de superposition et d’intrication, testez le code jusqu’à ce point pour voir l’initialisation et la mesure des qubits.

Pour ce faire, dans le Q# fichier, ajoutez un @EntryPoint() qui précède directement l’opération que vous souhaitez exécuter. Par exemple, dans ce cas est l’opération TestBellState .

Notes

@EntryPoint() est nécessaire uniquement pour les programmes Q# autonomes. Lors de l’exécution d’un Q# programme dans Jupyter Notebooks ou de l’appel d’un Q# programme à partir d’un fichier hôte Python, il n’est pas obligatoire et génère une erreur si elle est incluse.

Votre fichier CreateBellStates.qs doit maintenant ressembler à ceci :

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Avant d’exécuter le programme, vous devez définir le profil cible sur Sans restriction. Sélectionnez Affichage -> Palette de commandes, recherchez QIR, sélectionnezQ# : Définissez le profil cible Azure Quantum QIR, puis sélectionnez Q#: sans restriction.

Pour exécuter le programme, sélectionnez Exécuter Q# le fichier dans la liste déroulante icône de lecture en haut à droite, ou appuyez sur Ctrl+F5. Le programme exécute l’opération ou la fonction marquée avec l’attribut @EntryPoint() sur le simulateur par défaut.

Notes

Si le profil cible n’est pas défini sur Sans restriction, vous obtiendrez une erreur lorsque vous exécutez le programme.

Votre sortie s’affiche dans la console de débogage.

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 1000
Q2 - Ones: 0

Comme les qubits n’ont pas encore été manipulés, ils ont conservé leurs valeurs initiales : le premier qubit retourne One chaque fois et le deuxième qubit retourne Zero.

Si vous modifiez la valeur de initial et Zero réexécutez le programme, vous devez observer que le premier qubit retourne Zero également à chaque fois.

Q1 - Zeros: 0
Q1 - Ones: 1000
Q2 - Zeros: 0
Q2 - Ones: 1000

Conseil

Rappelez-vous d’enregistrer votre fichier chaque fois que vous apportez une modification au code avant de l’exécuter à nouveau.

Mettre un qubit en superposition

Actuellement, les qubits dans le programme sont tous dans un état classique, autrement dit, 1 ou 0. Vous le savez parce que le programme initialise les qubits sur un état connu et que vous n’avez pas ajouté de processus pour les manipuler. Avant d’intriquer les qubits, vous placez le premier qubit dans un état de superposition, où une mesure du qubit retourne Zero 50 % du temps et One 50 % du temps. D’un point de vue conceptuel, le qubit peut être considéré à mi-chemin entre Zero et One.

Pour mettre un qubit en superposition, Q# fournit l’opération H ou Hadarmard. Rappelez-vous l’opération X de la procédure Initialiser un qubit vers un état connu précédemment, qui a retourné un qubit de Zero à One (ou inversement) ; l’opération H retourne le qubit à mi-chemin dans un état de probabilité égale de Zero ou One. Quand il est mesuré, un qubit en superposition doit retourner approximativement un nombre égal de résultats Zero et One.

Modifiez le code de l’opération TestBellState pour ajouter l’opération H :

    for test in 1..count {
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
            
            H(q1);                // Add the H operation after initialization and before measurement

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2); 
            ...

Désormais, quand vous exécutez le programme, vous pouvez voir les résultats du premier qubit en superposition :

Q1 - Zeros: 523            // results will vary
Q1 - Ones: 477
Q2 - Zeros: 1000
Q2 - Ones: 0

Chaque fois que vous exécutez le programme, les résultats du premier qubit varient légèrement, mais se rapprochent de 50 % de One et 50 % de Zero, tandis que les résultats du deuxième qubit restent Zero en permanence.

Q1 - Zeros: 510           
Q1 - Ones: 490
Q2 - Zeros: 1000
Q2 - Ones: 0

L’initialisation du premier qubit sur Zero retourne des résultats similaires.

Q1 - Zeros: 504           
Q1 - Ones: 496
Q2 - Zeros: 1000
Q2 - Ones: 0

Intriquer deux qubits

Comme mentionné précédemment, les qubits intriqués sont connectés de façon à ne pas pouvoir être décrits indépendamment les uns des autres. Autrement dit, toute opération sur un qubit se produit également sur le qubit intriqué. Cela vous permet de connaître l’état résultant d’un qubit sans le mesurer, simplement en mesurant l’état de l’autre qubit. (Cet exemple utilise deux qubits, mais vous pouvez intriquer trois qubits ou plus).

Pour activer l’intrication, Q# fournit l’opération CNOT, qui correspond à Controlled-NOT. Le résultat de l’exécution de cette opération sur deux qubits consiste à inverser le second qubit si le premier correspond à One.

Ajoutez l’opération CNOT à votre programme immédiatement après l’opération H. Votre programme complet doit ressembler à ceci :

namespace Bell {
    open Microsoft.Quantum.Intrinsic;
    open Microsoft.Quantum.Canon;

       operation SetQubitState(desired : Result, target : Qubit) : Unit {
           if desired != M(target) {
               X(target);
           }
       }

    @EntryPoint()
    operation TestBellState() : (Int, Int, Int, Int) {
        mutable numOnesQ1 = 0;
        mutable numOnesQ2 = 0;
        let count = 1000;
        let initial = One;

        // allocate the qubits
        use (q1, q2) = (Qubit(), Qubit());   
        for test in 1..count {
            SetQubitState(initial, q1);
            SetQubitState(Zero, q2);
        
            H(q1);            
            CNOT(q1, q2);      // Add the CNOT operation after the H operation

            // measure each qubit
            let resultQ1 = M(q1);            
            let resultQ2 = M(q2);           
    
            // Count the number of 'Ones' returned:
            if resultQ1 == One {
                set numOnesQ1 += 1;
            }
            if resultQ2 == One {
                set numOnesQ2 += 1;
            }
        }
    
        // reset the qubits
        SetQubitState(Zero, q1);             
        SetQubitState(Zero, q2);
        
    
        // Display the times that |0> is returned, and times that |1> is returned
        Message($"Q1 - Zeros: {count - numOnesQ1}");
        Message($"Q1 - Ones: {numOnesQ1}");
        Message($"Q2 - Zeros: {count - numOnesQ2}");
        Message($"Q2 - Ones: {numOnesQ2}");
        return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );

    }
}

Q1 - Zeros: 502           
Q1 - Ones: 498       // results will vary
Q2 - Zeros: 502
Q2 - Ones: 498

Les statistiques du premier qubit n’ont pas changé (autant de chances d’avoir Zero que One après la mesure), mais les résultats des mesures du deuxième qubit sont toujours les mêmes que ceux du premier qubit. L’opération CNOT a intriqué les deux qubits de sorte que ce qui arrive à l’un arrive également à l’autre.

Tracer l’histogramme de fréquence

Nous allons visualiser la distribution des résultats obtenus à partir de l’exécution du programme quantique plusieurs fois. L’histogramme de fréquence permet de visualiser la distribution de probabilité de ces résultats.

  1. Sélectionnez Affichage -> Palette de commandes ou appuyez sur Ctrl+Maj+P, puis tapez « histogramme » qui doit faire apparaître l’option : Exécuter leQ# fichier et afficher l’histogramme. Sélectionnez cette option pour ouvrir la fenêtre d’histogramme Q# .

  2. Entrez un certain nombre de tirs pour exécuter le programme, par exemple 100 tirs, puis appuyez sur Entrée. L’histogramme s’affiche dans la Q# fenêtre histogramme.

  3. Chaque barre de l’histogramme correspond à un résultat possible, et sa hauteur représente le nombre de fois où le résultat est observé. Dans ce cas, il existe 50 résultats uniques différents. Notez que pour chaque résultat, les résultats de mesure pour le premier et le deuxième qubit sont toujours les mêmes.

    Capture d’écran de la Q# fenêtre histogramme dans Visual Studio Code.

    Conseil

    Vous pouvez zoomer sur l’histogramme à l’aide de la roulette de défilement de la souris ou d’un mouvement de trackpad. Lorsque vous effectuez un zoom avant, vous pouvez parcourir le graphique en appuyant sur « Alt » pendant le défilement.

  4. Cliquez sur une barre pour afficher le pourcentage de ce résultat.

  5. Cliquez sur l’icône des paramètres en haut à gauche pour afficher les options. Vous pouvez afficher les 10 premiers résultats, les 25 premiers résultats ou tous les résultats. Vous pouvez également trier les résultats de haut à faible, ou bas à élevé.

    Capture d’écran de la Q# fenêtre histogramme dans Visual Studio Code montrant comment afficher les paramètres.

Étapes suivantes

Explorez les autres tutoriels Q# :