Implementace v Qiskitu
V teto sekci se podivame na nektere implementace v Qiskitu pro koncepty predstavene v teto lekci. Pokud si chces tyto implementace spustit sam/sama, coz vrele doporucujeme, podivej se na stranku Instalace Qiskitu v dokumentaci IBM Quantum, kde najdes podrobnosti o nastaveni Qiskitu.
Je dulezite mit na pameti, ze Qiskit je neustale vyvijen a je primarne zameren na maximalizaci vykonu kvantovych pocitacu, ktere pomoci nej ovladas a ktere se samy stale vyviji. V dusledku toho se Qiskit meni, coz muze obcas vest k zastaravani kodu. S ohledem na to vzdy pred ukazkami kodu v Qiskitu v tomto kurzu spustime nasledujici prikazy, aby bylo jasne, ktera verze Qiskitu byla pouzita. Od verze Qiskit v1.0 je to jednoduchy zpusob, jak zjistit aktualne nainstalovanu verzi Qiskitu.
# Added by doQumentation — required packages for this notebook
!pip install -q numpy qiskit
from qiskit import __version__
print(__version__)
2.2.3
Pokud to spoustis v cloudovem prostredi Pythonu, muzes potrebovat nainstalovat nektere z nasledujicich balicku:
#!pip install qiskit
#!pip install jupyter
#!pip install sympy
#!pip install matplotlib
#!pip install pylatexenc
Vektory a matice v Pythonu
Qiskit pouziva programovaci jazyk Python, takze nez budeme mluvit konkretne o Qiskitu, muze byt uzitecne si velmi strucne projit vypocty s maticemi a vektory v Pythonu.
V Pythonu lze vypocty s maticemi a vektory provadet pomoci tridy array z knihovny NumPy, ktera poskytuje funkcionalitu pro mnoho numerickych a vedeckych vypoctu.
Nasledujici kod nacte tuto knihovnu, definuje dva sloupcove vektory, ket0 a ket1, odpovidajici stavovym vektorum qubit a a pote vypise jejich prumer.
import numpy as np
ket0 = np.array([[1], [0]])
ket1 = np.array([[0], [1]])
print(ket0 / 2 + ket1 / 2)
[[0.5]
[0.5]]
Pomoci array muzeme take vytvaret matice reprezentujici operace.
M1 = np.array([[1, 1], [0, 0]])
M2 = np.array([[1, 0], [0, 1]])
M = M1 / 2 + M2 / 2
print(M)
[[1. 0.5]
[0. 0.5]]
Vezmi prosim na vedomi, ze veskerý kod v dane lekci tohoto kurzu se ocekava, ze bude spousten postupne.
Proto zde nemusime znovu importovat NumPy, protoze uz byl naimportovan.
Nasobeni matic, vcetne nasobeni matice vektorem jako specialniho pripadu, lze provadet pomoci funkce matmul z NumPy.
print(M1 @ ket1)
print(M1 @ M2)
print(M @ M)
[[1]
[0]]
[[1 1]
[0 0]]
[[1. 0.75]
[0. 0.25]]
Toto formatovani vystupu neni vizualne uplne idealni.
Jednim resenim pro situace, kdy potrebujes neco hezciho, je pouziti funkce array_to_latex v Qiskitu z modulu qiskit.visualization.
Vsimni si, ze v nasledujicim kodu pouzivame obecnou funkci Pythonu display.
Naproti tomu konkretni chovani print muze zaviset na tom, co se tiskne, jako je tomu u poli definovanych pomoci NumPy.
from qiskit.visualization import array_to_latex
display(array_to_latex(M1 @ ket1))
display(array_to_latex(M1 @ M2))
display(array_to_latex(M @ M))
Stavy, mereni a operace
Qiskit obsahuje nekolik trid, ktere umoznuji vytvaret a manipulovat se stavy, merenimi a operacemi -- takze neni treba programovat vse potrebne pro simulaci kvantovych stavu, mereni a operaci v Pythonu od nuly. Nize jsou uvedeny nektere priklady, ktere ti pomohou zacit.
Definice a zobrazeni stavovych vektoru
Trida Statevector v Qiskitu poskytuje funkcionalitu pro definovani a manipulaci s kvantovymi stavovymi vektory.
V nasledujicim kodu je naimportovana trida Statevector a definovano nekolik vektoru.
(Take importujeme funkci sqrt z knihovny NumPy pro vypocet odmocniny.
Tuto funkci lze alternativne volat jako np.sqrt za predpokladu, ze NumPy jiz byl naimportovan, jak tomu bylo vyse; jde pouze o jiny zpusob importu a pouziti teto konkretni funkce.)
from qiskit.quantum_info import Statevector
from numpy import sqrt
u = Statevector([1 / sqrt(2), 1 / sqrt(2)])
v = Statevector([(1 + 2.0j) / 3, -2 / 3])
w = Statevector([1 / 3, 2 / 3])
Trida Statevector obsahuje metodu draw pro zobrazeni stavovych vektoru ruznymi zpusoby, vcetne
text pro cisty text, latex pro vykresleny LaTeX a latex_source pro zdrojovy kod LaTeXu, coz se muze hodit pro kopirovani do dokumentu.
(Pro zobrazeni LaTeX kodu pouzij print misto display pro nejlepsi vysledky.)
display(u.draw("text"))
display(u.draw("latex"))
print(u.draw("latex_source"))
[0.70710678+0.j,0.70710678+0.j]
\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle
Trida Statevector take obsahuje metodu is_valid, ktera overuje, zda je dany vektor platnym kvantovym stavovym vektorem (jinymi slovy, ze ma euklidovskou normu rovnou 1):
Trida Statevector take obsahuje metodu is_valid, ktera overuje, zda je dany vektor platnym kvantovym stavovym vektorem (jinymi slovy, ze ma euklidovskou normu rovnou 1):
display(u.is_valid())
display(w.is_valid())
True
False
Simulace mereni pomoci Statevector
Dale se podivame na jeden zpusob, jak lze v Qiskitu simulovat mereni kvantovych stavu, a to pomoci metody measure z tridy Statevector.
Pouzijme stejny stavovy vektor qubit v, ktery jsme definovali drive.
display(v.draw("latex"))
Spusteni metody measure simuluje mereni ve standardni bazi.
Vrati vysledek tohoto mereni a novy kvantovy stavovy vektor systemu po mereni.
(Zde pouzivame Pythonovou funkci print s prefixem f pro formatovany vystup s vlozenymi vyrazy.)
outcome, state = v.measure()
print(f"Measured: {outcome}\nPost-measurement state:")
display(state.draw("latex"))
Measured: 1
Post-measurement state:
Vysledky mereni jsou pravdepodobnostni, takze tato metoda muze pri opakovanem spusteni vracet ruzne vysledky.
Pro konkretni priklad vektoru v definovaneho vyse metoda measure definuje kvantovy stavovy vektor po mereni jako
(misto ) nebo
(misto ), v zavislosti na vysledku mereni. V obou pripadech jsou alternativy k a ve skutecnosti ekvivalentni temto stavovym vektorum; rika se, ze jsou ekvivalentni az na globalni fazi, protoze jeden se rovna druhemu vynasobenemu komplexnim cislem na jednotkove kruznici. Tato problematika je podrobneji probrána v lekci Kvantove Circuit a prozatim ji muzete bezpecne ignorovat.
Statevector vyhodi chybu, pokud je metoda measure aplikovana na neplatny kvantovy stavovy vektor.
Statevector take disponuje metodou sample_counts, ktera umoznuje simulovat libovolny pocet mereni na systemu, pricemz pokazde zacina s novou kopii stavu. Napriklad nasledujici kod ukazuje vysledek mereni vektoru v krat, coz (s vysokou pravdepodobnosti) vede k vysledku priblizne z kazych pripadu (neboli asi z pokusu) a k vysledku priblizne z kazych pripadu (neboli asi z pokusu).
Nasledujici kod take demonstruje funkci plot_histogram z modulu qiskit.visualization pro vizualizaci vysledku.
from qiskit.visualization import plot_histogram
statistics = v.sample_counts(1000)
plot_histogram(statistics)
Spusteni tohoto kodu vicekrat s ruznymi pocty vzorku misto ti muze pomoci vybudovat intuici pro to, jak pocet pokusu ovlivnuje pocet vyskytu jednotlivych vysledku. S vice a vice vzorky se podil vzorku pro kazdou moznost pravdepodobne priblizuje odpovidajici pravdepodobnosti. Tento jev je obecneji znam jako zakon velkych cisel v teorii pravdepodobnosti.
Provadeni operaci pomoci Operator a Statevector
Unitarni operace lze v Qiskitu definovat pomoci tridy Operator, jak ukazuje nasledujici priklad.
Tato trida obsahuje metodu draw s podobnymi argumenty jako Statevector.
Vezmi na vedomi, ze volba latex produkuje vysledky ekvivalentni array_from_latex.
from qiskit.quantum_info import Operator
Y = Operator([[0, -1.0j], [1.0j, 0]])
H = Operator([[1 / sqrt(2), 1 / sqrt(2)], [1 / sqrt(2), -1 / sqrt(2)]])
S = Operator([[1, 0], [0, 1.0j]])
T = Operator([[1, 0], [0, (1 + 1.0j) / sqrt(2)]])
display(T.draw("latex"))
Unitarni operaci muzeme na stavovy vektor aplikovat pomoci metody evolve.
v = Statevector([1, 0])
v = v.evolve(H)
v = v.evolve(T)
v = v.evolve(H)
v = v.evolve(S)
v = v.evolve(Y)
display(v.draw("latex"))
Nahled na kvantove Circuit
Kvantove Circuit budou formalne predstaveny az v lekci Kvantove Circuit, coz je treti lekce v tomto kurzu, ale uz ted si muzeme vyzkouset skladani unitarnich operaci na qubit pomoci tridy QuantumCircuit v Qiskitu.
Konkretne muzeme definovat kvantovy Circuit (ktery v tomto pripade bude jednodusse sekvenci unitarnich operaci provedenych na jednom qubit) nasledovne.
from qiskit import QuantumCircuit
circuit = QuantumCircuit(1)
circuit.h(0)
circuit.t(0)
circuit.h(0)
circuit.s(0)
circuit.y(0)
display(circuit.draw(output="mpl"))
Zde pouzivame metodu draw z tridy QuantumCircuit s rendererem mpl (zkratka pro Matplotlib, vizualizacni knihovnu Pythonu).
Toto je jediny renderer, ktery budeme pro kvantove Circuit v tomto kurzu pouzivat, ale existuji i dalsi moznosti, vcetne textoveho a LaTeX rendereru.
Operace se aplikuji sekvencne, od leve strany diagramu smerem doprava.
Sikovny zpusob, jak ziskat unitarni matici odpovidajici tomuto Circuit, je pouzit metodu from_circuit z tridy Operator.
display(Operator.from_circuit(circuit).draw("latex"))
Muzeme take inicializovat pocatecni kvantovy stavovy vektor a pak ho nechat vyvijt podle sekvence operaci popsane Circuit.
ket0 = Statevector([1, 0])
v = ket0.evolve(circuit)
display(v.draw("latex"))
Nasledujici kod simuluje experiment, ve kterem je stav ziskany z vyse uvedeneho Circuit meren standardnim bazovym merenim 4000 krat (pokazde s novou kopii stavu).
statistics = v.sample_counts(4000)
display(plot_histogram(statistics))