Spaces:
Paused
Paused
Download src/core/spatial_index.py from ThomasHeisig/Brain-5D-Space: direct link, hf CLI and curl.
- Browser
- Download file 18 kB
-
https://huggingface.co/spaces/ThomasHeisig/Brain-5D-Space/resolve/main/src/core/spatial_index.py
- Command line
-
hf download hf://spaces/ThomasHeisig/Brain-5D-Space/src/core/spatial_index.py
-
curl -L -o spatial_index.py https://huggingface.co/spaces/ThomasHeisig/Brain-5D-Space/resolve/main/src/core/spatial_index.py
18 kB
| """5D spatial indexing for Brain-5D neural networks. | |
| This module provides coordinate manipulation and spatial indexing for | |
| the 5-dimensional neuron space used in Brain-5D. It supports: | |
| - Packing/unpacking 5D coordinates into 64-bit integers | |
| - Conversion between linear indices and 5D coordinates | |
| - Euclidean and weighted distance calculations | |
| - Neighbor iteration within a radius | |
| - Boundary coordinate generation | |
| - LRU-cached offset computation for performance | |
| The 5D space is organized as (x, y, z, d4, d5) where: | |
| - x, y, z: spatial dimensions (0-255) | |
| - d4, d5: functional dimensions (0-255) | |
| """ | |
| from __future__ import annotations | |
| import math | |
| from collections.abc import Iterable, Iterator | |
| from functools import lru_cache | |
| from itertools import product | |
| # ============================================================================ | |
| # Type Aliases | |
| # ============================================================================ | |
| Coord5D = tuple[int, int, int, int, int] | |
| """Type alias for a 5D coordinate.""" | |
| Dim5D = tuple[int, int, int, int, int] | |
| """Type alias for 5D dimensions.""" | |
| # ============================================================================ | |
| # Constants | |
| # ============================================================================ | |
| BITS_PER_DIM: int = 8 | |
| """Number of bits allocated per dimension in packed representation.""" | |
| MASK: int = 0xFF | |
| """Bitmask for extracting a single dimension (8 bits).""" | |
| SHIFTS: tuple[int, int, int, int, int] = (0, 8, 16, 24, 32) | |
| """Bit shifts for each dimension in packed representation.""" | |
| DIM_NAMES: dict[str, int] = { | |
| "x": 0, | |
| "y": 1, | |
| "z": 2, | |
| "d4": 3, | |
| "d5": 4, | |
| } | |
| """Mapping from dimension names to indices.""" | |
| DIM_INDICES: dict[int, str] = {v: k for k, v in DIM_NAMES.items()} | |
| """Mapping from dimension indices to names.""" | |
| MAX_COORD: int = 255 | |
| """Maximum coordinate value (8-bit range).""" | |
| # ============================================================================ | |
| # Coordinate Validation | |
| # ============================================================================ | |
| def validate_coord(coord: Coord5D) -> None: | |
| """Validate that all coordinates are within the 0-255 range. | |
| Args: | |
| coord: 5D coordinate to validate. | |
| Raises: | |
| ValueError: If any coordinate is outside the valid range. | |
| """ | |
| for i, c in enumerate(coord): | |
| if c < 0 or c > MAX_COORD: | |
| raise ValueError( | |
| f"Coordinate {c} at dimension {i} must be between 0 and {MAX_COORD}" | |
| ) | |
| def validate_dims(dims: Dim5D) -> None: | |
| """Validate that all dimensions are positive. | |
| Args: | |
| dims: 5D dimensions to validate. | |
| Raises: | |
| ValueError: If any dimension is <= 0. | |
| """ | |
| for i, d in enumerate(dims): | |
| if d <= 0: | |
| raise ValueError(f"Dimension {i} must be positive, got {d}") | |
| def validate_coord_in_dims(coord: Coord5D, dims: Dim5D) -> None: | |
| """Validate that a coordinate is within the given dimensions. | |
| Args: | |
| coord: 5D coordinate to validate. | |
| dims: 5D dimensions. | |
| Raises: | |
| ValueError: If the coordinate is outside the dimensions. | |
| """ | |
| validate_dims(dims) | |
| for i, (c, d) in enumerate(zip(coord, dims)): | |
| if c < 0 or c >= d: | |
| raise ValueError(f"Coordinate {c} at dimension {i} outside dimension {d}") | |
| def is_valid_coord(coord: Coord5D) -> bool: | |
| """Check if a coordinate is valid (all coordinates in 0-255 range). | |
| Args: | |
| coord: 5D coordinate to check. | |
| Returns: | |
| True if valid, False otherwise. | |
| """ | |
| try: | |
| validate_coord(coord) | |
| return True | |
| except ValueError: | |
| return False | |
| def is_valid_coord_in_dims(coord: Coord5D, dims: Dim5D) -> bool: | |
| """Check if a coordinate is valid within the given dimensions. | |
| Args: | |
| coord: 5D coordinate to check. | |
| dims: 5D dimensions. | |
| Returns: | |
| True if valid, False otherwise. | |
| """ | |
| try: | |
| validate_coord_in_dims(coord, dims) | |
| return True | |
| except ValueError: | |
| return False | |
| # ============================================================================ | |
| # Packing / Unpacking | |
| # ============================================================================ | |
| def pack_coords(x: int, y: int, z: int, d4: int, d5: int) -> int: | |
| """Pack five 8-bit coordinates into a single 64-bit integer. | |
| This is useful for storing coordinates as keys in dictionaries | |
| or for efficient hashing. | |
| Args: | |
| x: X coordinate (0-255). | |
| y: Y coordinate (0-255). | |
| z: Z coordinate (0-255). | |
| d4: Fourth dimension coordinate (0-255). | |
| d5: Fifth dimension coordinate (0-255). | |
| Returns: | |
| A 64-bit integer with packed coordinates. | |
| Raises: | |
| ValueError: If any coordinate is outside the 0-255 range. | |
| Example: | |
| >>> packed = pack_coords(1, 2, 3, 4, 5) | |
| >>> unpack_coords(packed) | |
| (1, 2, 3, 4, 5) | |
| """ | |
| coords = (x, y, z, d4, d5) | |
| for i, c in enumerate(coords): | |
| if c < 0 or c > MAX_COORD: | |
| raise ValueError( | |
| f"Coordinate {c} at dimension {i} must be between 0 and {MAX_COORD}" | |
| ) | |
| return ( | |
| (x << SHIFTS[0]) | |
| | (y << SHIFTS[1]) | |
| | (z << SHIFTS[2]) | |
| | (d4 << SHIFTS[3]) | |
| | (d5 << SHIFTS[4]) | |
| ) | |
| def unpack_coords(index: int) -> Coord5D: | |
| """Unpack a 64-bit integer into five 8-bit coordinates. | |
| Args: | |
| index: Packed 64-bit integer containing 5D coordinates. | |
| Returns: | |
| A 5D coordinate tuple (x, y, z, d4, d5). | |
| Example: | |
| >>> pack = pack_coords(1, 2, 3, 4, 5) | |
| >>> unpack_coords(pack) | |
| (1, 2, 3, 4, 5) | |
| """ | |
| return ( | |
| (index >> SHIFTS[0]) & MASK, | |
| (index >> SHIFTS[1]) & MASK, | |
| (index >> SHIFTS[2]) & MASK, | |
| (index >> SHIFTS[3]) & MASK, | |
| (index >> SHIFTS[4]) & MASK, | |
| ) | |
| # ============================================================================ | |
| # Linear Index Conversion | |
| # ============================================================================ | |
| def coords_to_linear(coord: Coord5D, dims: Dim5D) -> int: | |
| """Convert 5D coordinates to a linear index (row-major order). | |
| The linear index is computed as: | |
| (((x * dims[1] + y) * dims[2] + z) * dims[3] + d4) * dims[4] + d5 | |
| Args: | |
| coord: 5D coordinate to convert. | |
| dims: 5D dimensions (must all be positive). | |
| Returns: | |
| Linear index in [0, product(dims)). | |
| Raises: | |
| ValueError: If dimensions are not positive or coordinate is out of bounds. | |
| Example: | |
| >>> dims = (10, 10, 10, 10, 10) | |
| >>> coords_to_linear((1, 2, 3, 4, 5), dims) | |
| # Returns a unique index for that coordinate | |
| """ | |
| validate_dims(dims) | |
| validate_coord_in_dims(coord, dims) | |
| x, y, z, d4, d5 = coord | |
| return (((x * dims[1] + y) * dims[2] + z) * dims[3] + d4) * dims[4] + d5 | |
| def linear_to_5d(index: int, dims: Dim5D) -> Coord5D: | |
| """Convert a linear index back to 5D coordinates (row-major order). | |
| This is the inverse of coords_to_linear. | |
| Args: | |
| index: Linear index in [0, product(dims)). | |
| dims: 5D dimensions (must all be positive). | |
| Returns: | |
| The corresponding 5D coordinate. | |
| Raises: | |
| ValueError: If dimensions are not positive or index is out of bounds. | |
| Example: | |
| >>> dims = (10, 10, 10, 10, 10) | |
| >>> linear_to_5d(12345, dims) | |
| # Returns the original coordinate | |
| """ | |
| validate_dims(dims) | |
| total = 1 | |
| for d in dims: | |
| total *= d | |
| if index < 0 or index >= total: | |
| raise ValueError(f"Linear index {index} outside [0, {total})") | |
| # Decode in reverse order (row-major) | |
| idx = index | |
| d5 = idx % dims[4] | |
| idx //= dims[4] | |
| d4 = idx % dims[3] | |
| idx //= dims[3] | |
| z = idx % dims[2] | |
| idx //= dims[2] | |
| y = idx % dims[1] | |
| idx //= dims[1] | |
| x = idx % dims[0] | |
| return (x, y, z, d4, d5) | |
| def linear_to_coord(index: int, dims: Dim5D) -> Coord5D: | |
| """Alias for linear_to_5d.""" | |
| return linear_to_5d(index, dims) | |
| # ============================================================================ | |
| # Distance Functions | |
| # ============================================================================ | |
| def euclidean_distance_5d(a: Coord5D, b: Coord5D) -> float: | |
| """Calculate the Euclidean distance between two 5D coordinates. | |
| Args: | |
| a: First 5D coordinate. | |
| b: Second 5D coordinate. | |
| Returns: | |
| The Euclidean distance (sqrt of sum of squared differences). | |
| """ | |
| return math.sqrt(sum((ai - bi) ** 2 for ai, bi in zip(a, b))) | |
| def distance_5d(a: Coord5D, b: Coord5D) -> float: | |
| """Alias for euclidean_distance_5d.""" | |
| return euclidean_distance_5d(a, b) | |
| def weighted_distance_5d( | |
| a: Coord5D, | |
| b: Coord5D, | |
| weights: tuple[float, float, float, float, float], | |
| ) -> float: | |
| """Calculate weighted Euclidean distance between two 5D coordinates. | |
| This allows different importance to be assigned to each dimension. | |
| Args: | |
| a: First 5D coordinate. | |
| b: Second 5D coordinate. | |
| weights: Weight for each dimension (x, y, z, d4, d5). | |
| Returns: | |
| The weighted Euclidean distance. | |
| Example: | |
| >>> a = (1, 2, 3, 4, 5) | |
| >>> b = (2, 3, 4, 5, 6) | |
| >>> weights = (1.0, 1.0, 1.0, 0.5, 0.5) | |
| >>> weighted_distance_5d(a, b, weights) | |
| """ | |
| return math.sqrt( | |
| sum(weights[i] * (ai - bi) ** 2 for i, (ai, bi) in enumerate(zip(a, b))) | |
| ) | |
| def chebyshev_distance_5d(a: Coord5D, b: Coord5D) -> float: | |
| """Calculate the Chebyshev distance between two 5D coordinates. | |
| Chebyshev distance is the maximum absolute difference along any dimension. | |
| Args: | |
| a: First 5D coordinate. | |
| b: Second 5D coordinate. | |
| Returns: | |
| The Chebyshev distance. | |
| """ | |
| return float(max(abs(ai - bi) for ai, bi in zip(a, b))) | |
| def manhattan_distance_5d(a: Coord5D, b: Coord5D) -> float: | |
| """Calculate the Manhattan distance between two 5D coordinates. | |
| Manhattan distance is the sum of absolute differences along each dimension. | |
| Args: | |
| a: First 5D coordinate. | |
| b: Second 5D coordinate. | |
| Returns: | |
| The Manhattan distance. | |
| """ | |
| return float(sum(abs(ai - bi) for ai, bi in zip(a, b))) | |
| # ============================================================================ | |
| # Neighbor Generation | |
| # ============================================================================ | |
| def neighbour_offsets(radius: float) -> tuple[Coord5D, ...]: | |
| """Generate all 5D offset vectors within a given radius. | |
| Results are cached for performance. | |
| Args: | |
| radius: Maximum distance from origin (inclusive). | |
| Returns: | |
| A tuple of 5D offset vectors (excluding the zero vector). | |
| Note: | |
| Only integer offsets are considered. The radius is effectively | |
| the Chebyshev radius (max coordinate difference). | |
| """ | |
| if radius <= 0: | |
| return () | |
| r = int(math.ceil(radius)) | |
| offsets: list[Coord5D] = [] | |
| for off in product(range(-r, r + 1), repeat=5): | |
| if off == (0, 0, 0, 0, 0): | |
| continue | |
| # Calculate squared distance directly from the offset | |
| sq_dist = sum(v * v for v in off) | |
| if math.sqrt(sq_dist) <= radius: | |
| offsets.append((off[0], off[1], off[2], off[3], off[4])) | |
| return tuple(offsets) | |
| def iter_neighbour_coords( | |
| coord: Coord5D, | |
| dimensions: Dim5D, | |
| radius: float, | |
| include_self: bool = False, | |
| ) -> Iterator[Coord5D]: | |
| """Iterate over all neighboring coordinates within a radius. | |
| Args: | |
| coord: Center coordinate. | |
| dimensions: 5D dimensions for bounds checking. | |
| radius: Search radius. | |
| include_self: Whether to include the center coordinate. | |
| Yields: | |
| Valid neighboring coordinates within the radius and dimensions. | |
| Example: | |
| >>> center = (5, 5, 5, 5, 5) | |
| >>> dims = (10, 10, 10, 10, 10) | |
| >>> for neighbor in iter_neighbour_coords(center, dims, 2.0): | |
| ... print(neighbor) | |
| """ | |
| validate_dims(dimensions) | |
| validate_coord_in_dims(coord, dimensions) | |
| for offset in neighbour_offsets(radius): | |
| candidate = tuple(c + oc for c, oc in zip(coord, offset)) | |
| if all(0 <= candidate[i] < dimensions[i] for i in range(5)): | |
| yield (candidate[0], candidate[1], candidate[2], candidate[3], candidate[4]) | |
| if include_self: | |
| yield coord | |
| def iter_linear_neighbours( | |
| center_idx: int, | |
| dims: Dim5D, | |
| radius: float, | |
| include_self: bool = False, | |
| ) -> Iterator[int]: | |
| """Iterate over linear indices of neighbors within a radius. | |
| Args: | |
| center_idx: Linear index of the center coordinate. | |
| dims: 5D dimensions. | |
| radius: Search radius. | |
| include_self: Whether to include the center index. | |
| Yields: | |
| Linear indices of neighboring coordinates. | |
| Example: | |
| >>> for idx in iter_linear_neighbours(12345, (10,10,10,10,10), 2.0): | |
| ... print(idx) | |
| """ | |
| center = linear_to_5d(center_idx, dims) | |
| for coord in iter_neighbour_coords(center, dims, radius, include_self): | |
| yield coords_to_linear(coord, dims) | |
| def neighbour_count(dims: Dim5D, radius: float) -> int: | |
| """Count the number of neighbors within a radius for a given dimension. | |
| Note: This is an upper bound estimate, as it doesn't account for boundary | |
| effects (coordinates at the edges have fewer neighbors). | |
| Args: | |
| dims: 5D dimensions. | |
| radius: Search radius. | |
| Returns: | |
| Maximum number of neighbors within the radius. | |
| """ | |
| offsets = neighbour_offsets(radius) | |
| return len(offsets) | |
| # ============================================================================ | |
| # Boundary Coordinates | |
| # ============================================================================ | |
| def make_boundary_coord( | |
| dims: Dim5D, | |
| dimension: str, | |
| value: int, | |
| ) -> Coord5D: | |
| """Create a coordinate on a specific dimension boundary. | |
| This is used for defining input and output layers on specific | |
| dimensions of the 5D space. | |
| Args: | |
| dims: 5D dimensions. | |
| dimension: Name of the dimension ('x', 'y', 'z', 'd4', 'd5'). | |
| value: Coordinate value on that dimension. | |
| Returns: | |
| A 5D coordinate with all other dimensions set to 0. | |
| Raises: | |
| ValueError: If the dimension name is unknown or the value is out of bounds. | |
| Example: | |
| >>> dims = (10, 10, 10, 10, 10) | |
| >>> make_boundary_coord(dims, 'x', 5) | |
| (5, 0, 0, 0, 0) | |
| """ | |
| if dimension not in DIM_NAMES: | |
| raise ValueError( | |
| f"Unknown dimension: {dimension}. " | |
| f"Valid dimensions: {', '.join(DIM_NAMES.keys())}" | |
| ) | |
| idx = DIM_NAMES[dimension] | |
| if value < 0 or value >= dims[idx]: | |
| raise ValueError( | |
| f"Value {value} outside dimension {dimension} (0-{dims[idx]-1})" | |
| ) | |
| coord = [0, 0, 0, 0, 0] | |
| coord[idx] = value | |
| return (coord[0], coord[1], coord[2], coord[3], coord[4]) | |
| def get_dimension_name(index: int) -> str | None: | |
| """Get the name of a dimension by its index. | |
| Args: | |
| index: Dimension index (0-4). | |
| Returns: | |
| Dimension name, or None if index is invalid. | |
| """ | |
| return DIM_INDICES.get(index) | |
| def get_dimension_index(name: str) -> int | None: | |
| """Get the index of a dimension by its name. | |
| Args: | |
| name: Dimension name ('x', 'y', 'z', 'd4', 'd5'). | |
| Returns: | |
| Dimension index, or None if name is invalid. | |
| """ | |
| return DIM_NAMES.get(name) | |
| # ============================================================================ | |
| # Utility Functions | |
| # ============================================================================ | |
| def total_cells(dims: Dim5D) -> int: | |
| """Calculate the total number of cells in the 5D grid. | |
| Args: | |
| dims: 5D dimensions. | |
| Returns: | |
| Product of all dimensions. | |
| """ | |
| total = 1 | |
| for d in dims: | |
| total *= d | |
| return total | |
| def linear_to_coords_batch( | |
| indices: Iterable[int], | |
| dims: Dim5D, | |
| ) -> Iterator[Coord5D]: | |
| """Convert multiple linear indices to coordinates. | |
| Args: | |
| indices: Iterable of linear indices. | |
| dims: 5D dimensions. | |
| Yields: | |
| 5D coordinates for each index. | |
| """ | |
| for idx in indices: | |
| yield linear_to_5d(idx, dims) | |
| def coords_to_linear_batch( | |
| coords: Iterable[Coord5D], | |
| dims: Dim5D, | |
| ) -> Iterator[int]: | |
| """Convert multiple coordinates to linear indices. | |
| Args: | |
| coords: Iterable of 5D coordinates. | |
| dims: 5D dimensions. | |
| Yields: | |
| Linear indices for each coordinate. | |
| """ | |
| for coord in coords: | |
| yield coords_to_linear(coord, dims) | |
| # ============================================================================ | |
| # Module Exports | |
| # ============================================================================ | |
| __all__ = [ | |
| # Type aliases | |
| "Coord5D", | |
| "Dim5D", | |
| # Constants | |
| "BITS_PER_DIM", | |
| "MASK", | |
| "SHIFTS", | |
| "DIM_NAMES", | |
| "DIM_INDICES", | |
| "MAX_COORD", | |
| # Validation | |
| "validate_coord", | |
| "validate_dims", | |
| "validate_coord_in_dims", | |
| "is_valid_coord", | |
| "is_valid_coord_in_dims", | |
| # Packing | |
| "pack_coords", | |
| "unpack_coords", | |
| # Linear conversion | |
| "coords_to_linear", | |
| "linear_to_5d", | |
| "linear_to_coord", | |
| "linear_to_coords_batch", | |
| "coords_to_linear_batch", | |
| # Distance | |
| "euclidean_distance_5d", | |
| "distance_5d", | |
| "weighted_distance_5d", | |
| "chebyshev_distance_5d", | |
| "manhattan_distance_5d", | |
| # Neighbors | |
| "neighbour_offsets", | |
| "iter_neighbour_coords", | |
| "iter_linear_neighbours", | |
| "neighbour_count", | |
| # Boundary | |
| "make_boundary_coord", | |
| "get_dimension_name", | |
| "get_dimension_index", | |
| # Utilities | |
| "total_cells", | |
| ] | |