75 std::priority_queue<std::pair<HnswData_, hnswlib::labeltype> > my_queue;
77 static constexpr bool same_internal_data = std::is_same<Data_, HnswData_>::value;
78 std::vector<HnswData_> my_buffer;
85 if constexpr(!same_internal_data) {
86 my_buffer.resize(my_parent.my_dim);
94 void search(Index_ i, Index_ k, std::vector<Index_>* output_indices, std::vector<Distance_>* output_distances) {
95 my_buffer = my_parent.my_index.template getDataByLabel<HnswData_>(i);
97 my_queue = my_parent.my_index.searchKnn(my_buffer.data(), kp1);
100 output_indices->clear();
101 output_indices->reserve(kp1);
103 if (output_distances) {
104 output_distances->clear();
105 output_distances->reserve(kp1);
108 bool self_found =
false;
109 hnswlib::labeltype icopy = i;
110 while (!my_queue.empty()) {
111 const auto& top = my_queue.top();
112 if (!self_found && top.second == icopy) {
115 if (output_indices) {
116 output_indices->push_back(top.second);
118 if (output_distances) {
119 output_distances->push_back(top.first);
125 if (output_indices) {
126 std::reverse(output_indices->begin(), output_indices->end());
128 if (output_distances) {
129 std::reverse(output_distances->begin(), output_distances->end());
138 if (output_indices) {
139 output_indices->pop_back();
141 if (output_distances) {
142 output_distances->pop_back();
146 if (output_distances && my_parent.my_normalize) {
147 for (
auto& d : *output_distances) {
148 d = my_parent.my_normalize(d);
154 void search_raw(
const HnswData_* query, Index_ k, std::vector<Index_>* output_indices, std::vector<Distance_>* output_distances) {
155 k = std::min(k, my_parent.my_obs);
156 my_queue = my_parent.my_index.searchKnn(query, k);
158 if (output_indices) {
159 output_indices->resize(k);
161 if (output_distances) {
162 output_distances->resize(k);
166 while (!my_queue.empty()) {
167 const auto& top = my_queue.top();
169 if (output_indices) {
170 (*output_indices)[position] = top.second;
172 if (output_distances) {
173 (*output_distances)[position] = top.first;
178 if (output_distances && my_parent.my_normalize) {
179 for (
auto& d : *output_distances) {
180 d = my_parent.my_normalize(d);
186 void search(
const Data_* query, Index_ k, std::vector<Index_>* output_indices, std::vector<Distance_>* output_distances) {
187 if constexpr(same_internal_data) {
188 my_queue = my_parent.my_index.searchKnn(query, k);
189 search_raw(query, k, output_indices, output_distances);
191 std::copy_n(query, my_parent.my_dim, my_buffer.begin());
192 search_raw(my_buffer.data(), k, output_indices, output_distances);
214 template<
class Matrix_>
216 my_dim(data.num_dimensions()),
217 my_obs(data.num_observations()),
218 my_space(distance_config.
create(my_dim)),
222 auto work = data.new_extractor();
223 if constexpr(std::is_same<Data_, HnswData_>::value) {
224 for (Index_ i = 0; i < my_obs; ++i) {
225 auto ptr = work->next();
226 my_index.addPoint(ptr, i);
229 std::vector<HnswData_> incoming(my_dim);
230 for (Index_ i = 0; i < my_obs; ++i) {
231 auto ptr = work->next();
232 std::copy_n(ptr, my_dim, incoming.begin());
233 my_index.addPoint(incoming.data(), i);
250 std::shared_ptr<hnswlib::SpaceInterface<HnswData_> > my_space;
252 std::function<HnswData_(HnswData_)> my_normalize;
253 hnswlib::HierarchicalNSW<HnswData_> my_index;
255 friend class HnswSearcher<Index_, Data_, Distance_, HnswData_>;
258 std::size_t num_dimensions()
const {
262 Index_ num_observations()
const {
269 std::unique_ptr<knncolle::Searcher<Index_, Data_, Distance_> >
initialize()
const {
270 return std::make_unique<HnswSearcher<Index_, Data_, Distance_, HnswData_> >(*this);