Condividi tramite


Esercitazione: Esplorare l'entanglement quantistico con Q#

In questa esercitazione si scrive un Q# programma che modifica e misura i qubit e illustra gli effetti della sovrapposizione e dell'entanglement. Si preparano due qubit in uno stato quantistico specifico, si apprenderà come operare sui qubit con Q# per modificarne lo stato e dimostrare gli effetti della sovrapposizione e dell'entanglement. Si compila il Q# programma a fasi per introdurre stati, operazioni e misurazioni del qubit.

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 misurazione di un qubit produce un risultato binario con una certa probabilità e modifica lo stato del qubit fuori dalla sovrapposizione.
  • Più qubit possono essere entangled in modo che non possano essere descritti in modo indipendente l'uno dall'altro. Ciò significa che qualsiasi cosa accada a un qubit in una coppia in correlazione (entanglement) accade anche all'altro qubit.

Questa esercitazione illustra come:

  • Creare Q# 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. Qui è possibile eseguire esempi predefiniti Q# o programmi personalizzati Q# , generare nuovo Q# codice dalle richieste, aprire ed eseguire il codice in VS Code per il Web con un solo 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 su Copilot, vedere Esplorare Azure Quantum.

Inizializzare un qubit in uno stato noto

Il primo passaggio consiste nel definire un'operazione Q# che inizializza un qubit su uno stato noto. Questa operazione può essere chiamata per impostare un qubit su uno stato classico, vale a dire che, se misurato, restituisce Zero il 100% dell'ora o restituisce One il 100% del tempo. La misurazione di un qubit restituisce un Q# tipo , che può avere solo un valore o ResultZero.One

Aprire Copilot per Azure Quantum e copiare il codice seguente nella finestra dell'editor di codice. Non selezionare ancora Esegui; il codice verrà eseguito più avanti nell'esercitazione.

import Microsoft.Quantum.Intrinsic.*;
import 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 bell

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

Copiare il codice seguente nella finestra dell'editor di codice, sotto l'operazione SetQubitState .

operation Main() : (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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 vengono 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 Main:

  1. Imposta le variabili per il contatore e lo stato del 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. La reimpostazione è richiesta dall'istruzione use .
  5. Infine, usa la Message funzione per stampare i risultati nelle finestre di output di 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 in Copilot deve sapere dove avviare il programma. Poiché non viene specificato alcuno spazio dei nomi, il compilatore riconosce il punto di ingresso predefinito come Main operazione. Per altre informazioni, vedere Progetti e spazi dei nomi impliciti.

Il Q# programma fino a questo punto dovrebbe essere simile al seguente:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

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

operation Main() : (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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 );

}

Copia e incolla l'esempio di codice completo nella finestra del codice di Copilot per Azure Quantum, imposta il cursore per il numero di esecuzioni su "1" e seleziona 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, è necessario osservare che il primo qubit restituisce Zero anche ogni volta.

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

Suggerimento

Selezionare CTRL-Z o Modifica > Annulla e salvare il file ogni volta che si introduce una modifica di test al codice prima di eseguirlo 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 incorporare i qubit, inserire il primo qubit in uno stato di sovrapposizione, in cui una misurazione del qubit restituisce 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. Richiamare l'operazione X dall'inizializzazione di un qubit a una procedura di stato nota precedente, che ha capovolto un qubit da 0 a 1 (o viceversa). L'operazione H capovolge il qubit a metà in uno stato di uguale probabilità 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 Main 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 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 rimangono Zero sempre.

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 in Copilot per Azure Quantum e aumentando il numero di colpi, è possibile vedere come i risultati della sovrapposizione variano leggermente rispetto alla distribuzione degli scatti.

Eseguire l'entanglement di due qubit

Come accennato in precedenza, i qubit in 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:

import Microsoft.Quantum.Intrinsic.*;
import Microsoft.Quantum.Canon.*;

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

operation Main() : (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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 dovrebbe essere visualizzato 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 circa 50/50 di una Zero o dopo la One 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:

Creare un nuovo Q# file

  1. Aprire Visual Studio Code e selezionare File > Nuovo file di 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 inizializza un qubit su uno stato noto. Questa operazione può essere chiamata per impostare un qubit su uno stato classico, ovvero restituisce Zero il 100% dell'ora o restituisce One il 100% del tempo. 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:

import Microsoft.Quantum.Intrinsic.*;
import 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 bell

Successivamente, per illustrare l'effetto dell'operazione SetQubitState, creare un'altra operazione denominata Main. Questa operazione alloca due qubit, chiama SetQubitState per impostare il primo qubit su uno stato noto e quindi misura i qubit per visualizzare i risultati.

Aggiungere l'operazione seguente al file CreateBellStates.qs dopo l'operazione SetQubitState:

operation Main() : (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 {
            numOnesQ1 += 1;
        }
        if resultQ2 == One {
            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 vengono impostate rispettivamente su 1000 e One . Questo passaggio inizializza il primo qubit in One e misura ogni qubit 1000 volte.

L'operazione Main:

  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. La reimpostazione del qubit è richiesta 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.

Per eseguire il codice come programma autonomo, il Q# compilatore deve sapere dove avviare il programma. Poiché non viene specificato alcuno spazio dei nomi, il compilatore riconosce il punto di ingresso predefinito come Main operazione. Per altre informazioni, vedere Progetti e spazi dei nomi impliciti.

  1. Il CreateBellStates.qs file fino a questo punto dovrebbe essere simile al seguente:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
    operation SetQubitState(desired : Result, target : Qubit) : Unit {
        if desired != M(target) {
            X(target);
        }
    }
    
    operation Main() : (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 {
                numOnesQ1 += 1;
            }
            if resultQ2 == One {
                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, assicurarsi che il profilo di destinazione sia impostato su Senza restrizioni. Selezionare Visualizza -> Riquadro comandi, cercare QIR, selezionare Q#: Impostare il profilo di destinazione di Azure Quantum QIR e quindi selezionare 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 file dall'elenco a discesa dell'icona di riproduzione in alto a destra, selezionare Q# nell'elenco dei comandi precedenti all'operazione oppure premere CTRL+F5.Main Il programma esegue l'operazione Main 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, è necessario osservare che il primo qubit restituisce Zero anche ogni volta.

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

Suggerimento

Selezionare CTRL-Z o Modifica > Annulla e salvare il file ogni volta che si introduce una modifica di test al codice prima di eseguirlo 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 incorporare i qubit, inserire il primo qubit in uno stato di sovrapposizione, in cui una misurazione del qubit restituisce Zero il 50% del tempo e One il 50% del tempo. 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. Richiamare l'operazione X 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 H capovolge il qubit a metà strada in uno stato di uguale probabilità 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 Main 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 rimangono Zero sempre.

    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 in 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:

    import Microsoft.Quantum.Intrinsic.*;
    import Microsoft.Quantum.Canon.*;
    
        operation SetQubitState(desired : Result, target : Qubit) : Unit {
            if desired != M(target) {
                X(target);
            }
        }
    
    operation Main() : (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 {
                numOnesQ1 += 1;
            }
            if resultQ2 == One {
                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
    Result: "(502, 498, 502, 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 incastrato i due qubit, in modo che ciò che accade a uno di essi, accade all'altro.

Tracciare l'istogramma di frequenza

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

  1. Selezionare Visualizza -> Riquadro comandi oppure premere CTRL+MAIUSC+P e digitare "istogramma" che dovrebbe visualizzare il file : Esegui file e visualizzare l'opzione Q#istogramma. È anche possibile selezionare Istogramma nell'elenco dei comandi precedenti Main. Selezionare questa opzione per aprire la finestra dell'istogramma Q# .

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

  3. Ogni barra nell'istogramma corrisponde a un possibile risultato e l'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 del mouse o un movimento del trackpad. Quando si esegue lo zoom avanti, è possibile eseguire la panoramica del grafico premendo ALT durante lo scorrimento.

  4. Selezionare una barra per visualizzare la percentuale di tale risultato.

  5. Selezionare l'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 alta a bassa o bassa a alta.

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

Esplorare altre esercitazioni su Q#:

  • L'algoritmo di ricerca di Grover mostra come scrivere un Q# programma che usa l'algoritmo di ricerca di Grover.
  • Quantum Fourier Transform illustra come scrivere un Q# programma che punta direttamente a qubit specifici.
  • I kata quantistici sono esercitazioni e esercizi di programmazione auto-ritmo volti a insegnare contemporaneamente gli elementi del calcolo quantistico e Q# della programmazione.