Přeskočit na hlavní obsah

Kvantové bity, brány a obvody

poznámka

Kifumi Numata (19 Apr 2024)

Klikni zde a stáhni si PDF původní přednášky. Některé ukázky kódu mohou být zastaralé, protože se jedná o statické obrázky.

Přibližná doba QPU pro spuštění tohoto experimentu je 5 sekund.

1. Úvod

Bity, brány a obvody jsou základní stavební kameny kvantových výpočtů. Naučíš se kvantové výpočty s obvodovým modelem pomocí kvantových bitů a bran a také si zopakuješ superpozici, měření a provázanost.

V této lekci se naučíš:

  • Single-qubit gates
  • Bloch sphere
  • Superpozici
  • Měření
  • Two-qubit gates a stav provázanosti

Na konci této přednášky se dozvíš o hloubce obvodu, která je klíčová pro kvantové výpočty v užitkové škále.

2. Výpočet jako diagram

Když pracujeme s qubity nebo bity, potřebujeme s nimi manipulovat, abychom ze vstupů, které máme, dostali výstupy, které potřebujeme. Pro nejjednodušší programy s velmi malým počtem bitů je užitečné tento proces znázornit pomocí diagramu zvaného schéma obvodu.

Obrázek vlevo dole je příkladem klasického obvodu a obrázek vpravo dole je příkladem kvantového obvodu. V obou případech jsou vstupy vlevo a výstupy vpravo, zatímco operace jsou znázorněny symboly. Symboly používané pro operace se nazývají „Gate", převážně z historických důvodů.

"classical logic and quantum circuit"

3. Single-qubit quantum gate

3.1 Quantum state and Bloch sphere

Stav Qubitu je reprezentován jako superpozice 0|0\rangle a 1|1\rangle. Libovolný kvantový stav je vyjádřen jako

ψ=α0+β1|\psi\rangle =\alpha|0\rangle+ \beta|1\rangle

kde α\alpha a β\beta jsou komplexní čísla taková, že α2+β2=1|\alpha|^2+|\beta|^2=1.

0|0\rangle a 1|1\rangle jsou vektory ve dvourozměrném komplexním vektorovém prostoru:

0=(10),1=(01)|0\rangle = \begin{pmatrix} 1 \\0 \end{pmatrix}, |1\rangle = \begin{pmatrix} 0\\1 \end{pmatrix}

Libovolný kvantový stav je tedy také vyjádřen jako

ψ=α(10)+β(01)=(αβ)|\psi\rangle = \alpha\begin{pmatrix} 1 \\ 0 \end{pmatrix} + \beta\begin{pmatrix}0\\ 1 \end{pmatrix} = \begin{pmatrix} \alpha \\ \beta \end{pmatrix}

Z toho vidíme, že stav kvantového bitu je jednotkový vektor ve dvourozměrném komplexním prostoru se skalárním součinem s ortonormální bází 0|0\rangle a 1|1\rangle. Je normalizován na 1.

ψψ=(αβ)(αβ)=1\langle\psi|\psi\rangle = \begin{pmatrix} \alpha^* & \beta^* \end{pmatrix} \begin{pmatrix} \alpha \\ \beta \end{pmatrix} = 1

|\psi\rangle =\begin\{pmatrix\} \alpha \\ \beta \end\{pmatrix\} se také nazývá stavový vektor (statevector).

Stav jednoho Qubitu lze také vyjádřit jako

ψ=cosθ20+eiφsinθ21=((cosθ2eiφsinθ2))|\psi\rangle =\cos\frac{\theta}{2}|0\rangle+e^{i\varphi}\sin\frac{\theta}{2}|1\rangle =\left( \begin{pmatrix} \cos\frac{\theta}{2}\\ e^{i\varphi}\sin\frac{\theta}{2} \end{pmatrix}\right)

kde θ\theta a φ\varphi jsou úhly Blochovy sféry na následujícím obrázku.

Bloch sphere V několika následujících buňkách kódu postupně sestavíme základní výpočty ze stavebních prvků v Qiskitu. Vytvoříme prázdný Circuit a pak přidáme kvantové operace – budeme probírat jednotlivé Gate a vizualizovat jejich efekty. Buňku spustíš stisknutím „Shift" + „Enter". Nejprve importuj knihovny.

# Added by doQumentation — required packages for this notebook
!pip install -q qiskit qiskit-aer qiskit-ibm-runtime
# Import the qiskit library
from qiskit import QuantumCircuit
from qiskit_aer import AerSimulator
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
from qiskit_ibm_runtime import Sampler
from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
from qiskit.visualization import plot_histogram

Příprava kvantového obvodu

Vytvoříme a nakreslíme Circuit s jedním Qubitem.

# Create the single-qubit quantum circuit
qc = QuantumCircuit(1)

# Draw the circuit
qc.draw("mpl")

Output of the previous code cell

X Gate

X Gate je rotace o π\pi kolem osy xx na Blochově sféře. Aplikování X Gate na 0|0\rangle1|1\rangle a aplikování X Gate na 1|1\rangle0|0\rangle, takže jde o operaci podobnou klasickému hradlu NOT, která se také nazývá překlopení bitu (bit flip). Maticová reprezentace X Gate je níže.

X=(0110)X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \\ \end{pmatrix}
qc = QuantumCircuit(1)  # Prepare the single-qubit quantum circuit

# Apply a X gate to qubit 0
qc.x(0)

# Draw the circuit
qc.draw("mpl")

Output of the previous code cell

V IBM Quantum® je počáteční stav nastaven na 0|0\rangle, takže výše uvedený kvantový Circuit v maticové reprezentaci je

X0=(0110)(10)=(01)=1X|0\rangle= \begin{pmatrix} 0 & 1 \\ 1 & 0 \end{pmatrix} \begin{pmatrix} 1 \\ 0 \end{pmatrix} =\begin{pmatrix} 0 \\ 1 \end{pmatrix} = |1\rangle

Dále spustíme tento Circuit pomocí simulátoru stavového vektoru.

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))

Output of the previous code cell

Svislý vektor je zobrazen jako řádkový vektor s komplexními čísly (imaginární část je indexována jj).

H Gate

Hadamardův Gate je rotace o π\pi kolem osy ležící na půl cesty mezi osami xx a zz na Blochově sféře. Aplikování H Gate na 0|0\rangle vytvoří superpozici ve tvaru 0+12\frac{|0\rangle + |1\rangle}{\sqrt{2}}. Maticová reprezentace H Gate je níže.

H=12(1111)H = \frac{1}{\sqrt{2}}\begin{pmatrix} 1 & 1 \\ 1 & -1 \\ \end{pmatrix}
qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit

# Apply an Hadamard gate to qubit 0
qc.h(0)

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.70710678+0.j, 0.70710678+0.j],
dims=(2,))

Output of the previous code cell

Toto je

H0=12(1111)(10)=12(11)=(0.7070.707)=12(0+1)H|0\rangle= \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix} \begin{pmatrix} 1 \\0 \end{pmatrix} =\frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\ 1 \end{pmatrix} =\begin{pmatrix} 0.707 \\ 0.707 \end{pmatrix} =\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle)

Tento stav superpozice je tak běžný a důležitý, že má vlastní symbol:

+12(0+1).|+\rangle \equiv \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle).

Aplikováním H Gate na 0|0\rangle jsme vytvořili superpozici 0|0\rangle a 1|1\rangle, kde by měření ve výpočetní bázi (podél osy z v obrazci Blochovy sféry) dalo každý stav se stejnou pravděpodobností.

Stav |-\rangle

Možná sis uhodl/a, že existuje odpovídající stav |-\rangle:

012.|-\rangle \equiv \frac{|0\rangle -|1\rangle}{\sqrt{2}}.

Pro vytvoření tohoto stavu nejprve aplikuj X Gate, aby vznikl 1|1\rangle, a pak aplikuj H Gate.

qc = QuantumCircuit(1)  # Create the single-qubit quantum circuit

# Apply a X gate to qubit 0
qc.x(0)

# Apply an Hadamard gate to qubit 0
qc.h(0)

# draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([ 0.70710678+0.j, -0.70710678+0.j],
dims=(2,))

Output of the previous code cell

Toto je

H1=12(11 11)(0 1)=12(1 1)=(0.707 0.707)=12(01)=H|1\rangle= \frac{1}{\sqrt{2}} \begin{pmatrix} 1 & 1 \\\ 1 & -1 \end{pmatrix} \begin{pmatrix} 0 \\\ 1 \end{pmatrix} =\frac{1}{\sqrt{2}}\begin{pmatrix} 1 \\\ -1 \end{pmatrix} =\begin{pmatrix} 0.707 \\\ -0.707 \end{pmatrix} =\frac{1}{\sqrt{2}}(|0\rangle-|1\rangle) = |-\rangle

Aplikováním H Gate na 1|1\rangle dostaneme rovnoměrnou superpozici 0|0\rangle a 1|1\rangle, ale znaménko u 1|1\rangle je záporné.

3.2 Single-qubit quantum state and unitary evolution

Akce všech Gate, které jsme dosud viděli, byly unitární, což znamená, že je lze reprezentovat unitárním operátorem. Jinými slovy, výstupní stav lze získat působením unitární matice na počáteční stav:

ψ=Uψ|\psi^{'}\rangle = U|\psi\rangle

Unitární matice je matice splňující

UU=UU=I.U^{\dagger}U =U U^{\dagger} = I.

Z hlediska provozu kvantového počítače bychom řekli, že aplikace kvantového Gate na Qubit vyvíjí kvantový stav. Mezi běžné jednoqubitové Gate patří následující.

Pauli Gate:

X=(0110)=01+10X = \begin{pmatrix} 0 & 1 \\ 1 & 0 \\ \end{pmatrix} = |0\rangle \langle 1|+|1\rangle \langle 0| Y=(0ii0)=i01+i10Y = \begin{pmatrix} 0 & -i \\ i & 0 \\ \end{pmatrix} = -i|0\rangle \langle 1|+i|1\rangle \langle 0| Z=(1001)=0011Z = \begin{pmatrix} 1 & 0 \\ 0 & -1 \\ \end{pmatrix} = |0\rangle \langle 0|-|1\rangle \langle 1|

kde vnější součin byl vypočítán takto:

00=[10][10]=[1000],10=[01][10]=[0010],|0\rangle \langle 0|= \begin{bmatrix} 1 \\ 0 \end{bmatrix} \begin{bmatrix} 1 & 0 \end{bmatrix} =\begin{bmatrix} 1 & 0 \\ 0 & 0 \\ \end{bmatrix}, \quad |1\rangle \langle 0|= \begin{bmatrix} 0 \\ 1 \end{bmatrix} \begin{bmatrix} 1 & 0 \end{bmatrix} =\begin{bmatrix} 0 & 0 \\ 1 & 0 \\ \end{bmatrix}, \quad 01=[10][01]=[0100],11=[01][01]=[0001],|0\rangle \langle 1|= \begin{bmatrix} 1 \\ 0 \end{bmatrix} \begin{bmatrix} 0 & 1 \end{bmatrix} =\begin{bmatrix} 0 & 1 \\ 0 & 0 \\ \end{bmatrix}, \quad |1\rangle \langle 1|= \begin{bmatrix} 0 \\ 1 \end{bmatrix} \begin{bmatrix} 0 & 1 \end{bmatrix} =\begin{bmatrix} 0 & 0 \\ 0 & 1 \\ \end{bmatrix}, \quad

Další typické jednoqubitové Gate:

H=12[1111],S=[100i],T=[100exp(iπ/4)]H= \frac{1}{\sqrt{2}}\begin{bmatrix} 1 & 1 \\ 1 & -1 \\ \end{bmatrix},\quad S = \begin{bmatrix} 1 & 0 \\ 0 & i \\ \end{bmatrix}, \quad T = \begin{bmatrix} 1 & 0 \\ 0 & exp(i\pi/4) \\ \end{bmatrix} Rx(θ)=eiθX/2=cosθ2Iisinθ2X=[cosθ2isinθ2isinθ2cosθ2]R_x(\theta) = e^{-i\theta X/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}X = \begin{bmatrix} cos\frac{\theta}{2} & -i sin \frac{\theta}{2} \\ -i sin \frac{\theta}{2} & cos\frac{\theta}{2} \\ \end{bmatrix} Ry(θ)=eiθY/2=cosθ2Iisinθ2Y=[cosθ2sinθ2sinθ2cosθ2]R_y(\theta) = e^{-i\theta Y/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}Y = \begin{bmatrix} cos\frac{\theta}{2} & - sin \frac{\theta}{2} \\ sin \frac{\theta}{2} & cos\frac{\theta}{2} \\ \end{bmatrix} Rz(θ)=eiθZ/2=cosθ2Iisinθ2Z=[eiθ/200eiθ/2]R_z(\theta) = e^{-i\theta Z/2} = cos\frac{\theta}{2}I - i sin \frac{\theta}{2}Z = \begin{bmatrix} e^{-i\theta /2} & 0 \\ 0 & e^{i\theta /2} \\ \end{bmatrix}

Význam a použití těchto Gate jsou podrobněji popsány v kurzu Základy kvantových informací.

Exercise 1

Použij Qiskit k vytvoření kvantových Circuit, které připraví níže popsané stavy. Poté spusť každý Circuit pomocí simulátoru stavového vektoru a zobraz výsledný stav na Bloch sféře. Jako bonus zkus odhadnout, jaký by měl být konečný stav, na základě intuice o Gate a rotacích v Bloch sféře.

(1) XX0XX|0\rangle

(2) HH0HH|0\rangle

(3) HZH0HZH|0\rangle

Tip: Gate Z lze použít pomocí

qc.z(0)

Řešení:

### (1) XX|0> ###

# Create the single-qubit quantum circuit
qc = QuantumCircuit(1) ##your code goes here##

# Add a X gate to qubit 0
qc.x(0) ##your code goes here##

# Add a X gate to qubit 0
qc.x(0) ##your code goes here##

# Draw a circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))

Output of the previous code cell

### (2) HH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.h(0)
qc.draw("mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([1.+0.j, 0.+0.j],
dims=(2,))

Output of the previous code cell

### (3) HZH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.z(0)
qc.h(0)
qc.draw("mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)
Statevector([0.+0.j, 1.+0.j],
dims=(2,))

Output of the previous code cell

3.3 Měření

Měření je teoreticky velmi složité téma. V praxi však měření podél zz (jak to dělají všechny kvantové počítače IBM®) jednoduše přinutí stav qubitu α0+β1(s.t.α2+β2=1)\alpha|0\rangle+\beta|1\rangle \quad (s.t.|\alpha|^2+|\beta|^2=1) přejít buď do 0|0\rangle, nebo do 1|1\rangle, a my pozorujeme výsledek.

  • α2|\alpha|^2 je pravděpodobnost, že při měření dostaneme 0|0\rangle.
  • β2|\beta|^2 je pravděpodobnost, že při měření dostaneme 1|1\rangle.

Tedy α\alpha a β\beta se nazývají pravděpodobnostní amplitudy. (viz „Bornovo pravidlo")

Například 220+221\frac{\sqrt{2}}{2}|0\rangle+\frac{\sqrt{2}}{2}|1\rangle má při měření stejnou pravděpodobnost přechodu do 0|0\rangle nebo 1|1\rangle. 32012i1\frac{\sqrt{3}}{2}|0\rangle-\frac{1}{2}i|1\rangle má 75% šanci přejít do 0|0\rangle.

Qiskit Aer Simulator

Teď změříme Circuit, který připraví výše zmíněnou superpozici s rovnými pravděpodobnostmi. Přidáme měřicí Gate, protože Qiskit Aer simulator ve výchozím nastavení simuluje ideální kvantový hardware (bez šumu). Poznámka: Aer simulator může také aplikovat model šumu založený na skutečném kvantovém počítači. K modelům šumu se vrátíme později.

# Create a new circuit with one qubits (first argument) and one classical bits (second argument)
qc = QuantumCircuit(1, 1)
qc.h(0)
qc.measure(0, 0) # Add the measurement gate

qc.draw(output="mpl")

Output of the previous code cell

Jsme nyní připraveni spustit náš Circuit na Aer simulatoru. V tomto příkladu použijeme výchozí shots=1024, což znamená, že budeme měřit 1024krát. Poté zobrazíme tyto počty v histogramu.

# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'0': 521, '1': 503}

Output of the previous code cell

Vidíme, že hodnoty 0 a 1 byly naměřeny s pravděpodobností téměř 50 % každá. Přestože zde nebyl simulován šum, stavy jsou stále pravděpodobnostní. Takže i když očekáváme přibližně rozdělení 50:50, jen zřídka najdeme přesně takový výsledek. Stejně jako 100 hodů mincí by jen zřídka přineslo přesně 50 výskytů každé strany.

4. Multi-qubit quantum gate and entanglement

4.1 Multi-qubit quantum circuit

Dvouqubitový kvantový Circuit můžeme vytvořit pomocí následujícího kódu. Na každý Qubit aplikujeme Hadamard Gate.

# Create the two qubits quantum circuit
qc = QuantumCircuit(2)

# Apply an H gate to qubit 0
qc.h(0)

# Apply an H gate to qubit 1
qc.h(1)

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.5+0.j, 0.5+0.j, 0.5+0.j, 0.5+0.j],
dims=(2, 2))

Poznámka: Řazení bitů v Qiskitu

Qiskit používá pro řazení Qubitů a bitů notaci Little Endian, což znamená, že Qubit 0 je nejpravější bit v bitových řetězcích. Příklad: 01|01\rangle znamená, že q0 je 1|1\rangle a q1 je 0|0\rangle. Buď opatrný, protože část literatury v oblasti kvantových výpočtů používá notaci Big Endian (Qubit 0 je nejlevější bit) a stejně tak velká část literatury z kvantové mechaniky.

Další věcí, které si všimni, je, že při znázornění kvantového Circuitu je q0|q_0\rangle vždy umístěn v horní části Circuitu. S tímto na paměti lze kvantový stav výše uvedeného Circuitu zapsat jako tenzorový součin jednoqubitových kvantových stavů.

q1q0=(a0+b1)(c0+d1)|q1\rangle \otimes|q0\rangle = (a|0\rangle+b|1\rangle) \otimes (c|0\rangle+d|1\rangle)

=ac00+ad01+bc10+bd11= ac|0\rangle|0\rangle+ad|0\rangle|1\rangle+bc|1\rangle|0\rangle+bd|1\rangle|1\rangle

=ac00+ad01+bc10+bd11= ac|00\rangle+ad|01\rangle+bc|10\rangle+bd|11\rangle

( ac2+ad2+bc2+bd2=1|ac|^2+ |ad|^2+ |bc|^2+ |bd|^2=1 )

Počáteční stav Qiskitu je 00=00|0\rangle|0\rangle=|00\rangle, takže aplikováním HH na každý Qubit se změní na stav rovnoměrné superpozice.

H0H0=12(0+1)12(0+1)=12(00+01+10+11)H|0\rangle \otimes H|0\rangle=\frac{1}{\sqrt{2}}(|0\rangle+|1\rangle) \otimes \frac{1}{\sqrt{2}}(|0\rangle+|1\rangle) = \frac{1}{2}(|00\rangle+|01\rangle+|10\rangle+|11\rangle)

=12((11)(11))=12(1111)=12((1000)+(0100)+(0010)+(0001))=\frac{1}{2}\left( \begin{pmatrix} 1 \\ 1 \end{pmatrix} \otimes \begin{pmatrix} 1 \\ 1 \end{pmatrix}\right) = \frac{1}{2}\begin{pmatrix} 1 \\ 1 \\ 1 \\ 1 \end{pmatrix}=\frac{1}{2}\left(\begin{pmatrix} 1 \\ 0 \\ 0 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 1 \\ 0 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 0 \\ 1 \\ 0 \end{pmatrix}+\begin{pmatrix} 0 \\ 0 \\ 0 \\ 1 \end{pmatrix}\right)

Pravidlo měření je stejné jako v případě jednoqubitovém: pravděpodobnost naměření 00|00\rangle je ac2|ac|^2.

# Draw a Bloch sphere
plot_bloch_multivector(out_vector)

Output of the previous code cell

Teď tento Circuit změříme.

# Create a new circuit with two qubits (first argument) and two classical bits (second argument)
qc = QuantumCircuit(2, 2)

# Apply the gates
qc.h(0)
qc.h(1)

# Add the measurement gates
qc.measure(0, 0) # Measure qubit 0 and save the result in bit 0
qc.measure(1, 1) # Measure qubit 1 and save the result in bit 1

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

Nyní opět použijeme Aer simulator k experimentálnímu ověření, že relativní pravděpodobnosti všech možných výstupních stavů jsou přibližně stejné.

# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(mode=backend)
job = sampler.run([isa_qc])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'10': 262, '01': 246, '00': 265, '11': 251}

Output of the previous code cell

Jak bylo očekáváno, stavy 00|00\rangle, 01|01\rangle, 10|10\rangle, 11|11\rangle byly naměřeny přibližně z 25 % každý.

4.2 Multi-qubit quantum gates

CNOT Gate

CNOT Gate („controlled NOT" neboli CX) je dvouqubitový Gate, což znamená, že jeho akce zahrnuje dva Qubity najednou: řídící Qubit a cílový Qubit. CNOT překlopí cílový Qubit pouze tehdy, když je řídící Qubit ve stavu 1|1\rangle.

Vstup (cíl, řídící)Výstup (cíl, řídící)
0000
0111
1010
1101

Nejprve nasimulujme akci tohoto dvouqubitového Gate, když jsou q0 i q1 ve stavu 0|0\rangle, a získejme výstupní stavový vektor. Použitá Qiskit syntaxe je qc.cx(control qubit, target qubit).

# Create a circuit with two quantum registers and two classical registers
qc = QuantumCircuit(2, 2)

# Apply the CNOT (cx) gate to a |00> state.
qc.cx(0, 1) # Here the control is set to q0 and the target is set to q1.

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([1.+0.j, 0.+0.j, 0.+0.j, 0.+0.j],
dims=(2, 2))

Jak bylo očekáváno, aplikace CNOT Gate na 00|00\rangle nezměnila stav, protože řídící Qubit byl ve stavu 0|0\rangle. Vraťme se k naší operaci CNOT. Tentokrát aplikujeme CNOT Gate na 01|01\rangle a uvidíme, co se stane.

qc = QuantumCircuit(2, 2)

# q0=1, q1=0
qc.x(0) # Apply a X gate to initialize q0 to 1
qc.cx(0, 1) # Set the control bit to q0 and the target bit to q1.

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# See the statevector
out_vector = Statevector(qc)
print(out_vector)
Statevector([0.+0.j, 0.+0.j, 0.+0.j, 1.+0.j],
dims=(2, 2))

Aplikací CNOT Gate se stav 01|01\rangle změnil na 11|11\rangle.

Ověřme tyto výsledky spuštěním Circuit na simulátoru.

# Add measurements
qc.measure(0, 0)
qc.measure(1, 1)

# Draw the circuit
qc.draw(output="mpl")

Output of the previous code cell

# Run the circuit on a simulator to get the results
# Define backend
backend = AerSimulator()

# Transpile to backend
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

# Run the job
sampler = Sampler(backend)
job = sampler.run([isa_qc])
result = job.result()

# Print the results
counts = result[0].data.c.get_counts()
print(counts)

# Plot the counts in a histogram
plot_histogram(counts)
{'11': 1024}

Output of the previous code cell

Výsledky by ti měly ukázat, že 11|11\rangle bylo naměřeno se 100% pravděpodobností.

4.3 Quantum entanglement and execution on a real quantum device

Začněme představením konkrétního provázaného stavu, který je v kvantovém výpočtu obzvláště důležitý, a poté definujeme pojem „provázaný":

1200+1211\frac{1}{\sqrt{2}}|00\rangle + \frac{1}{\sqrt{2}}|11\rangle

a tento stav se nazývá Bell state.

Provázaný stav je stav ψAB|\psi_{AB}\rangle skládající se z kvantových stavů ψA|\psi_A\rangle a ψB|\psi_B\rangle, který nelze vyjádřit jako tenzorový součin jednotlivých kvantových stavů.

Pokud ψAB|\psi_{AB}\rangle níže obsahuje dva stavy ψA|\psi\rangle_A a ψB|\psi\rangle_B;

ψAB=12(00+11)=12(0A0B+1A1B)|\psi_{AB}\rangle = \frac{1}{\sqrt{2}}(|00\rangle +|11\rangle) = \frac{1}{\sqrt{2}}(|0\rangle_A|0\rangle_B +|1\rangle_A|1\rangle_B) ψA=a00+a11|\psi\rangle_A = a_0|0\rangle+a_1|1\rangle ψB=b00+b11|\psi\rangle_B = b_0|0\rangle+b_1|1\rangle

tenzorový součin těchto dvou stavů je následující

ψAψB=a0b000+a0b101+a1b010+a1b111|\psi\rangle _A\otimes |\psi\rangle _B = a_0 b_0|00\rangle+a_0 b_1|01\rangle+a_1 b_0|10\rangle+a_1 b_1|11\rangle

ale neexistují žádné koeficienty a0,a1,b0,a_0, a_1, b_0, a b1b_1, které by splňovaly tyto dvě rovnice. Proto ψAB|\psi_{AB}\rangle není vyjádřitelný jako tenzorový součin jednotlivých kvantových stavů ψA|\psi\rangle_A a ψB|\psi\rangle_B, což znamená, že ψAB=12(00+11)|\psi_{AB}\rangle = \frac{1}{\sqrt{2}}(|00\rangle +|11\rangle) je provázaný stav.

Vytvořme Bell state a spusťme ho na skutečném kvantovém počítači. Nyní budeme postupovat podle čtyř kroků pro psaní kvantového programu, které se nazývají Qiskit patterns:

  1. Map problem to quantum circuits and operators
  2. Optimize for target hardware
  3. Execute on target hardware
  4. Post-process the results

Krok 1. Namapování problému na Circuit a operátory

V kvantovém programu jsou Circuit nativním formátem pro reprezentaci kvantových instrukcí. Při vytváření Circuit obvykle vytvoříš nový objekt QuantumCircuit a pak do něj sekvenčně přidáváš instrukce.

Následující buňka kódu vytvoří Circuit, který produkuje Bell state, konkrétní dvouqubitový provázaný stav uvedený výše.

qc = QuantumCircuit(2, 2)

qc.h(0)
qc.cx(0, 1)

qc.measure(0, 0)
qc.measure(1, 1)

qc.draw("mpl")

Output of the previous code cell

Krok 2. Optimalizace pro cílový hardware

Qiskit převádí abstraktní Circuit na QISA (Quantum Instruction Set Architecture) Circuit, které respektují omezení cílového hardware, a optimalizuje výkon Circuit. Před optimalizací tedy určíme cílový hardware. Pokud nemáš nainstalováno qiskit-ibm-runtime, budeš ho nejprve muset nainstalovat. Více informací o Qiskit Runtime najdeš v referenci API.

# Install
# !pip install qiskit-ibm-runtime

Určíme cílový hardware.

from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
service.backends()
# You can specify the device
# backend = service.backend('ibm_kingston')
# You can also identify the least busy device
backend = service.least_busy(operational=True)
print("The least busy device is ", backend)

Transpilace Circuit je další složitý proces. Stručně řečeno, přepíše Circuit na logicky ekvivalentní pomocí „nativních Gate" (Gate, které dokáže konkrétní kvantový počítač implementovat) a namapuje Qubity ve tvém Circuit na optimální skutečné Qubity na cílovém kvantovém počítači. Více o transpilaci najdeš v této dokumentaci.

# Transpile the circuit into basis gates executable on the hardware
pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
target_circuit = pm.run(qc)

target_circuit.draw("mpl", idle_wires=False)

Vidíš, že při transpilaci byl Circuit přepsán pomocí nových Gate. Více informací najdeš v dokumentaci ECRGate.

Krok 3. Spuštění cílového Circuit

Nyní spustíme cílový Circuit na skutečném zařízení.

sampler = Sampler(backend)
job_real = sampler.run([target_circuit])

job_id = job_real.job_id()
print("job id:", job_id)

Spuštění na skutečném zařízení může vyžadovat čekání ve frontě, protože kvantové počítače jsou cenné zdroje a jsou velmi žádané. job_id se používá ke kontrole stavu spuštění a výsledků úlohy později.

# Check the job status (replace the job id below with your own)
job_real.status(job_id)

Stav úlohy můžeš také zkontrolovat ze svého IBM Quantum dashboardu:https://quantum.cloud.ibm.com/workloads

# If the Notebook session got disconnected you can also check your job status by running the following code
from qiskit_ibm_runtime import QiskitRuntimeService

service = QiskitRuntimeService()
job_real = service.job(job_id) # Input your job-id between the quotations
job_real.status()
# Execute after job has successfully run
result_real = job_real.result()
print(result_real[0].data.c.get_counts())

Krok 4. Post-processing výsledků

Nakonec musíme zpracovat naše výsledky a vytvořit výstupy v očekávaném formátu, například hodnoty nebo grafy.

plot_histogram(result_real[0].data.c.get_counts())

Jak vidíš, 00|00\rangle a 11|11\rangle jsou nejčastěji pozorované výsledky. Existuje několik výsledků jiných než očekávaná data a jsou způsobeny šumem a dekoherencí Qubitů. O chybách a šumu v kvantových počítačích se dozvíme více v pozdějších lekcích tohoto kurzu.

GHZ stav

Koncept provázání lze rozšířit na systémy s více než dvěma qubity. GHZ stav (Greenberger-Horne-Zeilinger stav) je maximálně provázaný stav tří nebo více qubitů. GHZ stav pro tři qubity je definován jako

12(000+111)\frac{1}{\sqrt 2}(|000\rangle + |111\rangle)

Lze ho vytvořit pomocí následujícího kvantového Circuit.

qc = QuantumCircuit(3, 3)

qc.h(0)
qc.cx(0, 1)
qc.cx(1, 2)

qc.measure(0, 0)
qc.measure(1, 1)
qc.measure(2, 2)

qc.draw("mpl")

Output of the previous code cell

„Hloubka" kvantového Circuit je užitečná a běžně používaná metrika pro popis kvantových obvodů. Sleduj cestu skrz kvantový Circuit zleva doprava, přičemž měníš qubity pouze tehdy, jsou-li propojeny vícequbitovým Gate. Počítej počet Gate podél této cesty. Maximální počet Gate pro jakoukoli takovou cestu skrz Circuit je jeho hloubka. V moderních hlučných kvantových počítačích mají Circuit s malou hloubkou méně chyb a pravděpodobněji vrátí dobré výsledky. Velmi hluboké Circuit to tak nemají.

Pomocí QuantumCircuit.depth() můžeme zkontrolovat hloubku našeho kvantového Circuit. Hloubka výše uvedeného Circuit je 4. Horní Qubit má pouze tři Gate včetně měření. Ale existuje cesta z horního qubitu dolů k qubitu 1 nebo qubitu 2, která zahrnuje další CNOT Gate.

qc.depth()
4

Cvičení 2

GHZ stav 8-qubitového systému je

12(00000000+11111111)\frac{1}{\sqrt 2}(|00000000\rangle + |11111111\rangle)

Napiš kód pro přípravu tohoto stavu s co nejmělčím možným Circuit. Hloubka nejmělčího kvantového Circuit je 5, včetně měřicích Gate.

Řešení:

# Step 1
qc = QuantumCircuit(8, 8)

##your code goes here##
qc.h(0)
qc.cx(0, 4)
qc.cx(4, 6)
qc.cx(6, 7)

qc.cx(4, 5)

qc.cx(0, 2)
qc.cx(2, 3)

qc.cx(0, 1)
qc.barrier() # for visual separation

# measure
for i in range(8):
qc.measure(i, i)

qc.draw("mpl")
# print(qc.depth())

Output of the previous code cell

print(qc.depth())
5
from qiskit.visualization import plot_histogram
# Step 2
# For this exercise, the circuit and operators are simple, so no optimizations are needed.

# Step 3
# Run the circuit on a simulator to get the results
backend = AerSimulator()

pm = generate_preset_pass_manager(backend=backend, optimization_level=1)
isa_qc = pm.run(qc)

sampler = Sampler(mode=backend)
job = sampler.run([isa_qc], shots=1024)
result = job.result()

counts = result[0].data.c.get_counts()
print(counts)

# Step 4
# Plot the counts in a histogram

plot_histogram(counts)
{'11111111': 535, '00000000': 489}

Output of the previous code cell

5. Shrnutí

Naučil ses kvantové výpočty s modelem Circuit pomocí kvantových bitů a Gate, a zopakoval sis superpozici, měření a provázání. Také ses naučil metodu pro spouštění kvantového Circuit na skutečném kvantovém zařízení.

V závěrečném cvičení na vytvoření GHZ Circuit ses pokusil snížit hloubku Circuit, což je důležitý faktor pro dosažení řešení v měřítku utility na hlučném kvantovém počítači. V pozdějších lekcích tohoto kurzu se dozvíš podrobnosti o hluku a metodách potlačení chyb. V této lekci jsme jako úvod uvažovali o snižování hloubky Circuit na ideálním zařízení, ale ve skutečnosti musíme brát v úvahu omezení reálného zařízení, jako je konektivita qubitů. Více se o tom dozvíš v dalších lekcích tohoto kurzu.

# See the version of Qiskit
import qiskit

qiskit.__version__
'2.0.2'