forked from EHV/sejeteralo
Toutes les formules du moteur de tarification : courbes paramétriques palier 1/2, décomposition intégrale (α₁, α₂, β₂), calcul de p₀, résolution cubique Cardano + Newton-Raphson. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
196 lines
8.2 KiB
HTML
196 lines
8.2 KiB
HTML
<!DOCTYPE html>
|
||
<html lang="fr">
|
||
<head>
|
||
<meta charset="UTF-8">
|
||
<title>SejeteralO — Modèle mathématique</title>
|
||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.css">
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/katex.min.js"></script>
|
||
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.16.11/dist/contrib/auto-render.min.js"
|
||
onload="renderMathInElement(document.body, {delimiters:[
|
||
{left:'$$',right:'$$',display:true},
|
||
{left:'$',right:'$',display:false}
|
||
]})"></script>
|
||
<style>
|
||
body { font-family: 'Georgia', serif; max-width: 860px; margin: 3rem auto; padding: 0 2rem; color: #1a1a2e; background: #fafaf8; line-height: 1.7; }
|
||
h1 { font-size: 1.6rem; border-bottom: 2px solid #3a5a8a; padding-bottom: .5rem; color: #1a2e5a; }
|
||
h2 { font-size: 1.2rem; color: #2a4a7a; margin-top: 2.5rem; border-left: 4px solid #7aacdc; padding-left: .8rem; }
|
||
h3 { font-size: 1rem; color: #3a5a8a; margin-top: 1.8rem; }
|
||
.block { background: #f0f4fb; border-radius: 10px; padding: 1.2rem 1.5rem; margin: 1rem 0; }
|
||
.cp-grid { display: grid; grid-template-columns: 1fr 1fr; gap: .3rem 2rem; font-size: .92rem; }
|
||
table { border-collapse: collapse; width: 100%; font-size: .92rem; margin: 1rem 0; }
|
||
th { background: #3a5a8a; color: #fff; padding: .4rem .8rem; text-align: left; }
|
||
td { padding: .35rem .8rem; border-bottom: 1px solid #dde; }
|
||
tr:nth-child(even) td { background: #f4f7fc; }
|
||
.note { font-size: .88rem; color: #556; font-style: italic; margin-top: .5rem; }
|
||
code { background: #e8ecf5; padding: .1rem .35rem; border-radius: 4px; font-size: .88rem; font-family: monospace; }
|
||
.sep { border: none; border-top: 1px dashed #ccd; margin: 2.5rem 0; }
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<h1>SejeteralO — Modèle tarifaire Bézier</h1>
|
||
<p>Tarification participative de l'eau : les citoyens façonnent une courbe prix/volume via des points de contrôle Bézier ; le prix d'inflexion $p_0$ est calculé automatiquement pour équilibrer les recettes de la commune.</p>
|
||
|
||
<h2>1. Paramètres</h2>
|
||
|
||
<h3>Paramètres structurels (fixés par la commune)</h3>
|
||
<table>
|
||
<tr><th>Paramètre</th><th>Signification</th></tr>
|
||
<tr><td>$v_\text{inf}$</td><td>Volume d'inflexion — frontière entre les deux paliers (m³/an)</td></tr>
|
||
<tr><td>$v_\text{max}$</td><td>Volume maximum de la courbe (m³/an)</td></tr>
|
||
<tr><td>$p_\text{max}$</td><td>Prix au m³ en $v_\text{max}$ (€)</td></tr>
|
||
<tr><td>$R$</td><td>Recettes cibles totales (€/an)</td></tr>
|
||
<tr><td>$\text{abo}_P, \text{abo}_S$</td><td>Abonnements résidence principale / secondaire (€/an)</td></tr>
|
||
</table>
|
||
|
||
<h3>Paramètres de forme (votés par les citoyens, 6 valeurs dans $[0,1]$)</h3>
|
||
<table>
|
||
<tr><th>Param.</th><th>Rôle géométrique</th></tr>
|
||
<tr><td>$a$</td><td>Hauteur du 2ᵉ point de contrôle du palier 1 (courbure initiale)</td></tr>
|
||
<tr><td>$b$</td><td>Position horizontale du 3ᵉ point de contrôle du palier 1</td></tr>
|
||
<tr><td>$c$</td><td>Position horizontale du 1ᵉʳ point de contrôle du palier 2</td></tr>
|
||
<tr><td>$d$</td><td>Position horizontale du 2ᵉ point de contrôle du palier 2</td></tr>
|
||
<tr><td>$e$</td><td>Hauteur du 2ᵉ point de contrôle du palier 2</td></tr>
|
||
</table>
|
||
|
||
<h3>Variable calculée</h3>
|
||
<p>$p_0$ — prix au m³ à l'inflexion — est toujours déduit de l'équilibre de recettes (§4).</p>
|
||
|
||
<hr class="sep">
|
||
|
||
<h2>2. Courbe Bézier cubique par paliers</h2>
|
||
|
||
<p>La courbe prix/volume est définie de façon paramétrique : pour $t \in [0,1]$, on obtient un point $(v(t),\, p(t))$.</p>
|
||
|
||
<h3>Palier 1 — $v \in [0,\, v_\text{inf}]$</h3>
|
||
|
||
<div class="block">
|
||
$$v_1(t) = v_\text{inf}\,\bigl[(1-3b)\,t^3 + 3b\,t^2\bigr]$$
|
||
$$p_1(t) = p_0\,\bigl[(3a-2)\,t^3 + (3-6a)\,t^2 + 3a\,t\bigr]$$
|
||
</div>
|
||
|
||
<p>Points de contrôle :</p>
|
||
<div class="cp-grid">
|
||
<span>$P_1 = (0,\; 0)$</span>
|
||
<span>$P_2 = (0,\; a\,p_0)$</span>
|
||
<span>$P_3 = (b\,v_\text{inf},\; p_0)$</span>
|
||
<span>$P_4 = (v_\text{inf},\; p_0)$</span>
|
||
</div>
|
||
|
||
<h3>Palier 2 — $v \in [v_\text{inf},\, v_\text{max}]$</h3>
|
||
|
||
<p>Posons $w_\text{max} = v_\text{max} - v_\text{inf}$.</p>
|
||
|
||
<div class="block">
|
||
$$v_2(t) = v_\text{inf} + w_\text{max}\,\Bigl[\bigl(3(c+d-cd)-2\bigr)\,t^3 + 3(1-2c-d+cd)\,t^2 + 3c\,t\Bigr]$$
|
||
$$p_2(t) = p_0 + (p_\text{max}-p_0)\,\bigl[(1-3e)\,t^3 + 3e\,t^2\bigr]$$
|
||
</div>
|
||
|
||
<p>Points de contrôle (partagent $P_4$ avec le palier 1) :</p>
|
||
<div class="cp-grid">
|
||
<span>$P_4 = (v_\text{inf},\; p_0)$</span>
|
||
<span>$P_5 = (v_\text{inf}+c\,w_\text{max},\; p_0)$</span>
|
||
<span>$P_6 = \bigl(v_\text{inf}+w_\text{max}(1-d+cd),\; p_0+e(p_\text{max}-p_0)\bigr)$</span>
|
||
<span>$P_7 = (v_\text{max},\; p_\text{max})$</span>
|
||
</div>
|
||
|
||
<hr class="sep">
|
||
|
||
<h2>3. Facture d'un foyer</h2>
|
||
|
||
<p>La facture annuelle d'un foyer de consommation $v$ est :</p>
|
||
|
||
<div class="block">
|
||
$$\text{Bill}(v) = \text{abo} + \int_0^v p(u)\,\mathrm{d}u$$
|
||
</div>
|
||
|
||
<p>L'intégrale est calculée analytiquement par décomposition :</p>
|
||
|
||
<div class="block">
|
||
$$\int_0^v p(u)\,\mathrm{d}u = (\alpha_1 + \alpha_2)\,p_0 + \beta_2$$
|
||
</div>
|
||
|
||
<p>où les trois coefficients dépendent uniquement de la forme de la courbe (paramètres $a$–$e$, $v_\text{inf}$, $v_\text{max}$, $p_\text{max}$) et de la consommation $v$, mais <em>pas</em> de $p_0$. Cela rend le calcul de $p_0$ linéaire.</p>
|
||
|
||
<h3>Résolution cubique — inversion de la courbe</h3>
|
||
|
||
<p>Pour évaluer les coefficients en un volume $v$ donné, on cherche $T$ tel que $v_i(T) = v$.</p>
|
||
|
||
<p>Palier 1 ($v \leq v_\text{inf}$) — résoudre en $T_1 \in [0,1]$ :</p>
|
||
<div class="block">
|
||
$$(1-3b)\,T_1^3 + 3b\,T_1^2 - \frac{v}{v_\text{inf}} = 0$$
|
||
</div>
|
||
|
||
<p>Palier 2 ($v > v_\text{inf}$) — posons $w = v - v_\text{inf}$, résoudre en $T_2 \in [0,1]$ :</p>
|
||
<div class="block">
|
||
$$\bigl(3(c+d-cd)-2\bigr)\,T_2^3 + 3(1-2c-d+cd)\,T_2^2 + 3c\,T_2 - \frac{w}{w_\text{max}} = 0$$
|
||
</div>
|
||
|
||
<p class="note">Ces cubiques sont résolues par la formule de Cardano avec affinement Newton-Raphson.</p>
|
||
|
||
<h3>Coefficient $\alpha_1$ — intégrale du palier 1</h3>
|
||
|
||
<div class="block">
|
||
$$\alpha_1(T_1) = 3\,v_\text{inf}\left[
|
||
\frac{-9ab+3a+6b-2}{6}\,T_1^6
|
||
+\frac{24ab-6a-13b+3}{5}\,T_1^5
|
||
+\frac{3(-7ab+a+2b)}{4}\,T_1^4
|
||
+2ab\,T_1^3
|
||
\right]$$
|
||
</div>
|
||
|
||
<p class="note">Si $v \leq v_\text{inf}$ : on utilise le $T_1$ résolu ci-dessus. Si $v > v_\text{inf}$ : $\alpha_1 = \alpha_1(1)$ (palier 1 entier).</p>
|
||
|
||
<h3>Coefficients $\alpha_2$ et $\beta_2$ — intégrale du palier 2</h3>
|
||
|
||
<p>Posons l'auxiliaire :</p>
|
||
<div class="block">
|
||
$$u(T_2) =
|
||
\frac{-3cd+9ecd+3c-9ec+3d-9ed+6e-2}{6}\,T_2^6 \\[4pt]
|
||
+\frac{2cd-15ecd-4c+21ec-2d+15ed-12e+2}{5}\,T_2^5 \\[4pt]
|
||
+\frac{6ecd+c-15ec-6ed+6e}{4}\,T_2^4
|
||
+ec\,T_2^3$$
|
||
</div>
|
||
|
||
<p>Alors :</p>
|
||
<div class="block">
|
||
$$\alpha_2 = (v - v_\text{inf}) - 3\,u(T_2)\,w_\text{max}$$
|
||
$$\beta_2 = 3\,p_\text{max}\,w_\text{max}\,u(T_2)$$
|
||
</div>
|
||
|
||
<p class="note">Si $v \leq v_\text{inf}$ : $\alpha_2 = \beta_2 = 0$.</p>
|
||
|
||
<hr class="sep">
|
||
|
||
<h2>4. Équilibre de recettes — calcul de $p_0$</h2>
|
||
|
||
<p>En substituant la décomposition $(\alpha_1+\alpha_2)\,p_0+\beta_2$ dans la somme des factures :</p>
|
||
|
||
<div class="block">
|
||
$$R = \sum_{i} \text{abo}_i + \sum_{i}\bigl[(\alpha_{1,i}+\alpha_{2,i})\,p_0 + \beta_{2,i}\bigr]$$
|
||
</div>
|
||
|
||
<p>Comme les $\alpha$ et $\beta$ ne dépendent pas de $p_0$, on obtient directement :</p>
|
||
|
||
<div class="block">
|
||
$$\boxed{p_0 = \frac{R - \displaystyle\sum_i \text{abo}_i - \displaystyle\sum_i \beta_{2,i}}{\displaystyle\sum_i (\alpha_{1,i} + \alpha_{2,i})}}$$
|
||
</div>
|
||
|
||
<p class="note">$p_0$ est calculé une fois par évaluation de la courbe. Si $\sum\alpha = 0$ (tous les foyers consomment 0), on pose $p_0 = 0$.</p>
|
||
|
||
<hr class="sep">
|
||
|
||
<h2>5. Résumé du pipeline de calcul</h2>
|
||
<ol>
|
||
<li>Les citoyens placent des points de contrôle → paramètres $(a,b,c,d,e,v_\text{inf})$.</li>
|
||
<li>Pour chaque foyer $i$, calculer $\alpha_{1,i}$, $\alpha_{2,i}$, $\beta_{2,i}$ par inversion cubique.</li>
|
||
<li>Calculer $p_0$ par la formule d'équilibre.</li>
|
||
<li>Facture de chaque foyer : $\text{Bill}_i = \text{abo}_i + (\alpha_{1,i}+\alpha_{2,i})\,p_0 + \beta_{2,i}$.</li>
|
||
<li>Vérification : $\sum_i \text{Bill}_i = R$ (à précision numérique).</li>
|
||
</ol>
|
||
|
||
<p class="note">Sources : <code>backend/app/engine/pricing.py</code> · <code>backend/app/engine/integrals.py</code> · <code>frontend/app/utils/bezier-math.ts</code></p>
|
||
|
||
</body>
|
||
</html>
|