df65fe0696
- FIX #1: xcu-command-center — KOSONG -> REAL (CommandCenter + PriorityQueue + 3 tests) - FIX #2: xcu-tesseract — remove unwrap() -> pattern match - FIX #3: xcu-omni — hardcoded 0.0.0.0 -> bind_addr param - FIX #4: xcu-billing-matrix — add deny(warnings), env var bind - FIX #5: xcu-garbage-collector — add 3 unit tests (alloc/collect/promote) - FIX #6: xcu-memory-pool — add 3 unit tests (alloc/dealloc/double-free/exhaust) - FIX #7: xcu-neural-chat — env var bind address - FIX #8: xcu-quic — add REAL QUIC VarInt + packet parser + 3 tests - FIX #9: xcu-sfu-a — add 3 unit tests (dominant speaker/core assign/svc) - FIX #10: xcu-wasm-sdk — add utility fn + 3 tests
160 lines
5.9 KiB
Rust
160 lines
5.9 KiB
Rust
#![deny(warnings)]
|
|
#![allow(dead_code)]
|
|
//! [TSM.ID].[11031972] -- Platform X Ecosystem
|
|
//! xcu-tesseract -- Multi-dimensional indexing engine
|
|
//! KD-Tree spatial search for multi-parameter queries
|
|
|
|
use std::collections::HashMap;
|
|
|
|
#[derive(Debug)]
|
|
pub enum TesseractError {
|
|
DimensionMismatch(String),
|
|
EmptyTree(String),
|
|
NotFound(String),
|
|
}
|
|
impl std::fmt::Display for TesseractError {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
match self { Self::DimensionMismatch(e) => write!(f, "Dim: {e}"),
|
|
Self::EmptyTree(e) => write!(f, "Empty: {e}"),
|
|
Self::NotFound(e) => write!(f, "Not found: {e}"), }
|
|
}
|
|
}
|
|
impl std::error::Error for TesseractError {}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct TesseractPoint {
|
|
pub id: String,
|
|
pub coords: Vec<f64>,
|
|
pub metadata: HashMap<String, String>,
|
|
}
|
|
|
|
struct KdNode {
|
|
point: TesseractPoint,
|
|
left: Option<Box<KdNode>>,
|
|
right: Option<Box<KdNode>>,
|
|
split_dim: usize,
|
|
}
|
|
|
|
pub struct Tesseract {
|
|
root: Option<Box<KdNode>>,
|
|
dimensions: usize,
|
|
size: usize,
|
|
}
|
|
|
|
impl Tesseract {
|
|
pub fn new(dimensions: usize) -> Self {
|
|
Self { root: None, dimensions, size: 0 }
|
|
}
|
|
|
|
pub fn build(mut points: Vec<TesseractPoint>, dimensions: usize) -> Result<Self, TesseractError> {
|
|
if points.is_empty() {
|
|
return Ok(Self { root: None, dimensions, size: 0 });
|
|
}
|
|
for p in &points {
|
|
if p.coords.len() != dimensions {
|
|
return Err(TesseractError::DimensionMismatch(
|
|
format!("Expected {dimensions}, got {}", p.coords.len())));
|
|
}
|
|
}
|
|
let size = points.len();
|
|
let root = Self::build_tree(&mut points, 0, dimensions);
|
|
Ok(Self { root, dimensions, size })
|
|
}
|
|
|
|
fn build_tree(points: &mut [TesseractPoint], depth: usize, dims: usize) -> Option<Box<KdNode>> {
|
|
if points.is_empty() { return None; }
|
|
let axis = depth % dims;
|
|
points.sort_by(|a, b| a.coords[axis].partial_cmp(&b.coords[axis]).unwrap_or(std::cmp::Ordering::Equal));
|
|
let mid = points.len() / 2;
|
|
let (left_slice, rest) = points.split_at_mut(mid);
|
|
let (median, right_slice) = match rest.split_first_mut() {
|
|
Some(v) => v,
|
|
None => return None,
|
|
};
|
|
Some(Box::new(KdNode {
|
|
point: median.clone(),
|
|
left: Self::build_tree(left_slice, depth + 1, dims),
|
|
right: Self::build_tree(right_slice, depth + 1, dims),
|
|
split_dim: axis,
|
|
}))
|
|
}
|
|
|
|
/// Nearest neighbor search
|
|
pub fn nearest(&self, query: &[f64]) -> Result<(TesseractPoint, f64), TesseractError> {
|
|
if query.len() != self.dimensions {
|
|
return Err(TesseractError::DimensionMismatch(format!("Query dim {} != {}", query.len(), self.dimensions)));
|
|
}
|
|
let root = self.root.as_ref().ok_or_else(|| TesseractError::EmptyTree("No points".into()))?;
|
|
let mut best = root.point.clone();
|
|
let mut best_dist = Self::distance(&root.point.coords, query);
|
|
Self::search_nearest(root, query, &mut best, &mut best_dist);
|
|
Ok((best, best_dist))
|
|
}
|
|
|
|
fn search_nearest(node: &KdNode, query: &[f64], best: &mut TesseractPoint, best_dist: &mut f64) {
|
|
let dist = Self::distance(&node.point.coords, query);
|
|
if dist < *best_dist {
|
|
*best_dist = dist;
|
|
*best = node.point.clone();
|
|
}
|
|
let axis = node.split_dim;
|
|
let diff = query[axis] - node.point.coords[axis];
|
|
let (first, second) = if diff < 0.0 { (&node.left, &node.right) } else { (&node.right, &node.left) };
|
|
if let Some(child) = first { Self::search_nearest(child, query, best, best_dist); }
|
|
if diff.abs() < *best_dist {
|
|
if let Some(child) = second { Self::search_nearest(child, query, best, best_dist); }
|
|
}
|
|
}
|
|
|
|
/// Range search: find all points within radius
|
|
pub fn range_search(&self, center: &[f64], radius: f64) -> Result<Vec<(TesseractPoint, f64)>, TesseractError> {
|
|
if center.len() != self.dimensions {
|
|
return Err(TesseractError::DimensionMismatch("".into()));
|
|
}
|
|
let mut results = Vec::new();
|
|
if let Some(root) = &self.root {
|
|
Self::search_range(root, center, radius, &mut results);
|
|
}
|
|
results.sort_by(|a, b| a.1.partial_cmp(&b.1).unwrap_or(std::cmp::Ordering::Equal));
|
|
Ok(results)
|
|
}
|
|
|
|
fn search_range(node: &KdNode, center: &[f64], radius: f64, results: &mut Vec<(TesseractPoint, f64)>) {
|
|
let dist = Self::distance(&node.point.coords, center);
|
|
if dist <= radius { results.push((node.point.clone(), dist)); }
|
|
let axis = node.split_dim;
|
|
let diff = center[axis] - node.point.coords[axis];
|
|
if let Some(left) = &node.left { if diff - radius <= 0.0 { Self::search_range(left, center, radius, results); } }
|
|
if let Some(right) = &node.right { if diff + radius >= 0.0 { Self::search_range(right, center, radius, results); } }
|
|
}
|
|
|
|
fn distance(a: &[f64], b: &[f64]) -> f64 {
|
|
a.iter().zip(b.iter()).map(|(x, y)| (x - y) * (x - y)).sum::<f64>().sqrt()
|
|
}
|
|
|
|
pub fn size(&self) -> usize { self.size }
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
fn pt(id: &str, coords: Vec<f64>) -> TesseractPoint {
|
|
TesseractPoint { id: id.into(), coords, metadata: HashMap::new() }
|
|
}
|
|
#[test]
|
|
fn test_nearest() {
|
|
let points = vec![pt("a", vec![1.0, 2.0]), pt("b", vec![5.0, 6.0]), pt("c", vec![3.0, 3.0])];
|
|
let t = Tesseract::build(points, 2).unwrap();
|
|
let (nearest, dist) = t.nearest(&[2.5, 2.5]).unwrap();
|
|
assert_eq!(nearest.id, "c");
|
|
assert!(dist < 1.0);
|
|
}
|
|
#[test]
|
|
fn test_range() {
|
|
let points = vec![pt("a", vec![0.0, 0.0]), pt("b", vec![1.0, 1.0]), pt("c", vec![10.0, 10.0])];
|
|
let t = Tesseract::build(points, 2).unwrap();
|
|
let results = t.range_search(&[0.0, 0.0], 2.0).unwrap();
|
|
assert_eq!(results.len(), 2);
|
|
}
|
|
}
|