Nuclear magnetic resonance gamit ang Qiskit
Para sa module na ito ng Qiskit in Classrooms, kailangang may gumaganang Python environment ang mga estudyante na naka-install ang mga sumusunod na package:
qiskitv2.1 o mas bagoqiskit-ibm-runtimev0.40.1 o mas bagoqiskit-aerv0.17 o mas bagoscipyatmatplotlib(para sa fitting at plotting)pylatexenc(para sa pag-render ng mga circuit diagram)
Para i-set up at i-install ang mga package sa itaas, tingnan ang gabay na Install Qiskit. Para magpatakbo ng mga job sa totoong quantum computer, kailangang gumawa ng account ang mga estudyante sa IBM Quantum® sa pamamagitan ng pagsunod sa mga hakbang sa gabay na Set up your IBM Cloud® account.
Nasubukan na ang module na ito at gumagamit ito ng humigit-kumulang 5 minuto ng QPU time. Pagtatantya lang ito, at maaaring iba ang aktwal mong paggamit.
Panimula
Kapag nagpapatakbo ng NMR experiment ang isang chemist, naglalagay sila ng sample ng mga nuclear spin sa malakas na magnetic field, naglalapat ng radio-frequency (RF) pulse, at sinusukat ang signal na bumabalik. Nakasalalay ang teknik na ito sa ilang ideya mula sa quantum mechanics ng isang spin-1/2 na particle sa magnetic field. May dalawang antas ng enerhiya ang spin na pinaghihiwalay ng enerhiyang tumutugma sa isang katangi-tanging Larmor frequency. Ang resonant na pulse sa frequency na iyon ay itinutumba ang spin papunta sa transverse plane, kung saan ito nagpe-precess at nag-i-induce ng signal na unti-unting nawawala sa dalawang katangi-tanging oras, at .
Ang superconducting qubit ay isang ginawang bersyon ng parehong bagay: isang kontroladong two-level na quantum system. Ang mga estado nitong at ay katumbas ng spin-up at spin-down, ang gate na ginagamit natin para i-rotate ito ay katumbas ng RF pulse, at nawawalan ito ng coherence sa sarili nitong at . Hindi lang ito basta paghahambing; ilan sa mga pinakaunang eksperimental na quantum processor noong huling bahagi ng 1990s at unang bahagi ng 2000s ay gumamit ng NMR.
Sa module na ito, gagamit ka ng totoong quantum computer para patakbuhin ang parehong mga characterization experiment na ginagawa ng isang NMR spectroscopist (o quantum engineer na nagka-calibrate ng hardware):
-
Rabi / nutation — pagpapagalaw sa spin at pagmamasid sa pag-ikot nito. Ganito mo ka-calibrate ang o na rotation.
-
— spin-lattice relaxation, ang pagbalik ng excited na spin sa equilibrium.
-
— spin-spin relaxation (dephasing), sinusukat gamit ang Ramsey experiment at nire-refocus gamit ang Hahn echo.
-
NMR spectroscopy (chemical shift at -coupling) — pag-simulate ng maliit na molekula sa ilang qubit at pagbasa sa multiplet spectrum nito para makuha ang koneksyon sa pamamagitan ng rule.
Para sa bawat konsepto, ibibigay muna namin ang minimal na teorya, saka ipapatupad ang experiment sa Qiskit ayon sa apat na hakbang na workflow ng Qiskit patterns.
Teorya
Mga spin-1/2 na particle sa magnetic field
Ang spin-1/2 na nucleus ay may magnetic moment na , kung saan ang ay ang gyromagnetic ratio. Sa static na field na sa direksyong , nahahati sa enerhiya ang dalawang spin state (ang Zeeman effect):
Binibigyang-kahulugan ng energy gap ang Larmor (resonance) frequency na . Ang magnetic moment ay nagpe-precess sa paligid ng sa parehong frequency na ito.
Para i-rotate ang spin, naglalapat tayo ng oscillating na RF field sa (o malapit sa) . Sa frame na umiikot sa drive frequency (ang rotating frame), ang resonant na drive ay nagro-rotate sa Bloch vector sa paligid ng axis sa - plane. Ang lakas at tagal ng pulse ang nagtatakda kung gaano kalayo ang rotation (ang flip angle). Dalawang pagpipilian ang pinakamahalaga: itinutumba ng na pulse ang na spin papunta sa transverse plane, at ganap itong ini-rotate ng na pulse papunta sa .
Pagsasalin sa pagitan ng jargon ng NMR at quantum computing
Ang qubit ay isang two-level system, na matematikal na kapareho ng spin-1/2 sa magnetic field — kaya kahit sa quantum processor tayo tumatakbo at hindi sa nucleus, ang pisika ay ang parehong pisika na pinagbabatayan ng NMR. Bokabularyo lang ang magkaiba. Makakatulong ang talahanayang ito para makipag-usap ka sa mga physical chemist at quantum-computing specialist.
| NMR / spin-1/2 | Quantum processor (qubit) |
|---|---|
| Spin-up / spin-down | / |
| Zeeman gap | Enerhiya ng transition ng qubit |
| Larmor frequency | Frequency ng qubit |
| Resonant na RF pulse (flip angle ) | Single-qubit rotation gate |
| / na pulse | / |
| Spin-lattice relaxation | Oras ng energy-relaxation ng qubit na |
| Spin-spin relaxation | Oras ng dephasing ng qubit na |
| Nutation | Mga Rabi oscillation |
| Free induction decay (FID), Hahn echo | Mga Ramsey at echo sequence |
Ang lahat ng nasa ibaba ay pagsasanay sa pagsukat ng kanang hanay at pagbasa rito bilang kaliwang hanay.
I-set up ang Qiskit environment
Sinusunod natin ang workflow ng Qiskit patterns sa buong module:
-
I-map ang problema sa isang quantum circuit.
-
I-optimize ang circuit para sa execution (i-transpile sa backend).
-
I-execute gamit ang isang IBM Quantum primitive.
-
I-post-process at suriin.
Una, ilo-load natin ang runtime service at pipiliin ang pinakakaunting abalang totoong backend. Kung hindi mo pa nase-save ang iyong mga credential, tingnan ang pahina ng dokumentasyon kung paano i-save ang iyong mga login credential.
# Added by doQumentation — installs the packages this notebook needs if they are missing
import importlib.util
_needed = {"matplotlib": "matplotlib", "numpy": "numpy", "qiskit": "qiskit", "qiskit_aer": "qiskit-aer", "qiskit_ibm_runtime": "qiskit-ibm-runtime", "scipy": "scipy"}
_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")
# Load the IBM Quantum Compute Service and select the least-busy real backend
from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2 as Sampler, Batch
# After setup, this picks up your saved credentials automatically:
service = QiskitRuntimeService()
backend = service.least_busy(operational=True, simulator=False, min_num_qubits=156)
print(f"Selected backend: {backend.name}")
Selected backend: ibm_kingston
Gamitin ang cell sa ibaba para magpalit sa pagitan ng totoong hardware at local simulator para sa buong notebook. Ang pagpapatakbo sa hardware ang layunin ng module, pero kung may problema sa connectivity o paggamit, maaaring maging backup ang simulator. I-set ang USE_HARDWARE = True para tumakbo sa QPU na pinili sa itaas.
import numpy as np
from itertools import combinations
from qiskit_aer import AerSimulator
from qiskit.transpiler import generate_preset_pass_manager
from qiskit_ibm_runtime import EstimatorV2 as Estimator
USE_HARDWARE = True # <-- set True to run on the QPU selected above
USE_BATCH = False # Safer for a class with pauses; set True for an uninterrupted run
if USE_HARDWARE:
run_backend = backend # the real QPU selected above
else:
# Local testing mode: an Aer simulator that mimics the selected device -- its noise model,
# coupling map, and qubit count -- while layout choices still use real calibration data.
run_backend = AerSimulator.from_backend(backend)
# --- Choose connected qubits with low readout error. --------------------------------------
def readout_error(q):
props = backend.target["measure"].get((q,))
return props.error if props is not None and props.error is not None else 1.0
coupling_map = backend.coupling_map or backend.target.build_coupling_map()
edges = {tuple(sorted(edge)) for edge in coupling_map.get_edges() if edge[0] != edge[1]}
# AX needs one connected pair.
AX_LAYOUT = list(min(edges, key=lambda edge: sum(readout_error(q) for q in edge)))
# AX2 needs one qubit connected to two neighbours; the first entry is the central A qubit.
neighbors = {q: set() for q in range(backend.num_qubits)}
for q0, q1 in edges:
neighbors[q0].add(q1)
neighbors[q1].add(q0)
ax2_layouts = (
[a, x1, x2]
for a, adjacent in neighbors.items()
for x1, x2 in combinations(adjacent, 2)
)
AX2_LAYOUT = min(ax2_layouts, key=lambda layout: sum(readout_error(q) for q in layout))
# Use a long-lived qubit for the single-qubit experiments.
def best_qubit(backend):
return max(
range(backend.num_qubits), key=lambda q: backend.qubit_properties(q).t2 or 0.0
)
QUBIT = best_qubit(backend)
qp = backend.qubit_properties(QUBIT)
print(
f"Using qubit {QUBIT} for single-qubit experiments: "
f"T1 = {qp.t1 * 1e6:.0f} us, T2 = {qp.t2 * 1e6:.0f} us"
)
print(f"Using physical qubits {AX_LAYOUT} for AX")
print(f"Using physical qubits {AX2_LAYOUT} for AX2 (A first, then the two X spins)")
pm_q = generate_preset_pass_manager(
optimization_level=1, backend=run_backend, initial_layout=[QUBIT]
)
pm_ax = generate_preset_pass_manager(
optimization_level=1, backend=run_backend, initial_layout=AX_LAYOUT
)
pm_ax2 = generate_preset_pass_manager(
optimization_level=1, backend=run_backend, initial_layout=AX2_LAYOUT
)
# Job mode is the default because a classroom pause can deactivate a Batch. On the Open plan,
# a Batch has a 10-minute maximum lifetime and deactivates after 1 minute with no queued job.
batch = Batch(backend=run_backend) if USE_BATCH else None
execution_mode = batch if batch is not None else run_backend
sampler = Sampler(mode=execution_mode)
estimator = Estimator(mode=execution_mode)
estimator.options.resilience_level = 0 # raw expectation values, no error mitigation
estimator.options.default_shots = 1000
mode_name = "Batch" if USE_BATCH else "individual jobs"
device_name = "hardware" if USE_HARDWARE else "local simulator (runtime local mode)"
print(f"Ready. Running on {device_name} using {mode_name}.")
Experiment: Mga Rabi oscillation (nutation)
Teorya
Kapag pinagana mo ang spin nang on resonance, tuluy-tuloy na umiikot ang Bloch vector nito mula pole hanggang pole — ito ay nagnu-nutate. Kung maglalapat tayo ng rotation na may flip angle na sa paligid ng -axis sa isang qubit na nagsisimula sa , ang probability na mahanap ito sa ay:
Ito ang Rabi curve. Ang unang maximum nito ay ang na pulse (ganap na inversion, ang na pulse); ang na pulse ay isang kapat na ikot (ang na pulse na nagtutumba ng spin papunta sa transverse plane). Sa NMR, ganito mo ka-calibrate ang iyong mga pulse.
Ang literal na Rabi experiment ay nag-i-sweep ng drive amplitude o duration sa oras. Nangangailangan iyon ng pulse-level na kontrol, na inalis sa Qiskit v2.0. Dito, ini-sweep natin sa halip ang rotation angle na ng isang na gate. Pareho ang curve at ang pagkilala sa /; ang pagkakaiba lang ay direkta tayong pumipili ng anggulo sa halip na mag-calibrate ng haba ng pulse. Sa hardware na may fractional gates, native na tumatakbo ang para sa anumang .
Isang tanaw sa Bloch sphere
Ipinapakita ng animation sa ibaba ang nutation: tuluy-tuloy na iniikot ng resonant na drive ang Bloch vector sa paligid ng -axis, dinadala ito mula pababa papunta sa at pabalik. Ito mismo ang galaw na sinusukat ng Rabi curve.
I-map ang problema sa isang circuit
Bumubuo tayo ng isang parameterized na circuit, na sinusundan ng pagsukat, at susuriin ito sa maraming anggulo nang sabay-sabay mamaya.
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
theta = Parameter("theta")
rabi = QuantumCircuit(1, 1)
rabi.rx(theta, 0)
rabi.measure(0, 0)
rabi.draw("mpl")
I-optimize para sa execution
I-transpile sa isang Instruction Set Architecture (ISA) circuit para sa napiling backend.
rabi_isa = pm_q.run(rabi)
Isagawa
Ini-sweep natin ang mula hanggang (dalawang buong Rabi cycle). Kapag ipinasa ang array ng mga halaga ng parameter bilang isang Primitive Unified Bloc (PUB), lahat ng ito ay tatakbo sa iisang job.
angles = np.linspace(0, 4 * np.pi, 41)
job = sampler.run([(rabi_isa, angles.reshape(-1, 1))], shots=1000)
rabi_result = job.result()
Post-process at pagsusuri
Kunin ang sa bawat anggulo at ihambing sa .
import matplotlib.pyplot as plt
ba = rabi_result[0].data.c # BitArray, one entry per angle
shots = ba.num_shots
p1 = np.array([ba.get_counts(i).get("1", 0) / shots for i in range(len(angles))])
plt.figure(figsize=(7, 4))
plt.plot(angles, p1, "o", label="measured")
plt.plot(angles, np.sin(angles / 2) ** 2, "-", label=r"$\sin^2(\theta/2)$")
for k, name in [(np.pi / 2, r"$\pi/2$ (90°)"), (np.pi, r"$\pi$ (180°)")]:
plt.axvline(k, color="gray", ls="--", lw=1)
plt.text(k, 1.02, name, ha="center", fontsize=9)
plt.xlabel(r"flip angle $\theta$ (rad)")
plt.ylabel(r"$P_1$")
plt.title("Rabi / nutation curve")
plt.legend()
plt.tight_layout()
plt.show()

Suriin ang pag-unawa mo
Sa curve na nasukat mo, unang naaabot ng ang maximum nito sa pulse (). Ngayon, ipagpalagay na mali ang calibration ng isang device, kaya ang nominal na anggulong sa x-axis ay talagang nagbubunga ng rotation na .
(a) Sa anong nominal na anggulo lalabas ngayon ang unang maximum ng ? (b) Magiging sensitibong paraan ba ang paglapat ng isang pulse para matukoy ang 5% na error na ito?
Sagot
(a) Lumalabas ang maximum kung saan ang aktwal na rotation ay katumbas ng , ibig sabihin, sa nominal na anggulong — bahagyang paglipat ng peak pakaliwa.
(b) Hindi. Ang nominal na pulse ay nagbubunga ng aktwal na rotation na , kaya sa halip na — pagbabagong masyadong maliit para makita laban sa measurement noise. Kaya para mag-calibrate nang tumpak, pinalalaki ng mga NMR spectroscopist ang error sa pamamagitan ng paglapat ng rotation nang maraming beses (halimbawa ang method, o mahabang pulse train), para ang maliit na error kada pulse ay mag-ipon at maging malaki at masusukat na paglihis. Babalikan natin ang ideyang ito sa mga challenge problem.
Eksperimento: (spin-lattice relaxation)
Teorya
Kapag pinabayaan, ang isang excited na spin ay nagbibigay ng enerhiya sa paligid nito (ang "lattice") at bumabalik sa thermal equilibrium. Ang populasyon ng excited state ay nabubulok nang exponential ayon sa spin-lattice relaxation time na :
Para sa isang chemist, itinatakda ng ang recycle delay na kailangan mong hintayin sa pagitan ng mga scan para sa quantitative NMR, at nagbibigay ito ng impormasyon tungkol sa molecular tumbling at dynamics. Sa isang qubit, ito ang energy-relaxation time, at isa ito sa dalawang pangunahing numerong ginagamit para imodelo ang mga epekto ng decoherence sa isang quantum computer.
Ang eksperimento. Ihanda ang gamit ang gate (isang pulse), maghintay ng variable na delay na , saka sukatin. Ang bahaging nasa pa rin ang bumubuo ng decay.
Tanaw sa Bloch sphere
Ibinabalik ng relaxation ang excited state sa equilibrium, kaya ang Bloch vector ay dumudulas mula pabalik sa sa kahabaan ng -axis.
Bumuo at mag-transpile ng delay scan
Dapat konkretong halaga ang mga tagal ng delay (ini-schedule ang mga ito sa hardware time), kaya bumubuo tayo ng isang circuit kada delay.
# Scale the T1 delay sweep to the qubit's reported coherence, and snap each delay to an integer
# number of samples (dt) so there are no "duration rounded" warnings (as in the Ramsey/echo cells).
T1_us = (backend.qubit_properties(QUBIT).t1 or 100e-6) * 1e6 # reported T1 (us)
delays_us = np.linspace(0, 5 * T1_us, 20) # 0 .. ~5 T1 captures the full decay
print(f"T1 sweep: 0..{5*T1_us:.0f} us in {len(delays_us)} points")
dt = backend.dt
t1_circuits = []
for tau in delays_us:
n_dt = int(round(tau * 1e-6 / dt)) # integer samples -> no rounding warning
qc = QuantumCircuit(1, 1)
qc.x(0) # pi pulse: prepare |1>
qc.delay(n_dt, 0, unit="dt") # wait tau
qc.measure(0, 0)
t1_circuits.append(qc)
t1_isa = pm_q.run(t1_circuits)
T1 sweep: 0..1393 us in 20 points
Isagawa
t1_job = sampler.run([(c,) for c in t1_isa], shots=1000)
t1_res = t1_job.result()
Pagsusuri — i-fit ang exponential
from scipy.optimize import curve_fit
p1_t1 = np.array(
[r.data.c.get_counts().get("1", 0) / r.data.c.num_shots for r in t1_res]
)
def decay(t, A, T1, B):
return A * np.exp(-t / T1) + B
p0 = [1.0, 100.0, 0.0]
popt, _ = curve_fit(decay, delays_us, p1_t1, p0=p0, maxfev=10000)
T1_fit = popt[1]
plt.figure(figsize=(7, 4))
plt.plot(delays_us, p1_t1, "o", label="measured")
tt = np.linspace(0, delays_us.max(), 200)
plt.plot(tt, decay(tt, *popt), "-", label=rf"fit: $T_1$ = {T1_fit:.1f} µs")
plt.xlabel("delay τ (µs)")
plt.ylabel(r"$P_1$")
plt.title("$T_1$ relaxation")
plt.legend()
plt.tight_layout()
plt.show()
print(f"Measured T1 = {T1_fit:.1f} microseconds")
Measured T1 = 225.3 microseconds
Nag-iiba ang eksaktong time sa bawat eksperimento at sa bawat backend, pero dapat makakita ka ng resultang humigit-kumulang ilang daang microsecond.
Suriin ang pag-unawa mo
Sa quantitative NMR, sinasabihan kang maghintay ng mga sa pagitan ng mga scan. Gamit ang decay law, anong bahagi ng equilibrium magnetization ang bumalik na pagkatapos ng ?
Sagot
Pagkatapos ng , ang natitirang paglihis mula sa equilibrium ay , ibig sabihin, humigit-kumulang 99.3% na ang nakabalik.
Eksperimento: ,
Teorya
Sinusukat ng ang pagkawala ng enerhiya. Sinusukat naman ng ang pagkawala ng phase coherence sa transverse plane. Maoobserbahan natin ito sa pamamagitan ng Ramsey experiment: ibinababa ng isang pulse ang lahat ng spin sa equator, na lahat ay nakaturo sa iisang direksyon. Nag-Larmor precess sila, pero bawat isa ay nagpe-precess sa bahagyang magkaibang frequency, kaya kumakalat sila sa kahabaan ng equator at nabubulok ang kabuuang transverse signal, na may katangiang decay time na .
Paalala para sa mga quantum na mambabasa: Ipinapakita ng larawan ng pagkalat ang isang paraan ng pagkawala ng coherence: isang hanay ng mga tiyak na phase na nagko-cancel sa average. Mahalagang malaman na hindi ito ang tanging mekanismo. Maaari ring mawala ang coherence dahil ang phase ay nagiging entangled sa kapaligiran, kaya hindi na ito tiyak na halagang hawak ng sistema. Hindi mo matutukoy ang pagkakaiba ng dalawang mekanismo sa pagmamasid lang sa decay ng signal, kaya magandang intuwisyon ang larawan ng pagkalat. Mag-ingat lang na huwag itong basahin bilang kumpleto o literal na kuwento.
Dalawang epekto ang nagdudulot ng dephasing sa isang spin:
- Irreversible (o halos irreversible) na decoherence na nagmumula sa hindi kontroladong coupling sa ibang degrees of freedom, na inilalarawan ng tunay na . Sa NMR, karaniwang galing ito sa galaw ng molecule na nagmo-modulate sa mga coupling sa pagitan ng mga spin. Sa quantum computing, tumutugma ito sa mga hindi ninanais na coupling sa pagitan ng mga qubit at ng kapaligiran.
- Static o mabagal magbago, reversible na mga frequency offset, tulad ng field inhomogeneity, pagkakaiba ng frequency sa bawat qubit, at mga calibration error. Kapag pinagsama sa tunay na , nagbubunga ang mga ito ng mas maikling apparent decay time na na nakikita sa Ramsey experiment.
Kaya paano natin makukuha ang tunay na kung lang ang sinasabi ng Ramsey experiment? Ang pangalawang eksperimento, na tinatawag na Hahn echo, ay nagka-cancel ng lahat ng noise ng pangalawang uri para makuha ang tunay na . Pareho ang simula nito sa Ramsey experiment, na may pulse, tapos kumakalat ang mga spin gaya ng dati. Pagkalipas ng ilang oras na , may ilalapat na pulse. Binabaligtad ng pulse ang naipong phase na dulot ng mga static na frequency offset, kaya muling nagre-refocus ang mga spin pagkatapos ng pangalawang delay na kasing-haba ng una, .
Parehong mahalagang malaman ang at sa chemistry at sa quantum computing. Sa chemistry, itinatakda ng ang linewidth mo sa karaniwang NMR experiment (makikita mo kung ano ang ibig sabihin nito sa susunod na seksyon). Maraming masasabi ang tungkol sa mga molecule, tulad ng molecular tumbling, at ang pagbabago ng ay maaaring magsenyas na may kumapit na mas malaki sa molecule. Sa quantum computing, karaniwang gusto nating mahaba hangga't maaari ang parehong at , para mas marami tayong oras na magsagawa ng mga eksperimento bago madaig ng decoherence ang sistema. Isang buong pamilya ng mga teknik batay sa Hahn echo ang nagpapahaba ng oras na ito sa pamamagitan ng pag-cancel ng reversible na noise, kaya ang circuit ay ideyal na nililimitahan na lang ng tunay na , hindi ng . Tinatawag itong "dynamical decoupling."
Implementasyon
Kapag ini-implement natin ang mga Ramsey at Hahn echo experiment sa isang qubit, bahagyang naiiba ang readout kumpara sa NMR. Sa NMR, direkta mong makikita ang mga oscillating field na nililikha ng mga spin na nagpe-precess sa Larmor frequency sa transverse plane. Pero sa qubit, ang masusukat lang natin ay ang projection nito sa axis, ibig sabihin, kung o ito. Kaya, para sa parehong eksperimento, tinatapos natin ito sa dagdag na pulse na sinusundan ng measurement. Isinasalin ng pulse na ito ang impormasyon ng phase ng qubit tungo sa populasyon.
Sa ibaba, pinapatakbo natin ang bawat eksperimento para matukoy ang at .
Ramsey (): Dalawang pulse na may delay time na
Ibinabagsak ng unang pulse ang Bloch vector sa equator, at isinasalin naman ng sumunod ang phase ng Bloch vector tungo sa populasyon. Dahil nagbabago ang phase sa paglipas ng oras habang nagpe-precess ang Bloch vector, nakakakita tayo ng sinusoidal na pattern sa populasyon bilang function ng precession time na . Habang nawawalan ng phase coherence ang qubit, dapat nating makitang nabubulok ang amplitude ng sine curve na ito.
Ilan pang detalye para sa mga quantum na mambabasa: Sa mga eksperimento sa quantum computing, ang mga oscillation na nakikita natin ay hindi talaga nasa Larmor frequency, na nasa GHz range at masyadong mabilis para ma-resolve natin. Gumagana ang mga quantum experiment sa rotating frame: isang frame na umiikot kasabay ng qubit sa (halos) Larmor frequency, kaya hindi nakikita ang mabilis na precession at halos nakatigil ang tingin sa Bloch vector. Para makakita ng mga fringe, sadyang itinatakda natin ang rotating frame na bahagyang detuned mula sa Larmor frequency. Lumilitaw na nagpe-precess ang Bloch vector sa maliit na detuning na iyon, at nakakakuha tayo ng oscillating signal sa detuning frequency. Sa ibaba, hindi natin itinatakda ang detuning sa iisang halaga; pinipili natin ito para ang mga isang dosenang fringe ay sumaklaw sa measurement window (na sinusukat natin ayon sa coherence time ng qubit), na nagpapanatiling madaling i-sample ang oscillation nang walang aliasing. Isa pang kakaiba: sa Qiskit, wala tayong pulse-level na kontrol na kailangan para baguhin ang pulse frequency (na siyang nagtatakda ng frequency ng rotating frame). Sa halip, nagdaragdag tayo ng epektibong detuning nang mano-mano, gamit ito para itakda ang phase ng pangalawang Ramsey pulse. Medyo pilit ito, pero pareho ang resulta at ang decay na nakikita natin ay tunay pa ring .
Tanaw sa Bloch sphere
Ibinabagsak ng pulse ang mga spin sa equator; bawat isa ay nagpe-precess sa bahagyang magkaibang bilis at kumakalat sila, kaya lumiliit ang kabuuang (pulang) vector habang nagde-dephase sila — ang decay na ito ay .
# Adaptive Ramsey: scale the window to the reported coherence and choose the detuning so a fixed
# number of fringes span it. This decouples the point count from the window -- a long window stays
# cheap and cannot alias (we keep 8 samples per fringe).
T2_us = (backend.qubit_properties(QUBIT).t2 or 100e-6) * 1e6 # reported (echo) T2 (us)
ramsey_span = 0.5 * T2_us # window = half the reported T2
n_fringes = 12 # fringes across the window
f_detune = n_fringes / (
ramsey_span * 1e-6
) # adaptive detuning (Hz) -> low, so a long window is cheap
samp_per_fringe = 8
n_ramsey = n_fringes * samp_per_fringe + 1 # ~97 points, fixed regardless of T2
ramsey_delays_us = np.linspace(0, ramsey_span, n_ramsey)
print(
f"Ramsey sweep: 0..{ramsey_span:.0f} us in {n_ramsey} points "
f"(detuning {f_detune/1e3:.1f} kHz, {samp_per_fringe} samples/fringe)"
)
dt = backend.dt # seconds per sample
delays_dt = [int(round(t * 1e-6 / dt)) for t in ramsey_delays_us] # integer samples
actual_delays_us = np.array(delays_dt) * dt * 1e6 # true (snapped) delays for fitting
ramsey_circ = []
for n_dt, tau_us in zip(delays_dt, actual_delays_us):
qc = QuantumCircuit(1, 1)
qc.rx(np.pi / 2, 0)
qc.delay(n_dt, 0, unit="dt") # integer duration -> no rounding warning
qc.rz(
2 * np.pi * f_detune * tau_us * 1e-6, 0
) # detuning phase (uses the true delay)
qc.rx(np.pi / 2, 0)
qc.measure(0, 0)
ramsey_circ.append(qc)
ramsey_isa = pm_q.run(ramsey_circ)
ramsey_res = sampler.run([(c,) for c in ramsey_isa], shots=1000).result()
p1_ramsey = np.array(
[r.data.c.get_counts().get("1", 0) / r.data.c.num_shots for r in ramsey_res]
)
ramsey_circ[len(ramsey_circ) // 2].draw("mpl") # draw a sample circuit (mid-sweep)
Ramsey sweep: 0..248 us in 97 points (detuning 48.4 kHz, 8 samples/fringe)
Hahn echo (): Magdagdag ng refocusing na pulse sa gitna
Tanaw sa Bloch sphere
Ang Hahn echo: kumakalat ang mga spin gaya ng dati, tapos binabaligtad sila ng isang pulse, kaya ang patuloy nilang precession ay nagre-refocus sa kanila pabalik nang magkakasama (muling lumalaki ang pulang vector), na nagbabalik ng coherence na nawala dahil sa static dephasing.
# Scale the echo sweep to the reported (echo) T2. The echo signal is monotonic (no fringes),
# so only the range matters here; 0 .. ~2.5 T2 shows the full decay for a clean fit.
T2_us = (backend.qubit_properties(QUBIT).t2 or 100e-6) * 1e6
echo_delays_us = np.linspace(0, 2.5 * T2_us, 24) # total free-evolution time
print(f"Echo sweep: 0..{2.5*T2_us:.0f} us in {len(echo_delays_us)} points")
dt = backend.dt
half_dt = [
int(round(t / 2 * 1e-6 / dt)) for t in echo_delays_us
] # samples per half-delay
actual_echo_us = np.array(half_dt) * 2 * dt * 1e6 # true total delay for fitting
echo_circ = []
for n_half in half_dt:
qc = QuantumCircuit(1, 1)
qc.rx(np.pi / 2, 0)
qc.delay(n_half, 0, unit="dt") # half the free-evolution, integer samples
qc.rx(np.pi, 0) # refocusing pi pulse
qc.delay(n_half, 0, unit="dt")
qc.rx(-np.pi / 2, 0)
qc.measure(0, 0)
echo_circ.append(qc)
echo_isa = pm_q.run(echo_circ)
echo_res = sampler.run([(c,) for c in echo_isa], shots=1000).result()
p1_echo = np.array(
[r.data.c.get_counts().get("1", 0) / r.data.c.num_shots for r in echo_res]
)
echo_circ[len(echo_circ) // 2].draw("mpl") # draw a sample circuit
Echo sweep: 0..1240 us in 24 points
Pagsusuri: I-fit at ihambing ang dalawang decay
# Initial guesses / bounds derived from the reported coherence so the fits track the scaled axes.
T2_us = (backend.qubit_properties(QUBIT).t2 or 100e-6) * 1e6
# Ramsey: decaying oscillation -> extract T2*
def ramsey_fn(t, A, T2s, f, phi, B):
return A * np.exp(-t / T2s) * np.cos(2 * np.pi * f * t + phi) + B
rp0 = [0.4, T2_us / 2, f_detune * 1e-6, 0.0, 0.5] # T2* guess ~ half the echo T2
rbounds = (
[0, 0.1, 0, -np.pi, 0],
[1, 2 * T2_us, 5, np.pi, 1],
) # keep the fit from collapsing to ~0
rpopt, _ = curve_fit(
ramsey_fn, ramsey_delays_us, p1_ramsey, p0=rp0, bounds=rbounds, maxfev=20000
)
T2_star = abs(rpopt[1])
# Echo: simple exponential envelope -> extract T2
def env(t, A, T2, B):
return A * np.exp(-t / T2) + B
epopt, _ = curve_fit(env, echo_delays_us, p1_echo, p0=[0.5, T2_us, 0.0], maxfev=10000)
T2 = abs(epopt[1])
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(ramsey_delays_us, p1_ramsey, "o")
tt = np.linspace(0, ramsey_delays_us.max(), 400)
ax[0].plot(tt, ramsey_fn(tt, *rpopt), "-")
ax[0].set_title(rf"Ramsey: $T_2^*$ = {T2_star:.1f} µs")
ax[0].set_xlabel("τ (µs)")
ax[0].set_ylabel(r"$P_1$")
ax[1].plot(echo_delays_us, p1_echo, "o")
tt2 = np.linspace(0, echo_delays_us.max(), 400)
ax[1].plot(tt2, env(tt2, *epopt), "-")
ax[1].set_title(rf"Hahn echo: $T_2$ = {T2:.1f} µs")
ax[1].set_xlabel("τ (µs)")
plt.tight_layout()
plt.show()
print(f"T2* (Ramsey) = {T2_star:.1f} µs ; T2 (echo) = {T2:.1f} µs")

T2* (Ramsey) = 171.2 µs ; T2 (echo) = 326.0 µs
Dito makikita natin ang parehong Ramsey oscillation at ang Hahn echo signal na nabubulok, gaya ng inaasahan. Ang mga kaugnay na time scale ng mga decay na ito ay at , ayon sa pagkakasunod.
Suriin ang pag-unawa mo
Karaniwan dapat mong makita na . Ipaliwanag kung bakit sa isang pangungusap, at sabihin kung anong pisikal na epekto ang inaalis ng pulse ng Hahn echo, pati kung ano ang hindi nito kayang alisin.
Sagot
Kasama sa ang parehong irreversible na dephasing at reversible na static na pagkalat, kaya mas mabilis itong nabubulok; nire-refocus ng pulse ng echo ang static, reversible na dephasing (field inhomogeneity / mga nakapirming frequency offset), at ang natitira lang ay ang irreversible na spin-spin dephasing, na siyang tunay na . Hindi kayang bawiin ng echo ang mga pagbabago-bago na nag-iiba sa pagitan ng dalawang kalahati ng sequence.
NMR spectroscopy ng isang molecule: Chemical shift at -coupling
Mula sa isang spin tungo sa isang molecule
Ang mga eksperimento hanggang ngayon ay nagkarakterisa ng iisang nakahiwalay na spin. Ang tunay na chemical NMR ay bumabasa ng isang molecule (maraming magkakakabit na spin nang sabay-sabay) at ginagamit ang nagreresultang spectrum para ipahiwatig ang mga katangian ng istruktura ng molecule. Makapagsasabi ito sa atin tungkol sa dalawang epekto:
-
Chemical shift. Bawat chemically distinct na nucleus ay nagpe-precess sa bahagyang magkaibang frequency na , dahil ang mga lokal nitong electron ay nagsisilbing panangga sa inilapat na field sa magkakaibang antas. Kaya ang mga posisyon ng peak ay nagtutukoy ng mga chemical environment (halimbawa, isang CH na proton laban sa isang aromatic).
-
Scalar -coupling. Isang through-bond na interaksyon sa pagitan ng dalawang spin na naghahati sa bawat peak tungo sa multiplet. Ang nucleus na may equivalent na kapitbahay ay nahahati sa na linya na may binomial na intensity, ang rule. Ang pattern ng paghahati ay nagpapakita ng connectivity (aling mga nucleus ang magkabigkis), at ang pagitan ay ang coupling constant na .
Ang eksperimento
Para imodelo ito sa quantum computer natin, kailangan nating mag-implement ng spin Hamiltonian sa mga qubit. Sa weak-coupling, high-field na limit (mga pagkakaiba ng chemical shift mga coupling), nagka-cancel sa average ang mga bahaging at ng coupling, at na lang ang natitira. Kaya ang Hamiltonian ay (sa mga unit ng angular frequency, ):
Ang bawat nucleus ay isang qubit: ang chemical shift ay isang single-qubit na rotation, at ang coupling ay isang two-qubit na na interaksyon.
Ganito ang takbo ng eksperimento. Ibinabagsak ng pulse ang bawat spin sa transverse plane, at ang mga spin ay nagpe-precess at nagko-couple sa loob ng oras na . Itinatala natin ang complex transverse magnetization na na ibinuo mula sa lahat ng spin. Gaya sa Ramsey experiment sa itaas, ang transverse magnetization na ito ay bumubuo ng nabubulok na sinusoid bilang function ng precession time na . Kapag kinuha natin ang Fourier transform ng signal, nakakakuha tayo ng spectrum na may mga peak sa chemical shift na na hinati ng scalar coupling na .
Sini-simulate natin ang ebolusyon ng molecule sa pamamagitan ng pag-map ng oras na sa mga rotation angle: ang mas malaking ay nangangahulugan ng mas malalaking at rotation, hindi ng mas mahaba o mas malalim na circuit. Kaya habang sumusulong nga ang simulated na state kasabay ng (iyan ang dahilan kung bakit nag-o-oscillate ang free induction decay (FID)), hindi mas matagal na naka-idle ang mga pisikal na qubit at walang decoherence na nakadepende sa . Kaya ang simulated na FID ay hindi kailanman nabubulok nang kusa. Para sa walang-hanggang haba na ideyal na FID, walang-hanggang matalas ang mga spectral line; sa halip, ang may hangganan nating sampling window ay nagbibigay sa kanila ng may hangganang resolution at maaaring magdulot ng spectral leakage. Ang mga tunay na NMR line ay may hangganang lapad na itinatakda ng . Idinaragdag natin ito pabalik sa pamamagitan ng pagpaparami sa FID ng window na bago ang Fourier transform. Tinatawag itong line-broadening apodization, na ginagamit ng mga spectroscopist sa processing para itakda ang linewidth (ipinagpapalit ang resolution para sa signal-to-noise). (Ang isang opsyonal na cell sa Appendix ng module na ito ay nagpapakita ng Trotterized na alternatibo, kung saan ang decay ay nagmumula sa tunay na decoherence na lumalaki kasabay ng lalim ng circuit.)
Ang AX system
Magsimula tayo sa tinatawag na AX system, isang molecule na binubuo ng dalawang magkakakabit, chemically distinct na spin. Ang mga label na A at X ay tumutukoy sa dalawang chemically distinct na spin environment. Arbitraryo ang mga letra, pero ang katotohanang magkalayo sila sa alpabeto ay naglalarawan ng kanilang chemical na pagkakaiba.
I-map at i-optimize
Sumusulat tayo ng isang function na, kapag binigyan ng mga chemical-shift offset na at mga coupling na , ay nagbabalik ng parameterized na state-preparation circuit. Ibinabagsak ng pulse ang mga spin sa equator, tapos sini-simulate ng mga rotation ang ebolusyon ng state sa ilalim ng mga chemical-shift at -coupling na termino. Ang bawat ay maliit na precession offset sa Hz kaugnay ng napiling reference, o rotating-frame carrier. Dito, mano-mano natin itong itinatakda; sa tunay na molecule, binabago ng electron shielding ang lokal na magnetic field at inililipat nito ang resonance ng bawat nucleus kaugnay ng reference na iyon. Imomodelo ito ng mga single-qubit na gate, isa kada spin, at itinatakda ng bawat kung saan nakaupo ang peak ng spin na iyon sa spectrum. Inilalapat ng two-qubit na gate ang coupling na , na naghahati sa bawat peak tungo sa multiplet at nagtatakda ng pagitan ng mga linya nito.
from qiskit import QuantumCircuit
from qiskit.circuit import Parameter
from qiskit.quantum_info import SparsePauliOp
t = Parameter(
"t"
) # evolution time (arbitrary units; the frequencies below are in matching units)
def fid_circuit(offsets, couplings):
"""State-preparation circuit for a set of spins: a pi/2 pulse, then evolution under the
chemical-shift + J-coupling Hamiltonian for time t. No measurement -- the Estimator reads
<X> and <Y> directly.
offsets : list of chemical-shift frequencies nu_i, one per qubit
couplings : dict {(i, j): J_ij}
"""
n = len(offsets)
qc = QuantumCircuit(n)
qc.ry(np.pi / 2, range(n)) # pi/2 pulse: tip every spin into the transverse plane
for i, nu in enumerate(offsets):
qc.rz(2 * np.pi * nu * t, i) # chemical-shift precession -> line at nu_i
for (i, j), J in couplings.items():
qc.rzz(np.pi * J * t, i, j) # J-coupling -> splitting of size J
return qc
def transverse_obs(n):
"""Total transverse observables (sum over spins): (sum_i X_i, sum_i Y_i)."""
ox = SparsePauliOp.from_sparse_list(
[("X", [i], 1.0) for i in range(n)], num_qubits=n
)
oy = SparsePauliOp.from_sparse_list(
[("Y", [i], 1.0) for i in range(n)], num_qubits=n
)
return ox, oy
# AX system: two distinct chemical shifts, one coupling
ax_offsets = [6.0, -6.0] # chemical shifts nu_1, nu_2 (Hz)
ax_couplings = {(0, 1): 2.0} # J_12 = 2 Hz
ax_isa = pm_ax.run(fid_circuit(ax_offsets, ax_couplings))
fid_circuit(ax_offsets, ax_couplings).draw("mpl")
Isagawa at i-post-process
Sinusuri natin ang circuit sa isang grid ng mga evolution time, at ibinabalik ng Estimator ang at sa bawat isa. Pinagsasama natin ang mga ito sa complex FID na , inilalapat ang apodization window, at kinukuha ang Fourier transform ng resulta para makuha ang spectrum.
# --- time grid ---
n_t = 128 # number of FID samples
dt = 1 / 32 # time step -> Nyquist frequency = 1/(2 dt) = 16 Hz
times = np.arange(n_t) * dt
# --- Step 3-4: Estimator returns <X> and <Y> directly (both quadratures in one job) ---
def run_fid(isa_circ, n, est):
"""Complex FID s(t) = sum_i <X_i> + i <Y_i> over the time grid, via the Estimator."""
ox, oy = transverse_obs(n)
ox = ox.apply_layout(isa_circ.layout) # map observables onto the transpiled qubits
oy = oy.apply_layout(isa_circ.layout)
params = times.reshape(-1, 1)
res = est.run(
[(isa_circ, ox, params), (isa_circ, oy, params)]
).result() # both quadratures, one job
return res[0].data.evs + 1j * res[1].data.evs
def spectrum(fid, T2=1.0):
sig = fid * np.exp(-times / T2) # apodization -> Lorentzian linewidth ~ 1/(pi T2)
spec = np.fft.fftshift(np.fft.fft(sig))
freq = np.fft.fftshift(np.fft.fftfreq(len(times), dt))
return freq, np.abs(spec)
fid_ax = run_fid(ax_isa, n=2, est=estimator)
freq, spec = spectrum(fid_ax, T2=1.0)
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(times, fid_ax.real, label=r"Re $s(t)=\langle X\rangle$")
ax[0].plot(times, fid_ax.imag, label=r"Im $s(t)=\langle Y\rangle$")
ax[0].set_xlabel("evolution time $t$")
ax[0].set_ylabel("transverse signal")
ax[0].set_title("AX free induction decay")
ax[0].legend()
ax[1].plot(freq, spec)
for nu in ax_offsets:
for s in (-1, 1):
ax[1].axvline(nu + s * ax_couplings[(0, 1)] / 2, color="gray", ls="--", lw=1)
ax[1].set_xlim(-12, 12)
ax[1].set_xlabel(r"frequency $\nu$ (Hz)")
ax[1].set_ylabel("intensity")
ax[1].set_title("AX spectrum: two doublets, split by $J$")
plt.tight_layout()
plt.show()
print(
"Expected AX lines (Hz):",
sorted({nu + s * ax_couplings[(0, 1)] / 2 for nu in ax_offsets for s in (-1, 1)}),
)

Expected AX lines (Hz): [-7.0, -5.0, 5.0, 7.0]
Extension: Isang AX system at ang rule
Ngayon, magdagdag ng pangalawang equivalent na kapitbahay. Sa isang AX system, isang A na spin ang nagko-couple, sa parehong , sa dalawang equivalent na X na spin. (Tandaan, label lang ang X para sa dalawang equivalent na spin; walang kinalaman ito sa mga Pauli operator. Ang bawat coupling sa ibaba ay pa rin.) Nakikita ng spin A ang apat na configuration ng kapitbahay ; nagtutugma ang dalawang halo, kaya nahahati ang A sa isang 1:2:1 triplet ( linya). Ang bawat X spin ay A lang ang nakikita at nananatiling doublet. Hindi naghahati sa isa't isa ang mga equivalent na spin, kaya hindi tayo nagsasama ng X–X coupling.
Ang isang tunay na molecule na may ganitong pattern ay ang 1,1,2-trichloroethane (ClCH–CHCl). Kapag hydrogen spin ang tinutukan (ang pinakakaraniwang anyo ng NMR), ang nag-iisang hydrogen proton sa CH ang gumaganap bilang A, at ang dalawang equivalent na CH proton ang dalawang X na spin. Ngayon, bilangin lang ang mga kapitbahay: ang CH proton ay may dalawang kapitbahay (ang CH pair), kaya nahahati ang signal nito sa 1:2:1 triplet (); ang bawat CH proton ay may isang kapitbahay lang (ang CH), kaya ang CH signal ay isang 1:1 doublet (). Pansinin na ang grupong may mas kaunting proton (CH) ay nagpapakita ng mas maraming linya; ang bilang ng linya ay sumasalamin kung ilang kapitbahay ang isang signal, hindi kung ilang proton ang nagbabahagi nito.
Sa ibaba, sini-simulate natin ang isang AX system gamit ang tatlong qubit.
# AX2: spin A (qubit 0) coupled equally to two equivalent X spins (qubits 1, 2)
ax2_offsets = [6.0, -6.0, -6.0] # A at +6 Hz; the two X both at -6 Hz
ax2_couplings = {
(0, 1): 2.0,
(0, 2): 2.0,
} # equal A-X couplings; no coupling between the X spins
ax2_isa = pm_ax2.run(fid_circuit(ax2_offsets, ax2_couplings))
fid_ax2 = run_fid(ax2_isa, n=3, est=estimator)
freq2, spec2 = spectrum(fid_ax2, T2=1.0)
fig, ax = plt.subplots(1, 2, figsize=(12, 4))
ax[0].plot(times, fid_ax2.real, label=r"Re $s(t)=\langle X\rangle$")
ax[0].plot(times, fid_ax2.imag, label=r"Im $s(t)=\langle Y\rangle$")
ax[0].set_xlabel("evolution time $t$")
ax[0].set_ylabel("transverse signal")
ax[0].set_title("AX$_2$ free induction decay")
ax[0].legend()
ax[1].plot(freq2, spec2)
ax[1].set_xlim(-12, 12)
ax[1].set_xlabel(r"frequency $\nu$ (Hz)")
ax[1].set_ylabel("intensity")
ax[1].set_title(r"AX$_2$ spectrum: A is a 1:2:1 triplet, X is a doublet")
plt.tight_layout()
plt.show()
print(
"A triplet at (Hz):",
[ax2_offsets[0] + k * ax2_couplings[(0, 1)] for k in (-1, 0, 1)],
)
print(
"X doublet at (Hz):",
[ax2_offsets[1] + s * ax2_couplings[(0, 1)] / 2 for s in (-1, 1)],
)
Suriin ang pag-unawa mo
Basahin ang bawat tanong, pag-isipan ang sagot mo, saka i-click ang tatsulok para ipakita ang solusyon.
Sa AX spectrum, ang dalawang doublet ay pinaghihiwalay (center-to-center) ng 12 Hz, at ang dalawang linya sa loob ng bawat doublet ay 2 Hz ang layo. Alin ang pagkakaiba ng chemical shift at alin ang coupling constant na ? Kung lilipat ka sa spectrometer na may doble ang magnetic field, alin ang magbabago?
Sagot
Ang 12 Hz na center-to-center na paghihiwalay ay ang pagkakaiba ng chemical shift (); ang 2 Hz na pagitan ng linya ay ang coupling constant na . Nagmumula ang mga chemical shift sa shielding ng , kaya sumasabay sila sa field. Sa doble ng field, dumodoble ang paghihiwalay sa 24 Hz. Ang coupling na ay through-bond na katangian ng molecule at hindi nakadepende sa field, kaya nananatili itong 2 Hz. Natutukoy ng mga chemist ang shift mula sa coupling sa pagmamasid kung paano sumasabay ang isang paghahati sa field.
Gamit ang rule, hulaan ang A multiplet kung magdadagdag ng pangatlong equivalent na X spin (isang AX system), at ipaliwanag kung bakit hindi naghahati sa isa't isa ang dalawang equivalent na X spin sa AX.
Sagot
Sa na equivalent na kapitbahay, nagiging 1:3:3:1 na quartet ang A. Hindi naghahati sa isa't isa ang mga equivalent na spin dahil inililipat ng coupling nila ang mga kaugnay na energy level nang pare-pareho ang halaga, kaya ang mga agwat sa pagitan ng mga level na iyon — ang mga frequency na nakikita natin — ay hindi nagbabago.
Konklusyon
Gumamit tayo ng tunay na quantum computer para tuklasin kung paano nagpe-precess at nagde-decohere ang mga nuclear spin sa isang NMR experiment, at kung paano bigyang-kahulugan ang mga nagreresultang spectra. Sulit na umatras sandali at repasuhin kung bakit ito naging posible, at kung bakit higit pa ito sa isang kuryosidad lang.
Ang qubit at ang spin-1/2 na nucleus ay, sa matematika, iisang bagay: mga two-level na quantum system sa Bloch sphere, na pinaiikot ng mga resonant na pulse, nagpe-precess sa isang axis, at nawawalan ng coherence sa kanilang paligid. Ang buong bokabularyo ng module na ito (ang Larmor frequency, ang rotating frame, , , at , Ramsey fringes, ang Hahn echo) ay pag-aari ng NMR at quantum computing nang pantay. Ang tawag ng chemist na chemical shift ay tinatawag ng quantum engineer na single-qubit rotation; ang tawag ng chemist na -coupling ay tinatawag ng quantum engineer na interaction. Iisang pisika ang inilalarawan ng dalawang larangan sa magkaibang salita.
Makasaysayan ang koneksyong iyon, hindi lang konseptwal: ang NMR ay isa sa mga unang platform na nagpatakbo ng tunay na quantum algorithm. Noong 2001, isang molecule sa solusyon ang nagpatakbo ng algorithm ni Shor para i-factor ang 15, kung saan ang bawat nuclear spin ay nagsilbing qubit. Ibinigay din ng NMR sa quantum computing ang malaking bahagi ng toolkit nito sa kontrol. Ang spin echo, mga CPMG pulse train, composite pulse, at dynamical decoupling ay pawang naimbento ng mga spectroscopist mga dekada bago pa kailanganin ng mga qubit ang mga ito para labanan ang decoherence. May kasiya-siyang simetriya sa ginawa natin: ang larangang nagsilang sa mga unang quantum computer ay isa na ngayong bagay na kayang i-simulate ng quantum computer.
Pagsusuri at mga tanong
Mga kritikal na konsepto
-
Ang qubit ay isang engineered na two-level system na katumbas ng spin-1/2; ang , frequency, mga gate, , at nito ay direktang katumbas ng mga dami sa NMR.
-
Pinaiikot ng isang resonant na pulse ang Bloch vector; itinatakda ng flip angle ang rotation, at ang Rabi/nutation curve na ang nagtutukoy sa mga at na rotation.
-
Ang ay energy (spin-lattice) relaxation; ang ay phase (spin-spin) relaxation; ang ay may kasama pang reversible na static dephasing na nire-refocus ng Hahn echo.
-
Ang molecule ay isang hanay ng magkakakabit na spin: itinatakda ng chemical shift ang posisyon ng bawat peak, at hinahati ng -coupling ang mga peak tungo sa mga multiplet ayon sa rule, na magkasamang nag-eencode ng chemical environment at connectivity.
Totoo / Mali
-
T/F Ang Larmor frequency ay ang energy gap sa pagitan ng dalawang spin state na hinati sa .
-
T/F Ang () na pulse ay lubusang bumabaligtad sa isang spin na nasa equilibrium.
-
T/F Ang ay karaniwang mas mahaba kaysa sa .
-
T/F Nire-refocus ng Hahn echo ang irreversible na spin-spin dephasing.
-
T/F Sa isang AX system, lumilitaw ang A nucleus bilang 1:2:1 triplet.
-
T/F Dumodoble ang coupling constant na kapag dinoble mo ang magnetic field ng spectrometer.
-
T/F Ang pag-alis ng Qiskit Pulse ay nagiging imposible ang pagsukat ng sa kasalukuyang hardware.
Maikling sagot
-
Ipaliwanag sa dalawang pangungusap kung bakit mahinang paraan ang isang pulse para matukoy ang na flip-angle error, at kung paano ito naaayos ng pagkakadena ng mga pulse.
-
Ang isang sample ay nagpapakita ng malalapad na NMR line. Sa usapin ng , ano ang ipinapahiwatig nito, at ano ang katumbas na dami sa qubit?
-
Ibigay ang katumbas sa qubit ng bawat isa: (a) ang recycle delay, (b) ang na pulse, (c) ang chemical shift.
-
Gamit ang rule, ipaliwanag kung bakit ang isang ethyl group (CHCH–) ay nagpapakita ng 1:2:1 triplet at 1:3:3:1 quartet, at tukuyin kung aling grupo ang gumagawa ng aling multiplet.
Mga challenge problem
-
Carr-Purcell train. Baguhin ang Hahn echo para maglagay ng na pantay ang pagitan na pulse (isang CPMG-style na train) at sukatin ang bilang function ng . Talakayin kung bakit maaaring pahabain ng mas maraming refocusing pulse ang apparent na .
-
Pagpapalaki ng error ng pulse. Bumuo ng circuit na naglalapat ng nang beses sa at i-plot ang laban sa para sa sadyang maling anggulong . Ipakita kung paano nagiging nakikita ang error habang lumalaki ang . Hint: maglagay ng barrier pagkatapos ng bawat rotation; kung hindi, maaaring pagsamahin ng transpiler ang mga paulit-ulit na rotation tungo sa iisang katumbas na gate.
-
Ethyl group. Gamit ang
fid_circuit, buuin ang proton spectrum ng isang ethyl fragment (CH–CH): limang qubit, kung saan ang tatlong CH proton ay may iisang chemical shift at ang dalawang CH proton ay may isa pa, at ang bawat CH–CH pair ay magkakabit sa parehong (walang coupling sa loob ng equivalent na grupo). Hulaan ang pattern gamit ang rule, saka i-simulate; dapat makuha mo ang 1:3:3:1 quartet (CH) at 1:2:1 triplet (CH).
Appendix (opsyonal): Trotterized na ebolusyon — hayaang decoherence ang magtakda ng linewidth
Sa seksyong NMR spectroscopy ng isang molecule, inilalapat ang ebolusyong sa iisang layer na ang lalim ay hindi lumalaki kasabay ng , kaya hindi nabubulok nang kusa ang FID at ipinapataw natin ang linewidth gamit ang na apodization window. Kabaligtaran ang diskarte ng opsyonal na cell na ito. Hinahati nito ang ebolusyon sa na Trotter step at naglalagay ng barrier pagkatapos ng bawat step (para hindi maibalik ng transpiler ang mga ito sa iisang layer). Ang time point na ay gumagamit ng na step, kaya lumalaki ang lalim ng circuit kasabay ng oras.
Dahil nagko-commute ang bawat termino sa , eksakto ito: sa noiseless na simulator, nagbibigay ito ng parehong matatalas na peak. Pero sa noise-model backend o tunay na hardware, ang naiipong gate error ay nagiging dahilan para mabulok nang kusa ang FID, at iyon ang nagtatakda ng linewidth. Ito ang ideya ng linewidth sa seksyong , experiment, na ngayon ay nagmumula sa tunay na decoherence sa halip na processing window. Pinapatakbo natin ang parehong AX system (dalawang doublet) at AX system (isang 1:2:1 triplet at isang doublet) sa ganitong paraan.
Dalawang praktikal na paalala. Una, ang gastos ay nasa lalim: ang pinakamalalim na AX circuit ay gumagamit ng two-qubit gate at halos doble niyon ang AX na bersyon, kaya mas maingay at mas magastos ang dalawa kaysa sa eksaktong bersyon. Pangalawa, isinusumite pa rin bilang isang job ang bawat spin system, at ginagamit muli ng bawat time point ang parehong physical-qubit layout na pinili sa spectroscopy section. Kung USE_BATCH=True, ginagamit din ng mga job na ito ang opsyonal na notebook-wide na Batch.
# Trotterized FID: depth grows with time, so real decoherence (not apodization) sets the linewidth.
estimator.options.default_shots = 2000 # deep circuits need more shots in this appendix
n_tr, dt_tr = (
48,
1 / 20,
) # Nyquist = 1/(2 dt) = 10 Hz (covers the AX2 triplet's 8 Hz line)
times_tr = np.arange(n_tr) * dt_tr
APODIZE_TROTTER = False # keep False so the linewidth comes from decoherence
def trotter_fid_circuit(offsets, couplings, p, step):
n = len(offsets)
qc = QuantumCircuit(n)
qc.ry(np.pi / 2, range(n)) # 90-degree pulse
for _ in range(p): # p Trotter steps, each of duration `step`
for i, nu in enumerate(offsets):
qc.rz(2 * np.pi * nu * step, i) # chemical-shift evolution for one step
for (i, j), J in couplings.items():
qc.rzz(np.pi * J * step, i, j) # J-coupling evolution for one step
qc.barrier() # <-- stops the transpiler merging the steps
return qc
def run_trotter(offsets, couplings, n, est, pass_manager):
# Time point k uses k Trotter steps (its own circuit). Submit every time point and both
# quadratures together as ONE Estimator job, using one fixed physical-qubit layout.
ox, oy = transverse_obs(n)
pubs = []
for k in range(n_tr):
isa = pass_manager.run(trotter_fid_circuit(offsets, couplings, k, dt_tr))
pubs.append((isa, ox.apply_layout(isa.layout))) # <X> at time k
pubs.append((isa, oy.apply_layout(isa.layout))) # <Y> at time k
res = est.run(pubs).result()
return np.array(
[res[2 * k].data.evs + 1j * res[2 * k + 1].data.evs for k in range(n_tr)]
)
def trotter_spectrum(fid):
sig = fid * np.exp(-times_tr / 1.0) if APODIZE_TROTTER else fid
spec = np.abs(np.fft.fftshift(np.fft.fft(sig)))
freq = np.fft.fftshift(np.fft.fftfreq(n_tr, dt_tr))
return freq, spec
fid_tr = run_trotter(
ax_offsets, ax_couplings, 2, estimator, pm_ax
) # AX -> two doublets
fid2_tr = run_trotter(
ax2_offsets, ax2_couplings, 3, estimator, pm_ax2
) # AX2 -> triplet + doublet
f_ax, s_ax = trotter_spectrum(fid_tr)
f_ax2, s_ax2 = trotter_spectrum(fid2_tr)
fig, ax = plt.subplots(1, 3, figsize=(15, 4))
ax[0].plot(times_tr, np.abs(fid_tr), "o-", label="AX")
ax[0].plot(times_tr, np.abs(fid2_tr), "s-", label="AX$_2$")
ax[0].set_xlabel("evolution time $t$")
ax[0].set_ylabel("|FID|")
ax[0].set_title("Trotter FID envelope (decays only on a noisy backend)")
ax[0].legend()
ax[1].plot(f_ax, s_ax)
ax[1].set_xlim(-12, 12)
ax[1].set_xlabel(r"frequency $\nu$ (Hz)")
ax[1].set_ylabel("intensity")
ax[1].set_title("AX: two doublets")
ax[2].plot(f_ax2, s_ax2)
ax[2].set_xlim(-12, 12)
ax[2].set_xlabel(r"frequency $\nu$ (Hz)")
ax[2].set_title("AX$_2$: 1:2:1 triplet + doublet")
plt.tight_layout()
plt.show()
print(
f"Deepest AX circuit: {n_tr-1} two-qubit gates; deepest AX2 circuit: {2*(n_tr-1)} two-qubit gates."
)
print(
"Noiseless backend: |FID| stays flat, peaks razor-sharp (set APODIZE_TROTTER=True to tame ripples)."
)
print(
"Noise-model backend / hardware: |FID| decays on its own and the peaks gain a real linewidth."
)
# Close the optional runtime Batch, if one was opened.
if batch is not None:
batch.close()