plainproof 0.1.1__tar.gz → 0.2.0__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.
- {plainproof-0.1.1 → plainproof-0.2.0}/.gitignore +1 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/CITATION.cff +1 -1
- {plainproof-0.1.1 → plainproof-0.2.0}/PKG-INFO +37 -34
- {plainproof-0.1.1 → plainproof-0.2.0}/README.md +36 -33
- {plainproof-0.1.1 → plainproof-0.2.0}/pyproject.toml +1 -1
- plainproof-0.2.0/setup.py +31 -0
- plainproof-0.2.0/src/plainproof/cli.py +121 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/PKG-INFO +37 -34
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/SOURCES.txt +1 -0
- plainproof-0.1.1/src/plainproof/cli.py +0 -82
- {plainproof-0.1.1 → plainproof-0.2.0}/LICENSE +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/LICENSE-docs.md +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/MANIFEST.in +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/calibration-v2.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/calibration-v2.receipt.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/calibration.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/calibration.receipt.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/pilot.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/data/edm-v2-e0/study/tune.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/docs/PREREG_EDM_V2.md +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/docs/PROTOCOL_E0.md +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0/error-vs-d.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0/figures/error-vs-d.png +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0/freeze.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0/results-numbers.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0/signature-table.md +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0b/figures/probe-auc-vs-d.png +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0b/freeze.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0b/numbers.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0b/probe-auc-vs-d.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/edm-v2-e0b/probe-table.md +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/receipts/assist2009-dev-2pl.receipt.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/receipts/bobcat-gate.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/receipts/bobcat-run-settings.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/reports/receipts/catirt-install-receipt.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/requirements.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/bobcat/check_checkpoint.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/bobcat/fetch_bobcat.sh +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/bobcat/retrain.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/bobcat_gate.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/catirt_sprt_steps.R +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/fit_assist2009.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/heldout.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/install_catirt.R +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/pilot.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/plot_error_vs_d.R +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/r_env.sh +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/report.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/repro_paths.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0/study.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0b/plot_probe_auc.R +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0b/report.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/edm_v2_e0b/run.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/fetch_heldout.sh +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/published_cat_reference_v1/bobcat_support.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/published_cat_reference_v1/compare_selection_v1.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/rscript.sh +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/scripts/verify_frozen.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/setup.cfg +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/__init__.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/bank_from_fit.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/fit.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/irt.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/planted.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/reliability.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/signature.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/simulator.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/sprt.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof/stopping.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/dependency_links.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/entry_points.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/requires.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/src/plainproof.egg-info/top_level.txt +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/substitutions.json +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/conftest.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/fixtures/edm_v2_catirt_sprt/bank.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/fixtures/edm_v2_catirt_sprt/config.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/fixtures/edm_v2_catirt_sprt/resp.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/fixtures/edm_v2_catirt_sprt/steps.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/fixtures/edm_v2_catirt_sprt/terminal.csv +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/test_edm_v2_e0.py +0 -0
- {plainproof-0.1.1 → plainproof-0.2.0}/tests/test_edm_v2_e0b.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plainproof
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Reproduction tool for the paper 'How many follow-up questions distinguish genuine understanding from apparent mastery?'. Not a general library. Its sealed checks can stop a run on purpose.
|
|
5
5
|
Author: Vishnu Vettrivel
|
|
6
6
|
License-Expression: MIT
|
|
@@ -27,51 +27,33 @@ Reproduction package for **"How many follow-up questions distinguish genuine und
|
|
|
27
27
|
|
|
28
28
|
Everything here is CPU-only and needs no paid service. Code: MIT (`LICENSE`). Docs, figures and tables: CC BY 4.0 (`LICENSE-docs.md`).
|
|
29
29
|
|
|
30
|
-
## From
|
|
31
|
-
|
|
32
|
-
The `plainproof` command runs each step (`plainproof --help`); the raw script calls below are what it runs. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; use the `scripts/rscript.sh` wrapper, which `plainproof figures` calls.
|
|
30
|
+
## From install to the figure (about 10 minutes)
|
|
33
31
|
|
|
34
32
|
```sh
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
plainproof verify
|
|
43
|
-
|
|
44
|
-
# 3. Fetch the sealed held-out outputs (from the v0.1.0 release assets) and check their hashes
|
|
45
|
-
plainproof fetch heldout
|
|
46
|
-
|
|
47
|
-
# 4. Rebuild the tables and figures from the held-out summaries (needs R 4.x for the plots; base graphics only)
|
|
48
|
-
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json
|
|
49
|
-
scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png aff9a8c49d48821c0e9343cd058c4e0e2f1659ffabcaa719824412f3b14abc90
|
|
50
|
-
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
51
|
-
scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png 617be427feac24df2e342da00d34e91c78d5de91592cee390ef3516ae9e2ff3f
|
|
33
|
+
pip install 'plainproof[test,run]'
|
|
34
|
+
plainproof init ~/plainproof # writes the working directory: sealed scripts, freezes, receipts, docs, tests
|
|
35
|
+
cd ~/plainproof
|
|
36
|
+
plainproof test # 43 tests: SPRT against catIrt 0.5.1's saved steps, exact stopping time, simulator, signatures, probes
|
|
37
|
+
plainproof verify # every sealed file against both freezes (undoes the documented substitutions, then sha256)
|
|
38
|
+
plainproof fetch heldout # the sealed held-out outputs, hash-checked
|
|
39
|
+
plainproof figures # tables and figures from the held-out summaries (needs R 4.x on PATH; base graphics only)
|
|
52
40
|
```
|
|
53
41
|
|
|
54
|
-
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures
|
|
42
|
+
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures/`, byte-identical to the published copies. `plainproof init` writes the files in the exact layout the sealed scripts expect; nothing sealed changes. Every other command runs inside that directory, or takes `--root DIR`. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; the `scripts/rscript.sh` wrapper, which `plainproof figures` calls, is the one to use.
|
|
55
43
|
|
|
56
44
|
## Full rerun (about 4 hours of CPU)
|
|
57
45
|
|
|
58
46
|
Only if you want to regenerate everything, including the held-out outputs.
|
|
59
47
|
|
|
60
48
|
```sh
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# c. Retrain the BOBCAT checkpoint (about 2 hours; author defaults, fold 1, seed 221), then compare it with the original
|
|
67
|
-
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py
|
|
68
|
-
# d. catIrt fixture, development stages, held-out runs (each refuses to overwrite an existing cell)
|
|
69
|
-
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt
|
|
70
|
-
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout
|
|
71
|
-
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout
|
|
49
|
+
plainproof fetch bobcat # BOBCAT (MIT) at its pinned commit, with the preprocessed ASSISTments 2009-2010 file
|
|
50
|
+
plainproof fit # 2PL item fit on the development half of learners; checked against the receipt's hash
|
|
51
|
+
plainproof retrain # BOBCAT checkpoint, about 2 hours (author defaults, fold 1, seed 221), compared with the original run
|
|
52
|
+
plainproof run e0 # E0 held-out run and summary; refuses to overwrite an existing cell
|
|
53
|
+
plainproof run e0b # E0b held-out run and summary
|
|
72
54
|
```
|
|
73
55
|
|
|
74
|
-
Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop
|
|
56
|
+
The ASSISTments terms of use forbid passing the data on, so this package never contains it: `fetch bobcat` downloads it from its source, and you accept those terms yourself. Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop `fit`; and it asserts that the BOBCAT checkpoint's best epoch is 105, so a retrain that is not bit-identical stops `run e0`. In either case, use the published held-out outputs (`plainproof fetch heldout`). The development stages (`scripts/edm_v2_e0/study.py tune|calibrate|calibrate_sprt_full|pilot`) are included for the record; their outputs (synthetic learners only) are in `data/edm-v2-e0/study/`.
|
|
75
57
|
|
|
76
58
|
## Fingerprints (sha256)
|
|
77
59
|
|
|
@@ -90,6 +72,7 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
90
72
|
## What is in here
|
|
91
73
|
|
|
92
74
|
- `src/plainproof/`: item model, SPRT arm, exact stopping time, simulator (uniform and uncertainty-triggered outsourcing), item fit, signatures, planted probes (with the give-up model), matched-coverage scoring.
|
|
75
|
+
- `src/plainproof/cli.py`: the `plainproof` command. `setup.py` packs the working directory into the wheel for `plainproof init`.
|
|
93
76
|
- `scripts/edm_v2_e0/`, `scripts/edm_v2_e0b/`: the runners, report builders and R plots. `scripts/published_cat_reference_v1/`: the BOBCAT loading code the runners call.
|
|
94
77
|
- `reports/`: both sealed freezes, receipts, figures and tables. `docs/`: the E0 protocol and the pre-registration log (verbatim extract).
|
|
95
78
|
- `substitutions.json`: the only differences between this code and the sealed originals (package name, file locations, data paths). `scripts/verify_frozen.py` undoes them and checks every hash. `scripts/edm_v2_e0/r_env.sh` is kept verbatim as the record of the original R runtime; use `scripts/rscript.sh` instead.
|
|
@@ -97,3 +80,23 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
97
80
|
## Recorded departures
|
|
98
81
|
|
|
99
82
|
All are in `docs/PREREG_EDM_V2.md`: the SPRT tuning rule was revised after its first development pass (labelled post hoc); SPRT's calibration map was refitted once on full paths before the freeze; the E0 held-out run exceeded its 2 GiB memory cap (no result depends on it; the runner now enforces the cap); E0b was sealed before its pilot table had been reviewed (no result affected).
|
|
83
|
+
|
|
84
|
+
## Appendix: the raw script calls
|
|
85
|
+
|
|
86
|
+
What each `plainproof` command runs, from the working directory (`REPRO_DATA` defaults to `./data`):
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
python -m pytest -n auto -q tests # plainproof test
|
|
90
|
+
python scripts/verify_frozen.py # plainproof verify
|
|
91
|
+
ZENODO_URL=https://github.com/cloudronin/plainproof/releases/download/v0.1.0 bash scripts/fetch_heldout.sh # plainproof fetch heldout
|
|
92
|
+
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json # plainproof figures (E0 tables)
|
|
93
|
+
bash scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png <E0 summary sha256>
|
|
94
|
+
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
95
|
+
bash scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png <E0b summary sha256>
|
|
96
|
+
bash scripts/bobcat/fetch_bobcat.sh # plainproof fetch bobcat
|
|
97
|
+
python scripts/edm_v2_e0/fit_assist2009.py data/edm-v2-e0/item-fit # plainproof fit
|
|
98
|
+
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py # plainproof retrain
|
|
99
|
+
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout # plainproof run e0
|
|
100
|
+
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout # plainproof run e0b
|
|
101
|
+
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt # regenerate the catIrt fixture (R with catIrt 0.5.1)
|
|
102
|
+
```
|
|
@@ -8,51 +8,33 @@ Reproduction package for **"How many follow-up questions distinguish genuine und
|
|
|
8
8
|
|
|
9
9
|
Everything here is CPU-only and needs no paid service. Code: MIT (`LICENSE`). Docs, figures and tables: CC BY 4.0 (`LICENSE-docs.md`).
|
|
10
10
|
|
|
11
|
-
## From
|
|
12
|
-
|
|
13
|
-
The `plainproof` command runs each step (`plainproof --help`); the raw script calls below are what it runs. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; use the `scripts/rscript.sh` wrapper, which `plainproof figures` calls.
|
|
11
|
+
## From install to the figure (about 10 minutes)
|
|
14
12
|
|
|
15
13
|
```sh
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
#
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
#
|
|
23
|
-
plainproof verify
|
|
24
|
-
|
|
25
|
-
# 3. Fetch the sealed held-out outputs (from the v0.1.0 release assets) and check their hashes
|
|
26
|
-
plainproof fetch heldout
|
|
27
|
-
|
|
28
|
-
# 4. Rebuild the tables and figures from the held-out summaries (needs R 4.x for the plots; base graphics only)
|
|
29
|
-
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json
|
|
30
|
-
scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png aff9a8c49d48821c0e9343cd058c4e0e2f1659ffabcaa719824412f3b14abc90
|
|
31
|
-
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
32
|
-
scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png 617be427feac24df2e342da00d34e91c78d5de91592cee390ef3516ae9e2ff3f
|
|
14
|
+
pip install 'plainproof[test,run]'
|
|
15
|
+
plainproof init ~/plainproof # writes the working directory: sealed scripts, freezes, receipts, docs, tests
|
|
16
|
+
cd ~/plainproof
|
|
17
|
+
plainproof test # 43 tests: SPRT against catIrt 0.5.1's saved steps, exact stopping time, simulator, signatures, probes
|
|
18
|
+
plainproof verify # every sealed file against both freezes (undoes the documented substitutions, then sha256)
|
|
19
|
+
plainproof fetch heldout # the sealed held-out outputs, hash-checked
|
|
20
|
+
plainproof figures # tables and figures from the held-out summaries (needs R 4.x on PATH; base graphics only)
|
|
33
21
|
```
|
|
34
22
|
|
|
35
|
-
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures
|
|
23
|
+
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures/`, byte-identical to the published copies. `plainproof init` writes the files in the exact layout the sealed scripts expect; nothing sealed changes. Every other command runs inside that directory, or takes `--root DIR`. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; the `scripts/rscript.sh` wrapper, which `plainproof figures` calls, is the one to use.
|
|
36
24
|
|
|
37
25
|
## Full rerun (about 4 hours of CPU)
|
|
38
26
|
|
|
39
27
|
Only if you want to regenerate everything, including the held-out outputs.
|
|
40
28
|
|
|
41
29
|
```sh
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
# c. Retrain the BOBCAT checkpoint (about 2 hours; author defaults, fold 1, seed 221), then compare it with the original
|
|
48
|
-
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py
|
|
49
|
-
# d. catIrt fixture, development stages, held-out runs (each refuses to overwrite an existing cell)
|
|
50
|
-
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt
|
|
51
|
-
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout
|
|
52
|
-
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout
|
|
30
|
+
plainproof fetch bobcat # BOBCAT (MIT) at its pinned commit, with the preprocessed ASSISTments 2009-2010 file
|
|
31
|
+
plainproof fit # 2PL item fit on the development half of learners; checked against the receipt's hash
|
|
32
|
+
plainproof retrain # BOBCAT checkpoint, about 2 hours (author defaults, fold 1, seed 221), compared with the original run
|
|
33
|
+
plainproof run e0 # E0 held-out run and summary; refuses to overwrite an existing cell
|
|
34
|
+
plainproof run e0b # E0b held-out run and summary
|
|
53
35
|
```
|
|
54
36
|
|
|
55
|
-
Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop
|
|
37
|
+
The ASSISTments terms of use forbid passing the data on, so this package never contains it: `fetch bobcat` downloads it from its source, and you accept those terms yourself. Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop `fit`; and it asserts that the BOBCAT checkpoint's best epoch is 105, so a retrain that is not bit-identical stops `run e0`. In either case, use the published held-out outputs (`plainproof fetch heldout`). The development stages (`scripts/edm_v2_e0/study.py tune|calibrate|calibrate_sprt_full|pilot`) are included for the record; their outputs (synthetic learners only) are in `data/edm-v2-e0/study/`.
|
|
56
38
|
|
|
57
39
|
## Fingerprints (sha256)
|
|
58
40
|
|
|
@@ -71,6 +53,7 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
71
53
|
## What is in here
|
|
72
54
|
|
|
73
55
|
- `src/plainproof/`: item model, SPRT arm, exact stopping time, simulator (uniform and uncertainty-triggered outsourcing), item fit, signatures, planted probes (with the give-up model), matched-coverage scoring.
|
|
56
|
+
- `src/plainproof/cli.py`: the `plainproof` command. `setup.py` packs the working directory into the wheel for `plainproof init`.
|
|
74
57
|
- `scripts/edm_v2_e0/`, `scripts/edm_v2_e0b/`: the runners, report builders and R plots. `scripts/published_cat_reference_v1/`: the BOBCAT loading code the runners call.
|
|
75
58
|
- `reports/`: both sealed freezes, receipts, figures and tables. `docs/`: the E0 protocol and the pre-registration log (verbatim extract).
|
|
76
59
|
- `substitutions.json`: the only differences between this code and the sealed originals (package name, file locations, data paths). `scripts/verify_frozen.py` undoes them and checks every hash. `scripts/edm_v2_e0/r_env.sh` is kept verbatim as the record of the original R runtime; use `scripts/rscript.sh` instead.
|
|
@@ -78,3 +61,23 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
78
61
|
## Recorded departures
|
|
79
62
|
|
|
80
63
|
All are in `docs/PREREG_EDM_V2.md`: the SPRT tuning rule was revised after its first development pass (labelled post hoc); SPRT's calibration map was refitted once on full paths before the freeze; the E0 held-out run exceeded its 2 GiB memory cap (no result depends on it; the runner now enforces the cap); E0b was sealed before its pilot table had been reviewed (no result affected).
|
|
64
|
+
|
|
65
|
+
## Appendix: the raw script calls
|
|
66
|
+
|
|
67
|
+
What each `plainproof` command runs, from the working directory (`REPRO_DATA` defaults to `./data`):
|
|
68
|
+
|
|
69
|
+
```sh
|
|
70
|
+
python -m pytest -n auto -q tests # plainproof test
|
|
71
|
+
python scripts/verify_frozen.py # plainproof verify
|
|
72
|
+
ZENODO_URL=https://github.com/cloudronin/plainproof/releases/download/v0.1.0 bash scripts/fetch_heldout.sh # plainproof fetch heldout
|
|
73
|
+
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json # plainproof figures (E0 tables)
|
|
74
|
+
bash scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png <E0 summary sha256>
|
|
75
|
+
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
76
|
+
bash scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png <E0b summary sha256>
|
|
77
|
+
bash scripts/bobcat/fetch_bobcat.sh # plainproof fetch bobcat
|
|
78
|
+
python scripts/edm_v2_e0/fit_assist2009.py data/edm-v2-e0/item-fit # plainproof fit
|
|
79
|
+
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py # plainproof retrain
|
|
80
|
+
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout # plainproof run e0
|
|
81
|
+
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout # plainproof run e0b
|
|
82
|
+
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt # regenerate the catIrt fixture (R with catIrt 0.5.1)
|
|
83
|
+
```
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plainproof"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.2.0"
|
|
8
8
|
description = "Reproduction tool for the paper 'How many follow-up questions distinguish genuine understanding from apparent mastery?'. Not a general library. Its sealed checks can stop a run on purpose."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Build hook: copy the reproduction working directory into the package as data, so `plainproof init` can write it
|
|
2
|
+
out after `pip install plainproof` alone. The copied files are the repository's own files, unchanged."""
|
|
3
|
+
import shutil
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from setuptools import setup
|
|
7
|
+
from setuptools.command.build_py import build_py
|
|
8
|
+
|
|
9
|
+
PAYLOAD = ['scripts', 'reports', 'docs', 'tests', 'data/edm-v2-e0/study', 'substitutions.json', 'README.md', 'LICENSE',
|
|
10
|
+
'LICENSE-docs.md', 'CITATION.cff', 'requirements.txt']
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class with_payload(build_py):
|
|
14
|
+
def run(self):
|
|
15
|
+
super().run()
|
|
16
|
+
here = Path(__file__).resolve().parent
|
|
17
|
+
dest = Path(self.build_lib) / 'plainproof' / 'payload'
|
|
18
|
+
if dest.exists():
|
|
19
|
+
shutil.rmtree(dest)
|
|
20
|
+
for item in PAYLOAD:
|
|
21
|
+
src = here / item
|
|
22
|
+
if not src.exists():
|
|
23
|
+
raise SystemExit(f'payload item missing from the source tree: {item}')
|
|
24
|
+
if src.is_dir():
|
|
25
|
+
shutil.copytree(src, dest / item, ignore=shutil.ignore_patterns('__pycache__', '*.pyc'))
|
|
26
|
+
else:
|
|
27
|
+
(dest / item).parent.mkdir(parents=True, exist_ok=True)
|
|
28
|
+
shutil.copy2(src, dest / item)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
setup(cmdclass={'build_py': with_payload})
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"""plainproof: the command-line front end of this reproduction package.
|
|
2
|
+
|
|
3
|
+
`plainproof init DIR` writes a working directory from the package (sealed scripts, both freezes, receipts,
|
|
4
|
+
substitutions.json, R scripts, docs, tests) in the exact layout the sealed scripts expect; nothing sealed changes.
|
|
5
|
+
Every other command runs inside that directory, or takes --root DIR.
|
|
6
|
+
|
|
7
|
+
plainproof init DIR write the working directory (refuses a non-empty DIR)
|
|
8
|
+
plainproof test the 43 offline tests
|
|
9
|
+
plainproof verify check every sealed file against both freezes
|
|
10
|
+
plainproof fetch heldout|bobcat|all the sealed held-out outputs, and/or BOBCAT + the ASSISTments file (hash-checked)
|
|
11
|
+
plainproof figures rebuild tables and figures from the held-out summaries (needs R for the plots)
|
|
12
|
+
plainproof fit refit the 2PL item parameters on ASSISTments development learners
|
|
13
|
+
plainproof retrain retrain the BOBCAT checkpoint, then compare it with the original run
|
|
14
|
+
plainproof run e0|e0b held-out run and summary (refuses to overwrite an existing cell)
|
|
15
|
+
"""
|
|
16
|
+
import argparse
|
|
17
|
+
import hashlib
|
|
18
|
+
import os
|
|
19
|
+
import shutil
|
|
20
|
+
import subprocess
|
|
21
|
+
import sys
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
|
|
24
|
+
# The sealed held-out outputs. Their sha256 values are checked by scripts/fetch_heldout.sh before use.
|
|
25
|
+
HELDOUT_BASE_URL = 'https://github.com/cloudronin/plainproof/releases/download/v0.1.0'
|
|
26
|
+
PAYLOAD = Path(__file__).resolve().parent / 'payload'
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def find_root(given):
|
|
30
|
+
root = Path(given or os.getcwd()).resolve()
|
|
31
|
+
if not (root / 'substitutions.json').exists() or not (root / 'reports' / 'edm-v2-e0' / 'freeze.json').exists():
|
|
32
|
+
raise SystemExit(f'{root} is not a plainproof working directory; run `plainproof init DIR` and cd there, or pass --root')
|
|
33
|
+
return root
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def sh(root, *cmd, env_extra=None):
|
|
37
|
+
env = dict(os.environ)
|
|
38
|
+
env.setdefault('REPRO_DATA', str(root / 'data'))
|
|
39
|
+
env.update(env_extra or {})
|
|
40
|
+
print('+', ' '.join(str(c) for c in cmd), flush=True)
|
|
41
|
+
r = subprocess.run([str(c) for c in cmd], cwd=root, env=env)
|
|
42
|
+
if r.returncode:
|
|
43
|
+
raise SystemExit(r.returncode)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def sha(p):
|
|
47
|
+
return hashlib.sha256(Path(p).read_bytes()).hexdigest()
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def init(target):
|
|
51
|
+
target = Path(target).expanduser().resolve()
|
|
52
|
+
if target.exists() and any(target.iterdir()):
|
|
53
|
+
raise SystemExit(f'{target} is not empty; choose a new directory')
|
|
54
|
+
if not PAYLOAD.exists():
|
|
55
|
+
raise SystemExit('this installation has no payload; reinstall plainproof from the wheel or sdist')
|
|
56
|
+
shutil.copytree(PAYLOAD, target, dirs_exist_ok=True)
|
|
57
|
+
# The sealed scripts import the package from <root>/src and hash its modules there, so the package is written
|
|
58
|
+
# out too, byte for byte from this installation.
|
|
59
|
+
pkg = target / 'src' / 'plainproof'
|
|
60
|
+
pkg.mkdir(parents=True)
|
|
61
|
+
for f in Path(__file__).resolve().parent.glob('*.py'):
|
|
62
|
+
shutil.copy2(f, pkg / f.name)
|
|
63
|
+
for d in ('data/edm-v2-e0', 'data/edm-v2-e0b'):
|
|
64
|
+
(target / d).mkdir(parents=True, exist_ok=True)
|
|
65
|
+
for f in target.rglob('*.sh'):
|
|
66
|
+
f.chmod(0o755)
|
|
67
|
+
print(f'wrote {target}\nnext: cd {target} && plainproof test && plainproof verify && plainproof fetch heldout && plainproof figures')
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def main(argv=None):
|
|
71
|
+
ap = argparse.ArgumentParser(prog='plainproof', description=__doc__.split('\n\n')[0])
|
|
72
|
+
ap.add_argument('--root', help='working directory (default: current directory)')
|
|
73
|
+
sub = ap.add_subparsers(dest='cmd', required=True)
|
|
74
|
+
sub.add_parser('init').add_argument('dir')
|
|
75
|
+
sub.add_parser('test')
|
|
76
|
+
sub.add_parser('verify')
|
|
77
|
+
sub.add_parser('fetch').add_argument('what', choices=('heldout', 'bobcat', 'all'))
|
|
78
|
+
sub.add_parser('figures')
|
|
79
|
+
sub.add_parser('fit')
|
|
80
|
+
sub.add_parser('retrain')
|
|
81
|
+
sub.add_parser('run').add_argument('study', choices=('e0', 'e0b'))
|
|
82
|
+
a = ap.parse_args(argv)
|
|
83
|
+
if a.cmd == 'init':
|
|
84
|
+
return init(a.dir)
|
|
85
|
+
root = find_root(a.root)
|
|
86
|
+
py = sys.executable
|
|
87
|
+
data = Path(os.environ.get('REPRO_DATA', root / 'data'))
|
|
88
|
+
if a.cmd == 'test':
|
|
89
|
+
sh(root, py, '-m', 'pytest', '-n', 'auto', '-q', '-p', 'no:cacheprovider', 'tests')
|
|
90
|
+
elif a.cmd == 'verify':
|
|
91
|
+
sh(root, py, 'scripts/verify_frozen.py')
|
|
92
|
+
elif a.cmd == 'fetch':
|
|
93
|
+
if a.what in ('heldout', 'all'):
|
|
94
|
+
sh(root, 'bash', 'scripts/fetch_heldout.sh', env_extra={'ZENODO_URL': os.environ.get('ZENODO_URL', HELDOUT_BASE_URL)})
|
|
95
|
+
if a.what in ('bobcat', 'all'):
|
|
96
|
+
sh(root, 'bash', 'scripts/bobcat/fetch_bobcat.sh')
|
|
97
|
+
elif a.cmd == 'figures':
|
|
98
|
+
s0, s1 = data / 'edm-v2-e0' / 'heldout' / 'summary.json', data / 'edm-v2-e0b' / 'heldout' / 'summary.json'
|
|
99
|
+
for s in (s0, s1):
|
|
100
|
+
if not s.exists():
|
|
101
|
+
raise SystemExit(f'{s} missing; run `plainproof fetch heldout` first')
|
|
102
|
+
sh(root, py, 'scripts/edm_v2_e0/report.py', s0)
|
|
103
|
+
sh(root, 'bash', 'scripts/rscript.sh', 'scripts/edm_v2_e0/plot_error_vs_d.R', 'reports/edm-v2-e0/error-vs-d.csv',
|
|
104
|
+
'reports/edm-v2-e0/figures/error-vs-d.png', sha(s0))
|
|
105
|
+
sh(root, py, 'scripts/edm_v2_e0b/report.py', s1)
|
|
106
|
+
sh(root, 'bash', 'scripts/rscript.sh', 'scripts/edm_v2_e0b/plot_probe_auc.R', 'reports/edm-v2-e0b/probe-auc-vs-d.csv',
|
|
107
|
+
'reports/edm-v2-e0b/figures/probe-auc-vs-d.png', sha(s1))
|
|
108
|
+
elif a.cmd == 'fit':
|
|
109
|
+
sh(root, py, 'scripts/edm_v2_e0/fit_assist2009.py', data / 'edm-v2-e0' / 'item-fit')
|
|
110
|
+
elif a.cmd == 'retrain':
|
|
111
|
+
sh(root, py, 'scripts/bobcat/retrain.py')
|
|
112
|
+
sh(root, py, 'scripts/bobcat/check_checkpoint.py')
|
|
113
|
+
elif a.cmd == 'run':
|
|
114
|
+
out = data / a.study.replace('e0', 'edm-v2-e0', 1) / 'heldout'
|
|
115
|
+
script = 'scripts/edm_v2_e0/heldout.py' if a.study == 'e0' else 'scripts/edm_v2_e0b/run.py'
|
|
116
|
+
sh(root, py, script, 'run', out)
|
|
117
|
+
sh(root, py, script, 'summarize', out)
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if __name__ == '__main__':
|
|
121
|
+
main()
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plainproof
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0
|
|
4
4
|
Summary: Reproduction tool for the paper 'How many follow-up questions distinguish genuine understanding from apparent mastery?'. Not a general library. Its sealed checks can stop a run on purpose.
|
|
5
5
|
Author: Vishnu Vettrivel
|
|
6
6
|
License-Expression: MIT
|
|
@@ -27,51 +27,33 @@ Reproduction package for **"How many follow-up questions distinguish genuine und
|
|
|
27
27
|
|
|
28
28
|
Everything here is CPU-only and needs no paid service. Code: MIT (`LICENSE`). Docs, figures and tables: CC BY 4.0 (`LICENSE-docs.md`).
|
|
29
29
|
|
|
30
|
-
## From
|
|
31
|
-
|
|
32
|
-
The `plainproof` command runs each step (`plainproof --help`); the raw script calls below are what it runs. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; use the `scripts/rscript.sh` wrapper, which `plainproof figures` calls.
|
|
30
|
+
## From install to the figure (about 10 minutes)
|
|
33
31
|
|
|
34
32
|
```sh
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
#
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
#
|
|
42
|
-
plainproof verify
|
|
43
|
-
|
|
44
|
-
# 3. Fetch the sealed held-out outputs (from the v0.1.0 release assets) and check their hashes
|
|
45
|
-
plainproof fetch heldout
|
|
46
|
-
|
|
47
|
-
# 4. Rebuild the tables and figures from the held-out summaries (needs R 4.x for the plots; base graphics only)
|
|
48
|
-
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json
|
|
49
|
-
scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png aff9a8c49d48821c0e9343cd058c4e0e2f1659ffabcaa719824412f3b14abc90
|
|
50
|
-
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
51
|
-
scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png 617be427feac24df2e342da00d34e91c78d5de91592cee390ef3516ae9e2ff3f
|
|
33
|
+
pip install 'plainproof[test,run]'
|
|
34
|
+
plainproof init ~/plainproof # writes the working directory: sealed scripts, freezes, receipts, docs, tests
|
|
35
|
+
cd ~/plainproof
|
|
36
|
+
plainproof test # 43 tests: SPRT against catIrt 0.5.1's saved steps, exact stopping time, simulator, signatures, probes
|
|
37
|
+
plainproof verify # every sealed file against both freezes (undoes the documented substitutions, then sha256)
|
|
38
|
+
plainproof fetch heldout # the sealed held-out outputs, hash-checked
|
|
39
|
+
plainproof figures # tables and figures from the held-out summaries (needs R 4.x on PATH; base graphics only)
|
|
52
40
|
```
|
|
53
41
|
|
|
54
|
-
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures
|
|
42
|
+
The figures land in `reports/edm-v2-e0/figures/` and `reports/edm-v2-e0b/figures/`, byte-identical to the published copies. `plainproof init` writes the files in the exact layout the sealed scripts expect; nothing sealed changes. Every other command runs inside that directory, or takes `--root DIR`. The local path inside the sealed `scripts/edm_v2_e0/r_env.sh` is part of the frozen record; the `scripts/rscript.sh` wrapper, which `plainproof figures` calls, is the one to use.
|
|
55
43
|
|
|
56
44
|
## Full rerun (about 4 hours of CPU)
|
|
57
45
|
|
|
58
46
|
Only if you want to regenerate everything, including the held-out outputs.
|
|
59
47
|
|
|
60
48
|
```sh
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
# c. Retrain the BOBCAT checkpoint (about 2 hours; author defaults, fold 1, seed 221), then compare it with the original
|
|
67
|
-
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py
|
|
68
|
-
# d. catIrt fixture, development stages, held-out runs (each refuses to overwrite an existing cell)
|
|
69
|
-
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt
|
|
70
|
-
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout
|
|
71
|
-
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout
|
|
49
|
+
plainproof fetch bobcat # BOBCAT (MIT) at its pinned commit, with the preprocessed ASSISTments 2009-2010 file
|
|
50
|
+
plainproof fit # 2PL item fit on the development half of learners; checked against the receipt's hash
|
|
51
|
+
plainproof retrain # BOBCAT checkpoint, about 2 hours (author defaults, fold 1, seed 221), compared with the original run
|
|
52
|
+
plainproof run e0 # E0 held-out run and summary; refuses to overwrite an existing cell
|
|
53
|
+
plainproof run e0b # E0b held-out run and summary
|
|
72
54
|
```
|
|
73
55
|
|
|
74
|
-
Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop
|
|
56
|
+
The ASSISTments terms of use forbid passing the data on, so this package never contains it: `fetch bobcat` downloads it from its source, and you accept those terms yourself. Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a different numpy can stop `fit`; and it asserts that the BOBCAT checkpoint's best epoch is 105, so a retrain that is not bit-identical stops `run e0`. In either case, use the published held-out outputs (`plainproof fetch heldout`). The development stages (`scripts/edm_v2_e0/study.py tune|calibrate|calibrate_sprt_full|pilot`) are included for the record; their outputs (synthetic learners only) are in `data/edm-v2-e0/study/`.
|
|
75
57
|
|
|
76
58
|
## Fingerprints (sha256)
|
|
77
59
|
|
|
@@ -90,6 +72,7 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
90
72
|
## What is in here
|
|
91
73
|
|
|
92
74
|
- `src/plainproof/`: item model, SPRT arm, exact stopping time, simulator (uniform and uncertainty-triggered outsourcing), item fit, signatures, planted probes (with the give-up model), matched-coverage scoring.
|
|
75
|
+
- `src/plainproof/cli.py`: the `plainproof` command. `setup.py` packs the working directory into the wheel for `plainproof init`.
|
|
93
76
|
- `scripts/edm_v2_e0/`, `scripts/edm_v2_e0b/`: the runners, report builders and R plots. `scripts/published_cat_reference_v1/`: the BOBCAT loading code the runners call.
|
|
94
77
|
- `reports/`: both sealed freezes, receipts, figures and tables. `docs/`: the E0 protocol and the pre-registration log (verbatim extract).
|
|
95
78
|
- `substitutions.json`: the only differences between this code and the sealed originals (package name, file locations, data paths). `scripts/verify_frozen.py` undoes them and checks every hash. `scripts/edm_v2_e0/r_env.sh` is kept verbatim as the record of the original R runtime; use `scripts/rscript.sh` instead.
|
|
@@ -97,3 +80,23 @@ Two caveats, stated plainly. The sealed code checks the item fit's sha256, so a
|
|
|
97
80
|
## Recorded departures
|
|
98
81
|
|
|
99
82
|
All are in `docs/PREREG_EDM_V2.md`: the SPRT tuning rule was revised after its first development pass (labelled post hoc); SPRT's calibration map was refitted once on full paths before the freeze; the E0 held-out run exceeded its 2 GiB memory cap (no result depends on it; the runner now enforces the cap); E0b was sealed before its pilot table had been reviewed (no result affected).
|
|
83
|
+
|
|
84
|
+
## Appendix: the raw script calls
|
|
85
|
+
|
|
86
|
+
What each `plainproof` command runs, from the working directory (`REPRO_DATA` defaults to `./data`):
|
|
87
|
+
|
|
88
|
+
```sh
|
|
89
|
+
python -m pytest -n auto -q tests # plainproof test
|
|
90
|
+
python scripts/verify_frozen.py # plainproof verify
|
|
91
|
+
ZENODO_URL=https://github.com/cloudronin/plainproof/releases/download/v0.1.0 bash scripts/fetch_heldout.sh # plainproof fetch heldout
|
|
92
|
+
python scripts/edm_v2_e0/report.py data/edm-v2-e0/heldout/summary.json # plainproof figures (E0 tables)
|
|
93
|
+
bash scripts/rscript.sh scripts/edm_v2_e0/plot_error_vs_d.R reports/edm-v2-e0/error-vs-d.csv reports/edm-v2-e0/figures/error-vs-d.png <E0 summary sha256>
|
|
94
|
+
python scripts/edm_v2_e0b/report.py data/edm-v2-e0b/heldout/summary.json
|
|
95
|
+
bash scripts/rscript.sh scripts/edm_v2_e0b/plot_probe_auc.R reports/edm-v2-e0b/probe-auc-vs-d.csv reports/edm-v2-e0b/figures/probe-auc-vs-d.png <E0b summary sha256>
|
|
96
|
+
bash scripts/bobcat/fetch_bobcat.sh # plainproof fetch bobcat
|
|
97
|
+
python scripts/edm_v2_e0/fit_assist2009.py data/edm-v2-e0/item-fit # plainproof fit
|
|
98
|
+
python scripts/bobcat/retrain.py && python scripts/bobcat/check_checkpoint.py # plainproof retrain
|
|
99
|
+
python scripts/edm_v2_e0/heldout.py run data/edm-v2-e0/heldout && python scripts/edm_v2_e0/heldout.py summarize data/edm-v2-e0/heldout # plainproof run e0
|
|
100
|
+
python scripts/edm_v2_e0b/run.py run data/edm-v2-e0b/heldout && python scripts/edm_v2_e0b/run.py summarize data/edm-v2-e0b/heldout # plainproof run e0b
|
|
101
|
+
scripts/rscript.sh scripts/edm_v2_e0/catirt_sprt_steps.R tests/fixtures/edm_v2_catirt_sprt # regenerate the catIrt fixture (R with catIrt 0.5.1)
|
|
102
|
+
```
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
"""plainproof: the command-line front end of this reproduction package.
|
|
2
|
-
|
|
3
|
-
It runs the repository's own scripts, so it needs a checkout or the unpacked sdist (the sealed scripts locate the
|
|
4
|
-
repository by its layout). Pass --root, or run it from the repository root.
|
|
5
|
-
|
|
6
|
-
plainproof fetch [bobcat|heldout|all] fetch BOBCAT + the ASSISTments file, and/or the held-out outputs (all hash-checked)
|
|
7
|
-
plainproof fit refit the 2PL item parameters on ASSISTments development learners
|
|
8
|
-
plainproof run e0|e0b held-out run and summary (refuses to overwrite an existing cell)
|
|
9
|
-
plainproof figures rebuild tables and figures from the held-out summaries (needs R for the plots)
|
|
10
|
-
plainproof verify check every sealed file against both freezes
|
|
11
|
-
"""
|
|
12
|
-
import argparse
|
|
13
|
-
import hashlib
|
|
14
|
-
import os
|
|
15
|
-
import subprocess
|
|
16
|
-
import sys
|
|
17
|
-
from pathlib import Path
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def find_root(given):
|
|
21
|
-
root = Path(given or os.getcwd()).resolve()
|
|
22
|
-
if not (root / 'substitutions.json').exists() or not (root / 'reports' / 'edm-v2-e0' / 'freeze.json').exists():
|
|
23
|
-
raise SystemExit(f'{root} is not a plainproof checkout (no substitutions.json or reports/); use --root')
|
|
24
|
-
return root
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
def sh(root, *cmd):
|
|
28
|
-
env = dict(os.environ)
|
|
29
|
-
env.setdefault('REPRO_DATA', str(root / 'data'))
|
|
30
|
-
print('+', ' '.join(str(c) for c in cmd), flush=True)
|
|
31
|
-
r = subprocess.run([str(c) for c in cmd], cwd=root, env=env)
|
|
32
|
-
if r.returncode:
|
|
33
|
-
raise SystemExit(r.returncode)
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
def sha(p):
|
|
37
|
-
return hashlib.sha256(Path(p).read_bytes()).hexdigest()
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def main(argv=None):
|
|
41
|
-
ap = argparse.ArgumentParser(prog='plainproof', description=__doc__.split('\n\n')[0])
|
|
42
|
-
ap.add_argument('--root', help='repository root (default: current directory)')
|
|
43
|
-
sub = ap.add_subparsers(dest='cmd', required=True)
|
|
44
|
-
f = sub.add_parser('fetch'); f.add_argument('what', nargs='?', default='all', choices=('bobcat', 'heldout', 'all'))
|
|
45
|
-
sub.add_parser('fit')
|
|
46
|
-
r = sub.add_parser('run'); r.add_argument('study', choices=('e0', 'e0b'))
|
|
47
|
-
sub.add_parser('figures')
|
|
48
|
-
sub.add_parser('verify')
|
|
49
|
-
a = ap.parse_args(argv)
|
|
50
|
-
root = find_root(a.root)
|
|
51
|
-
py = sys.executable
|
|
52
|
-
data = Path(os.environ.get('REPRO_DATA', root / 'data'))
|
|
53
|
-
if a.cmd == 'fetch':
|
|
54
|
-
if a.what in ('bobcat', 'all'):
|
|
55
|
-
sh(root, 'bash', 'scripts/bobcat/fetch_bobcat.sh')
|
|
56
|
-
if a.what in ('heldout', 'all'):
|
|
57
|
-
sh(root, 'bash', 'scripts/fetch_heldout.sh')
|
|
58
|
-
elif a.cmd == 'fit':
|
|
59
|
-
sh(root, py, 'scripts/edm_v2_e0/fit_assist2009.py', data / 'edm-v2-e0' / 'item-fit')
|
|
60
|
-
elif a.cmd == 'run':
|
|
61
|
-
if a.study == 'e0':
|
|
62
|
-
out = data / 'edm-v2-e0' / 'heldout'
|
|
63
|
-
sh(root, py, 'scripts/edm_v2_e0/heldout.py', 'run', out)
|
|
64
|
-
sh(root, py, 'scripts/edm_v2_e0/heldout.py', 'summarize', out)
|
|
65
|
-
else:
|
|
66
|
-
out = data / 'edm-v2-e0b' / 'heldout'
|
|
67
|
-
sh(root, py, 'scripts/edm_v2_e0b/run.py', 'run', out)
|
|
68
|
-
sh(root, py, 'scripts/edm_v2_e0b/run.py', 'summarize', out)
|
|
69
|
-
elif a.cmd == 'figures':
|
|
70
|
-
s0, s1 = data / 'edm-v2-e0' / 'heldout' / 'summary.json', data / 'edm-v2-e0b' / 'heldout' / 'summary.json'
|
|
71
|
-
sh(root, py, 'scripts/edm_v2_e0/report.py', s0)
|
|
72
|
-
sh(root, 'bash', 'scripts/rscript.sh', 'scripts/edm_v2_e0/plot_error_vs_d.R', 'reports/edm-v2-e0/error-vs-d.csv',
|
|
73
|
-
'reports/edm-v2-e0/figures/error-vs-d.png', sha(s0))
|
|
74
|
-
sh(root, py, 'scripts/edm_v2_e0b/report.py', s1)
|
|
75
|
-
sh(root, 'bash', 'scripts/rscript.sh', 'scripts/edm_v2_e0b/plot_probe_auc.R', 'reports/edm-v2-e0b/probe-auc-vs-d.csv',
|
|
76
|
-
'reports/edm-v2-e0b/figures/probe-auc-vs-d.png', sha(s1))
|
|
77
|
-
elif a.cmd == 'verify':
|
|
78
|
-
sh(root, py, 'scripts/verify_frozen.py')
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
if __name__ == '__main__':
|
|
82
|
-
main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{plainproof-0.1.1 → plainproof-0.2.0}/scripts/published_cat_reference_v1/compare_selection_v1.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|