Esercitazione: Esplorare l'entanglement quantistico con Q#

Questa esercitazione illustra come scrivere un Q# programma che modifica e misura qubit e illustra gli effetti della sovrapposizione e dell'entanglement. Si preparano due qubit in uno stato quantistico specifico, si apprenderà come operare su qubit con Q# per modificare lo stato e illustrare gli effetti della sovrapposizione e dell'entanglement. Si compila il Q# programma in base al pezzo per introdurre stati, operazioni e misurazioni qubit.

Nota

Microsoft Quantum Development Kit (QDK classico) non sarà più supportato dopo il 30 giugno 2024. Se si è uno sviluppatore QDK esistente, è consigliabile passare al nuovo Kit di sviluppo quantistico di Azure (QDK moderno) per continuare a sviluppare soluzioni quantistiche. Per altre informazioni, vedere Eseguire la Q# migrazione del codice a QDK moderno.

Ecco alcuni concetti chiave da comprendere prima di iniziare:

  • Mentre i bit classici contengono un singolo valore binario come 0 o 1, lo stato di un qubit può essere una sovrapposizione di due stati quantistici, 0 e 1. A ogni stato quantico possibile è associata un'ampiezza di probabilità.
  • L'atto di misurare un qubit produce un risultato binario con una certa probabilità e modifica lo stato del qubit fuori dalla sovrapposizione.
  • Più qubit possono essere intangibili in modo che non possano essere descritti in modo indipendente tra loro. Ciò significa che qualsiasi cosa accada a un qubit in una coppia in correlazione (entanglement) accade anche all'altro qubit.

In questa esercitazione si apprenderà come:

  • Q# Create operazioni per inizializzare un qubit in uno stato desiderato.
  • Posizionare un qubit in sovrapposizione.
  • Mettere in correlazione una coppia di qubit.
  • Misurare un qubit e osservare i risultati.

Suggerimento

Per accelerare il percorso di calcolo quantistico, vedere Codice con Azure Quantum, una funzionalità univoca del sito Web di Azure Quantum. In questo caso, è possibile eseguire esempi predefiniti Q# o programmi personalizzati Q# , generare nuovo Q# codice dai prompt, aprire ed eseguire il codice in VS Code per il Web con un clic e porre a Copilot eventuali domande sul calcolo quantistico.

Prerequisiti

Per eseguire l'esempio di codice in Copilot per Azure Quantum, è necessario:

  • Un account di posta elettronica Microsoft (MSA).

Per altre informazioni sul Copilot, vedere Esplorare Azure Quantum.

Inizializzare un qubit in uno stato noto

Il primo passaggio consiste nel definire un'operazione Q# che inizializzerà un qubit su uno stato noto. Può essere chiamato per impostare un qubit su uno stato classico, ovvero, quando misurato, restituisce Zero il 100% del tempo o restituisce One il 100% del tempo. La misurazione di un qubit restituisce un tipo Result, che può avere solo un Q# valore di Zero o One.

Aprire Copilot per Azure Quantum e copiare il codice seguente nella finestra dell'editor di codice. Non fare clic su Esegui ancora; si eseguirà il codice più avanti nell'esercitazione.

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

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

L'esempio di codice introduce due operazioni standard, M e X, che trasformano lo stato di un qubit.

L'operazione SetQubitState:

  1. Accetta due parametri: un tipo Result, denominato desired, che rappresenta lo stato desiderato per il qubit in (Zero o One) e un tipo Qubit.
  2. Esegue un'operazione di misurazione, M, che misura lo stato del qubit (Zero o One) e confronta il risultato con il valore specificato in desired.
  3. Se la misura non corrisponde al valore confrontato, esegue un'operazione X che capovolge lo stato del qubit in cui le probabilità che una misura restituisca Zero e One sono invertite. In questo modo, SetQubitState inserisce sempre il qubit di destinazione nello stato desiderato.

Scrivere un'operazione di test per testare lo stato di Bell

Successivamente, per illustrare l'effetto dell'operazione SetQubitState, creare un'altra operazione denominata TestBellState. Questa operazione allocherà due qubit, chiamare SetQubitState per impostare il primo qubit su uno stato noto e quindi misurare i qubit per visualizzare i risultati.

Copiare il codice seguente nella finestra dell'editor di codice, sotto l'operazione 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 );

}

Nel codice le count variabili e initial sono impostate rispettivamente su 1000 e One . In questo modo si inizializza il primo qubit in One e si misura ogni qubit 1000 volte.

L'operazione TestBellState:

  1. Imposta le variabili per il contatore e lo stato qubit iniziale.
  2. Chiama l'istruzione use per inizializzare due qubit.
  3. Esegue cicli per count iterazioni. Per ogni ciclo
    1. Chiama SetQubitState per impostare un valore initial specificato sul primo qubit.
    2. Chiama SetQubitState di nuovo per impostare il secondo qubit su uno stato Zero.
    3. Usa l'operazione M per misurare ogni qubit.
    4. Archivia il numero di misure per ogni qubit che restituisce One.
  4. Al termine del ciclo, chiama di nuovo SetQubitState per reimpostare i qubit su uno stato noto (Zero) per consentire ad altri di allocare i qubit in uno stato noto. Questo passaggio è richiesto dall'istruzione use.
  5. Infine, usa la Message funzione per stampare i risultati nelle finestre di output copilot prima di restituire i risultati.

Eseguire il codice in Copilot per Azure Quantum

Prima di passare alle procedure per la sovrapposizione e l'entanglement, è possibile testare il codice fino a questo punto per visualizzare l'inizializzazione e la misurazione dei qubit.

Per eseguire il codice come programma autonomo, il Q# compilatore nel Copilot deve conoscere dove avviare il programma. Questa operazione viene eseguita nel Q# file aggiungendo un'operazione @EntryPoint() precedente direttamente all'operazione che si vuole eseguire prima. Ad esempio, in questo caso è l'operazione TestBellState .

Nota

@EntryPoint() è necessario solo per i programmi Q# autonomi. Quando si esegue un programma in Jupyter Notebooks o si chiama un Q# programma da un Q# file host Python, non è necessario e genera un errore se incluso.

Aggiungere immediatamente l'operazione prima TestBellState dell'operazione e il @EntryPoint()Q# programma fino a questo punto dovrebbe essere simile al seguente:

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

    }
}

Copiare e incollare l'esempio di codice completo nella finestra Codice Copilot per Azure Quantum , impostare la diapositiva per il numero di colpi su "1" e fare clic su Esegui. I risultati vengono visualizzati nell'istogramma e nei campi Risultati .

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

Poiché i qubit non sono ancora stati manipolati, hanno mantenuto i valori iniziali: il primo qubit restituisce One ogni volta e il secondo qubit restituisce Zero.

Se si modifica il valore di initial in Zero e si esegue di nuovo il programma, si dovrebbe osservare che il primo qubit restituisce Zero anche ogni volta.

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

Posizionare un qubit in sovrapposizione

Attualmente, i qubit nel programma sono tutti in uno stato classico, ovvero sono 1 o 0. Questo è noto perché il programma inizializza i qubit su uno stato noto e non sono stati aggiunti processi per modificarli. Prima di incorporare i qubit, si metterà il primo qubit in uno stato di sovrapposizione, dove una misurazione del qubit restituirà Zero ~50% del tempo e One ~50% del tempo. Concettualmente, il qubit può essere considerato come avere una probabilità uguale di misurare Zero o One.

Per inserire un qubit in sovrapposizione, Q# fornisce l'operazione H, o Hadamard. Ricordare l'operazione Xdall'inizializzazione di un qubit a una procedura di stato nota in precedenza, che ha capovolto un qubit da 0 a 1 (o viceversa); l'operazione H capovolge il qubit in uno stato di probabilità uguale di Zero o One. Quando viene misurato, un qubit in sovrapposizione deve restituire approssimativamente un numero uguale di risultati Zero e One .

Modificare il codice nell'operazione TestBellState reimpostando il valore iniziale su One e inserendo una riga per l'operazione 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); 
        ...

Ora quando si esegue il programma, è possibile visualizzare i risultati del primo qubit in sovrapposizione.

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

Ogni volta che si esegue il programma, i risultati per il primo qubit variano leggermente, ma saranno vicini al 50% One e al 50% Zero, mentre i risultati per il secondo qubit rimarranno sempre Zero.

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

L'inizializzazione del primo qubit in Zero restituisce risultati simili.

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

Nota

Spostando il dispositivo di scorrimento nel Copilot per Azure Quantum e aumentando il numero di colpi, è possibile vedere come i risultati della sovrapposizione variano leggermente rispetto alla distribuzione dei colpi.

Eseguire l'entanglement di due qubit

Come accennato in precedenza, i qubit correlati tramite entanglement sono connessi in modo che non possano essere descritti in modo indipendente l'uno dall'altro. Ciò significa che qualsiasi operazione venga effettuata su un qubit, si verifica anche nel qubit correlato tramite entanglement. In questo modo è possibile conoscere lo stato risultante di un qubit senza misurarlo, semplicemente misurando lo stato dell'altro qubit. (Questo esempio usa due qubit, ma è anche possibile eseguire l'entanglement di tre o più qubit).

Per abilitare l'entanglement, Q# fornisce l'operazione CNOT, che sta per Controlled-NOT. Il risultato dell'esecuzione di questa operazione su due qubit è l'inversione del secondo qubit se il primo qubit è One.

Aggiungere l'operazione CNOT al programma immediatamente dopo l'operazione H. L'intero programma dovrebbe risultare simile al seguente:

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

    }
}

Ora quando si esegue il programma si dovrebbe visualizzare un aspetto simile al seguente:

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

Si noti che le statistiche per il primo qubit non sono state modificate (esiste ancora una probabilità di ~50/50 di una Zero o One dopo la misurazione), ma i risultati della misurazione per il secondo qubit sono sempre uguali alla misurazione del primo qubit, indipendentemente dal numero di volte in cui si esegue il programma. L'operazione CNOT ha eseguito l'entanglement dei due qubit, così qualsiasi cosa accada a uno di essi, accade anche all'altro.

Prerequisiti

Per sviluppare ed eseguire l'esempio di codice nell'ambiente di sviluppo locale:

Create un nuovo Q# file

  1. Aprire Visual Studio Code e selezionare File > nuovo testo per creare un nuovo file.
  2. Salvare il file come CreateBellStates.qs. Questo file conterrà il Q# codice per il programma.

Inizializzare un qubit in uno stato noto

Il primo passaggio consiste nel definire un'operazione Q# che inizializzerà un qubit su uno stato noto. Questa può essere chiamata per impostare un qubit su uno stato classico, ovvero restituisce Zero il 100% delle volte o restituisce One il 100% delle volte. Zero e One sono valori Q# che rappresentano gli unici due risultati possibili della misura di un qubit.

Aprire CreateBellStates.qs e copiare il codice seguente:

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

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

L'esempio di codice introduce due operazioni standard, M e X, che trasformano lo stato di un qubit.

L'operazione SetQubitState:

  1. Accetta due parametri: un tipo Result, denominato desired, che rappresenta lo stato desiderato per il qubit in (Zero o One) e un tipo Qubit.
  2. Esegue un'operazione di misurazione, M, che misura lo stato del qubit (Zero o One) e confronta il risultato con il valore specificato in desired.
  3. Se la misura non corrisponde al valore confrontato, esegue un'operazione X che capovolge lo stato del qubit in cui le probabilità che una misura restituisca Zero e One sono invertite. In questo modo, SetQubitState inserisce sempre il qubit di destinazione nello stato desiderato.

Scrivere un'operazione di test per testare lo stato di Bell

Successivamente, per illustrare l'effetto dell'operazione SetQubitState, creare un'altra operazione denominata TestBellState. Questa operazione allocherà due qubit, chiamare SetQubitState per impostare il primo qubit su uno stato noto e quindi misurare i qubit per visualizzare i risultati.

Aggiungere l'operazione seguente al file CreateBellStates.qs dopo l'operazione 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 );

}

Nel codice le count variabili e initial sono impostate rispettivamente su 1000 e One . In questo modo si inizializza il primo qubit in One e si misura ogni qubit 1000 volte.

L'operazione TestBellState:

  1. Accetta due parametri: count, il numero di volte in cui eseguire una misurazione e initial, lo stato desiderato per inizializzare il qubit.
  2. Chiama l'istruzione use per inizializzare due qubit.
  3. Esegue cicli per count iterazioni. Per ogni ciclo
    1. Chiama SetQubitState per impostare un valore initial specificato sul primo qubit.
    2. Chiama SetQubitState di nuovo per impostare il secondo qubit su uno stato Zero.
    3. Usa l'operazione M per misurare ogni qubit.
    4. Archivia il numero di misure per ogni qubit che restituisce One.
  4. Al termine del ciclo, chiama di nuovo SetQubitState per reimpostare i qubit su uno stato noto (Zero) per consentire ad altri di allocare i qubit in uno stato noto. Questo passaggio è richiesto dall'istruzione use.
  5. Infine, usa la funzione Message per stampare un messaggio nella console prima di restituire i risultati.

Eseguire il codice

Prima di passare alle procedure per la sovrapposizione e l'entanglement, testare il codice fino a questo punto per visualizzare l'inizializzazione e la misurazione dei qubit.

Questa operazione viene eseguita nel Q# file aggiungendo un'operazione @EntryPoint() precedente direttamente all'esecuzione. Ad esempio, in questo caso è l'operazione TestBellState .

Nota

@EntryPoint() è necessario solo per i programmi Q# autonomi. Quando si esegue un programma in Jupyter Notebooks o si chiama un Q# programma da un Q# file host Python, non è necessario e genera un errore se incluso.

  1. Il file CreateBellStates.qs dovrà risultare simile al seguente:

    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 );
    
        }
    }
    
  2. Prima di eseguire il programma, è necessario impostare il profilo di destinazione su Senza restrizioni. Selezionare Visualizza -> Tavolozza comandi, cercare QIR, selezionare : Impostare il profilo di destinazione di Azure Quantum QIR e quindi selezionareQ#Q#: senza restrizioni.

    Nota

    Se il profilo di destinazione non è impostato su Senza restrizioni, viene visualizzato un errore quando si esegue il programma.

  3. Per eseguire il programma, selezionare Esegui Q# file dall'icona di riproduzione a discesa nella parte superiore destra, fare clic su Esegui dall'elenco dei comandi sotto @EntryPoint()o premere CTRL+F5. Il programma esegue l'operazione o la funzione contrassegnata con l'attributo @EntryPoint() nel simulatore predefinito.

  4. L'output viene visualizzato nella console di debug.

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

    Poiché i qubit non sono ancora stati manipolati, hanno mantenuto i valori iniziali: il primo qubit restituisce One ogni volta e il secondo qubit restituisce Zero.

  5. Se si modifica il valore di initial in Zero e si esegue di nuovo il programma, si dovrebbe osservare che il primo qubit restituisce Zero anche ogni volta.

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

Suggerimento

Ricordarsi di salvare il file ogni volta che si introduce una modifica al codice prima di eseguirla di nuovo.

Posizionare un qubit in sovrapposizione

Attualmente, i qubit nel programma sono tutti in uno stato classico, ovvero sono 1 o 0. Questo è noto perché il programma inizializza i qubit su uno stato noto e non sono stati aggiunti processi per modificarli. Prima di eseguire l'entanglement dei qubit, si inserirà il primo qubit in uno stato di sovrapposizione, in cui una misurazione del qubit restituirà Zero il 50% delle volte e One il 50% delle volte. A livello concettuale, il qubit può essere considerato a metà tra Zero e One.

Per inserire un qubit in sovrapposizione, Q# fornisce l'operazione H, o Hadamard. Ricordare l'operazione dall'inizializzazione di un qubit a una procedura di stato nota precedente, che ha capovolto un qubit da Zero a One (o viceversa); l'operazione XH capovolge il qubit a metà in uno stato di probabilità uguale di Zero o One. Quando viene misurato, un qubit in sovrapposizione deve restituire approssimativamente un numero uguale di risultati Zero e One.

  1. Modificare il codice nell'operazione TestBellState per includere l'operazione 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); 
                ...
    
  2. A questo punto, quando si esegue il programma, è possibile visualizzare i risultati del primo qubit in sovrapposizione:

    Q1 - Zeros: 523            // results will vary
    Q1 - Ones: 477
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  3. Ogni volta che si esegue il programma, i risultati per il primo qubit variano leggermente, ma saranno vicini al 50% One e al 50% Zero, mentre i risultati per il secondo qubit rimarranno sempre Zero.

    Q1 - Zeros: 510           
    Q1 - Ones: 490
    Q2 - Zeros: 1000
    Q2 - Ones: 0
    
  4. L'inizializzazione del primo qubit in Zero restituisce risultati simili.

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

Eseguire l'entanglement di due qubit

Come accennato in precedenza, i qubit correlati tramite entanglement sono connessi in modo che non possano essere descritti in modo indipendente l'uno dall'altro. Ciò significa che qualsiasi operazione venga effettuata su un qubit, si verifica anche nel qubit correlato tramite entanglement. In questo modo è possibile conoscere lo stato risultante di un qubit senza misurarlo, semplicemente misurando lo stato dell'altro qubit. (Questo esempio usa due qubit, ma è anche possibile eseguire l'entanglement di tre o più qubit).

Per abilitare l'entanglement, Q# fornisce l'operazione CNOT, che sta per Controlled-NOT. Il risultato dell'esecuzione di questa operazione su due qubit è l'inversione del secondo qubit se il primo qubit è One.

  1. Aggiungere l'operazione CNOT al programma immediatamente dopo l'operazione H. L'intero programma dovrebbe risultare simile al seguente:

    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
    

Le statistiche per il primo qubit non sono cambiate (probabilità 50/50 di Zero o One dopo la misurazione), ma i risultati della misurazione per il secondo qubit sono sempre gli stessi della misura del primo qubit. L'operazione CNOT ha eseguito l'entanglement dei due qubit, così qualsiasi cosa accada a uno di essi, accade anche all'altro.

Tracciare l'istogramma di frequenza

Verrà visualizzata la distribuzione dei risultati ottenuti dall'esecuzione del programma quantistico più volte. L'istogramma di frequenza consente di visualizzare la distribuzione della probabilità di questi risultati.

  1. Selezionare Visualizza -> Tavolozza comandi oppure premere CTRL+MAIUSC+P e digitare "istogramma" che deve visualizzare il file : Eseguire il file e visualizzare l'opzioneQ# istogramma. È anche possibile fare clic su Istogram nell'elenco dei comandi seguenti @EntryPoint(). Selezionare questa opzione per aprire la Q# finestra istogramma.

  2. Immettere un numero di colpi per eseguire il programma, ad esempio 100 colpi e premere INVIO. L'istogramma visualizzerà nella finestra dell'istogramma Q# .

  3. Ogni barra nell'istogramma corrisponde a un risultato possibile e la relativa altezza rappresenta il numero di volte in cui viene osservato il risultato. In questo caso, ci sono 50 risultati univoci diversi. Si noti che per ogni risultato i risultati della misurazione per il primo e il secondo qubit sono sempre uguali.

    Screenshot della Q# finestra istogramma in Visual Studio Code.

    Suggerimento

    È possibile ingrandire l'istogramma usando la rotellina di scorrimento del mouse o un movimento del trackpad. Quando si esegue lo zoom avanti, è possibile visualizzare il grafico premendo "ALT" durante lo scorrimento.

  4. Fare clic su una barra per visualizzare la percentuale di tale risultato.

  5. Fare clic sull'icona delle impostazioni in alto a sinistra per visualizzare le opzioni. È possibile visualizzare i primi 10 risultati, i primi 25 risultati o tutti i risultati. È anche possibile ordinare i risultati da alto a basso o basso a alto.

    Screenshot della Q# finestra istogramma in Visual Studio Code che mostra come visualizzare le impostazioni.

Passaggi successivi

Esplorare altre esercitazioni su Q#: