Merge commit 'd803bfe2b1fe7f5e219e50ac20d6801a0a58ac75' as 'vendor/ruvector'
This commit is contained in:
221
vendor/ruvector/examples/ultra-low-latency-sim/src/hierarchical.rs
vendored
Normal file
221
vendor/ruvector/examples/ultra-low-latency-sim/src/hierarchical.rs
vendored
Normal file
@@ -0,0 +1,221 @@
|
||||
//! Hierarchical Meta-Simulation
|
||||
//!
|
||||
//! Each level of hierarchy compresses BATCH_SIZE simulations into one result.
|
||||
//! Level k represents BATCH_SIZE^k simulations per output value.
|
||||
|
||||
/// Default batch size for hierarchical compression
|
||||
pub const DEFAULT_BATCH_SIZE: usize = 64;
|
||||
|
||||
/// Hierarchical simulation compressor
|
||||
/// Each output represents BATCH_SIZE^level input simulations
|
||||
#[repr(align(64))]
|
||||
pub struct HierarchicalCompressor {
|
||||
/// Current results (each represents many sub-simulations)
|
||||
results: Vec<f32>,
|
||||
/// Hierarchy level
|
||||
level: u32,
|
||||
/// Batch size for compression
|
||||
batch_size: usize,
|
||||
}
|
||||
|
||||
impl HierarchicalCompressor {
|
||||
/// Create new compressor at given hierarchy level
|
||||
pub fn new(output_size: usize, level: u32, batch_size: usize) -> Self {
|
||||
Self {
|
||||
results: vec![0.0; output_size],
|
||||
level,
|
||||
batch_size,
|
||||
}
|
||||
}
|
||||
|
||||
/// Simulations represented by each result value
|
||||
pub fn sims_per_result(&self) -> u64 {
|
||||
(self.batch_size as u64).pow(self.level)
|
||||
}
|
||||
|
||||
/// Total simulations represented by all results
|
||||
pub fn total_simulations(&self) -> u64 {
|
||||
self.results.len() as u64 * self.sims_per_result()
|
||||
}
|
||||
|
||||
/// Compress batch of inputs into meta-results
|
||||
/// Aggregates BATCH_SIZE values per output
|
||||
#[inline]
|
||||
pub fn compress(&mut self, inputs: &[f32]) {
|
||||
let out_count = inputs.len() / self.batch_size;
|
||||
|
||||
for (i, result) in self.results.iter_mut().take(out_count).enumerate() {
|
||||
let start = i * self.batch_size;
|
||||
let end = start + self.batch_size;
|
||||
|
||||
// Sum and average (vectorizable loop)
|
||||
let sum: f32 = inputs[start..end].iter().sum();
|
||||
*result = sum / self.batch_size as f32;
|
||||
}
|
||||
}
|
||||
|
||||
/// Get compressed results
|
||||
pub fn results(&self) -> &[f32] {
|
||||
&self.results
|
||||
}
|
||||
|
||||
/// Hierarchy level
|
||||
pub fn level(&self) -> u32 {
|
||||
self.level
|
||||
}
|
||||
}
|
||||
|
||||
/// Multi-level hierarchical simulation pipeline
|
||||
/// Compresses through multiple levels for exponential multiplier
|
||||
pub struct HierarchicalPipeline {
|
||||
/// Compressors for each level
|
||||
levels: Vec<HierarchicalCompressor>,
|
||||
/// Batch size
|
||||
batch_size: usize,
|
||||
}
|
||||
|
||||
impl HierarchicalPipeline {
|
||||
/// Create pipeline with given depth
|
||||
pub fn new(base_size: usize, depth: usize, batch_size: usize) -> Self {
|
||||
let mut levels = Vec::with_capacity(depth);
|
||||
let mut size = base_size;
|
||||
|
||||
for level in 0..depth as u32 {
|
||||
size /= batch_size;
|
||||
if size == 0 { size = 1; }
|
||||
levels.push(HierarchicalCompressor::new(size, level + 1, batch_size));
|
||||
}
|
||||
|
||||
Self { levels, batch_size }
|
||||
}
|
||||
|
||||
/// Run full compression pipeline
|
||||
pub fn compress_all(&mut self, base_inputs: &[f32]) {
|
||||
if self.levels.is_empty() { return; }
|
||||
|
||||
// First level compresses base inputs
|
||||
self.levels[0].compress(base_inputs);
|
||||
|
||||
// Each subsequent level compresses previous level's output
|
||||
for i in 1..self.levels.len() {
|
||||
let prev_results = self.levels[i - 1].results.clone();
|
||||
self.levels[i].compress(&prev_results);
|
||||
}
|
||||
}
|
||||
|
||||
/// Total simulations at final level
|
||||
pub fn final_simulations(&self) -> u64 {
|
||||
self.levels.last()
|
||||
.map(|l| l.total_simulations())
|
||||
.unwrap_or(0)
|
||||
}
|
||||
|
||||
/// Get final results
|
||||
pub fn final_results(&self) -> Option<&[f32]> {
|
||||
self.levels.last().map(|l| l.results())
|
||||
}
|
||||
}
|
||||
|
||||
/// Ensemble aggregator for Monte Carlo with hierarchical batching
|
||||
/// Each "sample" represents many underlying random samples
|
||||
pub struct EnsembleAggregator {
|
||||
/// Running mean estimates
|
||||
means: Vec<f64>,
|
||||
/// Running M2 for Welford's online variance
|
||||
m2: Vec<f64>,
|
||||
/// Sample count (each "sample" = batch_size underlying samples)
|
||||
count: u64,
|
||||
/// Samples per aggregate
|
||||
samples_per_aggregate: u64,
|
||||
}
|
||||
|
||||
impl EnsembleAggregator {
|
||||
/// Create aggregator for n-dimensional output
|
||||
pub fn new(dimensions: usize, samples_per_aggregate: u64) -> Self {
|
||||
Self {
|
||||
means: vec![0.0; dimensions],
|
||||
m2: vec![0.0; dimensions],
|
||||
count: 0,
|
||||
samples_per_aggregate,
|
||||
}
|
||||
}
|
||||
|
||||
/// Add aggregate sample (represents many underlying samples)
|
||||
/// Using Welford's online algorithm for numerical stability
|
||||
#[inline]
|
||||
pub fn add_aggregate(&mut self, values: &[f64]) {
|
||||
self.count += 1;
|
||||
let n = self.count as f64;
|
||||
|
||||
for (i, &x) in values.iter().enumerate() {
|
||||
let delta = x - self.means[i];
|
||||
self.means[i] += delta / n;
|
||||
let delta2 = x - self.means[i];
|
||||
self.m2[i] += delta * delta2;
|
||||
}
|
||||
}
|
||||
|
||||
/// Total underlying samples represented
|
||||
pub fn total_samples(&self) -> u64 {
|
||||
self.count * self.samples_per_aggregate
|
||||
}
|
||||
|
||||
/// Get current mean estimates
|
||||
pub fn means(&self) -> &[f64] {
|
||||
&self.means
|
||||
}
|
||||
|
||||
/// Get sample variance
|
||||
pub fn variance(&self) -> Vec<f64> {
|
||||
if self.count < 2 {
|
||||
return vec![0.0; self.means.len()];
|
||||
}
|
||||
self.m2.iter().map(|m| m / (self.count - 1) as f64).collect()
|
||||
}
|
||||
|
||||
/// Standard error (adjusted for aggregation)
|
||||
pub fn standard_error(&self) -> Vec<f64> {
|
||||
let var = self.variance();
|
||||
let n = self.total_samples() as f64;
|
||||
var.iter().map(|v| (v / n).sqrt()).collect()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_hierarchical_compressor() {
|
||||
let mut comp = HierarchicalCompressor::new(16, 1, 64);
|
||||
let inputs: Vec<f32> = (0..1024).map(|i| i as f32).collect();
|
||||
|
||||
comp.compress(&inputs);
|
||||
|
||||
assert_eq!(comp.results().len(), 16);
|
||||
assert_eq!(comp.sims_per_result(), 64);
|
||||
assert_eq!(comp.total_simulations(), 16 * 64);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_hierarchical_pipeline() {
|
||||
let mut pipeline = HierarchicalPipeline::new(4096, 3, 4);
|
||||
let inputs: Vec<f32> = (0..4096).map(|i| (i as f32).sin()).collect();
|
||||
|
||||
pipeline.compress_all(&inputs);
|
||||
|
||||
assert!(pipeline.final_simulations() > 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_ensemble_aggregator() {
|
||||
let mut agg = EnsembleAggregator::new(2, 1000);
|
||||
|
||||
for i in 0..100 {
|
||||
agg.add_aggregate(&[i as f64, -i as f64]);
|
||||
}
|
||||
|
||||
assert_eq!(agg.total_samples(), 100_000);
|
||||
assert!((agg.means()[0] - 49.5).abs() < 0.1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user