logaritmisk
|
d2aab82c1e
|
T0 + T1 + T2: engine redesign through new API surface (#1)
Implements tiers T0, T1, T2 of `docs/superpowers/specs/2026-04-23-trueskill-engine-redesign-design.md`. All three tiers have landed together on this branch because they build on one another; this PR rolls them up for a single review pass.
Per-tier plans:
- T0: `docs/superpowers/plans/2026-04-23-t0-numerical-parity.md`
- T1: `docs/superpowers/plans/2026-04-24-t1-factor-graph.md`
- T2: `docs/superpowers/plans/2026-04-24-t2-new-api-surface.md`
## Summary
### T0 — Numerical parity (internal)
- `Gaussian` switched to natural-parameter storage `(pi, tau)`; mul/div now ~7× faster (218 ps vs 1.57 ns).
- `HashMap<Index, _>` → dense `Vec<_>` keyed by `Index.0` (via `AgentStore<D>`, `SkillStore`).
- `ScratchArena` eliminates per-event allocations in `Game::likelihoods`.
- `InferenceError` seed type added (1 variant).
- 38 → 53 tests passing through T1.
- Benchmark: `Batch::iteration` 29.84 → 21.25 µs.
### T1 — Factor graph machinery (internal)
- `Factor` trait + `BuiltinFactor` enum (TeamSum / RankDiff / Trunc) driving within-game inference.
- `VarStore` flat storage for variable marginals.
- `Schedule` trait + `EpsilonOrMax` impl replacing the hand-rolled EP loop.
- `Game::likelihoods` rebuilt on the factor-graph machinery; iteration counts and goldens preserved to within 1e-6.
- 53 tests passing.
- Benchmark: `Batch::iteration` 23.01 µs (slight regression absorbed in T2).
### T2 — New API surface (breaking)
**Renames:**
- `IndexMap → KeyTable`, `Player → Rating`, `Agent → Competitor`, `Batch → TimeSlice`
**New types:**
- `Time` trait with `Untimed` ZST and `i64` impls; `Drift<T>`, `Rating<T, D>`, `Competitor<T, D>`, `TimeSlice<T>`, `History<T, D, O, K>` all generic.
- `Event<T, K>`, `Team<K>`, `Member<K>`, `Outcome` (`Ranked` variant; `#[non_exhaustive]`).
- `Observer<T>` trait + `NullObserver`.
- `ConvergenceOptions`, `ConvergenceReport`.
- `GameOptions`, `OwnedGame<T, D>`.
**Three-tier ingestion:**
- `history.record_winner(&K, &K, T)` / `record_draw(&K, &K, T)` — 1v1 convenience.
- `history.add_events(iter)` — typed bulk.
- `history.event(T).team([...]).weights([...]).ranking([...]).commit()` — fluent.
**Query API:** `current_skill`, `learning_curve`, `learning_curves` (keyed on `K`), `log_evidence`, `log_evidence_for`, `predict_quality`, `predict_outcome`.
**Game constructors:** `ranked`, `one_v_one`, `free_for_all`, `custom` — all returning `Result<_, InferenceError>`.
**`factors` module:** `Factor`, `Schedule`, `VarStore`, `VarId`, `BuiltinFactor`, `EpsilonOrMax`, `ScheduleReport`, `TeamSumFactor`, `RankDiffFactor`, `TruncFactor` now public.
**Errors:** `InferenceError` gains `MismatchedShape`, `InvalidProbability`, `ConvergenceFailed`; boundary panics converted to `Result`.
**Removed (breaking):** `History::convergence(iters, eps, verbose)`, `HistoryBuilder::gamma(f64)`, `HistoryBuilder::time(bool)`, `History.time: bool`, `learning_curves_by_index`, nested-Vec public `add_events`.
## Behavior change (documented in CHANGELOG)
`Time = Untimed` has `elapsed_to → 0`, so no drift accumulates between slices. The old `time=false` mode implicitly forced `elapsed=1` on reappearance via an `i64::MAX` sentinel — that quirk is not reproducible under a typed time axis. Tests that depended on it now use `History::<i64, _>` with explicit `1..=n` timestamps. One test (`test_env_ttt`) had 3 Gaussian goldens updated to reflect the corrected semantics; documented in commit `33a7d90`.
## Final numbers
| Metric | Before T0 | After T2 | Delta |
|---|---|---|---|
| `Batch::iteration` | 29.84 µs | 21.36 µs | **-28%** |
| `Gaussian::mul` | 1.57 ns | 219 ps | **-86%** |
| `Gaussian::div` | 1.57 ns | 219 ps | **-86%** |
| Tests passing | 38 | 90 | +52 |
All other Gaussian ops unchanged (~219 ps add/sub, ~264 ps pi/tau reads).
## Test plan
- [x] `cargo test --features approx` — 90/90 pass (68 lib + 10 api_shape + 6 game + 4 record_winner + 2 equivalence)
- [x] `cargo clippy --all-targets --features approx -- -D warnings` — clean
- [x] `cargo +nightly fmt --check` — clean
- [x] `cargo bench --bench batch` — 21.36 µs
- [x] `cargo bench --bench gaussian` — unchanged from T1
- [x] `cargo run --example atp --features approx` — rewritten in new API, runs clean
- [x] Historical Game-level goldens preserved in `tests/equivalence.rs`
- [x] Public API matches spec Section 4 (verified by integration tests in `tests/api_shape.rs`)
## Commit history
~45 commits total across T0 + T1 + T2. Each task is self-contained and individually tested; the branch is bisectable. See `git log main..t2-new-api-surface` for the full list.
## Deferred to later tiers
- `Outcome::Scored` + `MarginFactor` — T4
- `Damped` / `Residual` schedules — T4
- `Send + Sync` bounds + Rayon parallelism — T3
- N-team `predict_outcome` — T4
- `Game::custom` full ergonomics — T4
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Reviewed-on: #1
Co-authored-by: Anders Olsson <anders.e.olsson@gmail.com>
Co-committed-by: Anders Olsson <anders.e.olsson@gmail.com>
|
2026-04-24 11:20:04 +00:00 |
|
logaritmisk
|
a14df02089
|
chore: do not publish
|
2026-04-23 20:26:52 +02:00 |
|
logaritmisk
|
0d266b4428
|
chore: make cargo release add CHANGELOG.md before commit
|
2026-04-23 20:26:16 +02:00 |
|
logaritmisk
|
a4b4e5e8fa
|
chore: clean up
|
2026-04-23 20:24:10 +02:00 |
|
logaritmisk
|
04d5478ee4
|
style: cargo fmt
|
2026-04-23 20:23:13 +02:00 |
|
logaritmisk
|
480467ac32
|
chore: added cliff.toml, release.toml and rustfmt.toml
|
2026-04-23 20:22:27 +02:00 |
|
logaritmisk
|
dc47964310
|
added benchmark
|
2026-03-23 14:55:18 +01:00 |
|
logaritmisk
|
61a5507f5c
|
remove notepad
|
2026-03-23 14:21:23 +01:00 |
|
logaritmisk
|
a1f282a1c8
|
feat: added a Drift trait and a "default" ConstantDrift implementation
|
2026-03-16 12:06:04 +01:00 |
|
logaritmisk
|
853f177fa8
|
Small changes for new 2024 edition
|
2025-02-21 14:09:58 +01:00 |
|
logaritmisk
|
fc0efcdc52
|
Update edition
|
2025-02-21 14:06:28 +01:00 |
|
logaritmisk
|
3bbddb168f
|
Ignore temp folder
|
2024-04-03 14:43:54 +02:00 |
|
logaritmisk
|
2366c45f6a
|
Basic test for quality
|
2024-04-03 10:25:10 +02:00 |
|
logaritmisk
|
3a22b20a17
|
Added todo to readme, and documentation for quality function
|
2024-04-03 09:53:07 +02:00 |
|
logaritmisk
|
02ae2f0977
|
Change assert to debug_assert
|
2024-04-03 09:44:41 +02:00 |
|
logaritmisk
|
a491f8de8d
|
Fix broken link in README
|
2023-01-09 14:37:07 +01:00 |
|
logaritmisk
|
0b4b07d60e
|
Added more links to readme
|
2023-01-09 14:35:34 +01:00 |
|
logaritmisk
|
05f178641c
|
Rename d to diff, and t to team
|
2022-12-29 20:38:36 +01:00 |
|
logaritmisk
|
e3906aebaa
|
Small refactor
|
2022-12-27 22:37:12 +01:00 |
|
logaritmisk
|
8e25826f91
|
More rustifying
|
2022-12-27 22:30:20 +01:00 |
|
logaritmisk
|
9b6cb9e7eb
|
Make it more rusty
|
2022-12-27 22:24:01 +01:00 |
|
logaritmisk
|
fdddf56156
|
Remove unused mut reference
|
2022-12-27 22:11:04 +01:00 |
|
logaritmisk
|
b93194f762
|
Added default implementation for TeamMessage
|
2022-12-20 11:08:27 +01:00 |
|
logaritmisk
|
2b83ee5ef9
|
Added benchmark for Batch
|
2022-12-19 07:42:08 +01:00 |
|
logaritmisk
|
2bdd3d9b89
|
Remove warnings and refactor some code
|
2022-12-16 19:46:01 +01:00 |
|
logaritmisk
|
912a282cd8
|
More refactoring
|
2022-12-16 15:57:56 +01:00 |
|
logaritmisk
|
51467f7b69
|
Fix clippy warning
|
2022-12-16 15:51:58 +01:00 |
|
logaritmisk
|
6dd84f7fd2
|
Refactor so we can see if there is any way to improve the performance
|
2022-12-16 15:38:29 +01:00 |
|
logaritmisk
|
5eb8e62d6e
|
Agents doens't have to be behind a mutable reference in within_priors
|
2022-12-15 20:13:25 +01:00 |
|
logaritmisk
|
8bea1b5399
|
Agents doens't have to be behind a mutable reference in within_prior
|
2022-12-15 20:12:55 +01:00 |
|
logaritmisk
|
6546cb54b5
|
Added a get function to IndexMap
|
2022-12-12 13:25:07 +01:00 |
|
logaritmisk
|
13e6454d3d
|
Update crates and added methods to get a key or all keys in an IndexMap
|
2022-12-12 10:50:59 +01:00 |
|
logaritmisk
|
18d55a8ccf
|
Clean up example
|
2022-07-04 23:13:57 +02:00 |
|
logaritmisk
|
32df04fb6d
|
Small change
|
2022-06-28 23:29:44 +02:00 |
|
logaritmisk
|
22c61d47b1
|
Change time to use i64 instead of u64
|
2022-06-28 23:18:55 +02:00 |
|
logaritmisk
|
6125a81696
|
Fixed test
|
2022-06-27 11:49:47 +02:00 |
|
logaritmisk
|
2467d7e027
|
Update test to use assert_ulps_eq
|
2022-06-27 11:46:59 +02:00 |
|
logaritmisk
|
0633c766a5
|
Update example so now it works, and thats, well, good
|
2022-06-27 10:22:26 +02:00 |
|
logaritmisk
|
cd1079a811
|
Use and Index struct instead of str and String for player id
|
2022-06-27 10:16:12 +02:00 |
|
logaritmisk
|
d52895f804
|
Remove unused code
|
2022-06-23 07:48:44 +02:00 |
|
logaritmisk
|
ba2f8cffdc
|
Update test to use builder
|
2022-06-23 07:44:34 +02:00 |
|
logaritmisk
|
73b9cabac8
|
Added builder for History, and start migrating test to use builder instead.
|
2022-06-22 21:13:24 +02:00 |
|
logaritmisk
|
a573f5cf0a
|
More tests
|
2022-06-21 10:48:04 +02:00 |
|
logaritmisk
|
1647ba5c77
|
More tests
|
2022-06-21 10:42:14 +02:00 |
|
logaritmisk
|
be4834ca85
|
Fix tests
|
2022-06-20 23:58:05 +02:00 |
|
logaritmisk
|
0a35645091
|
More things, more tests
|
2022-06-20 23:56:35 +02:00 |
|
logaritmisk
|
0efb0312da
|
More tests, more code
|
2022-06-19 23:52:52 +02:00 |
|
logaritmisk
|
c9d9d59535
|
More things, better things, awesome
|
2022-06-18 23:39:42 +02:00 |
|
logaritmisk
|
dc10504b80
|
Port from julia version instead
|
2022-06-18 22:27:38 +02:00 |
|
logaritmisk
|
36c3366990
|
Refactor some stuff
|
2022-06-15 13:26:03 +02:00 |
|
logaritmisk
|
0a3327f076
|
Refactor some code
|
2022-06-15 11:27:24 +02:00 |
|
logaritmisk
|
811a4ca418
|
Inline a lot of functions
|
2022-06-14 23:00:21 +02:00 |
|
logaritmisk
|
9b025fb53a
|
Use PlayerIndex instead of String
|
2022-06-14 22:51:11 +02:00 |
|
logaritmisk
|
3fbac02de3
|
It works, or so it seems
|
2022-06-13 23:18:19 +02:00 |
|
logaritmisk
|
1b6e07225b
|
Handle case where there is no time
|
2022-06-13 21:55:43 +02:00 |
|
logaritmisk
|
82e7b22443
|
Use flatten instead of flat_map
|
2022-06-13 11:37:56 +02:00 |
|
logaritmisk
|
de4b324651
|
Remove Display impl, better to use Debug
|
2022-06-13 11:35:08 +02:00 |
|
logaritmisk
|
87a64acb83
|
Added more functions to History
|
2022-06-13 11:27:49 +02:00 |
|
logaritmisk
|
4a13e4dcd2
|
More test passing for History
|
2022-06-13 11:04:05 +02:00 |
|
logaritmisk
|
4227617513
|
Working on History struct. First test is passing.
|
2022-06-12 23:11:13 +02:00 |
|
logaritmisk
|
5a7053fb5d
|
Passing tests for Batch
|
2022-06-12 21:43:35 +02:00 |
|
logaritmisk
|
ae1c765dbb
|
Begin working on batch.
|
2022-06-12 21:02:57 +02:00 |
|
logaritmisk
|
de58d01322
|
Initial commit.
|
2022-06-10 15:22:27 +02:00 |
|