pub struct TemporalGraphIndex<D: DistanceMetric> {
inner: TemporalHnsw<D>,
edges: TemporalEdgeLayer,
typed_edges: TypedEdgeStore,
}Expand description
Temporal Graph Index: HNSW with temporal successor/predecessor edges.
Wraps TemporalHnsw (untouched) with a TemporalEdgeLayer for
causal navigation and hybrid search.
Fields§
§inner: TemporalHnsw<D>The underlying spatiotemporal HNSW index.
edges: TemporalEdgeLayerTemporal edge layer (successor/predecessor per entity).
typed_edges: TypedEdgeStoreTyped relational edges (RFC-013 Part B).
Implementations§
Source§impl<D: DistanceMetric + Clone> TemporalGraphIndex<D>
impl<D: DistanceMetric + Clone> TemporalGraphIndex<D>
Sourcepub fn new(config: HnswConfig, metric: D) -> Self
pub fn new(config: HnswConfig, metric: D) -> Self
Create a new empty temporal graph index.
Sourcepub fn from_temporal_hnsw(inner: TemporalHnsw<D>) -> Self
pub fn from_temporal_hnsw(inner: TemporalHnsw<D>) -> Self
Create from an existing TemporalHnsw (migration path).
Rebuilds the temporal edge layer from the entity_index.
Sourcepub fn insert(&mut self, entity_id: u64, timestamp: i64, vector: &[f32]) -> u32
pub fn insert(&mut self, entity_id: u64, timestamp: i64, vector: &[f32]) -> u32
Insert a temporal point.
Sourcepub fn insert_with_reward(
&mut self,
entity_id: u64,
timestamp: i64,
vector: &[f32],
reward: f32,
) -> u32
pub fn insert_with_reward( &mut self, entity_id: u64, timestamp: i64, vector: &[f32], reward: f32, ) -> u32
Insert a temporal point with an outcome reward.
Sourcepub fn search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
) -> Vec<(u32, f32)>
pub fn search( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, ) -> Vec<(u32, f32)>
Standard search (delegates to inner TemporalHnsw).
Sourcepub fn causal_search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
temporal_context: usize,
) -> Vec<CausalSearchResult>
pub fn causal_search( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, temporal_context: usize, ) -> Vec<CausalSearchResult>
Causal search: semantic search + temporal edge context.
Phase 1: Standard HNSW search. Phase 2: For each result, walk temporal edges to get what happened before and after.
Answers: “Find similar entities, and show me what happened to them next.”
Sourcepub fn hybrid_search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
beta: f32,
query_timestamp: i64,
) -> Vec<(u32, f32)>
pub fn hybrid_search( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, beta: f32, query_timestamp: i64, ) -> Vec<(u32, f32)>
Hybrid search: beam search exploring both semantic AND temporal edges.
At each step of the beam search on level 0, when visiting a node,
also adds its temporal neighbors to the candidate set with a
distance penalty controlled by beta.
beta = 0.0: pure semantic HNSW (ignores temporal edges)beta = 1.0: always follow temporal edges (aggressive temporal exploration)
Sourcepub fn inner(&self) -> &TemporalHnsw<D>
pub fn inner(&self) -> &TemporalHnsw<D>
Access the underlying TemporalHnsw.
Sourcepub fn edges(&self) -> &TemporalEdgeLayer
pub fn edges(&self) -> &TemporalEdgeLayer
Access the temporal edge layer.
Sourcepub fn trajectory(
&self,
entity_id: u64,
filter: TemporalFilter,
) -> Vec<(i64, u32)>
pub fn trajectory( &self, entity_id: u64, filter: TemporalFilter, ) -> Vec<(i64, u32)>
Get trajectory for an entity.
Sourcepub fn inner_mut(&mut self) -> &mut TemporalHnsw<D>
pub fn inner_mut(&mut self) -> &mut TemporalHnsw<D>
Mutable access to the underlying TemporalHnsw.
Sourcepub fn config(&self) -> &HnswConfig
pub fn config(&self) -> &HnswConfig
Get HNSW config.
Sourcepub fn set_ef_construction(&mut self, ef: usize)
pub fn set_ef_construction(&mut self, ef: usize)
Set ef_construction at runtime.
Sourcepub fn set_ef_search(&mut self, ef: usize)
pub fn set_ef_search(&mut self, ef: usize)
Set ef_search at runtime.
Sourcepub fn enable_scalar_quantization(&mut self, min_val: f32, max_val: f32)
pub fn enable_scalar_quantization(&mut self, min_val: f32, max_val: f32)
Enable scalar quantization.
Sourcepub fn disable_scalar_quantization(&mut self)
pub fn disable_scalar_quantization(&mut self)
Disable scalar quantization.
Sourcepub fn search_with_recency(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
recency_lambda: f32,
recency_weight: f32,
) -> Vec<(u32, f32)>
pub fn search_with_recency( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, recency_lambda: f32, recency_weight: f32, ) -> Vec<(u32, f32)>
Search with recency bias and normalized distances.
Sourcepub fn set_reward(&mut self, node_id: u32, reward: f32)
pub fn set_reward(&mut self, node_id: u32, reward: f32)
Set the reward for a node retroactively.
Sourcepub fn search_with_reward(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
min_reward: f32,
) -> Vec<(u32, f32)>
pub fn search_with_reward( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, min_reward: f32, ) -> Vec<(u32, f32)>
Search with reward pre-filtering.
Sourcepub fn compute_centroid(&self) -> Option<Vec<f32>>
pub fn compute_centroid(&self) -> Option<Vec<f32>>
Compute the centroid of all vectors.
Sourcepub fn set_centroid(&mut self, centroid: Vec<f32>)
pub fn set_centroid(&mut self, centroid: Vec<f32>)
Set centroid for anisotropy correction.
Sourcepub fn clear_centroid(&mut self)
pub fn clear_centroid(&mut self)
Clear centroid.
Sourcepub fn centered_vector(&self, vec: &[f32]) -> Vec<f32>
pub fn centered_vector(&self, vec: &[f32]) -> Vec<f32>
Center a vector by subtracting the centroid.
Sourcepub fn regions(&self, level: usize) -> Vec<(u32, Vec<f32>, usize)>
pub fn regions(&self, level: usize) -> Vec<(u32, Vec<f32>, usize)>
Get semantic regions at a given HNSW level.
Sourcepub fn region_assignments(
&self,
level: usize,
filter: TemporalFilter,
) -> HashMap<u32, Vec<(u64, i64)>>
pub fn region_assignments( &self, level: usize, filter: TemporalFilter, ) -> HashMap<u32, Vec<(u64, i64)>>
O(N) single-pass region assignments.
Sourcepub fn region_trajectory(
&self,
entity_id: u64,
level: usize,
window_days: i64,
alpha: f32,
) -> Vec<(i64, Vec<f32>)>
pub fn region_trajectory( &self, entity_id: u64, level: usize, window_days: i64, alpha: f32, ) -> Vec<(i64, Vec<f32>)>
Smoothed region distribution trajectory for an entity.
Sourcepub fn typed_edges(&self) -> &TypedEdgeStore
pub fn typed_edges(&self) -> &TypedEdgeStore
Access the typed edge store.
Sourcepub fn typed_edges_mut(&mut self) -> &mut TypedEdgeStore
pub fn typed_edges_mut(&mut self) -> &mut TypedEdgeStore
Mutable access to the typed edge store.
Sourcepub fn add_typed_edge(
&mut self,
source: u32,
target: u32,
edge_type: EdgeType,
weight: f32,
)
pub fn add_typed_edge( &mut self, source: u32, target: u32, edge_type: EdgeType, weight: f32, )
Add a typed edge between two nodes.
Sourcepub fn success_score(&self, node_id: u32) -> f32
pub fn success_score(&self, node_id: u32) -> f32
Get the success score of a node based on typed edges.
Uses Beta prior: P(success) = (1 + n_success) / (2 + n_total).
Sourcepub fn save(&self, dir: &Path) -> Result<()>
pub fn save(&self, dir: &Path) -> Result<()>
Save to directory (index + temporal edges + typed edges).
Sourcepub fn scored_search(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
query_timestamp: i64,
weights: &ScoringWeights,
query_region: Option<u32>,
) -> Vec<(u32, f32)>
pub fn scored_search( &self, query: &[f32], k: usize, filter: TemporalFilter, query_timestamp: i64, weights: &ScoringWeights, query_region: Option<u32>, ) -> Vec<(u32, f32)>
Search with Bayesian multi-factor scoring.
Pipeline:
- HNSW over-fetch 4k candidates
- Compute features per candidate (similarity, recency, reward, success_score, region)
- Bayesian rerank using
weights - Return top-k
This integrates typed edges (success_score), reward annotations, recency, and region membership into a single scored retrieval.
Sourcepub fn assign_region(&self, vector: &[f32], level: usize) -> Option<u32>
pub fn assign_region(&self, vector: &[f32], level: usize) -> Option<u32>
Assign a vector to a region at a given HNSW level.
Sourcepub fn trajectory_search(
&self,
recent_trajectory: &[(i64, &[f32])],
k: usize,
signature_depth: usize,
) -> Vec<(u64, f64, usize)>
pub fn trajectory_search( &self, recent_trajectory: &[(i64, &[f32])], k: usize, signature_depth: usize, ) -> Vec<(u64, f64, usize)>
Search for episodes with similar trajectory SHAPE (not just similar state).
Uses path signatures to compare the agent’s recent trajectory against stored episodes. Returns episodes whose trajectory shape is most similar, regardless of where in embedding space they are.
This enables “lateral thinking”: finding episodes that MOVED similarly, not just episodes that WERE in a similar position.
Returns (entity_id, signature_distance, trajectory_length).
Search for episodes with similar trajectory SHAPE (not just similar state).
Uses path signatures to compare the agent’s recent trajectory against stored episodes. Returns episodes whose trajectory shape is most similar.
This enables “lateral thinking”: finding episodes that MOVED similarly, not just episodes that WERE in a similar position.
Returns (entity_id, signature_distance, trajectory_length).
Trait Implementations§
Source§impl<D: DistanceMetric + Clone> TemporalIndexAccess for TemporalGraphIndex<D>
impl<D: DistanceMetric + Clone> TemporalIndexAccess for TemporalGraphIndex<D>
Source§fn search_raw(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
) -> Vec<(u32, f32)>
fn search_raw( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, ) -> Vec<(u32, f32)>
Source§fn trajectory(&self, entity_id: u64, filter: TemporalFilter) -> Vec<(i64, u32)>
fn trajectory(&self, entity_id: u64, filter: TemporalFilter) -> Vec<(i64, u32)>
Source§fn vector(&self, node_id: u32) -> Vec<f32>
fn vector(&self, node_id: u32) -> Vec<f32>
Source§fn regions(&self, _level: usize) -> Vec<(u32, Vec<f32>, usize)>
fn regions(&self, _level: usize) -> Vec<(u32, Vec<f32>, usize)>
(hub_node_id, hub_vector, n_assigned) per region.Source§fn region_members(
&self,
_region_hub: u32,
_level: usize,
_filter: TemporalFilter,
) -> Vec<(u32, u64, i64)>
fn region_members( &self, _region_hub: u32, _level: usize, _filter: TemporalFilter, ) -> Vec<(u32, u64, i64)>
(node_id, entity_id, timestamp) per member.Source§fn region_assignments(
&self,
_level: usize,
_filter: TemporalFilter,
) -> HashMap<u32, Vec<(u64, i64)>>
fn region_assignments( &self, _level: usize, _filter: TemporalFilter, ) -> HashMap<u32, Vec<(u64, i64)>>
Source§fn region_trajectory(
&self,
_entity_id: u64,
_level: usize,
_window_days: i64,
_alpha: f32,
) -> Vec<(i64, Vec<f32>)>
fn region_trajectory( &self, _entity_id: u64, _level: usize, _window_days: i64, _alpha: f32, ) -> Vec<(i64, Vec<f32>)>
Source§fn metadata(&self, _node_id: u32) -> HashMap<String, String>
fn metadata(&self, _node_id: u32) -> HashMap<String, String>
Source§fn search_with_metadata(
&self,
query: &[f32],
k: usize,
filter: TemporalFilter,
alpha: f32,
query_timestamp: i64,
metadata_filter: &MetadataFilter,
) -> Vec<(u32, f32)>
fn search_with_metadata( &self, query: &[f32], k: usize, filter: TemporalFilter, alpha: f32, query_timestamp: i64, metadata_filter: &MetadataFilter, ) -> Vec<(u32, f32)>
Auto Trait Implementations§
impl<D> Freeze for TemporalGraphIndex<D>where
D: Freeze,
impl<D> RefUnwindSafe for TemporalGraphIndex<D>where
D: RefUnwindSafe,
impl<D> Send for TemporalGraphIndex<D>
impl<D> Sync for TemporalGraphIndex<D>
impl<D> Unpin for TemporalGraphIndex<D>where
D: Unpin,
impl<D> UnwindSafe for TemporalGraphIndex<D>where
D: UnwindSafe,
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more