//! Adaptive query planner for ANN search.
//!
//! Selects the optimal ANN strategy based on estimated filter selectivity --
//! the fraction of vectors that pass the user's filter predicate. The decision
//! tree follows the same pattern used by Qdrant, Weaviate, and Pinecone:
//!
//! - **High selectivity (>= 20%):** In-graph filtering with default `ef_search`.
//!   HNSW traversal skips non-matching nodes but still uses them for navigation,
//!   preserving recall.
//! - **Moderate selectivity (1-20%):** Widened `ef_search` to compensate for
//!   filter-induced recall loss. The beam is expanded by 2x (5-20%) or 3x (1-5%).
//! - **Extreme selectivity (< 1%):** Pre-filter to a candidate set, then
//!   brute-force exact search over the small filtered set.
//! - **No filter (100%):** Unfiltered HNSW search -- no predicate overhead.
//!
//! The planner does NOT self-tune thresholds at runtime. [`AnnQueryStats`]
//! captures per-query observability (selectivity, strategy chosen, latency,
//! result count) for external monitoring and analysis.
//!
//! # References
//!
//! - ACORN (Patel et al., Stanford, SIGMOD 2024): two-hop expansion for
//!   predicate-agnostic search. `WidenedFilter` approximates ACORN-1 by
//!   increasing beam width rather than graph density.
//! - `USearch` `filtered_search`: evaluates predicates during graph traversal.
//! - `docs/research/ann_for_tidaldb.md`: full analysis of the filtered ANN
//!   problem and why this adaptive approach converges with production systems.

mod config;
mod estimator;
mod executor;
mod stats;
mod strategy;

pub use config::PlannerConfig;
pub use estimator::{FixedSelectivityEstimator, SelectivityEstimator};
pub use executor::AdaptiveQueryPlanner;
pub use stats::AnnQueryStats;
pub use strategy::AnnStrategy;
