99 compute_clone_diagnostics_summary ,
1010 clone_diagnostics_path ,
1111 initialize_weight_priors ,
12+ PUF_CLONE_PRIOR_TOTAL_SHARE ,
1213 refresh_clone_diagnostics_report ,
1314 save_clone_diagnostics_report ,
15+ validate_clone_diagnostics ,
1416)
1517
1618
17- def test_initialize_weight_priors_gives_zero_weight_records_balanced_mass ():
19+ def test_initialize_weight_priors_gives_zero_weight_records_support_mass ():
1820 weights = np .array ([1_500.0 , 0.0 , 625.0 , 0.0 ], dtype = np .float64 )
1921
2022 priors = initialize_weight_priors (weights , seed = 123 )
2123
2224 assert np .all (priors > 0 )
2325 assert priors .sum () == pytest .approx (weights .sum ())
24- assert priors [[0 , 2 ]].sum () == pytest .approx (weights .sum () / 2 )
25- assert priors [[1 , 3 ]].sum () == pytest .approx (weights .sum () / 2 )
26+ assert priors [[1 , 3 ]].sum () == pytest .approx (
27+ weights .sum () * PUF_CLONE_PRIOR_TOTAL_SHARE
28+ )
29+ assert priors [[0 , 2 ]].sum () == pytest .approx (
30+ weights .sum () * (1 - PUF_CLONE_PRIOR_TOTAL_SHARE )
31+ )
2632 assert priors [1 ] == pytest .approx (priors [3 ])
2733 assert priors [0 ] / priors [2 ] == pytest .approx (weights [0 ] / weights [2 ])
2834
@@ -44,6 +50,15 @@ def test_initialize_weight_priors_is_reproducible():
4450 np .testing .assert_allclose (priors_a , priors_b )
4551
4652
53+ def test_initialize_weight_priors_honors_configured_zero_weight_share ():
54+ weights = np .array ([80.0 , 20.0 , 0.0 , 0.0 ])
55+
56+ priors = initialize_weight_priors (weights , zero_weight_total_share = 0.5 )
57+
58+ np .testing .assert_allclose (priors .sum (), 100.0 )
59+ np .testing .assert_allclose (priors , np .array ([40.0 , 10.0 , 25.0 , 25.0 ]))
60+
61+
4762def test_compute_clone_diagnostics_summary ():
4863 diagnostics = compute_clone_diagnostics_summary (
4964 household_is_puf_clone = [False , True ],
@@ -70,6 +85,49 @@ def test_compute_clone_diagnostics_summary():
7085 )
7186
7287
88+ def test_validate_clone_diagnostics_accepts_support_clone_share ():
89+ validate_clone_diagnostics (
90+ {
91+ "clone_household_weight_share_pct" : 10.0 ,
92+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
93+ }
94+ )
95+
96+
97+ def test_validate_clone_diagnostics_rejects_clone_starvation ():
98+ with pytest .raises (ValueError , match = "floor" ):
99+ validate_clone_diagnostics (
100+ {
101+ "clone_household_weight_share_pct" : 2.0 ,
102+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
103+ }
104+ )
105+
106+
107+ def test_validate_clone_diagnostics_accepts_high_share_no_cap ():
108+ # No upper cap on clone weight share (the household-count loss target governs
109+ # it); a high share with healthy tax quality must pass.
110+ validate_clone_diagnostics (
111+ {
112+ "clone_household_weight_share_pct" : 81.3 ,
113+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
114+ }
115+ )
116+
117+
118+ def test_validate_clone_diagnostics_rejects_clone_tax_pathology ():
119+ with pytest .raises (
120+ ValueError ,
121+ match = "PUF clone taxes-exceed-market-income share" ,
122+ ):
123+ validate_clone_diagnostics (
124+ {
125+ "clone_household_weight_share_pct" : 10.0 ,
126+ "clone_taxes_exceed_market_income_share_pct" : 66.6 ,
127+ }
128+ )
129+
130+
73131def test_build_clone_diagnostics_for_simulation_maps_household_weights (
74132 monkeypatch ,
75133):
@@ -201,7 +259,11 @@ class DummyDataset:
201259
202260 monkeypatch .setattr (
203261 "policyengine_us_data.datasets.cps.enhanced_cps.build_clone_diagnostics_for_saved_dataset" ,
204- lambda dataset_cls , period : {"clone_person_weight_share_pct" : float (period )},
262+ lambda dataset_cls , period : {
263+ "clone_person_weight_share_pct" : float (period ),
264+ "clone_household_weight_share_pct" : 10.0 ,
265+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
266+ },
205267 )
206268
207269 output_path , payload = save_clone_diagnostics_report (
@@ -213,8 +275,39 @@ class DummyDataset:
213275 assert output_path == clone_diagnostics_path (DummyDataset .file_path )
214276 assert payload == {
215277 "periods" : {
216- "2024" : {"clone_person_weight_share_pct" : 2024.0 },
217- "2025" : {"clone_person_weight_share_pct" : 2025.0 },
278+ "2024" : {
279+ "clone_person_weight_share_pct" : 2024.0 ,
280+ "clone_household_weight_share_pct" : 10.0 ,
281+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
282+ },
283+ "2025" : {
284+ "clone_person_weight_share_pct" : 2025.0 ,
285+ "clone_household_weight_share_pct" : 10.0 ,
286+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
287+ },
218288 }
219289 }
220290 assert output_path .exists ()
291+
292+
293+ def test_save_clone_diagnostics_report_rejects_bad_clone_payload (tmp_path , monkeypatch ):
294+ class DummyDataset :
295+ file_path = tmp_path / "enhanced_cps_2024.h5"
296+
297+ DummyDataset .file_path .write_text ("placeholder" )
298+
299+ monkeypatch .setattr (
300+ "policyengine_us_data.datasets.cps.enhanced_cps.build_clone_diagnostics_for_saved_dataset" ,
301+ lambda dataset_cls , period : {
302+ "clone_person_weight_share_pct" : 1.0 ,
303+ "clone_household_weight_share_pct" : 2.0 ,
304+ "clone_taxes_exceed_market_income_share_pct" : 5.0 ,
305+ },
306+ )
307+
308+ with pytest .raises (ValueError , match = "PUF clone household weight share" ):
309+ save_clone_diagnostics_report (
310+ DummyDataset ,
311+ start_year = 2024 ,
312+ end_year = 2024 ,
313+ )
0 commit comments