MCPcopy Create free account
hub / github.com/NodeDB-Lab/nodedb / expand_directed

Function expand_directed

nodedb-vector/src/navix/traversal.rs:338–396  ·  view source on GitHub ↗
(
    index: &HnswIndex,
    query: &[f32],
    neighbors_1hop: &[u32],
    allowed: &RoaringBitmap,
    ef: usize,
    metric: nodedb_types::vector_distance::DistanceMetric,
    visited: &mut HashSet

Source from the content-addressed store, hash-verified

336/// then expand that neighbor's 2-hop neighbors into the heaps.
337#[allow(clippy::too_many_arguments)]
338fn expand_directed(
339 index: &HnswIndex,
340 query: &[f32],
341 neighbors_1hop: &[u32],
342 allowed: &RoaringBitmap,
343 ef: usize,
344 metric: nodedb_types::vector_distance::DistanceMetric,
345 visited: &mut HashSet<u32>,
346 candidates: &mut BinaryHeap<Reverse<Candidate>>,
347 results: &mut BinaryHeap<Candidate>,
348) {
349 // Score 1-hop; track the best allowed neighbor.
350 let mut best_allowed: Option<(u32, f32)> = None;
351
352 for &nb in neighbors_1hop {
353 let already_visited = !visited.insert(nb);
354 if already_visited {
355 continue;
356 }
357 let d = dist(index, query, nb, metric);
358 let nb_cand = Candidate { dist: d, id: nb };
359
360 let worst_dist = results.peek().map_or(f32::INFINITY, |w| w.dist);
361 if d < worst_dist || results.len() < ef {
362 candidates.push(Reverse(nb_cand));
363 }
364
365 if !index.is_deleted(nb) && allowed.contains(nb) {
366 if best_allowed.is_none_or(|(_, bd)| d < bd) {
367 best_allowed = Some((nb, d));
368 }
369 results.push(nb_cand);
370 if results.len() > ef {
371 results.pop();
372 }
373 }
374 }
375
376 // Expand 2-hop of the single best allowed neighbor.
377 if let Some((best_id, _)) = best_allowed {
378 for &nb2 in index.neighbors_at(best_id, 0) {
379 if !visited.insert(nb2) {
380 continue;
381 }
382 let d = dist(index, query, nb2, metric);
383 let nb2_cand = Candidate { dist: d, id: nb2 };
384 let worst_dist = results.peek().map_or(f32::INFINITY, |w| w.dist);
385 if d < worst_dist || results.len() < ef {
386 candidates.push(Reverse(nb2_cand));
387 }
388 if !index.is_deleted(nb2) && allowed.contains(nb2) {
389 results.push(nb2_cand);
390 if results.len() > ef {
391 results.pop();
392 }
393 }
394 }
395 }

Callers 1

navix_search_layer_0Function · 0.85

Calls 8

distFunction · 0.85
insertMethod · 0.45
peekMethod · 0.45
lenMethod · 0.45
pushMethod · 0.45
is_deletedMethod · 0.45
containsMethod · 0.45
neighbors_atMethod · 0.45

Tested by

no test coverage detected