{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c3245409",
   "metadata": {},
   "source": [
    "# Order into chaos: the logistic map\n",
    "### Chapter 7 · chaos, bifurcation, the butterfly effect · **[PREDICT-FIRST]**\n",
    "\n",
    "[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/MeiraDavidson/math_module1/blob/main/notebooks/notebook_7_2_logistic_map_chaos.ipynb)\n",
    "\n",
    "**What you'll see:** the most important notebook in this book. One absurdly simple\n",
    "rule — $f(x) = r\\,x\\,(1-x)$ — fed its own output. Turn a single knob $r$ and watch a\n",
    "calm, settled system **split, split again, and dissolve into chaos**. Then generate\n",
    "the famous bifurcation diagram, and finally watch two nearly-identical starts explode\n",
    "into different futures: the **butterfly effect**.\n",
    "\n",
    "**Predict-first.** Do the experiment *before* you read the meaning at the bottom."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6a7f5fa1",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "import matplotlib.pyplot as plt\n",
    "from ipywidgets import interact, FloatSlider\n",
    "\n",
    "def logistic_path(r, x0, n):\n",
    "    x = x0\n",
    "    path = [x]\n",
    "    for _ in range(n):\n",
    "        x = r * x * (1 - x)\n",
    "        path.append(x)\n",
    "    return path"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "820ffa56",
   "metadata": {},
   "source": [
    "## 1. Turn the knob\n",
    "\n",
    "🔮 **Predict first:** at $r=2$, predict whether the population *settles* to one value.\n",
    "Then raise $r$ past $3$ and predict what \"settling\" *becomes* — does it stay one\n",
    "value, or do something new? Drag the slider slowly and watch the time series."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "82a17637",
   "metadata": {},
   "outputs": [],
   "source": [
    "def show_timeseries(r=2.0):\n",
    "    path = logistic_path(r, 0.3, 50)\n",
    "    plt.figure(figsize=(8, 3.5))\n",
    "    plt.plot(path, \"o-\", color=\"#1A6FB0\", ms=4, lw=1.2)\n",
    "    plt.ylim(0, 1); plt.xlabel(\"year\"); plt.ylabel(\"population\")\n",
    "    plt.title(f\"r = {r:.2f}\"); plt.show()\n",
    "\n",
    "interact(show_timeseries, r=FloatSlider(min=1.0, max=4.0, step=0.01, value=2.0));"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2ee1f768",
   "metadata": {},
   "source": [
    "Watch the journey as you raise $r$: **settles** → **2-cycle** (bounces between two\n",
    "values) → **4-cycle** → and past about $r=3.57$, **chaos** — jumping around forever\n",
    "with no pattern, even though the rule is utterly fixed and simple."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "851104e2",
   "metadata": {},
   "source": [
    "## 2. The bifurcation diagram (the iconic image)\n",
    "\n",
    "For each value of $r$, throw away the first few hundred steps (the transient) and\n",
    "plot the values it *settles into*. This single picture shows the whole\n",
    "period-doubling cascade at once — the famous \"fig tree.\"\n",
    "\n",
    "*(This takes a couple of seconds to compute — it's iterating thousands of times.)*"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "412753b0",
   "metadata": {},
   "outputs": [],
   "source": [
    "rs = np.linspace(2.5, 4.0, 2000)\n",
    "R, X = [], []\n",
    "for r in rs:\n",
    "    x = 0.5\n",
    "    for _ in range(300):          # let transients die out\n",
    "        x = r * x * (1 - x)\n",
    "    for _ in range(120):          # record the attractor\n",
    "        x = r * x * (1 - x)\n",
    "        R.append(r); X.append(x)\n",
    "\n",
    "plt.figure(figsize=(9, 5))\n",
    "plt.plot(R, X, \",\", color=\"#1A6FB0\", alpha=0.25)\n",
    "plt.title(\"Bifurcation diagram: the road from order to chaos\")\n",
    "plt.xlabel(\"r\"); plt.ylabel(\"long-run population\")\n",
    "plt.axvline(3.57, color=\"#999\", ls=\":\"); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2c316f62",
   "metadata": {},
   "source": [
    "One line splits to two, to four, to eight — faster and faster — then shatters into\n",
    "the chaotic spray. The white gaps inside the chaos are \"windows\" where order briefly\n",
    "returns. **This image is impossible to draw by hand and unforgettable on a screen.**\n",
    "Zoom in by changing `rs = np.linspace(3.4, 4.0, 2000)` and run again."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b6b14c93",
   "metadata": {},
   "source": [
    "## 3. The butterfly effect\n",
    "\n",
    "🔮 **Predict first:** two runs at $r=3.9$, starting a hair apart — $0.300$ and\n",
    "$0.301$. **Predict whether starting a hair apart matters.** Will they stay together,\n",
    "or drift?"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a64ec36a",
   "metadata": {},
   "outputs": [],
   "source": [
    "a = logistic_path(3.9, 0.300, 45)\n",
    "b = logistic_path(3.9, 0.301, 45)\n",
    "plt.figure(figsize=(9, 3.8))\n",
    "plt.plot(a, \"-\", color=\"#1A6FB0\", lw=1.6, label=\"start 0.300\")\n",
    "plt.plot(b, \"-\", color=\"#E8833A\", lw=1.6, label=\"start 0.301\")\n",
    "plt.xlabel(\"year\"); plt.ylabel(\"population\"); plt.legend()\n",
    "plt.title(\"A hair apart — then worlds apart\"); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c7c9da30",
   "metadata": {},
   "source": [
    "They track almost perfectly for a while... and then, around step 10–15, they\n",
    "**explode apart** and have nothing to do with each other. A difference of $0.001$ —\n",
    "invisible — became total disagreement. That's why weather can't be forecast far\n",
    "ahead: not because the rules are unknown, but because they're *chaotic*."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "becf3521",
   "metadata": {},
   "source": [
    "## Why this matters (read it now, after you've played)\n",
    "\n",
    "Look at the *shape* of what happened. As you slowly turned one knob, the system held\n",
    "steady, held steady — and then, at a sharp threshold, **abruptly reorganized** into\n",
    "something qualitatively new. Calm, then suddenly a 2-cycle. Order, then suddenly\n",
    "chaos.\n",
    "\n",
    "That pattern — *a smooth change in a setting producing a sudden jump in behavior* —\n",
    "is called a **phase transition**, and once you have eyes for it you see it\n",
    "everywhere: water cooling degree by degree and then, at one temperature, abruptly\n",
    "freezing; and — this is the live frontier — an artificial intelligence that is\n",
    "trained and trained showing no sign of a skill, and then, rather suddenly,\n",
    "*acquiring* it.\n",
    "\n",
    "You just watched a simple rule reorganize itself all at once. Many researchers\n",
    "suspect this is the shape of how AI models suddenly acquire new abilities as they\n",
    "grow. Nobody fully understands it yet — and a kid iterating $r\\,x(1-x)$ is touching\n",
    "the same mathematics."
   ]
  }
 ],
 "metadata": {
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
