dsfb-add 0.1.0

Deterministic Algebraic Deterministic Dynamics (ADD) parameter sweeps for AET, TCP, RLT, and IWLT
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
# dsfb-add — Algebraic Deterministic Dynamics Sweep

`dsfb-add` is the empirical sweep and figure-generation companion for the Algebraic Deterministic Dynamics (ADD) stack. It runs deterministic lambda sweeps, exports structural observables as CSV, and feeds a Colab notebook that regenerates the paper-facing figures from those CSVs.

At a high level, the crate does three things:

1. It evolves four deterministic toy models across a shared lambda grid.
2. It writes reproducible sweep outputs into `output-dsfb-add/<timestamp>/` at the repo root.
3. It provides the numerical substrate for the ADD paper's figures: cross-layer response curves, transport transition summaries, structural-law fits, robustness checks, and finite-size scaling diagnostics.

The stack it sweeps is:

- Algebraic Echo Theory (AET)
- Topological Charge Propagation (TCP)
- Resonance Lattice Theory (RLT)
- Invariant Word-Length Thermodynamics (IWLT)

## Citation

Primary paper for this crate:

- de Beer, R. (2026). *Algebraic Deterministic Dynamics (ADD): A Non-Stochastic Structural Extension of DSFB* (v1.0). Zenodo. DOI: [10.5281/zenodo.18830567](https://doi.org/10.5281/zenodo.18830567)

Zenodo record:

- https://zenodo.org/records/18830567

Suggested BibTeX:

```bibtex
@misc{debeer2026add,
  author       = {Riaan de Beer},
  title        = {Algebraic Deterministic Dynamics (ADD): A Non-Stochastic Structural Extension of DSFB},
  year         = {2026},
  publisher    = {Zenodo},
  doi          = {10.5281/zenodo.18830567},
  url          = {https://doi.org/10.5281/zenodo.18830567},
  version      = {1.0}
}
```

## Motivation

ADD extends the deterministic style of DSFB upward into structural dynamics. Instead of using stochastic primitives as the default language for memory, disorder, spread, and irreversibility, the ADD paper frames those effects through exact evolution rules on words, graphs, and trajectory-generated complexes.

`dsfb-add` is the empirical side of that argument. It is not a full physics engine and it does not claim microscopic fidelity. Its job is narrower and more useful for the paper: it provides a deterministic numerical laboratory in which the four layers can be swept together, perturbed in a controlled way, compared across finite trajectory lengths, and summarized with a small number of interpretable structural observables.

In practice that means the crate can answer questions like:

- how echo growth changes across lambda,
- how invariant word-length entropy tracks that echo growth,
- where the resonance transport transition occurs,
- how persistent-topology summaries respond across the same sweep,
- whether the AET-IWLT structural law survives deterministic rule perturbations,
- and whether those claims stabilize as `steps_per_run` increases.

## Mathematical Model

The ADD paper defines a common deterministic template for all four layers. The abstract state evolves by

```text
S_{k+1} = Φ(S_k),
```

with a discrete invariant

```text
I(S_{k+1}) = I(S_k),
```

and a monotone structural functional

```text
L(S_{k+1}) >= L(S_k).
```

`dsfb-add` is the numerical sweep implementation of that idea. It does not attempt to symbolically prove the paper's theorems inside Rust; instead it instantiates deterministic toy models whose exported diagnostics are direct empirical proxies for the functionals defined in the paper.

### Algebraic Echo Theory (AET)

In the paper, AET works on words in a free monoid `G*` with a terminating, confluent rewriting system `R`. The echo of a word is its normal form,

```text
Echo(w) = NF(w),
```

and the echo length is

```text
L_AET(w) = len(Echo(w)).
```

The paper's AET evolution is left-multiplicative:

```text
w_{k+1} = NF(g* w_k),
```

with increment sequence

```text
Delta_k = L_k+1 - L_k,
L_k = L_AET(w_k),
```

and asymptotic survival rate

```text
sigma = lim inf_{n -> inf} (1 / n) sum_{k=0}^{n-1} Delta_k.
```

In `dsfb-add`, the `aet` module implements exactly this style of deterministic word evolution on a small alphabet with terminating, confluent local rules. The exported sweep statistics are empirical summaries of the paper's `L_AET` dynamics:

- `echo_slope(lambda)` is the finite-run slope estimate

  ```text
  echo_slope ~= (L_final - L_initial) / steps_per_run
  ```

- `avg_increment(lambda)` is the finite-run average of the increments

  ```text
  avg_increment = (1 / N) sum Delta_k.
  ```

So the AET CSVs are a sampled lambda-family of the paper's echo-length growth law.

### Topological Charge Propagation (TCP)

In the paper, TCP starts from a deterministic trajectory, builds a filtration of simplicial complexes,

```text
K_{alpha_1} subseteq K_{alpha_2}  whenever alpha_1 <= alpha_2,
```

and defines the topological charge vector

```text
Q(alpha) = (beta_0(K_alpha), beta_1(K_alpha), beta_2(K_alpha), ...).
```

The paper also uses the Euler-characteristic identity

```text
chi(K_alpha) = sum_{k >= 0} (-1)^k beta_k(K_alpha),
```

and a topological-disorder functional of the form

```text
L_TCP(t) = sum_k w_k * #{persistent classes in dimension k with lifetime >= delta}.
```

`dsfb-add` keeps persistent homology itself in the notebook rather than in Rust. The Rust crate exports deterministic point clouds for each lambda and each deterministic run window, and the notebook computes the paper-facing PH summaries:

- `betti1_mean(lambda)`
- `betti1_std(lambda)`
- `total_persistence_mean(lambda)`
- `total_persistence_std(lambda)`

The smooth TCP observable used in the figures is total persistence, which is the notebook's empirical surrogate for the paper's `L_TCP`.

### Resonance Lattice Theory (RLT)

In the paper, RLT evolves on a locally finite resonance graph `G = (V, E)` with deterministic dynamics

```text
v_{k+1} = Psi(v_k).
```

From an initial configuration `v_0`, the reachable component is

```text
C(v_0) = { v in V | v = Psi^(k)(v_0) for some k >= 0 },
```

and the resonance spread is

```text
L_RLT(v_0) = |C(v_0)|.
```

The paper further defines escape rate

```text
lambda(v_0) = lim inf_{n -> inf} (1 / n) d_G(v_0, v_n),
```

and resonance expansion ratio

```text
rho(v_0, n) = |V_n| / (n + 1),
rho(v_0) = lim inf_{n -> inf} rho(v_0, n),
```

where `V_n = {v_0, ..., v_n}` is the visited set up to time `n`.

The `rlt` module exports finite-run deterministic proxies for these exact paper objects:

- `escape_rate(lambda)` is the sampled version of `lambda(v_0)`
- `expansion_ratio(lambda)` is the sampled version of `rho(v_0, n)`
- `rlt_examples/...csv` stores representative bounded and expanding trajectories

The crate also exports the paper-facing phase-boundary summary:

```text
lambda_star   = first lambda with expansion_ratio >= 0.5
lambda_0_1    = first lambda with expansion_ratio >= 0.1
lambda_0_9    = first lambda with expansion_ratio >= 0.9
transition_width = lambda_0_9 - lambda_0_1
```

These are the deterministic transport-transition metrics used by the notebook's RLT scaling plots and hero figure annotation.

### Invariant Word-Length Thermodynamics (IWLT)

In the paper, IWLT defines the equivalence class of a history word under a rewriting system as

```text
[w] = { u in E* | u is reachable from w by finitely many rewrites },
```

and the word-length entropy as the minimal representative length

```text
S_IWLT(w) = min_{u in [w]} len(u).
```

The evolution is append-only,

```text
w_{k+1} = w_k e_{i_{k+1}},
```

and the paper proves existence of the entropy-density limit

```text
s_inf = lim_{k -> inf} S_IWLT(w_k) / k.
```

Under the paper's local-irreversibility assumptions, IWLT obeys the deterministic entropy-density law

```text
S_IWLT(w_k) >= (m - BC) k,
s_inf >= m - BC > 0.
```

The `iwlt` module implements a deterministic append-and-reduce history system in exactly this spirit. Its exported diagnostics are finite-run empirical surrogates of the paper quantities:

- `entropy_density(lambda)` is the sampled estimate

  ```text
  entropy_density ~= S_IWLT(w_final) / steps_per_run
  ```

- `avg_increment(lambda)` is the mean per-step increase in the minimal representative length.

### Cross-Layer Structural Law

The main empirical claim tested by this crate is that the AET and IWLT functionals lock together numerically across the same lambda sweep. Concretely, for every run length `N`, the notebook merges

- `echo_slope(lambda)` from AET, and
- `entropy_density(lambda)` from IWLT,

then fits the linear law

```text
entropy_density ~= a * echo_slope + b.
```

From that fit it computes:

- Pearson correlation,
- Spearman rank correlation,
- regression slope `a`,
- intercept `b`,
- `R^2`,
- mean-squared residual,
- and the dimensionless ratio

  ```text
  entropy_density / echo_slope.
  ```

This is the structural-law pipeline behind `aet_iwlt_law_summary.csv`, the finite-size scaling summaries, the residual diagnostics, the universality comparison, and the bottom panel of `fig_hero_add_stack.png`.

### What The Crate Actually Computes

Putting the paper mathematics and the Rust implementation together:

- the Rust crate generates deterministic trajectories, words, and graph walks parameterized by lambda and optional multiple `steps_per_run` values,
- the CSVs store finite-run samples of `L_AET`, `S_IWLT`, TCP persistence summaries, and RLT spread/escape observables,
- perturbed sweeps test whether those laws are stable under small deterministic rule changes,
- and the notebook reconstructs the paper-facing diagnostics from those exported deterministic samples.

So the crate is not merely a plotting harness. It is the executable empirical realization of the paper's algebraic-topological stack: the place where the formal quantities from AET, TCP, RLT, and IWLT are turned into concrete sweep data, regression summaries, phase-boundary estimates, and final figures.

## Architecture

The crate is split into four simulation modules plus shared configuration, output, and orchestration code.

- `aet`:
  deterministic word evolution on a finite alphabet with terminating, confluent local rewrite rules. It tracks irreducible echo length growth and average increment statistics.
- `tcp`:
  deterministic 2D trajectory generation indexed by lambda. Rust writes per-lambda point clouds and coarse topological proxies; the Colab notebook can then compute richer persistent-homology diagnostics from those point clouds.
- `rlt`:
  deterministic walks on a synthetic resonance lattice. It measures graph escape rate and expansion ratio from the visited component.
- `iwlt`:
  append-only symbolic evolution with local length-non-increasing rewrites. It tracks minimal representative length, entropy density, and average increment.
- `config`:
  defines `SimulationConfig`, including the lambda sweep bounds, step count, seed, and per-subtheory toggles.
- `output`:
  creates `output-dsfb-add/<timestamp>/` using `chrono::Utc::now()` and writes sweep, phase-boundary, and robustness CSV files.
- `sweep`:
  orchestrates baseline and perturbed sweeps, optional multi-`N` runs, phase-boundary extraction, and robustness summaries.
- `analysis/rlt_phase`:
  extracts `lambda_star`, transition brackets, and transition width from the RLT expansion curve.

`SimulationConfig::lambda_grid()` produces evenly spaced lambda values on `[lambda_min, lambda_max]`. With the default configuration the sweep is deterministic and reproducible across runs because each sub-theory derives all pseudo-random choices from `random_seed` and the lambda index.

If `multi_steps_per_run` is populated, the crate repeats the full sweep for every requested trajectory length. This is what supports the paper's finite-size scaling story: the exact same lambda grid and deterministic rules are re-run at multiple `N`, and the notebook then measures how regression slope, `R^2`, residual variance, and phase-boundary location stabilize.

The crate also depends on the workspace `dsfb` crate. That dependency is used to build a small deterministic drive signal shared across the ADD toy models, so the sweep remains aligned with the DSFB repository's observer-first philosophy without modifying any existing DSFB source code.

## Code-Level Walkthrough

The crate is intentionally split so the Rust side handles deterministic data generation and the notebook side handles heavier plotting and PH post-processing.

### Library Entry Points

The main library entry point is:

```rust
pub fn run_all_sweeps(config: &SimulationConfig) -> Result<(), AddError>;
```

This is the simplest API when embedding `dsfb-add` from another Rust program: pass a `SimulationConfig`, let the crate create a fresh timestamped output directory, and write the full sweep there.

The lower-level entry point used by the binary is:

```rust
pub fn run_sweeps_into_dir(
    config: &SimulationConfig,
    output_dir: &Path,
) -> Result<SweepResult, AddError>;
```

This is the better choice when you want explicit control over where outputs are written or when integrating ADD sweeps into a larger orchestration layer.

### CLI Binary

The binary target is:

```text
dsfb_add_sweep
```

It accepts:

- `--config path/to/config.json`
- `--steps-per-run-list 512,5000,10000,20000`

If a `config.json` exists in the current working directory, it is loaded automatically. Otherwise the binary uses `SimulationConfig::default()`.

### SimulationConfig Parameters

`SimulationConfig` is the central contract for the crate. Its fields are:

- `num_lambda`:
  number of lambda samples in the sweep grid
- `lambda_min`, `lambda_max`:
  inclusive sweep bounds used by `lambda_grid()`
- `steps_per_run`:
  fallback single run length when no multi-`N` sweep is requested
- `multi_steps_per_run`:
  optional list of run lengths for finite-size scaling; if non-empty this takes precedence over `steps_per_run`
- `random_seed`:
  deterministic seed for all pseudo-random branch choices
- `enable_aet`, `enable_tcp`, `enable_rlt`, `enable_iwlt`:
  per-layer switches that allow focused runs

Default values are chosen to make the crate useful out of the box:

- `num_lambda = 360`
- `lambda_min = 0.0`
- `lambda_max = 1.0`
- `steps_per_run = 512`
- `multi_steps_per_run = [512, 5000, 10000, 20000]`

That means the default binary run is already a finite-size scaling experiment across four trajectory lengths. For a one-off local production run, you can override this with:

```bash
cargo run --release -p dsfb-add --bin dsfb_add_sweep -- \
  --steps-per-run-list 512,5000,10000,20000,50000,100000
```

### What Each Rust Module Does

- `src/aet.rs`
  implements the AET word-evolution sweep and its perturbed variant
- `src/iwlt.rs`
  implements the IWLT append-and-reduce entropy sweep and its perturbed variant
- `src/rlt.rs`
  implements deterministic resonance walks, phase-transition proxies, and example trajectories
- `src/tcp.rs`
  implements deterministic 2D trajectory generation and exports multi-run point clouds for notebook-side PH
- `src/analysis/rlt_phase.rs`
  extracts `lambda_star`, transition-width brackets, and related phase-boundary quantities
- `src/analysis/structural_law.rs`
  fits the AET-IWLT structural law and computes the confidence interval used in downstream summaries
- `src/output.rs`
  owns CSV schema definitions and file-writing helpers
- `src/sweep.rs`
  is the orchestration layer: it loops over enabled `steps_per_run` values, runs baseline and perturbed sweeps, aggregates summaries, and writes the full output set
- `src/bin/dsfb_add_sweep.rs`
  is the CLI wrapper around `SimulationConfig` loading and sweep execution

### Progress Reporting

The sweep binary emits percentage-based progress updates while it runs. This is especially useful for large local finite-size runs where `steps_per_run` may extend up to `100000` or higher.

The progress tracker reports:

- the current subsystem,
- whether the run is baseline or perturbed,
- the current `steps_per_run`,
- and the overall percentage through the entire ADD job.

## Running The Sweep

From the repo root:

```bash
cargo run -p dsfb-add --bin dsfb_add_sweep
```

Optional config override:

```bash
cargo run -p dsfb-add --bin dsfb_add_sweep -- --config crates/dsfb-add/config.json
```

Finite-size scaling run:

```bash
cargo run -p dsfb-add --bin dsfb_add_sweep -- --steps-per-run-list 512,5000,10000,20000,50000,100000
```

If `config.json` exists in the current working directory, the binary loads it automatically. Otherwise it uses `SimulationConfig::default()`.

By default the crate now runs a finite-size scaling sweep across:

- `512`
- `5000`
- `10000`
- `20000`

and writes per-`N` files with `_N<steps>` suffixes, while also keeping unsuffixed canonical CSVs for the reference run. If `--steps-per-run-list` is provided, those values override the configured sweep list for that run.

Each run creates:

```text
output-dsfb-add/<YYYY-MM-DDTHH-MM-SSZ>/
```

inside the workspace root and writes the requested CSV outputs there.

## Why The Crate Is Split Between Rust And Colab

The Rust crate is responsible for deterministic generation, reproducibility, and explicit CSV schemas. The notebooks are responsible for figure production, persistent-homology post-processing, and exploratory views that would be awkward or heavyweight to maintain directly in Rust.

That split is intentional:

- Rust owns deterministic execution and file layout.
- CSVs provide stable interchange points for the paper workflow.
- Colab owns presentation, diagnostics, and final publication figures.

This design keeps the core ADD experiment reproducible from the command line while still making the paper's figure pipeline easy to rerun in the cloud.

## Using The Colab Notebook

Workflow:

1. Run the Rust sweep locally so the CSV files, point clouds, and trajectory examples are generated.
2. Zip, upload, or sync `output-dsfb-add/<timestamp>/` into your Colab environment, or let the notebook generate a fresh run in Colab.
3. Open `crates/dsfb-add/dsfb_add_sweep.ipynb` using the Colab badge in the main repo README.
4. Set `OUTPUT_DIR` only if you intentionally want an existing run directory; otherwise the notebook can bootstrap a fresh one.
5. Run the notebook cells to regenerate all PNG figures and derived summary CSVs in the same directory as the sweep outputs.

The notebook is structured so Rust remains the authoritative simulation layer and Colab remains the analysis and figure-generation layer. The Rust side produces deterministic sweeps and structural summaries; the notebook performs the paper-facing regression, finite-size scaling, residual diagnostics, universality comparison, and hero-figure assembly.

For Colab specifically, the notebook uses a minimal reproducible default sweep profile of `512` when it bootstraps a fresh Rust run. A dropdown near the top of the notebook selects the active `steps_per_run` value for both bootstrap and figure display, and it defaults to `512` so free CPU sessions remain practical. If you want the full production profile in Colab, set `RUST_MULTI_STEPS = [512, 5000, 10000, 20000, 50000, 100000]` in the notebook before running the bootstrap cell. If you run the large multi-`N` sweep locally and upload the results, that same dropdown lets you switch the displayed analysis to any available `N` without editing the plotting code.

For the completed local production run currently present in this workspace, use the dedicated replay notebook:

- `crates/dsfb-add/dsfb_add_results_replay.ipynb`

That notebook is preconfigured for:

- timestamp: `2026-03-01T18-19-22Z`
- expected archive: `output-dsfb-add/dsfb-add-2026-03-01T18-19-22Z.zip`

Its default behavior is analysis-only:

- `RUN_RUST_SWEEP_IN_COLAB = False`
- `OUTPUT_DIR = /content/output-dsfb-add/2026-03-01T18-19-22Z`

Upload that zip in Colab, run the helper cell `upload_and_unpack_replay_zip()`, and then run the remainder of the notebook. The same `steps_per_run` dropdown can then switch between `512`, `5000`, `10000`, `20000`, `50000`, and `100000` using the uploaded local results.

## Outputs

Expected runtime files:

- `aet_sweep.csv`
- `aet_sweep_perturbed.csv`
- `aet_sweep_N<steps>.csv`
- `aet_sweep_perturbed_N<steps>.csv`
- `tcp_sweep.csv`
- `tcp_sweep_N<steps>.csv`
- `rlt_sweep.csv`
- `rlt_sweep_perturbed.csv`
- `rlt_sweep_N<steps>.csv`
- `rlt_sweep_perturbed_N<steps>.csv`
- `iwlt_sweep.csv`
- `iwlt_sweep_perturbed.csv`
- `iwlt_sweep_N<steps>.csv`
- `iwlt_sweep_perturbed_N<steps>.csv`
- `tcp_points/lambda_<idx>_run_<r>.csv`
- `tcp_points_N<steps>/lambda_<idx>_run_<r>.csv`
- `rlt_examples/trajectory_bounded_lambda_<idx>.csv`
- `rlt_examples/trajectory_expanding_lambda_<idx>.csv`
- `rlt_examples_N<steps>/trajectory_bounded_lambda_<idx>.csv`
- `rlt_examples_N<steps>/trajectory_expanding_lambda_<idx>.csv`
- `rlt_phase_boundary.csv`
- `cross_layer_thresholds.csv`
- `tcp_phase_alignment.csv`
- `robustness_metrics.csv`
- `aet_iwlt_law_summary.csv`
- `aet_iwlt_scaling_summary.csv`
- `aet_iwlt_diagnostics_summary.csv`
- `tcp_ph_summary.csv` (written by the Colab notebook after persistent-homology post-processing)

Expected notebook figure outputs:

- `fig_aet_echo_slope_vs_lambda.png`
- `fig_aet_robustness.png`
- `fig_iwlt_entropy_density_vs_lambda.png`
- `fig_iwlt_robustness.png`
- `fig_rlt_escape_rate_vs_lambda.png`
- `fig_rlt_expansion_ratio_vs_lambda.png`
- `fig_rlt_expansion_ratio_vs_lambda_zoom.png`
- `fig_rlt_robustness.png`
- `fig_rlt_trajectory_bounded.png`
- `fig_rlt_trajectory_expanding.png`
- `fig_tcp_betti1_mean_vs_lambda.png`
- `fig_tcp_total_persistence_vs_lambda.png`
- `fig_aet_iwlt_structural_law.png`
- `fig_aet_iwlt_universality.png`
- `fig_aet_iwlt_scaling_slope_vs_N.png`
- `fig_aet_iwlt_scaling_r2_vs_N.png`
- `fig_aet_iwlt_scaling_resid_vs_N.png`
- `fig_aet_iwlt_residuals_vs_echo.png`
- `fig_aet_iwlt_residual_hist.png`
- `fig_aet_iwlt_ratio_vs_lambda.png`
- `fig_aet_iwlt_ratio_hist.png`
- `fig_aet_iwlt_loglog.png`
- `fig_cross_layer_summary_vs_lambda.png`
- `fig_rlt_phase_lambda_star_vs_N.png`
- `fig_rlt_phase_width_vs_N.png`
- `fig_rlt_phase_sharpness_vs_N.png`
- `fig_rlt_vs_aet_threshold.png`
- `fig_rlt_vs_iwlt_threshold.png`
- `fig_tcp_phase_alignment_vs_N.png`
- `fig_hero_add_stack.png`

`tcp_sweep.csv` includes coarse Rust-side topological proxies (`betti0`, `betti1`, `l_tcp`) plus radius statistics. The notebook augments those proxies with `ripser`-based H1 summary statistics computed from the exported per-lambda run clouds, with total persistence treated as the main smooth TCP observable.

The perturbed sweep CSVs are small deterministic robustness experiments: they nudge the update laws without changing the overall structural regime picture. The Rust sweep now writes the core numerical summaries directly:

- `aet_iwlt_law_summary.csv` contains the linear AET-IWLT fit per `N` and per mode, including `R^2`, residual variance, and slope confidence interval.
- `aet_iwlt_scaling_summary.csv` isolates the baseline finite-size scaling branch across `N`.
- `aet_iwlt_diagnostics_summary.csv` stores residual and ratio statistics per `N`.
- `rlt_phase_boundary.csv` stores `lambda_star`, the 0.1-0.9 transition width, and a finite-difference sharpness estimate.
- `cross_layer_thresholds.csv` records the AET and IWLT structural values at the RLT transport transition.
- `tcp_phase_alignment.csv` records how the TCP peak observables align with the RLT phase transition.
- `robustness_metrics.csv` compresses baseline-vs-perturbed deltas for the structural law and the RLT transition.

The notebook then turns those summaries into paper-ready figures, adds PH-derived TCP summaries, overlays diagnostics, and rebuilds the fully annotated hero figure.

Taken together, the outputs are meant to support the numerical section of the ADD paper:

- baseline and perturbed sweeps show the main structural response,
- multi-`N` runs show finite-size convergence,
- phase-boundary summaries quantify the RLT transport transition,
- structural-law summaries quantify the AET-IWLT coupling,
- and the hero figure condenses the stack into a single paper-facing panel.

## Publishability Notes

The crate is intended to be publishable on crates.io as a normal Rust package:

- it exposes a reusable library API,
- it ships a documented CLI binary,
- it includes the notebooks that consume the exported CSVs,
- and it depends on the published `dsfb` crate rather than on unpublished workspace-only internals.

The crate is therefore usable in two ways:

1. as a command-line experiment runner for ADD paper reproduction, and
2. as a library dependency for projects that want to orchestrate ADD sweeps programmatically.

## Relationship To The DSFB / ADD Papers

The DSFB crate provides the deterministic observer philosophy already present in this monorepo. The ADD paper extends that philosophy into structural dynamics: irreducible word growth, deterministic topological complexity, resonance spread, and entropy production without stochastic assumptions.

`dsfb-add` turns that argument into a repeatable experiment. Its outputs are the empirical curves used to study echo slopes, entropy densities, resonance spreads, and topology-vs-lambda structure for the ADD stack.