Kubity kwantowe, bramki i obwody
Kifumi Numata (19 Apr 2024)
Kliknij tutaj, aby pobrać plik PDF oryginalnego wykładu. Pamiętaj, że niektóre fragmenty kodu mogą być przestarzałe, ponieważ są to statyczne obrazy.
Szacowany czas QPU potrzebny do przeprowadzenia tego eksperymentu wynosi 5 sekund.
1. Wprowadzenie
Bity, bramki i obwody to podstawowe elementy składowe obliczeń kwantowych. Nauczysz się obliczeń kwantowych z modelem obwodów za pomocą kubitów i bramek kwantowych, a także powtórzysz zasady superpozycji, pomiaru i splątania.
W tej lekcji dowiesz się o:
- Bramkach jednoQubitowych
- Sferze Blocha
- Superpozycji
- Pomiarze
- Bramkach dwuQubitowych i stanie splątania
Na końcu tego wykładu poznasz pojęcie głębokości obwodu, która jest kluczowa dla obliczeń kwantowych w skali użytkowej.
2. Obliczenia jako diagram
Gdy używamy kubitów lub bitów, musimy nimi manipulować, aby przekształcić dane wejściowe w potrzebne wyniki. W przypadku najprostszych programów z bardzo małą liczbą bitów przydatne jest przedstawienie tego procesu w formie diagramu zwanego diagramem obwodu.
Rysunek w lewym dolnym rogu to przykład obwodu klasycznego, a rysunek w prawym dolnym rogu to przykład obwodu kwantowego. W obu przypadkach dane wejściowe znajdują się po lewej stronie, a wyjściowe po prawej, natomiast operacje są reprezentowane przez symbole. Symbole używane dla operacji nazywane są „bramkami" — głównie z przyczyn historycznych.
3. Jednokubitowa bramka kwantowa
3.1 Stan kwantowy i sfera Blocha
Stan Qubitu jest reprezentowany jako superpozycja i . Dowolny stan kwantowy jest reprezentowany jako
gdzie i są liczbami zespolonymi takimi, że .
i są wektorami w dwuwymiarowej zespolonej przestrzeni wektorowej:
Dlatego dowolny stan kwantowy jest również reprezentowany jako
Z tego wynika, że stan bitu kwantowego jest wektorem jednostkowym w dwuwymiarowej zespolonej przestrzeni z iloczynem wewnętrznym, z ortonormalną bazą i . Jest znormalizowany do 1.
jest również nazywany wektorem stanu (statevector).
Jednokubitowy stan kwantowy jest również reprezentowany jako
gdzie i są kątami sfery Blocha przedstawionej na poniższym rysunku.
W kolejnych kilku komórkach kodu zbudujemy podstawowe obliczenia z elementów składowych w Qiskit. Skonstruujemy pusty Circuit, a następnie będziemy dodawać operacje kwantowe, omawiając bramki i wizualizując ich efekty w miarę postępu.
Możesz uruchomić komórkę za pomocą "Shift" + "Enter". Najpierw zaimportuj biblioteki.
# 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
Przygotowanie Circuit kwantowego
Stworzymy i narysujemy jednokubitowy Circuit.
# Create the single-qubit quantum circuit
qc = QuantumCircuit(1)
# Draw the circuit
qc.draw("mpl")
Gate X
Gate X to obrót o wokół osi sfery Blocha. Zastosowanie Gate X do daje , a zastosowanie Gate X do daje , więc jest to operacja podobna do klasycznej bramki NOT i znana jest również jako przerzut bitu. Macierzowa reprezentacja Gate X jest poniżej.
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")
W IBM Quantum® stan początkowy jest ustawiony na , więc powyższy Circuit kwantowy w reprezentacji macierzowej ma postać
Następnie uruchommy ten Circuit przy użyciu symulatora wektora stanu.
# 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,))
Wektor pionowy jest wyświetlany jako wektor wierszowy, z liczbami zespolonymi (część urojona jest indeksowana przez ).
Gate H
Gate Hadamarda to obrót o wokół osi leżącej w połowie drogi między osiami i na sferze Blocha. Zastosowanie Gate H do tworzy stan superpozycji taki jak . Macierzowa reprezentacja Gate H jest poniżej.
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")
# 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,))
To jest
Ten stan superpozycji jest tak powszechny i ważny, że otrzymał własny symbol:
Stosując Gate na , stworzyliśmy superpozycję i , gdzie pomiar w bazie obliczeniowej (wzdłuż osi z na sferze Blocha) dałby każdy stan z równym prawdopodobieństwem.
Stan
Być może zgadłeś, że istnieje odpowiadający stan :
Aby stworzyć ten stan, najpierw zastosuj Gate X, aby uzyskać , a następnie zastosuj Gate H.
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")
# 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,))
To jest
Zastosowanie Gate na daje równą superpozycję i , ale znak przy jest ujemny.
3.2 Stan kwantowy pojedynczego Qubit i ewolucja unitarna
Działanie wszystkich bramek, które do tej pory poznaliśmy, jest unitarne, co oznacza, że można je opisać operatorem unitarnym. Innymi słowy, stan wyjściowy otrzymujemy, działając na stan początkowy macierzą unitarną:
Macierz unitarna to macierz spełniająca warunek
Jeśli chodzi o działanie komputera kwantowego, powiemy, że zastosowanie Gate'u kwantowego do Qubit ewoluuje stan kwantowy. Do typowych Gate'ów jednoQubitowych należą poniższe.
Bramki Pauliego:
gdzie iloczyn zewnętrzny obliczono następująco:
Inne typowe Gate'y jednoQubitowe:
Znaczenie i zastosowanie tych Gate'ów zostały opisane szczegółowo w kursie Podstawy informacji kwantowej.
Ćwiczenie 1
Użyj Qiskit, aby utworzyć Circuit kwantowe przygotowujące stany opisane poniżej. Następnie uruchom każdy Circuit za pomocą symulatora wektora stanu i wyświetl wynikowy stan na sferze Blocha. Jako dodatkowe zadanie sprawdź, czy potrafisz przewidzieć stan końcowy na podstawie intuicji dotyczącej Gate'ów i obrotów na sferze Blocha.
(1)
(2)
(3)
Wskazówka: Gate Z można zastosować za pomocą
qc.z(0)
Rozwiązanie:
### (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")
# 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,))
### (2) HH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.h(0)
qc.draw("mpl")
# 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,))
### (3) HZH|0> ###
##your code goes here##
qc = QuantumCircuit(1)
qc.h(0)
qc.z(0)
qc.h(0)
qc.draw("mpl")
# 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,))
3.3 Pomiar
Pomiar jest teoretycznie bardzo skomplikowanym zagadnieniem. W praktyce jednak wykonanie pomiaru wzdłuż osi (jak robią to wszystkie komputery kwantowe IBM®) po prostu wymusza, aby stan Qubit przyjął wartość lub , a my obserwujemy wynik.
- to prawdopodobieństwo uzyskania przy pomiarze.
- to prawdopodobieństwo uzyskania przy pomiarze.
Dlatego i nazywa się amplitudami prawdopodobieństwa (zob. „reguła Borna").
Na przykład ma jednakowe prawdopodobieństwo przyjęcia wartości lub po pomiarze. ma 75% szans na przyjęcie wartości .
Symulator Qiskit Aer
Następnie zmierzmy Circuit przygotowujący opisaną powyżej superpozycję o równym prawdopodobieństwie. Powinniśmy dodać Gate'y pomiaru, ponieważ symulator Qiskit Aer domyślnie symuluje idealne (bezszumowe) sprzętowe środowisko kwantowe. Uwaga: symulator Aer może również stosować model szumów oparty na rzeczywistym komputerze kwantowym. Do modeli szumów wrócimy później.
# 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")
Jesteśmy teraz gotowi uruchomić nasz Circuit na symulatorze Aer. W tym przykładzie zastosujemy domyślne ustawienie shots=1024, co oznacza, że dokonamy 1024 pomiarów. Następnie przedstawimy te wyniki na histogramie.
# 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}
Widzimy, że 0 i 1 były mierzone z prawdopodobieństwem bliskim 50% każde. Mimo że szum nie był tu symulowany, stany nadal mają charakter probabilistyczny. Dlatego chociaż oczekujemy rozkładu mniej więcej 50-50, rzadko uzyskamy dokładnie taki wynik — podobnie jak 100 rzutów monetą rzadko daje dokładnie 50 wyników każdej strony.
4. Wieloqubitowe bramki kwantowe i splątanie
4.1 Wieloqubitowy Circuit kwantowy
Dwuqubitowy Circuit kwantowy możemy utworzyć za pomocą poniższego kodu. Zastosujemy bramkę H do każdego Qubit.
# 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")
# 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))
Uwaga: kolejność bitów w Qiskit
Qiskit stosuje notację Little Endian przy porządkowaniu qubitów i bitów, co oznacza, że Qubit 0 jest skrajnym prawym bitem w ciągach bitów. Przykład: oznacza, że q0 jest w stanie , a q1 jest w stanie . Uważaj, ponieważ część literatury z zakresu informatyki kwantowej używa notacji Big Endian (Qubit 0 jest skrajnym lewym bitem) — podobnie jak wiele tekstów z dziedziny mechaniki kwantowej.
Należy też zauważyć, że w reprezentacji Circuitu kwantowego jest zawsze umieszczany na górze. Mając to na uwadze, stan kwantowy powyższego Circuitu można zapisać jako iloczyn tensorowy stanów jednoQubitowych.
( )
Stanem początkowym w Qiskit jest , więc przez zastosowanie do każdego Qubit stan zmienia się w stan równej superpozycji.
Reguła pomiaru jest taka sama jak w przypadku jednego Qubit — prawdopodobieństwo zmierzenia wynosi .
# Draw a Bloch sphere
plot_bloch_multivector(out_vector)

Zmierzmy teraz ten Circuit.
# 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")
Użyjemy teraz symulatora Aer, aby eksperymentalnie potwierdzić, że względne prawdopodobieństwa wszystkich możliwych stanów wyjściowych są w przybliżeniu równe.
# 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}
Zgodnie z oczekiwaniami stany , , , były mierzone z prawdopodobieństwem bliskim 25% każdy.
4.2 Wieloqubitowe bramki kwantowe
Bramka CNOT
Bramka CNOT (ang. „controlled NOT" lub CX) jest dwuqubitową bramką, co oznacza, że jej działanie obejmuje dwa Qubit jednocześnie: Qubit sterujący (ang. control) i Qubit docelowy (ang. target). Bramka CNOT odwraca stan Qubit docelowego tylko wtedy, gdy Qubit sterujący jest w stanie .
| Wejście (target, control) | Wyjście (target, control) |
|---|---|
| 00 | 00 |
| 01 | 11 |
| 10 | 10 |
| 11 | 01 |
Zasymulujmy najpierw działanie tej dwuqubitowej bramki, gdy q0 i q1 są oba w stanie , i uzyskajmy wyjściowy wektor stanu. Składnia Qiskit to 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")
# 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))
Zgodnie z oczekiwaniami zastosowanie bramki CNOT do stanu nie zmieniło stanu, ponieważ Qubit sterujący był w stanie . Wróćmy do operacji CNOT. Tym razem zastosujemy bramkę CNOT do stanu i zobaczmy, co się stanie.
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")
# 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))
Po zastosowaniu bramki CNOT stan stał się stanem .
Zweryfikujmy te wyniki, uruchamiając Circuit na symulatorze.
# Add measurements
qc.measure(0, 0)
qc.measure(1, 1)
# Draw the circuit
qc.draw(output="mpl")
# 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}
Wyniki powinny pokazać, że stan był mierzony ze 100-procentowym prawdopodobieństwem.
4.3 Splątanie kwantowe i wykonanie na prawdziwym urządzeniu kwantowym
Zacznijmy od wprowadzenia konkretnego stanu splątanego, który jest szczególnie ważny w obliczeniach kwantowych, a następnie zdefiniujemy pojęcie „splątania":
i ten stan jest nazywany stanem Bella.
Stan splątany to taki stan , składający się ze stanów kwantowych i , który nie może być przedstawiony jako iloczyn tensorowy poszczególnych stanów kwantowych.
Jeśli poniżej zawiera dwa stany i :
to iloczyn tensorowy tych dwóch stanów jest następujący
jednak nie istnieją współczynniki i spełniające oba powyższe równania. Dlatego nie może być przedstawiony jako iloczyn tensorowy poszczególnych stanów kwantowych i , co oznacza, że