Qubits, suprapunere și încurcare: fundamente cuantice fără fizică cuantică
Fiecare introducere în calculul cuantic pare să înceapă cu mecanica cuantică, ecuațiile Schrodinger și dualitatea undă-particulă. Rezultatul este că majoritatea dezvoltatorilor te pierzi în detaliile fizice înainte de a înțelege de ce un computer cuantic este diferit de unul clasic. Acest articol face opusul: explică conceptele fundamentale - qubiți, suprapunere, încurcare și decoerență — folosind analogii matematice accesibile și codul Qiskit, puteți fugi acum.
Nu va trebui să cunoașteți mecanica cuantică. Veți avea nevoie de vectori și probabilități.
Ce vei învăța
- Ce este matematic un qubit: vector în spațiul Hilbert 2D
- Sfera Bloch: vizualizarea stării unui qubit
- Suprapunerea: probabilitate, nu magie
- Entanglement: corelație cuantică fără comunicare
- Decoerența: de ce calculul cuantic este dificil
- Măsura: prăbușirea statului și consecințele acestuia
- Tot codul Qiskit pentru a vizualiza fiecare concept
Bitul clasic vs Qubit
Un bit clasic are exact una dintre cele două valori: 0 sau 1. Din punct de vedere fizic, este un tranzistor care conduce sau nu conducă curentul. Nu există ambiguitate: bitul este întotdeauna într-o stare definită.
Un qubit este descris matematic de a vector într-un spațiu cu 2 hilbert dimensiuni. Starea generală a unui qubit este:
|ψ⟩ = α|0⟩ + β|1⟩
dove:
|0⟩ e il vettore [1, 0] (stato base "zero")
|1⟩ e il vettore [0, 1] (stato base "uno")
α e β sono numeri complessi (ampiezze)
con il vincolo: |α|² + |β|² = 1
La probabilita di misurare 0 e |α|²
La probabilita di misurare 1 e |β|²
Acesta este punctul critic: α și β nu sunt probabilități - sunt amplitudini. Probabilitățile se obțin prin pătrarea mărimii amplitudinilor. Această distincție și fundamental, deoarece amplitudinile pot interfera (se adaugă sau se anulează) ca undele, în timp ce probabilităţile clasice nu.
# Visualizzare lo stato di un qubit con Qiskit
from qiskit import QuantumCircuit
from qiskit.visualization import plot_bloch_multivector, plot_histogram
from qiskit.quantum_info import Statevector
import numpy as np
# Stato |0⟩ — qubit "a zero"
qc_zero = QuantumCircuit(1)
sv_zero = Statevector.from_instruction(qc_zero)
print(f"Stato |0⟩: {sv_zero}")
# Statevector([1.+0.j, 0.+0.j], dims=(2,))
# probabilita di misurare 0: |1|^2 = 1.0 (100%)
# probabilita di misurare 1: |0|^2 = 0.0 (0%)
# Stato |1⟩ — applico gate X (equivalente al NOT classico)
qc_one = QuantumCircuit(1)
qc_one.x(0)
sv_one = Statevector.from_instruction(qc_one)
print(f"Stato |1⟩: {sv_one}")
# Statevector([0.+0.j, 1.+0.j], dims=(2,))
# Stato in superposizione — applico gate Hadamard
qc_plus = QuantumCircuit(1)
qc_plus.h(0) # Hadamard: |0⟩ -> (|0⟩ + |1⟩)/√2
sv_plus = Statevector.from_instruction(qc_plus)
print(f"Stato |+⟩ (superposizione): {sv_plus}")
# Statevector([0.707+0.j, 0.707+0.j], dims=(2,))
# probabilita 0: 0.707^2 = 0.5 (50%)
# probabilita 1: 0.707^2 = 0.5 (50%)
# Verifica le probabilita
probs = sv_plus.probabilities_dict()
print(f"Probabilita di misura: {probs}")
# {'0': 0.4999..., '1': 0.4999...}
Sfera Bloch: Vizualizarea unui Qubit
Sfera Bloch este o sferă cu raza 1 în care fiecare punct de pe suprafață reprezintă o stare cuantum pur (un qubit). Polul nord este |0⟩, polul sud este |1⟩. Punctele de pe ecuator sunt suprapuneri echiprobabile ale lui |0⟩ și |1⟩.
# Visualizzare vari stati sulla Bloch sphere
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit.visualization import plot_bloch_multivector
def show_state_on_bloch(circuit: QuantumCircuit, label: str) -> None:
sv = Statevector.from_instruction(circuit)
probs = sv.probabilities_dict()
print(f"\nStato: {label}")
print(f"Statevector: {sv.data}")
print(f"P(0)={probs.get('0', 0):.3f}, P(1)={probs.get('1', 0):.3f}")
# Polo Nord: |0⟩
qc_north = QuantumCircuit(1)
show_state_on_bloch(qc_north, "|0⟩ (polo nord)")
# Polo Sud: |1⟩
qc_south = QuantumCircuit(1)
qc_south.x(0)
show_state_on_bloch(qc_south, "|1⟩ (polo sud)")
# Equatore: |+⟩ = (|0⟩ + |1⟩)/√2 — Hadamard da |0⟩
qc_plus = QuantumCircuit(1)
qc_plus.h(0)
show_state_on_bloch(qc_plus, "|+⟩ (equatore, fase reale +)")
# Equatore: |−⟩ = (|0⟩ - |1⟩)/√2 — X poi Hadamard
qc_minus = QuantumCircuit(1)
qc_minus.x(0)
qc_minus.h(0)
show_state_on_bloch(qc_minus, "|−⟩ (equatore, fase reale -)")
# Stato arbitrario: rotazione di pi/4 attorno all'asse Y
qc_ry = QuantumCircuit(1)
qc_ry.ry(np.pi/4, 0) # Rotazione Y di 45 gradi
show_state_on_bloch(qc_ry, "RY(π/4)|0⟩ (stato intermedio)")
# P(0) ≈ 0.854, P(1) ≈ 0.146
Cheia conceptuală: poarta Hadamard nu „pune qubitul în suprapunere” așa cum ar fi o poziţie fizică ambiguă. Rotește vectorul de stare de la polul nord la ecuator a sferei Bloch. „Suprapunerea” este pur și simplu qubit-ul îndreptat într-o direcție diferit de |0⟩ și |1⟩.
Interferență: Adevărata Putere a Cuantumului
Numai suprapunerea nu este utilă - un qubit în suprapunere pe care îl măsurați singur un pic la întâmplare. Adevărata putere a calculului cuantic vine dininterferență: amplitudinile se pot adăuga (interferență constructivă) sau se pot anula reciproc (interferență distructivă), permițându-vă să amplificați căile care duc la răspunsul corect și să le suprimați pe cele greșite.
# Interferenza: l'Hadamard applicato due volte
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
# H applicato due volte torna allo stato iniziale (interferenza perfetta)
qc_hh = QuantumCircuit(1)
qc_hh.h(0) # Prima H: |0⟩ -> |+⟩ = (|0⟩+|1⟩)/√2
qc_hh.h(0) # Seconda H: le ampiezze interferiscono
sv = Statevector.from_instruction(qc_hh)
print(f"H|H|0⟩ = {sv.data}")
# [1.+0.j, 0.+0.j] — torna esattamente a |0⟩!
# Perche? La matematica:
# Prima H: [1/√2, 1/√2]
# Seconda H: il gate applica la matrice [[1/√2, 1/√2], [1/√2, -1/√2]]
# Risultato: [1/√2*1/√2 + 1/√2*1/√2, 1/√2*1/√2 - 1/√2*1/√2]
# = [1, 0] = |0⟩
# Il termine per |1⟩ si annulla (interferenza distruttiva)!
# Gli algoritmi quantum sfruttano questa interferenza:
# - Amplificano stati con la risposta giusta (interferenza costruttiva)
# - Sopprimono stati con risposte sbagliate (interferenza distruttiva)
Întanglement: corelație cuantică
Încurcarea este al doilea concept fundamental. Doi qubiți încâlciți au stări corelate: măsurarea unuia determină instantaneu rezultatul măsurării celuilalt, independent de la distanta. Dar - și acesta este punctul în care multe articole greșesc - asta nu este permite o comunicare mai rapidă decât lumina.
Starea Bell este cel mai simplu exemplu de încrucișare de 2 qubiți:
# Creare e misurare il Bell State
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
from qiskit_aer import AerSimulator
from qiskit import transpile
# Crea il Bell State |Φ+⟩ = (|00⟩ + |11⟩) / √2
qc_bell = QuantumCircuit(2, 2)
qc_bell.h(0) # Superposizione sul qubit 0
qc_bell.cx(0, 1) # CNOT: se qubit 0 e |1⟩, nega qubit 1
# Lo stato e: (|00⟩ + |11⟩) / √2
# NON e separabile: impossibile scrivere come |a⟩ ⊗ |b⟩
sv = Statevector.from_instruction(qc_bell)
print(f"Bell State: {sv.data}")
# [0.707, 0, 0, 0.707] -> 50% |00⟩, 50% |11⟩
# Misura
qc_bell.measure([0, 1], [0, 1])
simulator = AerSimulator()
compiled = transpile(qc_bell, simulator)
result = simulator.run(compiled, shots=10000).result()
counts = result.get_counts()
print(f"Risultati (10000 shots): {counts}")
# Solo '00' e '11' — MAI '01' o '10'!
# Se qubit 0 e 0, qubit 1 e sempre 0. Se qubit 0 e 1, qubit 1 e sempre 1.
# Questo e l'entanglement: non si manifesta come comunicazione
# ma come CORRELAZIONE perfetta nelle misure.
# "Misuro il qubit 0: ottengo 0. So con certezza che qubit 1 sara 0."
# La correlazione vale anche se i due qubit sono a chilometri di distanza.
# Einstein chiamava questo "spooky action at a distance" — e reale e verificato.
Pentru că încurcarea nu permite comunicarea: când vă măsurați qubit-ul, obțineți un rezultat aleatoriu (0 sau 1 cu 50% probabilitate fiecare). Doar atunci când comunici acest rezultat către cealaltă persoană prin canalul clasic, ea înțelege ce are. Canalul clasic - care este limitat de viteza luminii - este întotdeauna necesar pentru a extrage informația util.
Decoerența: dușmanul calculului cuantic
Motivul pentru care construirea calculatoarelor cuantice este atât de dificilă este decoerență: qubiții interacționează cu mediul (fotoni termici, câmpuri magnetice, vibrații) și se scurg proprietățile lor cuantice, prăbușindu-se în stări clasice. Acest proces are loc în microsecunde pe hardware-ul curent.
# Simulare l'effetto della decoerenza con noise model
from qiskit_aer import AerSimulator
from qiskit_aer.noise import NoiseModel, depolarizing_error
from qiskit import QuantumCircuit, transpile
# Noise model semplice: errore di depolarizzazione dopo ogni gate
noise_model = NoiseModel()
error_1qubit = depolarizing_error(0.01, 1) # 1% di errore per gate a 1 qubit
error_2qubit = depolarizing_error(0.05, 2) # 5% di errore per gate a 2 qubit
noise_model.add_all_qubit_quantum_error(error_1qubit, ['h', 'x', 'ry'])
noise_model.add_all_qubit_quantum_error(error_2qubit, ['cx'])
# Test: Bell state con e senza noise
def run_bell(shots: int, noisy: bool = False) -> dict:
qc = QuantumCircuit(2, 2)
qc.h(0)
qc.cx(0, 1)
qc.measure([0, 1], [0, 1])
if noisy:
sim = AerSimulator(noise_model=noise_model)
else:
sim = AerSimulator()
compiled = transpile(qc, sim)
result = sim.run(compiled, shots=shots).result()
return result.get_counts()
ideal = run_bell(10000, noisy=False)
noisy = run_bell(10000, noisy=True)
print("Senza noise:")
for state, count in sorted(ideal.items()):
print(f" |{state}⟩: {count/10000*100:.1f}%")
print("\nCon noise (1% per gate, 5% per CNOT):")
for state, count in sorted(noisy.items()):
print(f" |{state}⟩: {count/10000*100:.1f}%")
# Output tipico con noise:
# |00⟩: ~49%, |11⟩: ~49%, |01⟩: ~1%, |10⟩: ~1%
# Gli stati '01' e '10' compaiono a causa del noise — "bit flip errors"
Analogie pentru dezvoltatori pentru concepte cheie
- Qubits: o variabilă care poate fi 0, 1 sau o distribuție a probabilitate peste {0,1} — dar când o „citești” (măsori), aceasta scade la 0 sau 1
- Suprapunere: variabila se află într-o stare „încă nedeterminată”. — ca o Promisiune înainte de rezolvare(). Măsurarea și rezolvarea ()
- Încurcarea: două variabile cu corelație perfectă garantată — ca două obiecte care împărtășesc o referință imuabilă, dar nu cunosc valoarea pana la "citire"
- Interferență: Căile de calcul se adaugă/anulează ca unde — vă permite să amplificați răspunsul corect
- Decoerența: quantum bit put — sistemul își pierde proprietățile cuantică prin interferență cu mediul
Măsurare și colaps
Măsurarea și operațiunea care extrage informații clasice dintr-o stare cuantică - e distruge iremediabil statul. Și o constrângere fundamentală a calculului cuantic: nu poți „citi” starea intermediară a unui calcul fără a o distruge.
# Il collasso della misura: dimostrazione pratica
from qiskit import QuantumCircuit
from qiskit.quantum_info import Statevector
# Crea superposizione
qc = QuantumCircuit(1)
qc.h(0)
sv_before = Statevector.from_instruction(qc)
print(f"Prima della misura: {sv_before.data}")
# [0.707+0j, 0.707+0j] — superposizione
# Misura (simulata 1000 volte)
qc_measure = QuantumCircuit(1, 1)
qc_measure.h(0)
qc_measure.measure(0, 0)
from qiskit_aer import AerSimulator
from qiskit import transpile
sim = AerSimulator()
compiled = transpile(qc_measure, sim)
result = sim.run(compiled, shots=1000).result()
print(f"Dopo 1000 misure: {result.get_counts()}")
# {'0': ~500, '1': ~500}
# Punto critico: ogni singola misura collassa il qubit
# Non puoi misurare |+⟩ e poi continuare a lavorarci
# Devi preparare di nuovo lo stato dall'inizio
# Questo e perche no-cloning theorem: non puoi copiare uno stato sconosciuto
Concluzii
Conceptele fundamentale ale calculului cuantic - qubiți, suprapunere, încrucișare și decoerență — toate sunt descrise cu algebră liniară și probabilitate, fără fizică ezoterică. Bloch sfera și vectorii de stare Qiskit sunt instrumente concrete pentru vizualizarea și lucrul cu ei.
Următorul articol se bazează pe aceste fundamente: porțile cuantice ca transformări liniară, construcția primului algoritm real (starea Bell) și execuția pe hardware IBM.







