b-load 0.1.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. b_load-0.1.2/LICENSE +21 -0
  2. b_load-0.1.2/PKG-INFO +266 -0
  3. b_load-0.1.2/README.md +233 -0
  4. b_load-0.1.2/b_load.egg-info/PKG-INFO +266 -0
  5. b_load-0.1.2/b_load.egg-info/SOURCES.txt +36 -0
  6. b_load-0.1.2/b_load.egg-info/dependency_links.txt +1 -0
  7. b_load-0.1.2/b_load.egg-info/requires.txt +9 -0
  8. b_load-0.1.2/b_load.egg-info/top_level.txt +2 -0
  9. b_load-0.1.2/bload/__init__.py +10 -0
  10. b_load-0.1.2/bload/analysis.py +1 -0
  11. b_load-0.1.2/bload/background_knowledge.py +1 -0
  12. b_load-0.1.2/bload/counting_ci_tests.py +1 -0
  13. b_load-0.1.2/bload/data_generation.py +1 -0
  14. b_load-0.1.2/bload/evaluation.py +1 -0
  15. b_load-0.1.2/bload/load.py +1 -0
  16. b_load-0.1.2/bload/mb_by_mb.py +1 -0
  17. b_load-0.1.2/bload/pc.py +1 -0
  18. b_load-0.1.2/bload/real_data_applications/__init__.py +1 -0
  19. b_load-0.1.2/bload/real_data_applications/dream.py +1 -0
  20. b_load-0.1.2/bload/real_data_applications/sachs.py +1 -0
  21. b_load-0.1.2/bload/running.py +1 -0
  22. b_load-0.1.2/bload/utils.py +1 -0
  23. b_load-0.1.2/pyproject.toml +55 -0
  24. b_load-0.1.2/setup.cfg +4 -0
  25. b_load-0.1.2/src/__init__.py +5 -0
  26. b_load-0.1.2/src/analysis.py +805 -0
  27. b_load-0.1.2/src/background_knowledge.py +283 -0
  28. b_load-0.1.2/src/counting_ci_tests.py +101 -0
  29. b_load-0.1.2/src/data_generation.py +185 -0
  30. b_load-0.1.2/src/evaluation.py +642 -0
  31. b_load-0.1.2/src/load.py +553 -0
  32. b_load-0.1.2/src/mb_by_mb.py +930 -0
  33. b_load-0.1.2/src/pc.py +341 -0
  34. b_load-0.1.2/src/real_data_applications/__init__.py +1 -0
  35. b_load-0.1.2/src/real_data_applications/dream.py +306 -0
  36. b_load-0.1.2/src/real_data_applications/sachs.py +202 -0
  37. b_load-0.1.2/src/running.py +1194 -0
  38. b_load-0.1.2/src/utils.py +106 -0
b_load-0.1.2/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 b-LOAD contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
b_load-0.1.2/PKG-INFO ADDED
@@ -0,0 +1,266 @@
1
+ Metadata-Version: 2.4
2
+ Name: b-load
3
+ Version: 0.1.2
4
+ Summary: Background-Knowledge-Augmented Local Causal Discovery
5
+ Author: b-LOAD contributors
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/chrisahn99/b-load
8
+ Project-URL: Repository, https://github.com/chrisahn99/b-load
9
+ Project-URL: Issues, https://github.com/chrisahn99/b-load/issues
10
+ Keywords: causal discovery,background knowledge,graph learning,statistics,python
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
+ Classifier: Topic :: Scientific/Engineering :: Information Analysis
20
+ Requires-Python: >=3.9
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: causal-learn
24
+ Requires-Dist: rpy2
25
+ Requires-Dist: networkx
26
+ Requires-Dist: numpy
27
+ Requires-Dist: pandas
28
+ Requires-Dist: scikit-learn
29
+ Requires-Dist: scipy
30
+ Requires-Dist: matplotlib
31
+ Requires-Dist: tqdm
32
+ Dynamic: license-file
33
+
34
+ <h1 align="center">b-LOAD: Background-Knowledge-Augmented Local Causal Discovery
35
+ </h1>
36
+
37
+ <p>
38
+ <strong>b-Load</strong> is a knowledge-informed extension of the Local Ordering-based Ancestral Discovery (LOAD) algorithm for local causal discovery of optimal adjustment sets. It integrates prior edge constraints into local structure learning and dynamically expands the discovery frontier using Meek's rules, producing knowledge-constrained maximal partially directed acyclic graphs. By leveraging background knowledge, <strong>b-Load</strong> reduces structural uncertainty and enables the identification of adjustment sets that may not be identifiable from observational data alone. The method improves causal effect estimation, particularly in data-scarce and structurally complex settings, while maintaining scalability and robustness to moderate noise in prior knowledge.
39
+ </p>
40
+
41
+ <p align="center">
42
+ <a href="#theproblem">Problem</a> &bull;
43
+ <a href="#install">Install</a> &bull;
44
+ <a href="#quickstart">Quickstart</a> &bull;
45
+ <a href="#results">Results</a> &bull;
46
+ <a href="#reproducing-the-paper">Paper</a>
47
+ </p>
48
+
49
+ <p align="center">
50
+ <a href="https://doi.org/10.1145/3799682.3840893"><img alt="DOI" src="https://img.shields.io/badge/DOI-10.1145%2F3799682.3840893-1f6feb"></a>
51
+ <a href="https://pypi.org/project/b-load/"><img alt="PyPI" src="https://img.shields.io/pypi/v/b-load"></a>
52
+ <a href="https://pypi.org/project/b-load/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/b-load"></a>
53
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-green"></a>
54
+ </p>
55
+
56
+ ---
57
+
58
+ ## The Problem
59
+
60
+ Local causal discovery methods such as LOAD can recover adjustment sets without learning the full global graph, but they operate under uncertainty and may miss identifiable causal directions that are already known from domain knowledge. This project addresses that limitation by augmenting the local search with background knowledge and Meek-rule propagation.
61
+
62
+ ### LOAD (base)
63
+ The base LOAD algorithm performs local causal structure learning around a target node using a Markov-blanket-by-Markov-blanket (MB-by-MB) expansion. It identifies the optimal adjustment set (o-set) for a treatment–outcome pair without reconstructing the full global graph. The core MB-by-MB implementation in `src/mb_by_mb.py` and the top-level estimation logic in `src/load.py` are adapted from the original LOAD authors' public implementation. The public package exposes these components via `bload.mb_by_mb` and `bload.load`.
64
+
65
+ ### b-LOAD (this work)
66
+ b-LOAD extends LOAD with three key modifications to the MB-by-MB loop:
67
+
68
+ 1. **BK initialisation** — the growing graph is seeded with required background-knowledge edges so that known causal directions are present from the first iteration.
69
+ 2. **BK-protected graph update** — after each local structure is merged, required edges are re-stamped to prevent CI-test errors from erasing known constraints.
70
+ 3. **Four-rule MPDAG Meek** — a fourth Meek orientation rule (using the sep-set from skeleton search) propagates orientations induced by BK edges that the three structural rules alone cannot deduce.
71
+
72
+ ### b-PC (baseline)
73
+ b-PC runs the standard PC algorithm to produce a CPDAG, injects required background-knowledge edges, and then applies four-rule Meek to propagate the induced orientations.
74
+
75
+ ### Graph encoding
76
+
77
+ Throughout the implementation, adjacency matrices use the following internal convention:
78
+
79
+ | `g[i, j]` | `g[j, i]` | Meaning |
80
+ |-----------|-----------|---------|
81
+ | `-1` | `-1` | Undirected edge i — j |
82
+ | `-1` | `+1` | Directed edge i → j |
83
+ | `0` | `0` | No edge |
84
+
85
+ Background knowledge is encoded identically: `bk[i,j] = -1` and `bk[j,i] = 1` for a required edge i → j.
86
+
87
+ The final `"amat"` output (returned by `pc` and `pc_with_bk`) follows the `pcalg` convention: `amat[i][j] = 1` indicates a tail at i (edge from i toward j, directed or undirected).
88
+
89
+ ---
90
+
91
+ ## Install
92
+
93
+ ### Requirements
94
+
95
+ Install the package from PyPI:
96
+
97
+ ```bash
98
+ pip install b-load
99
+ ```
100
+
101
+ Or install from source in editable mode:
102
+
103
+ ```bash
104
+ git clone https://github.com/chrisahn99/b-load.git
105
+ cd b-load
106
+ pip install -e .
107
+ ```
108
+
109
+ R dependencies (required for data generation and CPDAG/optAdjSet computation):
110
+
111
+ ```r
112
+ install.packages(c("pcalg", "graph", "RBGL"))
113
+ ```
114
+
115
+ The R scripts `generate_data.R` and `evaluate.R` are sourced automatically when the package is imported.
116
+
117
+ ### Repository structure
118
+
119
+ ```text
120
+ .
121
+ ├── bload/ # Public import namespace for pip users
122
+ │ ├── __init__.py # Package version metadata
123
+ │ ├── load.py # Re-export of src.load
124
+ │ ├── pc.py # Re-export of src.pc
125
+ │ ├── running.py # Re-export of src.running
126
+ │ ├── analysis.py # Re-export of src.analysis
127
+ │ ├── background_knowledge.py # Re-export of src.background_knowledge
128
+ │ ├── data_generation.py # Re-export of src.data_generation
129
+ │ ├── evaluation.py # Re-export of src.evaluation
130
+ │ ├── mb_by_mb.py # Re-export of src.mb_by_mb
131
+ │ ├── counting_ci_tests.py # Re-export of src.counting_ci_tests
132
+ │ ├── utils.py # Re-export of src.utils
133
+ │ └── real_data_applications/
134
+ │ ├── __init__.py
135
+ │ ├── sachs.py # Sachs protein-signalling dataset helpers
136
+ │ └── dream.py # DREAM4 / DREAM5 benchmark helpers
137
+ │
138
+ ├── src/ # Internal implementation package
139
+ │ ├── ...
140
+ │
141
+ ├── experiment_scripts/ # Entry-point scripts for each experimental condition
142
+ │ ├── run_load_local_bk.py
143
+ │ ├── run_load_global_bk.py
144
+ │ ├── run_load_noised.py
145
+ │ ├── run_pc.py
146
+ │ ├── run_bpc_local_bk.py
147
+ │ └── run_bpc_global_bk.py
148
+ │
149
+ ├── generate_data.R
150
+ ├── evaluate.R
151
+ ├── pyproject.toml
152
+ ├── requirements.txt
153
+ ├── LICENSE
154
+ ├── README.md
155
+ └── .github/workflows/publish.yml
156
+ ```
157
+
158
+ ---
159
+
160
+ ## Quickstart
161
+
162
+ ### Running experiments
163
+
164
+ Each script in `experiment_scripts/` accepts a `--save_path` argument and optional graph/sample-size parameters. Example usage:
165
+
166
+ ```bash
167
+ # b-LOAD vs LOAD with locally sampled background knowledge
168
+ python experiment_scripts/run_load_local_bk.py --save_path experiment_runs/load_local.csv
169
+
170
+ # b-PC with globally sampled background knowledge
171
+ python experiment_scripts/run_bpc_global_bk.py --save_path experiment_runs/bpc_global.csv
172
+
173
+ # PC baseline (no background knowledge)
174
+ python experiment_scripts/run_pc.py --save_path experiment_runs/pc.csv
175
+ ```
176
+
177
+ > **Note:** Output files are written to `experiment_runs/` by default. Create this directory locally if needed — it is excluded from version control.
178
+
179
+ ### Background knowledge sampling strategies
180
+
181
+ Two strategies are available (controlled by the `sampling_strategy` argument in experiment runners):
182
+
183
+ - **`"local"`** — only edges incident on the treatment or outcome nodes are sampled as required BK. This is the primary strategy evaluated in the paper.
184
+ - **`"global"`** — required edges are drawn uniformly from all true edges in the DAG.
185
+
186
+ The fraction of edges revealed is controlled by `fraction_required` (0–1).
187
+
188
+ ### Real-data experiments
189
+
190
+ Real-data runners for the Sachs protein-signalling and DREAM4/DREAM5 benchmarks are provided in `bload.real_data_applications` and `src/real_data_applications`. Place the data files under `experiments/dream4/` and `experiments/dream5/` respectively, then call:
191
+
192
+ ```python
193
+ from bload.real_data_applications.dream import run_experiment_dream4, run_experiment_dream5
194
+ from bload.real_data_applications.sachs import get_sachs_ground_truth_dag, fit_oracle_weights
195
+
196
+ # DREAM4 network 1, local BK, 30 % of true edges revealed
197
+ result_dict, details_dict = run_experiment_dream4(subset_number=1, sampling_strategy="local", frac_req=0.3)
198
+ ```
199
+
200
+ ### Analysing results
201
+
202
+ `bload.analysis` provides utilities for loading result CSVs, computing the complexity metric $\pi = n_{samples} / (n_{nodes} \times expected\_degree / 2)$, aggregating into regime tables, and producing F1 and intervention-distance plots:
203
+
204
+ ```python
205
+ from bload.analysis import load_iter_folder, add_complexity_metric, regime_table_3, plot_f1
206
+
207
+ df_bload = load_iter_folder("experiment_runs/load_local_*", stat_col_pairs=[...])
208
+ df_bload = add_complexity_metric(df_bload)
209
+ fig = plot_f1(df_pc, df_bpc, df_bpc_global, df_load, df_bload_global)
210
+ ```
211
+
212
+ ---
213
+
214
+ ## Results
215
+
216
+ The repository is organized around the experimental comparison between standard LOAD, background-knowledge-augmented b-LOAD, and PC-style baselines. The key outputs are CSV result files produced by the experiment scripts and summary plots generated via `src/analysis.py`.
217
+
218
+ These experiments typically report:
219
+
220
+ - structural accuracy (precision, recall, F1),
221
+ - intervention-distance performance,
222
+ - the effect of revealed background knowledge on adjustment-set identification, and
223
+ - robustness under partially noisy background knowledge.
224
+
225
+ The analysis utilities in `src/analysis.py` let you aggregate runs across graph sizes, sampling strategies, and difficulty regimes and visualize the outcome trends.
226
+
227
+ ---
228
+
229
+ ## Reproducing the Paper
230
+
231
+ To reproduce the paper's experiments:
232
+
233
+ 1. Install the Python and R dependencies listed in the installation section.
234
+ 2. Run the synthetic experiment scripts in `experiment_scripts/` with the desired background-knowledge setting.
235
+ 3. Save the resulting outputs under `experiment_runs/`.
236
+ 4. Use the analysis utilities in `src/analysis.py` to aggregate metrics and generate plots.
237
+
238
+ This workflow matches the study design used to compare:
239
+
240
+ - LOAD without background knowledge,
241
+ - b-LOAD with local and global background knowledge,
242
+ - b-PC with the same background-knowledge settings, and
243
+ - the PC baseline without knowledge augmentation.
244
+
245
+ ---
246
+
247
+ ## Citation
248
+
249
+ If you use this code, please cite:
250
+
251
+ ```bibtex
252
+ @inproceedings{ahnbload206,
253
+ author = {Ahn, Seong Woo and Leite, Alessandro and De Melo Costa, Jos{\'e} Lucas and Popineau, Fabrice and Doan, Bich-Li{\^e}n and Rimmel, Arpad},
254
+ title = {Knowledge-Informed Local Causal Discovery of Optimal Adjustment Sets},
255
+ year = {2026},
256
+ doi = {10.1145/3799682.3840893},
257
+ booktitle = {The 35th ACM International Conference on Information and Knowledge Management},
258
+ pages = {72--82},
259
+ }
260
+ ```
261
+
262
+ ---
263
+
264
+ ## License
265
+
266
+ MIT, see [LICENSE](LICENSE).
b_load-0.1.2/README.md ADDED
@@ -0,0 +1,233 @@
1
+ <h1 align="center">b-LOAD: Background-Knowledge-Augmented Local Causal Discovery
2
+ </h1>
3
+
4
+ <p>
5
+ <strong>b-Load</strong> is a knowledge-informed extension of the Local Ordering-based Ancestral Discovery (LOAD) algorithm for local causal discovery of optimal adjustment sets. It integrates prior edge constraints into local structure learning and dynamically expands the discovery frontier using Meek's rules, producing knowledge-constrained maximal partially directed acyclic graphs. By leveraging background knowledge, <strong>b-Load</strong> reduces structural uncertainty and enables the identification of adjustment sets that may not be identifiable from observational data alone. The method improves causal effect estimation, particularly in data-scarce and structurally complex settings, while maintaining scalability and robustness to moderate noise in prior knowledge.
6
+ </p>
7
+
8
+ <p align="center">
9
+ <a href="#theproblem">Problem</a> &bull;
10
+ <a href="#install">Install</a> &bull;
11
+ <a href="#quickstart">Quickstart</a> &bull;
12
+ <a href="#results">Results</a> &bull;
13
+ <a href="#reproducing-the-paper">Paper</a>
14
+ </p>
15
+
16
+ <p align="center">
17
+ <a href="https://doi.org/10.1145/3799682.3840893"><img alt="DOI" src="https://img.shields.io/badge/DOI-10.1145%2F3799682.3840893-1f6feb"></a>
18
+ <a href="https://pypi.org/project/b-load/"><img alt="PyPI" src="https://img.shields.io/pypi/v/b-load"></a>
19
+ <a href="https://pypi.org/project/b-load/"><img alt="Python" src="https://img.shields.io/pypi/pyversions/b-load"></a>
20
+ <a href="LICENSE"><img alt="License" src="https://img.shields.io/badge/license-MIT-green"></a>
21
+ </p>
22
+
23
+ ---
24
+
25
+ ## The Problem
26
+
27
+ Local causal discovery methods such as LOAD can recover adjustment sets without learning the full global graph, but they operate under uncertainty and may miss identifiable causal directions that are already known from domain knowledge. This project addresses that limitation by augmenting the local search with background knowledge and Meek-rule propagation.
28
+
29
+ ### LOAD (base)
30
+ The base LOAD algorithm performs local causal structure learning around a target node using a Markov-blanket-by-Markov-blanket (MB-by-MB) expansion. It identifies the optimal adjustment set (o-set) for a treatment–outcome pair without reconstructing the full global graph. The core MB-by-MB implementation in `src/mb_by_mb.py` and the top-level estimation logic in `src/load.py` are adapted from the original LOAD authors' public implementation. The public package exposes these components via `bload.mb_by_mb` and `bload.load`.
31
+
32
+ ### b-LOAD (this work)
33
+ b-LOAD extends LOAD with three key modifications to the MB-by-MB loop:
34
+
35
+ 1. **BK initialisation** — the growing graph is seeded with required background-knowledge edges so that known causal directions are present from the first iteration.
36
+ 2. **BK-protected graph update** — after each local structure is merged, required edges are re-stamped to prevent CI-test errors from erasing known constraints.
37
+ 3. **Four-rule MPDAG Meek** — a fourth Meek orientation rule (using the sep-set from skeleton search) propagates orientations induced by BK edges that the three structural rules alone cannot deduce.
38
+
39
+ ### b-PC (baseline)
40
+ b-PC runs the standard PC algorithm to produce a CPDAG, injects required background-knowledge edges, and then applies four-rule Meek to propagate the induced orientations.
41
+
42
+ ### Graph encoding
43
+
44
+ Throughout the implementation, adjacency matrices use the following internal convention:
45
+
46
+ | `g[i, j]` | `g[j, i]` | Meaning |
47
+ |-----------|-----------|---------|
48
+ | `-1` | `-1` | Undirected edge i — j |
49
+ | `-1` | `+1` | Directed edge i → j |
50
+ | `0` | `0` | No edge |
51
+
52
+ Background knowledge is encoded identically: `bk[i,j] = -1` and `bk[j,i] = 1` for a required edge i → j.
53
+
54
+ The final `"amat"` output (returned by `pc` and `pc_with_bk`) follows the `pcalg` convention: `amat[i][j] = 1` indicates a tail at i (edge from i toward j, directed or undirected).
55
+
56
+ ---
57
+
58
+ ## Install
59
+
60
+ ### Requirements
61
+
62
+ Install the package from PyPI:
63
+
64
+ ```bash
65
+ pip install b-load
66
+ ```
67
+
68
+ Or install from source in editable mode:
69
+
70
+ ```bash
71
+ git clone https://github.com/chrisahn99/b-load.git
72
+ cd b-load
73
+ pip install -e .
74
+ ```
75
+
76
+ R dependencies (required for data generation and CPDAG/optAdjSet computation):
77
+
78
+ ```r
79
+ install.packages(c("pcalg", "graph", "RBGL"))
80
+ ```
81
+
82
+ The R scripts `generate_data.R` and `evaluate.R` are sourced automatically when the package is imported.
83
+
84
+ ### Repository structure
85
+
86
+ ```text
87
+ .
88
+ ├── bload/ # Public import namespace for pip users
89
+ │ ├── __init__.py # Package version metadata
90
+ │ ├── load.py # Re-export of src.load
91
+ │ ├── pc.py # Re-export of src.pc
92
+ │ ├── running.py # Re-export of src.running
93
+ │ ├── analysis.py # Re-export of src.analysis
94
+ │ ├── background_knowledge.py # Re-export of src.background_knowledge
95
+ │ ├── data_generation.py # Re-export of src.data_generation
96
+ │ ├── evaluation.py # Re-export of src.evaluation
97
+ │ ├── mb_by_mb.py # Re-export of src.mb_by_mb
98
+ │ ├── counting_ci_tests.py # Re-export of src.counting_ci_tests
99
+ │ ├── utils.py # Re-export of src.utils
100
+ │ └── real_data_applications/
101
+ │ ├── __init__.py
102
+ │ ├── sachs.py # Sachs protein-signalling dataset helpers
103
+ │ └── dream.py # DREAM4 / DREAM5 benchmark helpers
104
+ │
105
+ ├── src/ # Internal implementation package
106
+ │ ├── ...
107
+ │
108
+ ├── experiment_scripts/ # Entry-point scripts for each experimental condition
109
+ │ ├── run_load_local_bk.py
110
+ │ ├── run_load_global_bk.py
111
+ │ ├── run_load_noised.py
112
+ │ ├── run_pc.py
113
+ │ ├── run_bpc_local_bk.py
114
+ │ └── run_bpc_global_bk.py
115
+ │
116
+ ├── generate_data.R
117
+ ├── evaluate.R
118
+ ├── pyproject.toml
119
+ ├── requirements.txt
120
+ ├── LICENSE
121
+ ├── README.md
122
+ └── .github/workflows/publish.yml
123
+ ```
124
+
125
+ ---
126
+
127
+ ## Quickstart
128
+
129
+ ### Running experiments
130
+
131
+ Each script in `experiment_scripts/` accepts a `--save_path` argument and optional graph/sample-size parameters. Example usage:
132
+
133
+ ```bash
134
+ # b-LOAD vs LOAD with locally sampled background knowledge
135
+ python experiment_scripts/run_load_local_bk.py --save_path experiment_runs/load_local.csv
136
+
137
+ # b-PC with globally sampled background knowledge
138
+ python experiment_scripts/run_bpc_global_bk.py --save_path experiment_runs/bpc_global.csv
139
+
140
+ # PC baseline (no background knowledge)
141
+ python experiment_scripts/run_pc.py --save_path experiment_runs/pc.csv
142
+ ```
143
+
144
+ > **Note:** Output files are written to `experiment_runs/` by default. Create this directory locally if needed — it is excluded from version control.
145
+
146
+ ### Background knowledge sampling strategies
147
+
148
+ Two strategies are available (controlled by the `sampling_strategy` argument in experiment runners):
149
+
150
+ - **`"local"`** — only edges incident on the treatment or outcome nodes are sampled as required BK. This is the primary strategy evaluated in the paper.
151
+ - **`"global"`** — required edges are drawn uniformly from all true edges in the DAG.
152
+
153
+ The fraction of edges revealed is controlled by `fraction_required` (0–1).
154
+
155
+ ### Real-data experiments
156
+
157
+ Real-data runners for the Sachs protein-signalling and DREAM4/DREAM5 benchmarks are provided in `bload.real_data_applications` and `src/real_data_applications`. Place the data files under `experiments/dream4/` and `experiments/dream5/` respectively, then call:
158
+
159
+ ```python
160
+ from bload.real_data_applications.dream import run_experiment_dream4, run_experiment_dream5
161
+ from bload.real_data_applications.sachs import get_sachs_ground_truth_dag, fit_oracle_weights
162
+
163
+ # DREAM4 network 1, local BK, 30 % of true edges revealed
164
+ result_dict, details_dict = run_experiment_dream4(subset_number=1, sampling_strategy="local", frac_req=0.3)
165
+ ```
166
+
167
+ ### Analysing results
168
+
169
+ `bload.analysis` provides utilities for loading result CSVs, computing the complexity metric $\pi = n_{samples} / (n_{nodes} \times expected\_degree / 2)$, aggregating into regime tables, and producing F1 and intervention-distance plots:
170
+
171
+ ```python
172
+ from bload.analysis import load_iter_folder, add_complexity_metric, regime_table_3, plot_f1
173
+
174
+ df_bload = load_iter_folder("experiment_runs/load_local_*", stat_col_pairs=[...])
175
+ df_bload = add_complexity_metric(df_bload)
176
+ fig = plot_f1(df_pc, df_bpc, df_bpc_global, df_load, df_bload_global)
177
+ ```
178
+
179
+ ---
180
+
181
+ ## Results
182
+
183
+ The repository is organized around the experimental comparison between standard LOAD, background-knowledge-augmented b-LOAD, and PC-style baselines. The key outputs are CSV result files produced by the experiment scripts and summary plots generated via `src/analysis.py`.
184
+
185
+ These experiments typically report:
186
+
187
+ - structural accuracy (precision, recall, F1),
188
+ - intervention-distance performance,
189
+ - the effect of revealed background knowledge on adjustment-set identification, and
190
+ - robustness under partially noisy background knowledge.
191
+
192
+ The analysis utilities in `src/analysis.py` let you aggregate runs across graph sizes, sampling strategies, and difficulty regimes and visualize the outcome trends.
193
+
194
+ ---
195
+
196
+ ## Reproducing the Paper
197
+
198
+ To reproduce the paper's experiments:
199
+
200
+ 1. Install the Python and R dependencies listed in the installation section.
201
+ 2. Run the synthetic experiment scripts in `experiment_scripts/` with the desired background-knowledge setting.
202
+ 3. Save the resulting outputs under `experiment_runs/`.
203
+ 4. Use the analysis utilities in `src/analysis.py` to aggregate metrics and generate plots.
204
+
205
+ This workflow matches the study design used to compare:
206
+
207
+ - LOAD without background knowledge,
208
+ - b-LOAD with local and global background knowledge,
209
+ - b-PC with the same background-knowledge settings, and
210
+ - the PC baseline without knowledge augmentation.
211
+
212
+ ---
213
+
214
+ ## Citation
215
+
216
+ If you use this code, please cite:
217
+
218
+ ```bibtex
219
+ @inproceedings{ahnbload206,
220
+ author = {Ahn, Seong Woo and Leite, Alessandro and De Melo Costa, Jos{\'e} Lucas and Popineau, Fabrice and Doan, Bich-Li{\^e}n and Rimmel, Arpad},
221
+ title = {Knowledge-Informed Local Causal Discovery of Optimal Adjustment Sets},
222
+ year = {2026},
223
+ doi = {10.1145/3799682.3840893},
224
+ booktitle = {The 35th ACM International Conference on Information and Knowledge Management},
225
+ pages = {72--82},
226
+ }
227
+ ```
228
+
229
+ ---
230
+
231
+ ## License
232
+
233
+ MIT, see [LICENSE](LICENSE).