diff --git a/reports/blend/pd/README.md b/reports/blend/README.md
similarity index 94%
rename from reports/blend/pd/README.md
rename to reports/blend/README.md
index b7c8a1d..181da7b 100644
--- a/reports/blend/pd/README.md
+++ b/reports/blend/README.md
@@ -1,8 +1,8 @@
-# Peering degree in the Blend network — a Monte-Carlo study
+# The Blend network — a Monte-Carlo study
-*Static-graph network simulation of the Blend message cascade. Simulator: [`pd`](../../../tools/simulators/blend/pd). All delays in **milliseconds**; the free-running mix clock's maximum interval (`max_blend_delay`) is in **whole seconds**. Adversary and deanonymization metrics are exact at every network size; propagation is Monte-Carlo over random senders.*
+*Network simulation of the Blend message cascade. Simulator: [`blend`](../../tools/simulators/blend). All delays in **milliseconds**; the free-running mix clock's maximum interval (`max_blend_delay`) is in **whole seconds**. Adversary and deanonymization metrics are exact at every network size; propagation is Monte-Carlo over random senders.*
-This report quantifies how a node's **peering degree** — the number of symmetric peers it keeps — trades off four properties of the Blend network at once: how fast a message propagates, how much of the network an adversary observes, how often a message is deanonymized, and how reliably messages are delivered when a fraction of nodes go dark. The headline is a single tension: **raising the peering degree improves propagation speed, eclipse resistance, and churn resilience, but *worsens* observation and sender deanonymization.** The anonymity axis has its own, degree-independent control — the **blend-path length** — so the two knobs separate cleanly: set the degree for the transport goals, set the path length for the anonymity goal. Two further questions follow from the deanonymization rates: *how long* an adversary needs to link an emitter to its messages and to learn its stake — which scales inversely with the node's own stake — and how **messaging redundancy** (sending each message over several independent cascades) trades reliability against anonymity, amplifying both by the very same factor.
+This report measures the Blend network end to end: how fast a message propagates, how much of the network an adversary observes, how often a message is deanonymized and how quickly a node can be linked to one, how reliably messages are delivered when nodes go dark or whole regions fail, and what cover traffic buys. **Peering degree** is the first axis and the one that ties the others together, because it trades off several of these at once: the headline is a single tension: **raising the peering degree improves propagation speed, eclipse resistance, and churn resilience, but *worsens* observation and sender deanonymization.** The anonymity axis has its own, degree-independent control — the **blend-path length** — so the two knobs separate cleanly: set the degree for the transport goals, set the path length for the anonymity goal. Two further questions follow from the deanonymization rates: *how long* an adversary needs to link an emitter to its messages and to learn its stake — which scales inversely with the node's own stake — and how **messaging redundancy** (sending each message over several independent cascades) trades reliability against anonymity, amplifying both by the very same factor.
## Headline
@@ -392,7 +392,7 @@ Because `s_max` is expressed against `D̂`, an estimator that runs low tightens
## 6. Reproducibility
-The simulator, configs, and analytic checks live in [`tools/simulators/blend/pd`](../../../tools/simulators/blend/pd). From that directory: `make install`, then `make sweep` runs the main grid (`configs/default.yaml`: N up to 10⁵, degree 3–16, 1–5 blend hops, `f_adv` up to 0.5, unresponsive fractions to 0.5, all three placement modes, 8 topology seeds) into `runs/_default/`, writing three tables — `propagation.parquet`, `adversary.parquet`, and `deanon.parquet` — and rendering the figures. `make sweep-fullscale` extends the exact metrics to 10⁶ nodes. The messaging-redundancy study (§3.8) and the linkability figures come from `configs/redundancy.yaml` (`python -m pd.sweep --config configs/redundancy.yaml`), which sweeps `redundancy` ∈ {1, 2, 3, 4} alongside the churn and adversary grids; the churn-threshold study (§3.5, Fig 20) comes from `configs/percolation.yaml`, which walks the unresponsive fraction to 0.9 so each degree's collapse can be located against `u_c = 1 − 1/(degree − 1)`; and the correlated-outage study (§3.9, Fig 22) from `configs/correlated-churn.yaml` (`make correlated-churn`), which partitions the network into failure domains and runs both churn modes on the same topologies. `make sweep-fullscale` produces the 10⁶ scaling check described in §5; and the cover-traffic study (§3.10, Figs 23–24) comes from `configs/cover-traffic.yaml`, which sweeps the emission rate over three decades against three release delays and pairs each timeline with the epoch-scale emission budget. Round counts in all three configs are set for statistical resolution, not speed — see the sampling-error note in §5. `make verify` runs the analytic anchors (d-regularity; `observed ≈ 1 − (1 − f)^degree`; `eclipsed ≈ f^degree`; delivery `≈ (1 − u)^blend_hops`; both deanonymization rates against a direct Monte-Carlo of the same draw; and — check 6 — `deanon_R` / `delivery_R = 1 − (1 − x)^R` for R independent cascades and the time-to-link geometric law), and `make test` the unit suite (`test_linkability.py` covers the time-to-link and stake formulae). The time-to-link and stake-inference curves are computed by `pd.linkability` from these exact rates.
+The simulator, configs, and analytic checks live in [`tools/simulators/blend`](../../tools/simulators/blend). From that directory: `make install`, then `make sweep` runs the main grid (`configs/default.yaml`: N up to 10⁵, degree 3–16, 1–5 blend hops, `f_adv` up to 0.5, unresponsive fractions to 0.5, all three placement modes, 8 topology seeds) into `runs/_default/`, writing three tables — `propagation.parquet`, `adversary.parquet`, and `deanon.parquet` — and rendering the figures. `make sweep-fullscale` extends the exact metrics to 10⁶ nodes. The messaging-redundancy study (§3.8) and the linkability figures come from `configs/redundancy.yaml` (`python -m blend.sweep --config configs/redundancy.yaml`), which sweeps `redundancy` ∈ {1, 2, 3, 4} alongside the churn and adversary grids; the churn-threshold study (§3.5, Fig 20) comes from `configs/percolation.yaml`, which walks the unresponsive fraction to 0.9 so each degree's collapse can be located against `u_c = 1 − 1/(degree − 1)`; and the correlated-outage study (§3.9, Fig 22) from `configs/correlated-churn.yaml` (`make correlated-churn`), which partitions the network into failure domains and runs both churn modes on the same topologies. `make sweep-fullscale` produces the 10⁶ scaling check described in §5; and the cover-traffic study (§3.10, Figs 23–24) comes from `configs/cover-traffic.yaml`, which sweeps the emission rate over three decades against three release delays and pairs each timeline with the epoch-scale emission budget. Round counts in all three configs are set for statistical resolution, not speed — see the sampling-error note in §5. `make verify` runs the analytic anchors (d-regularity; `observed ≈ 1 − (1 − f)^degree`; `eclipsed ≈ f^degree`; delivery `≈ (1 − u)^blend_hops`; both deanonymization rates against a direct Monte-Carlo of the same draw; and — check 6 — `deanon_R` / `delivery_R = 1 − (1 − x)^R` for R independent cascades and the time-to-link geometric law), and `make test` the unit suite (`test_linkability.py` covers the time-to-link and stake formulae). The time-to-link and stake-inference curves are computed by `blend.linkability` from these exact rates.
The figures of record for this report are the copies checked in under [`report-figures/`](report-figures); the simulator does not commit its own generated figures. To regenerate: run the sweeps above, then copy `runs/<…>/figures/*.png` into `report-figures/`.
diff --git a/reports/blend/pd/data/README.md b/reports/blend/data/README.md
similarity index 95%
rename from reports/blend/pd/data/README.md
rename to reports/blend/data/README.md
index c5921a5..eb52f24 100644
--- a/reports/blend/pd/data/README.md
+++ b/reports/blend/data/README.md
@@ -17,7 +17,7 @@ Each run directory holds the three tables the simulator writes: `propagation.par
| `cover-traffic/` | `configs/cover-traffic.yaml` | 900 s timeline × 4 seeds | §3.10 — blending, mixing, and the emission-quota stake ceiling. Carries a fourth table, `traffic.parquet` |
The linkability results (§3.6–§3.7) and both deanonymization rates are closed forms over these
-tables rather than separate measurements, so they have no run of their own — `pd.linkability`
+tables rather than separate measurements, so they have no run of their own — `blend.linkability`
derives them and `make verify` checks them against Monte-Carlo.
## Regenerating the report's numbers
@@ -33,7 +33,7 @@ runs instead.
## Regenerating the data itself
-From [`tools/simulators/blend/pd`](../../../../tools/simulators/blend/pd): `make sweep`,
+From [`tools/simulators/blend`](../../../tools/simulators/blend): `make sweep`,
`make redundancy`, `make percolation`, `make correlated-churn`, `make sweep-fullscale`. Results
land in that simulator's `runs/_/`. Note that the seed streams depend on the
configuration, so re-running reproduces the *statistics*, not bit-identical numbers, unless the
diff --git a/reports/blend/pd/data/correlated-churn/adversary.parquet b/reports/blend/data/correlated-churn/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/correlated-churn/adversary.parquet
rename to reports/blend/data/correlated-churn/adversary.parquet
diff --git a/reports/blend/pd/data/correlated-churn/deanon.parquet b/reports/blend/data/correlated-churn/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/correlated-churn/deanon.parquet
rename to reports/blend/data/correlated-churn/deanon.parquet
diff --git a/reports/blend/pd/data/correlated-churn/propagation.parquet b/reports/blend/data/correlated-churn/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/correlated-churn/propagation.parquet
rename to reports/blend/data/correlated-churn/propagation.parquet
diff --git a/reports/blend/pd/data/cover-traffic/adversary.parquet b/reports/blend/data/cover-traffic/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/cover-traffic/adversary.parquet
rename to reports/blend/data/cover-traffic/adversary.parquet
diff --git a/reports/blend/pd/data/cover-traffic/deanon.parquet b/reports/blend/data/cover-traffic/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/cover-traffic/deanon.parquet
rename to reports/blend/data/cover-traffic/deanon.parquet
diff --git a/reports/blend/pd/data/cover-traffic/propagation.parquet b/reports/blend/data/cover-traffic/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/cover-traffic/propagation.parquet
rename to reports/blend/data/cover-traffic/propagation.parquet
diff --git a/reports/blend/pd/data/cover-traffic/traffic.parquet b/reports/blend/data/cover-traffic/traffic.parquet
similarity index 100%
rename from reports/blend/pd/data/cover-traffic/traffic.parquet
rename to reports/blend/data/cover-traffic/traffic.parquet
diff --git a/reports/blend/pd/data/default/adversary.parquet b/reports/blend/data/default/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/default/adversary.parquet
rename to reports/blend/data/default/adversary.parquet
diff --git a/reports/blend/pd/data/default/deanon.parquet b/reports/blend/data/default/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/default/deanon.parquet
rename to reports/blend/data/default/deanon.parquet
diff --git a/reports/blend/pd/data/default/propagation.parquet b/reports/blend/data/default/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/default/propagation.parquet
rename to reports/blend/data/default/propagation.parquet
diff --git a/reports/blend/pd/data/fullscale/adversary.parquet b/reports/blend/data/fullscale/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/fullscale/adversary.parquet
rename to reports/blend/data/fullscale/adversary.parquet
diff --git a/reports/blend/pd/data/fullscale/deanon.parquet b/reports/blend/data/fullscale/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/fullscale/deanon.parquet
rename to reports/blend/data/fullscale/deanon.parquet
diff --git a/reports/blend/pd/data/fullscale/propagation.parquet b/reports/blend/data/fullscale/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/fullscale/propagation.parquet
rename to reports/blend/data/fullscale/propagation.parquet
diff --git a/reports/blend/pd/data/percolation/adversary.parquet b/reports/blend/data/percolation/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/percolation/adversary.parquet
rename to reports/blend/data/percolation/adversary.parquet
diff --git a/reports/blend/pd/data/percolation/deanon.parquet b/reports/blend/data/percolation/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/percolation/deanon.parquet
rename to reports/blend/data/percolation/deanon.parquet
diff --git a/reports/blend/pd/data/percolation/propagation.parquet b/reports/blend/data/percolation/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/percolation/propagation.parquet
rename to reports/blend/data/percolation/propagation.parquet
diff --git a/reports/blend/pd/data/redundancy/adversary.parquet b/reports/blend/data/redundancy/adversary.parquet
similarity index 100%
rename from reports/blend/pd/data/redundancy/adversary.parquet
rename to reports/blend/data/redundancy/adversary.parquet
diff --git a/reports/blend/pd/data/redundancy/deanon.parquet b/reports/blend/data/redundancy/deanon.parquet
similarity index 100%
rename from reports/blend/pd/data/redundancy/deanon.parquet
rename to reports/blend/data/redundancy/deanon.parquet
diff --git a/reports/blend/pd/data/redundancy/propagation.parquet b/reports/blend/data/redundancy/propagation.parquet
similarity index 100%
rename from reports/blend/pd/data/redundancy/propagation.parquet
rename to reports/blend/data/redundancy/propagation.parquet
diff --git a/reports/blend/pd/data/report_numbers.py b/reports/blend/data/report_numbers.py
similarity index 100%
rename from reports/blend/pd/data/report_numbers.py
rename to reports/blend/data/report_numbers.py
diff --git a/reports/blend/pd/report-figures/01_delay_vs_degree.png b/reports/blend/report-figures/01_delay_vs_degree.png
similarity index 100%
rename from reports/blend/pd/report-figures/01_delay_vs_degree.png
rename to reports/blend/report-figures/01_delay_vs_degree.png
diff --git a/reports/blend/pd/report-figures/02_delay_vs_blendhops.png b/reports/blend/report-figures/02_delay_vs_blendhops.png
similarity index 100%
rename from reports/blend/pd/report-figures/02_delay_vs_blendhops.png
rename to reports/blend/report-figures/02_delay_vs_blendhops.png
diff --git a/reports/blend/pd/report-figures/03_delay_vs_N.png b/reports/blend/report-figures/03_delay_vs_N.png
similarity index 100%
rename from reports/blend/pd/report-figures/03_delay_vs_N.png
rename to reports/blend/report-figures/03_delay_vs_N.png
diff --git a/reports/blend/pd/report-figures/04_observed_vs_fadv.png b/reports/blend/report-figures/04_observed_vs_fadv.png
similarity index 100%
rename from reports/blend/pd/report-figures/04_observed_vs_fadv.png
rename to reports/blend/report-figures/04_observed_vs_fadv.png
diff --git a/reports/blend/pd/report-figures/05_eclipse_vs_fadv.png b/reports/blend/report-figures/05_eclipse_vs_fadv.png
similarity index 100%
rename from reports/blend/pd/report-figures/05_eclipse_vs_fadv.png
rename to reports/blend/report-figures/05_eclipse_vs_fadv.png
diff --git a/reports/blend/pd/report-figures/06_observed_vs_degree.png b/reports/blend/report-figures/06_observed_vs_degree.png
similarity index 100%
rename from reports/blend/pd/report-figures/06_observed_vs_degree.png
rename to reports/blend/report-figures/06_observed_vs_degree.png
diff --git a/reports/blend/pd/report-figures/07_eclipse_vs_degree.png b/reports/blend/report-figures/07_eclipse_vs_degree.png
similarity index 100%
rename from reports/blend/pd/report-figures/07_eclipse_vs_degree.png
rename to reports/blend/report-figures/07_eclipse_vs_degree.png
diff --git a/reports/blend/pd/report-figures/08_heatmap_observed.png b/reports/blend/report-figures/08_heatmap_observed.png
similarity index 100%
rename from reports/blend/pd/report-figures/08_heatmap_observed.png
rename to reports/blend/report-figures/08_heatmap_observed.png
diff --git a/reports/blend/pd/report-figures/09_heatmap_eclipse.png b/reports/blend/report-figures/09_heatmap_eclipse.png
similarity index 100%
rename from reports/blend/pd/report-figures/09_heatmap_eclipse.png
rename to reports/blend/report-figures/09_heatmap_eclipse.png
diff --git a/reports/blend/pd/report-figures/10_delivery_vs_unresponsive.png b/reports/blend/report-figures/10_delivery_vs_unresponsive.png
similarity index 100%
rename from reports/blend/pd/report-figures/10_delivery_vs_unresponsive.png
rename to reports/blend/report-figures/10_delivery_vs_unresponsive.png
diff --git a/reports/blend/pd/report-figures/11_coverage_vs_unresponsive.png b/reports/blend/report-figures/11_coverage_vs_unresponsive.png
similarity index 100%
rename from reports/blend/pd/report-figures/11_coverage_vs_unresponsive.png
rename to reports/blend/report-figures/11_coverage_vs_unresponsive.png
diff --git a/reports/blend/pd/report-figures/12_deanon_vs_blendhops.png b/reports/blend/report-figures/12_deanon_vs_blendhops.png
similarity index 100%
rename from reports/blend/pd/report-figures/12_deanon_vs_blendhops.png
rename to reports/blend/report-figures/12_deanon_vs_blendhops.png
diff --git a/reports/blend/pd/report-figures/13_full_deanon_vs_blendhops.png b/reports/blend/report-figures/13_full_deanon_vs_blendhops.png
similarity index 100%
rename from reports/blend/pd/report-figures/13_full_deanon_vs_blendhops.png
rename to reports/blend/report-figures/13_full_deanon_vs_blendhops.png
diff --git a/reports/blend/pd/report-figures/14_full_deanon_vs_fadv.png b/reports/blend/report-figures/14_full_deanon_vs_fadv.png
similarity index 100%
rename from reports/blend/pd/report-figures/14_full_deanon_vs_fadv.png
rename to reports/blend/report-figures/14_full_deanon_vs_fadv.png
diff --git a/reports/blend/pd/report-figures/15_full_deanon_vs_degree.png b/reports/blend/report-figures/15_full_deanon_vs_degree.png
similarity index 100%
rename from reports/blend/pd/report-figures/15_full_deanon_vs_degree.png
rename to reports/blend/report-figures/15_full_deanon_vs_degree.png
diff --git a/reports/blend/pd/report-figures/16_time_to_link_vs_stake.png b/reports/blend/report-figures/16_time_to_link_vs_stake.png
similarity index 100%
rename from reports/blend/pd/report-figures/16_time_to_link_vs_stake.png
rename to reports/blend/report-figures/16_time_to_link_vs_stake.png
diff --git a/reports/blend/pd/report-figures/17_time_to_link_vs_stake_redundancy.png b/reports/blend/report-figures/17_time_to_link_vs_stake_redundancy.png
similarity index 100%
rename from reports/blend/pd/report-figures/17_time_to_link_vs_stake_redundancy.png
rename to reports/blend/report-figures/17_time_to_link_vs_stake_redundancy.png
diff --git a/reports/blend/pd/report-figures/18_time_to_stake_vs_threshold.png b/reports/blend/report-figures/18_time_to_stake_vs_threshold.png
similarity index 100%
rename from reports/blend/pd/report-figures/18_time_to_stake_vs_threshold.png
rename to reports/blend/report-figures/18_time_to_stake_vs_threshold.png
diff --git a/reports/blend/pd/report-figures/19_redundancy_tradeoff.png b/reports/blend/report-figures/19_redundancy_tradeoff.png
similarity index 100%
rename from reports/blend/pd/report-figures/19_redundancy_tradeoff.png
rename to reports/blend/report-figures/19_redundancy_tradeoff.png
diff --git a/reports/blend/pd/report-figures/20_coverage_percolation.png b/reports/blend/report-figures/20_coverage_percolation.png
similarity index 100%
rename from reports/blend/pd/report-figures/20_coverage_percolation.png
rename to reports/blend/report-figures/20_coverage_percolation.png
diff --git a/reports/blend/pd/report-figures/21_redundancy_time_to_link.png b/reports/blend/report-figures/21_redundancy_time_to_link.png
similarity index 100%
rename from reports/blend/pd/report-figures/21_redundancy_time_to_link.png
rename to reports/blend/report-figures/21_redundancy_time_to_link.png
diff --git a/reports/blend/pd/report-figures/22_churn_correlated_vs_uniform.png b/reports/blend/report-figures/22_churn_correlated_vs_uniform.png
similarity index 100%
rename from reports/blend/pd/report-figures/22_churn_correlated_vs_uniform.png
rename to reports/blend/report-figures/22_churn_correlated_vs_uniform.png
diff --git a/reports/blend/pd/report-figures/23_blending_vs_rate_and_delay.png b/reports/blend/report-figures/23_blending_vs_rate_and_delay.png
similarity index 100%
rename from reports/blend/pd/report-figures/23_blending_vs_rate_and_delay.png
rename to reports/blend/report-figures/23_blending_vs_rate_and_delay.png
diff --git a/reports/blend/pd/report-figures/24_quota_stake_ceiling.png b/reports/blend/report-figures/24_quota_stake_ceiling.png
similarity index 100%
rename from reports/blend/pd/report-figures/24_quota_stake_ceiling.png
rename to reports/blend/report-figures/24_quota_stake_ceiling.png
diff --git a/tools/simulators/blend/pd/.gitignore b/tools/simulators/blend/.gitignore
similarity index 100%
rename from tools/simulators/blend/pd/.gitignore
rename to tools/simulators/blend/.gitignore
diff --git a/tools/simulators/blend/pd/Makefile b/tools/simulators/blend/Makefile
similarity index 76%
rename from tools/simulators/blend/pd/Makefile
rename to tools/simulators/blend/Makefile
index 343832a..f9fe822 100644
--- a/tools/simulators/blend/pd/Makefile
+++ b/tools/simulators/blend/Makefile
@@ -21,28 +21,28 @@ $(STAMP): pyproject.toml
install: $(STAMP)
smoke: $(STAMP) ## fast end-to-end (seconds): tiny N, few rounds/seeds
- $(PY) -m pd.sweep --config configs/smoke.yaml
+ $(PY) -m blend.sweep --config configs/smoke.yaml
sweep: $(STAMP)
- $(PY) -m pd.sweep --config configs/default.yaml
+ $(PY) -m blend.sweep --config configs/default.yaml
sweep-fullscale: $(STAMP)
- $(PY) -m pd.sweep --config configs/fullscale.yaml
+ $(PY) -m blend.sweep --config configs/fullscale.yaml
redundancy: $(STAMP) ## messaging redundancy R=1..4 (delivery vs deanonymization, time-to-link)
- $(PY) -m pd.sweep --config configs/redundancy.yaml
+ $(PY) -m blend.sweep --config configs/redundancy.yaml
percolation: $(STAMP) ## churn threshold: coverage collapse at u_c = 1 - 1/(degree-1)
- $(PY) -m pd.sweep --config configs/percolation.yaml
+ $(PY) -m blend.sweep --config configs/percolation.yaml
correlated-churn: $(STAMP) ## correlated AS/region outages vs uniform churn, matched fractions
- $(PY) -m pd.sweep --config configs/correlated-churn.yaml
+ $(PY) -m blend.sweep --config configs/correlated-churn.yaml
figures: $(STAMP) ## make figures RUN=runs/
- $(PY) -m pd.plotting.make_figures --run $(RUN)
+ $(PY) -m blend.plotting.make_figures --run $(RUN)
verify: $(STAMP)
- $(PY) -m pd.verify
+ $(PY) -m blend.verify
test: $(STAMP)
$(PY) -m pytest
diff --git a/tools/simulators/blend/pd/README.md b/tools/simulators/blend/README.md
similarity index 92%
rename from tools/simulators/blend/pd/README.md
rename to tools/simulators/blend/README.md
index 0fcbec1..4f44c56 100644
--- a/tools/simulators/blend/pd/README.md
+++ b/tools/simulators/blend/README.md
@@ -1,6 +1,9 @@
-# pd — peering-degree Monte-Carlo graph simulator
+# blend — a Monte-Carlo simulator for the Blend network
-Quantifies how a node's **peering degree** trades off, in the Blend network:
+Measures the Blend network on a seeded peer graph: propagation, adversary exposure,
+deanonymization, reliability under churn, messaging redundancy and cover traffic.
+Peering degree is the primary study axis and the one that ties the rest together —
+it trades off, simultaneously:
- **propagation speed** — the full delay (ms) of a message: a random sender routes it along a
`blend_hops`-relay Blend path (each relay a free-running timed-release mix node) and the last
@@ -62,14 +65,14 @@ adversary metrics are exact at every N).
random node set. Clustered failure leaves the survivors fully connected (`frac_reached_live`
stays ~1) while stranding the dead domains (`frac_reached` falls); see `configs/correlated-churn.yaml`.
Regions are failure and peering domains only — link latency does not depend on them.
-- **Linkability over time** (`pd.linkability`): given the rates above and an emission cadence (one
+- **Linkability over time** (`blend.linkability`): given the rates above and an emission cadence (one
node emits per 30 s slot, chosen ∝ stake), the module derives the *time to link* an emitter
(`≈ 30 s·ln(1/(1−α))/(stake·q)`, inverse in stake) and the *time to learn its stake* to a threshold
from the count of attributable observations. See `configs/redundancy.yaml` and the report.
## Quick start
```
-make install # or reuse a sibling venv: PYTHONPATH=src -m pd.sweep ...
+make install # or reuse a sibling venv: PYTHONPATH=src -m blend.sweep ...
make smoke # fast end-to-end (every code path + 19 of 21 figure builders)
make verify # analytic checks (closed forms + graph invariants)
make test # unit tests
@@ -93,7 +96,7 @@ unresponsive fraction (with the `u_c = 1-1/(degree-1)` threshold), the deanonymi
time-to-link / stake-inference / redundancy curves derived from them by `linkability`.
## Layout
-`src/pd/`: `graph` (matching-union CSR d-regular), `propagation` (Blend cascade), `mixclock`
+`src/blend/`: `graph` (matching-union CSR d-regular), `propagation` (Blend cascade), `mixclock`
(release-clock residual), `adversary` (exact observation/eclipse + deanonymization + placement),
`config`/`engine`/`sweep`/`metrics`, `plotting`. `configs/` sweeps, `tests/`, `scripts/` shims.
-Reports of record live outside the sim at `reports/blend/pd/`.
+Reports of record live outside the sim at `reports/blend/`.
diff --git a/tools/simulators/blend/pd/configs/correlated-churn.yaml b/tools/simulators/blend/configs/correlated-churn.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/correlated-churn.yaml
rename to tools/simulators/blend/configs/correlated-churn.yaml
diff --git a/tools/simulators/blend/pd/configs/cover-traffic.yaml b/tools/simulators/blend/configs/cover-traffic.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/cover-traffic.yaml
rename to tools/simulators/blend/configs/cover-traffic.yaml
diff --git a/tools/simulators/blend/pd/configs/default.yaml b/tools/simulators/blend/configs/default.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/default.yaml
rename to tools/simulators/blend/configs/default.yaml
diff --git a/tools/simulators/blend/pd/configs/fullscale.yaml b/tools/simulators/blend/configs/fullscale.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/fullscale.yaml
rename to tools/simulators/blend/configs/fullscale.yaml
diff --git a/tools/simulators/blend/pd/configs/percolation.yaml b/tools/simulators/blend/configs/percolation.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/percolation.yaml
rename to tools/simulators/blend/configs/percolation.yaml
diff --git a/tools/simulators/blend/pd/configs/redundancy.yaml b/tools/simulators/blend/configs/redundancy.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/redundancy.yaml
rename to tools/simulators/blend/configs/redundancy.yaml
diff --git a/tools/simulators/blend/pd/configs/smoke.yaml b/tools/simulators/blend/configs/smoke.yaml
similarity index 100%
rename from tools/simulators/blend/pd/configs/smoke.yaml
rename to tools/simulators/blend/configs/smoke.yaml
diff --git a/tools/simulators/blend/pd/pyproject.toml b/tools/simulators/blend/pyproject.toml
similarity index 83%
rename from tools/simulators/blend/pd/pyproject.toml
rename to tools/simulators/blend/pyproject.toml
index 458a292..fcad6ec 100644
--- a/tools/simulators/blend/pd/pyproject.toml
+++ b/tools/simulators/blend/pyproject.toml
@@ -3,7 +3,7 @@ requires = ["hatchling"]
build-backend = "hatchling.build"
[project]
-name = "pd"
+name = "blend"
version = "0.1.0"
description = "Peering-degree Monte-Carlo graph simulator for the Blend network"
requires-python = ">=3.11"
@@ -22,12 +22,12 @@ dependencies = [
dev = ["pytest", "pytest-xdist", "ruff", "mypy"]
[project.scripts]
-pd-sweep = "pd.sweep:main"
-pd-verify = "pd.verify:main"
-pd-figures = "pd.plotting.make_figures:main"
+pd-sweep = "blend.sweep:main"
+pd-verify = "blend.verify:main"
+pd-figures = "blend.plotting.make_figures:main"
[tool.hatch.build.targets.wheel]
-packages = ["src/pd"]
+packages = ["src/blend"]
[tool.ruff]
line-length = 100
diff --git a/tools/simulators/blend/pd/requirements-dev.txt b/tools/simulators/blend/requirements-dev.txt
similarity index 100%
rename from tools/simulators/blend/pd/requirements-dev.txt
rename to tools/simulators/blend/requirements-dev.txt
diff --git a/tools/simulators/blend/pd/requirements.txt b/tools/simulators/blend/requirements.txt
similarity index 100%
rename from tools/simulators/blend/pd/requirements.txt
rename to tools/simulators/blend/requirements.txt
diff --git a/tools/simulators/blend/pd/scripts/make_figures.py b/tools/simulators/blend/scripts/make_figures.py
similarity index 57%
rename from tools/simulators/blend/pd/scripts/make_figures.py
rename to tools/simulators/blend/scripts/make_figures.py
index be5fbe5..bc37f44 100644
--- a/tools/simulators/blend/pd/scripts/make_figures.py
+++ b/tools/simulators/blend/scripts/make_figures.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
-"""Shim: add src/ to sys.path, then run pd.plotting.make_figures:main."""
+"""Shim: add src/ to sys.path, then run blend.plotting.make_figures:main."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
-from pd.plotting.make_figures import main # noqa: E402
+from blend.plotting.make_figures import main # noqa: E402
if __name__ == "__main__":
raise SystemExit(main())
diff --git a/tools/simulators/blend/pd/scripts/run_sweep.py b/tools/simulators/blend/scripts/run_sweep.py
similarity index 64%
rename from tools/simulators/blend/pd/scripts/run_sweep.py
rename to tools/simulators/blend/scripts/run_sweep.py
index 9e18f86..5777b8e 100644
--- a/tools/simulators/blend/pd/scripts/run_sweep.py
+++ b/tools/simulators/blend/scripts/run_sweep.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
-"""Shim: add src/ to sys.path, then run pd.sweep:main."""
+"""Shim: add src/ to sys.path, then run blend.sweep:main."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
-from pd.sweep import main # noqa: E402
+from blend.sweep import main # noqa: E402
if __name__ == "__main__":
raise SystemExit(main())
diff --git a/tools/simulators/blend/pd/scripts/verify.py b/tools/simulators/blend/scripts/verify.py
similarity index 63%
rename from tools/simulators/blend/pd/scripts/verify.py
rename to tools/simulators/blend/scripts/verify.py
index 7863933..7174595 100644
--- a/tools/simulators/blend/pd/scripts/verify.py
+++ b/tools/simulators/blend/scripts/verify.py
@@ -1,11 +1,11 @@
#!/usr/bin/env python3
-"""Shim: add src/ to sys.path, then run pd.verify:main."""
+"""Shim: add src/ to sys.path, then run blend.verify:main."""
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
-from pd.verify import main # noqa: E402
+from blend.verify import main # noqa: E402
if __name__ == "__main__":
raise SystemExit(main())
diff --git a/tools/simulators/blend/pd/src/pd/__init__.py b/tools/simulators/blend/src/blend/__init__.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/__init__.py
rename to tools/simulators/blend/src/blend/__init__.py
diff --git a/tools/simulators/blend/pd/src/pd/adversary.py b/tools/simulators/blend/src/blend/adversary.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/adversary.py
rename to tools/simulators/blend/src/blend/adversary.py
diff --git a/tools/simulators/blend/pd/src/pd/config.py b/tools/simulators/blend/src/blend/config.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/config.py
rename to tools/simulators/blend/src/blend/config.py
diff --git a/tools/simulators/blend/pd/src/pd/constants.py b/tools/simulators/blend/src/blend/constants.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/constants.py
rename to tools/simulators/blend/src/blend/constants.py
diff --git a/tools/simulators/blend/pd/src/pd/engine.py b/tools/simulators/blend/src/blend/engine.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/engine.py
rename to tools/simulators/blend/src/blend/engine.py
diff --git a/tools/simulators/blend/pd/src/pd/graph.py b/tools/simulators/blend/src/blend/graph.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/graph.py
rename to tools/simulators/blend/src/blend/graph.py
diff --git a/tools/simulators/blend/pd/src/pd/latency.py b/tools/simulators/blend/src/blend/latency.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/latency.py
rename to tools/simulators/blend/src/blend/latency.py
diff --git a/tools/simulators/blend/pd/src/pd/linkability.py b/tools/simulators/blend/src/blend/linkability.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/linkability.py
rename to tools/simulators/blend/src/blend/linkability.py
diff --git a/tools/simulators/blend/pd/src/pd/memguard.py b/tools/simulators/blend/src/blend/memguard.py
similarity index 92%
rename from tools/simulators/blend/pd/src/pd/memguard.py
rename to tools/simulators/blend/src/blend/memguard.py
index 5a4bddf..5fd57ce 100644
--- a/tools/simulators/blend/pd/src/pd/memguard.py
+++ b/tools/simulators/blend/src/blend/memguard.py
@@ -6,7 +6,7 @@ sampled single-source distance matrices (``S x N`` or ``(blend_hops+1) x N``), w
would exceed its budget, so an under-sized config fails with a clear message instead of freezing
the machine.
-Budget (``budget_bytes``): ``PD_BYTES_BUDGET`` > 0 -> that many bytes (the sweep sets this to
+Budget (``budget_bytes``): ``BLEND_BYTES_BUDGET`` > 0 -> that many bytes (the sweep sets this to
each worker's RAM share); otherwise ``DEFAULT_BUDGET_FRAC`` of physical RAM.
"""
@@ -38,7 +38,7 @@ def total_ram_bytes() -> int:
def budget_bytes() -> int:
"""Per-process byte budget for a single big array (see module docstring)."""
try:
- explicit = int(os.environ.get("PD_BYTES_BUDGET", "0"))
+ explicit = int(os.environ.get("BLEND_BYTES_BUDGET", "0"))
except ValueError:
explicit = 0
if explicit > 0:
diff --git a/tools/simulators/blend/pd/src/pd/metrics.py b/tools/simulators/blend/src/blend/metrics.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/metrics.py
rename to tools/simulators/blend/src/blend/metrics.py
diff --git a/tools/simulators/blend/pd/src/pd/mixclock.py b/tools/simulators/blend/src/blend/mixclock.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/mixclock.py
rename to tools/simulators/blend/src/blend/mixclock.py
diff --git a/tools/simulators/blend/pd/src/pd/plotting/__init__.py b/tools/simulators/blend/src/blend/plotting/__init__.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/plotting/__init__.py
rename to tools/simulators/blend/src/blend/plotting/__init__.py
diff --git a/tools/simulators/blend/pd/src/pd/plotting/figures.py b/tools/simulators/blend/src/blend/plotting/figures.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/plotting/figures.py
rename to tools/simulators/blend/src/blend/plotting/figures.py
diff --git a/tools/simulators/blend/pd/src/pd/plotting/make_figures.py b/tools/simulators/blend/src/blend/plotting/make_figures.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/plotting/make_figures.py
rename to tools/simulators/blend/src/blend/plotting/make_figures.py
diff --git a/tools/simulators/blend/pd/src/pd/plotting/style.py b/tools/simulators/blend/src/blend/plotting/style.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/plotting/style.py
rename to tools/simulators/blend/src/blend/plotting/style.py
diff --git a/tools/simulators/blend/pd/src/pd/propagation.py b/tools/simulators/blend/src/blend/propagation.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/propagation.py
rename to tools/simulators/blend/src/blend/propagation.py
diff --git a/tools/simulators/blend/pd/src/pd/quota.py b/tools/simulators/blend/src/blend/quota.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/quota.py
rename to tools/simulators/blend/src/blend/quota.py
diff --git a/tools/simulators/blend/pd/src/pd/rng.py b/tools/simulators/blend/src/blend/rng.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/rng.py
rename to tools/simulators/blend/src/blend/rng.py
diff --git a/tools/simulators/blend/pd/src/pd/sweep.py b/tools/simulators/blend/src/blend/sweep.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/sweep.py
rename to tools/simulators/blend/src/blend/sweep.py
diff --git a/tools/simulators/blend/pd/src/pd/traffic.py b/tools/simulators/blend/src/blend/traffic.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/traffic.py
rename to tools/simulators/blend/src/blend/traffic.py
diff --git a/tools/simulators/blend/pd/src/pd/verify.py b/tools/simulators/blend/src/blend/verify.py
similarity index 100%
rename from tools/simulators/blend/pd/src/pd/verify.py
rename to tools/simulators/blend/src/blend/verify.py
diff --git a/tools/simulators/blend/pd/tests/test_adversary.py b/tools/simulators/blend/tests/test_adversary.py
similarity index 93%
rename from tools/simulators/blend/pd/tests/test_adversary.py
rename to tools/simulators/blend/tests/test_adversary.py
index 52649b6..901cf4f 100644
--- a/tools/simulators/blend/pd/tests/test_adversary.py
+++ b/tools/simulators/blend/tests/test_adversary.py
@@ -2,9 +2,9 @@ from itertools import combinations
import numpy as np
-from pd.adversary import _greedy_coverage, adversary_metrics, place_adversary
-from pd.config import SimConfig
-from pd.graph import Graph, build_graph
+from blend.adversary import _greedy_coverage, adversary_metrics, place_adversary
+from blend.config import SimConfig
+from blend.graph import Graph, build_graph
def _cycle4():
diff --git a/tools/simulators/blend/pd/tests/test_config.py b/tools/simulators/blend/tests/test_config.py
similarity index 98%
rename from tools/simulators/blend/pd/tests/test_config.py
rename to tools/simulators/blend/tests/test_config.py
index a3d3459..daae8d0 100644
--- a/tools/simulators/blend/pd/tests/test_config.py
+++ b/tools/simulators/blend/tests/test_config.py
@@ -2,7 +2,7 @@ import dataclasses
import pytest
-from pd.config import SimConfig, SweepConfig
+from blend.config import SimConfig, SweepConfig
def test_key_covers_every_field():
diff --git a/tools/simulators/blend/pd/tests/test_deanon.py b/tools/simulators/blend/tests/test_deanon.py
similarity index 96%
rename from tools/simulators/blend/pd/tests/test_deanon.py
rename to tools/simulators/blend/tests/test_deanon.py
index 8c2bd3b..aa42022 100644
--- a/tools/simulators/blend/pd/tests/test_deanon.py
+++ b/tools/simulators/blend/tests/test_deanon.py
@@ -6,10 +6,10 @@ uniformly blind to who is adversarial, so both rates are exact (no sampling in p
import numpy as np
-from pd.adversary import adversary_metrics, deanon_metrics, place_adversary
-from pd.config import SimConfig
-from pd.engine import run_graph_cell
-from pd.graph import build_graph
+from blend.adversary import adversary_metrics, deanon_metrics, place_adversary
+from blend.config import SimConfig
+from blend.engine import run_graph_cell
+from blend.graph import build_graph
def test_deanon_rate_hand_computed():
diff --git a/tools/simulators/blend/pd/tests/test_graph.py b/tools/simulators/blend/tests/test_graph.py
similarity index 96%
rename from tools/simulators/blend/pd/tests/test_graph.py
rename to tools/simulators/blend/tests/test_graph.py
index cdfda46..da100a2 100644
--- a/tools/simulators/blend/pd/tests/test_graph.py
+++ b/tools/simulators/blend/tests/test_graph.py
@@ -1,8 +1,8 @@
import numpy as np
import pytest
-from pd.config import SimConfig
-from pd.graph import build_graph, build_regular_edges
+from blend.config import SimConfig
+from blend.graph import build_graph, build_regular_edges
@pytest.mark.parametrize("n,degree", [(10, 1), (10, 2), (10, 3), (100, 4), (100, 7),
diff --git a/tools/simulators/blend/pd/tests/test_linkability.py b/tools/simulators/blend/tests/test_linkability.py
similarity index 98%
rename from tools/simulators/blend/pd/tests/test_linkability.py
rename to tools/simulators/blend/tests/test_linkability.py
index 84fd2a3..38a1137 100644
--- a/tools/simulators/blend/pd/tests/test_linkability.py
+++ b/tools/simulators/blend/tests/test_linkability.py
@@ -4,7 +4,7 @@ import math
import numpy as np
-from pd.linkability import (
+from blend.linkability import (
capture_prob,
obs_for_precision,
redundant,
diff --git a/tools/simulators/blend/pd/tests/test_mixclock.py b/tools/simulators/blend/tests/test_mixclock.py
similarity index 91%
rename from tools/simulators/blend/pd/tests/test_mixclock.py
rename to tools/simulators/blend/tests/test_mixclock.py
index bb1082d..405ae5f 100644
--- a/tools/simulators/blend/pd/tests/test_mixclock.py
+++ b/tools/simulators/blend/tests/test_mixclock.py
@@ -1,6 +1,6 @@
import numpy as np
-from pd.mixclock import mean_residual_ms, mix_wait
+from blend.mixclock import mean_residual_ms, mix_wait
def test_zero_max_delay_is_zero():
diff --git a/tools/simulators/blend/pd/tests/test_propagation.py b/tools/simulators/blend/tests/test_propagation.py
similarity index 96%
rename from tools/simulators/blend/pd/tests/test_propagation.py
rename to tools/simulators/blend/tests/test_propagation.py
index 1fc6546..2edddea 100644
--- a/tools/simulators/blend/pd/tests/test_propagation.py
+++ b/tools/simulators/blend/tests/test_propagation.py
@@ -1,9 +1,9 @@
import numpy as np
-from pd.config import SimConfig
-from pd.graph import Graph, build_graph
-from pd.propagation import assign_responsive, blend_round, propagation_metrics
-from pd.rng import responsive_seedseq, round_seedseq
+from blend.config import SimConfig
+from blend.graph import Graph, build_graph
+from blend.propagation import assign_responsive, blend_round, propagation_metrics
+from blend.rng import responsive_seedseq, round_seedseq
def _k4(p):
@@ -206,7 +206,7 @@ def test_redundant_cascades_flood_the_same_component():
def test_regional_churn_drops_whole_regions_and_matches_the_uniform_count():
"""Correlated churn kills failure domains, not scattered nodes -- at the same total count."""
- from pd.graph import region_of
+ from blend.graph import region_of
n, n_regions, u = 1000, 10, 0.3
rng = np.random.default_rng(0)
mask = assign_responsive(n, u, rng, "regional", n_regions)
@@ -220,7 +220,7 @@ def test_regional_churn_drops_whole_regions_and_matches_the_uniform_count():
def test_uniform_churn_scatters_across_all_regions():
- from pd.graph import region_of
+ from blend.graph import region_of
n, n_regions, u = 1000, 10, 0.3
mask = assign_responsive(n, u, np.random.default_rng(0), "uniform", n_regions)
region = region_of(n, n_regions)
@@ -229,7 +229,7 @@ def test_uniform_churn_scatters_across_all_regions():
def test_region_locality_keeps_peers_inside_the_region_and_stays_d_regular():
- from pd.graph import build_graph, region_of
+ from blend.graph import build_graph, region_of
n, n_regions, degree = 2000, 10, 8
region = region_of(n, n_regions)
for locality, want in ((0.0, 0.1), (0.5, 0.5), (1.0, 1.0)):
@@ -244,7 +244,7 @@ def test_region_locality_keeps_peers_inside_the_region_and_stays_d_regular():
def test_regional_churn_leaves_survivors_better_connected():
"""The point of the correlated model: clustered failure removes whole neighbourhoods and
leaves the rest intact, so surviving nodes keep more live peers than under scattered failure."""
- from pd.graph import build_graph
+ from blend.graph import build_graph
n, n_regions, degree, u = 4000, 20, 8, 0.4
cfg = SimConfig(n_nodes=n, degree=degree, n_regions=n_regions, region_locality=0.75,
graph_seed=0)
diff --git a/tools/simulators/blend/pd/tests/test_quota.py b/tools/simulators/blend/tests/test_quota.py
similarity index 99%
rename from tools/simulators/blend/pd/tests/test_quota.py
rename to tools/simulators/blend/tests/test_quota.py
index 813ccd8..5da6592 100644
--- a/tools/simulators/blend/pd/tests/test_quota.py
+++ b/tools/simulators/blend/tests/test_quota.py
@@ -4,7 +4,7 @@ import math
import numpy as np
-from pd.quota import (
+from blend.quota import (
alpha_max,
assign_stake,
emission_quota_per_slot,
diff --git a/tools/simulators/blend/pd/tests/test_rng.py b/tools/simulators/blend/tests/test_rng.py
similarity index 96%
rename from tools/simulators/blend/pd/tests/test_rng.py
rename to tools/simulators/blend/tests/test_rng.py
index 188e64c..b45016b 100644
--- a/tools/simulators/blend/pd/tests/test_rng.py
+++ b/tools/simulators/blend/tests/test_rng.py
@@ -1,5 +1,5 @@
-from pd.config import SimConfig
-from pd.rng import (
+from blend.config import SimConfig
+from blend.rng import (
graph_seedseq,
responsive_seedseq,
rng_for,
diff --git a/tools/simulators/blend/pd/tests/test_traffic.py b/tools/simulators/blend/tests/test_traffic.py
similarity index 97%
rename from tools/simulators/blend/pd/tests/test_traffic.py
rename to tools/simulators/blend/tests/test_traffic.py
index fc57f31..e345463 100644
--- a/tools/simulators/blend/pd/tests/test_traffic.py
+++ b/tools/simulators/blend/tests/test_traffic.py
@@ -2,9 +2,9 @@
import numpy as np
-from pd.config import SimConfig
-from pd.graph import build_graph
-from pd.traffic import ReleaseClock, simulate_window, traffic_metrics
+from blend.config import SimConfig
+from blend.graph import build_graph
+from blend.traffic import ReleaseClock, simulate_window, traffic_metrics
def _win(n_nodes=2000, degree=8, hops=3, M=3, mult=1.0, slots=600, seed=0):