Lumaktaw sa pangunahing nilalaman
Ang proyektong ito ay nasa beta. Nakakita ng bug? Mag-bukas ng GitHub issue. May tanong o ideya? Magtanong sa Discussions — gusto naming marinig ang iyong feedback!
Gaano kaganda ang kalidad ng pagsasalin sa pahinang ito?

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:

  • qiskit v2.1 o mas bago
  • qiskit-ibm-runtime v0.40.1 o mas bago
  • qiskit-aer v0.17 o mas bago
  • scipy at matplotlib (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, T1T_1 at T2T_2.

Ang superconducting qubit ay isang ginawang bersyon ng parehong bagay: isang kontroladong two-level na quantum system. Ang mga estado nitong ∣0⟩|0\rangle at ∣1⟩|1\rangle 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 T1T_1 at T2T_2. 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 π\pi o π/2\pi/2 na rotation.

  • T1T_1 — spin-lattice relaxation, ang pagbalik ng excited na spin sa equilibrium.

  • T2T_2 — spin-spin relaxation (dephasing), sinusukat gamit ang Ramsey experiment at nire-refocus gamit ang Hahn echo.

  • NMR spectroscopy (chemical shift at JJ-coupling) — pag-simulate ng maliit na molekula sa ilang qubit at pagbasa sa multiplet spectrum nito para makuha ang koneksyon sa pamamagitan ng n+1n+1 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 μ=γℏI\boldsymbol{\mu} = \gamma \hbar \mathbf{I}, kung saan ang γ\gamma ay ang gyromagnetic ratio. Sa static na field na B0B_0 sa direksyong zz, nahahati sa enerhiya ang dalawang spin state (ang Zeeman effect):

E±=∓12γℏB0,ΔE=γℏB0=ℏω0.E_{\pm} = \mp \tfrac{1}{2}\gamma \hbar B_0, \qquad \Delta E = \gamma \hbar B_0 = \hbar \omega_0 .

Binibigyang-kahulugan ng energy gap ang Larmor (resonance) frequency na ω0=γB0\omega_0 = \gamma B_0. Ang magnetic moment ay nagpe-precess sa paligid ng B0B_0 sa parehong frequency na ito.

Para i-rotate ang spin, naglalapat tayo ng oscillating na RF field sa (o malapit sa) ω0\omega_0. 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 xx-yy plane. Ang lakas at tagal ng pulse ang nagtatakda kung gaano kalayo ang rotation (ang flip angle). Dalawang pagpipilian ang pinakamahalaga: itinutumba ng 90∘90^\circ na pulse ang +1/2+1/2 na spin papunta sa transverse plane, at ganap itong ini-rotate ng 180∘180^\circ na pulse papunta sa −1/2-1/2.

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/2Quantum processor (qubit)
Spin-up / spin-down∣0⟩\ket{0} / ∣1⟩\ket{1}
Zeeman gap ΔE=ℏω0\Delta E = \hbar\omega_0Enerhiya ng transition ng qubit ℏω01\hbar\omega_{01}
Larmor frequency ω0\omega_0Frequency ng qubit ω01\omega_{01}
Resonant na RF pulse (flip angle θ\theta)Single-qubit rotation gate RX(θ)R_X(\theta)
90∘90^\circ / 180∘180^\circ na pulseRX(π/2)R_X(\pi/2) / RX(π)R_X(\pi)
Spin-lattice relaxation T1T_1Oras ng energy-relaxation ng qubit na T1T_1
Spin-spin relaxation T2T_2Oras ng dephasing ng qubit na T2T_2
NutationMga Rabi oscillation
Free induction decay (FID), Hahn echoMga 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:

  1. I-map ang problema sa isang quantum circuit.

  2. I-optimize ang circuit para sa execution (i-transpile sa backend).

  3. I-execute gamit ang isang IBM Quantum primitive.

  4. 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 θ\theta sa paligid ng xx-axis sa isang qubit na nagsisimula sa ∣0⟩|0\rangle, ang probability na mahanap ito sa ∣1⟩|1\rangle ay:

P1(θ)=sin⁡2 ⁣(θ2)=12(1−cos⁡θ).P_1(\theta) = \sin^2\!\left(\tfrac{\theta}{2}\right) = \tfrac{1}{2}\bigl(1 - \cos\theta\bigr).

Ito ang Rabi curve. Ang unang maximum nito ay ang π\pi na pulse (ganap na inversion, ang 180∘180^\circ na pulse); ang π/2\pi/2 na pulse ay isang kapat na ikot (ang 90∘90^\circ na pulse na nagtutumba ng spin papunta sa transverse plane). Sa NMR, ganito mo ka-calibrate ang iyong mga pulse.

Experimental caveat

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 θ\theta ng isang RX(θ)R_X(\theta) na gate. Pareho ang curve at ang pagkilala sa π\pi/π/2\pi/2; 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 RX(θ)R_X(\theta) para sa anumang θ\theta.

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 xx-axis, dinadala ito mula ∣0⟩|0\rangle pababa papunta sa ∣1⟩|1\rangle 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, RX(θ)R_X(\theta) 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")

Output of the previous code cell

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 θ\theta mula 00 hanggang 4π4\pi (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 P1P_1 sa bawat anggulo at ihambing sa sin⁡2(θ/2)\sin^2(\theta/2).

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

Output of the previous code cell

Suriin ang pag-unawa mo​

Sa curve na nasukat mo, unang naaabot ng P1P_1 ang maximum nito sa π\pi pulse (θ=π\theta = \pi). Ngayon, ipagpalagay na mali ang calibration ng isang device, kaya ang nominal na anggulong θ\theta sa x-axis ay talagang nagbubunga ng rotation na 1.05 θ1.05\,\theta.

(a) Sa anong nominal na anggulo lalabas ngayon ang unang maximum ng P1P_1? (b) Magiging sensitibong paraan ba ang paglapat ng isang π\pi pulse para matukoy ang 5% na error na ito?

Sagot

(a) Lumalabas ang maximum kung saan ang aktwal na rotation ay katumbas ng π\pi, ibig sabihin, sa nominal na anggulong θ=π/1.05≈0.95π\theta = \pi/1.05 \approx 0.95\pi — bahagyang paglipat ng peak pakaliwa.

(b) Hindi. Ang nominal na π\pi pulse ay nagbubunga ng aktwal na rotation na 1.05π1.05\pi, kaya P1=sin⁡2(1.05π/2)≈0.994P_1 = \sin^2(1.05\pi/2) \approx 0.994 sa halip na 11 — 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 360∘360^\circ 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: T1T_1 (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 T1T_1:

P1(τ)=e−τ/T1.P_1(\tau) = e^{-\tau/T_1}.

Para sa isang chemist, itinatakda ng T1T_1 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 ∣1⟩|1\rangle gamit ang XX gate (isang π\pi pulse), maghintay ng variable na delay na τ\tau, saka sukatin. Ang bahaging nasa ∣1⟩|1\rangle pa rin ang bumubuo ng decay.

Tanaw sa Bloch sphere​

Ibinabalik ng T1T_1 relaxation ang excited state sa equilibrium, kaya ang Bloch vector ay dumudulas mula ∣1⟩|1\rangle pabalik sa ∣0⟩|0\rangle sa kahabaan ng zz-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")

Output of the previous code cell

Measured T1 = 225.3 microseconds

Nag-iiba ang eksaktong T1T_1 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 5 T15\,T_1 sa pagitan ng mga scan. Gamit ang decay law, anong bahagi ng equilibrium magnetization ang bumalik na pagkatapos ng 5 T15\,T_1?

Sagot

Pagkatapos ng 5 T15\,T_1, ang natitirang paglihis mula sa equilibrium ay e−5≈0.0067e^{-5}\approx 0.0067, ibig sabihin, humigit-kumulang 99.3% na ang nakabalik.

Eksperimento: T2T_2, T2∗T_2^*​

Teorya​

Sinusukat ng T1T_1 ang pagkawala ng enerhiya. Sinusukat naman ng T2T_2 ang pagkawala ng phase coherence sa transverse plane. Maoobserbahan natin ito sa pamamagitan ng Ramsey experiment: ibinababa ng isang π/2\pi/2 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 T2∗T_2^*.

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 T2T_2. 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 T2T_2, nagbubunga ang mga ito ng mas maikling apparent decay time na T2∗T_2^* na nakikita sa Ramsey experiment.

Kaya paano natin makukuha ang tunay na T2T_2 kung T2∗T_2^* 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 T2T_2. Pareho ang simula nito sa Ramsey experiment, na may π/2\pi/2 pulse, tapos kumakalat ang mga spin gaya ng dati. Pagkalipas ng ilang oras na τ\tau, may ilalapat na π\pi 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, τ\tau.

Parehong mahalagang malaman ang T2∗T_2^* at T2T_2 sa chemistry at sa quantum computing. Sa chemistry, itinatakda ng T2∗T_2^* ang linewidth mo sa karaniwang NMR experiment (makikita mo kung ano ang ibig sabihin nito sa susunod na seksyon). Maraming masasabi ang T2T_2 tungkol sa mga molecule, tulad ng molecular tumbling, at ang pagbabago ng T2T_2 ay maaaring magsenyas na may kumapit na mas malaki sa molecule. Sa quantum computing, karaniwang gusto nating mahaba hangga't maaari ang parehong T2T_2 at T2∗T_2^*, 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 T2T_2, hindi ng T2∗T_2^*. 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 ZZ axis, ibig sabihin, kung ∣0⟩\vert 0 \rangle o ∣1⟩\vert 1 \rangle ito. Kaya, para sa parehong eksperimento, tinatapos natin ito sa dagdag na π/2\pi/2 pulse na sinusundan ng measurement. Isinasalin ng π/2\pi/2 pulse na ito ang impormasyon ng phase ng qubit tungo sa populasyon.

Sa ibaba, pinapatakbo natin ang bawat eksperimento para matukoy ang T2∗T_2^* at T2T_2.

Ramsey (T2∗T_2^{*}): Dalawang π/2\pi/2 pulse na may delay time na τ\tau​

Ibinabagsak ng unang π/2\pi/2 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 τ\tau. 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 T2∗T_2^*.

Tanaw sa Bloch sphere​

Ibinabagsak ng π/2\pi/2 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 T2∗T_2^*.

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

Output of the previous code cell

Hahn echo (T2T_2): Magdagdag ng refocusing na π\pi pulse sa gitna​

Tanaw sa Bloch sphere​

Ang Hahn echo: kumakalat ang mga spin gaya ng dati, tapos binabaligtad sila ng isang π\pi 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

Output of the previous code cell

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

Output of the previous code cell

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 T2∗T_2^* at T2T_2, ayon sa pagkakasunod.

Suriin ang pag-unawa mo​

Karaniwan dapat mong makita na T2≳T2∗T_2 \gtrsim T_2^{*}. Ipaliwanag kung bakit sa isang pangungusap, at sabihin kung anong pisikal na epekto ang inaalis ng π\pi pulse ng Hahn echo, pati kung ano ang hindi nito kayang alisin.

Sagot

Kasama sa T2∗T_2^{*} ang parehong irreversible na dephasing at reversible na static na pagkalat, kaya mas mabilis itong nabubulok; nire-refocus ng π\pi 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 T2T_2. 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 JJ-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 νi\nu_i, 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 CH3_3 na proton laban sa isang aromatic).

  • Scalar JJ-coupling. Isang through-bond na interaksyon sa pagitan ng dalawang spin na naghahati sa bawat peak tungo sa multiplet. Ang nucleus na may nn equivalent na kapitbahay ay nahahati sa n+1n+1 na linya na may binomial na intensity, ang n+1n+1 rule. Ang pattern ng paghahati ay nagpapakita ng connectivity (aling mga nucleus ang magkabigkis), at ang pagitan ay ang coupling constant na JJ.

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 ≫\gg mga coupling), nagka-cancel sa average ang mga bahaging XXXX at YYYY ng coupling, at ZZZZ na lang ang natitira. Kaya ang Hamiltonian ay (sa mga unit ng angular frequency, ℏ=1\hbar=1):

H=∑iπ νi Zi⏟chemical shift  +  ∑i<jπ2 Jij ZiZj⏟J-coupling.H = \underbrace{\sum_i \pi\,\nu_i\, Z_i}_{\text{chemical shift}} \;+\; \underbrace{\sum_{i<j} \tfrac{\pi}{2}\,J_{ij}\, Z_iZ_j}_{J\text{-coupling}}.

Ang bawat nucleus ay isang qubit: ang chemical shift ay isang single-qubit na ZZ rotation, at ang coupling ay isang two-qubit na ZZZZ na interaksyon.

Ganito ang takbo ng eksperimento. Ibinabagsak ng π/2\pi/2 pulse ang bawat spin sa transverse plane, at ang mga spin ay nagpe-precess at nagko-couple sa loob ng oras na tt. Itinatala natin ang complex transverse magnetization na s(t)=⟨X⟩+i⟨Y⟩s(t) = \langle X\rangle + i\langle Y\rangle 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 tt. Kapag kinuha natin ang Fourier transform ng signal, nakakakuha tayo ng spectrum na may mga peak sa chemical shift na νi\nu_i na hinati ng scalar coupling na JijJ_{ij}.

tala

Sini-simulate natin ang ebolusyon ng molecule sa pamamagitan ng pag-map ng oras na tt sa mga rotation angle: ang mas malaking tt ay nangangahulugan ng mas malalaking ZZ at ZZZZ rotation, hindi ng mas mahaba o mas malalim na circuit. Kaya habang sumusulong nga ang simulated na state kasabay ng tt (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 tt. 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 T2∗T_2^*. Idinaragdag natin ito pabalik sa pamamagitan ng pagpaparami sa FID ng window na e−t/T2∗e^{-t/T_2^{*}} 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 νi\nu_i at mga coupling na JijJ_{ij}, ay nagbabalik ng parameterized na state-preparation circuit. Ibinabagsak ng π/2\pi/2 pulse ang mga spin sa equator, tapos sini-simulate ng mga ZZ rotation ang ebolusyon ng state sa ilalim ng mga chemical-shift at JJ-coupling na termino. Ang bawat νi\nu_i 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 RZR_Z gate, isa kada spin, at itinatakda ng bawat νi\nu_i kung saan nakaupo ang peak ng spin na iyon sa spectrum. Inilalapat ng two-qubit na ZZZZ gate ang coupling na JijJ_{ij}, 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 ⟨X⟩\langle X\rangle at ⟨Y⟩\langle Y\rangle sa bawat isa. Pinagsasama natin ang mga ito sa complex FID na ⟨X⟩+i⟨Y⟩\langle X\rangle + i\langle Y\rangle, 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)}),
)

Output of the previous code cell

Expected AX lines (Hz): [-7.0, -5.0, 5.0, 7.0]

Extension: Isang AX2_2 system at ang n+1n+1 rule​

Ngayon, magdagdag ng pangalawang equivalent na kapitbahay. Sa isang AX2_2 system, isang A na spin ang nagko-couple, sa parehong JJ, sa dalawang equivalent na X na spin. (Tandaan, label lang ang X para sa dalawang equivalent na spin; walang kinalaman ito sa mga Pauli XX operator. Ang bawat coupling sa ibaba ay ZZZZ pa rin.) Nakikita ng spin A ang apat na configuration ng kapitbahay (↑↑, ↑↓, ↓↑, ↓↓)(\uparrow\uparrow,\ \uparrow\downarrow,\ \downarrow\uparrow,\ \downarrow\downarrow); nagtutugma ang dalawang halo, kaya nahahati ang A sa isang 1:2:1 triplet (n=2⇒n+1=3n=2 \Rightarrow n+1 = 3 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 (Cl2_2CH–CH2_2Cl). 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 CH2_2 proton ang dalawang X na spin. Ngayon, bilangin lang ang mga kapitbahay: ang CH proton ay may dalawang kapitbahay (ang CH2_2 pair), kaya nahahati ang signal nito sa 1:2:1 triplet (n=2n=2); ang bawat CH2_2 proton ay may isang kapitbahay lang (ang CH), kaya ang CH2_2 signal ay isang 1:1 doublet (n=1n=1). 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.

1,1,2-trichloroethane: the CH proton is A, the two equivalent CH_2 protons are X

Sa ibaba, sini-simulate natin ang isang AX2_2 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 JJ? 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 (ν1−ν2\nu_1-\nu_2); ang 2 Hz na pagitan ng linya ay ang coupling constant na JJ. Nagmumula ang mga chemical shift sa shielding ng B0B_0, kaya sumasabay sila sa field. Sa doble ng field, dumodoble ang paghihiwalay sa 24 Hz. Ang coupling na JJ 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 n+1n+1 rule, hulaan ang A multiplet kung magdadagdag ng pangatlong equivalent na X spin (isang AX3_3 system), at ipaliwanag kung bakit hindi naghahati sa isa't isa ang dalawang equivalent na X spin sa AX2_2.

Sagot

Sa n=3n=3 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, T1T_1, T2T_2, at T2∗T_2^*, 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 ZZ rotation; ang tawag ng chemist na JJ-coupling ay tinatawag ng quantum engineer na ZZZZ 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 ∣0⟩/∣1⟩|0\rangle/|1\rangle, frequency, mga gate, T1T_1, at T2T_2 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 P1=sin⁡2(θ/2)P_1=\sin^2(\theta/2) ang nagtutukoy sa mga π\pi at π/2\pi/2 na rotation.

  • Ang T1T_1 ay energy (spin-lattice) relaxation; ang T2T_2 ay phase (spin-spin) relaxation; ang T2∗T_2^{*} 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 JJ-coupling ang mga peak tungo sa mga multiplet ayon sa n+1n+1 rule, na magkasamang nag-eencode ng chemical environment at connectivity.

Totoo / Mali​

  1. T/F Ang Larmor frequency ay ang energy gap sa pagitan ng dalawang spin state na hinati sa ℏ\hbar.

  2. T/F Ang 90∘90^\circ (π/2\pi/2) na pulse ay lubusang bumabaligtad sa isang spin na nasa equilibrium.

  3. T/F Ang T2∗T_2^{*} ay karaniwang mas mahaba kaysa sa T2T_2.

  4. T/F Nire-refocus ng Hahn echo ang irreversible na spin-spin dephasing.

  5. T/F Sa isang AX2_2 system, lumilitaw ang A nucleus bilang 1:2:1 triplet.

  6. T/F Dumodoble ang coupling constant na JJ kapag dinoble mo ang magnetic field ng spectrometer.

  7. T/F Ang pag-alis ng Qiskit Pulse ay nagiging imposible ang pagsukat ng T1T_1 sa kasalukuyang hardware.

Maikling sagot​

  1. Ipaliwanag sa dalawang pangungusap kung bakit mahinang paraan ang isang π\pi pulse para matukoy ang 5%5\% na flip-angle error, at kung paano ito naaayos ng pagkakadena ng mga pulse.

  2. Ang isang sample ay nagpapakita ng malalapad na NMR line. Sa usapin ng T2T_2, ano ang ipinapahiwatig nito, at ano ang katumbas na dami sa qubit?

  3. Ibigay ang katumbas sa qubit ng bawat isa: (a) ang recycle delay, (b) ang 90∘90^\circ na pulse, (c) ang chemical shift.

  4. Gamit ang n+1n+1 rule, ipaliwanag kung bakit ang isang ethyl group (CH3_3CH2_2–) 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​

  1. Carr-Purcell train. Baguhin ang Hahn echo para maglagay ng nn na pantay ang pagitan na π\pi pulse (isang CPMG-style na train) at sukatin ang T2T_2 bilang function ng nn. Talakayin kung bakit maaaring pahabain ng mas maraming refocusing pulse ang apparent na T2T_2.

  2. Pagpapalaki ng error ng pulse. Bumuo ng circuit na naglalapat ng RX(π)R_X(\pi) nang  n\,n beses sa ∣0⟩|0\rangle at i-plot ang P1P_1 laban sa nn para sa sadyang maling anggulong RX(1.05π)R_X(1.05\pi). Ipakita kung paano nagiging nakikita ang error habang lumalaki ang nn. 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.

  3. Ethyl group. Gamit ang fid_circuit, buuin ang proton spectrum ng isang ethyl fragment (CH3_3–CH2_2): limang qubit, kung saan ang tatlong CH3_3 proton ay may iisang chemical shift at ang dalawang CH2_2 proton ay may isa pa, at ang bawat CH3_3–CH2_2 pair ay magkakabit sa parehong JJ (walang coupling sa loob ng equivalent na grupo). Hulaan ang pattern gamit ang n+1n+1 rule, saka i-simulate; dapat makuha mo ang 1:3:3:1 quartet (CH2_2) at 1:2:1 triplet (CH3_3).

Appendix (opsyonal): Trotterized na ebolusyon — hayaang decoherence ang magtakda ng linewidth​

Sa seksyong NMR spectroscopy ng isang molecule, inilalapat ang ebolusyong e−iHte^{-iHt} sa iisang layer na ang lalim ay hindi lumalaki kasabay ng tt, kaya hindi nabubulok nang kusa ang FID at ipinapataw natin ang linewidth gamit ang e−t/T2e^{-t/T_2} na apodization window. Kabaligtaran ang diskarte ng opsyonal na cell na ito. Hinahati nito ang ebolusyon sa pp 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 kk ay gumagamit ng kk na step, kaya lumalaki ang lalim ng circuit kasabay ng oras.

Dahil nagko-commute ang bawat termino sa HH, 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 T2↔T_2\leftrightarrowlinewidth sa seksyong T2T_2, T2∗T_2^* experiment, na ngayon ay nagmumula sa tunay na decoherence sa halip na processing window. Pinapatakbo natin ang parehong AX system (dalawang doublet) at AX2_2 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 ∼ ⁣47\sim\!47 two-qubit gate at halos doble niyon ang AX2_2 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()