docs: state filtered accessor cost and evidence semantics precisely

filtered_learning_curve's signature mirrors learning_curve, which is cheap
per key — so the mirroring trained callers to assume this one is too. It is
a full forward pass per call, making the natural loop over competitors
O(competitors * events). The doc now says so in complexity terms and points
multi-key callers at the plural form.

filtered_log_evidence claimed each event is scored "using only what was
known before it". That is exact for a slice holding one event, but events
sharing a timestamp inform each other through the within-slice sweep, so
the honest claim is "before that time". The behaviour is deliberate and
matches log_evidence's own convention; only the promise was too strong.

This branch exists because a feature's documentation was quietly false.
Shipping it with two more overstated doc comments would be a poor joke.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01T5SYDExxL4vZgvunrcNSMc
This commit is contained in:
2026-08-27 16:59:42 +02:00
co-authored by Claude Opus 5
parent 9c39d1e681
commit 69ddebe21d
+15 -8
View File
@@ -383,7 +383,9 @@ impl<T: Time, D: Drift<T>, O: Observer<T>, K: Eq + Hash + Clone> History<T, D, O
/// time — "what we knew then". Contrast `learning_curves`, whose points
/// are smoothed and so incorporate rounds played later.
///
/// Runs a full forward pass per call and caches nothing.
/// Runs a full forward pass per call and caches nothing. This is the
/// entry point for multi-key work — see `filtered_learning_curve` for
/// why calling that once per key is far more expensive.
pub fn filtered_learning_curves(&self) -> HashMap<K, Vec<(T, Gaussian)>> {
let mut data: HashMap<K, Vec<(T, Gaussian)>> = HashMap::new();
@@ -401,9 +403,11 @@ impl<T: Time, D: Drift<T>, O: Observer<T>, K: Eq + Hash + Clone> History<T, D, O
/// Filtered learning curve for a single key: (time, posterior) pairs in
/// time order.
///
/// Runs the same full pass as `filtered_learning_curves` and keeps one
/// key, so asking for several keys individually costs a pass each — use
/// the plural form for that.
/// Despite mirroring `learning_curve`'s signature, this is not the cheap
/// per-key lookup that method is: it runs a full forward pass, O(events),
/// discarding every posterior but the requested key's. N keys fetched
/// this way costs O(N * events); use `filtered_learning_curves` for
/// multi-key work instead — it computes the same pass once.
pub fn filtered_learning_curve<Q>(&self, key: &Q) -> Vec<(T, Gaussian)>
where
K: Borrow<Q>,
@@ -484,10 +488,13 @@ impl<T: Time, D: Drift<T>, O: Observer<T>, K: Eq + Hash + Clone> History<T, D, O
/// Total log-evidence under forward-only (filtering) information.
///
/// Each event is scored using only what was known before it, which is the
/// right quantity for prequential scoring and model comparison. Contrast
/// `log_evidence`, whose per-event priors carry information from events
/// that had not happened yet.
/// Each event is scored using only what was known before that *time*,
/// which is the right quantity for prequential scoring and model
/// comparison. Events sharing a timestamp still inform each other
/// through the within-slice sweep, so within one slice this is not a
/// guarantee that event A is scored independently of simultaneous event
/// B. Contrast `log_evidence`, whose per-event priors carry information
/// from events that had not happened yet.
///
/// Runs a full forward pass per call and caches nothing. The result does
/// not depend on whether `converge` has been called.