Kubity, superpozycja i splątanie: podstawy kwantowe bez fizyki kwantowej
Wydaje się, że każde wprowadzenie do obliczeń kwantowych zaczyna się od mechaniki kwantowej, czyli równań Schrodinger i dualizm korpuskularno-falowy. W rezultacie większość programistów gubisz się w szczegółach fizycznych, zanim w ogóle zrozumiesz, dlaczego komputer kwantowy różni się od jednego klasyczny. W tym artykule jest odwrotnie: wyjaśnia podstawowe pojęcia — kubity, superpozycja, splątanie i dekoherencja — korzystając z dostępnych analogii matematycznych i kodu Qiskit, jak to możliwe biegnij teraz.
Nie musisz znać mechaniki kwantowej. Będziesz potrzebować wektorów i prawdopodobieństw.
Czego się nauczysz
- Czym jest kubit matematycznie: wektor w przestrzeni Hilberta 2D
- Sfera Blocha: wizualizacja stanu kubitu
- Superpozycja: prawdopodobieństwo, a nie magia
- Splątanie: korelacja kwantowa bez komunikacji
- Dekoherencja: dlaczego obliczenia kwantowe są trudne
- Środek: upadek państwa i jego konsekwencje
- Cały kod Qiskit do wizualizacji każdej koncepcji
Klasyczny bit kontra Qubit
Bit klasyczny ma dokładnie jedną z dwóch wartości: 0 lub 1. Fizycznie jest to tranzystor który przewodzi lub nie przewodzi prądu. Nie ma tu żadnej dwuznaczności: bit jest zawsze w zdefiniowanym stanie.
Kubit jest matematycznie opisany przez a wektor w przestrzeni 2-Hilberta wymiary. Ogólny stan kubitu to:
|ψ⟩ = α|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 |β|²
To jest punkt krytyczny: α i β nie są prawdopodobieństwami – są to amplitudy. Prawdopodobieństwa uzyskuje się przez podniesienie wielkości amplitud do kwadratu. To rozróżnienie i fundamentalne, ponieważ amplitudy mogą się zakłócać (dodawać lub znosić) jak fale, podczas gdy prawdopodobieństwa klasyczne tego nie robią.
# 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 Blocha: wizualizacja Qubitu
Sfera Blocha to kula o promieniu 1, w której każdy punkt na powierzchni reprezentuje stan czysty kwant (jeden kubit). Biegun północny to |0⟩, biegun południowy to |1⟩. Punkty na równiku są to równie prawdopodobne superpozycje |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
Klucz koncepcyjny: bramka Hadamarda nie „umieszcza kubitu w superpozycji”. niejednoznaczna pozycja fizyczna. Obraca wektor stanu od bieguna północnego do równika sfery Blocha. „Superpozycja” to po prostu kubit skierowany w jednym kierunku różni się od |0⟩ i |1⟩.
Zakłócenia: prawdziwa moc kwantowa
Sama superpozycja nie jest użyteczna — kubit w superpozycji mierzy się samodzielnie losowy kawałek. Prawdziwa moc obliczeń kwantowych pochodzi zingerencja: amplitudy mogą się dodawać (interferencja konstruktywna) lub znosić się (interferencja destrukcyjna), co pozwala wzmacniać ścieżki prowadzące do właściwej odpowiedzi i tłumić błędne.
# 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)
Splątanie: korelacja kwantowa
Splątanie to drugie podstawowe pojęcie. Dwa splątane kubity mają skorelowane stany: pomiar jednego natychmiast i niezależnie określa wynik pomiaru drugiego z daleka. Ale – i tu właśnie pojawia się błąd w wielu artykułach – to nie jest umożliwia komunikację szybszą od światła.
Stan Bella jest najprostszym przykładem splątania 2-kubitowego:
# 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.
Ponieważ splątanie nie pozwala na komunikację: kiedy mierzysz swój kubit, otrzymujesz losowy wynik (0 lub 1 z 50% prawdopodobieństwem każdy). Tylko wtedy, gdy się komunikujesz ten wynik drugiej osobie za pośrednictwem klasycznego kanału, ona rozumie, co ma. Kanał klasyczna — ograniczona prędkością światła — jest zawsze konieczna do wydobycia informacji przydatne.
Dekoherencja: wróg obliczeń kwantowych
Powodem, dla którego budowanie komputerów kwantowych jest tak trudne, jest: dekoherencja: Kubity oddziałują z otoczeniem (fotony termiczne, pola magnetyczne, wibracje) i wyciekają ich właściwości kwantowe, zapadając się w stany klasyczne. Proces ten zachodzi w mikrosekund na obecnym sprzęcie.
# 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"
Analogia deweloperska dla kluczowych koncepcji
- Kubity: zmienna, która może mieć wartość 0, 1 lub rozkład prawdopodobieństwo powyżej {0,1} — ale kiedy je „przeczytasz” (zmierzysz), spada ono do 0 lub 1
- Nałożenie: zmienna jest w stanie „jeszcze nieokreślonym”. — jak obietnica przed rozwiązaniem(). Pomiar i rozdzielczość()
- Splątanie: dwie zmienne z gwarantowaną doskonałą korelacją — jak dwa obiekty, które mają wspólne niezmienne odniesienie, ale nie znają wartości aż do „czytania”
- Ingerencja: Ścieżki obliczeniowe dodają/anulują jako fale — pozwala wzmocnić poprawną odpowiedź
- Dekoherencja: kwantowa zgnilizna bitów – system traci swoje właściwości kwantowe poprzez ingerencję w środowisko
Pomiar i upadek
Pomiar i działanie polegające na wyodrębnieniu klasycznej informacji ze stanu kwantowego — np bezpowrotnie niszczy państwo. Oraz podstawowe ograniczenie obliczeń kwantowych: nie można „odczytać” stanu pośredniego obliczenia bez jego zniszczenia.
# 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
Wnioski
Podstawowe pojęcia obliczeń kwantowych — kubity, superpozycja, splątanie i dekoherencja — wszystkie dają się opisać algebrą liniową i prawdopodobieństwem, bez ezoterycznej fizyki. Blocha wektory stanu sfery i Qiskit to konkretne narzędzia do wizualizacji i pracy z nimi.
Następny artykuł opiera się na następujących podstawach: bramy kwantowe jako transformacje liniowy, konstrukcja pierwszego rzeczywistego algorytmu (stan Bella) i wykonanie na sprzęcie IBM.







