Sari la conținutul principal
Acest proiect este în versiune beta. Ai găsit o eroare? Deschide un issue pe GitHub. Ai o întrebare sau o idee? Întreabă în Discussions — ne-ar plăcea să aflăm părerea ta!
Cum este calitatea traducerii pe această pagină?

Implementare Qiskit

În această secțiune, vom analiza câteva implementări Qiskit ale conceptelor introduse în această lecție. Dacă dorești să rulezi aceste implementări tu însuți, ceea ce este recomandat cu insistență, consultă pagina Instalare Qiskit din IBM Quantum Documentation pentru detalii despre cum să configurezi Qiskit.

Trebuie înțeles că Qiskit este în continuă dezvoltare și este axat în principal pe maximizarea performanței calculatoarelor cuantice pe care le operează, care la rândul lor continuă să evolueze. Ca urmare, Qiskit este supus unor modificări care pot duce ocazional la deprecierea codului. Ținând cont de acest lucru, vom executa întotdeauna comenzile de mai jos înainte de a prezenta exemple de cod Qiskit în acest curs, pentru a fi clar care versiune de Qiskit a fost folosită. Începând cu Qiskit v1.0, aceasta este o modalitate simplă de a vedea ce versiune de Qiskit este instalată în prezent.

# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util

_needed = {"numpy": "numpy", "qiskit": "qiskit"}
_missing = [pip for module, pip in _needed.items()
if importlib.util.find_spec(module) is None]
# One at a time, so a package that fails to install does not block the others
for _pip in _missing:
%pip install -q {_pip}
if not _missing:
print("\u2713 All required packages are installed")
from qiskit import __version__

print(__version__)
2.2.3

Dacă rulezi acest cod într-un mediu Python bazat pe cloud, este posibil să fie nevoie să instalezi unele dintre pachetele de mai jos:

#!pip install qiskit
#!pip install jupyter
#!pip install sympy
#!pip install matplotlib
#!pip install pylatexenc

Vectori și matrice în Python​

Qiskit utilizează limbajul de programare Python, deci înainte de a discuta specific despre Qiskit, poate fi util să discutăm foarte pe scurt despre calculele cu matrice și vectori în Python.

În Python, calculele cu matrice și vectori pot fi efectuate folosind clasa array din biblioteca NumPy, care oferă funcționalitate pentru multe calcule numerice și științifice. Codul următor încarcă această bibliotecă, definește doi vectori coloană, ket0 și ket1, corespunzând vectorilor de stare qubit ∣0⟩\vert 0\rangle și ∣1⟩\vert 1\rangle, și apoi afișează media lor.

import numpy as np

ket0 = np.array([[1], [0]])
ket1 = np.array([[0], [1]])

print(ket0 / 2 + ket1 / 2)
[[0.5]
[0.5]]

Putem folosi de asemenea array pentru a crea matrice care pot reprezenta operații.

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

Te rog să reții că tot codul care apare într-o lecție dată din acest curs trebuie rulat secvențial. Prin urmare, nu este nevoie să importăm NumPy din nou aici, deoarece a fost deja importat.

Înmulțirea matricelor, inclusiv înmulțirea matrice-vector ca un caz special, poate fi efectuată folosind operatorul @.

print(M1 @ ket1)
print(M1 @ M2)
print(M @ M)
[[1]
[0]]
[[1 1]
[0 0]]
[[1. 0.75]
[0. 0.25]]

Această formatare a rezultatelor lasă de dorit din punct de vedere vizual. O soluție, pentru situațiile care necesită ceva mai estetic, este să folosești funcția array_to_latex din Qiskit, din modulul qiskit.visualization. Reține că, în codul care urmează, folosim funcția generică display din Python (mai ales în notebook-uri), deoarece aceasta poate reda obiecte folosind reprezentări mai bogate, în timp ce print() folosește pur și simplu reprezentarea sub formă de șir de caractere a obiectului. Acest lucru este similar cu modul în care array-urile NumPy oferă propria formatare specializată, în timp ce listele Python folosesc reprezentarea implicită de listă.

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))
[10] \begin{bmatrix} 1 \\ 0 \\ \end{bmatrix} [1100] \begin{bmatrix} 1 & 1 \\ 0 & 0 \\ \end{bmatrix} [134014] \begin{bmatrix} 1 & \frac{3}{4} \\ 0 & \frac{1}{4} \\ \end{bmatrix}

Stări, măsurători și operații​

Qiskit include mai multe clase care permit crearea și manipularea stărilor, măsurătorilor și operațiilor — deci nu este nevoie să programezi tot ce este necesar pentru a simula stări cuantice, măsurători și operații în Python. Mai jos sunt incluse câteva exemple pentru a te ajuta să începi.

Definirea și afișarea vectorilor de stare​

Clasa Statevector din Qiskit oferă funcționalitate pentru definirea și manipularea vectorilor de stare cuantică. În codul care urmează, clasa Statevector este importată și câțiva vectori sunt definiți. (Importăm de asemenea funcția sqrt din biblioteca NumPy pentru a calcula o rădăcină pătrată. Această funcție ar putea fi apelată alternativ ca np.sqrt cu condiția ca NumPy să fi fost deja importat, ceea ce s-a întâmplat mai sus; aceasta este pur și simplu o altă modalitate de a importa și utiliza doar această funcție specifică.)

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])

Clasa Statevector include o metodă draw pentru afișarea vectorilor de stare în diverse moduri, inclusiv text pentru text simplu, latex pentru LaTeX redat și latex_source pentru cod LaTeX, care poate fi util pentru a copia și lipi în documente. (Folosește print în loc de display pentru a afișa cod LaTeX cu cele mai bune rezultate.)

display(u.draw("text"))
display(u.draw("latex"))
print(u.draw("latex_source"))
[0.70710678+0.j,0.70710678+0.j]

22∣0⟩+22∣1⟩\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle

\frac{\sqrt{2}}{2} |0\rangle+\frac{\sqrt{2}}{2} |1\rangle

Clasa Statevector include de asemenea metoda is_valid, care verifică dacă un vector dat este un vector de stare cuantică valid (cu alte cuvinte, că are norma euclidiană egală cu 1):

display(u.is_valid())
display(w.is_valid())
True
False

Simularea măsurătorilor folosind Statevector​

În continuare, vom vedea o modalitate prin care măsurătorile stărilor cuantice pot fi simulate în Qiskit, folosind metoda measure din clasa Statevector. Să folosim același vector de stare qubit v definit anterior.

display(v.draw("latex"))

(13+2i3)∣0⟩−23∣1⟩(\frac{1}{3} + \frac{2 i}{3}) |0\rangle- \frac{2}{3} |1\rangle

Rularea metodei measure simulează o măsurătoare în baza standard. Aceasta returnează rezultatul acelei măsurători, plus noul vector de stare cuantică al sistemului după măsurătoare. (Aici folosim funcția print din Python cu prefixul f pentru afișare formatată cu expresii incluse.)

outcome, state = v.measure()
print(f"Measured: {outcome}\nPost-measurement state:")
display(state.draw("latex"))
Measured: 1
Post-measurement state:

−∣1⟩- |1\rangle

Rezultatele măsurătorilor sunt probabilistice, deci această metodă poate returna rezultate diferite la rulări multiple. Pentru exemplul particular al vectorului v definit mai sus, metoda measure definește vectorul de stare cuantică după ce are loc măsurătoarea ca fiind

(1+2i5)∣0⟩\biggl(\frac{1 + 2i}{\sqrt{5}}\biggr) \vert 0\rangle

(în loc de ∣0⟩\vert 0\rangle) sau

−∣1⟩- \vert 1\rangle

(în loc de ∣1⟩\vert 1\rangle), în funcție de rezultatul măsurătorii. În ambele cazuri, alternativele la ∣0⟩\vert 0\rangle și ∣1⟩\vert 1\rangle sunt, de fapt, echivalente cu acești vectori de stare; se spune că sunt echivalente până la o fază globală deoarece unul este egal cu celălalt înmulțit cu un număr complex de pe cercul unitate. Această problemă este discutată mai detaliat în lecția Circuite cuantice și poate fi ignorată fără grijă deocamdată.

Statevector va genera o eroare dacă metoda measure este aplicată unui vector de stare cuantică invalid.

Statevector vine de asemenea cu o metodă sample_counts care permite simularea oricărui număr de măsurători pe sistem, de fiecare dată pornind de la o copie nouă a stării. De exemplu, codul următor arată rezultatul măsurării vectorului v de 10001000 de ori, ceea ce (cu probabilitate ridicată) duce la rezultatul 00 în aproximativ 55 din 99 cazuri (sau aproximativ 556556 din cele 10001000 de încercări) și rezultatul 11 în aproximativ 44 din 99 cazuri (sau aproximativ 444444 din cele 10001000 de încercări). Codul care urmează demonstrează de asemenea funcția plot_histogram din modulul qiskit.visualization pentru vizualizarea rezultatelor.

from qiskit.visualization import plot_histogram

statistics = v.sample_counts(1000)
plot_histogram(statistics)

Output of the previous code cell

Rularea acestui cod de mai multe ori pe cont propriu, cu numere diferite de eșantioane în locul lui 10001000, poate fi utilă pentru a dezvolta o intuiție despre cum influențează numărul de încercări de câte ori apare fiecare rezultat. Cu din ce în ce mai multe eșantioane, proporția eșantioanelor pentru fiecare posibilitate va tinde, cel mai probabil, să se apropie tot mai mult de probabilitatea corespunzătoare. Mai general, acest fenomen este cunoscut sub numele de legea numerelor mari în teoria probabilității.

Efectuarea operațiilor cu Operator și Statevector​

Operațiile unitare pot fi definite în Qiskit folosind clasa Operator, ca în exemplul care urmează. Această clasă include o metodă draw cu argumente similare cu Statevector. Reține că opțiunea latex produce rezultate echivalente cu array_to_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"))
[10022+2i2] \begin{bmatrix} 1 & 0 \\ 0 & \frac{\sqrt{2}}{2} + \frac{\sqrt{2} i}{2} \\ \end{bmatrix}

Putem aplica o operație unitară unui vector de stare folosind metoda 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"))

(0.1464466094−0.3535533906i)∣0⟩+(−0.3535533906+0.8535533906i)∣1⟩(0.1464466094 - 0.3535533906 i) |0\rangle+(-0.3535533906 + 0.8535533906 i) |1\rangle

O primă privire asupra circuitelor cuantice​

Circuit-urile cuantice nu vor fi introduse formal până la lecția Circuite cuantice, care este a treia lecție din acest curs, dar putem totuși experimenta cu compunerea operațiilor unitare qubit folosind clasa QuantumCircuit din Qiskit. În special, putem defini un circuit cuantic (care, în acest caz, va fi pur și simplu o secvență de operații unitare efectuate pe un singur qubit) după cum urmează.

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"))

Output of the previous code cell

Aici folosim metoda draw din clasa QuantumCircuit cu renderer-ul mpl (prescurtare pentru Matplotlib, o bibliotecă de vizualizare Python). Acesta este singurul renderer pe care îl vom folosi pentru Circuit-urile cuantice în acest curs, dar există și alte opțiuni, inclusiv un renderer bazat pe text și unul bazat pe LaTeX.

Operațiile sunt aplicate secvențial, începând din stânga și terminând în dreapta în diagramă. O modalitate practică de a obține matricea unitară corespunzătoare acestui Circuit este să folosești metoda from_circuit din clasa Operator.

display(Operator.from_circuit(circuit).draw("latex"))
[0.1464466094−0.3535533906i0.8535533906+0.3535533906i−0.3535533906+0.8535533906i0.3535533906+0.1464466094i] \begin{bmatrix} 0.1464466094 - 0.3535533906 i & 0.8535533906 + 0.3535533906 i \\ -0.3535533906 + 0.8535533906 i & 0.3535533906 + 0.1464466094 i \\ \end{bmatrix}

Putem de asemenea inițializa un vector de stare cuantică de pornire și apoi evolua acea stare conform secvenței de operații descrise de circuit.

ket0 = Statevector([1, 0])
v = ket0.evolve(circuit)
display(v.draw("latex"))

(0.1464466094−0.3535533906i)∣0⟩+(−0.3535533906+0.8535533906i)∣1⟩(0.1464466094 - 0.3535533906 i) |0\rangle+(-0.3535533906 + 0.8535533906 i) |1\rangle

Codul următor simulează un experiment în care starea obținută din Circuit-ul de mai sus este măsurată cu o măsurătoare în baza standard de 4000 de ori (folosind o copie proaspătă a stării de fiecare dată).

statistics = v.sample_counts(4000)
display(plot_histogram(statistics))

Output of the previous code cell