condor-pathfinding-grid 0.4.0

Grid pathfinding, preprocessing, replanning, and multi-agent algorithms for Condor.
Documentation
//! Hierarchical build-once/query-many contracts for cluster abstraction and refinement.
//!
//! A [`HierarchicalGridBuilder`] snapshots a static grid into an abstract map; its
//! [`PreparedHierarchicalGrid`] answers repeated [`SearchRequest`]s with the normal
//! [`SearchResult`] contract. [`crate::HPAStarBuilder`] is the current implementation
//! and requires uniform traversal cost. Prefer [`crate::preprocessed_grid`] for
//! algorithm-neutral prepared maps that do not require hierarchical abstraction.

use crate::{
    grid::Grid,
    point::Point,
    search::{SearchRequest, SearchResult},
};

/// Preprocesses a static grid into a hierarchical search structure.
///
/// Implementations define how the grid is clustered and which abstract graph is
/// stored. Prep cost is paid once; query cost depends on cluster size and abstract
/// connectivity, not on re-scanning the full grid for every request.
pub trait HierarchicalGridBuilder {
    /// Immutable hierarchical map produced by this builder.
    type Map: PreparedHierarchicalGrid;

    /// Stable builder identity for reports and portfolios.
    fn name(&self) -> &'static str;

    /// Snapshot `grid` into a prepared hierarchical map.
    ///
    /// # Errors
    ///
    /// Returns [`HierarchicalGridBuildError`] when cluster parameters are invalid
    /// or the grid violates the builder's cost model (for example non-uniform
    /// `traversal_cost` for HPA*).
    fn preprocess(&self, grid: &Grid) -> Result<Self::Map, HierarchicalGridBuildError>;
}

/// Immutable hierarchical map that answers point-to-point grid searches.
///
/// Search uses the builder's abstract graph plus local refinement; the owned
/// grid snapshot (when present) is not mutated across queries.
pub trait PreparedHierarchicalGrid {
    /// Stable map identity (usually the builder name).
    fn name(&self) -> &'static str;

    /// Point-to-point search on the prepared hierarchical structure.
    ///
    /// Returns the same [`SearchResult`] shape as online grid pathfinders
    /// (validation errors, found path, or no-path with stats).
    fn search(&self, request: SearchRequest) -> SearchResult;
}

/// Hierarchical preprocess failed (cluster size or non-uniform costs).
#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
#[non_exhaustive]
pub enum HierarchicalGridBuildError {
    /// Cluster width/height must be positive for HPA*-style builders.
    #[error("HPA* cluster size must be greater than zero")]
    InvalidClusterSize,
    /// Hierarchical abstracts currently require unit `traversal_cost` on every walkable cell.
    #[error("HPA* supports only uniform-cost grids; cell {point:?} has traversal cost {cost}")]
    NonUniformCost { point: Point, cost: usize },
}