SPB Git
4.0 KB · 69 lines python
1#!/usr/bin/env python32"""Figures ch03 — Simulation d'un cycle stock-flux (SYNTHÉTIQUE, analysis/python/cases/ch03_cycles.py, paramètres pédagogiques).31. ch03-fig-cycle-simule.pdf : quatre panneaux (demande et stock ; inoccupation ; loyer ; mises en chantier) après un choc de demande.42. ch03-fig-cycle-sensibilite.pdf : trajectoires du loyer selon le délai de livraison L et selon la réactivité de l'offre κ."""5import sys, pathlib6ROOT = pathlib.Path(__file__).resolve().parents[3]7sys.path.insert(0, str(ROOT / "analysis/python")); sys.path.insert(0, str(ROOT / "analysis/python/cases"))8from dataclasses import replace9import matplotlib.pyplot as plt10from traite.style import setup, palette, savefig, LARGEUR11import ch03_cycles as cas121314def fig_cycle(pc):15    df = cas.simuler_cycle(pc); ss = cas.etat_stationnaire_cycle(pc); ss0 = cas.etat_stationnaire_cycle(pc, apres_choc=False)16    x = df["annee"]17    fig, axs = plt.subplots(2, 2, figsize=(LARGEUR, 4.6), sharex=True)18    c0, c1, c2 = palette.cat[0], palette.cat[1], palette.cat[2]19    a = axs[0, 0]20    a.plot(x, df["S"] / 1000, color=c0, label="stock $S_t$")21    a.plot(x, df["D"] / 1000, color=c1, label="demande occupée $D_t$")22    a.axhline(ss["S"] / 1000, color=c0, lw=0.7, ls=":")23    a.set_ylabel("milliers de logements"); a.legend(loc="lower right", fontsize=7.5); a.set_title("A. Stock et demande", loc="left")24    a = axs[0, 1]25    a.plot(x, 100 * df["v"], color=c0)26    a.axhline(100 * pc.v_nat, color=palette.ink2, lw=0.8, ls="--"); a.text(x.iloc[-1], 100 * pc.v_nat + 0.15, "$v^*$", ha="right", fontsize=8, color=palette.ink2)27    a.set_ylabel("%"); a.set_title("B. Taux d'inoccupation $v_t$", loc="left"); a.set_ylim(0, None)28    a = axs[1, 0]29    a.plot(x, df["R_mois"], color=c0)30    a.axhline(ss["R"] / 12, color=palette.ink2, lw=0.8, ls="--"); a.text(x.iloc[-1], ss["R"] / 12 + 8, "nouveau stationnaire", ha="right", fontsize=7.5, color=palette.ink2)31    a.set_ylabel("$/mois"); a.set_title("C. Loyer $R_t$", loc="left"); a.set_xlabel("années depuis le début")32    a = axs[1, 1]33    a.plot(x, df["C_annuel"], color=c0)34    a.axhline(ss["C"], color=palette.ink2, lw=0.8, ls="--"); a.text(x.iloc[-1], ss["C"] + 80, "$\\delta S^*$", ha="right", fontsize=8, color=palette.ink2)35    a.set_ylabel("logements / an (rythme annuel)"); a.set_title("D. Mises en chantier $C_t$", loc="left"); a.set_xlabel("années depuis le début")36    for ax in axs.flat:37        ax.axvspan(pc.t_choc / 4, (pc.t_choc + pc.n_choc) / 4, color=palette.grid, alpha=0.6, lw=0)38    axs[0, 0].text((pc.t_choc + pc.n_choc / 2) / 4, axs[0, 0].get_ylim()[1] * 0.995, "choc de\ndemande", ha="center", va="top", fontsize=7, color=palette.ink2)39    fig.tight_layout(h_pad=1.0, w_pad=1.2)40    return savefig(fig, "ch03/ch03-fig-cycle-simule.pdf")414243def fig_sensibilite(pc):44    fig, axs = plt.subplots(1, 2, figsize=(LARGEUR, 2.7), sharey=True)45    ss = cas.etat_stationnaire_cycle(pc)46    for k, L in enumerate((2, 6, 12)):47        p = replace(pc, L=L); d = cas.simuler_cycle(p); s = cas.etat_stationnaire_cycle(p)48        axs[0].plot(d["annee"], 100 * (d["R"] / s["R"] - 1), color=palette.cat[k], label=f"$L$ = {L} trimestres")49    axs[0].set_title("A. Délai de livraison ($\\kappa$ = 0,48)", loc="left")50    for k, m in enumerate((1.0, 0.5, 0.25)):51        p = replace(pc, mult_c1=m); d = cas.simuler_cycle(p); s = cas.etat_stationnaire_cycle(p)52        axs[1].plot(d["annee"], 100 * (d["R"] / s["R"] - 1), color=palette.cat[k], label=f"$\\kappa$ = {p.kappa:.2f}")53    axs[1].set_title("B. Réactivité de l'offre ($L$ = 6)", loc="left")54    for ax in axs:55        ax.axhline(0, color=palette.ink2, lw=0.8, ls="--"); ax.set_xlabel("années depuis le début"); ax.legend(fontsize=7.5)56    axs[0].set_ylabel("loyer, écart au stationnaire final (%)")57    fig.tight_layout(w_pad=1.2)58    return savefig(fig, "ch03/ch03-fig-cycle-sensibilite.pdf")596061def main():62    setup()63    pc = cas.ParametresCycle()64    print("OK", fig_cycle(pc)); print("OK", fig_sensibilite(pc))656667if __name__ == "__main__":68    main()69
Files · 2eb2bf4e67f754808bae5090a9e53eab37149ddb
Menu

Theme