#[allow(dead_code)]
mod common;
use aprender_contrastive_data::pairs::{
EmittedKinds, PairConfig, PairKind, PairLayout, PairSampler, RetainedState, SamplerStateReport,
};
const C_EXAMPLES: usize = 1;
const C_CLASSES: usize = 3;
const C_CONST: usize = 8;
fn capacity_bound(examples: u64, classes: usize) -> usize {
let examples = usize::try_from(examples).expect("test layouts are far below usize::MAX");
C_EXAMPLES * examples + C_CLASSES * classes + C_CONST
}
fn check_capacity_invariant(
subject: &dyn RetainedState,
examples: u64,
classes: usize,
) -> Result<SamplerStateReport, String> {
let report = subject.state_report();
let total = report.total_retained_entries();
let bound = capacity_bound(examples, classes);
if total <= bound {
return Ok(report);
}
Err(format!(
"retained state {total} exceeds {bound} = {C_EXAMPLES}*{examples} + \
{C_CLASSES}*{classes} + {C_CONST}; buckets={}, pos_weights={}, neg_weights={}, \
offsets={}, materialized_pairs={}",
report.bucket_entries,
report.positive_weight_entries,
report.negative_weight_entries,
report.class_offset_entries,
report.materialized_pairs,
))
}
struct MaterializingSampler {
class_offsets: Vec<u64>,
positive_weights: Vec<u64>,
negative_weights: Vec<u64>,
bucket: Vec<u32>,
pairs: Vec<(u32, u32)>,
}
impl MaterializingSampler {
fn from_class_sizes(class_sizes: &[u64]) -> Self {
let total: u64 = class_sizes.iter().sum();
let examples = u32::try_from(total).expect("test layouts stay small");
let mut class_offsets = Vec::with_capacity(class_sizes.len());
let mut positive_weights = Vec::with_capacity(class_sizes.len());
let mut negative_weights = Vec::with_capacity(class_sizes.len());
let mut running = 0_u64;
for &n in class_sizes {
class_offsets.push(running);
positive_weights.push(n * n.saturating_sub(1) / 2);
negative_weights.push(n * (total - n));
running += n;
}
let mut pairs = Vec::new();
for first in 0..examples {
for second in (first + 1)..examples {
pairs.push((first, second));
}
}
Self {
class_offsets,
positive_weights,
negative_weights,
bucket: (0..examples).collect(),
pairs,
}
}
}
impl RetainedState for MaterializingSampler {
fn state_report(&self) -> SamplerStateReport {
SamplerStateReport {
bucket_entries: self.bucket.len(),
positive_weight_entries: self.positive_weights.len(),
negative_weight_entries: self.negative_weights.len(),
class_offset_entries: self.class_offsets.len(),
materialized_pairs: self.pairs.len(),
}
}
}
const WIDE_CLASSES: usize = 3;
const WIDE_SHOTS: u32 = 64;
const NARROW_SHOTS: u32 = 8;
const EXAMPLE_GROWTH_FACTOR: usize = (WIDE_SHOTS / NARROW_SHOTS) as usize;
const SEED: u64 = 31;
fn wide_class_sizes() -> Vec<u64> {
vec![u64::from(WIDE_SHOTS); WIDE_CLASSES]
}
fn narrow_class_sizes() -> Vec<u64> {
vec![u64::from(NARROW_SHOTS); WIDE_CLASSES]
}
fn layout(class_sizes: &[u64], budget: u64) -> PairLayout {
PairLayout::from_class_sizes(
class_sizes,
&PairConfig {
budget: Some(budget),
..PairConfig::new(SEED)
},
)
.expect("every layout used here has pair capacity")
}
#[test]
fn the_materializing_sampler_violates_the_capacity_invariant() {
let sizes = wide_class_sizes();
let examples: u64 = sizes.iter().sum();
let materializing = MaterializingSampler::from_class_sizes(&sizes);
let report = materializing.state_report();
assert_eq!(
report.materialized_pairs,
(192 * 191) / 2,
"the materializer must actually hold the whole Cartesian set"
);
let failure = check_capacity_invariant(&materializing, examples, WIDE_CLASSES).expect_err(
"the capacity gate ACCEPTED a sampler holding the entire Cartesian pair set. \
Every boundedness result in this crate is worthless.",
);
assert!(
failure.contains("materialized_pairs=18336"),
"the failure does not report the materialized pair count: {failure}"
);
assert!(
failure.contains("exceeds 209"),
"the failure does not report the bound it broke: {failure}"
);
}
#[test]
fn mirror_the_honest_sampler_satisfies_the_same_capacity_call_at_the_same_layout() {
let selection =
common::synthetic_selection(WIDE_CLASSES, WIDE_SHOTS as usize, SEED, WIDE_SHOTS);
let sampler = PairSampler::new(&selection, &PairConfig::new(SEED))
.expect("192 examples in 3 classes have pair capacity");
let examples: u64 = selection.len() as u64;
assert_eq!(
examples, 192,
"the mirror must be the SAME layout as the negative"
);
let report = check_capacity_invariant(&sampler, examples, WIDE_CLASSES)
.expect("the identical call must ACCEPT the honest streaming sampler");
assert_eq!(
report.materialized_pairs, 0,
"an honest streaming sampler holds no pairs at all"
);
assert!(
sampler.budget() >= 24_576,
"the mirror must run at a budget large enough for materialization to be tempting; \
got {}",
sampler.budget()
);
}
#[test]
fn honest_state_grows_no_faster_than_the_examples_while_the_materializer_grows_quadratically() {
let small = common::synthetic_selection(WIDE_CLASSES, WIDE_SHOTS as usize, SEED, NARROW_SHOTS);
let large = common::synthetic_selection(WIDE_CLASSES, WIDE_SHOTS as usize, SEED, WIDE_SHOTS);
let budget = 128;
let cfg = PairConfig {
budget: Some(budget),
..PairConfig::new(SEED)
};
let small_sampler = PairSampler::new(&small, &cfg).expect("24 examples support 128 pairs");
let large_sampler = PairSampler::new(&large, &cfg).expect("192 examples support 128 pairs");
assert_eq!(small_sampler.budget(), large_sampler.budget());
assert_eq!(large.len(), small.len() * EXAMPLE_GROWTH_FACTOR);
let honest_small = small_sampler.state_report().total_retained_entries();
let honest_large = large_sampler.state_report().total_retained_entries();
assert!(
honest_large <= honest_small * (EXAMPLE_GROWTH_FACTOR + 1),
"honest state grew from {honest_small} to {honest_large} over an \
{EXAMPLE_GROWTH_FACTOR}x growth in examples — that is faster than linear"
);
let mat_small = MaterializingSampler::from_class_sizes(&narrow_class_sizes())
.state_report()
.total_retained_entries();
let mat_large = MaterializingSampler::from_class_sizes(&wide_class_sizes())
.state_report()
.total_retained_entries();
assert!(
mat_large > mat_small * EXAMPLE_GROWTH_FACTOR * 4,
"the materializer grew only {mat_small} -> {mat_large}; it is not behaving \
quadratically and cannot serve as the contrast"
);
}
#[test]
fn the_honest_layout_arrays_are_unchanged_at_ten_times_the_example_count() {
let base = vec![8_u64; WIDE_CLASSES];
let ten_x = vec![80_u64; WIDE_CLASSES];
assert_eq!(
ten_x.iter().sum::<u64>(),
base.iter().sum::<u64>() * 10,
"the two layouts must really differ by 10x or this proves nothing"
);
let small = layout(&base, 64);
let large = layout(&ten_x, 64);
assert_eq!(
small.state_report(),
large.state_report(),
"ten times the examples must not change a single retained entry"
);
check_capacity_invariant(&small, base.iter().sum(), base.len())
.expect("the small layout is bounded");
check_capacity_invariant(&large, ten_x.iter().sum(), ten_x.len())
.expect("the ten-times layout is bounded");
}
#[test]
fn the_adversarial_k_equals_n_layout_retains_o_k_state_not_o_k_squared() {
let sizes = common::all_singleton_layout(32);
assert_eq!(
sizes,
common::contracted_layout("singletons_32"),
"the adversarial layout must be the one the contracted fixture records"
);
let rejected_design_entries =
usize::try_from(common::contracted_negative_capacity("singletons_32"))
.expect("496 fits in a usize");
assert_eq!(rejected_design_entries, (32 * 31) / 2);
let adversarial = layout(&sizes, common::ADVERSARIAL_BUDGET);
let report = check_capacity_invariant(&adversarial, 32, sizes.len())
.expect("the shipped O(K) layout is bounded at K = N");
assert_eq!(
report.negative_weight_entries, 32,
"the negative weight array must be K long, not K(K-1)/2 = {rejected_design_entries}"
);
assert_eq!(report.class_offset_entries, 32);
assert_eq!(report.positive_weight_entries, 32);
assert_eq!(
report.materialized_pairs, 0,
"nothing is materialized at any layout"
);
assert!(
report.negative_weight_entries < rejected_design_entries,
"at K = N the shipped design must retain strictly fewer entries than the rejected \
one, or this case discriminates nothing"
);
assert_eq!(adversarial.budget(), common::ADVERSARIAL_BUDGET);
assert_eq!(
layout(&sizes, 992).state_report(),
report,
"sixty-two times the budget must not change one retained entry"
);
}
#[test]
fn the_materializing_sampler_is_red_at_the_adversarial_layout_too() {
let sizes = common::all_singleton_layout(32);
let materializing = MaterializingSampler::from_class_sizes(&sizes);
let failure = check_capacity_invariant(&materializing, 32, sizes.len())
.expect_err("a materializing sampler must be RED at K = N as well");
assert!(
failure.contains("materialized_pairs=496"),
"the failure does not report the 496 materialized pairs: {failure}"
);
}
#[test]
fn honest_state_is_linear_in_the_class_count_across_three_all_singleton_layouts() {
let mut totals = Vec::new();
for k in [8_usize, 32, 128] {
let sizes = common::all_singleton_layout(k);
let subject = layout(&sizes, common::ADVERSARIAL_BUDGET);
let report = check_capacity_invariant(&subject, k as u64, k)
.unwrap_or_else(|e| panic!("K = {k} must be bounded: {e}"));
assert_eq!(subject.budget(), common::ADVERSARIAL_BUDGET);
totals.push(report.total_retained_entries());
}
assert_eq!(totals, vec![24, 96, 384]);
assert_eq!(totals[1], totals[0] * 4, "4x in K must be 4x in state");
assert_eq!(totals[2], totals[1] * 4, "and again");
}
#[test]
fn falsify_cpp_007_pairs_at_n_512_singletons_stays_bounded() {
const N: usize = 512;
const BUDGET: u64 = 64;
const EXPECTED_NEGATIVE_CAPACITY: u64 = (N as u64) * (N as u64 - 1) / 2;
assert_eq!(
EXPECTED_NEGATIVE_CAPACITY, 130_816,
"the contract's C(512,2) literal"
);
let sizes = common::all_singleton_layout(N);
let subject = layout(&sizes, BUDGET);
let report = check_capacity_invariant(&subject, N as u64, N)
.unwrap_or_else(|e| panic!("K = N = {N} must be bounded: {e}"));
assert_eq!(subject.budget(), BUDGET, "the budget is FIXED, not derived");
assert_eq!(
subject.positive_capacity(),
0,
"no singleton class can furnish a positive pair"
);
assert_eq!(
subject.negative_capacity(),
EXPECTED_NEGATIVE_CAPACITY,
"negative_capacity must be C(512,2)"
);
assert_eq!(
subject.emitted_kinds(),
EmittedKinds::NegativesOnly,
"positives are impossible at this layout"
);
let retained = report.total_retained_entries();
assert_eq!(
retained, 1536,
"K = 512 must retain 4x the K = 128 total (384), not 16x"
);
assert!(
(retained as u64) < EXPECTED_NEGATIVE_CAPACITY / 10,
"retained {retained} is not comfortably below the {EXPECTED_NEGATIVE_CAPACITY} \
entries the rejected class-pair design would need"
);
let drawn: Vec<_> = (0..BUDGET)
.map(|ordinal| {
subject
.raw_pair_at(ordinal)
.unwrap_or_else(|e| panic!("ordinal {ordinal} must draw at K = N: {e}"))
})
.collect();
assert_eq!(drawn.len(), BUDGET as usize);
assert!(
drawn.iter().all(|p| p.kind == PairKind::Negative),
"every emitted pair at an all-singleton layout must be a negative"
);
assert!(
drawn
.iter()
.all(|p| p.first.class_index != p.second.class_index),
"a negative pair must span two classes"
);
}
#[test]
fn draining_the_whole_stream_changes_no_retained_entry() {
let selection = common::synthetic_selection(WIDE_CLASSES, 20, SEED, NARROW_SHOTS);
let cfg = PairConfig {
budget: Some(256),
..PairConfig::new(SEED)
};
let sampler = PairSampler::new(&selection, &cfg).expect("24 examples support 256 pairs");
let before = sampler.state_report();
let drained = sampler
.iter_from(0)
.expect("offset 0 is within the budget")
.count();
assert_eq!(drained, 256, "the stream must actually be drained");
assert_eq!(
sampler.state_report(),
before,
"emitting 256 pairs must not change one retained entry"
);
}
#[test]
fn the_capacity_gate_is_one_call_for_both_implementations() {
let path =
std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/negative_materializing.rs");
let text = std::fs::read_to_string(&path).expect("this file is readable");
let call = format!("{}{}", "check_capacity_", "invariant(&");
let hits = text
.lines()
.filter(|line| line.split("//").next().unwrap_or("").contains(&call))
.count();
assert!(
hits >= 6,
"expected every capacity assertion — honest and materializing alike — to go \
through the SAME helper; found {hits} call sites"
);
for needle in [
format!("{}{}", "memory_", "used"),
format!("{}{}", "retained_", "bytes"),
format!("{}{}", "bytes_", "allocated"),
] {
assert!(
!text.contains(&needle),
"`{needle}` — a self-reported size — has appeared in this file; the gate must \
stay structural"
);
}
}