Summary
get_leave_one_out_set is documented as constructing the Kline–Saggio–Sølvsten (KSS) leave-one-out connected sample, but its component-selection rule differs from the released KSS MATLAB implementation.
This is a sample-construction issue, not a change to the exact/JLA correction formulas or to the leave_out_level setting.
Where the implementations differ
The current Julia implementation:
- constructs the initial full worker–firm bipartite graph in
find_connected_set;
- constructs another full bipartite graph after deleting articulation workers and ranks connected components by total vertices in
prunning_connected_set.
The released MATLAB implementation at commit 8b957ff:
- selects the largest component of the firm-transition graph by number of firms in
connected_set.m;
- constructs the articulation graph from movers and their unique worker–firm pairs in
pruning_unbal_v3.m;
- removes the complete histories of articulation workers;
- rebuilds the mover-induced firm-transition graph with
build_adj.m and again selects the largest component by number of firms;
- repeats to a fixed point.
For correctly ordered worker histories, the full bipartite and firm-transition representations induce the same partition of firms: a worker's bipartite star and that worker's transition path both connect all firms visited by the worker. The discrepancy is how components are ranked. The Julia code counts worker and firm vertices, while the MATLAB code counts firms.
Likewise, stayer workers are degree-one leaves. Leaves are never cut vertices, and attaching leaves to firm vertices cannot change whether a worker vertex is a cut vertex. Therefore, on any common current sample, the mover-only and full bipartite graphs identify the same articulation workers. The algorithms can first diverge only when selecting the surviving component: MATLAB ranks firm-mobility components by firms, while VCHDFE ranks full bipartite components by workers plus firms.
Minimal counterexample
Consider one connected network:
- Firms A, B, and C form a K(2,3) core: movers m1 and m2 are each observed at all three firms.
- Worker b connects C to firm D.
- Six stayers are each observed twice at D.
Worker b is an articulation worker. Once b is removed:
| component |
firms |
workers |
bipartite vertices |
raw observations |
| mover core |
3 |
2 |
5 |
6 |
| stayer-heavy component |
1 |
6 |
7 |
12 |
The MATLAB rule retains the three-firm mover core and its six observations. The current Julia rule retains firm D and the twelve stayer observations because that component contains more total bipartite vertices.
The bundled public KSS fixture does not expose the discrepancy: both selectors happen to retain 56,044 final observations. A synthetic component-ranking test is therefore needed.
Fixed-point detail
Algorithm 1 in the KSS computational appendix is printed as one deletion/component-selection pass. Its stated output must remain connected after removing any worker, and the released MATLAB routine implements that requirement with a while loop until no articulation worker remains. The Julia implementation should follow that executable fixed point.
Secondary state observation
firsts is initialized before the loop, while the in-loop relabeling assigns first_ids. The stale worker count adds isolated phantom worker vertices in later articulation graphs and wastes memory, but does not appear to alter articulation workers or component selection: phantom vertices cannot be cut vertices, firms remain above the stale offset, and the post-deletion component graph is rebuilt with current dimensions.
Proposed change
I plan to submit a PR that preserves the public API while:
- selecting components using mover-induced firm connectivity and firm counts;
- retaining the existing fixed-point deletion of complete articulation-worker histories;
- recomputing graph dimensions each round;
- keeping the final raw-observation singleton filter;
- adding the synthetic divergence, cascade, failure-mode, and released-fixture tests;
- documenting that leave-one-worker-out sample pruning is distinct from match/observation-level bias correction.
Related: #17 concerns parallelizing the connected-set routines; it is not a duplicate of this correctness issue.
Summary
get_leave_one_out_setis documented as constructing the Kline–Saggio–Sølvsten (KSS) leave-one-out connected sample, but its component-selection rule differs from the released KSS MATLAB implementation.This is a sample-construction issue, not a change to the exact/JLA correction formulas or to the
leave_out_levelsetting.Where the implementations differ
The current Julia implementation:
find_connected_set;prunning_connected_set.The released MATLAB implementation at commit
8b957ff:connected_set.m;pruning_unbal_v3.m;build_adj.mand again selects the largest component by number of firms;For correctly ordered worker histories, the full bipartite and firm-transition representations induce the same partition of firms: a worker's bipartite star and that worker's transition path both connect all firms visited by the worker. The discrepancy is how components are ranked. The Julia code counts worker and firm vertices, while the MATLAB code counts firms.
Likewise, stayer workers are degree-one leaves. Leaves are never cut vertices, and attaching leaves to firm vertices cannot change whether a worker vertex is a cut vertex. Therefore, on any common current sample, the mover-only and full bipartite graphs identify the same articulation workers. The algorithms can first diverge only when selecting the surviving component: MATLAB ranks firm-mobility components by firms, while VCHDFE ranks full bipartite components by workers plus firms.
Minimal counterexample
Consider one connected network:
Worker b is an articulation worker. Once b is removed:
The MATLAB rule retains the three-firm mover core and its six observations. The current Julia rule retains firm D and the twelve stayer observations because that component contains more total bipartite vertices.
The bundled public KSS fixture does not expose the discrepancy: both selectors happen to retain 56,044 final observations. A synthetic component-ranking test is therefore needed.
Fixed-point detail
Algorithm 1 in the KSS computational appendix is printed as one deletion/component-selection pass. Its stated output must remain connected after removing any worker, and the released MATLAB routine implements that requirement with a
whileloop until no articulation worker remains. The Julia implementation should follow that executable fixed point.Secondary state observation
firstsis initialized before the loop, while the in-loop relabeling assignsfirst_ids. The stale worker count adds isolated phantom worker vertices in later articulation graphs and wastes memory, but does not appear to alter articulation workers or component selection: phantom vertices cannot be cut vertices, firms remain above the stale offset, and the post-deletion component graph is rebuilt with current dimensions.Proposed change
I plan to submit a PR that preserves the public API while:
Related: #17 concerns parallelizing the connected-set routines; it is not a duplicate of this correctness issue.