Vai al contenuto principale

Inizia con Qiskit in classe

Per questo modulo di Qiskit in classe, gli studenti devono disporre di un ambiente Python funzionante con i seguenti pacchetti installati:

  • qiskit v2.1.0 o più recente
  • qiskit-ibm-runtime v0.40.1 o più recente
  • qiskit-aer v0.17.0 o più recente
  • qiskit.visualization
  • numpy
  • pylatexenc

Per configurare e installare i pacchetti sopra indicati, consulta la guida Installa Qiskit. Per eseguire job su computer quantistici reali, gli studenti dovranno creare un account IBM Quantum® seguendo i passaggi della guida Configura il tuo account IBM Cloud®.

Questo modulo è stato testato e ha utilizzato 2 secondi di tempo QPU su un processore Heron v2. Questa è solo una stima. L'utilizzo effettivo può variare.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Uncomment and modify this line as needed to install dependencies
#!pip install 'qiskit>=2.1.0' 'qiskit-ibm-runtime>=0.40.1' 'qiskit-aer>=0.17.0' 'numpy' 'pylatexenc'

Introduzione​

Nei moduli di Qiskit in classe, avrai l'opportunità di usare un computer quantistico per esplorare vari concetti in campi affini al calcolo quantistico, come la meccanica quantistica, l'informatica, la chimica e altro ancora. Questo modulo è un prerequisito per gli altri: introduce i fondamenti del calcolo quantistico e come usare Qiskit per eseguire circuiti quantistici.

Prima ti daremo una breve panoramica di come funziona un computer classico, poi ti mostreremo come questi concetti vengono adattati al paradigma del calcolo quantistico. Infine, ti mostreremo come mettere insieme questi concetti per costruire ed eseguire il tuo primo circuito quantistico.

Computer classici​

Probabilmente conosci già le basi del funzionamento dei computer classici, ma qui evidenzieremo alcune delle caratteristiche principali per poter poi fare un confronto con i computer quantistici.

Le unità base dell'informazione: i bit​

I computer classici elaborano informazioni classiche, e l'unità fondamentale dell'informazione classica è il bit. Un singolo bit può memorizzare la risposta a una domanda "sì/no". Di solito rappresentiamo i due stati binari di un bit come "0" e "1".

Ripasso dei numeri binari​

Combinare i bit ti permette di memorizzare più informazioni. Per esempio, se vuoi memorizzare un numero da 0 a 15, puoi farlo con quattro bit nel modo seguente:

0 = 00004 = 01008 = 100012 = 1100
1 = 00015 = 01019 = 100113 = 1101
2 = 00106 = 011010 = 101014 = 1110
3 = 00117 = 011111 = 101115 = 1111

In generale, per convertire un numero binario di NN bit in un numero familiare in base 10, moltiplica il bit meno significativo (il più a destra) per 20=12^0 = 1, il bit successivo a sinistra per 21=22^1 = 2, poi il successivo per 22=42^2 = 4, e così via, fino al bit più significativo (il più a sinistra), che moltiplichi per 2N−12^{N-1}.

Quindi, ciò significa che NN bit possono trovarsi in uno di 2N2^N possibili stati diversi.

Verifica la tua comprensione​

Leggi le domande di seguito, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Di quanti bit avresti bisogno per rappresentare il numero 86? Scrivi la stringa di bit che codifica questo numero in binario.

Risposta:

Ricorda: NN bit permettono di rappresentare i numeri da 00 a 2N−12^N - 1, quindi con sei bit arriviamo fino a 26−1=632^6 - 1 = 63. Non è abbastanza. Aggiungiamo un altro bit per arrivare fino a 27−1=1272^7 - 1 = 127. Ora scomponiamo 86 in potenze di 2:

86=64+16+4+2=26×1+25×0+24×1+23×0+22×1+21×1+20×0=1010110\begin{aligned} 86 &= 64 + 16 + 4 + 2 \\ &= 2^6 \times 1 + 2^5 \times 0 + 2^4 \times 1 + 2^3 \times 0 + 2^2 \times 1 + 2^1 \times 1 + 2^0 \times 0 \\ &= 1010110 \end{aligned}

Operazioni fondamentali: le porte​

Un computer deve essere in grado di fare qualcosa con i bit per poter, appunto, calcolare. Le porte binarie sono le operazioni che costituiscono i mattoni fondamentali di tutti gli algoritmi e i codici più complessi.

Porta a un bit:​

NOT​

Quando hai un solo bit, c'è un solo modo in cui puoi trasformare il suo stato: invertire lo stato da 0 a 1 o da 1 a 0. Chiamiamo questa operazione la porta "NOT". L'effetto di questa porta — e delle altre porte di cui parleremo di seguito — può essere rappresentato in una cosiddetta "tabella della verità", con colonne per gli stati di ingresso e di uscita dei qubit. La tabella della verità per la porta NOT è:

IngressoUscita
01
10

Porte a più bit:​

AND​

AND è una porta a due bit che prende due bit di ingresso e produce un singolo bit di uscita. Produce 1 se entrambi i bit di ingresso sono 1, altrimenti 0:

IngressoUscita
000
010
100
111

OR​

OR è un'altra porta a due bit con un singolo bit di uscita. Produce 1 se uno qualsiasi dei bit è 1:

IngressoUscita
000
011
101
111

XOR​

XOR sta per "OR esclusivo" ed è simile alla porta OR, ma produce 1 se soltanto uno dei bit di ingresso è 1. Produce 0 se sono entrambi 1 o entrambi 0:

IngressoUscita
000
011
101
110

Misurazioni:​

Di solito, quando si studia il calcolo classico, al processo di lettura dello stato dei bit non viene dedicata molta attenzione. Questo perché, dal punto di vista concettuale, non è molto complesso. Puoi misurare i bit in qualsiasi momento, prima, durante o dopo un calcolo, e ciò non influisce sul risultato. Non è così nel calcolo quantistico, come discuteremo di seguito.

Circuiti:​

Combinando le porte sopra descritte, puoi eseguire qualsiasi tipo di operazione su un computer. Facciamo un semplice esempio: usando le porte AND e XOR, puoi costruire il circuito half-adder, che calcola la somma di due bit. Questo è rappresentato in un diagramma di circuito logico, dove i fili rappresentano i bit e le porte che operano sui bit sono mostrate come simboli sui fili corrispondenti:

Diagramma del circuito classico per il circuito half-adder. Una porta XOR genera il bit di uscita Sum e una porta AND genera il bit di uscita Carry.

Quindi, i due bit vengono copiati e inviati attraverso sia una porta AND che una porta XOR. Il risultato della porta XOR è il "bit di somma" (S), che rimane nella posizione delle unità del numero binario, e il risultato della porta AND è il "bit di riporto" (C), che è il valore della cifra più significativa successiva nel numero binario. Ecco la tabella della verità:

AABBSomma (A⊕BA \oplus B)Riporto (A∧BA \wedge B)
0000
0110
1010
1101

Verifica la tua comprensione​

Leggi le domande di seguito, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Verifica che la tabella della verità di cui sopra fornisca la soluzione corretta per un circuito sommatore. Cioè, per ciascuna delle quattro opzioni di A e B, verifica che A+B=S+2×CA+B=S+2 \times C.

Risposta:

0+0=0+0=0 ✓0+1=1+0=1 ✓1+0=1+0=1 ✓1+1=0+2=2 ✓\begin{aligned} 0+0 &= 0+0 = 0 ~\checkmark \\ 0+1 &= 1+0 = 1 ~\checkmark \\ 1+0 &= 1+0 = 1 ~\checkmark \\ 1+1 &= 0+2 = 2 ~\checkmark \\ \end{aligned}

Computer quantistici​

Bit →\rightarrow qubit​

Così come i bit sono le unità fondamentali dell'informazione classica, i bit quantistici, o "qubit", sono le unità fondamentali dell'informazione quantistica. Come il bit classico, lo stato di un qubit può essere 0 o 1, che di solito denotiamo come ∣0⟩\vert 0\rangle e ∣1⟩\vert 1\rangle. Ma a differenza del bit classico, un bit quantistico può anche trovarsi in una sovrapposizione di entrambi gli stati ∣0⟩\vert 0\rangle e ∣1⟩\vert 1\rangle allo stesso tempo. In generale, un qubit può trovarsi in qualsiasi stato ∣ψ⟩\vert \psi\rangle della forma:

∣ψ⟩=c0∣0⟩+c1∣1⟩\vert \psi\rangle = c_0 \vert 0\rangle + c_1 \vert 1\rangle

dove c0c_0 e c1c_1 sono ampiezze complesse con ∣c0∣2+∣c1∣2=1\vert c_0 \vert ^2+\vert c_1\vert ^2=1.

La fase quantistica​

Poiché c0c_0 e c1c_1 sono complessi, ciascuno può essere scritto come ci=∣ci∣eiϕic_i = \vert c_i\vert e^{i\phi_i} dove ϕi\phi_i è chiamata la fase. Se moltiplichiamo l'intero stato per lo stesso fattore di fase globale, nulla cambia fisicamente — questa si chiama fase globale, e non ha conseguenze osservabili.

Per questa ragione, è convenzione "fattorizzare" eiϕ0e^{i\phi_0}, ottenendo:

∣ψ⟩=∣c0∣∣0⟩+∣c1∣eiϕ∣1⟩\vert \psi\rangle = \vert c_0\vert \vert 0\rangle + \vert c_1\vert e^{i\phi}\vert 1\rangle

dove ϕ=ϕ1−ϕ0\phi = \phi_1-\phi_0 è la fase relativa dello stato quantistico, che ha conseguenze osservabili.

Questa fase svolge un ruolo molto importante nel calcolo quantistico, e ne esplorerai le varie conseguenze nei successivi moduli di Qiskit in classe.

qubit multipli​

Mentre lo stato di più bit può essere semplicemente espresso come una stringa di 0 e 1, lo stato di più qubit diventa un po' più complicato a causa dei principi di sovrapposizione e entanglement.

Ricorda che NN bit possono trovarsi in uno di 2N2^N possibili stati, che vanno dal numero binario 000...000 al 111...111. Ma ora, grazie al principio di sovrapposizione, NN qubit possono trovarsi in una sovrapposizione di tutti questi stati contemporaneamente!

Questo può essere espresso come

ψN=∑i=02N−1ci∣i⟩\psi_N = \sum_{i=0}^{2^N-1} c_i \vert i\rangle

dove, come nel caso classico, lo stato ∣i⟩\vert i\rangle corrisponde allo stato in cui ogni qubit si trova nella giusta combinazione di 0 e 1 per produrre il numero binario ii. Questi sono noti come "stati della base computazionale" del sistema quantistico. Per esempio, uno stato a tre qubit può essere scritto come sovrapposizione dei suoi otto stati della base computazionale:

ψ3=c0∣000⟩+c1∣001⟩+c2∣010⟩+c3∣011⟩+c4∣100⟩+c5∣101⟩+c6∣110⟩+c7∣111⟩\psi_3 = c_0 \vert 000\rangle + c_1 \vert 001\rangle + c_2 \vert 010\rangle + c_3 \vert 011\rangle + c_4 \vert 100\rangle + c_5 \vert 101\rangle + c_6 \vert 110\rangle + c_7 \vert 111\rangle

Ogni qubit nel sistema è indicato con un indice da 00 a N−1N-1. La convenzione è di leggere gli stati dei qubit da destra a sinistra, in modo che lo stato del qubit 00 sia il più a destra e lo stato del qubit N−1N-1 sia il più a sinistra. Questa è nota come notazione "little-endian", e all'inizio può sembrare controintuitiva, poiché siamo abituati a leggere da sinistra a destra.

Verifica la tua comprensione​

Leggi le domande di seguito, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

A prima vista, può sembrare controintuitivo ordinare i qubit da destra a sinistra come nella notazione little-endian, ma in realtà è una cosa molto logica da fare! Spiega perché. (Ricorda la nostra discussione sulla conversione da binario a numero in base 10.)

Risposta:

Se ordiniamo i qubit da destra a sinistra, in modo che il qubit 0 sia il più a destra e il qubit N-1 il più a sinistra, è logico associare il qubit 00 al bit meno significativo, che viene moltiplicato per 202^0, e il qubit N−1N-1 al bit più significativo, che viene moltiplicato per 2N−12^{N-1}.

Entanglement​

Come abbiamo accennato in precedenza, un'altra caratteristica fondamentale dei qubit è che possono essere entangled tra loro. Prendiamo un esempio di stato a due qubit, dove c0=c3=12c_0 = c_3 = \frac{1}{\sqrt{2}} e c1=c2=0c_1 = c_2 = 0:

∣ψ⟩=12(∣00⟩+∣11⟩)\vert \psi\rangle = \frac{1}{\sqrt{2}}(\vert 00\rangle + \vert 11\rangle)

Quindi, lo stato del qubit 0 può essere ∣0⟩\vert 0\rangle o ∣1⟩\vert 1\rangle con uguale probabilità, e lo stesso vale per lo stato del qubit 1. Ma queste probabilità non sono più indipendenti l'una dall'altra. Se troviamo lo stato del qubit 0 essere ∣0⟩\vert 0\rangle, allora sappiamo che anche il qubit 1 sarà in ∣0⟩\vert 0\rangle. Questo vale indipendentemente da quanto lontani siano l'uno dall'altro, motivo per cui l'atto di misurare uno stato entangled è talvolta definito "azione spettrale a distanza".

L'entanglement può assumere anche altre forme. Per esempio, lo stato

∣ψ⟩=12(∣01⟩+∣10⟩)\vert \psi\rangle = \frac{1}{\sqrt{2}}(\vert 01\rangle + \vert 10\rangle)

produce risultati opposti ogni volta: se un qubit viene misurato ∣0⟩\vert 0\rangle, l'altro è garantito di essere trovato nello stato ∣1⟩\vert 1\rangle.

Verifica la tua comprensione​

Leggi le domande di seguito, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Lo stato ∣ψ⟩=∣11⟩\vert \psi\rangle = \vert 11\rangle è entangled? Perché sì o perché no?

Risposta:

Non è entangled. Sebbene i risultati siano sempre gli stessi quando misuri entrambi i qubit, questo è dovuto solo al fatto che ogni qubit è sempre fisso nello stato ∣1⟩\vert 1\rangle. Il risultato della misurazione di un qubit non dipende effettivamente dall'altro — entrambi sono semplicemente sempre ∣1⟩\vert 1\rangle.

In generale, se puoi descrivere lo stato di ciascun qubit separatamente e poi moltiplicarli insieme in questo modo:

∣ψ⟩=∣ψ1⟩∣ψ0⟩\vert \psi\rangle = \vert \psi_1\rangle \vert \psi_0\rangle

Allora è noto come "stato prodotto" e non è entangled.

Notazione vettoriale​

È spesso utile usare vettori e matrici per vedere come lo stato quantistico si trasforma sotto diverse operazioni. In questa rappresentazione, i nostri stati quantistici saranno vettori, e le nostre porte quantistiche (discusse nella sezione successiva) saranno matrici che trasformano i vettori.

Per un singolo qubit, le forme vettoriali degli stati sono scelte come: ∣0⟩=(10)\vert 0\rangle = \begin{pmatrix}1 \\ 0\end{pmatrix} ∣1⟩=(01)\vert 1\rangle = \begin{pmatrix}0 \\ 1\end{pmatrix} In questo modo, uno stato arbitrario ∣ψ⟩=a∣0⟩+b∣1⟩\vert \psi\rangle = a\vert 0\rangle+b\vert 1\rangle può essere scritto come ∣ψ⟩=(ab)\vert \psi\rangle =\begin{pmatrix}a \\ b\end{pmatrix}

Per uno stato generale a nn qubit, avremo bisogno di un vettore di dimensione 2n2^n, con gli stati della base ordinati come ci si aspetta, in ordine binario crescente:

∣0…000⟩=(100⋮0),∣0…001⟩=∣1…110⟩=(0⋮010),∣1…111⟩=(0⋮001)\vert 0 \dots 000\rangle = \begin{pmatrix}1 \\ 0 \\ 0 \\ \vdots \\ 0\end{pmatrix}, \vert 0 \dots 001 \rangle = \vert 1 \dots 110\rangle = \begin{pmatrix}0 \\ \vdots \\ 0 \\ 1 \\ 0\end{pmatrix}, \vert 1 \dots 111 \rangle = \begin{pmatrix}0 \\ \vdots \\ 0 \\ 0\\ 1\end{pmatrix}

Con questa scelta di notazione vettoriale in mente, possiamo introdurre le porte quantistiche necessarie, i loro effetti sugli stati quantistici e le loro forme matriciali.

Verifica la tua comprensione​

Leggi le domande di seguito, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Ci sono quattro stati della base computazionale per un sistema a due qubit. Scrivi ciascuno di essi sia nella notazione ket che in quella vettoriale.

Risposta:

∣00⟩=(1000),∣01⟩=(0100),…,∣10⟩=(0010),∣11⟩=(0001)\vert 00\rangle = \begin{pmatrix}1 \\ 0 \\ 0 \\ 0\end{pmatrix}, \vert 01 \rangle = \begin{pmatrix}0 \\ 1 \\ 0 \\ 0\end{pmatrix}, \dots, \vert 10\rangle = \begin{pmatrix}0 \\ 0 \\ 1 \\ 0\end{pmatrix}, \vert 11 \rangle = \begin{pmatrix}0 \\ 0 \\ 0\\ 1\end{pmatrix}

gate →\rightarrow gate quantistici​

Proprio come i gate classici NOT, AND, OR e XOR possono essere combinati per costruire circuiti classici arbitrari, i gate quantistici svolgono lo stesso ruolo nel quantum computing. Poiché i qubit possiedono proprietà aggiuntive della meccanica quantistica, i gate quantistici sono corrispondentemente più ricchi. Sebbene sia ancora possibile descrivere la loro azione sugli stati di base ∣0⟩|0\rangle e ∣1⟩|1\rangle con una tabella di verità, questo non cattura l'intera immagine. Per i gate quantistici, è spesso più naturale usare una rappresentazione matriciale, poiché essi agiscono anche sulle sovrapposizioni degli stati di base.

Di seguito introdurremo i gate quantistici più comuni e il modo in cui trasformano i qubit con cui interagiscono. Quando applicabile, li collegheremo ai gate classici già noti.

gate a singolo qubit​

gate XX: È l'equivalente quantistico dell'operazione NOT. La sua tabella di verità è identica a quella del gate NOT classico:

IngressoUscita
∣0⟩\vert 0\rangle∣1⟩\vert 1\rangle
∣1⟩\vert 1\rangle∣0⟩\vert 0\rangle

E la rappresentazione matriciale:

X=(0110)X=\begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix}

In Qiskit, la creazione di un circuito con un gate XX è la seguente:

from qiskit import QuantumCircuit

qc = QuantumCircuit(1)
qc.x(0)
qc.draw("mpl")

Output of the previous code cell

In questo semplicissimo diagramma del circuito, il qubit è rappresentato da un filo, la linea orizzontale nera, e il gate compare come un riquadro su quel filo.

Gate di Hadamard: Crea uno stato di sovrapposizione. Tabella di verità:

IngressoUscita
∣0⟩\vert 0\rangle12(∣0⟩+∣1⟩)\frac{1}{\sqrt{2}}\left(\vert 0\rangle+\vert 1\rangle\right)
∣1⟩\vert 1\rangle12(∣0⟩−∣1⟩)\frac{1}{\sqrt{2}}\left(\vert 0\rangle-\vert 1\rangle\right)

Rappresentazione matriciale: H=12(111−1)H=\frac{1}{\sqrt{2}}\begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}

Un circuito con un gate di Hadamard si costruisce così:

from qiskit import QuantumCircuit

qc = QuantumCircuit(1)
qc.h(0)
qc.draw("mpl")

Output of the previous code cell

gate ZZ: Aggiunge uno sfasamento di Δϕ=π\Delta \phi = \pi allo stato ∣1⟩|1\rangle:

IngressoUscita
∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle
∣1⟩\vert 1\rangle−∣1⟩-\vert 1\rangle

Z=(100−1)Z=\begin{pmatrix} 1 & 0 \\ 0 & -1 \end{pmatrix}

In Qiskit, la creazione di un circuito con un gate ZZ è la seguente:

qc = QuantumCircuit(1)
qc.z(0)
qc.draw("mpl")

Output of the previous code cell

gate TT: Aggiunge uno sfasamento di Δϕ=π/4\Delta \phi = \pi/4 allo stato ∣1⟩|1\rangle:

IngressoUscita
∣0⟩\vert 0\rangle∣0⟩\vert 0\rangle
∣1⟩\vert 1\rangleeiπ/4∣1⟩e^{i\pi/4}\vert 1\rangle

T=(100eiπ/4)T=\begin{pmatrix} 1 & 0 \\ 0 & e^{i\pi/4} \end{pmatrix}

In Qiskit, la creazione di un circuito con un gate TT è la seguente:

qc = QuantumCircuit(1)
qc.t(0)
qc.draw("mpl")

Output of the previous code cell

gate a più qubit​

I gate a due qubit possono assomigliare ai gate classici a due bit, ma con un'importante differenza: tutti i gate quantistici devono essere reversibili. In termini di algebra lineare, questo significa che sono rappresentati da matrici unitarie. Quindi, due qubit in ingresso corrispondono sempre a due qubit in uscita, e l'operazione può, in linea di principio, essere annullata. Ciò contrasta con i gate classici visti in precedenza come AND o OR, che perdono informazioni e sono irreversibili — dato un output, non è possibile determinare univocamente l'input.

Gate CNOT (Controlled-NOT): I due qubit in ingresso sono chiamati qubit di "controllo" e qubit di "target". Il qubit di controllo rimane invariato, ma il suo stato determina cosa accade al qubit target. Se il qubit di controllo è nello stato ∣1⟩\vert 1\rangle, viene applicato un gate XX al target; se lo stato del qubit di controllo è ∣0⟩\vert 0\rangle, non viene apportata alcuna modifica. Nella notazione seguente, si assume che il qubit AA (qubit più a destra) sia il controllo e il qubit BB (il qubit più a sinistra) sia il target. Di seguito, la notazione usata è CNOT(qcontrol,qtarget)∣BA⟩.CNOT(q_{control},q_{target})\vert BA\rangle.

CNOT(A,B)∣BA⟩input=∣BA⟩outputCNOT(A,B)\vert BA\rangle_{input} = \vert BA\rangle_{output}

IngressoUscita
∣00⟩\vert 00\rangle∣00⟩\vert 00\rangle
∣01⟩\vert 01\rangle∣11⟩\vert 11\rangle
∣10⟩\vert 10\rangle∣10⟩\vert 10\rangle
∣11⟩\vert 11\rangle∣01⟩\vert 01\rangle

Quindi, la matrice che rappresenta questa azione è:

CNOT=(1000000100100100)CNOT=\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix}

qc = QuantumCircuit(2)
qc.cx(0, 1)
qc.draw("mpl")

Output of the previous code cell

Questo è il primo diagramma del circuito che vediamo con due qubit, rappresentati dai due fili. Il gate CNOT è implementato tra i due qubit, con q0q_0 come controllo e q1q_1 come target.

Verifica la tua comprensione​

Leggi la/le domanda/e seguente/i, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

La maggior parte dei gate ha la stessa forma matriciale in Qiskit come altrove. Ma il gate CNOT agisce su due qubit, e quindi all'improvviso le convenzioni di ordinamento dei qubit diventano un problema. I testi che ordinano i qubit come ∣q0,q1,...⟩\vert q_0,q_1,...\rangle mostreranno una forma matriciale diversa per i loro gate CNOT. Verifica con un'esplicita moltiplicazione matriciale che la matrice CNOT sopra ha l'azione corretta sullo stato ∣01⟩.\vert 01\rangle.

Risposta:

CNOT∣01⟩=(1000000100100100)(0100)=(0001)=∣11⟩CNOT\vert 01\rangle =\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix}\begin{pmatrix}0 \\ 1 \\ 0 \\0\end{pmatrix} = \begin{pmatrix}0 \\ 0 \\ 0 \\1\end{pmatrix} = \vert 11\rangle

Gate SWAP: Questo gate scambia gli stati di due qubit. Tabella di verità:

IngressoUscita
∣00⟩\vert 00\rangle∣00⟩\vert 00\rangle
∣01⟩\vert 01\rangle∣10⟩\vert 10\rangle
∣10⟩\vert 10\rangle∣01⟩\vert 01\rangle
∣11⟩\vert 11\rangle∣11⟩\vert 11\rangle

Quindi, la matrice che rappresenta questa azione è:

SWAP=(1000001001000001)SWAP=\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1\end{pmatrix}

qc = QuantumCircuit(2)
qc.swap(0, 1)
qc.draw("mpl")

Output of the previous code cell

Il gate SWAP può in realtà essere costruito da tre CNOT. Per vedere come, possiamo decomporre (decompose()) il gate con Qiskit:

qc = QuantumCircuit(2)
qc.swap(0, 1)
qc.decompose().draw("mpl")

Output of the previous code cell

Qui vediamo per la prima volta come più gate vengono mostrati in un diagramma di circuito. Lo si legge da sinistra a destra, quindi il gate più a sinistra viene applicato per primo.

Verifica la tua comprensione​

Leggi la/le domanda/e seguente/i, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Verifica che la combinazione di CNOT sopra produca un gate SWAP. Puoi farlo con la moltiplicazione matriciale o con qualsiasi altro metodo.

Risposta:

Con la moltiplicazione matriciale:

(1000000100100100)(1000010000010010)(1000000100100100)=(1000001001000001)=SWAP ✓\begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0\end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0\end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 1\end{pmatrix} = SWAP ~\checkmark

Usando una tabella di verità per vedere come gli stati cambiano con ciascun CNOT. Nell'ultima colonna, gli stati dovrebbero essere equivalenti alla colonna "Uscita" della tabella di verità dello SWAP:

IngressoCNOT(A,B)CNOT(B,A)CNOT(A,B)
∣00⟩\vert 00\rangle∣00⟩\vert 00\rangle∣00⟩\vert 00\rangle∣00⟩✓\vert 00\rangle \checkmark
∣01⟩\vert 01\rangle∣11⟩\vert 11\rangle∣10⟩\vert 10\rangle∣10⟩✓\vert 10\rangle \checkmark
∣10⟩\vert 10\rangle∣10⟩\vert 10\rangle∣11⟩\vert 11\rangle∣01⟩✓\vert 01\rangle \checkmark
∣11⟩\vert 11\rangle∣01⟩\vert 01\rangle∣01⟩\vert 01\rangle∣11⟩✓\vert 11\rangle \checkmark

Gate di Toffoli (o "controlled-controlled-NOT" (CCNOT)): Questo è un gate a tre qubit. Il nome "controlled-controlled-NOT" ti dice già come funziona: ci sono due qubit di controllo e un qubit target, e lo stato del qubit target viene invertito solo se entrambi i qubit di controllo si trovano nello stato ∣1⟩\vert 1\rangle. Manteniamo la convenzione di ordinamento usata con il CNOT:

CCNOT(ControlA,ControlB,TargetC)∣CBA⟩CCNOT(Control A, Control B, Target C)\vert CBA\rangle

Quindi la tabella di verità è:

IngressoUscita
∣000⟩\vert 000\rangle∣000⟩\vert 000\rangle
∣001⟩\vert 001\rangle∣001⟩\vert 001\rangle
∣010⟩\vert 010\rangle∣010⟩\vert 010\rangle
∣011⟩\vert 011\rangle∣111⟩\vert 111\rangle
∣100⟩\vert 100\rangle∣100⟩\vert 100\rangle
∣101⟩\vert 101\rangle∣101⟩\vert 101\rangle
∣110⟩\vert 110\rangle∣110⟩\vert 110\rangle
∣111⟩\vert 111\rangle∣011⟩\vert 011\rangle

E la matrice che rappresenta questa azione è:

CCNOT=(1000000001000000001000000000000100001000000001000000001000010000)CCNOT=\begin{pmatrix} 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0 \\0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 0 & 1 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 1 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 & 0 & 0 & 0 & 0\end{pmatrix}
qc = QuantumCircuit(3)
qc.ccx(0, 1, 2)
qc.draw("mpl")

Output of the previous code cell

Anche il gate di Toffoli può essere decomposto in CNOT, insieme ad altri gate. Tuttavia, è significativamente più complicato della decomposizione del gate SWAP, quindi verrà lasciato come esercizio opzionale alla fine del modulo per esplorare e verificare questa decomposizione.

Misure​

Le misure svolgono un ruolo speciale nel quantum computing — uno che non ha alcun analogo nel computing classico. Mentre nel computing classico puoi controllare i tuoi bit in qualsiasi momento dell'algoritmo, nel quantum computing devi essere molto selettivo su quando osservare i tuoi qubit, perché la misura collassa il loro stato e distrugge la sovrapposizione che conferisce ai qubit la loro complessità computazionale.

In particolare, dato uno stato quantistico a NN bit ∣ψ⟩=∑i=02N−1ci∣i⟩\vert \psi\rangle = \sum_{i=0}^{2^N-1} c_i \vert i\rangle, una misura collasserà lo stato in una delle funzioni di base ∣i⟩\vert i\rangle con una probabilità pari a ∣ci∣2\vert c_i\vert ^2.

Ma questo effetto distruttivo della misura non è sempre un ostacolo. È in realtà una risorsa chiave in certi algoritmi e protocolli, come il teletrasporto quantistico e la distribuzione quantistica della chiave.

In Qiskit, quando viene eseguita una misura, essa viene inviata a un registro classico dove viene memorizzata come bit classico. La creazione di un circuito con una misura è la seguente:

qc = QuantumCircuit(
1, 1
) # the second number is the number of classical bits in the circuit
qc.measure(0, 0)
qc.draw("mpl")

Output of the previous code cell

Circuiti​

Ora che sappiamo come funzionano qubit, gate e misure, costruiamo ed eseguiamo il nostro circuito quantistico! Per questo, dobbiamo introdurti a un utile flusso di lavoro chiamato Qiskit patterns.

Framework Qiskit patterns​

Il framework Qiskit patterns è una procedura generale per affrontare e risolvere problemi con un computer quantistico. Si compone di quattro passi:

  1. Mappare il nostro problema su circuiti e operatori quantistici
  2. Ottimizzare il circuito per l'hardware di destinazione
  3. Eseguire sull'hardware di destinazione
  4. Post-elaborare i risultati

Per illustrare questi passi, implementeremo una versione quantistica del circuito half-adder discusso in precedenza.

1. Mappatura​

Il circuito adder classico usa un gate XOR e un gate AND per calcolare rispettivamente i bit di somma e di riporto. Possiamo adattare questi gate al contesto quantistico per realizzare il quantum half-adder. Prima di tutto, ricordando che i gate quantistici sono reversibili, non possiamo semplicemente sovrascrivere gli input. Invece, introduciamo due qubit ausiliari inizializzati a ∣0⟩\vert 0\rangle per memorizzare gli output di somma e riporto. Quindi, il nostro stato quantistico completo sarà composto dai qubit AA e BB, e dai qubit di somma e riporto, che chiameremo SS e CC:

∣ψ⟩=∣CSBA⟩\vert \psi\rangle = \vert C S B A\rangle

Ora abbiamo bisogno di gate quantistici che svolgano ciò che i gate XOR e AND facevano nel circuito classico.

Somma:

Per lo XOR, applichiamo due CNOT, ciascuno con qubit di controllo AA e BB e qubit target SS per entrambi. Se AA e BB sono diversi, uno dei gate CNOT porterà SS allo stato ∣1⟩\vert 1\rangle. Se AA e BB sono entrambi ∣0⟩\vert 0\rangle, allora SS non subisce alcuna modifica e rimane nello stato ∣0⟩\vert 0\rangle. Se AA e BB sono entrambi ∣1⟩\vert 1\rangle, allora lo stato di SS verrà invertito due volte, riportandolo allo stato ∣0⟩\vert 0\rangle.

Riporto:

Per il bit di riporto, abbiamo bisogno di qualcosa che funzioni come il gate AND classico.

Verifica la tua comprensione​

Leggi la/le domanda/e seguente/i, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Scorri i gate di cui abbiamo parlato per vedere se riesci a intuire quale gate quantistico useremo al posto del gate AND classico:

Risposta:

È il gate di Toffoli! Ricorda, il gate di Toffoli, o controlled-controlled-NOT, inverte lo stato target se e solo se il qubit di controllo 0 E il qubit di controllo 1 sono entrambi ∣1⟩\vert 1\rangle. Quindi, se il qubit target parte dallo stato ∣0⟩\vert 0\rangle, ha la stessa azione del gate AND.

Quindi, ora abbiamo tutti gli ingredienti necessari per costruire il circuito quantistico:

# qubits: a, b, sum, carry
qc = QuantumCircuit(4)

# Choose values for A and B:
a = 0
b = 0

# Prepare A and B qubits according to selected values:
if a:
qc.x(0)
if b:
qc.x(1)

# XOR (sum) into qubit 2
qc.cx(0, 2)
qc.cx(1, 2)

# AND (carry) into qubit 3
qc.ccx(0, 1, 3) # a AND b

# measure
qc.measure_all()

qc.draw("mpl")

Output of the previous code cell

Sopra è riportato il diagramma del circuito quantistico half-adder. Come accennato in precedenza, i fili rappresentano i qubit da 00 a 33 ordinati dall'alto verso il basso, e il registro dei bit classici è il filo in basso con la doppia linea. Poi, leggendo da sinistra a destra, vediamo come i gate vengono applicati a ciascun qubit osservando dove compaiono i riquadri sui fili corrispondenti. Infine, le misure sono mostrate alla fine. Le misure collassano gli stati dei qubit in valori definiti 00 o 11, e i risultati vengono inviati a un registro classico.

Una sottigliezza: sebbene il diagramma del circuito sia disegnato da sinistra a destra, quando scriviamo la corrispondente espressione matriciale dobbiamo leggerla da destra a sinistra. Questo perché nella moltiplicazione matriciale, l'operatore più vicino al vettore di stato (quello più a destra) agisce per primo. Quindi, ad esempio, il circuito sopra (ignorando le misure) si scriverebbe:

CCNOT(q0,q1,q3)CNOT(q1,q2)CNOT(q0,q2)∣q3q2q1q0⟩CCNOT(q_0,q_1,q_3)CNOT(q_1, q_2)CNOT(q_0,q_2)\vert q_3 q_2 q_1 q_0\rangle

2. Ottimizzazione:​

Successivamente, dobbiamo ottimizzare il circuito per essere eseguito sull'hardware quantistico. Questa ottimizzazione viene realizzata tramite il transpiler, che traduce il circuito astratto mostrato sopra in istruzioni che il computer quantistico comprenderà. Assegna i qubit logici sopra a qubit reali e fisici sul processore e riscrive i gate in termini del proprio insieme nativo di gate ottimizzati per funzionare sul computer quantistico. Infine, il transpiler implementa anche qualcosa chiamato "soppressione e mitigazione degli errori" per cercare di ridurre al minimo l'effetto degli errori sul risultato. Questo non è così importante per il nostro circuito molto semplice, ma se continuerai nel tuo percorso di quantum computing eseguendo circuiti più complessi, vedrai presto il valore della soppressione e mitigazione degli errori. Se vuoi saperne di più, vedi il corso di Olivia Lane, Quantum Computing in Practice.

Prima di tutto, carichiamo i pacchetti necessari per comunicare con i computer quantistici IBM® e selezioniamo un backend su cui eseguire. Possiamo scegliere il backend meno occupato oppure selezionare un backend specifico di cui conosciamo le proprietà.

Di seguito è riportato il codice per salvare le tue credenziali al primo utilizzo. Assicurati di eliminare queste informazioni dal notebook dopo averle salvate nel tuo ambiente, in modo che le tue credenziali non vengano condivise accidentalmente quando condividi il notebook. Consulta Configura il tuo account IBM Cloud e Inizializza il servizio in un ambiente non attendibile per ulteriori indicazioni.

# Load the Qiskit Runtime service
from qiskit_ibm_runtime import QiskitRuntimeService

# Load the Qiskit Runtime service

# Syntax for first saving your token. Delete these lines after saving your credentials.
# QiskitRuntimeService.save_account(channel='ibm_quantum_platform', instance = '<YOUR_IBM_INSTANCE_CRN>', token='<YOUR-API_KEY>', overwrite=True, set_as_default=True)
# service = QiskitRuntimeService(channel='ibm_quantum_platform')

# Load saved credentials
service = QiskitRuntimeService()

# Use the least busy backend, or uncomment the loading of a specific backend like "ibm_brisbane".
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=127)
# backend = service.backend("ibm_brisbane")
print(backend.name)
ibm_fez

Ora usiamo il transpiler per ottimizzare il circuito. Possiamo scegliere il livello di ottimizzazione da 0 (nessuna ottimizzazione) a 3 (ottimizzazione massima). Per vedere cosa comporta ogni livello, visita la guida Imposta il livello di ottimizzazione del transpiler. Il circuito risultante apparirà significativamente diverso dal circuito logico che abbiamo creato nella fase di mappatura.

# Transpile the circuit and optimize for running on the quantum computer selected
# Step 2: Transpile
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager

target = backend.target
pm = generate_preset_pass_manager(target=target, optimization_level=3)
qc_isa = pm.run(qc)

qc_isa.draw("mpl")

Output of the previous code cell

Un "Sampler" è una primitiva progettata per campionare i possibili stati risultanti da un circuito quantistico e raccogliere statistiche su quali stati potrebbero essere misurati e con quale probabilità. Qui importiamo il Qiskit Runtime Sampler:

# Load the Runtime primitive and session
from qiskit_ibm_runtime import SamplerV2 as Sampler

sampler = Sampler(mode=backend)

Se hai esaurito il tempo assegnato sui computer quantistici reali oppure se non hai una connessione Internet, potresti preferire usare un simulatore. Per farlo, esegui la cella seguente e decommenta la riga associata nella fase "Esegui".

# Load the backend sampler
from qiskit.primitives import BackendSamplerV2

# Load the Aer simulator and generate a noise model based on the currently-selected backend.
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel

noise_model = NoiseModel.from_backend(backend)

# Define a simulator using Aer, and use it in Sampler.
backend_sim = AerSimulator(noise_model=noise_model)
sampler_sim = BackendSamplerV2(backend=backend_sim)

# Alternatively, load a fake backend with generic properties and define a simulator.
# backend_gen = GenericBackendV2(num_qubits=18)
# sampler_gen = BackendSamplerV2(backend=backend_gen)

3. Esecuzione​

Dopo aver preparato il circuito, possiamo ora eseguirlo sul computer quantistico!

job = sampler.run([qc_isa], shots=100)
# job = sampler_sim.run([qc_isa]) # uncomment if you want to run on a simulator
res = job.result()
counts = res[0].data.meas.get_counts()

4. Post-elaborazione​

Ora siamo pronti a visualizzare i nostri risultati! Mostreremo un istogramma dei 100 campionamenti del circuito.

from qiskit.visualization import plot_histogram

print("counts = ", counts)
plot_histogram(counts)
counts =  {'0000': 90, '0100': 4, '1100': 3, '0010': 3}

Output of the previous code cell

L'istogramma sopra mostra i risultati delle misure di tutti e quattro i qubit alla fine del circuito. Un computer quantistico ideale con zero rumore avrebbe misurato i qubit con gli stessi valori ogni volta, ma in realtà il rumore causerà ad alcune esecuzioni di produrre errori.

Verifica la tua comprensione​

Leggi la/le domanda/e seguente/i, pensa alla tua risposta, poi clicca sul triangolo per vedere la soluzione.

Usando la stringa di bit con il maggior numero di conteggi come valori per AA, BB, SS e CC, verifica che il circuito adder quantistico abbia funzionato.

Risposta:

Dobbiamo verificare che A+B=S+2×CA+B = S+2 \times C. Ricorda che l'ordine della stringa di bit segue la notazione little-endian, quindi si legge CSBA.

Dall'istogramma sopra, vediamo che la stringa di bit 0000 è quella dominante.

0+0=0+0×2=0 ✓0 + 0 = 0 + 0 \times 2 = 0 ~\checkmark

Torna indietro e cambia i valori di AA e BB in A=1A=1 e B=1B=1 e ripercorri i passi di Qiskit patterns per rieseguire il circuito. Verifica che il circuito adder abbia funzionato di nuovo.

Risposta:

Dovresti ottenere un istogramma con la stringa di bit dominante 1011:

1+1=0+1×2=2 ✓1 + 1 = 0 + 1 \times 2 = 2 ~\checkmark

Una delle caratteristiche aggiuntive del quantum half-adder rispetto al half-adder classico è che può funzionare con input quantistici. Ovvero, può "sommare" i qubit AA e BB anche se si trovano in stati di sovrapposizione. Nella sezione Domande di sfida qui sotto, ti verrà chiesto di preparare i qubit in sovrapposizioni e osservare cosa succede!

Conclusione​

Questo modulo è stato progettato per darti una solida comprensione di base dei principi fondamentali del quantum computing, confrontandolo con il computing classico. Abbiamo analizzato il circuito half-adder classico e poi ti abbiamo mostrato come adattarlo per funzionare con qubit su un computer quantistico. Ora sei pronto per esplorare gli altri moduli di Qiskit in the Classroom!

Concetti fondamentali:​

  • A differenza dei bit classici che possono assumere solo i valori 0 e 1, i qubit possono trovarsi in stati di sovrapposizione sia di 0 che di 1.
  • Più qubit possono trovarsi in una sovrapposizione sulle stringhe di bit classicamente consentite chiamate stati di base computazionale.
  • Più qubit possono essere entangled in modo che lo stato dell'uno dipenda dallo stato dell'altro.
  • La convenzione Qiskit è di usare la notazione little-endian, che colloca il qubit meno significativo, q0q_0, nella posizione più a destra e il qubit più significativo, qNq_N, più a sinistra.
  • I gate quantistici sono operazioni reversibili rappresentate da matrici unitarie che agiscono sui vettori di stato quantistici. In questa notazione, la matrice più vicina al vettore (quella più a destra) agisce per prima.
  • Le misure collassano uno stato quantistico di sovrapposizione in uno dei suoi stati classicamente consentiti, con probabilità pari al quadrato dell'ampiezza del corrispondente stato di base computazionale nella sovrapposizione.
  • I circuiti quantistici sono spesso rappresentati usando diagrammi di circuiti quantistici, dove i qubit sono raffigurati come fili orizzontali e i gate quantistici compaiono lungo questi fili da sinistra a destra.
  • Per eseguire un circuito quantistico, utilizziamo i quattro passi del flusso di lavoro Qiskit patterns: Mappa, Ottimizza, Esegui, Post-elabora.

Domande​

Domande vero/falso​

  1. Un singolo bit in un computer classico può contenere solo il valore 0 o 1.

  2. L'entanglement significa che lo stato di un qubit è indipendente dallo stato di un altro.

  3. I gate quantistici sono generalmente operazioni irreversibili.

  4. La convenzione Qiskit colloca il qubit meno significativo, q0q_0, nella posizione più a sinistra.

  5. Misurare uno stato quantistico dà sempre lo stesso risultato se ripetuto molte volte.

  6. Il gate di Hadamard crea sovrapposizione in un singolo qubit.

  7. I circuiti quantistici possono includere operazioni di misura che collassano lo stato di sovrapposizione in uno degli stati classicamente consentiti.

  8. Il numero di stati classici possibili per NN bit è 2N2N.

  9. Le probabilità dei risultati per le misure quantistiche sono date dalle ampiezze al quadrato degli stati di base misurabili classicamente.

Domande a risposta breve​

  1. Quali sono alcune differenze principali tra un bit e un qubit?

  2. Cosa succede a uno stato quantistico quando viene misurato?

  3. Perché usiamo la notazione little-endian in Qiskit?

  4. Quali sono i quattro passi del flusso di lavoro Qiskit patterns?

Domande di sfida:​

  1. Nel modulo, abbiamo usato l'adder solo per sommare stati classicamente consentiti per AA e BB. Ma possiamo anche preparare AA e BB in sovrapposizioni! Modifica il codice per preparare ogni qubit in una sovrapposizione uguale di 0 e 1, poi esegui il nuovo circuito e ottieni un nuovo istogramma. Cosa vedi? Spiega cosa sta accadendo.