Lección 41 · 15 min · Gratis

Mecanismo de pares de radicales en la magnetorrecepción aviar

Copyright 2026 Google LLC.
#@title Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

steps-re GitHub avatar

Este notebook fue contribuido por steps-re.

Descripción general

Las aves migratorias cruzan océanos y continentes y llegan a metros de donde comenzaron un año antes. La principal explicación de cómo leen el campo magnético de la Tierra no es un órgano ni un mineral. Es un efecto cuántico dentro de una proteína en el ojo: el mecanismo de pares de radicales.

En este notebook, Gemini actúa como socio de investigación. Gemini diseña el circuito cuántico, tú lo ejecutas en un simulador y en el hardware superconductor real de IBM, Gemini interpreta los resultados y luego Gemini responde la pregunta que la mayoría de las demostraciones evitan: ¿este problema realmente necesita una computadora cuántica?

La respuesta honesta aquí resulta ser no, y entender por qué es la parte más útil del notebook. Recorre instrucciones del sistema de múltiples turnos, razonamiento técnico estructurado y un modelo de pensamiento al que se le pide que emita un juicio genuinamente difícil contra un artefacto científico concreto.

El mecanismo de pares de radicales

La luz incide en una proteína criptocromo en la retina del ave y expulsa un electrón de una molécula a otra. Eso deja dos espines de electrones desapareados, uno en cada molécula: un par de radicales. El par nace en un estado cuántico singlete, donde los dos espines están perfectamente anticorrelacionados.

Si se deja solo, el par no permanece como un singlete. Los dos espines oscilan coherentemente entre el estado singlete y los tres estados triplete. Dos cosas impulsan esa oscilación:

  • la interacción de Zeeman con el campo magnético de la Tierra, y
  • la interacción hiperfina con los núcleos atómicos cercanos dentro de la molécula.

La química que sigue depende de si el par es un singlete o un triplete en el momento en que reacciona, por lo que el equilibrio singlete-triplete establece la cantidad de producto que produce la reacción. Debido a que el acoplamiento hiperfino es anisotrópico (depende de la orientación molecular), ese equilibrio depende de la dirección del campo externo. La proteína se convierte en una brújula química. La anisotropía es todo el truco. Elimínala y la sensibilidad direccional desaparece.

En español simple. Imagina los dos electrones como un par de pequeños trompos que comienzan perfectamente sincronizados. A medida que giran, se desincronizan y se vuelven a sincronizar, y la velocidad con la que se desincronizan depende de la dirección en la que el ave mira en el campo de la Tierra. El cuerpo del ave convierte esa diferencia de tiempo en un sentido de dirección. Esa es toda la brújula.

El modelo

Modelas la versión más pequeña y honesta de este sistema: tres partículas de espín-1/2. Los cúbits 0 y 1 son los dos electrones, preparados en un singlete. El cúbit 2 es un núcleo acoplado hiperfinamente. El libro de reglas de energía (el Hamiltoniano) es

$$ H ;=; \underbrace{X_0X_2 + Y_0Y_2 + 3,Z_0Z_2}{\textstyle \text{hiperfino: el electrón 0 siente el núcleo}} ;+; \underbrace{B_x,(X_0{+}X_1) + B_z,(Z_0{+}Z_1)}{\textstyle \text{Zeeman: ambos electrones sienten el campo de la Tierra}} $$

símbolo qué es
q0, q1 los dos espines de electrones, preparados como un singlete
q2 un núcleo atómico cercano
Bx, Bz las partes lateral y vertical del campo magnético
el 3 en Z0Z2 hace que el acoplamiento sea anisotrópico, lo que crea la detección de dirección

El observable es la probabilidad de supervivencia del singlete después de un tiempo fijo, barrida sobre la dirección del campo magnético.

En español simple. La fórmula anterior es solo un libro de reglas sobre cómo los tres espines se empujan y tiran entre sí. El primer grupo es un electrón que siente su núcleo vecino. El segundo es ambos electrones que sienten el campo de la Tierra. Gira el campo de otra manera y cambias el empuje y el tirón, lo que cambia el número que mides al final.

El plan:

  1. Gemini diseña el circuito a partir del Hamiltoniano y el observable.
  2. Tú lo construyes y ejecutas en un simulador, y lo comparas con la teoría exacta y con una ejecución real en hardware de IBM del mismo circuito.
  3. Das un paso adelante hacia un modelo de flavina más realista en hardware.
  4. Gemini interpreta los datos.
  5. Gemini evalúa si el hardware cuántico es realmente necesario aquí, con honestidad.

Configuración

Instala los SDK

%pip install -U -q "google-genai>=2.9.0" "qiskit>=1.0" "qiskit-aer>=0.14" "qiskit-ibm-runtime>=0.20" matplotlib scipy
# google-genai>=2.9.0 for the Interactions API; qiskit for building and simulating
# the circuits. The optional live-hardware run also uses qiskit-ibm-runtime.
Note: you may need to restart the kernel to use updated packages.

Configura tu clave de API

Para ejecutar la siguiente celda, tu clave de API debe estar almacenada en un Secreto de Colab llamado GEMINI_API_KEY. Si aún no tienes una clave de API, o no estás seguro de cómo crear un Secreto de Colab, consulta el inicio rápido de Autenticación para obtener un tutorial.

from google.colab import userdata
from google import genai
from google.genai import types

GEMINI_API_KEY = userdata.get("GEMINI_API_KEY")
client = genai.Client(api_key=GEMINI_API_KEY)

Selecciona los dos modelos que usa este notebook: un modelo rápido para el diseño de circuitos e interpretación, y un modelo de pensamiento más potente para la pregunta más difícil de "¿realmente necesitas una computadora cuántica?" al final.

FAST_MODEL = "gemini-3.7-flash" # @param ["gemini-3.1-pro-preview", "gemini-3.7-flash", "gemini-3.5-flash-lite", "gemini-2.5-pro"] {"allow-input":true, isTemplate: true}DEEP_MODEL = "gemini-3.1-pro-preview" # @param ["gemini-3.1-pro-preview", "gemini-2.5-pro"] {"allow-input":true, isTemplate: true}

Ayudantes y datos

Un pequeño ayudante envía un solo prompt con una instrucción del sistema a través de la API de Interacciones y devuelve el texto de la respuesta. Los tres archivos de resultados de hardware y benchmark están pregrabados para que todo el notebook se ejecute desde una laptop, sin necesidad de una cuenta de IBM Quantum o cola. Tienen licencia Apache 2.0 con este notebook y se descargan del repositorio del cookbook.

# @title Setup: imports, the `ask_gemini` helper, and the pre-recorded data
import json
import urllib.request
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
from IPython.display import Markdown, display


def ask_gemini(prompt, system, model=FAST_MODEL):
    """Send one prompt with a system instruction and return the reply text."""
    interaction = client.interactions.create(
        model=model,
        input=prompt,
        system_instruction=system,
    )
    return interaction.steps[-1].content[0].text


# The pre-recorded IBM hardware and classical-benchmark results (a few KB of JSON each),
# openly licensed under Apache 2.0 with this notebook.
DATA = Path("data")
DATA.mkdir(exist_ok=True)
# Served from this notebook's own data/ folder in the cookbook repo. If the maintainers
# prefer, these three files can instead live at gs://generativeai-downloads/data/.
DATA_URL = "https://github.com/google-gemini/cookbook/raw/main/examples/data"
for _f in ("hardware_sweep.json", "compass_ladder_result_v2.json", "frontier_benchmark.json"):
    if not (DATA / _f).exists():
        urllib.request.urlretrieve(f"{DATA_URL}/{_f}", DATA / _f)

Paso 1: Gemini diseña el circuito

Entrega a Gemini el Hamiltoniano y el observable y pídele una receta concreta a nivel de puertas: cómo preparar el singlete, cómo Trotterizar la evolución temporal y cómo medir la supervivencia del singlete en la base computacional.

DESIGN_SYSTEM = (
    "You are a quantum-computing co-scientist helping design a hardware experiment. "
    "Be concrete and correct about gate sequences. If a step is an approximation, say so. "
    "Keep the whole answer under about 500 words so no part is left unfinished. "
    "Format as Markdown that nests inside a notebook section: use bold labels or at most "
    "level-3 (###) headings, never level-1 (#) or level-2 (##), and no em-dashes. Write "
    "math as LaTeX ($...$ inline, $$...$$ display), but inside Markdown table cells use "
    "plain text or backticks, never LaTeX. If you use a table, keep every cell to a few "
    "words and put any longer explanation in prose beneath it, never full sentences inside "
    "cells. Keep literal gate sequences in code blocks."
)
DESIGN_PROMPT = """
    This experiment models the radical-pair mechanism of avian magnetoreception as three
    spin-1/2 particles. Qubits 0 and 1 are an electron pair born in a singlet; qubit 2 is
    one hyperfine-coupled nucleus. The Hamiltonian is
    H = X0X2 + Y0Y2 + 3*Z0Z2 + Bx*(X0+X1) + Bz*(Z0+Z1).
    The target observable is the survival probability of the electronic singlet after time
    t, as a function of the external field direction. Walk through building a Trotterized
    circuit:
    (1) how to prepare the two-electron singlet on qubits 0,1 from |00>;
    (2) how to decompose ONE Trotter step of exp(-i*H*dt) into standard gates
        (rzz/rxx/ryy or CX plus single-qubit rotations);
    (3) how to measure singlet-survival probability in the computational basis by applying
        the inverse singlet-prep before measurement so the |00> outcome projects onto the
        singlet.
    Give the concrete gate sequence for each part.
"""

design = ask_gemini(DESIGN_PROMPT, DESIGN_SYSTEM)
display(Markdown(design))
<IPython.core.display.Markdown object>

En español simple. Le describiste la física a Gemini y le permitiste escribir la receta puerta por puerta, de la misma manera que le pedirías a un asistente de cátedra inteligente que convirtiera una ecuación de un libro de texto en instrucciones de laboratorio paso a paso.

Paso 2: Construye el circuito

Aquí está el circuito que sigue la receta de Gemini. El singlete que preparas es

$$|S\rangle ;=; \tfrac{1}{\sqrt{2}}\big(|01\rangle - |10\rangle\big),$$

el estado "perfectamente sincronizado" de los dos electrones. Cada paso de Trotter aplica los términos hiperfinos de dos cúbits y los términos de campo de un solo cúbit. Las puertas de rotación de Qiskit usan la convención $R_{PP}(\theta) = e^{-i,(\theta/2),P\otimes P}$, así que para aplicar una porción de tiempo $e^{-i,c,P\otimes P,\delta t}$ estableces

$$\theta ;=; 2,c,\delta t.$$

Ese factor de dos es la única pieza de contabilidad que confunde a la gente. La preparación inversa antes de la medición mapea el singlete de vuelta a $|00\rangle$, por lo que la probabilidad de leer 00 en los cúbits 0 y 1 es la probabilidad de supervivencia del singlete.

from qiskit import ClassicalRegister, QuantumCircuit
from qiskit.circuit import QuantumRegister
from qiskit.quantum_info import SparsePauliOp
from qiskit_aer import AerSimulator
from scipy.linalg import expm


def trotter_step(qreg, Bx, Bz, dt):
    """One first-order Trotter step of exp(-i*H*dt). R_P(theta) uses theta = 2*coeff*dt."""
    qc = QuantumCircuit(qreg)
    qc.rxx(2.0 * 1.0 * dt, qreg[0], qreg[2])
    qc.ryy(2.0 * 1.0 * dt, qreg[0], qreg[2])
    qc.rzz(2.0 * 3.0 * dt, qreg[0], qreg[2])
    qc.rx(2.0 * Bx * dt, qreg[0])
    qc.rx(2.0 * Bx * dt, qreg[1])
    qc.rz(2.0 * Bz * dt, qreg[0])
    qc.rz(2.0 * Bz * dt, qreg[1])
    return qc


def build_circuit(total_time, steps, Bx, Bz, measure=True):
    qreg = QuantumRegister(3, "q")
    qc = QuantumCircuit(qreg)
    # Singlet prep on q0, q1: |00> -> (|01> - |10>)/sqrt(2).
    qc.x(qreg[0])
    qc.x(qreg[1])
    qc.h(qreg[0])
    qc.cx(qreg[0], qreg[1])
    qc.barrier()
    dt = total_time / steps
    step = trotter_step(qreg, Bx, Bz, dt)
    for _ in range(steps):
        qc.compose(step, inplace=True)
    qc.barrier()
    # Inverse prep: maps the singlet back to |00> so '00' measures the singlet operator.
    qc.cx(qreg[0], qreg[1])
    qc.h(qreg[0])
    qc.x(qreg[0])
    qc.x(qreg[1])
    if measure:
        creg = ClassicalRegister(2, "c")
        qc.add_register(creg)
        qc.measure(qreg[0], creg[0])
        qc.measure(qreg[1], creg[1])
    return qc

Dibuja el circuito para una configuración de campo con solo 3 pasos de Trotter para que siga siendo legible (las ejecuciones reales usan 50).

demo = build_circuit(total_time=1.0, steps=3, Bx=0.7, Bz=0.7)
display(demo.draw("mpl", fold=-1))
<Figure size 2712.22x367.889 with 1 Axes>

En español simple. Divides la evolución suave y continua en 50 finas porciones de tiempo y aplicas unas pocas puertas simples para cada porción, de la misma manera que muchos fotogramas fijos se suman a un movimiento suave.

Paso 3: Barre el ángulo del campo

Mantén la magnitud del campo fija y rota su dirección, $\theta$ de 0 a $\pi$. En cada ángulo, ejecuta el circuito y lee la probabilidad de supervivencia del singlete. Superpón tres cosas en un solo gráfico para el mismo modelo de un solo núcleo:

  • el resultado exacto de la exponenciación directa de $H$,
  • el simulador (solo ruido de disparo), y
  • una ejecución real en hardware de IBM de estos circuitos exactos (trabajo d94n6clgc6cc73ffas6g, ibm_kingston, 1024 disparos por ángulo), pregrabada en data/hardware_sweep.json.

El observable es $P(\texttt{00})$ en los cúbits 0 y 1 con el cúbit 2 libre, por lo que el proyector exacto suma sobre ambos estados nucleares:

$$P_S(t) ;=; \big|\langle S,|,\psi(t)\rangle\big|^2, \qquad B_x = B\sin\theta,;; B_z = B\cos\theta.$$

def exact_singlet_survival(total_time, Bx, Bz):
    """Exact P(singlet on q0,q1) after continuous evolution, nucleus (q2) traced free."""
    H = SparsePauliOp.from_list(
        [
            ("XIX", 1.0),
            ("YIY", 1.0),
            ("ZIZ", 3.0),  # little-endian: leftmost = q0
            ("IIX", Bx),
            ("IXI", Bx),
            ("IIZ", Bz),
            ("IZI", Bz),
        ]
    )
    U = expm(-1j * total_time * H.to_matrix())

    def idx(q0, q1, q2):
        return q2 * 4 + q1 * 2 + q0

    psi0 = np.zeros(8, dtype=complex)
    psi0[idx(0, 1, 0)] = 1 / np.sqrt(2)
    psi0[idx(1, 0, 0)] = -1 / np.sqrt(2)
    psit = U @ psi0
    ps = 0.0
    for q2 in (0, 1):
        s = np.zeros(8, dtype=complex)
        s[idx(0, 1, q2)] = 1 / np.sqrt(2)
        s[idx(1, 0, q2)] = -1 / np.sqrt(2)
        ps += abs(np.vdot(s, psit)) ** 2
    return ps

Ejecuta el barrido en el simulador y contra la teoría exacta, luego carga la ejecución de hardware pregrabada de los mismos circuitos.

B_TOT, TOTAL_TIME, STEPS, SHOTS = 1.0, 1.0, 50, 4096
thetas = np.linspace(0.0, np.pi, 10)
sim = AerSimulator()

ps_sim, ps_exact = [], []
for theta in thetas:
    Bx, Bz = B_TOT * np.sin(theta), B_TOT * np.cos(theta)
    qc = build_circuit(TOTAL_TIME, STEPS, Bx, Bz)
    counts = sim.run(qc, shots=SHOTS, seed_simulator=42).result().get_counts()
    ps_sim.append(counts.get("00", 0) / SHOTS)
    ps_exact.append(exact_singlet_survival(TOTAL_TIME, Bx, Bz))

ps_sim, ps_exact = np.array(ps_sim), np.array(ps_exact)

# Pre-recorded real-hardware run of the SAME circuits (same thetas, |B|, time, steps).
hw = json.loads((DATA / "hardware_sweep.json").read_text())
ps_hw = np.array(hw["ps_hw"])

mae_sim = np.mean(np.abs(ps_sim - ps_exact))
mae_hw = np.mean(np.abs(ps_hw - ps_exact))
max_hw = np.max(np.abs(ps_hw - ps_exact))
display(
    Markdown(
        f"**Simulator vs exact theory:** mean absolute error {mae_sim:.4f}  \n"
        f"**Hardware vs exact theory:** mean absolute error {mae_hw:.4f} (worst angle {max_hw:.4f})"
    )
)
<IPython.core.display.Markdown object>
plt.figure(figsize=(7, 4.5))
plt.plot(np.degrees(thetas), ps_exact, "-", color="#444", label="exact theory")
plt.plot(np.degrees(thetas), ps_sim, "o", color="#c1440e", label=f"simulator ({SHOTS} shots)")
plt.plot(
    np.degrees(thetas),
    ps_hw,
    "s",
    color="#2b6cb0",
    markersize=8,
    label="ibm_kingston hardware (1024 shots)",
)
plt.xlabel(r"magnetic-field angle $\theta$ (degrees)")
plt.ylabel("singlet survival probability")
plt.title("The compass response curve: theory, simulator, real hardware")
plt.legend()
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()
<Figure size 700x450 with 1 Axes>

Los tres concuerdan. El simulador sigue la teoría exacta dentro del ruido de disparo, y la ejecución real ibm_kingston sigue la misma curva con un error absoluto medio de aproximadamente 0.015 (el peor ángulo es de aproximadamente 0.03). La supervivencia del singlete cambia aproximadamente en un factor de tres en los ángulos del campo: esa oscilación es la señal de la brújula que leería el receptor de un ave.

En español simple. Rotar el campo y observar cuánto del estado original "sincronizado" sobrevive traza la curva de respuesta de la brújula, y la teoría, el simulador y el hardware real están todos de acuerdo.

Paso 4: Un modelo de flavina más realista en hardware

El barrido anterior es el juguete honesto de tres cúbits: un núcleo, tratado como espín-1/2. A continuación se muestra un experimento separado y más exigente en el mismo procesador ibm_kingston. No es el mismo circuito que el Paso 3. Modela el radical de flavina con su tensor hiperfino real de nitrógeno (N5) de espín-1, se ejecuta con 8192 disparos con mitigación de errores (desacoplamiento dinámico más giro de puertas y mediciones), y mide el contraste direccional del rendimiento del singlete, la diferencia entre el campo a lo largo y a través de la molécula.

Se ejecuta dos veces: una con la intensidad de campo actual y otra con el campo mucho más débil de la excursión geomagnética de Laschamp. Una brújula que funcione debería mostrar contraste hoy y perderlo en el campo débil. El resultado a continuación está pregrabado en data/compass_ladder_result_v2.json (trabajo d94t21cql68s73c9uod0).

Barrido del Paso 3 Escalera de flavina del Paso 4
núcleo uno, espín-1/2 (juguete) nitrógeno real de espín-1
variado ángulo del campo intensidad del campo
disparos 1024 8192
mitigación de errores ninguna desacoplamiento dinámico + giro
lo que muestra la curva de respuesta de la brújula la brújula encendiéndose y apagándose
ladder = json.loads((DATA / "compass_ladder_result_v2.json").read_text())

# JSON keys are field strengths as strings ("45.3", "20.0", ...); sort high to low.
keys = sorted(ladder["ladder"], key=float, reverse=True)
fields = [float(k) for k in keys]
aniso = [ladder["ladder"][k]["anisotropy"] for k in keys]

plt.figure(figsize=(7, 4.5))
bars = plt.bar([str(f) for f in fields], aniso, color="#2b6cb0")
bars[0].set_color("#c1440e")  # present-day Earth field
plt.axhline(0.015, ls="--", color="gray", lw=1, label="shot-noise floor")
plt.xlabel("field strength (microtesla)")
plt.ylabel("directional contrast of singlet yield")
plt.title("The compass on ibm_kingston (spin-1 flavin, error-mitigated)")
plt.legend()
plt.tight_layout()
plt.show()

display(
    Markdown(
        f"**Present-day field ({fields[0]} uT):** contrast = {ladder['present']:.4f} (compass ON)  \n"
        f"**Laschamp weak field:** contrast = {ladder['laschamp']:.4f} (compass OFF)  \n"
        f"**Contrast drop (present - weak):** {ladder['present'] - ladder['laschamp']:.4f}  \n"
        f"**Contrast ratio (present / weak):** {ladder['present'] / ladder['laschamp']:.1f}x"
    )
)
<Figure size 700x450 with 1 Axes>
<IPython.core.display.Markdown object>

En hardware real, la señal direccional está claramente presente con la intensidad del campo de la Tierra y colapsa en el nivel de ruido con el campo débil de Laschamp. La brújula se enciende y apaga aproximadamente donde la física dice que debería.

En español simple. Un sustituto más realista de la molécula pasa la prueba real de la brújula, funcionando con el campo actual y apagándose cuando el campo se vuelve demasiado débil.

Opcional: ejecuta el barrido en hardware en vivo

Para reproducir una ejecución de hardware tú mismo, configura una cuenta de IBM Quantum una vez y activa la bandera a continuación. Está desactivada por defecto para que este notebook se ejecute en cualquier lugar sin entrar en una cola.

RUN_ON_HARDWARE = False  # set True with a saved IBM Quantum account to submit the sweep live

if RUN_ON_HARDWARE:
    from qiskit.transpiler.preset_passmanagers import generate_preset_pass_manager
    from qiskit_ibm_runtime import QiskitRuntimeService, SamplerV2

    # One-time account setup (run once, then it is cached in ~/.qiskit):
    #   QiskitRuntimeService.save_account(channel="ibm_quantum_platform", token="YOUR_IBM_TOKEN")
    service = QiskitRuntimeService()
    backend = service.least_busy(operational=True, simulator=False, min_num_qubits=3)
    print("backend:", backend.name)

    circuits = [
        build_circuit(TOTAL_TIME, STEPS, B_TOT * np.sin(t), B_TOT * np.cos(t))
        for t in thetas
    ]
    pm = generate_preset_pass_manager(optimization_level=3, backend=backend)
    job = SamplerV2(mode=backend).run(pm.run(circuits), shots=SHOTS)
    print("job id:", job.job_id())

Paso 5: Gemini interpreta los resultados

Dale a Gemini el barrido del simulador junto a la curva exacta, más el error del hardware real, y pídele que separe la señal física del ruido y que diga qué significa la forma para la brújula.

table = "theta_deg, P_singlet_sim, P_singlet_exact\n" + "\n".join(
    f"{d:.0f}, {s:.3f}, {e:.3f}"
    for d, s, e in zip(np.degrees(thetas), ps_sim, ps_exact, strict=False)
)
INTERP_SYSTEM = (
    "You are interpreting quantum-simulation output for a reader who codes but is not a "
    "physicist. Separate physical signal from noise. Be specific, not reassuring. "
    "Do not invent citations or attribute specific behavioral results to specific animal "
    "species; discuss the mechanism generally. Keep the answer under about 600 words. "
    "Format as Markdown that nests inside a notebook section: use bold labels or at most "
    "level-3 (###) headings, never level-1 (#) or level-2 (##), and no em-dashes. Write "
    "any math as LaTeX ($...$ inline, $$...$$ display), but inside Markdown table cells "
    "use plain text or backticks, never LaTeX. If you use a table, keep every cell to a "
    "few words and put any longer explanation in prose beneath it, never full sentences "
    "inside cells."
)
INTERP_PROMPT = f"""
    Here is a sweep of singlet-survival probability P_S versus magnetic-field angle theta
    (0 to 180 degrees), from a Trotterized quantum circuit ({SHOTS} shots per point),
    alongside the exact theoretical curve:
    {table}
    The circuit uses {STEPS} Trotter steps, so the Trotter discretization error is on the
    order of 1e-4 and negligible here; residuals at this shot count are dominated by shot
    noise.
    (1) What does the shape of P_S(theta) reveal about the chemical compass, and where is
        it most directionally sensitive?
    (2) Which features are physical signal versus shot noise?
    (3) The simulator tracks theory to a mean absolute error of about {mae_sim:.3f}. On real
        IBM hardware the same circuits matched theory to a mean absolute error of about
        {mae_hw:.3f} (worst angle about {max_hw:.3f}). What does that gap reveal about
        today's quantum hardware?
"""

display(Markdown(ask_gemini(INTERP_PROMPT, INTERP_SYSTEM)))
<IPython.core.display.Markdown object>

En español simple. Le devuelves los números a Gemini como un compañero de laboratorio escéptico para que separe la señal real del ruido de medición.

Paso 6: ¿Realmente necesitas una computadora cuántica?

Las demostraciones de biología cuántica suelen detenerse aquí, en "mira, se ejecutó en una QPU". La pregunta más útil es si una computadora cuántica es la herramienta adecuada para este observable. La respuesta resulta ser no, y comprender por qué es más valioso que la demostración.

El problema con la simulación clásica es el baño de espines nucleares. Un criptocromo real tiene del orden de 20 núcleos acoplados. La simulación exacta por fuerza bruta almacena el vector de estado completo, cuyo tamaño se duplica con cada núcleo, por lo que se queda sin memoria de la laptop alrededor de 10 a 11 núcleos. Eso parece una pared que una computadora cuántica debería romper.

Pero el observable que importa, el rendimiento del singlete, no necesita el vector de estado completo. Un estimador de tipicidad de muestreo correlacionado obtiene la misma respuesta de un puñado de estados aleatorios. Compruébalo de dos maneras a continuación, ambas a partir de ejecuciones reales con un recuento de muestras fijo para que la comparación sea limpia:

  • donde la simulación exacta aún es asequible ($N \le 10$), el estimador coincide con ella, y
  • su dispersión de muestra a muestra sigue disminuyendo a medida que el baño crece (un efecto de concentración de la medida), por lo que sigue siendo fiable mucho más allá del punto en que la simulación exacta muere.

Las dos escaladas competidoras son

$$\dim(\text{estado completo}) ;=; 4\cdot 2^{N} \quad\text{(explota)}, \qquad \text{dispersión de tipicidad} ;\sim; \frac{1}{\sqrt{\dim}} \quad\text{(disminuye)}.$$

fb = json.loads((DATA / "frontier_benchmark.json").read_text())
R = fb[0]["R"]

N = np.array([r["N"] for r in fb])
# Left panel: exact solve time explodes and stops at the memory wall.
Ne = [r["N"] for r in fb if r["exact_t"] is not None]
Te = [r["exact_t"] for r in fb if r["exact_t"] is not None]
# Right panel: true accuracy where checkable, plus the estimator's own spread everywhere.
Nacc = [r["N"] for r in fb if r["typ_vs_exact"] is not None]
acc = [r["typ_vs_exact"] for r in fb if r["typ_vs_exact"] is not None]
spread = [r["typ_err"] for r in fb]

fig, (a1, a2) = plt.subplots(1, 2, figsize=(11, 4.2))
a1.semilogy(Ne, Te, "o-", color="#c1440e")
a1.axvspan(10.5, N.max() + 0.5, color="red", alpha=0.08)
a1.text(13, max(Te), "exact\ninfeasible", color="#a00", ha="center", va="top", fontsize=9)
a1.set_xlabel("number of nuclei N")
a1.set_ylabel("exact solve time (s, log)")
a1.set_title("Exact simulation hits a memory/time wall (~N=11)")
a1.grid(alpha=0.3)

a2.semilogy(Nacc, acc, "o-", color="#c1440e", label="|typicality - exact| (true error)")
a2.semilogy(N, spread, "s--", color="#2b6cb0", label=f"estimator spread, fixed R={R}")
a2.axvspan(10.5, N.max() + 0.5, color="red", alpha=0.08)
a2.set_xlabel("number of nuclei N")
a2.set_ylabel("error on singlet MFE (log)")
a2.set_title("Typicality: accurate where checkable, spread keeps shrinking")
a2.legend(fontsize=8)
a2.grid(alpha=0.3)
plt.tight_layout()
plt.show()

worst_acc = max(acc)
display(
    Markdown(
        f"**Exact solve** becomes infeasible on a laptop beyond N~{Ne[-1]} (state vector too large).  \n"
        f"**Typicality vs exact** where both exist (N<={Nacc[-1]}): worst error {worst_acc:.4f}.  \n"
        f"**Estimator spread** at fixed R={R}: N=3 -> {spread[2]:.4f}, N={N[-1]} -> {spread[-1]:.4f} (shrinking)."
    )
)
<Figure size 1100x420 with 2 Axes>
<IPython.core.display.Markdown object>

Entrega el benchmark a un modelo de pensamiento escéptico y pídele un veredicto honesto sobre la ventaja cuántica para este observable.

INTERP2_SYSTEM = (
    "You are a skeptical computational physicist. Do not flatter quantum computing. "
    "If a classical method wins, say so plainly and explain why. Keep the answer under "
    "about 600 words so no section is cut off. "
    "Format as Markdown that nests inside a notebook section: use bold labels or at most "
    "level-3 (###) headings, never level-1 (#) or level-2 (##), and no em-dashes. Write "
    "any math as LaTeX ($...$ inline, $$...$$ display), but inside Markdown table cells "
    "use plain text or backticks, never LaTeX. If you use a table, keep every cell to a "
    "few words and put any longer explanation in prose beneath it, never full sentences "
    "inside cells."
)
ADVANTAGE_PROMPT = f"""
    A popular claim is that quantum computers are needed to simulate quantum biology such as
    the radical-pair compass. Evaluate this critically for THIS observable, the magnetic-field
    effect on singlet yield. Facts to use (all from the runs above):
    - Exact simulation of the full nuclear-spin bath stores the full state vector, costs about
      O(4 * 2^N), and becomes infeasible on a laptop around N = 10 to 11 nuclei (a memory wall).
    - A correlated-sampling typicality estimator uses a FIXED number of random states (R={R}).
      Where exact simulation is still affordable (N <= {Nacc[-1]}), the estimator matches it to
      within {worst_acc:.3f} on the singlet MFE. At the SAME sample count its sample-to-sample
      spread shrinks as the bath grows (concentration of measure), from {spread[2]:.4f} at N=3 to
      {spread[-1]:.4f} at N={N[-1]}. The full ~20-nucleus bath fits in a few GB and runs on a
      laptop. There is no classical accuracy wall for this observable.
    Questions:
    (1) For this observable, is there any bath-size regime where a fault-tolerant quantum
        computer would actually beat classical simulation, or is the "quantum computer needed"
        framing wrong here?
    (2) What related problem WOULD genuinely require quantum hardware?
    Give an honest, specific verdict. It is fine to conclude quantum hardware is not needed for
    the headline observable.
"""

display(Markdown(ask_gemini(ADVANTAGE_PROMPT, INTERP2_SYSTEM, model=DEEP_MODEL)))
<IPython.core.display.Markdown object>

En español simple. Escribir todo el estado cuántico se expande rápidamente, pero solo necesitas un número, y un truco de muestreo lo fija en una laptop, así que aquí la computadora cuántica es la herramienta equivocada y Gemini lo dice claramente.

Advertencias y conclusiones

Qué es esto. Un juguete de tres cúbits (un núcleo) para el mecanismo, verificado contra la teoría exacta y una ejecución real en hardware de los mismos circuitos, además de un modelo de flavina más realista con mitigación de errores (nitrógeno de espín-1) en hardware real. Ambos están lejos de ser un criptocromo completo.

Lo que se pasó por alto. Error de Trotter de primer orden (pequeño aquí con 50 pasos), ruido de disparo y decoherencia NISQ en las ejecuciones de hardware. El modelo de juguete tiene un solo núcleo; la brújula real tiene muchos. Los dos experimentos de hardware (Paso 3 y Paso 4) son circuitos diferentes y Hamiltonianos diferentes, mostrados juntos para pasar del mecanismo al realismo, no porque uno sea un refinamiento del otro.

El titular honesto. Ejecutar biología cuántica en una computadora cuántica es una demostración genuinamente divertida, y el hardware realmente reproduce la brújula. Pero para el observable biológicamente relevante, el rendimiento del singlete, una laptop con el estimador clásico correcto gana. El lugar donde una computadora cuántica se ganaría su sustento es en la dinámica de espín de muchos cuerpos en tiempo real con muchos núcleos fuertemente acoplados y sin un buen estimador clásico, lo cual es un problema de la era tolerante a fallos, no uno de NISQ.

Lo más útil que hizo Gemini en este notebook no fue escribir el circuito. Fue decirte, con los números en la mano, cuándo la computadora cuántica es la herramienta equivocada.

Próximos pasos

Referencias útiles de la API

Ejemplos relacionados

El modelado de pares de radicales aquí es una visión compacta y autocontenida de la física revisada por Hore y Mouritsen, The Radical-Pair Mechanism of Magnetoreception (Annual Review of Biophysics, 2016).

Lección del curso «Gemini API Cookbook (examples)» de Google, publicado con licencia Apache 2.0. Traducción y adaptación al español de IA con Clase. IA con Clase no está afiliado a Google. Ver el original · Licencia
Esta lección es gratuita. El resto del curso se abre con la Membresía de IA con Clase, que incluye todos los cursos del catálogo. Ver precios