Przejdź do głównej treści

Zacznij pracę z Qiskit w klasie

W tym module Qiskit w Klasie uczniowie muszą mieć działające środowisko Python z zainstalowanymi następującymi pakietami:

  • qiskit w wersji 2.1.0 lub nowszej
  • qiskit-ibm-runtime w wersji 0.40.1 lub nowszej
  • qiskit-aer w wersji 0.17.0 lub nowszej
  • qiskit.visualization
  • numpy
  • pylatexenc

Aby skonfigurować i zainstalować powyższe pakiety, zapoznaj się z przewodnikiem Instalacja Qiskit. Aby uruchamiać zadania na prawdziwych komputerach kwantowych, uczniowie muszą założyć konto w IBM Quantum®, postępując zgodnie z instrukcjami w przewodniku Konfiguracja konta IBM Cloud®.

Ten moduł został przetestowany i wykorzystał 2 sekundy czasu QPU na procesorze Heron v2. Jest to wyłącznie szacunek. Twoje rzeczywiste zużycie może się różnić.

# 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'

Wprowadzenie

W modułach Qiskit w Klasie będziesz mieć okazję użyć komputera kwantowego do eksploracji różnych pojęć z dziedzin powiązanych z obliczeniami kwantowymi, takich jak mechanika kwantowa, informatyka, chemia i inne. Ten moduł stanowi warunek wstępny dla pozostałych — wprowadza podstawy obliczeń kwantowych oraz sposób korzystania z Qiskit do uruchamiania obwodów kwantowych.

Najpierw damy ci krótki przegląd działania klasycznego komputera, a następnie pokażemy, jak te pojęcia są adaptowane do paradygmatu obliczeń kwantowych. Na koniec pokażemy, jak połączyć te koncepcje, aby zbudować i uruchomić swój pierwszy obwód kwantowy.

Komputery klasyczne

Prawdopodobnie znasz już podstawy działania komputerów klasycznych, ale tutaj wyróżnimy kilka kluczowych cech, abyśmy mogli następnie przeprowadzić porównanie z komputerami kwantowymi.

Podstawowe jednostki informacji: bity

Komputery klasyczne przetwarzają informacje klasyczne, a podstawową jednostką informacji klasycznej jest bit. Pojedynczy bit może przechowywać odpowiedź na jedno pytanie „tak/nie". Dwa stany binarne bitu reprezentujemy zazwyczaj jako „0" i „1".

Przypomnienie liczb binarnych

Łączenie bitów pozwala przechowywać więcej informacji. Na przykład, jeśli chcesz przechować liczbę od 0 do 15, możesz to zrobić za pomocą czterech bitów w następujący sposób:

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

Ogólnie rzecz biorąc, aby przekonwertować liczbę binarną o NN bitach na znajomą liczbę w systemie dziesiętnym, mnożysz bit o najmniejszym znaczeniu (skrajny prawy) przez 20=12^0 = 1, następny bit z lewej przez 21=22^1 = 2, kolejny przez 22=42^2 = 4 i tak dalej, aż do bitu o największym znaczeniu (skrajny lewy), który mnożysz przez 2N12^{N-1}.

A zatem NN bitów może znajdować się w jednym z 2N2^N różnych możliwych stanów.

Sprawdź swoją wiedzę

Przeczytaj poniższe pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odsłonić rozwiązanie.

Ile bitów potrzeba, aby zapisać liczbę 86? Napisz bitstring kodujący tę liczbę w systemie binarnym.

Odpowiedź:

Pamiętaj, że NN bitów pozwala reprezentować liczby od 00 do 2N12^N - 1, więc sześć bitów daje nam zakres do 261=632^6 - 1 = 63. To trochę za mało. Dodajemy jeszcze jeden bit, aby uzyskać zakres do 271=1272^7 - 1 = 127. Teraz rozłóżmy 86 na potęgi liczby 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}

Podstawowe operacje: bramki

Komputer musi być w stanie coś robić z bitami, aby móc — no cóż — obliczać. Bramki binarne to operacje stanowiące podstawowe elementy składowe wszystkich bardziej skomplikowanych algorytmów i kodów.

Bramka jednobitowa:

NOT

Gdy masz tylko jeden bit, istnieje tylko jeden sposób na zmianę jego stanu: odwrócenie stanu z 0 na 1 lub z 1 na 0. Nazywamy to bramką „NOT". Efekt tej bramki — i pozostałych bramek omawianych poniżej — można przedstawić w tak zwanej „tabeli prawdy", z kolumnami dla stanów wejściowych i wyjściowych qubitów. Tabela prawdy dla bramki NOT wygląda następująco:

WejścieWyjście
01
10

Bramki wielobitowe:

AND

AND to bramka dwubitowa, która przyjmuje dwa bity wejściowe i daje jeden bit wyjściowy. Zwraca 1, jeśli oba bity wejściowe wynoszą 1, w przeciwnym razie 0:

WejścieWyjście
000
010
100
111

OR

OR to kolejna bramka dwubitowa z jednym bitem wyjściowym. Zwraca 1, jeśli którykolwiek z bitów wynosi 1:

WejścieWyjście
000
011
101
111

XOR

XOR oznacza „exclusive OR" (wyłączne OR) i działa jak bramka OR, ale zwraca 1 tylko wtedy, gdy dokładnie jeden z bitów wejściowych wynosi 1. Zwraca 0, jeśli oba wynoszą 1 lub oba wynoszą 0:

WejścieWyjście
000
011
101
110

Pomiary:

Zazwyczaj, ucząc się o obliczeniach klasycznych, nie poświęca się zbyt wiele uwagi procesowi odczytu stanu bitów. Wynika to z faktu, że nie jest to zbyt skomplikowane z konceptualnego punktu widzenia. Możesz mierzyć bity w dowolnym momencie — przed, w trakcie lub po obliczeniach — i nie wpływa to na wynik. W obliczeniach kwantowych sytuacja jest inna, jak omówimy poniżej.

Obwody:

Łącząc powyższe bramki, możesz wykonać dowolną operację na komputerze. Weźmy prosty przykład: używając bramek AND i XOR, można zbudować obwód półsumatora, który oblicza sumę dwóch bitów. Jest to przedstawione na schemacie obwodu logicznego, gdzie przewody reprezentują bity, a bramki operujące na bitach są pokazane jako symbole na odpowiednich przewodach:

Schemat klasycznego obwodu dla układu półsumatora. Bramka XOR generuje bit wyjściowy Sumy, a bramka AND generuje bit wyjściowy Przeniesienia.

A zatem dwa bity są kopiowane i przepuszczane zarówno przez bramkę AND, jak i XOR. Wynik bramki XOR to „bit sumy" (S), który pozostaje na miejscu jedności liczby binarnej, natomiast wynik bramki AND to „bit przeniesienia" (C), który jest wartością kolejnej najbardziej znaczącej cyfry w liczbie binarnej. Oto tabela prawdy:

AABBSuma (ABA \oplus B)Przeniesienie (ABA \wedge B)
0000
0110
1010
1101

Sprawdź swoją wiedzę

Przeczytaj poniższe pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odsłonić rozwiązanie.

Zweryfikuj, że powyższa tabela prawdy daje poprawny wynik dla obwodu sumatora. To znaczy, dla każdej z czterech kombinacji A i B, sprawdź, czy A+B=S+2×CA+B=S+2 \times C.

Odpowiedź:

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}

Komputery kwantowe

Bity \rightarrow Qubit

Tak jak bity są podstawowymi jednostkami klasycznej informacji, kwantowe bity, czyli „Qubit", są podstawowymi jednostkami informacji kwantowej. Podobnie jak klasyczny bit, stan Qubit może wynosić 0 lub 1, co zwykle oznaczamy jako 0\vert 0\rangle i 1\vert 1\rangle. Jednak w przeciwieństwie do klasycznego bitu, Qubit może też znajdować się w superpozycji stanu 0\vert 0\rangle i stanu 1\vert 1\rangle jednocześnie. Ogólnie rzecz biorąc, Qubit może być w dowolnym stanie ψ\vert \psi\rangle postaci:

ψ=c00+c11\vert \psi\rangle = c_0 \vert 0\rangle + c_1 \vert 1\rangle

gdzie c0c_0 i c1c_1 są zespolonymi amplitudami spełniającymi warunek c02+c12=1\vert c_0 \vert ^2+\vert c_1\vert ^2=1.

Faza kwantowa

Ponieważ c0c_0 i c1c_1 są zespolone, każdą z nich można zapisać jako ci=cieiϕic_i = \vert c_i\vert e^{i\phi_i}, gdzie ϕi\phi_i nazywamy fazą. Jeśli pomnożymy cały stan przez ten sam globalny czynnik fazowy, nic fizycznie się nie zmienia — nazywamy to fazą globalną i nie ma ona żadnych obserwowalnych konsekwencji.

Z tego powodu przyjęło się „wyłączać" eiϕ0e^{i\phi_0} przed nawias, co daje:

ψ=c00+c1eiϕ1\vert \psi\rangle = \vert c_0\vert \vert 0\rangle + \vert c_1\vert e^{i\phi}\vert 1\rangle

gdzie ϕ=ϕ1ϕ0\phi = \phi_1-\phi_0 jest względną fazą stanu kwantowego, która ma obserwowalne konsekwencje.

Faza ta odgrywa bardzo ważną rolę w obliczeniach kwantowych — jej różnorodne konsekwencje poznasz w kolejnych modułach Qiskit w klasie.

Wiele Qubit

O ile stan wielu bitów można było wyrazić po prostu jako ciąg zer i jedynek, o tyle stan wielu Qubit jest nieco bardziej skomplikowany ze względu na zasady superpozycji i splątania.

Przypomnij sobie, że NN bitów może przyjmować jeden z 2N2^N możliwych stanów — od binarnego 000...000 do 111...111. Teraz jednak, dzięki zasadzie superpozycji, NN Qubit może być jednocześnie w superpozycji wszystkich tych stanów!

Można to wyrazić jako

ψN=i=02N1cii\psi_N = \sum_{i=0}^{2^N-1} c_i \vert i\rangle

gdzie, podobnie jak w przypadku klasycznym, stan i\vert i\rangle odpowiada stanowi, w którym każdy Qubit przyjmuje odpowiednią kombinację zer i jedynek tworzącą liczbę binarną ii. Stany te znane są jako „obliczeniowe stany bazowe" układu kwantowego. Na przykład stan trzech Qubit można zapisać jako superpozycję ośmiu obliczeniowych stanów bazowych:

ψ3=c0000+c1001+c2010+c3011+c4100+c5101+c6110+c7111\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

Każdy Qubit w układzie jest oznaczony indeksem od 00 do N1N-1. Przyjęta konwencja zakłada odczytywanie stanów Qubit od prawej do lewej, tak że stan Qubit 00 jest stanem znajdującym się najdalej po prawej, a stan Qubit N1N-1 — najdalej po lewej. Taka notacja nazywa się „little-endian" i może początkowo wydawać się nieintuicyjna, skoro jesteśmy przyzwyczajeni do czytania od lewej do prawej.

Sprawdź swoje rozumienie

Przeczytaj poniższe pytanie/pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, by zobaczyć rozwiązanie.

Na pierwszy rzut oka porządkowanie Qubit od prawej do lewej, jak w notacji little-endian, może wydawać się nieintuicyjne, lecz jest to w rzeczywistości bardzo logiczne! Wyjaśnij dlaczego. (Przypomnij sobie omówiony wcześniej sposób zamiany liczb binarnych na dziesiętne.)

Odpowiedź:

Jeśli Qubit numerujemy od prawej do lewej, tak że Qubit 0 jest najdalej po prawej, a Qubit N-1 najdalej po lewej, logiczne jest powiązanie Qubit 00 z bitem najmniej znaczącym, mnożonym przez 202^0, oraz Qubit N1N-1 z bitem najbardziej znaczącym, mnożonym przez 2N12^{N-1}.

Splątanie

Jak wspomnieliśmy wcześniej, kolejną kluczową właściwością Qubit jest możliwość splątania ich ze sobą. Weźmy przykład stanu dwóch Qubit, gdzie c0=c3=12c_0 = c_3 = \frac{1}{\sqrt{2}} i c1=c2=0c_1 = c_2 = 0:

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

Stan Qubit 0 może być zatem równy 0\vert 0\rangle lub 1\vert 1\rangle z jednakowym prawdopodobieństwem — tak samo w przypadku Qubit 1. Jednak te prawdopodobieństwa nie są już od siebie niezależne. Jeśli zmierzymy stan Qubit 0 i okaże się, że wynosi 0\vert 0\rangle, to wiemy, że Qubit 1 również będzie w stanie 0\vert 0\rangle. Jest to prawdą niezależnie od tego, jak daleko od siebie się znajdują — dlatego pomiar splątanego stanu bywa określany mianem „upiornego działania na odległość".

Splątanie może przybierać też inne formy. Na przykład stan

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

za każdym razem daje przeciwne wyniki: jeśli jeden Qubit zostaje zmierzony jako 0\vert 0\rangle, drugi jest gwarantowanie w stanie 1\vert 1\rangle.

Sprawdź swoje rozumienie

Przeczytaj poniższe pytanie/pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, by zobaczyć rozwiązanie.

Czy stan ψ=11\vert \psi\rangle = \vert 11\rangle jest splątany? Dlaczego tak lub dlaczego nie?

Odpowiedź:

Nie jest splątany. Choć wyniki pomiaru obu Qubit są zawsze takie same, wynika to jedynie z tego, że każdy Qubit jest na stałe w stanie 1\vert 1\rangle. Wynik pomiaru jednego Qubit faktycznie nie zależy od drugiego — oba po prostu zawsze wynoszą 1\vert 1\rangle.

Ogólnie rzecz biorąc, jeśli możesz opisać stan każdego Qubit osobno, a następnie pomnożyć je przez siebie w taki sposób:

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

to taki stan nazywamy „stanem produktowym" i nie jest on splątany.

Notacja wektorowa

Często przydatne jest użycie wektorów i macierzy, by zobaczyć, jak stan kwantowy przekształca się pod wpływem różnych operacji. W tej reprezentacji stany kwantowe są wektorami, a Gate kwantowe (omówione w następnej sekcji) — macierzami przekształcającymi te wektory.

Dla pojedynczego Qubit wektorowe postacie stanów przyjmuje się jako: 0=(10)\vert 0\rangle = \begin{pmatrix}1 \\ 0\end{pmatrix} 1=(01)\vert 1\rangle = \begin{pmatrix}0 \\ 1\end{pmatrix} W ten sposób dowolny stan ψ=a0+b1\vert \psi\rangle = a\vert 0\rangle+b\vert 1\rangle można zapisać jako ψ=(ab)\vert \psi\rangle =\begin{pmatrix}a \\ b\end{pmatrix}

Dla ogólnego stanu nn Qubit potrzebujemy wektora o 2n2^n wymiarach, ze stanami bazowymi uporządkowanymi w rosnącym porządku binarnym, zgodnie z oczekiwaniami:

0000=(1000),0001=1110=(0010),1111=(0001)\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}

Mając tę notację wektorową na uwadze, możemy przejść do potrzebnych Gate kwantowych, ich działania na stany kwantowe oraz ich postaci macierzowych.

Sprawdź swoje rozumienie

Przeczytaj poniższe pytanie/pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, by zobaczyć rozwiązanie.

Dla układu dwóch Qubit istnieją cztery obliczeniowe stany bazowe. Zapisz każdy z nich w notacji ket oraz w notacji wektorowej.

Odpowiedź:

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}

Gates \rightarrow kwantowe Gate'y

Podobnie jak klasyczne Gate'y, takie jak NOT, AND, OR i XOR, można łączyć w celu budowania dowolnych klasycznych Circuit'ów, kwantowe Gate'y odgrywają tę samą rolę w obliczeniach kwantowych. Ponieważ Qubity posiadają dodatkowe właściwości mechaniki kwantowej, kwantowe Gate'y są odpowiednio bogatsze. Choć nadal możemy opisać ich działanie na stany bazowe 0|0\rangle i 1|1\rangle za pomocą tablicy prawdy, nie oddaje to pełnego obrazu. W przypadku kwantowych Gate'ów często bardziej naturalne jest użycie reprezentacji macierzowej, ponieważ działają one również na superpozycje stanów bazowych.

Poniżej przedstawimy najczęściej stosowane kwantowe Gate'y i sposób, w jaki przekształcają one oddziałujące z nimi Qubity. Tam, gdzie to możliwe, połączymy je ze znajomymi klasycznymi Gate'ami.

Jednobitowe Gate'y (Single-qubit gates)

Gate XX: Jest to kwantowy odpowiednik operacji NOT. Jego tablica prawdy wygląda dokładnie tak jak klasyczny Gate NOT:

WejścieWyjście
0\vert 0\rangle1\vert 1\rangle
1\vert 1\rangle0\vert 0\rangle

Reprezentacja macierzowa:

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

W Qiskit tworzenie Circuit'u z Gate'em XX wygląda następująco:

from qiskit import QuantumCircuit

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

Output of the previous code cell

W tym bardzo prostym diagramie Circuit'u Qubit jest reprezentowany przez przewód – czarną poziomą linię – a Gate pojawia się jako prostokąt na tym przewodzie.

Gate Hadamarda: Tworzy stan superpozycji. Tablica prawdy:

WejścieWyjście
0\vert 0\rangle12(0+1)\frac{1}{\sqrt{2}}\left(\vert 0\rangle+\vert 1\rangle\right)
1\vert 1\rangle12(01)\frac{1}{\sqrt{2}}\left(\vert 0\rangle-\vert 1\rangle\right)

Reprezentacja macierzowa: H=12(1111)H=\frac{1}{\sqrt{2}}\begin{pmatrix} 1 & 1 \\ 1 & -1 \end{pmatrix}

Circuit z Gate'em Hadamarda tworzy się w następujący sposób:

from qiskit import QuantumCircuit

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

Output of the previous code cell

Gate ZZ: Dodaje przesunięcie fazowe Δϕ=π\Delta \phi = \pi do stanu 1|1\rangle:

WejścieWyjście
0\vert 0\rangle0\vert 0\rangle
1\vert 1\rangle1-\vert 1\rangle

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

W Qiskit tworzenie Circuit'u z Gate'em ZZ wygląda następująco:

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

Output of the previous code cell

Gate TT: Dodaje przesunięcie fazowe Δϕ=π/4\Delta \phi = \pi/4 do stanu 1|1\rangle:

WejścieWyjście
0\vert 0\rangle0\vert 0\rangle
1\vert 1\rangleeiπ/41e^{i\pi/4}\vert 1\rangle

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

W Qiskit tworzenie Circuit'u z Gate'em TT wygląda następująco:

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

Output of the previous code cell

Wielobitowe Gate'y (Multi-qubit gates)

Dwubitowe Gate'y mogą przypominać klasyczne Gate'y dwubitowe, ale z jednym istotnym zastrzeżeniem: wszystkie kwantowe Gate'y muszą być odwracalne. W terminologii algebry liniowej oznacza to, że są reprezentowane przez macierze unitarne. Dlatego dwa wejściowe Qubity zawsze odwzorowują się na dwa wyjściowe Qubity, a operację można co do zasady cofnąć. Stoi to w sprzeczności z klasycznymi Gate'ami, takimi jak AND czy OR, które tracą informację i są nieodwracalne – znając wyjście, nie możesz jednoznacznie ustalić wejścia.

Gate CNOT (Controlled-NOT): Dwa wejściowe Qubity noszą nazwy Qubitu „sterującego" (control) i Qubitu „docelowego" (target). Qubit sterujący pozostaje niezmieniony, lecz jego stan decyduje o tym, co dzieje się z Qubitem docelowym. Jeśli Qubit sterujący jest w stanie 1\vert 1\rangle, to Gate XX jest stosowany do Qubitu docelowego; jeśli stan Qubitu sterującego wynosi 0\vert 0\rangle, żadna zmiana nie jest wprowadzana. W poniższej notacji zakładamy, że Qubit AA (skrajny prawy) jest sterującym, a Qubit BB (skrajny lewy) jest docelowym. Poniżej stosowana notacja to CNOT(qcontrol,qtarget)BA.CNOT(q_{control},q_{target})\vert BA\rangle.

CNOT(A,B)BAinput=BAoutputCNOT(A,B)\vert BA\rangle_{input} = \vert BA\rangle_{output}

WejścieWyjście
00\vert 00\rangle00\vert 00\rangle
01\vert 01\rangle11\vert 11\rangle
10\vert 10\rangle10\vert 10\rangle
11\vert 11\rangle01\vert 01\rangle

Zatem macierz reprezentująca tę operację to:

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

To pierwszy diagram Circuit'u, który widzimy z dwoma Qubitami, reprezentowanymi przez dwa przewody. Gate CNOT jest zastosowany między dwoma Qubitami, przy czym q0q_0 pełni rolę sterującego, a q1q_1 docelowego.

Sprawdź swoje zrozumienie

Przeczytaj poniższe pytanie(-a), zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odsłonić rozwiązanie.

Większość Gate'ów ma tę samą postać macierzową w Qiskit co wszędzie indziej. Jednak Gate CNOT działa na dwa Qubity, więc nagle konwencje kolejności Qubitów stają się problemem. Teksty, które porządkują Qubity jako q0,q1,...\vert q_0,q_1,...\rangle, będą pokazywać inną postać macierzową Gate'u CNOT. Zweryfikuj przez jawne mnożenie macierzy, że powyższa macierz CNOT ma właściwe działanie na stan 01.\vert 01\rangle.

Odpowiedź:

CNOT01=(1000000100100100)(0100)=(0001)=11CNOT\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: Ten Gate zamienia stany dwóch Qubitów. Tablica prawdy:

WejścieWyjście
00\vert 00\rangle00\vert 00\rangle
01\vert 01\rangle10\vert 10\rangle
10\vert 10\rangle01\vert 01\rangle
11\vert 11\rangle11\vert 11\rangle

Zatem macierz reprezentująca tę operację to:

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

Gate SWAP można w rzeczywistości zbudować z trzech Gate'ów CNOT. Aby zobaczyć jak, możemy rozłożyć (decompose()) Gate za pomocą Qiskit:

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

Output of the previous code cell

Widzimy tu po raz pierwszy, jak wiele Gate'ów jest przedstawianych w diagramie Circuit'u. Czytamy go od lewej do prawej, więc skrajny lewy Gate jest stosowany jako pierwszy.

Sprawdź swoje zrozumienie

Przeczytaj poniższe pytanie(-a), zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odsłonić rozwiązanie.

Zweryfikuj, że powyższa kombinacja Gate'ów CNOT daje w wyniku Gate SWAP. Możesz to zrobić poprzez mnożenie macierzy lub dowolną inną metodę.

Odpowiedź:

Za pomocą mnożenia macierzy:

(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

Za pomocą tablicy prawdy, aby zobaczyć jak stany zmieniają się przy każdym CNOT. W ostatniej kolumnie stany powinny odpowiadać kolumnie „wyjście" tablicy prawdy SWAP:

WejścieCNOT(A,B)CNOT(B,A)CNOT(A,B)
00\vert 00\rangle00\vert 00\rangle00\vert 00\rangle00\vert 00\rangle \checkmark
01\vert 01\rangle11\vert 11\rangle10\vert 10\rangle10\vert 10\rangle \checkmark
10\vert 10\rangle10\vert 10\rangle11\vert 11\rangle01\vert 01\rangle \checkmark
11\vert 11\rangle01\vert 01\rangle01\vert 01\rangle11\vert 11\rangle \checkmark

Gate Toffoliego (czyli „controlled-controlled-NOT" (CCNOT)): Jest to Gate działający na trzy Qubity. Nazwa „controlled-controlled-NOT" może już podpowiadać, jak działa: są dwa Qubity sterujące i jeden Qubit docelowy, a stan Qubitu docelowego jest odwracany tylko wtedy, gdy oba Qubity sterujące są w stanie 1\vert 1\rangle. Zachowujemy konwencję kolejności, którą stosowaliśmy przy CNOT:

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

Zatem tablica prawdy wygląda następująco:

WejścieWyjście
000\vert 000\rangle000\vert 000\rangle
001\vert 001\rangle001\vert 001\rangle
010\vert 010\rangle010\vert 010\rangle
011\vert 011\rangle111\vert 111\rangle
100\vert 100\rangle100\vert 100\rangle
101\vert 101\rangle101\vert 101\rangle
110\vert 110\rangle110\vert 110\rangle
111\vert 111\rangle011\vert 011\rangle

Macierz reprezentująca tę operację to:

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

Gate Toffoliego również można rozłożyć na Gate'y CNOT wraz z kilkoma innymi Gate'ami. Jest to jednak znacznie bardziej skomplikowane niż dekompozycja Gate'u SWAP, dlatego zostanie pozostawione jako opcjonalne ćwiczenie na końcu modułu do samodzielnego zbadania i weryfikacji tej dekompozycji.

Pomiary

Pomiary pełnią w obliczeniach kwantowych szczególną rolę, która nie ma analogu w klasycznych komputerach. W przypadku klasycznych komputerów możesz sprawdzić stan bitów w dowolnym momencie algorytmu, natomiast w obliczeniach kwantowych musisz bardzo starannie dobierać chwilę, w której patrzysz na swoje Qubity — pomiar powoduje kolaps stanu i niszczy superpozycję, która nadaje Qubitom ich obliczeniową złożoność.

W szczególności, dla NN-bitowego stanu kwantowego ψ=i=02N1cii\vert \psi\rangle = \sum_{i=0}^{2^N-1} c_i \vert i\rangle, pomiar spowoduje kolaps stanu do jednej z funkcji bazowych i\vert i\rangle z prawdopodobieństwem równym ci2\vert c_i\vert ^2.

Jednak ten destrukcyjny efekt pomiaru nie zawsze jest przeszkodą. W rzeczywistości jest kluczowym zasobem w pewnych algorytmach i protokołach, takich jak teleportacja kwantowa i kwantowa dystrybucja klucza.

W Qiskit, gdy wykonywany jest pomiar, jego wynik trafia do klasycznego rejestru, gdzie jest przechowywany jako klasyczny bit. Tworzenie Circuit z pomiarem wygląda następująco:

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

Circuits

Teraz, gdy wiemy już, jak działają Qubity, Gate'y i pomiary, stwórzmy i wykonajmy własny Circuit kwantowy! W tym celu zapoznamy cię z przydatnym przepływem pracy zwanym wzorcami Qiskit.

Wzorzec Qiskit patterns framework

Qiskit patterns framework to ogólna procedura podejścia do problemów i ich rozwiązywania za pomocą komputera kwantowego. Składa się z czterech kroków:

  1. Mapowanie naszego problemu na Circuits kwantowe i operatory
  2. Optymalizowanie Circuit pod kątem docelowego sprzętu
  3. Wykonanie na docelowym sprzęcie
  4. Post-processing wyników

Aby zilustrować te kroki, zaimplementujemy kwantową wersję omówionego powyżej układu półsumatora.

1. Mapowanie

Klasyczny układ sumatora używa bramki XOR i bramki AND do obliczenia odpowiednio bitu sumy i bitu przeniesienia. Możemy zaadaptować te Gate'y do kontekstu kwantowego, aby stworzyć kwantowy półsumator. Pamiętając, że Gate'y kwantowe są odwracalne, nie możemy po prostu nadpisać danych wejściowych. Zamiast tego wprowadzamy dwa pomocnicze Qubity zainicjowane w stanie 0\vert 0\rangle, które będą przechowywać wyjścia sumy i przeniesienia. Nasz pełny stan kwantowy będzie więc składał się z Qubitów AA i BB oraz Qubitów sumy i przeniesienia, które oznaczymy SS i CC:

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

Teraz potrzebujemy Gate'ów kwantowych, które wykonają to samo, co Gate'y XOR i AND w klasycznym układzie.

Suma:

Dla XOR stosujemy dwa CNOT-y, każdy z Qubitami sterującymi AA i BB oraz Qubit docelowym SS dla obu. Jeśli AA i BB są różne, jeden z Gate'ów CNOT przerzuci SS do stanu 1\vert 1\rangle. Jeśli AA i BB są oba 0\vert 0\rangle, nic się nie dzieje z SS i pozostaje on w stanie 0\vert 0\rangle. Jeśli AA i BB są oba 1\vert 1\rangle, stan SS zostanie przerzucony dwukrotnie, wracając do stanu 0\vert 0\rangle.

Przeniesienie:

Dla bitu przeniesienia potrzebujemy czegoś, co działa jak klasyczna bramka AND.

Sprawdź swoją wiedzę

Przeczytaj poniższe pytanie(-a), zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odkryć rozwiązanie.

Przejrzyj omówione Gate'y i sprawdź, czy potrafisz zgadnąć, którego Gate'a kwantowego użyjemy zamiast klasycznej bramki AND:

Odpowiedź:

To Gate Toffoli! Pamiętaj, Gate Toffoli, czyli bramka controlled-controlled-NOT, przerzuca stan docelowy wtedy i tylko wtedy, gdy Qubit sterujący 0 ORAZ Qubit sterujący 1 są oba w stanie 1\vert 1\rangle. Zatem jeśli Qubit docelowy zaczyna w stanie 0\vert 0\rangle, działa tak samo jak bramka AND.

Mamy więc już wszystkie składniki potrzebne do stworzenia Circuit kwantowego:

# 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

Powyżej przedstawiony jest diagram Circuit kwantowego półsumatora. Jak wspomniano wcześniej, przewody reprezentują Qubity 00 do 33 uporządkowane od góry do dołu, a dolny przewód z podwójną linią to rejestr klasycznych bitów. Czytając diagram od lewej do prawej, widzimy, jak Gate'y są stosowane do każdego Qubitu, obserwując, gdzie pojawiają się pola na odpowiadających im przewodach. Na końcu widoczne są pomiary. Pomiary powodują kolaps stanów Qubitów do określonych wartości 00 lub 11, a wyniki trafiają do klasycznego rejestru.

Jedna subtelność: choć diagram Circuit rysowany jest od lewej do prawej, pisząc odpowiadające mu wyrażenie macierzowe, musimy czytać je od prawej do lewej. Wynika to z tego, że w mnożeniu macierzy operator najbliższy wektorowi stanu działa jako pierwszy. Na przykład powyższy Circuit (pomijając pomiary) zapisalibyśmy jako:

CCNOT(q0,q1,q3)CNOT(q1,q2)CNOT(q0,q2)q3q2q1q0CCNOT(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. Optymalizowanie:

Następnie musimy zoptymalizować Circuit do uruchomienia na sprzęcie kwantowym. Ta optymalizacja jest realizowana przez Transpiler, który tłumaczy abstrakcyjny Circuit pokazany powyżej na instrukcje zrozumiałe dla komputera kwantowego. Przypisuje logiczne Qubity do rzeczywistych, fizycznych Qubitów na procesorze i przepisuje Gate'y w kategoriach własnego natywnego zestawu Gate'ów zoptymalizowanego do działania na komputerze kwantowym. Wreszcie Transpiler implementuje również coś, co nazywa się „tłumieniem i łagodzeniem błędów", aby zminimalizować wpływ błędów na wynik. Dla naszego bardzo prostego Circuit nie jest to tak istotne, ale jeśli będziesz kontynuować swoją przygodę z obliczeniami kwantowymi i uruchamiać bardziej skomplikowane Circuits, szybko docenisz wartość tłumienia i łagodzenia błędów. Jeśli chcesz dowiedzieć się więcej na ten temat, zapoznaj się z kursem Olivii Lane, Quantum Computing in Practice.

Na początku ładujemy pakiety wymagane do komunikacji z komputerami kwantowymi IBM® i wybieramy Backend, na którym będziemy uruchamiać zadania. Możemy wybrać najmniej zajęty Backend albo wybrać konkretny Backend, o którego właściwościach wiemy.

Poniżej znajduje się kod do jednorazowego zapisania twoich poświadczeń. Pamiętaj, aby usunąć te informacje z notatnika po zapisaniu ich w swoim środowisku, żeby poświadczenia nie zostały przypadkowo ujawnione podczas udostępniania notatnika. Więcej wskazówek znajdziesz w sekcjach Skonfiguruj konto IBM Cloud i Inicjalizuj usługę w niezaufanym środowisku.

# 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

Teraz używamy Transpilera do optymalizacji Circuit. Możemy wybrać poziom optymalizacji od 0 (brak optymalizacji) do 3 (najwyższy poziom optymalizacji). Aby zobaczyć, co obejmuje każdy poziom, odwiedź przewodnik Ustaw poziom optymalizacji Transpilera. Wynikowy Circuit będzie wyglądał znacznie inaczej niż logiczny Circuit, który stworzyliśmy na etapie mapowania.

# 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

„Sampler" to prymityw zaprojektowany do próbkowania możliwych stanów wynikających z Circuit kwantowego oraz zbierania statystyk dotyczących tego, jakie stany mogą zostać zmierzone i z jakim prawdopodobieństwem. Importujemy tutaj Qiskit Runtime Sampler:

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

sampler = Sampler(mode=backend)

Jeśli wyczerpałeś(-aś) przydzielony czas na prawdziwych komputerach kwantowych lub nie masz dostępu do internetu, możesz preferować użycie symulatora. W tym celu uruchom poniższą komórkę i odkomentuj powiązaną linię w kroku „Wykonanie".

# 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. Wykonanie

Po przygotowaniu Circuit możemy teraz uruchomić go na komputerze kwantowym!

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-processing

Teraz jesteśmy gotowi, aby zobaczyć wyniki! Wyświetlimy histogram 100 próbek Circuit.

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

Powyższy histogram pokazuje wyniki pomiarów wszystkich czterech Qubitów na końcu Circuit. Idealny komputer kwantowy bez szumów mierzyłby Qubity z tymi samymi wartościami przy każdym uruchomieniu, jednak w rzeczywistości szumy powodują, że część uruchomień produkuje błędy.

Sprawdź swoją wiedzę

Przeczytaj poniższe pytania, zastanów się nad odpowiedzią, a następnie kliknij trójkąt, aby odkryć rozwiązanie.

Używając bitstringa z największą liczbą zliczeń jako wartości AA, BB, SS i CC, zweryfikuj, że kwantowy układ dodający zadziałał prawidłowo.

Odpowiedź:

Musimy zweryfikować, że A+B=S+2×CA+B = S+2 \times C. Pamiętaj, że kolejność bitstringa jest zgodna z notacją little-endian, więc czyta się go jako CSBA.

Z powyższego histogramu widać, że dominującym bitstringiem jest 0000.

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

Wróć i zmień wartości AA i BB na A=1A=1 i B=1B=1, a następnie przejdź ponownie przez kroki wzorca Qiskit, aby uruchomić obwód jeszcze raz. Zweryfikuj ponownie, że układ dodający zadziałał prawidłowo.

Odpowiedź:

Powinieneś/powinnaś uzyskać histogram, w którym dominującym bitstringiem jest 1011:

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

Jedną z dodatkowych cech kwantowego półsumatora w porównaniu z klasycznym półsumatorem jest to, że może on działać z kwantowymi wejściami. Oznacza to, że potrafi „dodawać" Qubity AA i BB nawet wtedy, gdy znajdują się w stanach superpozycji. W sekcji Pytania dodatkowe poniżej zostaniesz poproszony/a o przygotowanie Qubitów w superpozycjach i sprawdzenie, co się stanie!

Podsumowanie

Ten moduł został zaprojektowany, aby dać ci solidne, podstawowe zrozumienie zasad leżących u podstaw obliczeń kwantowych poprzez porównanie ich z obliczeniami klasycznymi. Przyjrzeliśmy się klasycznemu obwodowi półsumatora, a następnie pokazaliśmy, jak dostosować ten obwód do działania z Qubitami na komputerze kwantowym. Teraz jesteś gotowy/gotowa, aby odkrywać pozostałe moduły Qiskit w Classroom!

Kluczowe pojęcia:

  • W odróżnieniu od klasycznych bitów, które mogą przyjmować wyłącznie wartości 0 i 1, Qubity mogą również znajdować się w stanach superpozycji obu wartości: 0 i 1.
  • Wiele Qubitów może znajdować się w superpozycji klasycznie dozwolonych bitstringów, zwanych stanami bazy obliczeniowej.
  • Wiele Qubitów może być splątanych, tak że stan jednego zależy od stanu drugiego.
  • Konwencją Qiskit jest stosowanie notacji little-endian, która umieszcza najmniej znaczący Qubit, q0q_0, na skrajnej prawej pozycji, a najbardziej znaczący Qubit, qNq_N, na skrajnej lewej.
  • Bramki kwantowe (Gate) to odwracalne operacje reprezentowane przez macierze unitarne, które działają na wektorach stanu kwantowego. W tej notacji macierz najbliżej wektora (najbardziej wysunięta w prawo) działa jako pierwsza.
  • Pomiary zwijają kwantowy stan superpozycji do jednego z klasycznie dozwolonych stanów, z prawdopodobieństwem równym kwadratowi amplitudy odpowiadającego mu stanu bazy obliczeniowej w superpozycji.
  • Obwody kwantowe są często przedstawiane za pomocą diagramów obwodów kwantowych (Circuit), gdzie Qubity są przedstawiane jako poziome linie, a bramki kwantowe (Gate) pojawiają się wzdłuż tych linii od lewej do prawej.
  • Aby uruchomić obwód kwantowy (Circuit), używamy czterech kroków przepływu pracy wzorców Qiskit: Mapuj, Optymalizuj, Wykonaj, Przetwórz wyniki.

Pytania

Pytania prawda/fałsz

  1. Pojedynczy bit w komputerze klasycznym może przechowywać wyłącznie wartość 0 lub 1.

  2. Splątanie oznacza, że stan jednego Qubitu jest niezależny od stanu drugiego.

  3. Bramki kwantowe (Gate) to operacje generalnie nieodwracalne.

  4. Konwencja Qiskit umieszcza najmniej znaczący Qubit, q0q_0, na skrajnej lewej pozycji.

  5. Pomiar stanu kwantowego zawsze daje dokładnie taki sam wynik, jeśli jest powtarzany wielokrotnie.

  6. Bramka Hadamarda tworzy superpozycję w pojedynczym Qubicie.

  7. Obwody kwantowe (Circuit) mogą zawierać operacje pomiarowe, które zwijają stan superpozycji do jednego z klasycznie dozwolonych stanów.

  8. Liczba możliwych stanów klasycznych dla NN bitów wynosi 2N2N.

  9. Prawdopodobieństwa wyników pomiarów kwantowych są dane przez kwadraty amplitud klasycznie mierzalnych stanów bazowych.

Pytania krótkiej odpowiedzi

  1. Jakie są główne różnice między bitem a Qubitem?

  2. Co dzieje się ze stanem kwantowym, gdy jest on mierzony?

  3. Dlaczego w Qiskit używamy notacji little-endian?

  4. Jakie są cztery kroki przepływu pracy wzorców Qiskit?

Pytania dodatkowe:

  1. W module używaliśmy sumatora wyłącznie do dodawania klasycznie dozwolonych stanów AA i BB. Możemy jednak również przygotować AA i BB w superpozycjach! Zmień kod tak, aby przygotować każdy Qubit w równej superpozycji stanów 0 i 1, a następnie uruchom nowy obwód (Circuit) i uzyskaj nowy histogram. Co widzisz? Wyjaśnij, co się dzieje.

  2. Dekompozycja bramki Toffoli (Gate). Użyj decompose(), aby pokazać, jak bramka Toffoli jest rozkładana na jednoQubitowe i dwuQubitowe Gate, a następnie zweryfikuj tę konstrukcję za pomocą mnożenia macierzy. Pamiętaj, że choć diagramy obwodów (Circuit) czyta się od lewej do prawej, macierze są stosowane do stanów kwantowych od prawej do lewej!