From 5cf83543db3d0e0a26e4ceed896a0fe8cd23f12a Mon Sep 17 00:00:00 2001 From: Dirkjan Ochtman Date: Wed, 20 Jan 2021 16:29:33 +0100 Subject: [PATCH] Reduce unnecessary work to enforce invariants --- src/lib.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index b2134ba..5ecdcd1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -509,7 +509,6 @@ trait Layer { } } - search.nearest.sort_unstable(); search.nearest.truncate(search.ef); } @@ -526,6 +525,8 @@ pub struct Search { /// Candidates for further inspection (`C` in the paper) candidates: BinaryHeap>, /// Nearest neighbors found so far (`W` in the paper) + /// + /// This must always be in sorted (nearest first) order. nearest: Vec, /// Working set for heuristic selection working: Vec, @@ -562,7 +563,6 @@ impl Search { /// Selection of neighbors for insertion (algorithm 3 from the paper) fn select_simple(&mut self) -> &[Candidate] { - self.nearest.sort_unstable(); &self.nearest } @@ -593,7 +593,10 @@ impl Search { } } - self.working.sort_unstable(); + if params.extend_candidates { + self.working.sort_unstable(); + } + self.nearest.clear(); self.discarded.clear(); for candidate in self.working.drain(..) { @@ -625,7 +628,6 @@ impl Search { } } - self.nearest.sort_unstable(); &self.nearest } @@ -649,9 +651,6 @@ impl Search { self.nearest.insert(idx, new); self.candidates.push(Reverse(new)); - if self.nearest.len() > self.ef { - self.nearest.truncate(self.ef); - } } /// Lower the search to the next lower level @@ -659,11 +658,9 @@ impl Search { /// Re-initialize the `Search`: `nearest`, the output `W` from the last round, now becomes /// the set of enter points, which we use to initialize both `candidates` and `visited`. /// - /// Invariant: `nearest` should be sorted before this is called. This is generally the case - /// because `Layer::search()` is always called right before calling `cull()`. + /// Invariant: `nearest` should be sorted and truncated before this is called. This is generally + /// the case because `Layer::search()` is always called right before calling `cull()`. fn cull(&mut self) { - self.nearest.truncate(self.ef); // Limit size of the set of nearest neighbors - self.candidates.clear(); for &candidate in self.nearest.iter() { self.candidates.push(Reverse(candidate));