exo-exotic 0.1.1

Exotic cognitive experiments: Strange Loops, Dreams, Free Energy, Morphogenesis, Collective Consciousness, Temporal Qualia, Multiple Selves, Cognitive Thermodynamics, Emergence Detection, Cognitive Black Holes
Documentation
//! Experiment 05: Memory-Mapped Neural Fields
//!
//! Research frontier: Zero-copy pattern storage via memory-mapped RVF containers.
//! Neural fields are encoded as continuous functions rather than discrete vectors,
//! allowing sub-millisecond retrieval via direct memory access.
//!
//! ADR-029: ruvector-verified + RVF mmap + ruvector-temporal-tensor provide
//! the implementation. This experiment documents the integration contract and
//! measures retrieval performance vs copy-based storage.

/// A neural field: continuous function over a domain, discretized to a grid.
#[derive(Debug, Clone)]
pub struct NeuralField {
    pub id: u64,
    /// Field values on a regular grid (flattened)
    pub values: Vec<f32>,
    /// Grid dimensions
    pub dims: Vec<usize>,
    /// Field bandwidth (controls smoothness)
    pub bandwidth: f32,
}

impl NeuralField {
    pub fn new(id: u64, dims: Vec<usize>, bandwidth: f32) -> Self {
        let total: usize = dims.iter().product();
        Self {
            id,
            values: vec![0.0f32; total],
            dims,
            bandwidth,
        }
    }

    /// Encode a pattern as a neural field (Gaussian RBF superposition)
    pub fn encode_pattern(id: u64, pattern: &[f32], bandwidth: f32) -> Self {
        let n = pattern.len();
        let mut values = vec![0.0f32; n];
        // Each point in the field gets a Gaussian contribution from each pattern element
        for (i, &center) in pattern.iter().enumerate() {
            let _ = i;
            for j in 0..n {
                let t = j as f32 / n as f32;
                let exponent = -(t - center).powi(2) / (2.0 * bandwidth * bandwidth);
                values[j] += exponent.exp();
            }
        }
        // Normalize
        let max = values.iter().cloned().fold(0.0f32, f32::max).max(1e-6);
        for v in values.iter_mut() {
            *v /= max;
        }
        Self {
            id,
            values,
            dims: vec![n],
            bandwidth,
        }
    }

    /// Query the field at position t ∈ [0,1]
    pub fn query(&self, t: f32) -> f32 {
        let n = self.values.len();
        let idx = (t * (n - 1) as f32).clamp(0.0, (n - 1) as f32);
        let lo = idx.floor() as usize;
        let hi = (lo + 1).min(n - 1);
        let frac = idx - lo as f32;
        self.values[lo] * (1.0 - frac) + self.values[hi] * frac
    }

    /// Compute overlap integral ∫ f₁(t)·f₂(t)dt (inner product of fields)
    pub fn overlap(&self, other: &NeuralField) -> f32 {
        let n = self.values.len().min(other.values.len());
        self.values
            .iter()
            .zip(other.values.iter())
            .take(n)
            .map(|(a, b)| a * b)
            .sum::<f32>()
            / n as f32
    }
}

/// Memory-mapped field store (simulated — production uses RVF mmap)
pub struct FieldStore {
    fields: Vec<NeuralField>,
    /// Simulated mmap access time (production: <1µs for read, 0 copy)
    pub simulated_mmap_us: u64,
}

pub struct FieldQueryResult {
    pub id: u64,
    pub overlap: f32,
    pub access_us: u64,
}

impl FieldStore {
    pub fn new() -> Self {
        Self {
            fields: Vec::new(),
            simulated_mmap_us: 1,
        }
    }

    pub fn store(&mut self, field: NeuralField) {
        self.fields.push(field);
    }

    pub fn query_top_k(&self, query: &NeuralField, k: usize) -> Vec<FieldQueryResult> {
        let t0 = std::time::Instant::now();
        let mut results: Vec<FieldQueryResult> = self
            .fields
            .iter()
            .map(|f| FieldQueryResult {
                id: f.id,
                overlap: f.overlap(query),
                access_us: self.simulated_mmap_us,
            })
            .collect();
        results.sort_unstable_by(|a, b| b.overlap.partial_cmp(&a.overlap).unwrap());
        results.truncate(k);
        let elapsed = t0.elapsed().as_micros() as u64;
        for r in results.iter_mut() {
            r.access_us = elapsed;
        }
        results
    }

    pub fn len(&self) -> usize {
        self.fields.len()
    }
}

impl Default for FieldStore {
    fn default() -> Self {
        Self::new()
    }
}

pub struct MemoryMappedFieldsExperiment {
    store: FieldStore,
    pub n_patterns: usize,
    pub pattern_dim: usize,
    pub bandwidth: f32,
}

pub struct MmapFieldResult {
    pub retrieval_accuracy: f64,
    pub avg_overlap_correct: f64,
    pub avg_overlap_wrong: f64,
    pub avg_latency_us: u64,
    pub n_fields_stored: usize,
}

impl MemoryMappedFieldsExperiment {
    pub fn new() -> Self {
        Self {
            store: FieldStore::new(),
            n_patterns: 20,
            pattern_dim: 128,
            bandwidth: 0.1,
        }
    }

    pub fn run(&mut self) -> MmapFieldResult {
        // Store patterns as neural fields
        let mut patterns = Vec::new();
        for i in 0..self.n_patterns {
            let pattern: Vec<f32> = (0..self.pattern_dim)
                .map(|j| ((i * j) as f32 / self.pattern_dim as f32).sin().abs())
                .collect();
            let field = NeuralField::encode_pattern(i as u64, &pattern, self.bandwidth);
            patterns.push(pattern);
            self.store.store(field);
        }

        // Query each pattern with 5% noise
        let mut correct = 0usize;
        let mut overlap_sum_correct = 0.0f64;
        let mut overlap_sum_wrong = 0.0f64;
        let mut total_latency = 0u64;

        for (i, pattern) in patterns.iter().enumerate() {
            let noisy: Vec<f32> = pattern.iter().map(|&v| v + (v * 0.05)).collect();
            let query = NeuralField::encode_pattern(999, &noisy, self.bandwidth);
            let results = self.store.query_top_k(&query, 3);
            if let Some(top) = results.first() {
                total_latency += top.access_us;
                if top.id == i as u64 {
                    correct += 1;
                    overlap_sum_correct += top.overlap as f64;
                } else {
                    overlap_sum_wrong += top.overlap as f64;
                }
            }
        }

        let n = self.n_patterns.max(1) as f64;
        MmapFieldResult {
            retrieval_accuracy: correct as f64 / n,
            avg_overlap_correct: overlap_sum_correct / n,
            avg_overlap_wrong: overlap_sum_wrong / n,
            avg_latency_us: total_latency / self.n_patterns.max(1) as u64,
            n_fields_stored: self.store.len(),
        }
    }
}

impl Default for MemoryMappedFieldsExperiment {
    fn default() -> Self {
        Self::new()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_neural_field_encode_decode() {
        let pattern = vec![0.0f32, 0.5, 1.0, 0.5, 0.0];
        let field = NeuralField::encode_pattern(0, &pattern, 0.2);
        assert_eq!(field.values.len(), 5);
        // Field values should be normalized
        assert!(field.values.iter().all(|&v| v >= 0.0 && v <= 1.0));
    }

    #[test]
    fn test_field_self_overlap() {
        let pattern = vec![0.5f32; 64];
        let field = NeuralField::encode_pattern(0, &pattern, 0.1);
        let self_overlap = field.overlap(&field);
        assert!(self_overlap > 0.0, "Field self-overlap should be positive");
    }

    #[test]
    fn test_mmap_experiment_runs() {
        let mut exp = MemoryMappedFieldsExperiment::new();
        exp.n_patterns = 5;
        exp.pattern_dim = 32;
        let result = exp.run();
        assert_eq!(result.n_fields_stored, 5);
        assert!(result.retrieval_accuracy >= 0.0 && result.retrieval_accuracy <= 1.0);
    }

    #[test]
    fn test_neural_field_query_interpolation() {
        let mut field = NeuralField::new(0, vec![10], 0.1);
        field.values = vec![0.0, 0.25, 0.5, 0.75, 1.0, 0.75, 0.5, 0.25, 0.0, 0.0];
        // Midpoint should be interpolated
        let mid = field.query(0.5);
        assert!(mid > 0.0 && mid <= 1.0);
    }
}