Skip to main content

gam_models/
outer_subsample.rs

1//! Outer-score row subsampling and the model-layer row-measure bridge.
2//!
3//! The canonical definitions of [`OuterScoreSubsample`], [`RowSet`], and
4//! [`WeightedOuterRow`] are neutral low-layer primitives that live in the
5//! `gam-problem` crate so the `CustomFamily` trait layer (and the model
6//! families above it) can depend on them downward without duplication. This
7//! module is the single model-layer authority that translates those primitives
8//! into custom-family fit options.
9
10pub use gam_problem::outer_subsample::*;
11
12/// Derive the exact family-facing outer options from the spatial optimizer's
13/// authoritative row measure.
14///
15/// This is the sole bridge from [`RowSet`] into custom-family options.  In
16/// particular, `All` must clear both an inherited pilot and automatic sampling;
17/// otherwise a pilot mask can survive the optimizer's full-data transition and
18/// make the inner mode, objective, gradient, and Hessian describe different
19/// measures.
20pub(crate) fn exact_outer_options_for_row_set(
21    options: &crate::custom_family::BlockwiseFitOptions,
22    row_set: &RowSet,
23) -> crate::custom_family::BlockwiseFitOptions {
24    let mut effective = options.clone();
25    effective.auto_outer_subsample = false;
26    effective.outer_score_subsample = match row_set {
27        RowSet::All => None,
28        RowSet::Subsample { rows, n_full } => Some(std::sync::Arc::new(
29            OuterScoreSubsample::from_weighted_rows(rows.as_ref().clone(), *n_full, 0),
30        )),
31    };
32    effective
33}
34
35#[cfg(test)]
36mod tests {
37    use super::*;
38
39    #[test]
40    fn exact_outer_options_bind_analytic_and_efs_lanes_to_one_row_measure() {
41        let mut options = crate::custom_family::BlockwiseFitOptions::default();
42        options.auto_outer_subsample = true;
43        options.outer_score_subsample = Some(std::sync::Arc::new(
44            OuterScoreSubsample::from_uniform_inclusion_mask(vec![9], 10, 17),
45        ));
46        let rows = std::sync::Arc::new(vec![
47            WeightedOuterRow {
48                index: 1,
49                weight: 2.5,
50                stratum: 3,
51            },
52            WeightedOuterRow {
53                index: 7,
54                weight: 4.0,
55                stratum: 8,
56            },
57        ]);
58
59        let sampled = exact_outer_options_for_row_set(
60            &options,
61            &RowSet::Subsample { rows, n_full: 11 },
62        );
63        assert!(!sampled.auto_outer_subsample);
64        let installed = sampled
65            .outer_score_subsample
66            .as_ref()
67            .expect("authoritative exact-outer row measure");
68        assert_eq!(installed.n_full, 11);
69        assert_eq!(installed.seed, 0);
70        assert_eq!(installed.rows.len(), 2);
71        assert_eq!(installed.rows[0].index, 1);
72        assert_eq!(installed.rows[0].weight.to_bits(), 2.5_f64.to_bits());
73        assert_eq!(installed.rows[0].stratum, 3);
74        assert_eq!(installed.rows[1].index, 7);
75        assert_eq!(installed.rows[1].weight.to_bits(), 4.0_f64.to_bits());
76        assert_eq!(installed.rows[1].stratum, 8);
77
78        let full = exact_outer_options_for_row_set(&options, &RowSet::All);
79        assert!(!full.auto_outer_subsample);
80        assert!(
81            full.outer_score_subsample.is_none(),
82            "full-data replay must clear every stale pilot mask"
83        );
84        assert!(
85            options.outer_score_subsample.is_some(),
86            "deriving the effective measure must not mutate caller options"
87        );
88    }
89}