Created
March 25, 2026 23:56
-
-
Save ofaurax/f3903c7817d78c87a93bb6f0f52c151d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "cells": [ | |
| { | |
| "cell_type": "markdown", | |
| "id": "446c78b0", | |
| "metadata": {}, | |
| "source": [ | |
| "# Estimation du report des voix St Max 1er vers 2nd tour\n", | |
| "\n", | |
| "## Méthodologie\n", | |
| "* On a 15 bureaux différents, qui ont chacun des scores différents\n", | |
| "* On a les scores du 1er tour (Garello=G1, Molina=M1, etc. y compris nuls-nlancs et abstention)\n", | |
| "* On a les scores du second tour Garello (G2), Molina (M2), les nuls-blancs et l'abstention regroupés en A2\n", | |
| "* On différencie le vote Decanis D1, du reste des autres listes R1\n", | |
| "* On cherche à trouver la fonction F(score 1er tour) = score 2nd tour\n", | |
| "\n", | |
| "## Hypothèses\n", | |
| "* On considère que Garello et Molina ont gardé leurs électeurs, c'est-à-dire `G2 = G1 + ...` et `M2 = M1 + ...`\n", | |
| "* D1 se reporte dans G2 (D1G2), M2 (D1M2) et dans A2 (D1A2) de manière linéaire: D1G2 est une fraction fixe de D1.\n", | |
| "* R1 idem. On considère R1 comme une grandeur homogène comme étant les votants non-Garello, non-RN, non-Decanis.\n", | |
| "* `G2 = G1 + D1 * D1G2 + R1 * R1G2`, idem pour M2 avec D1M2 et R1G2\n", | |
| "* Si on a D1G2 et D1M2, on en déduit D1A2 puisque la somme des 3 fait 1 (100%)\n", | |
| "* On connaît G1 et G2 pour 15 bureaux, l'objectif est de trouver D1G2 et R1G2 qui minimise l'erreur entre le G2 calculé (G2c) et le G2 connu" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 1, | |
| "id": "906e0024", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [ | |
| "# G1[n] correspond au bureau n, on met la G1[n] à 0\n", | |
| "G1 = [0, 172, 216, 170, 201, 227, 155, 183, 188, 148, 227, 204, 177, 166, 215, 222]\n", | |
| "D1 = [0, 106, 96,55,83,89,88,87,89,77,88,83,80,79,100,88]\n", | |
| "R1 = [0, 153, 143,114,148,148,108,145,116,134,154,178,138,110,148,143]\n", | |
| "G2 = [0, 291, 358,265,367,350,247,294,275,254,341,355,301,305,358,347]" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 2, | |
| "id": "be000e2b", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| " 0% 90% -35.0\n", | |
| " 10% 80% 44.2\n", | |
| " 20% 80% -84.6\n", | |
| " 30% 70% -5.4\n", | |
| " 40% 60% 73.8\n", | |
| " 50% 60% -55.0\n", | |
| " 60% 50% 24.2\n", | |
| " 80% 40% -25.4\n", | |
| " 90% 30% 53.8\n", | |
| " 100% 30% -75.0\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "for d1g2 in range(11): # 1 .. 10 => 10% .. 100%\n", | |
| " for r1g2 in range(11):\n", | |
| " diff = 0.0\n", | |
| " for bureau in range(1, 16):\n", | |
| " g2c = G1[bureau] + D1[bureau] * d1g2/10 + R1[bureau] * r1g2/10\n", | |
| " d = G2[bureau] - g2c\n", | |
| " diff += d\n", | |
| " if diff < 100 and diff > -100:\n", | |
| " print(\"{:4}% {:4}% {:7.7}\".format(d1g2*10, r1g2*10, diff))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "c86d2f30", | |
| "metadata": {}, | |
| "source": [ | |
| "On voit que pour minimiser la différence, chaque baisse de la part de D1 doit être compensé par la part de R1.\n", | |
| "On fait le même calcul pour Molina" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 3, | |
| "id": "8efddef1", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| " 0% 60% -5.0\n", | |
| " 10% 50% 74.2\n", | |
| " 20% 50% -54.6\n", | |
| " 30% 40% 24.6\n", | |
| " 50% 30% -25.0\n", | |
| " 60% 20% 54.2\n", | |
| " 70% 20% -74.6\n", | |
| " 80% 10% 4.6\n", | |
| " 90% 0% 83.8\n", | |
| " 100% 0% -45.0\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "M1 = [0, 151, 152,134,208,205,158,219,169,142,215,266,158,155,212,185]\n", | |
| "M2 = [0,262,251,180,262,296,263,308,255,222,305,339,244,205,294,286]\n", | |
| "for d1m2 in range(11):\n", | |
| " for r1m2 in range(11):\n", | |
| " diff = 0.0\n", | |
| " for bureau in range(1, 16):\n", | |
| " m2c = M1[bureau] + D1[bureau] * d1m2/10 + R1[bureau] * r1m2/10\n", | |
| " d = M2[bureau] - m2c\n", | |
| " diff += d\n", | |
| " if diff < 100 and diff > -100:\n", | |
| " print(\"{:4}% {:4}% {:7.7}\".format(d1m2*10, r1m2*10, diff))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "markdown", | |
| "id": "0a9e05fc", | |
| "metadata": {}, | |
| "source": [ | |
| "On sait que `d1g2 + d1m2 + d1a2 = 100` (idem `r1*`), donc on peut faire varier d1a2 et utiliser `d1m2 = 100 - d1g2 - d1a2` pour calculer la diff globale des 2 boucles, et idem pour `r1*`.\n", | |
| "Comme la participation est presque la même et que les nuls-blancs augmentent de seulement 2%, on néglige la fuite vers l'absentation, d'où `d1a2 = 0% ou 10%`" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": 4, | |
| "id": "bf86db3d", | |
| "metadata": {}, | |
| "outputs": [ | |
| { | |
| "name": "stdout", | |
| "output_type": "stream", | |
| "text": [ | |
| "De Decanis Réserve Score\n", | |
| "vers Gar Abs Mol | Gar Abs Mol | (meilleur qd petit)\n", | |
| " 0% 10% 90% | 80% 10% 10% | 392.4\n", | |
| " 0% 0% 100% | 90% 10% 0% | 377.8\n", | |
| " 0% 10% 90% | 90% 0% 10% | 397.0\n", | |
| " 10% 0% 90% | 80% 10% 10% | 371.4\n", | |
| " 10% 10% 80% | 80% 10% 10% | 375.4\n", | |
| " 20% 10% 70% | 70% 10% 20% | 377.8\n", | |
| " 30% 0% 70% | 70% 10% 20% | 376.2\n" | |
| ] | |
| } | |
| ], | |
| "source": [ | |
| "print(\"De {:18} {:18} {}\".format(\"Decanis\", \"Réserve\", \"Score\"))\n", | |
| "print(\"vers {:4} {:4} {:4} | {:4} {:4} {:4}| {}\".format(\"Gar\", \"Abs\", \"Mol\",\"Gar\", \"Abs\", \"Mol\", \"(meilleur qd petit)\"))\n", | |
| "for d1g2 in range(11): # 1 .. 10 => 10% .. 100%\n", | |
| " for r1g2 in range(11):\n", | |
| " for d1a2 in range(2):\n", | |
| " d1m2 = 10 - d1g2 - d1a2\n", | |
| " if d1m2 < 0:\n", | |
| " continue\n", | |
| " for r1a2 in range(2):\n", | |
| " r1m2 = 10 - r1g2 - r1a2\n", | |
| " if r1m2 < 0:\n", | |
| " continue\n", | |
| " diff = 0.0\n", | |
| " for bureau in range(1, 16):\n", | |
| " g2c = G1[bureau] + D1[bureau] * d1g2/10 + R1[bureau] * r1g2/10\n", | |
| " d = G2[bureau] - g2c\n", | |
| " diff += abs(d)\n", | |
| " m2c = M1[bureau] + D1[bureau] * d1m2/10 + R1[bureau] * r1m2/10\n", | |
| " d = M2[bureau] - m2c\n", | |
| " diff += abs(d)\n", | |
| " if diff < 400:\n", | |
| " print(\" {:4}% {:4}% {:4}% | {:4}% {:4}% {:4}% | {:7.7}\".format(\n", | |
| " d1g2*10, d1a2*10, d1m2*10, r1g2*10, r1a2*10, r1m2*10, diff))" | |
| ] | |
| }, | |
| { | |
| "cell_type": "code", | |
| "execution_count": null, | |
| "id": "d9eeca84", | |
| "metadata": {}, | |
| "outputs": [], | |
| "source": [] | |
| } | |
| ], | |
| "metadata": { | |
| "kernelspec": { | |
| "display_name": "Python 3", | |
| "language": "python", | |
| "name": "python3" | |
| }, | |
| "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.10.18" | |
| } | |
| }, | |
| "nbformat": 4, | |
| "nbformat_minor": 5 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment