2026-05-12 12:18:14 +02:00
|
|
|
|
{
|
|
|
|
|
|
"cells": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "markdown",
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"id": "bab453dd",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"source": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"# 14 — Mean-reverting McKean–Vlasov\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"Doc page: [mckean_vlasov.rst](../../docs/source/algorithms/mckean_vlasov.rst).\n"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
|
"execution_count": 1,
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"id": "ef5d758f",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"metadata": {
|
|
|
|
|
|
"execution": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"iopub.execute_input": "2026-05-12T14:05:47.635814Z",
|
|
|
|
|
|
"iopub.status.busy": "2026-05-12T14:05:47.635518Z",
|
|
|
|
|
|
"iopub.status.idle": "2026-05-12T14:05:48.206290Z",
|
|
|
|
|
|
"shell.execute_reply": "2026-05-12T14:05:48.204534Z"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"outputs": [],
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
"import numpy as np\n",
|
|
|
|
|
|
"import matplotlib.pyplot as plt\n",
|
|
|
|
|
|
"from optimizr import _core as opt\n",
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"plt.rcParams['figure.figsize'] = (8.5, 4.5)\n",
|
|
|
|
|
|
"plt.rcParams['figure.dpi'] = 110\n",
|
|
|
|
|
|
"plt.rcParams['axes.grid'] = True\n",
|
|
|
|
|
|
"plt.rcParams['grid.alpha'] = 0.3\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
|
"id": "e2a30664",
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
"## Cellule 1 — Conservation de la moyenne\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Théorème (McKean 1966).** Pour la dynamique de champ moyen\n",
|
|
|
|
|
|
"$$dX_t^i = \\theta\\,(\\bar X_t - X_t^i)\\,dt + \\sigma\\,dW_t^i,\n",
|
|
|
|
|
|
" \\qquad \\bar X_t = \\frac{1}{N}\\sum_j X_t^j,$$\n",
|
|
|
|
|
|
"la moyenne empirique est conservée en espérance,\n",
|
|
|
|
|
|
"$\\mathbb{E}[\\bar X_t] = \\bar X_0$.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Équation pivot.** $\\mathbb{E}[\\bar X_t] = \\bar X_0$ pour tout $t$.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Démonstration.** Sommer l'EDS sur $i$ : la dérive interne s'annule\n",
|
|
|
|
|
|
"(moyenne — individu). $\\square$\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Ce que la cellule vérifie.** `mean_reverting_mckean_vlasov` préserve\n",
|
|
|
|
|
|
"la moyenne et concentre la variance.\n"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "code",
|
|
|
|
|
|
"execution_count": 2,
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"id": "abd6c348",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"metadata": {
|
|
|
|
|
|
"execution": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"iopub.execute_input": "2026-05-12T14:05:48.211278Z",
|
|
|
|
|
|
"iopub.status.busy": "2026-05-12T14:05:48.210791Z",
|
|
|
|
|
|
"iopub.status.idle": "2026-05-12T14:05:48.950554Z",
|
|
|
|
|
|
"shell.execute_reply": "2026-05-12T14:05:48.949277Z"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"outputs": [
|
|
|
|
|
|
{
|
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
|
"text": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"n_steps stocké : 201 (snapshots)\n",
|
|
|
|
|
|
"n_particles : 500\n",
|
|
|
|
|
|
"Moyenne initiale : -8.527e-17\n",
|
|
|
|
|
|
"Moyenne finale : -1.148e-02\n",
|
|
|
|
|
|
"Variance init : 0.335\n",
|
|
|
|
|
|
"Variance finale : 0.039\n"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
2026-05-12 16:07:42 +02:00
|
|
|
|
},
|
2026-05-12 12:18:14 +02:00
|
|
|
|
{
|
|
|
|
|
|
"data": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"image/png": "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ygshaskjHSFEHeFwmLFjxzJixAjuuOMOQqEQNpsNgPvuu49Ro0bx05/+FJ/Px8aNG3nsscd49913Wb58OT179myy7hUrVjB+/HgsFgtXXXUVxcXFbNy4kYcffpiFCxeydOnS3I1gIBBg7NixrFq1irPPPpurrroKvV7PqlWrmDdvHj/72c84//zzSaVS3HPPPfzoRz9i7NixABQUFOSOecUVV/D0009z6qmncs899xAOh3nssceYOnUqTz31FJdddtkhX5NgMMiYMWPYtGkTl19+OUOHDsXv9/Ovf/2L0aNH89FHH3HCCScAcM899/D73/+e6dOnM2vWLAwGAzt27OCdd96htLSUwsLCZrXPpEmTKCkpYe7cuUyfPh2AZDLJ008/zfe+971cWx3o9ttv5w9/+AM9e/bk+uuvp0uXLuzYsYP//ve/7Nq1C5/PV6f8+vXrmTJlCuXl5cybNy93s7e/xx9/nFmzZjF8+HB++9vf4nK5+Pjjj7nllltYvnw5//nPf3JlX331VVavXs0FF1xAcXExgUCAF198kauuuory8nJuuummevVffvnlKIrCz3/+czQaDf/4xz+47LLL6NmzJyeffHKzrletWbNmcfPNN/P888/z4x//uM57tTfwtT0hm/L3v/8dt9vNrFmzKCwsZOfOncydO5cJEybwwQcf5KYkqKysZMKECWSzWX784x/TvXt3/H4/q1at4oMPPsj11MhkMkyfPp1FixYxffp0fvazn7F3714efvhhxowZw9tvv82ECRPQaDT88Ic/5O677+bjjz/m1FNPrRNX7dyrssiNEEKIo8mVV17J7Nmzeeyxx7j66qvrvPfZZ5+xZs0aLrnkErxeL9Dye9GdO3cybtw4zjvvPP74xz+yd+/eJuNpaf27d+/mtNNO45xzzuFPf/oTGzdu5G9/+xvnnnsuq1atqtMb74orruCpp55i+PDh3HjjjeTn57N582bmzZvHnXfemRsqPHv2bO68804mTJjA7NmzMZvNzJ8/n2uuuYZNmzZx7733HvS6tuQeDWqmzxk3blzufnndunU89NBD7N27l/POO4+HHnqIa665Brvdzr/+9a/cQ+QDp2LatWsXEyZM4JxzzuG+++5j3bp1PPLII3zyyScsW7aMzp07HzT2119/nf/7v//j2muv5ZprrmlyuqNgMMjYsWNz9+IjR45kzZo1nHXWWQf9XtIcV155JU899RTnnnsu3//+9wGYN28e5513Hg8//DDXXnvtYR9DiGOaKoQ47ixatEgF1Msvv7zO9nHjxqmAevPNNze4Xzgcrrdt9erVql6vV6+77rp6dRUXF9fZNmzYMLV79+5qZWVlne2ff/65qtVq1Tlz5uS2/fSnP1UB9YEHHqh3zEwmU+9cnnjiiXrlFi5cqALqtGnT1HQ6ndteVlam5ufnqy6XSw2FQk3G3NQ1+eUvf6nq9Xr1s88+q7Pd7/erXbp0UcePH5/bNnz4cLV///716miucePGqVqtVlVVVb3jjjtUvV6vlpWVqaqqqi+88IIKqJ988knuevzhD3/I7bt06VIVUE8++eQG23D/61lcXKw6nU7V6/WqTqdT/fDDDxuMZ8+eParJZFJnzJihZrPZOu/df//9KqAuXrw4t62x444dO1Z1Op1qMpnMbZ89e3au3faPbce
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"text/plain": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"<Figure size 1320x440 with 2 Axes>"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"source": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"N, T, n_steps = 500, 1.0, 200\n",
|
|
|
|
|
|
"theta, sigma = 1.5, 0.3\n",
|
|
|
|
|
|
"x0 = np.linspace(-1.0, 1.0, N).tolist() # mean = 0\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"res = opt.mean_reverting_mckean_vlasov(x0, theta, sigma, n_steps, T, 42)\n",
|
|
|
|
|
|
"n_t = res['n_steps']\n",
|
|
|
|
|
|
"n_part = res['n_particles']\n",
|
|
|
|
|
|
"paths = np.array(res['paths_flat']).reshape(n_t, n_part)\n",
|
|
|
|
|
|
"ts = np.array(res['time_grid'])\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"mean = paths.mean(axis=1)\n",
|
|
|
|
|
|
"var = paths.var(axis=1)\n",
|
|
|
|
|
|
"print(f\"n_steps stocké : {n_t} (snapshots)\")\n",
|
|
|
|
|
|
"print(f\"n_particles : {n_part}\")\n",
|
|
|
|
|
|
"print(f\"Moyenne initiale : {mean[0]:.3e}\")\n",
|
|
|
|
|
|
"print(f\"Moyenne finale : {mean[-1]:.3e}\")\n",
|
|
|
|
|
|
"print(f\"Variance init : {var[0]:.3f}\")\n",
|
|
|
|
|
|
"print(f\"Variance finale : {var[-1]:.3f}\")\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"fig, axes = plt.subplots(1, 2, figsize=(12, 4))\n",
|
|
|
|
|
|
"for i in range(0, n_part, 25):\n",
|
|
|
|
|
|
" axes[0].plot(ts, paths[:, i], alpha=0.4, lw=0.7)\n",
|
|
|
|
|
|
"axes[0].plot(ts, mean, 'k-', lw=2, label='moyenne empirique')\n",
|
|
|
|
|
|
"axes[0].set_xlabel('t'); axes[0].set_ylabel(r'$X_t^i$')\n",
|
|
|
|
|
|
"axes[0].set_title(\"Trajectoires McKean–Vlasov\")\n",
|
|
|
|
|
|
"axes[0].legend()\n",
|
|
|
|
|
|
"axes[1].plot(ts, var, lw=2, color='C2')\n",
|
|
|
|
|
|
"axes[1].set_xlabel('t'); axes[1].set_ylabel(r'Var($X_t$)')\n",
|
|
|
|
|
|
"axes[1].set_title(\"Variance empirique\")\n",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"fig.tight_layout(); plt.show()\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
2026-05-12 16:07:42 +02:00
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
|
"id": "9f7da718",
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
"**Résultat attendu.** $|\\bar X_t - 0|$ très petit, variance qui\n",
|
|
|
|
|
|
"décroît vers une borne stationnaire.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Lecture du graphique.** Faisceau qui se contracte autour de la\n",
|
|
|
|
|
|
"moyenne ; variance qui diminue.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Conclusion.** Le solveur reproduit la concentration mean-field.\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "markdown",
|
|
|
|
|
|
"id": "e2f69220",
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"source": [
|
|
|
|
|
|
"## Cellule 2 — Exemple concret : dynamique d'opinion polarisée\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Modèle.** Modèle de DeGroot continu : opinions initialement\n",
|
|
|
|
|
|
"bimodales (deux groupes opposés). La dynamique de champ moyen\n",
|
|
|
|
|
|
"détruit progressivement la polarisation.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Équation pivot.**\n",
|
|
|
|
|
|
"$$dX_t^i = \\theta\\,(\\bar X_t - X_t^i)\\,dt + \\sigma\\,dW_t^i.$$\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Ce que la cellule vérifie.** Une distribution initiale bimodale\n",
|
|
|
|
|
|
"fusionne en distribution unimodale centrée sur $\\bar X_0$.\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
2026-05-12 12:18:14 +02:00
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "code",
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"execution_count": 3,
|
|
|
|
|
|
"id": "a9afa9b3",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"metadata": {
|
|
|
|
|
|
"execution": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"iopub.execute_input": "2026-05-12T14:05:48.954428Z",
|
|
|
|
|
|
"iopub.status.busy": "2026-05-12T14:05:48.954151Z",
|
|
|
|
|
|
"iopub.status.idle": "2026-05-12T14:05:49.953468Z",
|
|
|
|
|
|
"shell.execute_reply": "2026-05-12T14:05:49.952156Z"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"outputs": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
{
|
|
|
|
|
|
"name": "stdout",
|
|
|
|
|
|
"output_type": "stream",
|
|
|
|
|
|
"text": [
|
|
|
|
|
|
"Variance t=0 : 1.033\n",
|
|
|
|
|
|
"Variance t=mid : 0.025\n",
|
|
|
|
|
|
"Variance t=T : 0.007\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
2026-05-12 12:18:14 +02:00
|
|
|
|
{
|
|
|
|
|
|
"data": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"image/png": "iVBORw0KGgoAAAANSUhEUgAABZIAAAGvCAYAAADBvyALAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAABDrAAAQ6wFQlOh8AACStUlEQVR4nOzdd3hUZfr/8c/MpIdUEiHUAKLgUi0UlRYExFVAVOyCCC4W/CnYwAKoNBfQtbDYWdRVFwVdEZEiqCyiX1kbJQrSAkTahExgSCAz5/cHZjZDJpM2kyl5v66Li5zntPuec848cOec55gMwzAEAAAAAAAAAEA5zIEOAAAAAAAAAAAQ3CgkAwAAAAAAAAC8opAMAAAAAAAAAPCKQjIAAAAAAAAAwCsKyQAAAAAAAAAArygkAwAAAAAAAAC8opAMAAAAAAAAAPCKQjIAAAAAAAAAwCsKyQAAAAAAAAAArygkAwAAAAAAAAC8opAMAAAAwOdWrFihKVOmaN++fYEOBQAAAD5AIRkAANQZmZmZ6t27d6DDqLNGjBghk8nkt+2bTCaNGDHCb9sPtDVr1shkMmn+/PlBv/3vvvtOgwcPVmRkpBo1alTz4MLAzp07ZTKZNHny5ECHAgAAUC0UkgEAYa2oqEgvvfSSLrnkEqWnpysyMlKpqanq0aOHnn76aeXl5QU6RARYZmZmWBcfw8nOnTs1efJk/fDDD4EOBV7s3btXgwcP1gMPPKCJEycGOhwAAAD4SESgAwAAwF92796tK664Qj/99JMuvvhi3XfffcrIyNCRI0e0bt06PfbYY/rggw/0zTffBDpUAJWwc+dOTZkyRZmZmerUqVOZ+cePH5fFYqn9wMJEz549dfz4cUVGRtZoO99++62eeOIJ3XbbbT6KDAAAAMGAQjIAICwVFRXp8ssv1+bNm/X222/rhhtucJt/3333ac+ePXrhhRcCFKH/nDhxQk6nUzExMYEOBahVnPPVY7PZlJiYKLPZ7JPP8Morr/RBVMGloKBACQkJgQ4DAAAgoBjaAgAQll5//XX9/PPPuvfee8sUkUs0adJEM2bMcGvLzs7WddddpwYNGig6OlotW7bU/fffL5vN5rbc/PnzZTKZtHr1aj377LM666yzFB0drRYtWmjOnDluy950002yWCzKyckpE4PdbldSUpJ69Ojh1v7999/r6quv1hlnnKGoqCi1bNlSDz/8sOx2u9tyJWPOHj58WLfffrsyMjIUGxur9evXS5Jyc3N18803q379+oqPj1ePHj305ZdfljtW7W+//aYRI0aoUaNGioqKUpMmTXTnnXfq0KFDbstNnjxZJpNJv/76qx5//HE1b95c0dHRatu2rd5++22Pn/dPP/2k66+/3rXtxo0ba/DgwdqwYUO1YvBmw4YNuuSSSxQfH6+UlBRdddVV2rlzZ6XW9TaOaclxX7NmjautOp9FZY9veXr37q3MzEzt2rVLV111lVJSUhQfH69+/frpv//9b5nlnU6nnnvuOXXs2FGxsbFKTExUVlaWVqxYUWbZknGkf/zxR/Xv318JCQlKSkrS0KFD9dtvv1X4eZSo7HjI2dnZuuuuu9SuXTslJSUpNjZW7du316xZs+RwOFzLTZ48WX369JEk3XrrrTKZTDKZTG5jXpc3RvLbb7+trl27Kj4+XvHx8erWrZvefffdMsuVfK6///6767qJjY1Vz5499d1331WYi+Q+zvDf//53tW3bVjExMcrMzNTkyZNVXFzs8TOozPeOJ06nU9OmTVPv3r2VkZHhuraGDx+u3bt3l1m+5DNas2aNevfurcTERHXs2LFM7CUMw9Dzzz+vzp07KykpSfXq1VOrVq10ww03KDc3123bVbl2CwoK9Mgjj+jss89WdHS0UlNTNWTIEP30008V5rxy5UqZTCZNnTrV4/xRo0bJZDJp27ZtVd5f6c/gpZdeUocOHRQTE6OxY8dKkvbs2aPbb79dLVq0UExMjNLS0nTeeedp2rRpFcbtzQcffKBevXopMTFRsbGx6ty5s1599dUqbeOrr77S4MGDlZ6erujoaDVr1kw33HBDmet22bJl6tOnj2tfnTp10osvvijDMNyWK7mGbTabxo4dq4yMDEVHR+vcc8/VZ599Vmb/y5YtU1ZWls444wzFxMSoSZMmGjhwoL766iu35apzLN58803XsWjcuLEmTpzo9v0gVe7YeBsHvOS7vHRf4a/jDQBAqOKOZABAWPrXv/4lSRozZkyl1/nhhx/Us2dPFRcX684771TLli21du1azZ49W6tWrdJ//vMfxcXFua0zceJE2Ww23XrrrapXr54WLFig8ePHq1GjRrruuusknfrP+Ntvv60FCxbokUcecVt/0aJFstlsbsWvZcuWaciQIWratKnGjh2rBg0a6Mcff9ScOXP0n//8R6tXr1ZEhHsXfskll6h+/fp6+OGH5XQ61bBhQ+Xn56tHjx7avn27Ro4cqfPOO0/Z2dn685//rFatWnnMv3fv3oqLi9PIkSPVvHlzbd26VX//+9+1atUqffvtt0pKSnJbZ/jw4TKZTLrnnntkNps1d+5c3XTTTWrVqpW6devmWu7TTz/VlVdeqaioKN12221q06aNDh8+rC+++ELr1q3TeeedV+0YTvff//5XPXv2lMVi0dixY9W0aVMtX75cvXv31rFjx7yuWxOV/Syqc3w9OXbsmHr16qXOnTvrqaeeUk5OjubOnauePXvqP//5j6s4KJ06B998801ddNFFmjZtmo4ePapXX31VAwYM0IIFC3TTTTe5bXvPnj3q06ePBg0apKefflpbtmzRvHnztG7dOm3YsEGNGzf22ee2Zs0arV69WpdffrlatGihwsJCLV26VA888IC2b9+uuXPnSpKGDh2qkydPatq0abr99ttdv3xp0KCB1+0//vjjevLJJ9W+fXtNmjRJhmHorbfe0vXXX6/t27eXGcP32LFj6tGjh8477zw9+eST2r9/v5555hkNHDhQ27dvr/RdqS+88IL27NmjMWPGKDU1VR999JGmTJmi3377TW+++aZruep875R24sQJzZw5U0OHDtWf//xnJSUl6aefftLrr7+uVatW6aefflJqaqrbOt99953ef/99jRw5UjfccIMKCgrK3f60adP06KOP6rLLLtOoUaMUFRWl3bt3a9myZdq3b58yMjJceVT22rXZbLr44ou1bds2DR8+XB07dlReXp5eeeUVde/eXV999ZXOPffccmPKyspS06ZN9Y9//KPMd6rdbtfChQt18cUX68wzz6z2/v72t79p//79Gj16tJo0aaKEhAQVFxerX79+ysnJ0R133KE2bdro6NGjys7O1ueff17t8aAnTZqkJ554Qn369NGkSZMUGxurzz77TKNHj9a2bdvK/MLTk1dffVV/+ctflJ6erlGjRqlFixb6/ffftWzZMm3cuNH1nf/aa69p9OjRatasmR544AHVq1dP77//vu6++279+OOPevnll8tse8CAAUpOTtaECRNkt9v17LPPatCgQdq6dauaNWsmSfryyy91+eWX65xzztEDDzyg+vXr6/fff9e6dev0/fffu67X6hyLl156SXv37tWoUaOUnp6uRYsWafr06UpMTNTDDz8sSX45Nv463gAAhDQDAIAwVL9+fSMhIaFK6/To0cMwmUzG2rVr3dqnTJliSDKefPJJV9sbb7xhSDI6dOhgFBYWutqPHj1q1K9f3+jevburzeFwGM2aNTNat25dZp99+/Y14uLiDJvNZhiGYRw/ftxo2LCh0aVLF7ftGoZhvP/++4YkY/78+a624cOHG5KM6667znA6nW7LT5w40ZBkvPjii27tixYtMiQZp/8zoFOnTkaLFi2Mw4cPu7V/8803hsViMSZPnuxqmzRpkiHJGDhwoOFwOFztu3fvNiIjI43rr7/e1Xbs2DEjPT3dSEpKMn777bcyn0Hp9asSQ3l69OhhmM1m47vvvnNr/8tf/mJIMnr16uV1/R07dhiSjEmTJpWZV3LcV69e7WqrymdR1eNbnl69ehmSjLvuusut/bvvvjPMZrNbjqtWrXL
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"text/plain": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"<Figure size 1430x418 with 3 Axes>"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"output_type": "display_data"
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"source": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"rng = np.random.default_rng(7)\n",
|
|
|
|
|
|
"N = 600\n",
|
|
|
|
|
|
"half = N // 2\n",
|
|
|
|
|
|
"x0 = np.concatenate([\n",
|
|
|
|
|
|
" rng.normal(-1.0, 0.2, half),\n",
|
|
|
|
|
|
" rng.normal(+1.0, 0.2, N - half),\n",
|
|
|
|
|
|
"]).tolist()\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"res = opt.mean_reverting_mckean_vlasov(x0, theta=2.0, sigma=0.15,\n",
|
|
|
|
|
|
" n_steps=400, t_horizon=2.0, seed=11)\n",
|
|
|
|
|
|
"n_t = res['n_steps']\n",
|
|
|
|
|
|
"n_part = res['n_particles']\n",
|
|
|
|
|
|
"paths = np.array(res['paths_flat']).reshape(n_t, n_part)\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"mid = n_t // 2\n",
|
|
|
|
|
|
"print(f\"Variance t=0 : {paths[0].var():.3f}\")\n",
|
|
|
|
|
|
"print(f\"Variance t=mid : {paths[mid].var():.3f}\")\n",
|
|
|
|
|
|
"print(f\"Variance t=T : {paths[-1].var():.3f}\")\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"fig, axes = plt.subplots(1, 3, figsize=(13, 3.8))\n",
|
|
|
|
|
|
"for ax, idx, label in zip(axes, [0, mid, -1], ['t=0', 't=T/2', 't=T']):\n",
|
|
|
|
|
|
" ax.hist(paths[idx], bins=40, density=True,\n",
|
|
|
|
|
|
" color='C0', edgecolor='white', alpha=0.85)\n",
|
|
|
|
|
|
" ax.set_title(f\"Distribution {label}\")\n",
|
|
|
|
|
|
" ax.set_xlabel('opinion'); ax.set_ylabel('densité')\n",
|
|
|
|
|
|
" ax.set_xlim(-2, 2)\n",
|
|
|
|
|
|
"fig.suptitle(\"Convergence d'une population polarisée vers le consensus\",\n",
|
|
|
|
|
|
" fontsize=12, y=1.02)\n",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"fig.tight_layout(); plt.show()\n"
|
|
|
|
|
|
]
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
"cell_type": "markdown",
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"id": "001ac849",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"metadata": {},
|
|
|
|
|
|
"source": [
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"**Résultat attendu.** L'histogramme bimodal initial fusionne en un\n",
|
|
|
|
|
|
"pic unique centré à $0$.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Lecture du graphique.** Trois snapshots montrent la fusion\n",
|
|
|
|
|
|
"progressive des deux modes.\n",
|
|
|
|
|
|
"\n",
|
|
|
|
|
|
"**Conclusion.** L'attraction par la moyenne (mean-field) détruit la\n",
|
|
|
|
|
|
"polarisation initiale en temps fini — illustration du théorème du\n",
|
|
|
|
|
|
"consensus dans les dynamiques de DeGroot continues.\n"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
]
|
|
|
|
|
|
}
|
|
|
|
|
|
],
|
|
|
|
|
|
"metadata": {
|
|
|
|
|
|
"kernelspec": {
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"display_name": "rhftlab",
|
2026-05-12 12:18:14 +02:00
|
|
|
|
"language": "python",
|
2026-05-12 16:07:42 +02:00
|
|
|
|
"name": "rhftlab"
|
2026-05-12 12:18:14 +02:00
|
|
|
|
},
|
|
|
|
|
|
"language_info": {
|
|
|
|
|
|
"codemirror_mode": {
|
|
|
|
|
|
"name": "ipython",
|
|
|
|
|
|
"version": 3
|
|
|
|
|
|
},
|
|
|
|
|
|
"file_extension": ".py",
|
|
|
|
|
|
"mimetype": "text/x-python",
|
|
|
|
|
|
"name": "python",
|
|
|
|
|
|
"nbconvert_exporter": "python",
|
|
|
|
|
|
"pygments_lexer": "ipython3",
|
|
|
|
|
|
"version": "3.11.13"
|
|
|
|
|
|
}
|
|
|
|
|
|
},
|
|
|
|
|
|
"nbformat": 4,
|
|
|
|
|
|
"nbformat_minor": 5
|
|
|
|
|
|
}
|