///|
/// One measured beam width from `Hnsw::calibrate_ef`.
pub struct EfTrial {
/// Beam width tested (must be at least k).
ef : Int32
/// Mean recall@k across the representative queries, against an exact scan
/// of live vectors using the index's own distance semantics. Neighbors tied
/// at the exact kth distance count as correct.
recall : Double
/// Mean distance computations per approximate query, excluding the exact
/// ground-truth scan.
avg_distance_computations : Double
} derive(Eq, @debug.Debug, ToJson)
///|
pub extend EfTrial with Eq::{not_equal, equal}
///|
pub extend EfTrial with @moonbitlang/core/debug.Debug::{to_repr}
///|
pub extend EfTrial with ToJson::{to_json}
///|
/// Empirical recall/cost curve for a set of query samples.
pub struct EfCalibration {
/// Smallest tested ef that met the target, or the largest tested ef when
/// no trial met it.
selected_ef : Int32
/// Whether the selected trial reached the requested target recall.
met_target : Bool
/// Trial results in ascending ef order.
trials : Array[EfTrial]
} derive(Eq, @debug.Debug, ToJson)
///|
pub extend EfCalibration with Eq::{not_equal, equal}
///|
pub extend EfCalibration with @moonbitlang/core/debug.Debug::{to_repr}
///|
pub extend EfCalibration with ToJson::{to_json}
///|
/// Measures recall@k and distance work for each candidate `ef`, then picks
/// the smallest width meeting `target_recall`. When none meets it, selects
/// the largest width and sets `met_target` to false.
///
/// `queries` must be nonempty and representative of production traffic;
/// measured recall is specific to those queries and this index state. `efs`
/// must be nonempty, strictly increasing, and each value at least `k`.
/// Ground truth is an exact top-k scan of non-deleted vectors using the same
/// metric and, for frozen SQ8, the same stored-vector distance as search.
/// Any result tied at the exact kth distance counts as a correct neighbor.
/// The stored `distance_computations()` after this call is the total work of
/// the approximate trial searches, excluding ground-truth scans.
pub fn Hnsw::calibrate_ef(
self : Hnsw,
queries : Array[FixedArray[Float]],
k : Int32,
target_recall : Double,
efs : Array[Int32],
) -> EfCalibration raise HnswError {
if k <= 0 || self.alive_count == 0 || queries.is_empty() || efs.is_empty() {
raise InvalidParams("calibration needs live vectors, queries, k, and efs")
}
if !(target_recall >= 0.0 && target_recall <= 1.0) {
raise InvalidParams("target_recall must be within [0, 1]")
}
let mut previous = 0
for ef in efs {
if ef < k || ef <= previous {
raise InvalidParams("efs must be strictly increasing and >= k")
}
previous = ef
}
for q in queries {
if q.length() != self.dim {
raise DimMismatch(self.dim, q.length())
}
validate_finite_vector(q)
}
let truth_k = if k < self.alive_count { k } else { self.alive_count }
let thresholds : Array[Double] = []
for query in queries {
let nearest = self.search_exact(query, truth_k)
thresholds.push(nearest[nearest.length() - 1].distance)
}
let trials : Array[EfTrial] = []
let mut selected_ef = efs[efs.length() - 1]
let mut met_target = false
let mut total_trial_calls = 0L
for ef in efs {
let mut hits = 0
let mut calls = 0L
for i in 0..= target_recall {
selected_ef = ef
met_target = true
}
}
self.dist_calls = total_trial_calls
{ selected_ef, met_target, trials, }
}