pub struct HyperbolicTensorNetwork { /* private fields */ }Expand description
Hyperbolic Tensor Network for tree data representation.
Embeds hierarchical data into the Poincaré disk model using Sarkar’s cone-based construction. Each node occupies a point in hyperbolic space, with children placed at hyperbolic distance τ from their parent using Möbius reflections to preserve the tree structure as a Delaunay graph.
Internal maps use DashMap for lock-free concurrent reads, preparing for multi-threaded access in later phases.
Implementations§
Source§impl HyperbolicTensorNetwork
impl HyperbolicTensorNetwork
Sourcepub fn new(dimension: usize, tau: FixedPoint) -> Self
pub fn new(dimension: usize, tau: FixedPoint) -> Self
Create a new hyperbolic tensor network with the given Sarkar scale factor τ.
Sourcepub fn with_grid_resolution(
dimension: usize,
tau: FixedPoint,
grid_resolution: usize,
) -> Self
pub fn with_grid_resolution( dimension: usize, tau: FixedPoint, grid_resolution: usize, ) -> Self
Create a new network with a specific grid resolution.
Sourcepub fn add_node_data_only(
&self,
metadata: NodeMetadata,
value: Vec<u8>,
_level: u32,
) -> String
pub fn add_node_data_only( &self, metadata: NodeMetadata, value: Vec<u8>, _level: u32, ) -> String
Add a node to the DashMap without computing geometric embedding.
Creates a key-derived unique_id for path_map/id_to_path lookups. Semantic queries (nearest_semantic, neighbors_semantic, get/set) work normally. Spatial queries (nearest, neighbors) will not find this node until it is embedded.
Sourcepub fn add_node(
&self,
metadata: NodeMetadata,
value: Vec<u8>,
parent_signature: Option<&GeometricSignature>,
level: u32,
) -> Option<GeometricSignature>
pub fn add_node( &self, metadata: NodeMetadata, value: Vec<u8>, parent_signature: Option<&GeometricSignature>, level: u32, ) -> Option<GeometricSignature>
Add a node to the tensor network.
Computes a position in the Poincaré disk using Sarkar’s cone construction: children are placed at hyperbolic distance τ from their parent, at golden-angle-spaced angles in the parent’s reflected frame.
Sourcepub fn add_node_positioned(
&self,
metadata: NodeMetadata,
value: Vec<u8>,
parent_signature: Option<&GeometricSignature>,
level: u32,
child_index: u32,
) -> Option<GeometricSignature>
pub fn add_node_positioned( &self, metadata: NodeMetadata, value: Vec<u8>, parent_signature: Option<&GeometricSignature>, level: u32, child_index: u32, ) -> Option<GeometricSignature>
Add a node with an explicit child_index for deterministic Sarkar reconstruction.
Used during snapshot replay: the stored child_index ensures the node gets the same geometric position regardless of replay order.
Sourcepub fn get_node_by_signature(
&self,
signature: &GeometricSignature,
) -> Option<CompressedNode>
pub fn get_node_by_signature( &self, signature: &GeometricSignature, ) -> Option<CompressedNode>
Get a node by its signature (returns cloned value).
Sourcepub fn update_node_value(&self, unique_id: &str, value: Vec<u8>) -> bool
pub fn update_node_value(&self, unique_id: &str, value: Vec<u8>) -> bool
Update the value of a node by its unique_id.
Sourcepub fn set_node_metadata_entry(
&self,
unique_id: &str,
key: &str,
val: &str,
) -> bool
pub fn set_node_metadata_entry( &self, unique_id: &str, key: &str, val: &str, ) -> bool
Set a metadata key-value pair on a node by its unique_id.
Sourcepub fn set_node_semantic(&self, unique_id: &str, coords: Vec<u8>) -> bool
pub fn set_node_semantic(&self, unique_id: &str, coords: Vec<u8>) -> bool
Set semantic coordinates on a node by its unique_id.
Sourcepub fn get_node_semantic(&self, unique_id: &str) -> Option<Vec<u8>>
pub fn get_node_semantic(&self, unique_id: &str) -> Option<Vec<u8>>
Get semantic coordinates for a node by its unique_id.
Sourcepub fn root_node(&self) -> Option<CompressedNode>
pub fn root_node(&self) -> Option<CompressedNode>
Get the root node (cloned).
Sourcepub fn root_signature(&self) -> Option<GeometricSignature>
pub fn root_signature(&self) -> Option<GeometricSignature>
Get the root node signature (cloned).
Sourcepub fn children_of(&self, signature: &GeometricSignature) -> Vec<CompressedNode>
pub fn children_of(&self, signature: &GeometricSignature) -> Vec<CompressedNode>
Get the children of a node by its signature (cloned).
Sourcepub fn get_point(&self, unique_id: &str) -> Option<HyperbolicPoint>
pub fn get_point(&self, unique_id: &str) -> Option<HyperbolicPoint>
Get the hyperbolic point for a node (cloned).
Sourcepub fn semantic_epoch(&self) -> u64
pub fn semantic_epoch(&self) -> u64
Monotone counter of semantic-relevant mutations (coordinate writes, inserts, deletes). External caches — like the semantic disk’s derived-position index — use it exactly as the internal per-slice cache does: tag on build, rebuild when it has advanced.
Sourcepub fn hash_table(&self) -> &HyperbolicHashTable
pub fn hash_table(&self) -> &HyperbolicHashTable
Get the hyperbolic hash table.
Sourcepub fn node_count(&self) -> usize
pub fn node_count(&self) -> usize
Get the number of nodes in the network.
Sourcepub fn remove_detached_node(&self, unique_id: &str)
pub fn remove_detached_node(&self, unique_id: &str)
Remove a node-map entry that has NO geometric registration — the
data-only entry retired by embed_existing after its embedded
replacement went live under a new signature-derived id. Not for
embedded nodes: those need Self::unregister_node_with_parent.
Sourcepub fn unregister_node(&self, unique_id: &str)
pub fn unregister_node(&self, unique_id: &str)
Unregister a node from the spatial index (for deletion).
Prefer Self::unregister_node_with_parent when the parent is known:
data-only nodes have no power cell, so the parent cannot always be
derived here, and the parent’s child list must drop the deleted node.
Sourcepub fn unregister_node_with_parent(
&self,
unique_id: &str,
parent_uid: Option<&str>,
)
pub fn unregister_node_with_parent( &self, unique_id: &str, parent_uid: Option<&str>, )
Unregister a node, removing it from the node map and from its parent’s
child list. parent_uid is used when the parent cannot be derived from
the power diagram (e.g. data-only nodes).
Sourcepub fn find_descendants_spatial(
&self,
signature: &GeometricSignature,
) -> Vec<(String, FixedPoint)>
pub fn find_descendants_spatial( &self, signature: &GeometricSignature, ) -> Vec<(String, FixedPoint)>
Find all descendants of a node using the spatial index.
Uses the parent’s stored point + a τ-based radius to find all nodes within the Sarkar cone. Radius = 3·τ covers ~3 levels of descendants.
Sourcepub fn nearest_neighbor_point(
&self,
query_poincare: &HyperbolicPoint,
) -> Option<(String, FixedPoint)>
pub fn nearest_neighbor_point( &self, query_poincare: &HyperbolicPoint, ) -> Option<(String, FixedPoint)>
Find the nearest node to an arbitrary point using the power diagram grid.
Algorithm:
- Convert Poincaré → Klein coordinates: O(d)
- Grid lookup for candidate: O(1)
- Power-distance pre-filter: rank all tree neighbors by pd (~24ns each)
- Hyperbolic distance verification: only top-K candidates (~59µs each)
- Return true nearest
Uses hyperbolic_ratio (~200ns) for all comparisons instead of hyperbolic_distance (~62µs), computing the full distance only once for the final winner. For high-degree nodes, power distance pre-filter ranks neighbors at ~24ns each, then ratio-verifies top-K.
Falls back to VP-tree KNN if grid misses.
Sourcepub fn nearest_neighbor_point_k(
&self,
query_poincare: &HyperbolicPoint,
k: usize,
) -> Vec<(String, FixedPoint)>
pub fn nearest_neighbor_point_k( &self, query_poincare: &HyperbolicPoint, k: usize, ) -> Vec<(String, FixedPoint)>
Find the k nearest stored nodes to an arbitrary Poincaré disk point.
Combines the Nielsen grid candidate + its neighbors with the VP-tree fallback to produce k results sorted by ascending hyperbolic distance.
Sourcepub fn get_klein_point(&self, unique_id: &str) -> Option<KleinPoint>
pub fn get_klein_point(&self, unique_id: &str) -> Option<KleinPoint>
Get the Klein point for a node by unique_id (cloned).
Sourcepub fn get_power_cell(&self, unique_id: &str) -> Option<PowerCell>
pub fn get_power_cell(&self, unique_id: &str) -> Option<PowerCell>
Get the power cell for a node by unique_id (cloned).
Sourcepub fn grid_assigned_tile_count(&self) -> usize
pub fn grid_assigned_tile_count(&self) -> usize
Get the number of assigned tiles in the point location grid.
Sourcepub fn semantic_distance(
coords_a: &[u8],
coords_b: &[u8],
dim_range: &Range<usize>,
) -> FixedPoint
pub fn semantic_distance( coords_a: &[u8], coords_b: &[u8], dim_range: &Range<usize>, ) -> FixedPoint
Compute Euclidean distance between two semantic coordinate vectors across a dimensional slice (specified dimension range).
Each dimension is 16 bytes (i128 LE, Q64.64 fixed-point). Dimensions outside the vectors are treated as zero.
Uses gMath’s fused kernel: differences, squares, and the accumulator all live at the compute tier, so the sum cannot wrap the way a storage-tier Q64.64 accumulator would for large coordinates or many dimensions.
Sourcepub fn decode_semantic_slice(
coords: &[u8],
dim_range: &Range<usize>,
) -> Vec<FixedPoint>
pub fn decode_semantic_slice( coords: &[u8], dim_range: &Range<usize>, ) -> Vec<FixedPoint>
Decode a dimension slice of a raw Q64.64 coordinate vector.
Dimensions beyond the end of coords decode as zero — short vectors
are zero-extended, matching Self::semantic_distance semantics.
Sourcepub fn nearest_semantic(
&self,
query_coords: &[u8],
k: usize,
dim_range: &Range<usize>,
) -> Vec<(String, FixedPoint)>
pub fn nearest_semantic( &self, query_coords: &[u8], k: usize, dim_range: &Range<usize>, ) -> Vec<(String, FixedPoint)>
Find the k nearest nodes by Euclidean distance in semantic dimension space.
query_coords: raw Q64.64 byte vector representing the query point.
k: number of nearest neighbors to return.
dim_range: which semantic dimensions to compare (the “dimensional slice”).
Returns Vec<(key, distance)> sorted ascending by (distance, key) —
ties break deterministically by the user-visible node key, both for
ordering and for which ties survive the k-boundary.
Routing (docs/SEMANTIC_INDEX.md): stores below
constants::SEMANTIC_INDEX_MIN_NODES use the brute-force scan;
larger stores query a lazily built per-dim_range VP-tree, rebuilt
when the semantic epoch has advanced (any coord write, insert, or
delete). Warm-index queries are O(log n) expected on low-dimensional
slices; the first query for a slice after a mutation pays the
O(n log n) build. Results are identical to the scan path.
Sourcepub fn nearest_semantic_scan(
&self,
query_coords: &[u8],
k: usize,
dim_range: &Range<usize>,
) -> Vec<(String, FixedPoint)>
pub fn nearest_semantic_scan( &self, query_coords: &[u8], k: usize, dim_range: &Range<usize>, ) -> Vec<(String, FixedPoint)>
Reference brute-force path for Self::nearest_semantic:
O(n × d) scan over every node with semantic coordinates.
Same ordering contract as the indexed path — ascending
(distance, key). Public so tests and benchmarks can compare
the two paths directly; prefer nearest_semantic, which picks.
Sourcepub fn validate_network(&self) -> bool
pub fn validate_network(&self) -> bool
Check if the network has a valid structure.
Verifies structural invariants across all internal data structures: nodes, point_map, klein_points, power_cells, and the hash table.