Fyskode Learning

Python científico y graficación · Licenciatura avanzada / posgrado inicial · 10 horas

Hidden Attractors FO: análisis y visualización

Pipeline reproducible, API pública, simulación entera y fraccionaria, métricas finitas y gráficas con Hidden Attractors FO.

Trazabilidad del pipeline

Un pipeline encadena una configuración validada con la trayectoria, los diagnósticos y las figuras. La configuración entra al sistema, se valida, produce una trayectoria, alimenta diagnósticos y genera figuras. Cada salida conserva de qué entrada y de qué versión procede. El pipeline no tiene que ser una plataforma compleja; debe hacer explícita la secuencia:

configuracioˊntrayectoriadiagnoˊsticofigura.\text{configuración} \longrightarrow \text{trayectoria} \longrightarrow \text{diagnóstico} \longrightarrow \text{figura}.

Cada dependencia del pipeline debe quedar documentada. Una FFT requiere ventana, muestreo y segmentación además de la trayectoria. Una sección de Poincaré requiere plano, orientación e interpolación. Si esos parámetros viven solo dentro de una celda, la figura no puede reconstruirse.

Los experimentos de Alligood, Sauer y Yorke aportan casos dinámicos y preguntas de control Alligood, 1996 Kathleen T. Alligood, Tim D. Sauer y James A. Yorke (1996) Chaos: An Introduction to Dynamical Systems Springer Ubicación consultada: visitas de laboratorio, desafíos y apéndice B . La estructura de archivos y las funciones de Python convierten esas preguntas en un procedimiento reproducible.

Código y evidencia computacional

Una derivación describe qué debería ocurrir; el programa fija qué se calculó de hecho. Datseris y Parlitz presentan conjuntamente teoría, código, ejercicios, datos y aplicaciones reproducibles. De esa organización se adopta un contrato sencillo: cada resultado debe poder rastrearse hasta una ecuación, una configuración y una versión ejecutable del método Datseris, 2022 George Datseris y Ulrich Parlitz (2022) Nonlinear Dynamics: A Concise Introduction Interlaced with Code Springer Nature Switzerland Ubicación consultada: cap. 1, §1.3, pp. 7–9 Abrir fuente .

El contrato tiene tres elementos que no deben confundirse:

  1. Modelo: ecuaciones, parámetros, variables, unidades y dominio donde se pretende interpretar la solución.
  2. Método: integrador, tolerancias, paso de salida, tratamiento de eventos, transitorio descartado y diagnóstico aplicado.
  3. Ejecución: versión del código, entorno, semilla, hora, estado final y archivos realmente producidos.

Guardar sólo un cuaderno mezcla estos elementos con el orden accidental de las celdas. Una estructura pequeña basta para separarlas:

experimento/
├── pyproject.toml
├── README.md
├── configs/lorenz-base.json
├── src/fyskode_dynamics/model.py
├── src/fyskode_dynamics/simulate.py
├── src/fyskode_dynamics/diagnostics.py
├── src/fyskode_dynamics/figures.py
├── tests/test_model.py
└── runs/<identificador>/

model.py evalúa el campo; simulate.py integra; diagnostics.py recibe datos guardados; figures.py no vuelve a resolver la EDO. El README debe contener un comando que parta de un entorno limpio, por ejemplo python -m fyskode_dynamics.run configs/lorenz-base.json. El archivo de dependencias fija intervalos o versiones compatibles, y la ejecución registra las versiones efectivas. Así se puede distinguir un cambio científico —otro modelo o tolerancia— de un cambio de presentación.

Un ensayo de reproducibilidad no consiste en ejecutar dos veces en la misma sesión. Se crea un entorno nuevo, se copia sólo el repositorio y la configuración declarada, se ejecuta el comando documentado y se comprueba que aparezcan los productos esperados. Si una biblioteca, un archivo descargado o una variable global no estaban declarados, el fallo revela una dependencia oculta que debe incorporarse al contrato.

Configuración validada e identificable

Un registro inicial para Lorenz puede ser:

{
  "system": "lorenz",
  "parameters": {"sigma": 10.0, "rho": 28.0, "beta": 2.6666666666666665},
  "initial_state": [1.0, 1.0, 1.0],
  "solver": {
    "method": "DOP853",
    "rtol": 1e-9,
    "atol": 1e-11
  },
  "interval": [0.0, 80.0],
  "transient": 20.0,
  "sample_step": 0.01,
  "projection": ["x", "z"]
}

La validación comprueba claves, tipos y relaciones. No basta que transient sea numérico: debe satisfacer t0ttrans<tft_0\leq t_{\mathrm{trans}}<t_f. El estado debe coincidir con la dimensión del sistema; las tolerancias deben ser positivas; las variables de proyección deben existir.

Una configuración normalizada se serializa con orden estable y se resume con un hash:

import hashlib
import json

def canonical_json(config):
    return json.dumps(
        config,
        sort_keys=True,
        separators=(",", ":"),
        ensure_ascii=False,
    )

def config_id(config):
    payload = canonical_json(config).encode("utf-8")
    return hashlib.sha256(payload).hexdigest()[:12]

El hash detecta cualquier cambio serializado; no explica su significado. Por eso el directorio combina un nombre legible y el identificador, por ejemplo lorenz-rho28-a1b2c3d4e5f6. Dos configuraciones iguales producen el mismo identificador. La política decide si se reutiliza una ejecución verificada o si se rechaza la sobrescritura.

Ejecución en un directorio temporal

Si el proceso falla a mitad, no debe parecer completo. Se calcula en una carpeta temporal y solo al final se publica el directorio definitivo:

from pathlib import Path
import tempfile

def run_atomic(config, results_root):
    results_root = Path(results_root)
    run_name = f"{config['system']}-{config_id(config)}"
    final = results_root / run_name
    if final.exists():
        raise FileExistsError(final)

    with tempfile.TemporaryDirectory(dir=results_root) as temporary:
        work = Path(temporary)
        result = simulate(config)
        save_raw(result, work)
        build_diagnostics(config, result, work)
        write_manifest(config, work, status="complete")
        work.replace(final)
    return final

En una implementación real, mover entre volúmenes distintos puede no ser atómico; se mantiene la carpeta temporal dentro de la misma raíz. El manifiesto se escribe al final con estado completo. Los fallos conservan un log separado o se reportan a la terminal, pero nunca crean un manifiesto de éxito.

Datos crudos, procesados y figuras

La trayectoria generada por el integrador es dato crudo respecto del análisis. Una serie sin transitorio, una FFT o una sección son derivados. Se organizan:

run/
  config.json
  manifest.json
  raw/
    trajectory.npz
  processed/
    section.npz
    spectrum.npz
  figures/
    phase_xz.png
    spectrum.png

NPZ conserva arreglos, nombres y tipos de NumPy. CSV facilita intercambio e inspección, pero necesita encabezados y puede perder precisión si se elige mal el formato. La documentación oficial de entrada y salida de NumPy permite elegir según el consumidor.

np.savez_compressed(
    work / "raw" / "trajectory.npz",
    time=times,
    state=states,
    variable_names=np.array(("x", "y", "z")),
)

Al leer se comprueban claves, formas, tiempo creciente y finitud. El archivo no se considera correcto solo porque np.load lo abra.

Cada derivado incluye sus parámetros. Un espectro guarda frecuencia, potencia, ventana, longitud de segmento y solapamiento. Una sección guarda coordenadas, tiempos de cruce, plano y orientación. La figura puede regenerarse desde el derivado sin integrar otra vez.

Evolución del esquema de datos

Guardar un arreglo no basta para saber cómo leerlo dentro de seis meses. La primera versión puede llamar state a una matriz (N,3)(N,3); otra puede añadir un eje para múltiples condiciones iniciales y usar (M,N,3)(M,N,3). Si ambas se escriben bajo la misma clave sin versión, una rutina antigua podría aceptar el archivo y reducir el eje equivocado. Cada conjunto incorpora un número de esquema y nombres de dimensiones, y el lector rechaza versiones que no sabe interpretar.

Una migración no debe reescribir silenciosamente los datos originales. Lee la versión anterior, valida sus supuestos y produce un archivo nuevo cuyo manifiesto apunta al hash de origen. Esa relación permite revisar qué cambió y repetir la transformación. En un proyecto pequeño puede bastar una función migrate_v1_to_v2; lo importante es que la conversión sea código probado y no una edición manual del archivo.

También conviene separar metadatos científicos de detalles accidentales. Los parámetros, unidades, nombres de variables y convención de ejes son parte del conjunto de datos. La ruta absoluta de la computadora que ejecutó el cálculo puede ayudar a diagnosticar, pero no debería ser necesaria para abrirlo. Las rutas guardadas dentro del manifiesto son relativas al directorio de la corrida, de modo que el paquete pueda moverse íntegro a otra máquina.

Considérese el espectro derivado de una coordenada de Lorenz. Su procedencia no se agota en el hash de trajectory.npz: incluye la coordenada seleccionada, el corte de transitorio, el paso uniforme, la remoción de media, la ventana y la normalización. Dos espectros con el mismo dato crudo pueden responder preguntas distintas. El registro del derivado conserva ese procedimiento y el identificador del archivo de entrada; la figura conserva, a su vez, el identificador del espectro.

Esta cadena forma un grafo dirigido sencillo. La configuración y el código producen datos crudos; los datos y una especificación producen derivados; los derivados y un estilo producen figuras. Cuando cambia solo el color, no se reintegra la EDO. Cuando cambia la tolerancia, todo descendiente de la trayectoria queda obsoleto. Expresar esas dependencias evita dos extremos: recalcular siempre todo o, peor, reutilizar un diagnóstico que ya no corresponde a la corrida.

Los tamaños y hashes del manifiesto permiten detectar truncamiento o reemplazo, pero no sustituyen la validación estructural. Después de verificar el hash, el lector comprueba que el número de tiempos coincide con las filas del estado, que los nombres coinciden con las columnas y que las unidades esperadas están presentes. Integridad de archivo y coherencia científica son controles complementarios.

Semillas pseudoaleatorias y reproducibilidad

Si se muestrean condiciones iniciales o se añade ruido, se crea un generador explícito:

rng = np.random.default_rng(seed=20260821)
initial = rng.uniform(low=-1.0, high=1.0, size=(500, 3))

La semilla se registra antes de generar. Usar el generador global en distintas funciones vuelve el resultado dependiente del orden de llamadas. Pasar rng como argumento localiza la fuente de aleatoriedad.

La misma semilla y versión no prometen igualdad bit a bit entre todo hardware. El contrato científico define qué debe coincidir: distribución, conteo, tolerancia o estadística. Si se exige identidad, se especifican plataforma, bibliotecas y configuración numérica.

Comparación mediante una métrica común

Comparación de trayectorias de Lorenz, Rössler y Sprott
Los tres paneles requieren un contrato común de transitorio, muestreo y presentación. Rangos y escalas distintas impiden usar el tamaño aparente como medida de complejidad.

Atlas reproducible de sistemas dinámicos Función: plot_flow_family_comparison

Descargar .py

Para comparar los tres flujos se crean tres configuraciones y se conserva un esquema común. No se fuerza la misma duración si sus escalas temporales son distintas; se documenta la decisión. Una tabla reúne:

  • ecuaciones y parámetros;
  • condición inicial;
  • integrador y tolerancias;
  • tiempo retenido y número de muestras;
  • rangos por variable;
  • divergencia media;
  • tiempo medio de retorno en una sección.

Sprott organiza flujos simples y diagnósticos que sirven para esta comparación Sprott, 2010 Julien Clinton Sprott (2010) Elegant Chaos: Algebraically Simple Chaotic Flows World Scientific Ubicación consultada: §§1.9–1.15 y cap. 3 . El proyecto retoma la pregunta dinámica, fija un protocolo común y conserva cada decisión necesaria para reconstruir el resultado.

La figura tridimensional plantea una hipótesis. La tabla debe sostenerla con una métrica. “Rössler gira más lentamente” requiere definir retorno y unidad de tiempo; “Sprott ocupa menos espacio” carece de significado sin normalización.

Manifiesto y procedencia

Un manifiesto legible puede contener:

{
  "status": "complete",
  "config_sha256": "a1b2c3...",
  "python": "3.13.5",
  "packages": {"numpy": "2.3.1", "scipy": "1.16.0", "matplotlib": "3.10.3"},
  "files": [
    {"path": "raw/trajectory.npz", "sha256": "…"},
    {"path": "figures/phase_xz.png", "sha256": "…"}
  ]
}

Los hashes detectan cambios accidentales. No certifican que el método sea correcto. La validez científica procede de pruebas, refinamiento y argumento. El manifiesto responde “qué archivo exacto se usó”; la tabla de convergencia responde “qué tan estable es la conclusión”.

Un registro de texto informa comienzo, fin, advertencias y costo. No imprime cada paso del integrador. El volumen de mensajes no equivale a trazabilidad.

Reconstrucción de una ejecución con datos guardados

El comando de reconstrucción acepta la carpeta de ejecución:

def rebuild(run_directory):
    run = Path(run_directory)
    config = json.loads((run / "config.json").read_text(encoding="utf-8"))
    data = np.load(run / "raw" / "trajectory.npz")
    validate_trajectory(data["time"], data["state"], dimension=3)
    make_phase_figure(config, data, run / "figures" / "phase_xz.png")

Regenerar una figura desde datos guardados prueba la separación entre cálculo y presentación. Regenerar todo desde la configuración prueba el pipeline completo. Ambas pruebas son necesarias y responden preguntas diferentes.

La reconstrucción se ejecuta en un directorio nuevo durante la evaluación. Se comparan hashes cuando se espera identidad o propiedades numéricas cuando puede haber variación de plataforma. Una discrepancia se documenta; no se reemplaza silenciosamente el resultado original.

API pública y niveles de estabilidad

Hidden Attractors FO proporciona modelos, integradores, diagnósticos y funciones de graficación para sistemas dinámicos. En esta unidad se usa después de haber programado funciones implementadas por el estudiante, un integrador elemental y gráficas con Matplotlib. El proyecto declara el nombre de paquete hidden-attractors-fo, la versión 1.2.0 y compatibilidad con Python 3.11–3.14. Una vez publicado en PyPI, podrá instalarse con:

python -m pip install hidden-attractors-fo

En Jupyter, el mismo intérprete puede instalar el paquete con %pip install hidden-attractors-fo. Después se reinicia el kernel si el entorno lo solicita. Los ejemplos no requieren Raspberry Pi ni otro hardware; necesitan un kernel de Python compatible con el paquete. Un intérprete en el navegador solo podrá ejecutar este tramo si su entorno ofrece la distribución hidden-attractors-fo y sus dependencias.

La referencia pública de la API y la política de estabilidad distinguen dos niveles usados aquí Order, 2026 Proyecto Hidden Attractors Fractional Order (2026) Hidden Attractors Fractional Order: API Reference Versión 1.2.0 · Repositorio oficial del proyecto Ubicación consultada: API Reference y API Stability, versión 1.2.0 Abrir fuente :

  • estable: firma y tipo de retorno protegidos entre versiones menores;
  • experimental: función probada y documentada cuya firma puede recibir argumentos opcionales nuevos con aviso de cambios.

El paquete expone esa información en tiempo de ejecución:

import os
from pathlib import Path

os.environ["HIDDEN_ATTRACTORS_OUTPUT_DIR"] = str(
    (Path("results") / "hafo_store").resolve()
)

import hidden_attractors as ha

symbols = (
    ha.chua_nonsmooth_parameters,
    ha.rhs_nonsmooth,
    ha.equilibria_nonsmooth,
    ha.get_system,
    ha.list_systems,
    ha.simulate,
    ha.simulate_fractional,
    ha.compute_trajectory_metrics,
)

for symbol in symbols:
    print(symbol.__name__, ha.get_tier(symbol))

print("chua-nonsmooth" in ha.list_systems())
print(ha.get_system("chua-nonsmooth").dimension)

Las cinco primeras funciones son estables. simulate, simulate_fractional y la métrica de trayectoria son experimentales. hidden_attractors.fractional y hidden_attractors.plotting son módulos públicos experimentales; sus clases y funciones se importan desde esos módulos cuando no aparecen como nombres de nivel superior.

Modelo de Chua con la API estable

El modelo no suave implementado por la biblioteca tiene el campo

CDtqx=α[yxf(x)],CDtqy=xy+z,CDtqz=βyγz,\begin{aligned} {}^C D_t^q x &= \alpha\,[y-x-f(x)],\\ {}^C D_t^q y &= x-y+z,\\ {}^C D_t^q z &= -\beta y-\gamma z, \end{aligned}

con

f(x)=m1x+m0m12(x+1x1).f(x)=m_1x+\frac{m_0-m_1}{2}\left(|x+1|-|x-1|\right).

Para q=1q=1 se recupera el sistema de EDO ordinarias. Un valor 0<q<10<q<1 representa una derivada de Caputo con memoria; el orden pertenece al contrato del integrador y no al registro de parámetros.

import numpy as np
import hidden_attractors as ha

parameters = ha.chua_nonsmooth_parameters()
state = np.array([0.1, 0.0, 0.0])

field_value = ha.rhs_nonsmooth(state, parameters)
equilibria = ha.equilibria_nonsmooth(parameters)

print(field_value)
for name, point in equilibria.items():
    print(name, point)

chua_nonsmooth_parameters() devuelve un registro inmutable con α\alpha, β\beta, γ\gamma, m0m_0 y m1m_1. rhs_nonsmooth(state, parameters) evalúa el lado derecho y devuelve un arreglo de tres componentes. equilibria_nonsmooth(parameters) resuelve los equilibrios del mismo modelo y devuelve un diccionario nombre: vector. Estas funciones reemplazan código repetido, pero no el razonamiento: antes de integrarlas se debe comprobar a mano al menos un estado, su forma y su finitud.

Práctica interactiva. Programa primero tu propia función chua_field(state, parameters) con las ecuaciones anteriores. Evalúala en el origen y en [0.1, 0.0, 0.0]. Después compara su salida con ha.rhs_nonsmooth mediante np.testing.assert_allclose. El ejercicio separa una implementación del estudiante de una función estable proporcionada por la biblioteca.

Integración entera y métricas de trayectoria

El siguiente bloque es una práctica final completa. Recupera el sistema del registro público, llama a la fachada de simulación, valida su estado y aplica una métrica pública a los arreglos resultantes:

import os
from pathlib import Path

# Debe definirse antes de importar hidden_attractors.
output = Path("results")
os.environ["HIDDEN_ATTRACTORS_OUTPUT_DIR"] = str(
    (output / "hafo_store").resolve()
)

import numpy as np
import hidden_attractors as ha
from hidden_attractors.plotting import plot_phase_space, plot_time_series

parameters = ha.chua_nonsmooth_parameters()
system = ha.get_system("chua-nonsmooth")
initial_state = np.array([
    0.7282151467357212,
    -0.8854021004889308,
    -5.297149991940586,
])

result = ha.simulate(
    system,
    initial_state=initial_state,
    step_size=0.01,
    duration=20.0,
    method="rk4",
    divergence_norm=120.0,
    use_acceleration=False,
)

if result.status != "ok":
    raise RuntimeError(f"La integración terminó con estado {result.status!r}")

times = result.times
states = result.states

metrics = ha.compute_trajectory_metrics(
    times,
    states,
    equilibria=ha.equilibria_nonsmooth(parameters),
    t_start=5.0,
)

print("forma:", states.shape)
print("acotada en la ventana:", metrics["bounded"])
print("norma máxima:", metrics["max_norm"])
print("pico FFT de x:", metrics["fft_peak_component_0"])
print("estado de evidencia:", metrics["evidence_status"])

trajectory = result.trajectory
plot_phase_space(
    trajectory,
    output / "chua_phase.png",
    dims=("x", "y", "z"),
    title="Sistema de Chua: espacio de fases",
)
plot_time_series(
    trajectory,
    output / "chua_series.png",
    columns=("x", "y", "z"),
    title="Sistema de Chua: series temporales",
)

ha.get_system recupera una definición registrada y ha.simulate es la fachada pública más sencilla para ejecutarla. El primer argumento recibe el sistema chua-nonsmooth; initial_state fija la condición inicial; step_size fija el paso; duration fija el horizonte; y method=“rk4” selecciona RK4. use_acceleration=False selecciona la implementación en Python y evita depender de compilación nativa. El objeto result conserva estado, tiempos, método, parámetros y número de pasos; su propiedad trajectory devuelve directamente la tabla (t, x, y, z).

La condición inicial procede del caso reproducible usado por el manifiesto público del catálogo de gráficas. Se elige porque produce una trayectoria finita no trivial durante este ejemplo, no porque certifique caos, atracción u ocultamiento. La condición [0.1, 0.0, 0.0] empleada antes para comprobar el campo se acerca al equilibrio central con estos parámetros y es útil como contraste.

compute_trajectory_metrics exige tiempos crecientes y una matriz states con forma (n_muestras, dimensión). El argumento t_start=5.0 selecciona el tramo usado para rangos, varianzas y FFT. La propiedad result.trajectory añade el tiempo como primera columna porque las funciones de dibujo reciben una tabla (t, x, y, z). plot_phase_space y plot_time_series validan esa tabla y escriben los PNG solicitados en results. Además, el almacén declarado en HIDDEN_ATTRACTORS_OUTPUT_DIR conserva pares PNG/PDF y metadatos de las figuras. La variable se fija antes del primer import del paquete para que toda la ejecución use results/hafo_store y no dependa de una configuración previa del equipo.

Simulación fraccionaria con contrato explícito

La nueva interfaz fraccionaria recibe un FractionalProblem. El contrato reúne definición de derivada, método, orden, condición inicial, paso, horizonte y política de memoria, por lo que esas decisiones no quedan dispersas entre argumentos independientes:

from hidden_attractors.fractional import FractionalProblem

fractional_problem = FractionalProblem(
    derivative="caputo",
    method="caputo_abm_pece",
    orders=0.98,
    initial_state=initial_state,
    step=0.01,
    t_span=(0.0, 2.0),
    memory_policy="full_history",
    problem_id="learning-chua-q098",
)

result_q = ha.simulate_fractional(
    system,
    fractional_problem,
    use_acceleration=False,
    allow_python_fallback=True,
    divergence_norm=120.0,
)

if result_q.status != "ok":
    raise RuntimeError(result_q.status)

print(result_q.states.shape)
print(result_q.metadata["fractional_problem"]["derivative"])

method=“caputo_abm_pece” selecciona el predictor-corrector de Caputo y memory_policy=“full_history” conserva la historia completa. result_q usa el mismo contrato de salida que la simulación entera y conserva además el problema fraccionario y la procedencia del backend en sus metadatos. Esta corrida corta enseña la interfaz; no es una comparación científica suficiente con el caso entero. Una comparación defendible debe refinar el paso, ampliar el horizonte, declarar el tratamiento del transitorio y contrastar observables compatibles con la memoria.

Alcance de los resultados numéricos

El valor metrics[“bounded”] significa que la trayectoria suministrada se mantuvo finita bajo el umbral y horizonte declarados. No demuestra acotamiento global. Un pico de FFT, una entropía espectral o una nube de puntos compleja no demuestran caos. Las gráficas muestran la proyección de muestras numéricas; por sí solas no demuestran atracción.

El ocultamiento requiere además un contrato separado de vecindades de todos los equilibrios, direcciones, radios, horizontes, clasificación de destinos y controles numéricos. Incluso un control finito completo sostiene únicamente una afirmación condicionada a las vecindades ensayadas; no constituye una prueba global de cuenca ni de ocultamiento. El curso usa la biblioteca para calcular y organizar evidencia, no para convertir un diagnóstico en teorema.

Práctica final ejecutable. Ejecuta el ejemplo entero en Jupyter o en un archivo .py. Repite con h=0.02h=0.02 y h=0.005h=0.005, conserva status, norma máxima, rangos, pico espectral y ambas figuras. Luego ejecuta el caso fraccionario corto. Entrega el código de configuración, las llamadas a la API pública, una tabla de resultados y tres conclusiones con su horizonte y limitaciones. No llames “caótico” u “oculto” a un caso basándote solo en estas salidas.

Práctica ejecutable

Diagnóstico finito del mapa logístico

Pyodide v314.0.4

Este ejercicio aislado usa una función implementada por el estudiante y NumPy en el navegador. Las llamadas a Hidden Attractors FO de esta unidad se ejecutan en un entorno Python o Jupyter con el paquete instalado. Compara los tres parámetros y modifica el transitorio.

Descargar cuaderno Jupyter (.ipynb)

Listo para ejecutar.

Salida

Todavía no se ha ejecutado el programa.
Ejecución, privacidad y límites

El programa se ejecuta en un Web Worker dentro de este navegador. No usa la Raspberry Pi ni un proceso Python del servidor de Fyskode. Al pulsar Ejecutar por primera vez, el navegador descarga Pyodide y las bibliotecas importadas desde el CDN oficial de jsDelivr; esas solicitudes siguen la política de privacidad del CDN. El código escrito aquí no se envía a Fyskode.

Cada ejecución dispone de hasta 60 segundos, 200 000 caracteres de salida y seis gráficas; las figuras excesivamente grandes se omiten. El tiempo se cuenta después de cargar el motor y las bibliotecas. Detener o agotar el tiempo elimina el Worker y su memoria. El entorno no tiene acceso directo a los archivos del equipo, pero un programa puede solicitar recursos de red si se le ordena; no pegues contraseñas ni credenciales.

Evaluación final del curso

  1. Rechaza una configuración con intervalo invertido o estado de dimensión incorrecta.
  2. Comprueba que una ejecución fallida no publique un manifiesto completo.
  3. Verifica claves, formas, finitud y tiempo al volver a cargar NPZ.
  4. Regenera una figura sin llamar al integrador.
  5. Cambia el transitorio y confirma que el hash y el resultado derivado cambien.
  6. Ejecuta desde un entorno nuevo siguiendo únicamente el README.
  7. Comprueba el nivel de estabilidad de las funciones HAFO utilizadas.
  8. Contrasta tu campo de Chua con rhs_nonsmooth en tres estados.
  9. Genera las series y el espacio de fases mediante las funciones públicas de graficación.
  10. Separa observaciones en tiempo finito de afirmaciones sobre caos, atracción y ocultamiento.

Antes de compartir la corrida, pide a otra persona que reconstruya una figura, rastree su diagnóstico hasta la trayectoria y señale con precisión qué etapa debe repetirse al cambiar una decisión numérica.

Fuentes consultadas

Obras citadas en el desarrollo; los localizadores indican los capítulos o secciones consultados.
  1. Kathleen T. Alligood, Tim D. Sauer y James A. Yorke (1996). Chaos: An Introduction to Dynamical Systems. Springer. ISBN 0-387-94677-2.

    visitas de laboratorio, desafíos y apéndice B · Experimentos computacionales de dinámica y controles adaptados.
  2. Julien Clinton Sprott (2010). Elegant Chaos: Algebraically Simple Chaotic Flows. World Scientific.

    §§1.9–1.15 y cap. 3 · Diagnósticos y comparación de flujos caóticos simples.
  3. Tamás Tél y Márton Gruiz (2006). Chaotic Dynamics: An Introduction Based on Classical Mechanics. Cambridge University Press. ISBN 978-0-521-54783-3.

    recuadro 5.4 y apéndice A.3–A.5 · Alcance de simulaciones y parámetros numéricos.
  4. George Datseris y Ulrich Parlitz (2022). Nonlinear Dynamics: A Concise Introduction Interlaced with Code. Springer Nature Switzerland. ISBN 978-3-030-91032-7. DOI 10.1007/978-3-030-91032-7.

    cap. 1, §1.3, pp. 7–9 · Código, datos, ejercicios y aplicaciones como partes reproducibles de un argumento dinámico.
  5. Proyecto Hidden Attractors Fractional Order (2026). Hidden Attractors Fractional Order: API Reference. Versión 1.2.0 Repositorio oficial del proyecto.

    API Reference y API Stability, versión 1.2.0 · Firmas públicas, niveles de estabilidad, integración, diagnósticos y graficación usados en la unidad.