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.
- 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, 0 o 1, con una certa probabilità, e modifica lo stato del qubit fuori sovrapposizione.
- Più qubit possono essere correlati 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 prevede la preparazione di due qubit in uno stato quantico specifico, per imparare come operare sui qubit con Q# per modificarne lo stato e mostrare gli effetti della sovrapposizione e dell'entanglement. Il programma Q# verrà compilato un'unità alla volta per introdurre stati, operazioni e misurazioni dei qubit.
Prerequisiti
Per completare questa esercitazione, è necessario disporre di:
- Un account Azure con una sottoscrizione attiva. Se non si dispone di un account Azure, registrarsi gratuitamente e iscriversi per una sottoscrizione con pagamento in base al consumo.
- Un'area di lavoro di Azure Quantum. Per altre informazioni, vedere Creare un'area di lavoro di Azure Quantum.
In questa esercitazione si apprenderà come:
- Creare operazioni Q# per misurare e inizializzare un qubit allo stato desiderato.
- Creare qubit e testare il programma.
- Posizionare un qubit in sovrapposizione.
- Mettere in correlazione una coppia di qubit.
Creare un nuovo notebook nell'area di lavoro
- Accedere al portale di Azure e selezionare l'area di lavoro creata nel passaggio precedente.
- A sinistra selezionare Notebook.
- Fare clic su Notebook personali e quindi su Aggiungi nuovo.
- In Tipo di kernel selezionare IQ#.
- Digitare un nome per il file, ad esempio Entanglement.ipynb, e fare clic su Crea file.
Quando si apre il nuovo notebook, viene creato automaticamente il codice per la prima cella, in base alle informazioni sulla sottoscrizione e sull'area di lavoro.
%azure.connect "/subscriptions/\<subscription ID>/\<resource group>/providers/Microsoft.Quantum/Workspaces/\<workspace>" \<location>
Nota
%azure.connect è un comando magic IQ#, un set di comandi che semplificano le attività in Jupyter Notebook.
Se si esegue questa cella, verrà eseguita l'autenticazione nella sottoscrizione e verrà visualizzato un elenco dei provider disponibili e delle relative destinazioni.
Inizializzare un qubit usando la misurazione
Il primo passaggio consiste nel definire un'operazione Q# che inizializza un qubit su uno stato noto. Viene utilizzata 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.
Fare clic su + Codice per aggiungere una nuova cella e aggiungere il codice seguente:
operation SetQubitState(desired : Result, target : Qubit) : Unit {
if desired != M(target) {
X(target);
}
}
Nota
Gli spazi dei nomi Microsoft.Quantum.Intrinsic
e Microsoft.Quantum.Canon
, usati dalle operazioni in questo codice, vengono aperti automaticamente in ogni cella di un notebook Azure Quantum.
L'esempio di codice introduce due operazioni standard, M
e X
, che trasformano lo stato di un qubit.
L'operazione SetQubitState
:
- Accetta due parametri: un tipo
Result
, denominatodesired
, che rappresenta lo stato desiderato per il qubit (0 o 1) e un tipoQubit
. - Esegue un'operazione di misurazione,
M
, che misura lo stato del qubit (Zero
oOne
) e confronta il risultato con il valore specificato indesired
. - 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 restituiscaZero
eOne
sono invertite. In questo modo,SetQubitState
inserisce sempre il qubit di destinazione nello stato desiderato.
Testare la misura
Successivamente, per illustrare l'effetto dell'operazione SetQubitState
, creare un'altra operazione denominata TestBellState
.
Aggiungere un'altra nuova cella e aggiungere il codice seguente:
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// 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':
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return number of |0> states, number of |1> states
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
L'operazione TestBellState
:
- Accetta due parametri:
count
, il numero di volte in cui eseguire una misurazione einitial
, lo stato desiderato per inizializzare il qubit. - Chiama l'istruzione
use
per inizializzare due qubit. - Esegue cicli per
count
iterazioni. Per ogni ciclo- Chiama
SetQubitState
per impostare un valoreinitial
specificato sul primo qubit. - Chiama
SetQubitState
di nuovo per impostare il secondo qubit su uno statoZero
. - Usa l'operazione
M
per misurare ogni qubit. - Archivia il numero di misure per ogni qubit che restituisce
One
.
- Chiama
- 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'istruzioneuse
. - Infine, usa la funzione
Message
per visualizzare un messaggio nella console prima di restituire i risultati.
Testare 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 l'operazione TestBellState
, usare il comando magic %simulate
per chiamare il simulatore di stato completo Azure Quantum. È necessario specificare gli argomenti count
e initial
, ad esempio count=1000
e initial=1
. In questo modo si inizializza il primo qubit in One
e si misura ogni qubit 1000 volte. Aggiungere una nuova cella con il comando seguente e fare clic su Esegui tutto:
%simulate TestBellState count=1000 initial=1
e si dovrà osservare l'output seguente:
q1:Zero, One q2:Zero, One
(0, 1000, 1000, 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 esegue di nuovo la cella con initial=0
, si dovrebbe osservare che anche il primo qubit restituisce Zero
ogni volta.
%simulate TestBellState count=1000 initial=0
q1:Zero, One q2:Zero, One
(1000, 0, 1000, 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 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
e il 50% delle volte. Concettualmente, il qubit può essere pensato come in una combinazione lineare di tutti gli stati tra Zero
e One
.
Per inserire un qubit in sovrapposizione, Q# fornisce l'operazione H
, o Hadamard. Richiamare l'operazione X
dalla procedura Inizializzare un qubit usando la misurazione precedente, che ha capovolto un qubit da 0 a 1 (o viceversa). L'operazione H
capovolge il qubit a metà strada in uno stato di probabilità uguali pari a 0 o 1. Quando viene misurato, un qubit in sovrapposizione deve restituire approssimativamente un numero uguale di risultati Zero
e One
.
Nella cella precedente con TestBellState
, aggiungere l'operazione H
all'interno del ciclo for
:
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);
Inizializzare di nuovo il qubit su 1 nel comando %simulate
e fare clic su Esegui tutti. È possibile visualizzare i risultati del primo qubit in sovrapposizione:
%simulate TestBellState count=1000 initial=1
q1:Zero, One q2:Zero, One
(523, 477, 1000, 0) // results will vary
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:Zero/One Q2:Zero/One
(510, 490, 1000, 0)
L'inizializzazione del primo qubit in Zero
restituisce risultati simili.
%simulate TestBellState count=1000 initial=0
Q1:Zero/One Q2:Zero/One
(504, 496, 1000, 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 eseguita su un qubit in una coppia in correlazione (entanglement) viene eseguita anche sull'altro qubit. 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 ciclo for
immediatamente dopo l'operazione H
. L'aspetto dell'operazione TestBellState
dovrebbe essere simile al seguente.
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// allocate the qubits
use (q1, q2) = (Qubit(), Qubit());
for test in 1..count {
SetQubitState(initial, q1);
SetQubitState(Zero, q2);
H(q1);
CNOT(q1, q2); // added CNOT operation
// measure each qubit
let resultQ1 = M(q1);
let resultQ2 = M(q2);
// Count the number of 'Ones':
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return number of |0> states, number of |1> states
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
Fare clic su Esegui tutti per eseguire l'operazione aggiornata. Verrà visualizzato:
Q1:Zero/One Q2:Zero/One
(502, 498, 502, 498) // actual results will vary
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 misurazione del primo qubit, indipendentemente dall'inizializzazione del qubit. L'operazione CNOT
ha eseguito l'entanglement dei due qubit, così qualsiasi cosa accada a uno di essi, accade anche all'altro.
Prerequisiti
- Installare Quantum Development Kit usando il linguaggio di programmazione e l'ambiente di sviluppo preferiti.
- Se QDK è già installato, assicurarsi di aver eseguito l'aggiornamento alla versione più recente.
- Creare un progetto Q# denominato Bell per un'applicazione Q# o un programma host C#. In alternativa, è possibile eseguire il codice Q# direttamente in Juptyer Notebooks o da un programma host Python.
In questa esercitazione si apprenderà come
- Creare operazioni Q# per misurare e inizializzare un qubit allo stato desiderato.
- Creare qubit e testare il programma.
- Posizionare un qubit in sovrapposizione.
- Mettere in correlazione una coppia di qubit.
Inizializzare un qubit usando la misura
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.
Nel progetto, sostituire quindi il contenuto di Program.qs
con 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
:
- Accetta due parametri: un tipo
Result
, denominatodesired
, che rappresenta lo stato desiderato per il qubit (0 o 1) e un tipoQubit
. - Esegue un'operazione di misurazione,
M
, che misura lo stato del qubit (Zero
oOne
) e confronta il risultato con il valore specificato indesired
. - 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 restituiscaZero
eOne
sono invertite. In questo modo,SetQubitState
inserisce sempre il qubit di destinazione nello stato desiderato.
Testare la misura
Successivamente, per illustrare l'effetto dell'operazione SetQubitState
, creare un'altra operazione denominata TestBellState
.
Aggiungere l'operazione seguente al file Program.qs
dopo l'operazione SetQubitState
:
operation TestBellState(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// 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' we saw:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return times we saw |0>, times we saw |1>
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
L'operazione TestBellState
:
- Accetta due parametri:
count
, il numero di volte in cui eseguire una misurazione einitial
, lo stato desiderato per inizializzare il qubit. - Chiama l'istruzione
use
per inizializzare due qubit. - Esegue cicli per
count
iterazioni. Per ogni ciclo- Chiama
SetQubitState
per impostare un valoreinitial
specificato sul primo qubit. - Chiama
SetQubitState
di nuovo per impostare il secondo qubit su uno statoZero
. - Usa l'operazione
M
per misurare ogni qubit. - Archivia il numero di misure per ogni qubit che restituisce
One
.
- Chiama
- 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'istruzioneuse
. - Infine, usa la funzione
Message
per stampare un messaggio nella console prima di restituire i risultati.
Eseguire il codice dal prompt dei comandi
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 compilatore Q# deve sapere dove avviare il programma quando si esegue il comando dotnet run
. Questa operazione viene eseguita nel file Q# aggiungendo un elemento @EntryPoint()
che precede direttamente l'operazione che si vuole eseguire, in questo caso l'operazione TestBellState
.
Nota
@EntryPoint()
è necessario solo per i programmi Q# autonomi. Quando si esegue un programma Q# in Jupyter Notebook o si chiama un programma Q# da un file host Python o .NET, non è necessario e genera un errore se incluso.
Il file program.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(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// 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' we saw:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return times we saw |0>, times we saw |1>
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
}
Per eseguire il programma, è necessario specificare gli argomenti count
e initial
dal prompt dei comandi. Ad esempio, --count 1000
e --initial One
inizializzano il primo qubit su One
e misurano ogni qubit 1000 volte. Eseguire il comando seguente:
dotnet run --count 1000 --initial One
si dovrebbe visualizzare l'output seguente:
Q1:Zero/One Q2:Zero/One
(0, 1000, 1000, 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 lo si esegue con --initial Zero
, si dovrebbe osservare che anche il primo qubit restituisce Zero
ogni volta.
dotnet run --count 1000 --initial Zero
Q1:Zero/One Q2:Zero/One
(1000, 0, 1000, 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 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. Richiamare l'operazione X
dalla procedura Inizializzare un qubit usando la misurazione precedente, che ha capovolto un qubit da 0 a 1 (o viceversa). L'operazione H
capovolge il qubit a metà strada in uno stato di probabilità uguali pari a 0 o 1. Quando viene misurato, un qubit in sovrapposizione deve restituire approssimativamente un numero uguale di risultati Zero
e One
.
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);
A questo punto, quando si esegue il programma, è possibile visualizzare i risultati del primo qubit in sovrapposizione:
dotnet run --count 1000 --initial One
Q1:Zero/One Q2:Zero/One
(523, 477, 1000, 0) // results will vary
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
.
dotnet run --count 1000 --initial One
Q1:Zero/One Q2:Zero/One
(510, 490, 1000, 0)
L'inizializzazione del primo qubit in Zero
restituisce risultati simili.
dotnet run --count 1000 --initial Zero
Q1:Zero/One Q2:Zero/One
(504, 496, 1000, 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
.
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(count : Int, initial : Result) : (Int, Int, Int, Int) {
mutable numOnesQ1 = 0;
mutable numOnesQ2 = 0;
// 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' we saw:
if resultQ1 == One {
set numOnesQ1 += 1;
}
if resultQ2 == One {
set numOnesQ2 += 1;
}
}
// reset the qubits
SetQubitState(Zero, q1);
SetQubitState(Zero, q2);
// Return times we saw |0>, times we saw |1>
Message("q1:Zero, One q2:Zero, One");
return (count - numOnesQ1, numOnesQ1, count - numOnesQ2, numOnesQ2 );
}
}
Ora, quando si esegue il programma:
dotnet run --count 1000 --initial One
Q1:Zero/One Q2:Zero/One
(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 eseguito l'entanglement dei due qubit, così qualsiasi cosa accada a uno di essi, accade anche all'altro.
Passaggi successivi
Continuare a esplorare altri algoritmi quantistici e tecniche:
- L'esercitazione Implementare l'algoritmo di ricerca di Grover illustra come scrivere un programma Q# che usa l'algoritmo di ricerca di Grover per risolvere un problema di colorazione del grafo.
- L'esercitazione Scrivere e simulare programmi a livello di qubit in Q# illustra come scrivere un programma Q# che operi direttamente su qubit specifici.
- Quantum Katas è una serie di esercitazioni ed esercizi di programmazione autogestiti basati su Jupyter Notebook per insegnare i concetti del calcolo quantistico e allo stesso tempo la programmazione Q#.