Beam search at layer 0 using `fast_symmetric_distance`. Returns candidates sorted ascending by symmetric distance (used only for routing; final ranking is done by `exact_asymmetric_distance` in the caller).
(&self, q_enc: &C::Quantized, ep_idx: u32, ef: usize)
| 135 | /// for routing; final ranking is done by `exact_asymmetric_distance` in |
| 136 | /// the caller). |
| 137 | fn search_layer_0(&self, q_enc: &C::Quantized, ep_idx: u32, ef: usize) -> Vec<Cand> { |
| 138 | let mut visited: HashSet<u32> = HashSet::new(); |
| 139 | visited.insert(ep_idx); |
| 140 | |
| 141 | let ep_dist = self |
| 142 | .codec |
| 143 | .fast_symmetric_distance(q_enc, &self.nodes[ep_idx as usize].quantized); |
| 144 | let ep_cand = Cand { |
| 145 | dist: ep_dist, |
| 146 | idx: ep_idx, |
| 147 | }; |
| 148 | |
| 149 | let mut candidates: BinaryHeap<Reverse<Cand>> = BinaryHeap::new(); |
| 150 | candidates.push(Reverse(ep_cand)); |
| 151 | |
| 152 | let mut results: BinaryHeap<Cand> = BinaryHeap::new(); |
| 153 | if !self.nodes[ep_idx as usize].deleted { |
| 154 | results.push(ep_cand); |
| 155 | } |
| 156 | |
| 157 | while let Some(Reverse(cur)) = candidates.pop() { |
| 158 | let worst = results.peek().map_or(f32::INFINITY, |w| w.dist); |
| 159 | if cur.dist > worst && results.len() >= ef { |
| 160 | break; |
| 161 | } |
| 162 | |
| 163 | for &nb in self.neighbors_at(cur.idx, 0) { |
| 164 | if !visited.insert(nb) { |
| 165 | continue; |
| 166 | } |
| 167 | let d = self |
| 168 | .codec |
| 169 | .fast_symmetric_distance(q_enc, &self.nodes[nb as usize].quantized); |
| 170 | let worst_now = results.peek().map_or(f32::INFINITY, |w| w.dist); |
| 171 | if d < worst_now || results.len() < ef { |
| 172 | candidates.push(Reverse(Cand { dist: d, idx: nb })); |
| 173 | } |
| 174 | if !self.nodes[nb as usize].deleted { |
| 175 | results.push(Cand { dist: d, idx: nb }); |
| 176 | if results.len() > ef { |
| 177 | results.pop(); |
| 178 | } |
| 179 | } |
| 180 | } |
| 181 | } |
| 182 | |
| 183 | let mut out: Vec<Cand> = results.into_vec(); |
| 184 | out.sort_unstable_by(|a, b| a.dist.total_cmp(&b.dist)); |
| 185 | out |
| 186 | } |
| 187 | } |
| 188 | |
| 189 | // ── Tests ───────────────────────────────────────────────────────────────────── |
no test coverage detected