"""Regola di scelta del modello (docs/algoritmi.md §6) su fit finti.""" from fitseg.analisi import scegli def fit(nome, k, aicc, rmse=0.1, scala_residui=0.1, **extra): base = {"modello": nome, "n_parametri": k, "aicc": aicc, "rmse": rmse, "scala_residui": scala_residui, "convergenza": True, "parametri_a_limite": [], "non_identificabile": False} return {**base, **extra} def test_vince_meno_parametri_entro_delta(cfg): scelto, _, _ = scegli([fit("a", 1, -100.0), fit("b", 3, -101.0)], 0.1, cfg) # ΔAICc = 1 < 2 assert scelto["modello"] == "a" def test_vince_il_migliore_oltre_delta(cfg): scelto, _, _ = scegli([fit("a", 1, -100.0), fit("b", 3, -110.0)], 0.1, cfg) assert scelto["modello"] == "b" def test_scarta_non_validi(cfg): fits = [fit("a", 1, -200.0, non_identificabile=True), fit("b", 2, -100.0), fit("c", 2, -300.0, parametri_a_limite=["tau"]), fit("d", 2, -400.0, convergenza=False)] assert scegli(fits, 0.1, cfg)[0]["modello"] == "b" def test_nessun_valido_indeterminato(cfg): scelto, motivo, adeguato = scegli([fit("a", 1, -1.0, non_identificabile=True)], 0.1, cfg) assert scelto is None and not adeguato and "nessun modello" in motivo def test_preferisce_i_modelli_adeguati(cfg): # b ha AICc molto migliore ma la scala dei residui supera soglia·σ; a è adeguato: vince tra gli adeguati scelto, _, adeguato = scegli([fit("a", 1, -50.0, scala_residui=0.1), fit("b", 3, -500.0, scala_residui=1.0)], 0.1, cfg) assert scelto["modello"] == "a" and adeguato def test_nessun_adeguato_lo_segnala(cfg): scelto, _, adeguato = scegli([fit("a", 1, -50.0, scala_residui=1.0)], 0.1, cfg) assert scelto["modello"] == "a" and adeguato is False def test_adeguatezza_usa_la_scala_robusta_non_la_rmse(cfg): # RMSE enorme per via degli scarti casuali, ma la scala robusta dei residui è vicina al rumore: adeguato scelto, _, adeguato = scegli([fit("a", 3, -50.0, rmse=0.5, scala_residui=0.11)], 0.1, cfg) assert scelto["modello"] == "a" and adeguato is True def test_sigma_non_stimabile_adeguatezza_non_valutabile(cfg): scelto, motivo, adeguato = scegli([fit("a", 1, -50.0)], None, cfg) assert scelto["modello"] == "a" and adeguato is None and "non valutabile" in motivo def test_motivo_senza_clausola_di_parsimonia_con_un_solo_candidato(cfg): assert "meno parametri" not in scegli([fit("a", 1, -50.0)], 0.1, cfg)[1] assert "meno parametri" in scegli([fit("a", 1, -50.0), fit("b", 3, -50.5)], 0.1, cfg)[1]