153 std::vector<std::vector<Node_> > simple_hosts;
154 std::vector<std::vector<std::pair<Node_, Weight_> > > ranked_hosts;
157 sanisizer::cast<Node_>(num_cells);
160 sanisizer::resize(ranked_hosts, num_cells);
161 for (Index_ i = 0; i < num_cells; ++i) {
162 ranked_hosts[i].emplace_back(i, 0);
163 const auto& current = get_neighbors(i);
165 for (
const auto& x : current) {
166 ranked_hosts[get_index(x)].emplace_back(i, rank);
171 sanisizer::resize(simple_hosts, num_cells);
172 for (Index_ i = 0; i < num_cells; ++i) {
173 simple_hosts[i].emplace_back(i);
174 const auto& current = get_neighbors(i);
175 for (
const auto& x : current) {
176 simple_hosts[get_index(x)].emplace_back(i);
182 auto edge_stores = sanisizer::create<std::vector<std::vector<Node_> > >(num_cells);
183 auto weight_stores = sanisizer::create<std::vector<std::vector<Weight_> > >(num_cells);
186 auto current_score = sanisizer::create<std::vector<Weight_> >(num_cells);
187 std::vector<Node_> current_added;
188 current_added.reserve(num_cells);
190 for (Index_ j = start, end = start + length; j < end; ++j) {
191 const auto& current_neighbors = get_neighbors(j);
192 const auto nneighbors = current_neighbors.size();
194 for (decltype(I(nneighbors)) i = 0; i <= nneighbors; ++i) {
197 const Node_ cur_neighbor = (i == 0 ? j : get_index(current_neighbors[i-1]));
202 if (options.weighting_scheme == SnnWeightScheme::RANKED) {
203 for (const auto& h : ranked_hosts[cur_neighbor]) {
204 const auto othernode = h.first;
205 if (othernode < static_cast<Node_>(j)) {
206 auto& existing_other = current_score[othernode];
209 const Weight_ currank = h.second + static_cast<Weight_>(i);
210 if (existing_other == 0) {
211 existing_other = currank;
212 current_added.push_back(othernode);
213 } else if (existing_other > currank) {
214 existing_other = currank;
220 for (const auto& othernode : simple_hosts[cur_neighbor]) {
221 if (othernode < static_cast<Node_>(j)) {
222 auto& existing_other = current_score[othernode];
225 if (existing_other == 0) {
226 current_added.push_back(othernode);
235 auto& current_edges = edge_stores[j];
236 current_edges.reserve(current_added.size() * 2);
237 auto& current_weights = weight_stores[j];
238 current_weights.reserve(current_added.size());
240 for (const auto othernode : current_added) {
241 current_edges.push_back(j);
242 current_edges.push_back(othernode);
244 Weight_& otherscore = current_score[othernode];
245 current_weights.push_back([&]{
246 if (options.weighting_scheme == SnnWeightScheme::RANKED) {
247 const Weight_ preliminary = static_cast<Weight_>(nneighbors) - otherscore / 2;
248 return std::max(preliminary, static_cast<Weight_>(1e-6));
249 } else if (options.weighting_scheme == SnnWeightScheme::JACCARD) {
250 return otherscore / (2 * (static_cast<Weight_>(nneighbors) + 1) - otherscore);
259 current_added.clear();
264 std::size_t nedges = 0;
265 for (
const auto& w : weight_stores) {
266 nedges = sanisizer::sum<std::size_t>(nedges, w.size());
269 output.num_cells = num_cells;
270 output.weights.clear();
271 output.weights.reserve(nedges);
272 for (
const auto& w : weight_stores) {
273 output.weights.insert(output.weights.end(), w.begin(), w.end());
275 weight_stores.clear();
276 weight_stores.shrink_to_fit();
278 output.edges.clear();
279 output.edges.reserve(nedges * 2);
280 for (
const auto& e : edge_stores) {
281 output.edges.insert(output.edges.end(), e.begin(), e.end());