sublinear_solver/temporal_nexus/core/
identity.rs1use std::collections::{HashMap, VecDeque};
8use super::{TemporalResult, TemporalError, TscTimestamp};
9
10#[derive(Debug, Clone, Default)]
12pub struct ContinuityMetrics {
13 pub continuity_score: f64,
14 pub identity_stability: f64,
15 pub continuity_breaks: u64,
16 pub average_gap_duration_ns: f64,
17 pub max_gap_duration_ns: u64,
18 pub identity_coherence: f64,
19 pub temporal_consistency: f64,
20 pub preservation_efficiency: f64,
21}
22
23#[derive(Debug, Clone)]
25struct IdentitySnapshot {
26 timestamp: TscTimestamp,
27 state_hash: u64,
28 feature_vector: Vec<f64>,
29 coherence_score: f64,
30 stability_metric: f64,
31 memory_fingerprint: Vec<u8>,
32}
33
34impl IdentitySnapshot {
35 fn new(timestamp: TscTimestamp, state: &[u8]) -> Self {
37 let feature_vector = Self::extract_features(state);
38 let state_hash = Self::compute_hash(state);
39 let coherence_score = Self::calculate_coherence(&feature_vector);
40
41 Self {
42 timestamp,
43 state_hash,
44 feature_vector,
45 coherence_score,
46 stability_metric: 1.0, memory_fingerprint: state.to_vec(),
48 }
49 }
50
51 fn extract_features(state: &[u8]) -> Vec<f64> {
53 if state.is_empty() {
54 return vec![0.0; 16]; }
56
57 let mut features = Vec::with_capacity(16);
58
59 let mean = state.iter().map(|&x| x as f64).sum::<f64>() / state.len() as f64;
61 features.push(mean);
62
63 let variance = state.iter()
64 .map(|&x| (x as f64 - mean).powi(2))
65 .sum::<f64>() / state.len() as f64;
66 features.push(variance.sqrt());
67
68 let mut byte_counts = [0u32; 256];
70 for &byte in state {
71 byte_counts[byte as usize] += 1;
72 }
73
74 let entropy = byte_counts.iter()
75 .filter(|&&count| count > 0)
76 .map(|&count| {
77 let p = count as f64 / state.len() as f64;
78 -p * p.ln()
79 })
80 .sum::<f64>();
81 features.push(entropy);
82
83 for i in 0..8 {
85 let freq_component = state.iter()
86 .enumerate()
87 .map(|(j, &x)| {
88 let phase = 2.0 * std::f64::consts::PI * (i + 1) as f64 * j as f64 / state.len() as f64;
89 x as f64 * phase.cos()
90 })
91 .sum::<f64>();
92 features.push(freq_component / state.len() as f64);
93 }
94
95 let complexity = Self::estimate_complexity(state);
97 features.push(complexity);
98
99 let pattern_density = Self::calculate_pattern_density(state);
101 features.push(pattern_density);
102
103 let autocorr = Self::calculate_autocorrelation(state, 1);
105 features.push(autocorr);
106
107 let trend = Self::calculate_trend(state);
109 features.push(trend);
110
111 for feature in &mut features {
113 *feature = feature.tanh(); }
115
116 features
117 }
118
119 fn compute_hash(state: &[u8]) -> u64 {
121 use std::collections::hash_map::DefaultHasher;
122 use std::hash::{Hash, Hasher};
123
124 let mut hasher = DefaultHasher::new();
125 state.hash(&mut hasher);
126 hasher.finish()
127 }
128
129 fn calculate_coherence(features: &[f64]) -> f64 {
131 if features.is_empty() {
132 return 0.0;
133 }
134
135 let mean = features.iter().sum::<f64>() / features.len() as f64;
137 let variance = features.iter()
138 .map(|x| (x - mean).powi(2))
139 .sum::<f64>() / features.len() as f64;
140
141 (-variance).exp().min(1.0)
143 }
144
145 fn calculate_similarity(&self, other: &IdentitySnapshot) -> f64 {
158 if self.feature_vector.len() != other.feature_vector.len() || self.feature_vector.is_empty() {
159 return 0.0;
160 }
161
162 let dot_product: f64 = self.feature_vector.iter()
163 .zip(other.feature_vector.iter())
164 .map(|(a, b)| a * b)
165 .sum();
166 let magnitude_self: f64 = self.feature_vector.iter().map(|x| x * x).sum::<f64>().sqrt();
167 let magnitude_other: f64 = other.feature_vector.iter().map(|x| x * x).sum::<f64>().sqrt();
168
169 let cosine = if magnitude_self > 0.0 && magnitude_other > 0.0 {
170 dot_product / (magnitude_self * magnitude_other)
171 } else {
172 0.0
173 };
174
175 let mut mean_l1 = 0.0;
183 let mut max_diff: f64 = 0.0;
184 for (a, b) in self.feature_vector.iter().zip(other.feature_vector.iter()) {
185 let d = (a - b).abs();
186 mean_l1 += d;
187 if d > max_diff {
188 max_diff = d;
189 }
190 }
191 mean_l1 /= self.feature_vector.len() as f64;
192 let l1_similarity = (1.0 - mean_l1 / 2.0).max(0.0);
193 let chebyshev_similarity = (1.0 - max_diff / 2.0).max(0.0);
195
196 0.3 * cosine + 0.3 * l1_similarity + 0.4 * chebyshev_similarity
201 }
202
203 fn estimate_complexity(data: &[u8]) -> f64 {
206 if data.len() < 2 {
207 return 0.0;
208 }
209
210 let mut runs = 0;
212 let mut current_byte = data[0];
213
214 for &byte in &data[1..] {
215 if byte != current_byte {
216 runs += 1;
217 current_byte = byte;
218 }
219 }
220
221 runs as f64 / data.len() as f64
222 }
223
224 fn calculate_pattern_density(data: &[u8]) -> f64 {
225 if data.len() < 4 {
226 return 0.0;
227 }
228
229 let mut patterns = HashMap::new();
230
231 for window in data.windows(2) {
233 *patterns.entry((window[0], window[1])).or_insert(0) += 1;
234 }
235
236 patterns.len() as f64 / (data.len() - 1) as f64
237 }
238
239 fn calculate_autocorrelation(data: &[u8], lag: usize) -> f64 {
240 if data.len() <= lag {
241 return 0.0;
242 }
243
244 let mean = data.iter().map(|&x| x as f64).sum::<f64>() / data.len() as f64;
245
246 let numerator: f64 = data.iter()
247 .take(data.len() - lag)
248 .zip(data.iter().skip(lag))
249 .map(|(&x, &y)| (x as f64 - mean) * (y as f64 - mean))
250 .sum();
251
252 let denominator: f64 = data.iter()
253 .map(|&x| (x as f64 - mean).powi(2))
254 .sum();
255
256 if denominator > 0.0 {
257 numerator / denominator
258 } else {
259 0.0
260 }
261 }
262
263 fn calculate_trend(data: &[u8]) -> f64 {
264 if data.len() < 2 {
265 return 0.0;
266 }
267
268 let n = data.len() as f64;
269 let sum_x = (0..data.len()).sum::<usize>() as f64;
270 let sum_y = data.iter().map(|&x| x as f64).sum::<f64>();
271 let sum_xy = data.iter()
272 .enumerate()
273 .map(|(i, &y)| i as f64 * y as f64)
274 .sum::<f64>();
275 let sum_x2 = (0..data.len())
276 .map(|i| (i as f64).powi(2))
277 .sum::<f64>();
278
279 let denominator = n * sum_x2 - sum_x * sum_x;
280 if denominator > 0.0 {
281 (n * sum_xy - sum_x * sum_y) / denominator
282 } else {
283 0.0
284 }
285 }
286}
287
288pub struct IdentityContinuityTracker {
290 snapshots: VecDeque<IdentitySnapshot>,
291 metrics: ContinuityMetrics,
292 max_snapshots: usize,
293 continuity_threshold: f64,
294 gap_tolerance_ns: u64,
295 identity_baseline: Option<IdentitySnapshot>,
296 last_validation_time: Option<TscTimestamp>,
297}
298
299impl IdentityContinuityTracker {
300 pub fn new() -> Self {
302 Self {
303 snapshots: VecDeque::new(),
304 metrics: ContinuityMetrics::default(),
305 max_snapshots: 1000,
306 continuity_threshold: 0.7, gap_tolerance_ns: 1_000_000, identity_baseline: None,
309 last_validation_time: None,
310 }
311 }
312
313 pub fn track_continuity(&mut self, timestamp: TscTimestamp, state: &[u8]) -> TemporalResult<()> {
315 let snapshot = IdentitySnapshot::new(timestamp, state);
316
317 if self.identity_baseline.is_none() {
319 self.identity_baseline = Some(snapshot.clone());
320 }
321
322 let continuity_break_info = if let Some(prev_snapshot) = self.snapshots.back() {
324 Some((snapshot.clone(), prev_snapshot.clone()))
325 } else {
326 None
327 };
328
329 if let Some((current, previous)) = continuity_break_info {
330 self.check_continuity_break(¤t, &previous)?;
331 }
332
333 self.update_stability_metrics(&snapshot);
335
336 self.store_snapshot(snapshot);
338
339 self.update_metrics();
341
342 self.last_validation_time = Some(timestamp);
343
344 Ok(())
345 }
346
347 pub fn validate_continuity(&self) -> TemporalResult<()> {
355 if self.snapshots.len() < 2 {
356 return Ok(());
357 }
358 if self.metrics.continuity_score < self.continuity_threshold {
359 return Err(TemporalError::IdentityContinuityBreak {
360 gap_ns: self.metrics.max_gap_duration_ns,
361 });
362 }
363
364 Ok(())
365 }
366
367 pub fn get_metrics(&self) -> TemporalResult<ContinuityMetrics> {
369 Ok(self.metrics.clone())
370 }
371
372 pub fn get_identity_stability(&self) -> f64 {
374 self.metrics.identity_stability
375 }
376
377 pub fn get_continuity_score(&self) -> f64 {
379 self.metrics.continuity_score
380 }
381
382 pub fn reset(&mut self) {
384 self.snapshots.clear();
385 self.metrics = ContinuityMetrics::default();
386 self.identity_baseline = None;
387 self.last_validation_time = None;
388 }
389
390 pub fn set_continuity_threshold(&mut self, threshold: f64) {
392 self.continuity_threshold = threshold.clamp(0.0, 1.0);
393 }
394
395 pub fn get_identity_trajectory(&self, window_size: usize) -> Vec<f64> {
397 self.snapshots.iter()
398 .rev()
399 .take(window_size)
400 .map(|s| s.coherence_score)
401 .collect()
402 }
403
404 pub fn calculate_identity_drift(&self) -> f64 {
406 if let Some(baseline) = &self.identity_baseline {
407 if let Some(current) = self.snapshots.back() {
408 return 1.0 - baseline.calculate_similarity(current);
409 }
410 }
411 0.0
412 }
413
414 fn check_continuity_break(
417 &mut self,
418 current: &IdentitySnapshot,
419 previous: &IdentitySnapshot,
420 ) -> TemporalResult<()> {
421 let gap_ns = current.timestamp.nanos_since(previous.timestamp, 3_000_000_000);
423 if gap_ns > self.gap_tolerance_ns {
424 self.metrics.continuity_breaks += 1;
425 self.metrics.max_gap_duration_ns = self.metrics.max_gap_duration_ns.max(gap_ns);
426 }
427
428 let similarity = current.calculate_similarity(previous);
430 if similarity < self.continuity_threshold {
431 self.metrics.continuity_breaks += 1;
432 }
433
434 Ok(())
435 }
436
437 fn update_stability_metrics(&mut self, snapshot: &IdentitySnapshot) {
438 if self.snapshots.len() < 2 {
439 return;
440 }
441
442 let recent_snapshots: Vec<_> = self.snapshots.iter().rev().take(10).collect();
444
445 if recent_snapshots.len() >= 2 {
446 let mut similarities = Vec::new();
447
448 for i in 0..recent_snapshots.len() - 1 {
449 let sim = recent_snapshots[i].calculate_similarity(recent_snapshots[i + 1]);
450 similarities.push(sim);
451 }
452
453 let current_sim = snapshot.calculate_similarity(recent_snapshots[0]);
455 similarities.push(current_sim);
456
457 let avg_similarity = similarities.iter().sum::<f64>() / similarities.len() as f64;
459
460 let alpha = 0.1;
462 self.metrics.identity_stability = (1.0 - alpha) * self.metrics.identity_stability + alpha * avg_similarity;
463 }
464 }
465
466 fn store_snapshot(&mut self, snapshot: IdentitySnapshot) {
467 self.snapshots.push_back(snapshot);
468
469 while self.snapshots.len() > self.max_snapshots {
471 self.snapshots.pop_front();
472 }
473 }
474
475 fn update_metrics(&mut self) {
476 if self.snapshots.len() < 2 {
477 return;
478 }
479
480 let mut total_similarity = 0.0;
482 let mut similarity_count = 0;
483
484 for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
485 let sim = window[1].calculate_similarity(window[0]);
486 total_similarity += sim;
487 similarity_count += 1;
488 }
489
490 if similarity_count > 0 {
491 self.metrics.continuity_score = total_similarity / similarity_count as f64;
492 }
493
494 let coherence_scores: Vec<f64> = self.snapshots.iter()
496 .map(|s| s.coherence_score)
497 .collect();
498
499 if !coherence_scores.is_empty() {
500 self.metrics.identity_coherence = coherence_scores.iter().sum::<f64>() / coherence_scores.len() as f64;
501 }
502
503 self.calculate_temporal_consistency();
505
506 self.calculate_preservation_efficiency();
508
509 self.update_gap_metrics();
511 }
512
513 fn calculate_temporal_consistency(&mut self) {
514 if self.snapshots.len() < 3 {
515 return;
516 }
517
518 let mut consistency_scores = Vec::new();
520
521 for i in 2..self.snapshots.len() {
522 let s1 = &self.snapshots[i - 2];
523 let s2 = &self.snapshots[i - 1];
524 let s3 = &self.snapshots[i];
525
526 let vel1: Vec<f64> = s2.feature_vector.iter()
528 .zip(s1.feature_vector.iter())
529 .map(|(a, b)| a - b)
530 .collect();
531
532 let vel2: Vec<f64> = s3.feature_vector.iter()
533 .zip(s2.feature_vector.iter())
534 .map(|(a, b)| a - b)
535 .collect();
536
537 let dot_product: f64 = vel1.iter().zip(vel2.iter()).map(|(a, b)| a * b).sum();
539 let mag1: f64 = vel1.iter().map(|x| x * x).sum::<f64>().sqrt();
540 let mag2: f64 = vel2.iter().map(|x| x * x).sum::<f64>().sqrt();
541
542 if mag1 > 0.0 && mag2 > 0.0 {
543 consistency_scores.push(dot_product / (mag1 * mag2));
544 }
545 }
546
547 if !consistency_scores.is_empty() {
548 self.metrics.temporal_consistency = consistency_scores.iter().sum::<f64>() / consistency_scores.len() as f64;
549 }
550 }
551
552 fn calculate_preservation_efficiency(&mut self) {
553 if let Some(baseline) = &self.identity_baseline {
554 if let Some(current) = self.snapshots.back() {
555 let similarity_to_baseline = current.calculate_similarity(baseline);
557 let time_factor = 1.0 / (1.0 + self.snapshots.len() as f64 / 1000.0); self.metrics.preservation_efficiency = similarity_to_baseline * time_factor;
560 }
561 }
562 }
563
564 fn update_gap_metrics(&mut self) {
565 if self.snapshots.len() < 2 {
566 return;
567 }
568
569 let mut gaps = Vec::new();
570
571 for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
572 let gap_ns = window[1].timestamp.nanos_since(window[0].timestamp, 3_000_000_000);
573 gaps.push(gap_ns);
574 }
575
576 if !gaps.is_empty() {
577 self.metrics.average_gap_duration_ns = gaps.iter().sum::<u64>() as f64 / gaps.len() as f64;
578 self.metrics.max_gap_duration_ns = *gaps.iter().max().unwrap_or(&0);
579 }
580 }
581}
582
583impl Default for IdentityContinuityTracker {
584 fn default() -> Self {
585 Self::new()
586 }
587}
588
589#[cfg(test)]
590mod tests {
591 use super::*;
592
593 #[test]
594 fn test_identity_snapshot_creation() {
595 let timestamp = TscTimestamp::now();
596 let state = vec![1, 2, 3, 4, 5];
597
598 let snapshot = IdentitySnapshot::new(timestamp, &state);
599 assert_eq!(snapshot.timestamp, timestamp);
600 assert!(!snapshot.feature_vector.is_empty());
601 assert!(snapshot.coherence_score >= 0.0 && snapshot.coherence_score <= 1.0);
602 }
603
604 #[test]
605 fn test_feature_extraction() {
606 let state = vec![1, 2, 3, 4, 5, 4, 3, 2, 1];
607 let features = IdentitySnapshot::extract_features(&state);
608
609 assert!(!features.is_empty());
610 for &feature in &features {
612 assert!(feature >= -1.0 && feature <= 1.0);
613 }
614 }
615
616 #[test]
617 fn test_similarity_calculation() {
618 let timestamp = TscTimestamp::now();
619 let state1 = vec![1, 2, 3, 4, 5];
620 let state2 = vec![1, 2, 3, 4, 5]; let state3 = vec![5, 4, 3, 2, 1]; let snapshot1 = IdentitySnapshot::new(timestamp, &state1);
624 let snapshot2 = IdentitySnapshot::new(timestamp, &state2);
625 let snapshot3 = IdentitySnapshot::new(timestamp, &state3);
626
627 let sim12 = snapshot1.calculate_similarity(&snapshot2);
628 let sim13 = snapshot1.calculate_similarity(&snapshot3);
629
630 assert!(sim12 > sim13); assert!(sim12 >= 0.0 && sim12 <= 1.0);
632 assert!(sim13 >= 0.0 && sim13 <= 1.0);
633 }
634
635 #[test]
636 fn test_continuity_tracker() {
637 let mut tracker = IdentityContinuityTracker::new();
638 let timestamp = TscTimestamp::now();
639 let state = vec![1, 2, 3, 4, 5];
640
641 tracker.track_continuity(timestamp, &state).unwrap();
642 assert_eq!(tracker.snapshots.len(), 1);
643
644 let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
646 let state2 = vec![1, 2, 3, 4, 6]; tracker.track_continuity(timestamp2, &state2).unwrap();
649 assert_eq!(tracker.snapshots.len(), 2);
650
651 let metrics = tracker.get_metrics().unwrap();
652 assert!(metrics.continuity_score > 0.0);
653 }
654
655 #[test]
656 fn test_continuity_break_detection() {
657 let mut tracker = IdentityContinuityTracker::new();
658 tracker.set_continuity_threshold(0.9); let timestamp = TscTimestamp::now();
661 let state1 = vec![1, 2, 3, 4, 5];
662 let state2 = vec![10, 20, 30, 40, 50]; tracker.track_continuity(timestamp, &state1).unwrap();
665
666 let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
667 tracker.track_continuity(timestamp2, &state2).unwrap();
668
669 assert!(tracker.metrics.continuity_breaks > 0);
671 }
672
673 #[test]
674 fn test_identity_drift_calculation() {
675 let mut tracker = IdentityContinuityTracker::new();
676 let timestamp = TscTimestamp::now();
677
678 let baseline_state = vec![1, 2, 3, 4, 5];
680 tracker.track_continuity(timestamp, &baseline_state).unwrap();
681
682 for i in 1..=10 {
684 let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
685 let drifted_state = vec![1 + i as u8, 2, 3, 4, 5];
686 tracker.track_continuity(timestamp_i, &drifted_state).unwrap();
687 }
688
689 let drift = tracker.calculate_identity_drift();
690 assert!(drift > 0.0); assert!(drift <= 1.0); }
693
694 #[test]
695 fn test_stability_metrics() {
696 let mut tracker = IdentityContinuityTracker::new();
697 let timestamp = TscTimestamp::now();
698
699 for i in 0..10 {
701 let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
702 let stable_state = vec![1, 2, 3, 4, 5]; tracker.track_continuity(timestamp_i, &stable_state).unwrap();
704 }
705
706 assert!(tracker.get_identity_stability() > 0.5); }
708}