137 std::vector<std::vector<Node_> > simple_hosts;
138 std::vector<std::vector<std::pair<Node_, Weight_> > > ranked_hosts;
141 ranked_hosts.resize(num_cells);
142 for (Index_ i = 0; i < num_cells; ++i) {
143 ranked_hosts[i].emplace_back(i, 0);
144 const auto& current = get_neighbors(i);
146 for (
auto x : current) {
147 ranked_hosts[get_index(x)].emplace_back(i, rank);
152 simple_hosts.resize(num_cells);
153 for (Index_ i = 0; i < num_cells; ++i) {
154 simple_hosts[i].emplace_back(i);
155 const auto& current = get_neighbors(i);
156 for (
auto x : current) {
157 simple_hosts[get_index(x)].emplace_back(i);
163 std::vector<std::vector<Node_> > edge_stores(num_cells);
164 std::vector<std::vector<Weight_> > weight_stores(num_cells);
167 std::vector<Weight_> current_score(num_cells);
168 std::vector<Node_> current_added;
169 current_added.reserve(num_cells);
171 for (Index_ j = start, end = start + length; j < end; ++j) {
172 const Node_ j_cast = j;
174 const auto& current_neighbors = get_neighbors(j);
175 auto nneighbors = current_neighbors.size();
177 for (decltype(nneighbors) i = 0; i <= nneighbors; ++i) {
180 const Node_ cur_neighbor = (i == 0 ? j : get_index(current_neighbors[i-1]));
185 if (options.weighting_scheme == SnnWeightScheme::RANKED) {
187 for (const auto& h : ranked_hosts[cur_neighbor]) {
188 auto othernode = h.first;
189 if (othernode < j_cast) {
190 auto& existing_other = current_score[othernode];
193 Weight_ currank = h.second + i_cast;
194 if (existing_other == 0) {
195 existing_other = currank;
196 current_added.push_back(othernode);
197 } else if (existing_other > currank) {
198 existing_other = currank;
204 for (const auto& othernode : simple_hosts[cur_neighbor]) {
205 if (othernode < j_cast) {
206 auto& existing_other = current_score[othernode];
209 if (existing_other == 0) {
210 current_added.push_back(othernode);
219 auto& current_edges = edge_stores[j];
220 current_edges.reserve(current_added.size() * 2);
221 auto& current_weights = weight_stores[j];
222 current_weights.reserve(current_added.size());
224 for (auto othernode : current_added) {
225 Weight_& otherscore = current_score[othernode];
227 if (options.weighting_scheme == SnnWeightScheme::RANKED) {
228 finalscore = static_cast<Weight_>(nneighbors) - 0.5 * static_cast<Weight_>(otherscore);
230 finalscore = otherscore;
231 if (options.weighting_scheme == SnnWeightScheme::JACCARD) {
232 finalscore = finalscore / (2 * (nneighbors + 1) - finalscore);
236 current_edges.push_back(j);
237 current_edges.push_back(othernode);
238 current_weights.push_back(std::max(finalscore, 1e-6));
243 current_added.clear();
248 std::size_t nedges = 0;
249 for (
const auto& w : weight_stores) {
253 output.num_cells = num_cells;
254 output.weights.clear();
255 output.weights.reserve(nedges);
256 for (
const auto& w : weight_stores) {
257 output.weights.insert(output.weights.end(), w.begin(), w.end());
259 weight_stores.clear();
260 weight_stores.shrink_to_fit();
262 output.edges.clear();
263 output.edges.reserve(nedges * 2);
264 for (
const auto& e : edge_stores) {
265 output.edges.insert(output.edges.end(), e.begin(), e.end());