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 {
147 if self.feature_vector.len() != other.feature_vector.len() {
148 return 0.0;
149 }
150
151 let dot_product: f64 = self.feature_vector.iter()
153 .zip(other.feature_vector.iter())
154 .map(|(a, b)| a * b)
155 .sum();
156
157 let magnitude_self: f64 = self.feature_vector.iter()
158 .map(|x| x * x)
159 .sum::<f64>()
160 .sqrt();
161
162 let magnitude_other: f64 = other.feature_vector.iter()
163 .map(|x| x * x)
164 .sum::<f64>()
165 .sqrt();
166
167 if magnitude_self > 0.0 && magnitude_other > 0.0 {
168 dot_product / (magnitude_self * magnitude_other)
169 } else {
170 0.0
171 }
172 }
173
174 fn estimate_complexity(data: &[u8]) -> f64 {
177 if data.len() < 2 {
178 return 0.0;
179 }
180
181 let mut runs = 0;
183 let mut current_byte = data[0];
184
185 for &byte in &data[1..] {
186 if byte != current_byte {
187 runs += 1;
188 current_byte = byte;
189 }
190 }
191
192 runs as f64 / data.len() as f64
193 }
194
195 fn calculate_pattern_density(data: &[u8]) -> f64 {
196 if data.len() < 4 {
197 return 0.0;
198 }
199
200 let mut patterns = HashMap::new();
201
202 for window in data.windows(2) {
204 *patterns.entry((window[0], window[1])).or_insert(0) += 1;
205 }
206
207 patterns.len() as f64 / (data.len() - 1) as f64
208 }
209
210 fn calculate_autocorrelation(data: &[u8], lag: usize) -> f64 {
211 if data.len() <= lag {
212 return 0.0;
213 }
214
215 let mean = data.iter().map(|&x| x as f64).sum::<f64>() / data.len() as f64;
216
217 let numerator: f64 = data.iter()
218 .take(data.len() - lag)
219 .zip(data.iter().skip(lag))
220 .map(|(&x, &y)| (x as f64 - mean) * (y as f64 - mean))
221 .sum();
222
223 let denominator: f64 = data.iter()
224 .map(|&x| (x as f64 - mean).powi(2))
225 .sum();
226
227 if denominator > 0.0 {
228 numerator / denominator
229 } else {
230 0.0
231 }
232 }
233
234 fn calculate_trend(data: &[u8]) -> f64 {
235 if data.len() < 2 {
236 return 0.0;
237 }
238
239 let n = data.len() as f64;
240 let sum_x = (0..data.len()).sum::<usize>() as f64;
241 let sum_y = data.iter().map(|&x| x as f64).sum::<f64>();
242 let sum_xy = data.iter()
243 .enumerate()
244 .map(|(i, &y)| i as f64 * y as f64)
245 .sum::<f64>();
246 let sum_x2 = (0..data.len())
247 .map(|i| (i as f64).powi(2))
248 .sum::<f64>();
249
250 let denominator = n * sum_x2 - sum_x * sum_x;
251 if denominator > 0.0 {
252 (n * sum_xy - sum_x * sum_y) / denominator
253 } else {
254 0.0
255 }
256 }
257}
258
259pub struct IdentityContinuityTracker {
261 snapshots: VecDeque<IdentitySnapshot>,
262 metrics: ContinuityMetrics,
263 max_snapshots: usize,
264 continuity_threshold: f64,
265 gap_tolerance_ns: u64,
266 identity_baseline: Option<IdentitySnapshot>,
267 last_validation_time: Option<TscTimestamp>,
268}
269
270impl IdentityContinuityTracker {
271 pub fn new() -> Self {
273 Self {
274 snapshots: VecDeque::new(),
275 metrics: ContinuityMetrics::default(),
276 max_snapshots: 1000,
277 continuity_threshold: 0.7, gap_tolerance_ns: 1_000_000, identity_baseline: None,
280 last_validation_time: None,
281 }
282 }
283
284 pub fn track_continuity(&mut self, timestamp: TscTimestamp, state: &[u8]) -> TemporalResult<()> {
286 let snapshot = IdentitySnapshot::new(timestamp, state);
287
288 if self.identity_baseline.is_none() {
290 self.identity_baseline = Some(snapshot.clone());
291 }
292
293 let continuity_break_info = if let Some(prev_snapshot) = self.snapshots.back() {
295 Some((snapshot.clone(), prev_snapshot.clone()))
296 } else {
297 None
298 };
299
300 if let Some((current, previous)) = continuity_break_info {
301 self.check_continuity_break(¤t, &previous)?;
302 }
303
304 self.update_stability_metrics(&snapshot);
306
307 self.store_snapshot(snapshot);
309
310 self.update_metrics();
312
313 self.last_validation_time = Some(timestamp);
314
315 Ok(())
316 }
317
318 pub fn validate_continuity(&self) -> TemporalResult<()> {
320 if self.metrics.continuity_score < self.continuity_threshold {
321 return Err(TemporalError::IdentityContinuityBreak {
322 gap_ns: self.metrics.max_gap_duration_ns,
323 });
324 }
325
326 Ok(())
327 }
328
329 pub fn get_metrics(&self) -> TemporalResult<ContinuityMetrics> {
331 Ok(self.metrics.clone())
332 }
333
334 pub fn get_identity_stability(&self) -> f64 {
336 self.metrics.identity_stability
337 }
338
339 pub fn get_continuity_score(&self) -> f64 {
341 self.metrics.continuity_score
342 }
343
344 pub fn reset(&mut self) {
346 self.snapshots.clear();
347 self.metrics = ContinuityMetrics::default();
348 self.identity_baseline = None;
349 self.last_validation_time = None;
350 }
351
352 pub fn set_continuity_threshold(&mut self, threshold: f64) {
354 self.continuity_threshold = threshold.clamp(0.0, 1.0);
355 }
356
357 pub fn get_identity_trajectory(&self, window_size: usize) -> Vec<f64> {
359 self.snapshots.iter()
360 .rev()
361 .take(window_size)
362 .map(|s| s.coherence_score)
363 .collect()
364 }
365
366 pub fn calculate_identity_drift(&self) -> f64 {
368 if let Some(baseline) = &self.identity_baseline {
369 if let Some(current) = self.snapshots.back() {
370 return 1.0 - baseline.calculate_similarity(current);
371 }
372 }
373 0.0
374 }
375
376 fn check_continuity_break(
379 &mut self,
380 current: &IdentitySnapshot,
381 previous: &IdentitySnapshot,
382 ) -> TemporalResult<()> {
383 let gap_ns = current.timestamp.nanos_since(previous.timestamp, 3_000_000_000);
385 if gap_ns > self.gap_tolerance_ns {
386 self.metrics.continuity_breaks += 1;
387 self.metrics.max_gap_duration_ns = self.metrics.max_gap_duration_ns.max(gap_ns);
388 }
389
390 let similarity = current.calculate_similarity(previous);
392 if similarity < self.continuity_threshold {
393 self.metrics.continuity_breaks += 1;
394 }
395
396 Ok(())
397 }
398
399 fn update_stability_metrics(&mut self, snapshot: &IdentitySnapshot) {
400 if self.snapshots.len() < 2 {
401 return;
402 }
403
404 let recent_snapshots: Vec<_> = self.snapshots.iter().rev().take(10).collect();
406
407 if recent_snapshots.len() >= 2 {
408 let mut similarities = Vec::new();
409
410 for i in 0..recent_snapshots.len() - 1 {
411 let sim = recent_snapshots[i].calculate_similarity(recent_snapshots[i + 1]);
412 similarities.push(sim);
413 }
414
415 let current_sim = snapshot.calculate_similarity(recent_snapshots[0]);
417 similarities.push(current_sim);
418
419 let avg_similarity = similarities.iter().sum::<f64>() / similarities.len() as f64;
421
422 let alpha = 0.1;
424 self.metrics.identity_stability = (1.0 - alpha) * self.metrics.identity_stability + alpha * avg_similarity;
425 }
426 }
427
428 fn store_snapshot(&mut self, snapshot: IdentitySnapshot) {
429 self.snapshots.push_back(snapshot);
430
431 while self.snapshots.len() > self.max_snapshots {
433 self.snapshots.pop_front();
434 }
435 }
436
437 fn update_metrics(&mut self) {
438 if self.snapshots.len() < 2 {
439 return;
440 }
441
442 let mut total_similarity = 0.0;
444 let mut similarity_count = 0;
445
446 for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
447 let sim = window[1].calculate_similarity(window[0]);
448 total_similarity += sim;
449 similarity_count += 1;
450 }
451
452 if similarity_count > 0 {
453 self.metrics.continuity_score = total_similarity / similarity_count as f64;
454 }
455
456 let coherence_scores: Vec<f64> = self.snapshots.iter()
458 .map(|s| s.coherence_score)
459 .collect();
460
461 if !coherence_scores.is_empty() {
462 self.metrics.identity_coherence = coherence_scores.iter().sum::<f64>() / coherence_scores.len() as f64;
463 }
464
465 self.calculate_temporal_consistency();
467
468 self.calculate_preservation_efficiency();
470
471 self.update_gap_metrics();
473 }
474
475 fn calculate_temporal_consistency(&mut self) {
476 if self.snapshots.len() < 3 {
477 return;
478 }
479
480 let mut consistency_scores = Vec::new();
482
483 for i in 2..self.snapshots.len() {
484 let s1 = &self.snapshots[i - 2];
485 let s2 = &self.snapshots[i - 1];
486 let s3 = &self.snapshots[i];
487
488 let vel1: Vec<f64> = s2.feature_vector.iter()
490 .zip(s1.feature_vector.iter())
491 .map(|(a, b)| a - b)
492 .collect();
493
494 let vel2: Vec<f64> = s3.feature_vector.iter()
495 .zip(s2.feature_vector.iter())
496 .map(|(a, b)| a - b)
497 .collect();
498
499 let dot_product: f64 = vel1.iter().zip(vel2.iter()).map(|(a, b)| a * b).sum();
501 let mag1: f64 = vel1.iter().map(|x| x * x).sum::<f64>().sqrt();
502 let mag2: f64 = vel2.iter().map(|x| x * x).sum::<f64>().sqrt();
503
504 if mag1 > 0.0 && mag2 > 0.0 {
505 consistency_scores.push(dot_product / (mag1 * mag2));
506 }
507 }
508
509 if !consistency_scores.is_empty() {
510 self.metrics.temporal_consistency = consistency_scores.iter().sum::<f64>() / consistency_scores.len() as f64;
511 }
512 }
513
514 fn calculate_preservation_efficiency(&mut self) {
515 if let Some(baseline) = &self.identity_baseline {
516 if let Some(current) = self.snapshots.back() {
517 let similarity_to_baseline = current.calculate_similarity(baseline);
519 let time_factor = 1.0 / (1.0 + self.snapshots.len() as f64 / 1000.0); self.metrics.preservation_efficiency = similarity_to_baseline * time_factor;
522 }
523 }
524 }
525
526 fn update_gap_metrics(&mut self) {
527 if self.snapshots.len() < 2 {
528 return;
529 }
530
531 let mut gaps = Vec::new();
532
533 for window in self.snapshots.iter().collect::<Vec<_>>().windows(2) {
534 let gap_ns = window[1].timestamp.nanos_since(window[0].timestamp, 3_000_000_000);
535 gaps.push(gap_ns);
536 }
537
538 if !gaps.is_empty() {
539 self.metrics.average_gap_duration_ns = gaps.iter().sum::<u64>() as f64 / gaps.len() as f64;
540 self.metrics.max_gap_duration_ns = *gaps.iter().max().unwrap_or(&0);
541 }
542 }
543}
544
545impl Default for IdentityContinuityTracker {
546 fn default() -> Self {
547 Self::new()
548 }
549}
550
551#[cfg(test)]
552mod tests {
553 use super::*;
554
555 #[test]
556 fn test_identity_snapshot_creation() {
557 let timestamp = TscTimestamp::now();
558 let state = vec![1, 2, 3, 4, 5];
559
560 let snapshot = IdentitySnapshot::new(timestamp, &state);
561 assert_eq!(snapshot.timestamp, timestamp);
562 assert!(!snapshot.feature_vector.is_empty());
563 assert!(snapshot.coherence_score >= 0.0 && snapshot.coherence_score <= 1.0);
564 }
565
566 #[test]
567 fn test_feature_extraction() {
568 let state = vec![1, 2, 3, 4, 5, 4, 3, 2, 1];
569 let features = IdentitySnapshot::extract_features(&state);
570
571 assert!(!features.is_empty());
572 for &feature in &features {
574 assert!(feature >= -1.0 && feature <= 1.0);
575 }
576 }
577
578 #[test]
579 fn test_similarity_calculation() {
580 let timestamp = TscTimestamp::now();
581 let state1 = vec![1, 2, 3, 4, 5];
582 let state2 = vec![1, 2, 3, 4, 5]; let state3 = vec![5, 4, 3, 2, 1]; let snapshot1 = IdentitySnapshot::new(timestamp, &state1);
586 let snapshot2 = IdentitySnapshot::new(timestamp, &state2);
587 let snapshot3 = IdentitySnapshot::new(timestamp, &state3);
588
589 let sim12 = snapshot1.calculate_similarity(&snapshot2);
590 let sim13 = snapshot1.calculate_similarity(&snapshot3);
591
592 assert!(sim12 > sim13); assert!(sim12 >= 0.0 && sim12 <= 1.0);
594 assert!(sim13 >= 0.0 && sim13 <= 1.0);
595 }
596
597 #[test]
598 fn test_continuity_tracker() {
599 let mut tracker = IdentityContinuityTracker::new();
600 let timestamp = TscTimestamp::now();
601 let state = vec![1, 2, 3, 4, 5];
602
603 tracker.track_continuity(timestamp, &state).unwrap();
604 assert_eq!(tracker.snapshots.len(), 1);
605
606 let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
608 let state2 = vec![1, 2, 3, 4, 6]; tracker.track_continuity(timestamp2, &state2).unwrap();
611 assert_eq!(tracker.snapshots.len(), 2);
612
613 let metrics = tracker.get_metrics().unwrap();
614 assert!(metrics.continuity_score > 0.0);
615 }
616
617 #[test]
618 fn test_continuity_break_detection() {
619 let mut tracker = IdentityContinuityTracker::new();
620 tracker.set_continuity_threshold(0.9); let timestamp = TscTimestamp::now();
623 let state1 = vec![1, 2, 3, 4, 5];
624 let state2 = vec![10, 20, 30, 40, 50]; tracker.track_continuity(timestamp, &state1).unwrap();
627
628 let timestamp2 = timestamp.add_nanos(1000, 3_000_000_000);
629 tracker.track_continuity(timestamp2, &state2).unwrap();
630
631 assert!(tracker.metrics.continuity_breaks > 0);
633 }
634
635 #[test]
636 fn test_identity_drift_calculation() {
637 let mut tracker = IdentityContinuityTracker::new();
638 let timestamp = TscTimestamp::now();
639
640 let baseline_state = vec![1, 2, 3, 4, 5];
642 tracker.track_continuity(timestamp, &baseline_state).unwrap();
643
644 for i in 1..=10 {
646 let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
647 let drifted_state = vec![1 + i as u8, 2, 3, 4, 5];
648 tracker.track_continuity(timestamp_i, &drifted_state).unwrap();
649 }
650
651 let drift = tracker.calculate_identity_drift();
652 assert!(drift > 0.0); assert!(drift <= 1.0); }
655
656 #[test]
657 fn test_stability_metrics() {
658 let mut tracker = IdentityContinuityTracker::new();
659 let timestamp = TscTimestamp::now();
660
661 for i in 0..10 {
663 let timestamp_i = timestamp.add_nanos(i * 1000, 3_000_000_000);
664 let stable_state = vec![1, 2, 3, 4, 5]; tracker.track_continuity(timestamp_i, &stable_state).unwrap();
666 }
667
668 assert!(tracker.get_identity_stability() > 0.5); }
670}