# Code 1.1 - Frise animee de la chronologie (aout-septembre 2026)
# Trois actes : lignage/travail secret, course, annonces et arbitrage.
%matplotlib inline
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib import animation, rcParams
import numpy as np
import base64
from IPython.display import HTML
EVENTS = [
("2013-2025", "Luo-Hou (num.)\npuis Cordoba-Martinez-Zoroa\nblowups forces (anal.)", 0),
("15 aout", "Buckmaster-Alpoge : blowup\nIPM, Boussinesq, Euler\n(forcage lisse, avec LLMs)", 0),
("22 aout", "verification Lean\nde leurs resultats", 0),
("28 aout", "OpenAI commence\nl'entrainement du modele interne", 1),
("31 aout", "Alpoge tweete\n'Augustus Mirabilis'", 1),
("1 sept.", "OpenAI lance l'effort\nsur les 7 problemes", 1),
("2 sept.", "Alpoge apprend\nla fuite vers OpenAI", 1),
("3 sept.", "Buckmaster ecrit\na OpenAI (les faits)", 1),
("5 sept.", "resolution des agents\n(~88 h apres lancement)", 1),
("6 sept.", "appels Bubeck :\n2 propositions, divergences\n+ fin de la formalisation Lean", 1),
("7 sept.", "Buckmaster-Alpoge publient\n(3 resultats + statement,\njuste avant minuit)", 2),
("8 sept.", "ANNONCE OpenAI\n(C)+(D), 166 p. + Lean\naccusations sur les donnees", 2),
("9-10 sept.","EMS : jalon historique,\nmodele interne = probleme\ndonnees : 'impossible'", 2),
("11 sept.", "CLAY : 'apparently settled',\nstatut actif, 'unhurried'\nTao : 'severe misalignment'", 2),
("13-14 sept.","'no inputs past July 3'\narticle Wolfram Community", 2),
]
ACT_COLORS = ["#4c72b0", "#dd8452", "#55a868"]
ACT_NAMES = ["I. Lignee et travail secret", "II. La course", "III. Annonces et arbitrage"]
fig, ax = plt.subplots(figsize=(11.5, 4.6), dpi=78)
frames = len(EVENTS) + 6
def draw(k):
ax.clear()
shown = min(k, len(EVENTS))
ax.axhline(0, color="#888888", lw=2, zorder=1)
for i, (date, label, act) in enumerate(EVENTS[:shown]):
x = i
col = ACT_COLORS[act]
ax.scatter([x], [0], s=110, color=col, zorder=3, edgecolors="white", linewidths=1.2)
up = (i % 2 == 0)
y_txt = 0.55 if up else -0.95
va = "bottom" if up else "top"
ax.annotate("", xy=(x, 0.16 if up else -0.16), xytext=(x, y_txt + (0.06 if up else -0.06)),
arrowprops=dict(arrowstyle="-", color=col, lw=1.0))
ax.text(x, y_txt, f"{date}\n{label}", ha="center", va=va, fontsize=7.6, color="#222222")
if k > 2:
for xs, xe, c, name in [(-0.7, 2.6, ACT_COLORS[0], ACT_NAMES[0]),
(2.6, 9.6, ACT_COLORS[1], ACT_NAMES[1]),
(9.6, 14.3, ACT_COLORS[2], ACT_NAMES[2])]:
if shown - 0.5 > xs:
ax.plot([max(xs, -0.7), min(xe, shown - 0.5)], [0, 0], color=c, lw=5, alpha=0.35, zorder=2, solid_capstyle="round")
handles = [mpatches.Patch(color=c, label=n) for c, n in zip(ACT_COLORS, ACT_NAMES)]
ax.legend(handles=handles, loc="lower left", fontsize=8, frameon=False, ncol=3,
bbox_to_anchor=(0.0, -0.30))
ax.set_xlim(-1.0, len(EVENTS) - 0.2)
ax.set_ylim(-2.3, 2.0)
ax.set_title("Navier-Stokes, aout-septembre 2026 : la course et son arbitrage", fontsize=11)
ax.axis("off")
anim = animation.FuncAnimation(fig, draw, frames=frames, interval=950)
anim.save("ns_frise_2026.gif", writer=animation.PillowWriter(fps=1.05))
plt.close(fig)
with open("ns_frise_2026.gif", "rb") as fh:
gif_bytes = fh.read()
print(f"frise : {len(EVENTS)} evenements, {len(gif_bytes)/1024:.0f} Ko")
display(HTML("<img src='data:image/gif;base64," + base64.b64encode(gif_bytes).decode() + "' style='max-width:100%' alt='GIF anime'/>"))