Skip to main content

HyperbolicTensorNetwork

Struct HyperbolicTensorNetwork 

Source
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

Source

pub fn new(dimension: usize, tau: FixedPoint) -> Self

Create a new hyperbolic tensor network with the given Sarkar scale factor τ.

Source

pub fn with_grid_resolution( dimension: usize, tau: FixedPoint, grid_resolution: usize, ) -> Self

Create a new network with a specific grid resolution.

Source

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.

Source

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.

Source

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.

Source

pub fn get_node_by_signature( &self, signature: &GeometricSignature, ) -> Option<CompressedNode>

Get a node by its signature (returns cloned value).

Source

pub fn update_node_value(&self, unique_id: &str, value: Vec<u8>) -> bool

Update the value of a node by its unique_id.

Source

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.

Source

pub fn set_node_semantic(&self, unique_id: &str, coords: Vec<u8>) -> bool

Set semantic coordinates on a node by its unique_id.

Source

pub fn get_node_semantic(&self, unique_id: &str) -> Option<Vec<u8>>

Get semantic coordinates for a node by its unique_id.

Source

pub fn root_node(&self) -> Option<CompressedNode>

Get the root node (cloned).

Source

pub fn root_signature(&self) -> Option<GeometricSignature>

Get the root node signature (cloned).

Source

pub fn children_of(&self, signature: &GeometricSignature) -> Vec<CompressedNode>

Get the children of a node by its signature (cloned).

Source

pub fn get_point(&self, unique_id: &str) -> Option<HyperbolicPoint>

Get the hyperbolic point for a node (cloned).

Source

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.

Source

pub fn hash_table(&self) -> &HyperbolicHashTable

Get the hyperbolic hash table.

Source

pub fn node_count(&self) -> usize

Get the number of nodes in the network.

Source

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.

Source

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.

Source

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).

Source

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.

Source

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:

  1. Convert Poincaré → Klein coordinates: O(d)
  2. Grid lookup for candidate: O(1)
  3. Power-distance pre-filter: rank all tree neighbors by pd (~24ns each)
  4. Hyperbolic distance verification: only top-K candidates (~59µs each)
  5. 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.

Source

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.

Source

pub fn get_klein_point(&self, unique_id: &str) -> Option<KleinPoint>

Get the Klein point for a node by unique_id (cloned).

Source

pub fn get_power_cell(&self, unique_id: &str) -> Option<PowerCell>

Get the power cell for a node by unique_id (cloned).

Source

pub fn grid_assigned_tile_count(&self) -> usize

Get the number of assigned tiles in the point location grid.

Source

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.

Source

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.

Source

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.

Source

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.

Source

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.

Trait Implementations§

Source§

impl Debug for HyperbolicTensorNetwork

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.