use serde::{Deserialize, Serialize};
use std::hash::{Hash, Hasher};
pub use exo_core::{Metadata, MetadataValue, Pattern, PatternId, SubstrateTime};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct TemporalPattern {
pub pattern: Pattern,
pub access_count: usize,
pub last_accessed: SubstrateTime,
}
impl TemporalPattern {
pub fn new(pattern: Pattern) -> Self {
Self {
pattern,
access_count: 0,
last_accessed: SubstrateTime::now(),
}
}
pub fn from_embedding(embedding: Vec<f32>, metadata: Metadata) -> Self {
let pattern = Pattern {
id: PatternId::new(),
embedding,
metadata,
timestamp: SubstrateTime::now(),
antecedents: Vec::new(),
salience: 1.0,
};
Self::new(pattern)
}
pub fn with_antecedents(
embedding: Vec<f32>,
metadata: Metadata,
antecedents: Vec<PatternId>,
) -> Self {
let pattern = Pattern {
id: PatternId::new(),
embedding,
metadata,
timestamp: SubstrateTime::now(),
antecedents,
salience: 1.0,
};
Self::new(pattern)
}
pub fn mark_accessed(&mut self) {
self.access_count += 1;
self.last_accessed = SubstrateTime::now();
}
pub fn id(&self) -> PatternId {
self.pattern.id
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Query {
pub embedding: Vec<f32>,
pub origin: Option<PatternId>,
pub k: usize,
}
impl Query {
pub fn from_embedding(embedding: Vec<f32>) -> Self {
Self {
embedding,
origin: None,
k: 10,
}
}
pub fn with_origin(mut self, origin: PatternId) -> Self {
self.origin = Some(origin);
self
}
pub fn with_k(mut self, k: usize) -> Self {
self.k = k;
self
}
pub fn hash(&self) -> u64 {
use ahash::AHasher;
let mut hasher = AHasher::default();
for &val in &self.embedding {
val.to_bits().hash(&mut hasher);
}
if let Some(origin) = &self.origin {
origin.hash(&mut hasher);
}
self.k.hash(&mut hasher);
hasher.finish()
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CausalResult {
pub pattern: TemporalPattern,
pub similarity: f32,
pub causal_distance: Option<usize>,
pub temporal_distance_ns: i64,
pub combined_score: f32,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchResult {
pub id: PatternId,
pub pattern: TemporalPattern,
pub score: f32,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct TimeRange {
pub start: SubstrateTime,
pub end: SubstrateTime,
}
impl TimeRange {
pub fn new(start: SubstrateTime, end: SubstrateTime) -> Self {
Self { start, end }
}
pub fn contains(&self, time: &SubstrateTime) -> bool {
time >= &self.start && time <= &self.end
}
pub fn past(reference: SubstrateTime) -> Self {
Self {
start: SubstrateTime::MIN,
end: reference,
}
}
pub fn future(reference: SubstrateTime) -> Self {
Self {
start: reference,
end: SubstrateTime::MAX,
}
}
}