22 """Likelihood synthétique (mélange de 2 gaussiennes) sur une grille."""
23 xs = np.linspace(-5.0, 5.0, 401)
24 w = np.exp(-0.5 * ((xs - (-1.2)) / 0.7) ** 2) + 0.65 * np.exp(-0.5 * (xs - 1.6) / 1.1) ** 2
26 return LikelihoodMarginalConfig(values=xs.tolist(), weights=w.tolist())
29@dataclass(frozen=True)
44 """Grille x basée sur des quantiles (robuste et adapté à la distrib)."""
48 if not (np.isfinite(x_lo)
and np.isfinite(x_hi)
and x_hi > x_lo):
49 raise ValueError(
"bad ppf range")
50 pad = 0.08 * (x_hi - x_lo)
51 return np.linspace(x_lo - pad, x_hi + pad, n)
53 return np.linspace(-6.0, 6.0, n)
72 name: str, dist, xs: np.ndarray, samples: np.ndarray, outpath: Optional[str] =
None
76 plt.figure(figsize=(10.2, 5.7))
77 plt.hist(samples, bins=60, density=
True, alpha=0.35, label=
"samples (density)")
78 plt.plot(xs, pdf, linewidth=2.3, label=
"pdf = exp(logpdf)")
81 q16, q50, q84 = dist.ppf(0.16), dist.ppf(0.50), dist.ppf(0.84)
82 q16, q50, q84 = float(q16), float(q50), float(q84)
83 if all(map(np.isfinite, [q16, q50, q84]))
and (q84 > q16):
84 plt.axvspan(q16, q84, alpha=0.12, label=
"68% interval [16%,84%]")
85 plt.axvline(q50, linestyle=
"--", linewidth=1.8, label=
"median (50%)")
90 mu = float(dist.mean())
92 plt.axvline(mu, linestyle=
":", linewidth=1.8, label=
"mean")
96 plt.title(f
"{name} — PDF vs samples")
99 plt.grid(
True, alpha=0.28)
101 plt.legend(frameon=
True)
105 plt.savefig(outpath, dpi=200)
110 name: str, dist, xs: np.ndarray, samples: np.ndarray, outpath: Optional[str] =
None
112 cdf_th =
_cdf(dist, xs)
113 s, y =
_ecdf(samples)
115 plt.figure(figsize=(10.2, 5.7))
116 plt.plot(xs, cdf_th, linewidth=2.4, label=
"theoretical CDF")
117 plt.step(s, y, where=
"post", linewidth=1.8, alpha=0.9, label=
"empirical CDF (ECDF)")
119 for p, ls
in [(0.25,
"--"), (0.50,
"--"), (0.75,
"--")]:
121 q = float(dist.ppf(p))
123 plt.axvline(q, linestyle=ls, linewidth=1.2)
127 plt.title(f
"{name} — CDF: theoretical vs empirical")
130 plt.ylim(-0.02, 1.02)
131 plt.grid(
True, alpha=0.28)
133 plt.legend(frameon=
True)
137 plt.savefig(outpath, dpi=200)
142 specs: List[DistSpec], seed: int, outpath: Optional[str] =
None
144 p = np.linspace(0.001, 0.999, 500)
146 plt.figure(figsize=(10.4, 5.8))
148 dist = DF.create(sp.kind, sp.cfg, seed=seed)
152 x = float(dist.ppf(float(pi)))
155 err.append(float(
"nan"))
156 err = np.array(err, dtype=float)
157 plt.plot(p, err, linewidth=2.1, label=sp.name)
159 plt.plot([0, 1], [0, 0], linestyle=
"--", linewidth=1.8, label=
"0 (ideal)")
160 plt.title(
"Sanity check — CDF(PPF(p)) − p (should be near 0)")
163 plt.grid(
True, alpha=0.28)
165 plt.legend(frameon=
True)
169 plt.savefig(outpath, dpi=200)
175 outdir: Optional[str] =
"marginal_plots",
177 n_samples: int = 3500,
179 specs: List[DistSpec] = [
180 DistSpec(
"Gaussian", MarginalKind.GAUSSIAN, GaussianMarginalConfig(mu=0.6, sigma=1.15)),
183 MarginalKind.HALF_GAUSSIAN,
184 SplitGaussianMarginalConfig(mu=0.0, sigma_p=0.75, sigma_m=1.55),
186 DistSpec(
"Flat", MarginalKind.FLAT, FlatMarginalConfig(a=-2.5, b=3.2)),
189 if outdir
is not None:
190 os.makedirs(outdir, exist_ok=
True)
193 dist = DF.create(sp.kind, sp.cfg, seed=seed)
196 samples = np.array(dist.rvs(n_samples), dtype=float)
198 pdf_path =
None if outdir
is None else os.path.join(outdir, f
"{sp.name}_pdf_samples.png")
199 cdf_path =
None if outdir
is None else os.path.join(outdir, f
"{sp.name}_cdf_ecdf.png")
204 global_path =
None if outdir
is None else os.path.join(outdir,
"global_cdf_ppf_consistency.png")