Align leave-one-out connected-set pruning with the official KSS MATLAB implementation#47
Open
ulrichwohak wants to merge 3 commits into
Open
Conversation
ulrichwohak
marked this pull request as ready for review
July 13, 2026 11:07
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #46.
Summary
This PR aligns leave-one-out connected-set construction with the released Kline–Saggio–Sølvsten (KSS) MATLAB implementation while preserving VCHDFE's public API and subsequent bias-correction code.
The change is deliberately limited to sample selection:
find_connected_set,prunning_connected_set,get_leave_one_out_set, their signatures and return fields, and the executable interface remain unchanged. The misspelled exported nameprunning_connected_setis retained for compatibility.Problem
The released MATLAB code and the previous Julia selector used different component objectives:
On a common sample, the two articulation graphs identify the same articulation workers. 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. The algorithms can therefore first diverge when selecting a surviving component: MATLAB maximizes the number of firms in the mobility component, whereas the previous Julia routine maximized the total number of worker and firm vertices.
The previous routine also retained a stale worker count across iterations. That state adds isolated phantom vertices and wastes memory, but does not appear to alter articulation workers or component selection. This PR recomputes current graph dimensions in every round without presenting the stale count as a separate correctness bug.
Reproduction
The regression fixture joins:
K(2, 3)mover core;After removing the articulation worker, the MATLAB rule retains the three-firm mover core (six observations). Total-vertex ranking instead retains the one-firm stayer component (twelve observations). This establishes algorithmic divergence without relying on private data.
Both selectors happen to agree on the public
test.csvfixture:Agreement on this fixture is useful for regression coverage, but it does not establish equivalence; the synthetic component-ranking example does.
Implementation
The new selector independently translates the behavior of the released MATLAB routines at commit
8b957ff:connected_set.mpruning_unbal_v3.mbuild_adj.mleave_out_KSS.mThe implementation:
ArgumentErrors for tied largest firm components and disappearance of the mover graph; andThe articulation graph retains the full current firm dimension, including isolated stayer-only firms, matching the MATLAB construction. Mover–firm edges are deduplicated before articulation detection.
Pruning is always leave-one-worker-out
get_leave_one_out_setalways constructs a raw-observation sample that remains connected after removing any one worker's complete history.VCHDFESettings.leave_out_leveldoes not alter sample pruning. Its"match"and"obs"values apply later, insideleave_out_estimation, when computing the bias correction on the selected sample.The new documentation page makes this separation explicit and records the old and new component rules.
Tests
The new always-run pruning suite covers:
Validated locally with Julia 1.8.5:
The standalone legacy command
julia +1.8.5 --project=. test/test_matrices.jlis not currently runnable onmain: it imports undeclaredDataFramesMeta, and after bypassing that import it references the removedeff_reshelper. This PR does not broaden scope into migrating that stale, non-CI test file; its pruning assertions are represented in the new always-run suite.Related: #17 concerns parallelization and performance; it is not a duplicate of this component-selection issue.
AI Attribution Statement
This work was created with an even blend of human and AI contributions. AI was used to make stylistic edits, such as changes to structure, wording, and clarity. AI was used to make content edits, such as changes to scope, information, and ideas. AI was used to make new content, such as text, images, analysis, and ideas. AI was prompted for its contributions, or AI assistance was enabled. AI-generated content was reviewed and approved. The following model(s) or application(s) were used: GPT 5.6 Sol.
AIA Human-AI blend, Stylistic edits, Content edits, New content, Human-initiated, Reviewed, GPT 5.6 Sol v1.0