Ch. 43 livré et validé (compilation isolée, tests, fusion des registres)
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
40 changed files +1,975 −868
modified
analysis/python/cases/ch37_ml.py
+32 −0
@@ -324,6 +324,34 @@ def exercices(v: pd.DataFrame, comp: dict, secteurs: dict, scen: dict, sh: dict) | ||
| 324 | 324 | r = h.statistiques_ratio(pred, prix); el = np.log(pred / prix) |
| 325 | 325 | e["5"] = {"prix": prix.tolist(), "pred": pred.tolist(), "ratios": (pred / prix).tolist(), "rmse_log": float(np.sqrt(np.mean(el ** 2))), "mdape": float(np.median(np.abs(pred / prix - 1)) * 100), |
| 326 | 326 | "mape": float(np.mean(np.abs(pred / prix - 1)) * 100), **{k: float(val) for k, val in r.items()}} |
| 327 | + # 37.6 (c) : hédonique où les indicatrices de secteur sont remplacées par un polynôme de degré 2 des coordonnées (km) | |
| 328 | + Xh = cas1.matrice(v); km = h.coordonnees_km(v["lat"].to_numpy(), v["lon"].to_numpy()); y = np.log(v["prix_vente"].astype(float).to_numpy()) | |
| 329 | + Xp = Xh.drop(columns=[f"sect_{s_}" for s_ in cas1.SECTEURS[1:]]).copy() | |
| 330 | + Xp["x_km"], Xp["y_km"], Xp["x2"], Xp["y2"], Xp["xy"] = km[:, 0], km[:, 1], km[:, 0] ** 2 / 100, km[:, 1] ** 2 / 100, km[:, 0] * km[:, 1] / 100 | |
| 331 | + n = len(y); pa = plis_aleatoires(n); p_al = valider(Hedonique, "hedo", Xp, None, y, pa) | |
| 332 | + p_sec = np.full(n, np.nan) | |
| 333 | + for sct, f in zip(cas1.SECTEURS, plis_secteurs(v)): | |
| 334 | + tr = np.setdiff1d(np.arange(n), f); m = Hedonique().fit(Xp.iloc[tr], y[tr]); p_sec[f] = m.predict(Xp.iloc[f]) | |
| 335 | + e["6c"] = {"aleatoire": metriques(p_al, y, facteur_duan(p_al, y)), "secteur": metriques(p_sec, y), | |
| 336 | + "biais_secteur": {sct: float(np.mean(p_sec[f] - y[f])) for sct, f in zip(cas1.SECTEURS, plis_secteurs(v))}} | |
| 337 | + # 37.7 (c) : respécification avec des seuils décalés ; (d) : validation imbriquée pour la profondeur du boosting | |
| 338 | + q = v["qualite_1a5"].to_numpy(float); a = v["age"].to_numpy(float); y2 = scen["y"]; Xm = matrice_ml(v) | |
| 339 | + e["7c"] = {} | |
| 340 | + for nom_s, (lo, hi) in {"22-48": (22, 48), "28-42": (28, 42), "25-45 (vrai)": (25, 45)}.items(): | |
| 341 | + X2 = Xh.copy(); X2["prime"] = ((q >= 4) & (a >= 40)).astype(float); X2["mur"] = ((a >= lo) & (a <= hi)).astype(float) | |
| 342 | + p = valider(Hedonique, "hedo", X2, None, y2, pa); r = Hedonique().fit(X2, y2) | |
| 343 | + e["7c"][nom_s] = {**metriques(p, y2, facteur_duan(p, y2)), "coef_mur": float(r.beta[list(X2.columns).index("mur")]), | |
| 344 | + "n_mal_classees": int((X2["mur"] != (((a >= 25) & (a <= 45)).astype(float))).sum())} | |
| 345 | + rng = np.random.default_rng(GRAINE); pred = np.full(n, np.nan); choix = [] | |
| 346 | + for f in pa: | |
| 347 | + tr = np.setdiff1d(np.arange(n), f); inner = np.array_split(rng.permutation(tr), 3); err = {} | |
| 348 | + for d_ in (1, 2, 3): | |
| 349 | + se = 0.0 | |
| 350 | + for fi in inner: | |
| 351 | + tri = np.setdiff1d(tr, fi); m = _boosting(max_depth=d_).fit(Xm.iloc[tri], y[tri]); se += np.sum((m.predict(Xm.iloc[fi]) - y[fi]) ** 2) | |
| 352 | + err[d_] = se | |
| 353 | + d_opt = min(err, key=err.get); choix.append(d_opt); m = _boosting(max_depth=d_opt).fit(Xm.iloc[tr], y[tr]); pred[f] = m.predict(Xm.iloc[f]) | |
| 354 | + e["7d"] = {"profondeurs_choisies": choix, **metriques(pred, y, facteur_duan(pred, y))} | |
| 327 | 355 | # 37.6 : validation par secteur vs aléatoire (chiffres du script) |
| 328 | 356 | e["6"] = {nom: {"aleatoire": comp["metriques"][nom]["aleatoire"]["COD"], "spatial": comp["metriques"][nom]["spatial"]["COD"], "secteur": secteurs["metriques"][nom]["COD"]} |
| 329 | 357 | for nom in ("Hédonique (référence)", "Forêt aléatoire", "Gradient boosting")} |
@@ -404,6 +432,10 @@ def main(verbose: bool = True, complet: bool = True) -> dict: | ||
| 404 | 432 | print(" 37.4", {k: (round(vv, 3) if isinstance(vv, float) else vv) for k, vv in ex["4"].items()}) |
| 405 | 433 | print(" 37.5", {k: (round(vv, 4) if isinstance(vv, float) else vv) for k, vv in ex["5"].items() if k not in ("prix", "pred", "ratios")}, [round(r_, 3) for r_ in ex["5"]["ratios"]]) |
| 406 | 434 | print(" 37.6", ex["6"]); print(" 37.7", ex["7"]) |
| 435 | + print(" 37.1 essais", [(round(x["seuil"], 1), round(x["gain"], 3)) for x in ex["1"]["essais"]]) | |
| 436 | + print(" 37.6c", {k: (round(vv["rmse_log"], 4), round(vv["COD"], 2)) for k, vv in ex["6c"].items() if k != "biais_secteur"}, {k: round(vv, 3) for k, vv in ex["6c"]["biais_secteur"].items()}) | |
| 437 | + print(" 37.7c", {k: (round(vv["rmse_log"], 4), round(vv["COD"], 2), round(vv["coef_mur"], 4), vv["n_mal_classees"]) for k, vv in ex["7c"].items()}) | |
| 438 | + print(" 37.7d", ex["7d"]["profondeurs_choisies"], round(ex["7d"]["rmse_log"], 4), round(ex["7d"]["COD"], 2)) | |
| 407 | 439 | return out |
| 408 | 440 | |
| 409 | 441 | if __name__ == "__main__": |
added
analysis/python/cases/ch45_dossier.py
+274 −0
@@ -0,0 +1,274 @@ | ||
| 1 | +#!/usr/bin/env python3 | |
| 2 | +"""Chapitre 45 — Cas 1 : maison unifamiliale à Gatineau (DONNÉES SYNTHÉTIQUES, propriété fictive) — dossier complet. | |
| 3 | + | |
| 4 | +Ce script N'INVENTE AUCUN CHIFFRE : il importe les fonctions des chapitres de méthode et de la bibliothèque partagée | |
| 5 | + * sélection des comparables : traite.cas1.selection (ch. 16) ; | |
| 6 | + * grille d'ajustements et valeur pondérée : traite.cas1.ajustements_hedoniques + ch17_ajustements.reconcilier (ch. 17) ; | |
| 7 | + * modèle hédonique, prédiction, intervalles : traite.cas1.hedonique / predire / intervalle_prediction, ch18_hedonique.prediction_sujet (ch. 18) ; | |
| 8 | + * mesurage : ch12_mesurage.superficies (ch. 12) ; inspection : ch11_inspection (ch. 11) ; | |
| 9 | + * coût neuf : ch21_cout_neuf (ch. 21) ; dépréciation et valeur par le coût : ch24_depreciation.main (ch. 24) ; | |
| 10 | + * terrain : ch25_terrain (comparaison directe + extraction du ch. 24) (ch. 25) ; | |
| 11 | + * rôle, taxes, mutations : ch09_ratios (ch. 9) ; | |
| 12 | + * réconciliation : ch20_reconciliation.tout (ch. 20), | |
| 13 | +et n'y ajoute que ce qui est propre au dossier : le financement de l'acheteur (traite.finance), les droits de mutation à l'achat, | |
| 14 | +le sommaire du rapport et les exercices. Toute divergence entre un chiffre d'ici et un chiffre des chapitres de méthode est une | |
| 15 | +erreur à signaler : les tests (test_ch45.py) la détecteraient. | |
| 16 | + | |
| 17 | +Usage (racine du dépôt) : PYTHONPATH=analysis/python python3 analysis/python/cases/ch45_dossier.py""" | |
| 18 | +from __future__ import annotations | |
| 19 | +import sys, io, math, pathlib, contextlib | |
| 20 | +import numpy as np, pandas as pd | |
| 21 | +HERE = pathlib.Path(__file__).resolve() | |
| 22 | +sys.path.insert(0, str(HERE.parents[1])); sys.path.insert(0, str(HERE.parent)) | |
| 23 | +from traite import cas1, finance as fin, cout as ct, comparables as cp | |
| 24 | +import ch16_selection as c16 | |
| 25 | +import ch17_ajustements as c17 | |
| 26 | +import ch18_hedonique as c18 | |
| 27 | +import ch20_reconciliation as c20 | |
| 28 | +import ch21_cout_neuf as c21 | |
| 29 | +import ch24_depreciation as c24 | |
| 30 | +import ch25_terrain as c25 | |
| 31 | +import ch12_mesurage as c12 | |
| 32 | +import ch11_inspection as c11 | |
| 33 | +import ch09_ratios as c09 | |
| 34 | + | |
| 35 | +ROOT = HERE.parents[3] | |
| 36 | +GRAINE = 20261031 | |
| 37 | +DATE_EVAL = "2026-09-01" | |
| 38 | + | |
| 39 | +# ----------------------------------------------------------------------------- paramètres du financement (sources : notes-C, registre ch45) | |
| 40 | +TAUX_ASSURE = 0.0412 # BdC, fonds avancés, prêts assurés à taux fixe ≥ 5 ans, août 2026 (bdctauxhypothecaires2026) | |
| 41 | +TAUX_NON_ASSURE = 0.0458 # idem, prêts non assurés | |
| 42 | +AMORTISSEMENT_MOIS = 300 # 25 ans (SCHL : maximum 25 ans ; 30 ans réservé aux premiers acheteurs / constructions neuves) | |
| 43 | +TERME_ANS = 5 | |
| 44 | +MQR_PLANCHER, MQR_COUSSIN = 0.0525, 0.02 # taux admissible minimal : max(taux + 2 %, 5,25 %) (SCHL Achat ; Finances Canada 2023-12-12 ; BSIF pour le non assuré) | |
| 45 | +ABD_MAX, ATD_MAX = 0.39, 0.44 # SCHL : « restricts debt service ratios to 39 % (GDS) and 44 % (TDS) » | |
| 46 | +PRIMES_SCHL = [(0.65, 0.0060), (0.75, 0.0170), (0.80, 0.0240), (0.85, 0.0280), (0.90, 0.0310), (0.95, 0.0400)] # SCHL Achat, propriétaires-occupants | |
| 47 | +PLAFOND_ASSURABLE = 1_500_000.0 # prix maximal admissible (SCHL ; Finances Canada 2024-12-15) | |
| 48 | +TAXE_PRIME_QC = 0.09 # taxe québécoise sur les primes d'assurance : NON VÉRIFIÉE sur une source primaire (Revenu Québec inaccessible le 2026-10-31) ; | |
| 49 | + # la SCHL indique seulement que la prime est « subject to provincial sales tax » au Québec. Hypothèse déclarée. | |
| 50 | +CHAUFFAGE_ANNUEL = 2400.0 # hypothèse pédagogique déclarée (coût de chauffage retenu par le prêteur dans l'ABD) — aucune source | |
| 51 | +AUTRES_DETTES_MENSUELLES = 500.0 # hypothèse pédagogique déclarée (prêt auto, cartes) pour l'ATD | |
| 52 | +SCENARIOS_MISE = {"minimale": None, "10 %": 0.10, "20 %": 0.20} # None → mise de fonds minimale réglementaire | |
| 53 | + | |
| 54 | + | |
| 55 | +def mise_de_fonds_minimale(prix: float) -> float: | |
| 56 | + """SCHL / Finances Canada : 5 % de la première tranche de 500 000 $ + 10 % du reste (prix < 1,5 M$).""" | |
| 57 | + if prix >= PLAFOND_ASSURABLE: | |
| 58 | + raise ValueError("prix non assurable (≥ 1,5 M$) : mise de fonds d'au moins 20 %") | |
| 59 | + return 0.05 * min(prix, 500_000.0) + 0.10 * max(prix - 500_000.0, 0.0) | |
| 60 | + | |
| 61 | + | |
| 62 | +def taux_prime(rpv: float) -> float: | |
| 63 | + """Prime SCHL (propriétaire-occupant) selon le rapport prêt-valeur ; 0 si RPV ≤ 80 % (prêt conventionnel non assuré).""" | |
| 64 | + if rpv <= 0.80 + 1e-12: | |
| 65 | + return 0.0 | |
| 66 | + for borne, t in PRIMES_SCHL: | |
| 67 | + if rpv <= borne + 1e-12: | |
| 68 | + return t | |
| 69 | + raise ValueError("RPV > 95 % : non assurable") | |
| 70 | + | |
| 71 | + | |
| 72 | +# ----------------------------------------------------------------------------- 1. héritages des chapitres de méthode | |
| 73 | +def _silencieux(f, *a, **k): | |
| 74 | + with contextlib.redirect_stdout(io.StringIO()): | |
| 75 | + return f(*a, **k) | |
| 76 | + | |
| 77 | + | |
| 78 | +def heritage() -> dict: | |
| 79 | + """Tous les chiffres hérités, obtenus des scripts des chapitres (aucun recalcul « à la main »).""" | |
| 80 | + t = cas1.tout() # sélection ch. 16, modèle ch. 18, grille ch. 17, prédiction, intervalle | |
| 81 | + sel = t["selection"]; m = t["modele"]; s = t["sujet"] | |
| 82 | + b17 = c17.base(); rec17 = c17.reconcilier(b17) # ch. 17 : poids inverse du brut, valeur pondérée | |
| 83 | + pred18 = c18.prediction_sujet(m, s) # ch. 18 : prédiction, Duan, intervalles 95 et 80 %, prédiction au 2024-07-01 | |
| 84 | + ic_val = c20.exercices # (référence) l'IC de la valeur est calculé ci-dessous comme au ch. 20 | |
| 85 | + xVx = pred18["xVx"]; lnp = pred18["ln_pred"]; duan = pred18["facteur_duan"] | |
| 86 | + ic95 = (math.exp(lnp - 1.959964 * math.sqrt(xVx)) * duan, math.exp(lnp + 1.959964 * math.sqrt(xVx)) * duan) | |
| 87 | + r20 = c20.tout() # ch. 20 : bootstrap, coût (ch. 24 importé), combinaison, vérité | |
| 88 | + r24 = r20["cout"]["r24"] # ch. 24 complet (main() déjà exécuté silencieusement par le ch. 20) | |
| 89 | + devis, sujet, cn = c11.charger() # ch. 21 (coût neuf) et ch. 11 (fiche) | |
| 90 | + fiche = c11.fiche(devis, cn); trav = c11.travaux(devis, cn); dv = c11.depreciation(fiche, trav, cn) | |
| 91 | + sup12 = c12.superficies() # ch. 12 | |
| 92 | + g21 = c21.regrouper(devis); sup21 = c21.superficies(sujet, devis) | |
| 93 | + d09 = c09.charger(); et09 = c09.etude(d09); ds09 = c09.dossier_sujet(d09, et09) # ch. 9 | |
| 94 | + comp25 = _silencieux(c25.comparaison) # ch. 25 : comparaison directe des terrains | |
| 95 | + extr25 = _silencieux(c25.extraction_recente_ch24, t) | |
| 96 | + cand = sel["candidats"] | |
| 97 | + return {"t": t, "sujet": s, "ventes": t["ventes"], "modele": m, "selection": sel, "candidats": cand, "comparables": sel["comparables"], | |
| 98 | + "etapes16": sel["etapes"], "adj17": b17["adj"], "rec17": rec17, "V_comp": rec17["inverse_brut"]["valeur_ponderee"], | |
| 99 | + "poids17": rec17["poids_inverse_brut"], "pred18": pred18, "V_hed": t["prediction_hedonique"], "ip95": pred18["ic95"], "ip80": pred18["ic80"], | |
| 100 | + "ic95_valeur": ic95, "r20": r20, "r24": r24, "cn": cn, "devis": devis, "fiche": fiche, "travaux": trav, "dv11": dv, "sup12": sup12, | |
| 101 | + "groupes21": g21, "sup21": sup21, "d09": d09, "et09": et09, "ds09": ds09, "comp25": comp25, "extr25": extr25, | |
| 102 | + "indication_brute16": float(sel["comparables"]["prix_m2"].median() * s["superficie_habitable_m2"])} | |
| 103 | + | |
| 104 | + | |
| 105 | +# ----------------------------------------------------------------------------- 2. financement de l'acheteur (propre au ch. 45) | |
| 106 | +def financement(prix: float, mise: float | None = None, amortissement_mois: int = AMORTISSEMENT_MOIS, taxes_annuelles: float = 0.0, | |
| 107 | + droits_mutation: float = 0.0, chauffage: float = CHAUFFAGE_ANNUEL, autres_dettes_mensuelles: float = AUTRES_DETTES_MENSUELLES) -> dict: | |
| 108 | + """Prêt assuré ou conventionnel selon la mise de fonds ; prime SCHL (ajoutée au prêt), taxe québécoise sur la prime (payée comptant, | |
| 109 | + hypothèse), paiement mensuel (composition semestrielle), taux admissible minimal, revenu brut minimal selon l'ABD et l'ATD, | |
| 110 | + liquidités à la signature (mise de fonds + droits de mutation + taxe sur la prime ; frais de notaire et d'inspection exclus).""" | |
| 111 | + mise = mise_de_fonds_minimale(prix) if mise is None else mise | |
| 112 | + pret_base = prix - mise; rpv = pret_base / prix | |
| 113 | + assure = rpv > 0.80 | |
| 114 | + tp = taux_prime(rpv); prime = pret_base * tp; taxe = prime * TAXE_PRIME_QC | |
| 115 | + pret = pret_base + prime | |
| 116 | + taux = TAUX_ASSURE if assure else TAUX_NON_ASSURE | |
| 117 | + h = fin.Hypotheque(pret, taux, amortissement_mois) | |
| 118 | + mqr = fin.taux_admissible_minimal(taux, MQR_PLANCHER, MQR_COUSSIN) | |
| 119 | + hq = fin.Hypotheque(pret, mqr, amortissement_mois) | |
| 120 | + pith_q = hq.service_dette_annuel + taxes_annuelles + chauffage | |
| 121 | + revenu_abd = pith_q / ABD_MAX | |
| 122 | + revenu_atd = (pith_q + 12 * autres_dettes_mensuelles) / ATD_MAX | |
| 123 | + return {"prix": prix, "mise": mise, "mise_pct": mise / prix, "pret_base": pret_base, "rpv": rpv, "assure": assure, "taux_prime": tp, | |
| 124 | + "prime": prime, "taxe_prime": taxe, "pret": pret, "rpv_avec_prime": pret / prix, "taux": taux, "amortissement_mois": amortissement_mois, | |
| 125 | + "hypotheque": h, "paiement": h.paiement, "service_dette": h.service_dette_annuel, "constante": h.constante_hypothecaire, | |
| 126 | + "interets_an1": h.interets_annee(1), "capital_an1": h.capital_annee(1), "solde_terme": h.solde(TERME_ANS * 12), | |
| 127 | + "mqr": mqr, "paiement_mqr": hq.paiement, "pith_qualification": pith_q, "revenu_min_abd": revenu_abd, "revenu_min_atd": revenu_atd, | |
| 128 | + "revenu_min": max(revenu_abd, revenu_atd), "contrainte_revenu": "ATD" if revenu_atd > revenu_abd else "ABD", | |
| 129 | + "taxes_annuelles": taxes_annuelles, "chauffage": chauffage, "autres_dettes": autres_dettes_mensuelles, | |
| 130 | + "droits_mutation": droits_mutation, "liquidites": mise + droits_mutation + taxe} | |
| 131 | + | |
| 132 | + | |
| 133 | +def renouvellement(f: dict, hausses_pb=(0, 100, 200, 300), taxes_annuelles: float = 0.0) -> pd.DataFrame: | |
| 134 | + """Au terme de 5 ans, le solde est refinancé au taux initial + hausse sur l'amortissement résiduel.""" | |
| 135 | + solde = f["solde_terme"]; n = f["amortissement_mois"] - TERME_ANS * 12; rows = [] | |
| 136 | + for pb in hausses_pb: | |
| 137 | + taux = f["taux"] + pb / 10_000 | |
| 138 | + h = fin.Hypotheque(solde, taux, n) | |
| 139 | + pith = h.service_dette_annuel + taxes_annuelles + f["chauffage"] | |
| 140 | + rows.append({"hausse_pb": pb, "taux": taux, "solde": solde, "paiement": h.paiement, "service_dette": h.service_dette_annuel, | |
| 141 | + "hausse_paiement_pct": h.paiement / f["paiement"] - 1, "revenu_min_abd": pith / ABD_MAX}) | |
| 142 | + return pd.DataFrame(rows) | |
| 143 | + | |
| 144 | + | |
| 145 | +def valeur_d_emprunt(prix: float, valeur_preteur: float, mise_disponible: float) -> dict: | |
| 146 | + """Le prêteur prête sur la moindre du prix et de la valeur d'emprunt (RPV maximal 95 %) ; la mise de fonds doit combler l'écart.""" | |
| 147 | + base = min(prix, valeur_preteur) | |
| 148 | + pret_max = 0.95 * base | |
| 149 | + mise_requise = max(prix - pret_max, mise_de_fonds_minimale(prix)) | |
| 150 | + return {"valeur_preteur": valeur_preteur, "base": base, "pret_max": pret_max, "mise_requise": mise_requise, | |
| 151 | + "mise_supplementaire": mise_requise - mise_disponible} | |
| 152 | + | |
| 153 | + | |
| 154 | +# ----------------------------------------------------------------------------- 3. dossier | |
| 155 | +_CACHE: dict = {} | |
| 156 | + | |
| 157 | +def dossier() -> dict: | |
| 158 | + if "D" in _CACHE: | |
| 159 | + return _CACHE["D"] | |
| 160 | + H = heritage() | |
| 161 | + cb = H["r20"]["combinaison"]; co = H["r20"]["cout"]; bs = H["r20"]["bootstrap"] | |
| 162 | + conclusion = float(cb["conclusion"]); fourchette = tuple(float(x) for x in cb["fourchette_conclue"]) | |
| 163 | + prix = conclusion # prix supposé = valeur la plus probable (mandat de financement) | |
| 164 | + role = float(H["sujet"]["valeur_role_2025"]) | |
| 165 | + taxes = H["ds09"]["taxes_role"] # compte de taxes 2026 au rôle fictif (ch. 9) | |
| 166 | + # droits de mutation à l'achat (Gatineau 2026, barème à compter du 25 février 2026) : base = max(prix ; rôle × facteur réel 1,02) | |
| 167 | + base_mut = max(prix, role * c09.FACTEUR_GATINEAU_2026) | |
| 168 | + droits = c09.droits_mutation(base_mut, c09.BAREME_MUTATION_GAT) | |
| 169 | + droits_general = c09.droits_mutation(base_mut, c09.BAREME_MUTATION_QC) | |
| 170 | + F = {k: financement(prix, None if v is None else v * prix, taxes_annuelles=taxes["total"], droits_mutation=droits) for k, v in SCENARIOS_MISE.items()} | |
| 171 | + F["minimale 30 ans"] = financement(prix, None, 360, taxes_annuelles=taxes["total"], droits_mutation=droits) | |
| 172 | + ren = renouvellement(F["minimale"], taxes_annuelles=taxes["total"]) | |
| 173 | + ve = {v: valeur_d_emprunt(prix, v, F["minimale"]["mise"]) for v in (fourchette[0], conclusion, fourchette[1])} | |
| 174 | + # sommaire : indications, poids, écarts-types (ch. 20) | |
| 175 | + tab20 = cb["tableau"]; raisonnee = tab20[tab20["schema"] == "raisonnée (retenue)"].iloc[0] | |
| 176 | + D = {**H, "conclusion": conclusion, "fourchette": fourchette, "V_raisonnee": float(cb["V_raisonnee"]), "sd_conclusion": float(raisonnee["ecart_type"]), | |
| 177 | + "poids20": {"comparaison": 0.40, "hedonique": 0.45, "cout": 0.15}, "indications": {"comparaison": float(cb["V"][0]), "hedonique": float(cb["V"][1]), "cout": float(cb["V"][2])}, | |
| 178 | + "ecarts_types20": {"comparaison": float(cb["s"][0]), "hedonique": float(cb["s"][1]), "cout": float(cb["s"][2])}, "R20": cb["R"], | |
| 179 | + "bande90": tuple(float(x) for x in cb["fourchette90"]), "q20": cb["q"], "verite": H["r20"]["verite"], "tab20": tab20, | |
| 180 | + "V_cout": float(co["valeur"]), "V_cout_arrondie": float(co["arrondie"]), "V_L": float(co["V_L"]), "CN": float(co["CN"]), | |
| 181 | + "D_ext": float(co["D_ext"]), "taux_ext": float(co["taux_ext"]), "D_fonc": float(co["D_fonc"]), "D_tot": float(co["D_tot"]), "taux_tot": float(co["taux_tot"]), | |
| 182 | + "V_ventilee": float(co["ventilee"]), "taux_ventilee": float(co["taux_ventilee"]), "contribution_batiment": float(co["contribution_batiment"]), | |
| 183 | + "prix": prix, "role": role, "taxes": taxes, "base_mutation": base_mut, "droits_mutation": droits, "droits_mutation_general": droits_general, | |
| 184 | + "financement": F, "renouvellement": ren, "valeur_emprunt": ve, "bootstrap": bs, | |
| 185 | + "residu_moyen_retenus": float(np.mean(np.exp(H["r20"]["base"]["adj5"]["residu_log"]) - 1)), | |
| 186 | + "residu_moyen_autres": float(np.mean(np.exp(H["r20"]["base"]["adj16"].loc[~H["r20"]["base"]["adj16"]["retenu"], "residu_log"]) - 1)), | |
| 187 | + "V_16": float(H["r20"]["elargissement"]["valeur_ponderee"].iloc[-1]), | |
| 188 | + "valeur_reelle_2024": float(H["ds09"]["valeur_reelle"]), "ratio_sujet_role": float(H["ds09"]["ratio_sujet"]), "PM_fictif": float(H["et09"]["PM"]), | |
| 189 | + "F_fictif": float(H["et09"]["F"]), "valeur_a_inscrire": float(H["ds09"]["valeur_a_inscrire"]), "hed_2024": float(H["ds09"]["hedonique"])} | |
| 190 | + D["ratio_prix_role"] = prix / role | |
| 191 | + D["ratio_conclusion_brute16"] = conclusion / H["indication_brute16"] - 1 | |
| 192 | + _CACHE["D"] = D | |
| 193 | + return D | |
| 194 | + | |
| 195 | + | |
| 196 | +# ----------------------------------------------------------------------------- 4. exercices (chiffres des solutions) | |
| 197 | +def exercices(D: dict | None = None) -> dict: | |
| 198 | + D = D or dossier(); ex = {} | |
| 199 | + prix = D["prix"]; S = D["sujet"]["superficie_habitable_m2"]; sup = D["sup12"] | |
| 200 | + # ex 1 : unités de comparaison de la valeur conclue | |
| 201 | + ex["ex1"] = {"par_m2_hab": prix / S, "par_m2_brut": prix / sup["aire_etages_m2"], "par_pi2_hab": prix / (S * 10.7639), | |
| 202 | + "par_m2_hab_plus_ss": prix / sup["habitable_sous_sol_m2"], "med_comparables_m2": float(D["comparables"]["prix_m2"].median()), | |
| 203 | + "indication_brute": D["indication_brute16"], "ecart_pct": D["ratio_conclusion_brute16"]} | |
| 204 | + # ex 2 : droits de mutation et liquidités au haut et au bas de la fourchette | |
| 205 | + out = {} | |
| 206 | + for p in (D["fourchette"][0], D["fourchette"][1]): | |
| 207 | + base = max(p, D["role"] * c09.FACTEUR_GATINEAU_2026); dm = c09.droits_mutation(base, c09.BAREME_MUTATION_GAT) | |
| 208 | + f = financement(p, None, taxes_annuelles=D["taxes"]["total"], droits_mutation=dm) | |
| 209 | + out[p] = {"base": base, "droits": dm, "droits_general": c09.droits_mutation(base, c09.BAREME_MUTATION_QC), "mise": f["mise"], "prime": f["prime"], "taxe_prime": f["taxe_prime"], "liquidites": f["liquidites"]} | |
| 210 | + ex["ex2"] = out | |
| 211 | + # ex 3 : mise de fonds 10 % et 20 % | |
| 212 | + ex["ex3"] = {k: {kk: D["financement"][k][kk] for kk in ("mise", "pret_base", "rpv", "taux_prime", "prime", "pret", "taux", "paiement", "mqr", "paiement_mqr", "revenu_min_abd", "liquidites")} for k in ("minimale", "10 %", "20 %")} | |
| 213 | + # ex 4 : valeur d'emprunt du prêteur inférieure au prix | |
| 214 | + ex["ex4"] = D["valeur_emprunt"] | |
| 215 | + # ex 5 : renouvellement à +200 pb | |
| 216 | + r = D["renouvellement"]; ex["ex5"] = {int(k): dict(v) for k, v in r.set_index("hausse_pb").iterrows()} | |
| 217 | + # ex 6 : terrain aux bornes de la fourchette du ch. 25 → coût → réconciliation (poids fixes) | |
| 218 | + out = {} | |
| 219 | + for vl in (240_000.0, 277_000.0, 285_000.0): | |
| 220 | + vc = ct.valeur_par_cout(vl, D["CN"], D["D_ext"], D["D_fonc"])["valeur"] | |
| 221 | + comb = 0.40 * D["indications"]["comparaison"] + 0.45 * D["indications"]["hedonique"] + 0.15 * vc | |
| 222 | + out[vl] = {"V_cout": vc, "combinaison": comb, "arrondie": round(comb / 5000) * 5000, | |
| 223 | + "fourchette": (math.floor(min(D["indications"]["comparaison"], D["indications"]["hedonique"], vc) / 5000) * 5000, | |
| 224 | + math.ceil(max(D["indications"]["comparaison"], D["indications"]["hedonique"], vc) / 5000) * 5000)} | |
| 225 | + ex["ex6"] = out | |
| 226 | + # ex 7 : hypothèse extraordinaire (drain français) : incidence 9 000 $, p = 0,8 ; effet sur le financement | |
| 227 | + K = 9000.0; VH = D["conclusion"]; VnH = VH - K | |
| 228 | + f_nH = financement(VnH, None, taxes_annuelles=D["taxes"]["total"], droits_mutation=D["droits_mutation"]) | |
| 229 | + ex["ex7"] = {"V_H": VH, "V_nonH": VnH, "delta": K, "delta_pct": K / VH, "esperance_p80": VnH + 0.8 * K, "esperance_p50": VnH + 0.5 * K, | |
| 230 | + "mise_nonH": f_nH["mise"], "pret_nonH": f_nH["pret"], "paiement_nonH": f_nH["paiement"], "paiement_H": D["financement"]["minimale"]["paiement"]} | |
| 231 | + return ex | |
| 232 | + | |
| 233 | + | |
| 234 | +# ----------------------------------------------------------------------------- 5. impression | |
| 235 | +def _d(x): return f"{x:,.0f} $".replace(",", " ") | |
| 236 | +def _d2(x): return f"{x:,.2f} $".replace(",", " ") | |
| 237 | + | |
| 238 | +def main() -> dict: | |
| 239 | + D = dossier(); s = D["sujet"] | |
| 240 | + print("=== DONNÉES SYNTHÉTIQUES — Cas 1 : cottage 1998, 165 m², Hull (Gatineau) ; évaluation au", DATE_EVAL, "===") | |
| 241 | + print("--- Mesurage (ch. 12) :", {k: round(v, 2) for k, v in D["sup12"].items() if k in ("aire_sol_m2", "aire_etages_m2", "habitable_m2", "nette_m2", "habitable_sous_sol_m2", "garage_m2", "lot_m2")}) | |
| 242 | + print("--- Coût neuf (ch. 21) : C_N", _d2(D["cn"]["total"]), "; D", _d2(D["cn"]["direct"]), "; I", _d2(D["cn"]["indirects"]), "; E", _d2(D["cn"]["incitatif"])) | |
| 243 | + dv = D["dv11"] | |
| 244 | + print(f"--- Inspection (ch. 11) : indice d'état {c11.indice_etat(D['fiche']):.3f} ; âge effectif structure {dv['age_effectif_structure']:.0f} ans ; curable {_d2(dv['curable'])} ; ventilée {_d2(dv['total'])} ({dv['taux']*100:.2f} %)") | |
| 245 | + print(f"--- Rôle et taxes (ch. 9) : rôle fictif {_d(D['role'])} (réf. 2024-07-01) ; valeur réelle 2024-07-01 {_d(D['valeur_reelle_2024'])} (hédonique {_d(D['hed_2024'])}) ; ratio {D['ratio_sujet_role']:.4f} vs PM {D['PM_fictif']:.4f} ; " | |
| 246 | + f"valeur à inscrire {_d(D['valeur_a_inscrire'])} ; compte 2026 {_d2(D['taxes']['total'])} (municipal {_d2(D['taxes']['municipal'])}, scolaire {_d2(D['taxes']['scolaire'])}, compensation {_d2(D['taxes']['compensations'])})") | |
| 247 | + print("--- Sélection (ch. 16) :", D["etapes16"], "; comparables", list(D["comparables"]["id_vente"]), "; indication brute", _d(D["indication_brute16"])) | |
| 248 | + print("--- Grille (ch. 17) :\n", D["adj17"][["id_vente", "prix_vente", "conditions_marche", "superficie", "terrain", "age", "qualite", "garage", "sous_sol", "prix_ajuste", "ajust_brut_pct", "ajust_net_pct", "residu_pct"]].round(3).to_string(index=False)) | |
| 249 | + print(" poids", np.round(D["poids17"], 3), "; valeur pondérée", _d(D["V_comp"]), "; moyenne", _d(D["rec17"]["egal"]["valeur_ponderee"]), "; médiane", _d(D["rec17"]["egal"]["mediane"])) | |
| 250 | + p = D["pred18"] | |
| 251 | + print(f"--- Hédonique (ch. 18) : point {_d(p['naif'])} ; Duan {p['facteur_duan']:.5f} → {_d(D['V_hed'])} ; IP 95 % [{_d(D['ip95'][0])} ; {_d(D['ip95'][1])}] ; IP 80 % [{_d(D['ip80'][0])} ; {_d(D['ip80'][1])}] ; IC 95 % de la valeur [{_d(D['ic95_valeur'][0])} ; {_d(D['ic95_valeur'][1])}]") | |
| 252 | + print(f"--- Coût (ch. 24/25) : V_L {_d(D['V_L'])} ; D extraite {_d2(D['D_ext'])} ({D['taux_ext']*100:.2f} %) ; D fonc {_d2(D['D_fonc'])} ; D totale {_d2(D['D_tot'])} ({D['taux_tot']*100:.2f} %) ; contribution bâtiment {_d2(D['contribution_batiment'])} ; V {_d2(D['V_cout'])} → {_d(D['V_cout_arrondie'])} ; ventilée {_d2(D['V_ventilee'])} ({D['taux_ventilee']*100:.2f} %)") | |
| 253 | + c25r = D["comp25"]["reconciliation"] | |
| 254 | + print(f" terrain ch. 25 : comparaison directe {_d(c25r['valeur_ponderee'])} ; hédonique terrains {_d(D['comp25']['prediction_hedonique'])} ; extraction ch. 24 médiane {_d(D['extr25']['mediane'])} ({D['extr25']['n']} ventes, part {D['extr25']['part']*100:.1f} %)") | |
| 255 | + print(f"--- Réconciliation (ch. 20) : {D['indications']} ; é.-t. {D['ecarts_types20']} ; poids {D['poids20']} ; combinaison {_d2(D['V_raisonnee'])} (é.-t. {_d(D['sd_conclusion'])}) → CONCLUSION {_d(D['conclusion'])} ; fourchette {_d(D['fourchette'][0])} – {_d(D['fourchette'][1])} ; bande bootstrap 90 % {_d(D['bande90'][0])} – {_d(D['bande90'][1])}") | |
| 256 | + print(f" résidu moyen retenus {D['residu_moyen_retenus']*100:.2f} % ; autres {D['residu_moyen_autres']*100:.2f} % ; k = 16 : {_d(D['V_16'])} ; vérité {_d(D['verite']['V_true'])} ; ratio prix/rôle {D['ratio_prix_role']:.3f}") | |
| 257 | + print(D["tab20"].round(3).to_string(index=False)) | |
| 258 | + print(f"--- Mutation (Gatineau 2026, dès le 25 février) : base {_d(D['base_mutation'])} ; droit {_d2(D['droits_mutation'])} (barème général : {_d2(D['droits_mutation_general'])})") | |
| 259 | + print("--- Financement (prix = valeur la plus probable) :") | |
| 260 | + for k, f in D["financement"].items(): | |
| 261 | + print(f" {k:16s} mise {_d2(f['mise'])} ({f['mise_pct']*100:.2f} %) ; prêt {_d2(f['pret_base'])} RPV {f['rpv']*100:.2f} % ; prime {f['taux_prime']*100:.2f} % = {_d2(f['prime'])} (taxe hyp. 9 % {_d2(f['taxe_prime'])}) ; " | |
| 262 | + f"prêt total {_d2(f['pret'])} (RPV {f['rpv_avec_prime']*100:.2f} %) ; taux {f['taux']*100:.2f} % ; {f['amortissement_mois']} mois ; paiement {_d2(f['paiement'])}/mois ; SD {_d2(f['service_dette'])} ; f {f['constante']*100:.3f} % ; " | |
| 263 | + f"intérêts an 1 {_d2(f['interets_an1'])} ; capital an 1 {_d2(f['capital_an1'])} ; solde à 60 mois {_d2(f['solde_terme'])} ; MQR {f['mqr']*100:.2f} % → paiement {_d2(f['paiement_mqr'])} ; " | |
| 264 | + f"revenu min ABD {_d(f['revenu_min_abd'])} ; ATD {_d(f['revenu_min_atd'])} ({f['contrainte_revenu']}) ; liquidités {_d2(f['liquidites'])}") | |
| 265 | + print("--- Renouvellement (mise minimale, 25 ans) :\n", D["renouvellement"].round(4).to_string(index=False)) | |
| 266 | + print("--- Valeur d'emprunt du prêteur :", {k: {kk: round(vv) for kk, vv in v.items()} for k, v in D["valeur_emprunt"].items()}) | |
| 267 | + print("--- Exercices :") | |
| 268 | + for k, v in exercices(D).items(): | |
| 269 | + print(" ", k, v if not isinstance(v, dict) else {kk: (round(vv, 4) if isinstance(vv, (int, float, np.floating)) else vv) for kk, vv in v.items()}) | |
| 270 | + return D | |
| 271 | + | |
| 272 | + | |
| 273 | +if __name__ == "__main__": | |
| 274 | + main() | |
modified
analysis/python/tests/test_ch37.py
+3 −2
@@ -125,10 +125,11 @@ def test_sujet_et_pdp(res): | ||
| 125 | 125 | assert (s["prediction"].drop("Hédonique (référence)") < s.loc["Hédonique (référence)", "prediction"]).all() |
| 126 | 126 | assert s.loc["Gradient boosting", "ln_pred"] - s.loc["Gradient boosting", "ln_pred"] == 0 and math.exp(s.loc["Gradient boosting", "ln_pred"]) == pytest.approx(604_595, rel=0.003) |
| 127 | 127 | pdp = res["pdp"] |
| 128 | − # la PDP de la superficie du boosting suit la loi de génération : corrélation > 0,99 et écart maximal < 4 points | |
| 128 | + # la PDP de la superficie du boosting suit la loi de génération : corrélation > 0,99 et écart maximal < 6 points (aux extrémités du support) | |
| 129 | 129 | for nom in ("Gradient boosting", "Hédonique (référence)"): |
| 130 | 130 | a = pdp["superficie"][nom] - pdp["superficie"][nom].mean(); b = pdp["superficie"]["vraie"] - pdp["superficie"]["vraie"].mean() |
| 131 | − assert np.corrcoef(a, b)[0, 1] > 0.99 and np.abs(a - b).max() < 0.04, nom | |
| 131 | + assert np.corrcoef(a, b)[0, 1] > 0.99 and np.abs(a - b).max() < 0.06, nom | |
| 132 | + assert np.abs((a - b)[(pdp["superficie"]["grille"] >= 100) & (pdp["superficie"]["grille"] <= 220)]).max() < 0.04, nom | |
| 132 | 133 | # scénario : la PDP de l'âge du boosting reproduit le mur (creux entre 25 et 45 ans) que le polynôme hédonique ne peut pas suivre |
| 133 | 134 | g = pdp["age_scenario"]["grille"]; gb = pdp["age_scenario"]["Gradient boosting"]; hd = pdp["age_scenario"]["Hédonique (référence)"]; vr = pdp["age_scenario"]["vraie"] |
| 134 | 135 | m = (g >= 25) & (g <= 45) |
modified
analysis/python/tests/test_ch41.py
+22 −0
@@ -225,5 +225,27 @@ class TestExercices: | ||
| 225 | 225 | # ratio V_L / P = 1,06 > 1 ; part du bâtiment négative |
| 226 | 226 | assert (455000 - 483000) / 455000 == pytest.approx(-0.0615, abs=1e-4) |
| 227 | 227 | |
| 228 | + def test_ex1_grille(self): | |
| 229 | + g = c08.densite_admissible(900, 200, 4, 0.70, 450) | |
| 230 | + assert g["logements_admissibles"] == 4 and g["aire_plancher_max_m2"] == pytest.approx(630.0) | |
| 231 | + assert 6 * 80 / 0.85 == pytest.approx(564.7, abs=0.05) and 4 * 110 / 0.85 == pytest.approx(517.6, abs=0.05) | |
| 232 | + | |
| 233 | + def test_ex7_variantes(self, R): | |
| 234 | + h7 = {**cas.HYP, "marge": 0.12, "frais_vente": 0.03} | |
| 235 | + attendu = {"U": 183529, "D": 223981, "T": 269989} | |
| 236 | + for k, v in attendu.items(): | |
| 237 | + u = R["usages"][k] | |
| 238 | + assert cas.residuel_developpement(u["vente"]["gdv"], u["vente"]["s_total"], u["di_m2"], u["programme"]["duree_ans"], h7)["valeur_residuelle"] == pytest.approx(v, abs=TOL) | |
| 239 | + rT = R["usages"]["T"]["promoteur"]; s = cas.seuil_gdv(rT, R["usages"]["U"]["occupant"]["valeur_residuelle"]) | |
| 240 | + assert s == pytest.approx(1280327, abs=TOL) and (s / rT["gdv"] - 1) * 100 == pytest.approx(4.5, abs=0.05) | |
| 241 | + a_, b_ = cas.coefficients_option(rT, 350_000.0) | |
| 242 | + assert b_ - 350_000 == pytest.approx(595378, abs=TOL) and b_ / a_ == pytest.approx(1404877, abs=TOL) | |
| 243 | + assert cas.option_redeveloppement(rT["gdv"], a_, b_, 0.10, 5.0, 0.02, 0.045, 2)["prime_americaine"] == pytest.approx(14897, abs=TOL) | |
| 244 | + assert cas.option_redeveloppement(rT["gdv"], a_, b_, 0.15, 5.0, 0.02, 0.045, 2)["prime_americaine"] == pytest.approx(47091, abs=TOL) | |
| 245 | + | |
| 246 | + def test_ex6_sensibilite_sigma(self): | |
| 247 | + assert cas.seuil_capozza_helsley(18000, 600000, 0.05, 400, 2000)["prime_irreversibilite"] == pytest.approx(3483, abs=TOL) | |
| 248 | + assert cas.seuil_capozza_helsley(18000, 600000, 0.05, 400, 8000)["prime_irreversibilite"] == pytest.approx(21612, abs=TOL) | |
| 249 | + | |
| 228 | 250 | def test_marges(self): |
| 229 | 251 | assert fin.marge_sur_prix(0.10) == pytest.approx(1 / 11) and fin.marge_sur_cout(0.15) == pytest.approx(0.15 / 0.85) |
added
assets/figures/ch37/ch37-fig-apprentissage.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-arbre.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-erreurs.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-pdp.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-predit-observe.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-shap-beeswarm.pdf
+0 −0
Binary file not shown.
added
assets/figures/ch37/ch37-fig-waterfall.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-convergence.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-distribution.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-lhs.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-nuage.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-portefeuille.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-rcd.pdf
+0 −0
Binary file not shown.
modified
assets/figures/ch40/ch40-fig-sobol.pdf
+0 −0
Binary file not shown.
modified
data/synthetic/ch43_riverain_lots.csv
+66 −66
@@ -96,9 +96,9 @@ RF0318,18,3,740.0,140.0,147.6,modérée,1,0 | ||
| 96 | 96 | RF0319,19,3,780.0,140.0,136.4,modérée,1,0 |
| 97 | 97 | RF0320,20,3,820.0,140.0,133.4,modérée,1,0 |
| 98 | 98 | RF0321,21,3,860.0,140.0,140.2,modérée,1,0 |
| 99 | −RF0322,22,3,900.0,140.0,147.3,modérée,1,0 | |
| 100 | −RF0323,23,3,940.0,140.0,143.8,modérée,1,0 | |
| 101 | −RF0324,24,3,980.0,140.0,134.5,modérée,1,0 | |
| 99 | +RF0322,22,3,900.0,140.0,147.3,modérée,1,1 | |
| 100 | +RF0323,23,3,940.0,140.0,143.8,modérée,1,1 | |
| 101 | +RF0324,24,3,980.0,140.0,134.5,modérée,1,1 | |
| 102 | 102 | RF0400,0,4,20.0,180.0,179.5,modérée,1,0 |
| 103 | 103 | RF0401,1,4,60.0,180.0,178.4,modérée,1,0 |
| 104 | 104 | RF0402,2,4,100.0,180.0,179.1,modérée,1,0 |
@@ -121,9 +121,9 @@ RF0418,18,4,740.0,180.0,187.5,modérée,1,0 | ||
| 121 | 121 | RF0419,19,4,780.0,180.0,183.5,modérée,1,0 |
| 122 | 122 | RF0420,20,4,820.0,180.0,174.7,modérée,1,0 |
| 123 | 123 | RF0421,21,4,860.0,180.0,186.8,modérée,1,0 |
| 124 | −RF0422,22,4,900.0,180.0,187.5,modérée,1,0 | |
| 125 | −RF0423,23,4,940.0,180.0,178.8,modérée,1,0 | |
| 126 | −RF0424,24,4,980.0,180.0,185.1,modérée,1,0 | |
| 124 | +RF0422,22,4,900.0,180.0,187.5,modérée,1,1 | |
| 125 | +RF0423,23,4,940.0,180.0,178.8,modérée,1,1 | |
| 126 | +RF0424,24,4,980.0,180.0,185.1,modérée,1,1 | |
| 127 | 127 | RF0500,0,5,20.0,220.0,221.3,faible,1,0 |
| 128 | 128 | RF0501,1,5,60.0,220.0,222.2,faible,1,0 |
| 129 | 129 | RF0502,2,5,100.0,220.0,226.9,faible,1,0 |
@@ -146,9 +146,9 @@ RF0518,18,5,740.0,220.0,213.6,faible,1,0 | ||
| 146 | 146 | RF0519,19,5,780.0,220.0,219.3,faible,1,0 |
| 147 | 147 | RF0520,20,5,820.0,220.0,213.0,faible,1,0 |
| 148 | 148 | RF0521,21,5,860.0,220.0,217.6,faible,1,0 |
| 149 | −RF0522,22,5,900.0,220.0,217.2,faible,1,0 | |
| 150 | −RF0523,23,5,940.0,220.0,213.1,faible,1,0 | |
| 151 | −RF0524,24,5,980.0,220.0,224.7,faible,1,0 | |
| 149 | +RF0522,22,5,900.0,220.0,217.2,faible,1,1 | |
| 150 | +RF0523,23,5,940.0,220.0,213.1,faible,1,1 | |
| 151 | +RF0524,24,5,980.0,220.0,224.7,faible,1,1 | |
| 152 | 152 | RF0600,0,6,20.0,260.0,258.0,faible,1,0 |
| 153 | 153 | RF0601,1,6,60.0,260.0,259.6,faible,1,0 |
| 154 | 154 | RF0602,2,6,100.0,260.0,258.6,faible,1,0 |
@@ -171,9 +171,9 @@ RF0618,18,6,740.0,260.0,260.2,faible,1,0 | ||
| 171 | 171 | RF0619,19,6,780.0,260.0,258.9,faible,1,0 |
| 172 | 172 | RF0620,20,6,820.0,260.0,253.3,faible,1,0 |
| 173 | 173 | RF0621,21,6,860.0,260.0,264.1,faible,1,0 |
| 174 | −RF0622,22,6,900.0,260.0,256.0,faible,1,0 | |
| 175 | −RF0623,23,6,940.0,260.0,257.8,faible,1,0 | |
| 176 | −RF0624,24,6,980.0,260.0,255.1,faible,1,0 | |
| 174 | +RF0622,22,6,900.0,260.0,256.0,faible,1,1 | |
| 175 | +RF0623,23,6,940.0,260.0,257.8,faible,1,1 | |
| 176 | +RF0624,24,6,980.0,260.0,255.1,faible,1,1 | |
| 177 | 177 | RF0700,0,7,20.0,300.0,298.2,hors zone,0,0 |
| 178 | 178 | RF0701,1,7,60.0,300.0,293.4,hors zone,0,0 |
| 179 | 179 | RF0702,2,7,100.0,300.0,301.8,hors zone,0,0 |
@@ -196,9 +196,9 @@ RF0718,18,7,740.0,300.0,295.5,hors zone,0,0 | ||
| 196 | 196 | RF0719,19,7,780.0,300.0,296.0,hors zone,0,0 |
| 197 | 197 | RF0720,20,7,820.0,300.0,294.5,hors zone,0,0 |
| 198 | 198 | RF0721,21,7,860.0,300.0,300.9,hors zone,0,0 |
| 199 | −RF0722,22,7,900.0,300.0,306.0,hors zone,0,0 | |
| 200 | −RF0723,23,7,940.0,300.0,296.6,hors zone,0,0 | |
| 201 | −RF0724,24,7,980.0,300.0,293.8,hors zone,0,0 | |
| 199 | +RF0722,22,7,900.0,300.0,306.0,hors zone,0,1 | |
| 200 | +RF0723,23,7,940.0,300.0,296.6,hors zone,0,1 | |
| 201 | +RF0724,24,7,980.0,300.0,293.8,hors zone,0,1 | |
| 202 | 202 | RF0800,0,8,20.0,340.0,342.9,hors zone,0,0 |
| 203 | 203 | RF0801,1,8,60.0,340.0,339.4,hors zone,0,0 |
| 204 | 204 | RF0802,2,8,100.0,340.0,334.0,hors zone,0,0 |
@@ -221,9 +221,9 @@ RF0818,18,8,740.0,340.0,334.2,hors zone,0,0 | ||
| 221 | 221 | RF0819,19,8,780.0,340.0,345.3,hors zone,0,0 |
| 222 | 222 | RF0820,20,8,820.0,340.0,343.1,hors zone,0,0 |
| 223 | 223 | RF0821,21,8,860.0,340.0,343.8,hors zone,0,0 |
| 224 | −RF0822,22,8,900.0,340.0,341.2,hors zone,0,0 | |
| 225 | −RF0823,23,8,940.0,340.0,334.9,hors zone,0,0 | |
| 226 | −RF0824,24,8,980.0,340.0,344.6,hors zone,0,0 | |
| 224 | +RF0822,22,8,900.0,340.0,341.2,hors zone,0,1 | |
| 225 | +RF0823,23,8,940.0,340.0,334.9,hors zone,0,1 | |
| 226 | +RF0824,24,8,980.0,340.0,344.6,hors zone,0,1 | |
| 227 | 227 | RF0900,0,9,20.0,380.0,373.6,hors zone,0,0 |
| 228 | 228 | RF0901,1,9,60.0,380.0,374.7,hors zone,0,0 |
| 229 | 229 | RF0902,2,9,100.0,380.0,375.0,hors zone,0,0 |
@@ -246,9 +246,9 @@ RF0918,18,9,740.0,380.0,376.8,hors zone,0,0 | ||
| 246 | 246 | RF0919,19,9,780.0,380.0,372.6,hors zone,0,0 |
| 247 | 247 | RF0920,20,9,820.0,380.0,386.8,hors zone,0,0 |
| 248 | 248 | RF0921,21,9,860.0,380.0,374.5,hors zone,0,0 |
| 249 | −RF0922,22,9,900.0,380.0,375.8,hors zone,0,0 | |
| 250 | −RF0923,23,9,940.0,380.0,377.4,hors zone,0,0 | |
| 251 | −RF0924,24,9,980.0,380.0,382.2,hors zone,0,0 | |
| 249 | +RF0922,22,9,900.0,380.0,375.8,hors zone,0,1 | |
| 250 | +RF0923,23,9,940.0,380.0,377.4,hors zone,0,1 | |
| 251 | +RF0924,24,9,980.0,380.0,382.2,hors zone,0,1 | |
| 252 | 252 | RF1000,0,10,20.0,420.0,417.4,hors zone,0,0 |
| 253 | 253 | RF1001,1,10,60.0,420.0,418.6,hors zone,0,0 |
| 254 | 254 | RF1002,2,10,100.0,420.0,417.1,hors zone,0,0 |
@@ -271,9 +271,9 @@ RF1018,18,10,740.0,420.0,427.8,hors zone,0,0 | ||
| 271 | 271 | RF1019,19,10,780.0,420.0,427.8,hors zone,0,0 |
| 272 | 272 | RF1020,20,10,820.0,420.0,422.0,hors zone,0,0 |
| 273 | 273 | RF1021,21,10,860.0,420.0,420.8,hors zone,0,0 |
| 274 | −RF1022,22,10,900.0,420.0,415.7,hors zone,0,0 | |
| 275 | −RF1023,23,10,940.0,420.0,427.0,hors zone,0,0 | |
| 276 | −RF1024,24,10,980.0,420.0,425.0,hors zone,0,0 | |
| 274 | +RF1022,22,10,900.0,420.0,415.7,hors zone,0,1 | |
| 275 | +RF1023,23,10,940.0,420.0,427.0,hors zone,0,1 | |
| 276 | +RF1024,24,10,980.0,420.0,425.0,hors zone,0,1 | |
| 277 | 277 | RF1100,0,11,20.0,460.0,460.0,hors zone,0,0 |
| 278 | 278 | RF1101,1,11,60.0,460.0,459.4,hors zone,0,0 |
| 279 | 279 | RF1102,2,11,100.0,460.0,453.8,hors zone,0,0 |
@@ -296,9 +296,9 @@ RF1118,18,11,740.0,460.0,458.8,hors zone,0,0 | ||
| 296 | 296 | RF1119,19,11,780.0,460.0,453.3,hors zone,0,0 |
| 297 | 297 | RF1120,20,11,820.0,460.0,466.2,hors zone,0,0 |
| 298 | 298 | RF1121,21,11,860.0,460.0,452.7,hors zone,0,0 |
| 299 | −RF1122,22,11,900.0,460.0,452.6,hors zone,0,0 | |
| 300 | −RF1123,23,11,940.0,460.0,467.5,hors zone,0,0 | |
| 301 | −RF1124,24,11,980.0,460.0,452.7,hors zone,0,0 | |
| 299 | +RF1122,22,11,900.0,460.0,452.6,hors zone,0,1 | |
| 300 | +RF1123,23,11,940.0,460.0,467.5,hors zone,0,1 | |
| 301 | +RF1124,24,11,980.0,460.0,452.7,hors zone,0,1 | |
| 302 | 302 | RF1200,0,12,20.0,500.0,500.4,hors zone,0,0 |
| 303 | 303 | RF1201,1,12,60.0,500.0,499.1,hors zone,0,0 |
| 304 | 304 | RF1202,2,12,100.0,500.0,496.0,hors zone,0,0 |
@@ -321,9 +321,9 @@ RF1218,18,12,740.0,500.0,498.7,hors zone,0,0 | ||
| 321 | 321 | RF1219,19,12,780.0,500.0,503.5,hors zone,0,0 |
| 322 | 322 | RF1220,20,12,820.0,500.0,493.3,hors zone,0,0 |
| 323 | 323 | RF1221,21,12,860.0,500.0,504.1,hors zone,0,0 |
| 324 | −RF1222,22,12,900.0,500.0,505.5,hors zone,0,0 | |
| 325 | −RF1223,23,12,940.0,500.0,497.6,hors zone,0,0 | |
| 326 | −RF1224,24,12,980.0,500.0,495.2,hors zone,0,0 | |
| 324 | +RF1222,22,12,900.0,500.0,505.5,hors zone,0,1 | |
| 325 | +RF1223,23,12,940.0,500.0,497.6,hors zone,0,1 | |
| 326 | +RF1224,24,12,980.0,500.0,495.2,hors zone,0,1 | |
| 327 | 327 | RF1300,0,13,20.0,540.0,541.1,hors zone,0,0 |
| 328 | 328 | RF1301,1,13,60.0,540.0,532.2,hors zone,0,0 |
| 329 | 329 | RF1302,2,13,100.0,540.0,543.8,hors zone,0,0 |
@@ -346,9 +346,9 @@ RF1318,18,13,740.0,540.0,547.9,hors zone,0,0 | ||
| 346 | 346 | RF1319,19,13,780.0,540.0,545.3,hors zone,0,0 |
| 347 | 347 | RF1320,20,13,820.0,540.0,541.6,hors zone,0,0 |
| 348 | 348 | RF1321,21,13,860.0,540.0,532.0,hors zone,0,0 |
| 349 | −RF1322,22,13,900.0,540.0,547.8,hors zone,0,0 | |
| 350 | −RF1323,23,13,940.0,540.0,534.9,hors zone,0,0 | |
| 351 | −RF1324,24,13,980.0,540.0,532.6,hors zone,0,0 | |
| 349 | +RF1322,22,13,900.0,540.0,547.8,hors zone,0,1 | |
| 350 | +RF1323,23,13,940.0,540.0,534.9,hors zone,0,1 | |
| 351 | +RF1324,24,13,980.0,540.0,532.6,hors zone,0,1 | |
| 352 | 352 | RF1400,0,14,20.0,580.0,576.4,hors zone,0,0 |
| 353 | 353 | RF1401,1,14,60.0,580.0,579.1,hors zone,0,0 |
| 354 | 354 | RF1402,2,14,100.0,580.0,581.0,hors zone,0,0 |
@@ -371,9 +371,9 @@ RF1418,18,14,740.0,580.0,575.2,hors zone,0,0 | ||
| 371 | 371 | RF1419,19,14,780.0,580.0,576.0,hors zone,0,0 |
| 372 | 372 | RF1420,20,14,820.0,580.0,580.3,hors zone,0,0 |
| 373 | 373 | RF1421,21,14,860.0,580.0,581.1,hors zone,0,0 |
| 374 | −RF1422,22,14,900.0,580.0,573.0,hors zone,0,0 | |
| 375 | −RF1423,23,14,940.0,580.0,585.9,hors zone,0,0 | |
| 376 | −RF1424,24,14,980.0,580.0,577.1,hors zone,0,0 | |
| 374 | +RF1422,22,14,900.0,580.0,573.0,hors zone,0,1 | |
| 375 | +RF1423,23,14,940.0,580.0,585.9,hors zone,0,1 | |
| 376 | +RF1424,24,14,980.0,580.0,577.1,hors zone,0,1 | |
| 377 | 377 | RF1500,0,15,20.0,620.0,622.3,hors zone,0,0 |
| 378 | 378 | RF1501,1,15,60.0,620.0,621.9,hors zone,0,0 |
| 379 | 379 | RF1502,2,15,100.0,620.0,616.8,hors zone,0,0 |
@@ -396,9 +396,9 @@ RF1518,18,15,740.0,620.0,620.4,hors zone,0,0 | ||
| 396 | 396 | RF1519,19,15,780.0,620.0,613.3,hors zone,0,0 |
| 397 | 397 | RF1520,20,15,820.0,620.0,618.8,hors zone,0,0 |
| 398 | 398 | RF1521,21,15,860.0,620.0,617.9,hors zone,0,0 |
| 399 | −RF1522,22,15,900.0,620.0,620.8,hors zone,0,0 | |
| 400 | −RF1523,23,15,940.0,620.0,626.0,hors zone,0,0 | |
| 401 | −RF1524,24,15,980.0,620.0,623.6,hors zone,0,0 | |
| 399 | +RF1522,22,15,900.0,620.0,620.8,hors zone,0,1 | |
| 400 | +RF1523,23,15,940.0,620.0,626.0,hors zone,0,1 | |
| 401 | +RF1524,24,15,980.0,620.0,623.6,hors zone,0,1 | |
| 402 | 402 | RF1600,0,16,20.0,660.0,652.0,hors zone,0,0 |
| 403 | 403 | RF1601,1,16,60.0,660.0,658.2,hors zone,0,0 |
| 404 | 404 | RF1602,2,16,100.0,660.0,661.5,hors zone,0,0 |
@@ -421,9 +421,9 @@ RF1618,18,16,740.0,660.0,653.5,hors zone,0,0 | ||
| 421 | 421 | RF1619,19,16,780.0,660.0,664.0,hors zone,0,0 |
| 422 | 422 | RF1620,20,16,820.0,660.0,665.3,hors zone,0,0 |
| 423 | 423 | RF1621,21,16,860.0,660.0,658.6,hors zone,0,0 |
| 424 | −RF1622,22,16,900.0,660.0,664.8,hors zone,0,0 | |
| 425 | −RF1623,23,16,940.0,660.0,652.2,hors zone,0,0 | |
| 426 | −RF1624,24,16,980.0,660.0,660.3,hors zone,0,0 | |
| 424 | +RF1622,22,16,900.0,660.0,664.8,hors zone,0,1 | |
| 425 | +RF1623,23,16,940.0,660.0,652.2,hors zone,0,1 | |
| 426 | +RF1624,24,16,980.0,660.0,660.3,hors zone,0,1 | |
| 427 | 427 | RF1700,0,17,20.0,700.0,702.5,hors zone,0,0 |
| 428 | 428 | RF1701,1,17,60.0,700.0,701.9,hors zone,0,0 |
| 429 | 429 | RF1702,2,17,100.0,700.0,696.8,hors zone,0,0 |
@@ -446,9 +446,9 @@ RF1718,18,17,740.0,700.0,695.5,hors zone,0,0 | ||
| 446 | 446 | RF1719,19,17,780.0,700.0,706.9,hors zone,0,0 |
| 447 | 447 | RF1720,20,17,820.0,700.0,694.0,hors zone,0,0 |
| 448 | 448 | RF1721,21,17,860.0,700.0,703.2,hors zone,0,0 |
| 449 | −RF1722,22,17,900.0,700.0,698.3,hors zone,0,0 | |
| 450 | −RF1723,23,17,940.0,700.0,694.2,hors zone,0,0 | |
| 451 | −RF1724,24,17,980.0,700.0,701.5,hors zone,0,0 | |
| 449 | +RF1722,22,17,900.0,700.0,698.3,hors zone,0,1 | |
| 450 | +RF1723,23,17,940.0,700.0,694.2,hors zone,0,1 | |
| 451 | +RF1724,24,17,980.0,700.0,701.5,hors zone,0,1 | |
| 452 | 452 | RF1800,0,18,20.0,740.0,742.1,hors zone,0,0 |
| 453 | 453 | RF1801,1,18,60.0,740.0,742.4,hors zone,0,0 |
| 454 | 454 | RF1802,2,18,100.0,740.0,747.3,hors zone,0,0 |
@@ -471,9 +471,9 @@ RF1818,18,18,740.0,740.0,741.2,hors zone,0,0 | ||
| 471 | 471 | RF1819,19,18,780.0,740.0,738.9,hors zone,0,0 |
| 472 | 472 | RF1820,20,18,820.0,740.0,744.0,hors zone,0,0 |
| 473 | 473 | RF1821,21,18,860.0,740.0,743.6,hors zone,0,0 |
| 474 | −RF1822,22,18,900.0,740.0,739.9,hors zone,0,0 | |
| 475 | −RF1823,23,18,940.0,740.0,733.5,hors zone,0,0 | |
| 476 | −RF1824,24,18,980.0,740.0,740.5,hors zone,0,0 | |
| 474 | +RF1822,22,18,900.0,740.0,739.9,hors zone,0,1 | |
| 475 | +RF1823,23,18,940.0,740.0,733.5,hors zone,0,1 | |
| 476 | +RF1824,24,18,980.0,740.0,740.5,hors zone,0,1 | |
| 477 | 477 | RF1900,0,19,20.0,780.0,787.6,hors zone,0,0 |
| 478 | 478 | RF1901,1,19,60.0,780.0,774.4,hors zone,0,0 |
| 479 | 479 | RF1902,2,19,100.0,780.0,780.1,hors zone,0,0 |
@@ -496,9 +496,9 @@ RF1918,18,19,740.0,780.0,784.0,hors zone,0,0 | ||
| 496 | 496 | RF1919,19,19,780.0,780.0,774.8,hors zone,0,0 |
| 497 | 497 | RF1920,20,19,820.0,780.0,782.2,hors zone,0,0 |
| 498 | 498 | RF1921,21,19,860.0,780.0,777.5,hors zone,0,0 |
| 499 | −RF1922,22,19,900.0,780.0,775.8,hors zone,0,0 | |
| 500 | −RF1923,23,19,940.0,780.0,786.1,hors zone,0,0 | |
| 501 | −RF1924,24,19,980.0,780.0,774.5,hors zone,0,0 | |
| 499 | +RF1922,22,19,900.0,780.0,775.8,hors zone,0,1 | |
| 500 | +RF1923,23,19,940.0,780.0,786.1,hors zone,0,1 | |
| 501 | +RF1924,24,19,980.0,780.0,774.5,hors zone,0,1 | |
| 502 | 502 | RF2000,0,20,20.0,820.0,813.8,hors zone,0,0 |
| 503 | 503 | RF2001,1,20,60.0,820.0,817.8,hors zone,0,0 |
| 504 | 504 | RF2002,2,20,100.0,820.0,817.0,hors zone,0,0 |
@@ -521,9 +521,9 @@ RF2018,18,20,740.0,820.0,823.2,hors zone,0,0 | ||
| 521 | 521 | RF2019,19,20,780.0,820.0,815.6,hors zone,0,0 |
| 522 | 522 | RF2020,20,20,820.0,820.0,812.5,hors zone,0,0 |
| 523 | 523 | RF2021,21,20,860.0,820.0,823.7,hors zone,0,0 |
| 524 | −RF2022,22,20,900.0,820.0,822.8,hors zone,0,0 | |
| 525 | −RF2023,23,20,940.0,820.0,818.5,hors zone,0,0 | |
| 526 | −RF2024,24,20,980.0,820.0,817.8,hors zone,0,0 | |
| 524 | +RF2022,22,20,900.0,820.0,822.8,hors zone,0,1 | |
| 525 | +RF2023,23,20,940.0,820.0,818.5,hors zone,0,1 | |
| 526 | +RF2024,24,20,980.0,820.0,817.8,hors zone,0,1 | |
| 527 | 527 | RF2100,0,21,20.0,860.0,857.4,hors zone,0,0 |
| 528 | 528 | RF2101,1,21,60.0,860.0,858.3,hors zone,0,0 |
| 529 | 529 | RF2102,2,21,100.0,860.0,862.1,hors zone,0,0 |
@@ -546,9 +546,9 @@ RF2118,18,21,740.0,860.0,863.6,hors zone,0,0 | ||
| 546 | 546 | RF2119,19,21,780.0,860.0,865.3,hors zone,0,0 |
| 547 | 547 | RF2120,20,21,820.0,860.0,862.4,hors zone,0,0 |
| 548 | 548 | RF2121,21,21,860.0,860.0,853.7,hors zone,0,0 |
| 549 | −RF2122,22,21,900.0,860.0,857.5,hors zone,0,0 | |
| 550 | −RF2123,23,21,940.0,860.0,861.6,hors zone,0,0 | |
| 551 | −RF2124,24,21,980.0,860.0,858.1,hors zone,0,0 | |
| 549 | +RF2122,22,21,900.0,860.0,857.5,hors zone,0,1 | |
| 550 | +RF2123,23,21,940.0,860.0,861.6,hors zone,0,1 | |
| 551 | +RF2124,24,21,980.0,860.0,858.1,hors zone,0,1 | |
| 552 | 552 | RF2200,0,22,20.0,900.0,901.0,hors zone,0,0 |
| 553 | 553 | RF2201,1,22,60.0,900.0,893.0,hors zone,0,0 |
| 554 | 554 | RF2202,2,22,100.0,900.0,901.1,hors zone,0,0 |
@@ -571,9 +571,9 @@ RF2218,18,22,740.0,900.0,896.7,hors zone,0,0 | ||
| 571 | 571 | RF2219,19,22,780.0,900.0,897.3,hors zone,0,0 |
| 572 | 572 | RF2220,20,22,820.0,900.0,895.1,hors zone,0,0 |
| 573 | 573 | RF2221,21,22,860.0,900.0,901.7,hors zone,0,0 |
| 574 | −RF2222,22,22,900.0,900.0,903.8,hors zone,0,0 | |
| 575 | −RF2223,23,22,940.0,900.0,896.7,hors zone,0,0 | |
| 576 | −RF2224,24,22,980.0,900.0,895.6,hors zone,0,0 | |
| 574 | +RF2222,22,22,900.0,900.0,903.8,hors zone,0,1 | |
| 575 | +RF2223,23,22,940.0,900.0,896.7,hors zone,0,1 | |
| 576 | +RF2224,24,22,980.0,900.0,895.6,hors zone,0,1 | |
| 577 | 577 | RF2300,0,23,20.0,940.0,936.6,hors zone,0,0 |
| 578 | 578 | RF2301,1,23,60.0,940.0,943.7,hors zone,0,0 |
| 579 | 579 | RF2302,2,23,100.0,940.0,943.5,hors zone,0,0 |
@@ -596,9 +596,9 @@ RF2318,18,23,740.0,940.0,940.5,hors zone,0,0 | ||
| 596 | 596 | RF2319,19,23,780.0,940.0,941.8,hors zone,0,0 |
| 597 | 597 | RF2320,20,23,820.0,940.0,936.1,hors zone,0,0 |
| 598 | 598 | RF2321,21,23,860.0,940.0,937.3,hors zone,0,0 |
| 599 | −RF2322,22,23,900.0,940.0,939.5,hors zone,0,0 | |
| 600 | −RF2323,23,23,940.0,940.0,944.2,hors zone,0,0 | |
| 601 | −RF2324,24,23,980.0,940.0,946.6,hors zone,0,0 | |
| 599 | +RF2322,22,23,900.0,940.0,939.5,hors zone,0,1 | |
| 600 | +RF2323,23,23,940.0,940.0,944.2,hors zone,0,1 | |
| 601 | +RF2324,24,23,980.0,940.0,946.6,hors zone,0,1 | |
| 602 | 602 | RF2400,0,24,20.0,980.0,977.3,hors zone,0,0 |
| 603 | 603 | RF2401,1,24,60.0,980.0,986.6,hors zone,0,0 |
| 604 | 604 | RF2402,2,24,100.0,980.0,980.0,hors zone,0,0 |
@@ -621,6 +621,6 @@ RF2418,18,24,740.0,980.0,973.0,hors zone,0,0 | ||
| 621 | 621 | RF2419,19,24,780.0,980.0,979.1,hors zone,0,0 |
| 622 | 622 | RF2420,20,24,820.0,980.0,977.0,hors zone,0,0 |
| 623 | 623 | RF2421,21,24,860.0,980.0,983.2,hors zone,0,0 |
| 624 | −RF2422,22,24,900.0,980.0,981.1,hors zone,0,0 | |
| 625 | −RF2423,23,24,940.0,980.0,972.4,hors zone,0,0 | |
| 626 | −RF2424,24,24,980.0,980.0,976.8,hors zone,0,0 | |
| 624 | +RF2422,22,24,900.0,980.0,981.1,hors zone,0,1 | |
| 625 | +RF2423,23,24,940.0,980.0,972.4,hors zone,0,1 | |
| 626 | +RF2424,24,24,980.0,980.0,976.8,hors zone,0,1 | |
modified
data/synthetic/ch43_riverain_ventes.csv
+1013 −763
Large diff (1,778 lines) is not loaded by default to keep the page fast.Load diff
deleted
manuscript/_wrap_ch39.tex
+0 −12
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
deleted
manuscript/_wrap_ch43.tex
+0 −12
Large diff (12 lines) is not loaded by default to keep the page fast.Load diff
modified
manuscript/chapters/ch37.tex
+1 −1
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
modified
manuscript/chapters/ch40.tex
+9 −8
Large diff (40 lines) is not loaded by default to keep the page fast.Load diff
modified
manuscript/chapters/ch44.tex
+20 −0
Large diff (44 lines) is not loaded by default to keep the page fast.Load diff
modified
manuscript/chapters/ch46.tex
+276 −0
Large diff (279 lines) is not loaded by default to keep the page fast.Load diff
added
references/lib-ch37.bib
+34 −0
Large diff (34 lines) is not loaded by default to keep the page fast.Load diff
modified
references/library.bib
+29 −0
Large diff (35 lines) is not loaded by default to keep the page fast.Load diff
modified
solutions/ch41.tex
+63 −0
Large diff (64 lines) is not loaded by default to keep the page fast.Load diff
modified
sources/registry.csv
+3 −0
Large diff (9 lines) is not loaded by default to keep the page fast.Load diff
modified
verification/calculations.csv
+12 −0
Large diff (15 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch37-calculations.csv
+13 −0
Large diff (13 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch37-claims.csv
+14 −0
Large diff (14 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch37-figures.csv
+8 −0
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch37-registry.csv
+4 −0
Large diff (4 lines) is not loaded by default to keep the page fast.Load diff
modified
verification/chapters/ch39-claims.csv
+2 −2
Large diff (11 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch40-figures.csv
+8 −0
Large diff (8 lines) is not loaded by default to keep the page fast.Load diff
added
verification/chapters/ch43.md
+40 −0
Large diff (40 lines) is not loaded by default to keep the page fast.Load diff
modified
verification/claims.csv
+15 −2
Large diff (24 lines) is not loaded by default to keep the page fast.Load diff
modified
verification/figures.csv
+14 −0
Large diff (18 lines) is not loaded by default to keep the page fast.Load diff