jubatus_core  0.1.2
Jubatus: Online machine learning framework for distributed environment
graph_wo_index.cpp
Go to the documentation of this file.
1 // Jubatus: Online machine learning framework for distributed environment
2 // Copyright (C) 2011,2012 Preferred Networks and Nippon Telegraph and Telephone Corporation.
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License version 2.1 as published by the Free Software Foundation.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
16 
17 #include <algorithm>
18 #include <iostream>
19 #include <map>
20 #include <string>
21 #include <utility>
22 #include <vector>
23 
24 #include "jubatus/util/data/unordered_set.h"
25 #include "jubatus/util/lang/cast.h"
26 
27 #include "graph_wo_index.hpp"
28 
29 using std::endl;
30 using std::map;
31 using std::pair;
32 using std::string;
33 using std::swap;
34 using std::vector;
35 using jubatus::util::lang::lexical_cast;
36 using jubatus::util::data::unordered_set;
37 
38 namespace jubatus {
39 namespace core {
40 namespace graph {
41 
42 namespace {
43 
44 bool is_empty_query(const preset_query& query) {
45  return query.node_query.empty() && query.edge_query.empty();
46 }
47 
48 bool is_matched_to_query(
49  const vector<pair<string, string> >& query,
50  const property& prop) {
51  for (size_t i = 0; i < query.size(); ++i) {
52  property::const_iterator it = prop.find(query[i].first);
53  if (it == prop.end() || it->second != query[i].second) {
54  return false;
55  }
56  }
57  return true;
58 }
59 
60 void normalize(eigen_vector_diff& v) {
61  double sum = 0;
62  for (eigen_vector_diff::const_iterator it = v.begin(); it != v.end(); ++it) {
63  sum += it->second.score;
64  }
65  const double normalizer = v.size() / sum;
66  for (eigen_vector_diff::iterator it = v.begin(); it != v.end(); ++it) {
67  it->second.score *= normalizer;
68  }
69 }
70 
71 } // namespace
72 
74  : config_(config) {
75 
76  if (!(0.0 < config.damping_factor && config.damping_factor < 1.0)) {
77  throw JUBATUS_EXCEPTION(
78  common::invalid_parameter("0.0 < damping_factor < 1.0"));
79  }
80 
81  if (!(0 <= config.landmark_num)) {
82  throw JUBATUS_EXCEPTION(
83  common::invalid_parameter("0 <= landmark_num"));
84  }
85 
86  clear();
87 }
88 
90  clear();
91 }
92 
94 }
95 
98 }
99 
101  local_nodes_.clear();
102  local_edges_.clear();
103  global_nodes_.clear();
104  eigen_scores_.clear();
105  spts_.clear();
106 }
107 
109  if (local_nodes_.count(id) > 0) {
111  }
112  local_nodes_[id] = node_info();
113  may_set_landmark(id);
114 }
115 
117  // Do we need it?
118  // if (id > 1) return;
119  for (spt_query_diff::iterator it = spts_.begin(); it != spts_.end(); ++it) {
120  spt_diff& mixed = it->second;
121  if (mixed.size() == static_cast<size_t>(config_.landmark_num)
122  || !is_node_matched_to_query(it->first, id)) {
123  return;
124  }
125 
126  shortest_path_tree spt;
127  spt.landmark = id;
128  mixed.push_back(spt);
129  }
130 }
131 
133  if (global_nodes_.count(id) > 0) {
135  }
136  global_nodes_[id] = 0;
137 }
138 
140  if (global_nodes_.count(id) == 0) {
141  throw JUBATUS_EXCEPTION(unknown_id("remove_global_node", id));
142  }
143  global_nodes_.erase(id);
144 }
145 
147  node_info_map::iterator it = local_nodes_.find(id);
148  if (it == local_nodes_.end()) {
149  throw JUBATUS_EXCEPTION(unknown_id("update_node", id));
150  }
151  it->second.property = p;
152  may_set_landmark(id);
153 }
154 
156  node_info ni;
157  try {
158  get_node(id, ni);
160  throw JUBATUS_EXCEPTION(unknown_id("remove_node", id));
161  }
162  if (ni.in_edges.size() > 0 || ni.out_edges.size() > 0) {
164  string("graph_wo_index::remove_node unknown id=")
165  + lexical_cast<string>(id)));
166  }
167  local_nodes_.erase(id);
168 }
169 
171  if (local_nodes_.find(src) == local_nodes_.end()
172  && local_nodes_.find(tgt) == local_nodes_.end()) {
173  throw JUBATUS_EXCEPTION(
174  unknown_id(
175  string("graph_wo_index::create_edge unknown src id=")
176  + lexical_cast<string>(src)
177  + " tgt id=" + lexical_cast<string>(tgt),
178  src));
179  }
180  if (local_edges_.count(eid) > 0) {
181  throw JUBATUS_EXCEPTION(edge_exists(eid));
182  }
183 
184  edge_info ei;
185  ei.src = src;
186  ei.tgt = tgt;
187  local_edges_[eid] = ei;
188  if (local_nodes_.count(src) > 0) {
189  local_nodes_[src].out_edges.push_back(eid);
190  }
191  if (local_nodes_.count(tgt) > 0) {
192  local_nodes_[tgt].in_edges.push_back(eid);
193  }
194 }
195 
197  edge_info_map::iterator it = local_edges_.find(eid);
198  if (it == local_edges_.end()) {
199  throw JUBATUS_EXCEPTION(unknown_id("update_edge:eid", eid));
200  }
201  it->second.p = p;
202 }
203 
205  edge_info_map::iterator it = local_edges_.find(eid);
206  if (it == local_edges_.end()) {
207  throw JUBATUS_EXCEPTION(unknown_id("remove_edge:eid", eid));
208  }
209  node_id_t src = it->second.src;
210  node_id_t tgt = it->second.tgt;
211 
212  if (local_nodes_.count(src) > 0) {
213  remove_by_swap(local_nodes_[src].out_edges, eid);
214  }
215  if (local_nodes_.count(tgt) > 0) {
216  remove_by_swap(local_nodes_[tgt].in_edges, eid);
217  }
218 
219  local_edges_.erase(it);
220 }
221 
223  eigen_scores_.insert(make_pair(query, eigen_vector_diff()));
224 }
225 
227  spts_.insert(make_pair(query, spt_diff()));
228 }
229 
231  eigen_scores_.erase(query);
232 }
233 
235  spts_.erase(query);
236 }
237 
239  node_id_t id,
240  centrality_type ct,
241  const preset_query& query) const {
242  if (ct == EIGENSCORE) {
243  eigen_vector_query_diff::const_iterator model_it
244  = eigen_scores_.find(query);
245  if (model_it == eigen_scores_.end()) {
247  }
248  eigen_vector_diff::const_iterator it = model_it->second.find(id);
249  if (it == model_it->second.end()) {
250  throw JUBATUS_EXCEPTION(unknown_id("centrality", id));
251  }
252  return it->second.score;
253  } else {
255  }
256 }
257 
259  node_id_t src,
260  node_id_t tgt,
261  uint64_t max_hop,
262  std::vector<node_id_t>& ret,
263  const preset_query& query) const {
264  if (global_nodes_.count(src) == 0) {
265  throw JUBATUS_EXCEPTION(unknown_id("shortest_path:src", src));
266  }
267  if (global_nodes_.count(tgt) == 0) {
268  throw JUBATUS_EXCEPTION(unknown_id("shortest_path:tgt", tgt));
269  }
270  spt_query_diff::const_iterator model_it = spts_.find(query);
271  if (model_it == spts_.end()) {
272  throw JUBATUS_EXCEPTION(unknown_query(query));
273  }
274  const spt_diff& mixed = model_it->second;
275  ret.clear();
276  uint64_t min_score = ~uint64_t();
277  uint64_t ind = ~uint64_t();
278  for (uint64_t i = 0; i < mixed.size(); ++i) {
279  const shortest_path_tree& spt = mixed[i];
280  spt_edges::const_iterator src_it = spt.to_root.find(src);
281  spt_edges::const_iterator tgt_it = spt.from_root.find(tgt);
282  if (src_it == spt.to_root.end() || tgt_it == spt.from_root.end()) {
283  continue;
284  }
285  uint64_t score = src_it->second.first + tgt_it->second.first;
286  if (score < min_score) {
287  min_score = score;
288  ind = i;
289  }
290  }
291 
292  if (ind >= static_cast<uint64_t>(config_.landmark_num)) {
293  return;
294  }
295 
296  const spt_edges& to_root = mixed[ind].to_root;
297  const spt_edges& from_root = mixed[ind].from_root;
298  uint64_t landmark = mixed[ind].landmark;
299 
300  for (uint64_t cur = src; cur != landmark;) {
301  if (ret.size() >= max_hop) {
302  return;
303  }
304  spt_edges::const_iterator it = to_root.find(cur);
305  if (it == to_root.end()) {
306  ret.clear();
307  return;
308  }
309  ret.push_back(cur);
310  if (cur == tgt) {
311  return;
312  }
313  cur = it->second.second;
314  }
315  ret.push_back(landmark);
316 
317  std::vector<node_id_t> from_root_path;
318  for (uint64_t cur = tgt; cur != landmark;) {
319  if (ret.size() + from_root_path.size() >= max_hop) {
320  return;
321  }
322  spt_edges::const_iterator it = from_root.find(cur);
323  if (it == from_root.end()) {
324  ret.clear();
325  return;
326  }
327  from_root_path.push_back(cur);
328  cur = it->second.second;
329  }
330 
331  for (vector<node_id_t>::const_reverse_iterator rit = from_root_path.rbegin();
332  rit != from_root_path.rend(); ++rit) {
333  ret.push_back(*rit);
334  }
335 }
336 
338  node_info_map::const_iterator it = local_nodes_.find(id);
339  if (it == local_nodes_.end()) {
340  throw JUBATUS_EXCEPTION(unknown_id("get_node", id));
341  }
342  ret = it->second;
343 }
344 
346  edge_info_map::const_iterator it = local_edges_.find(eid);
347  if (it == local_edges_.end()) {
348  throw JUBATUS_EXCEPTION(unknown_id("get_edge", eid));
349  }
350  ret = it->second;
351 }
352 
353 string graph_wo_index::type() const {
354  return string("graph_wo_index");
355 }
356 
358  packer.pack(*this);
359 }
360 
361 void graph_wo_index::unpack(msgpack::object o) {
362  o.convert(this);
363 }
364 
366  update_spt();
367  diff_type diff;
368  get_diff(diff);
369  put_diff(diff);
370 }
371 
373  diff.clear(); // tmp_diff + swap is better ?
374 
375  for (eigen_vector_query_diff::const_iterator query_it
376  = eigen_scores_.begin();
377  query_it != eigen_scores_.end(); ++query_it) {
378  const preset_query& query = query_it->first;
379  const eigen_vector_diff& model = query_it->second;
380 
381  double dist = 0;
382  for (eigen_vector_diff::const_iterator it = model.begin();
383  it != model.end(); ++it) {
384  if (it->second.out_degree_num == 0) {
385  dist += it->second.score;
386  }
387  }
388 
389  unordered_set<node_id_t> unmatched_nodes;
390 
391  uint64_t new_node_num = 0;
392  double dist_from_new_node = 0;
393  for (node_info_map::const_iterator node_it = local_nodes_.begin();
394  node_it != local_nodes_.end(); ++node_it) {
395  if (model.count(node_it->first) == 0) {
396  if (!is_matched_to_query(query.node_query, node_it->second.property)) {
397  unmatched_nodes.insert(node_it->first);
398  continue;
399  }
400  dist_from_new_node += 1.0;
401  ++new_node_num;
402  }
403  }
404  dist += dist_from_new_node;
405 
406  if (model.size() + new_node_num > 0) {
407  dist /= (model.size() + new_node_num);
408  }
409 
410  eigen_vector_diff& qdiff = diff[query];
411 
412  for (node_info_map::const_iterator node_it = local_nodes_.begin();
413  node_it != local_nodes_.end(); ++node_it) {
414  if (unmatched_nodes.count(node_it->first)) {
415  continue;
416  }
417  if (!is_matched_to_query(query.node_query, node_it->second.property)) {
418  unmatched_nodes.insert(node_it->first);
419  continue;
420  }
421 
422  const std::vector<edge_id_t>& in_edges = node_it->second.in_edges;
423  double score = 0;
424  for (size_t i = 0; i < in_edges.size(); ++i) {
425  if (unmatched_nodes.count(in_edges[i])) {
426  continue;
427  }
428  edge_info_map::const_iterator edge_it = local_edges_.find(in_edges[i]);
429  if (edge_it == local_edges_.end()) {
430  continue;
431  }
432 
433  const node_id_t src = edge_it->second.src;
434  if (unmatched_nodes.count(src)) {
435  continue;
436  }
437  if (!is_matched_to_query(query.edge_query, edge_it->second.p)) {
438  continue;
439  }
440 
441  eigen_vector_diff::const_iterator it = model.find(edge_it->second.src);
442  if (it == model.end()) {
443  continue;
444  }
445  if (it->second.out_degree_num != 0) {
446  // TODO(beam2d) it->second.score > 0 should indicate
447  // it->second.out_degree_num
448  score += it->second.score / it->second.out_degree_num;
449  }
450  }
451 
455 
456  if (is_empty_query(query)) {
457  ei.out_degree_num = node_it->second.out_edges.size();
458  } else {
459  uint64_t out_degree = 0;
460  for (size_t i = 0; i < node_it->second.out_edges.size(); ++i) {
461  const edge_info_map::const_iterator edge_it
462  = local_edges_.find(node_it->second.out_edges[i]);
463  const edge_info& edge = edge_it->second;
464  if (unmatched_nodes.count(edge.tgt)) {
465  continue;
466  }
467  if (!is_node_matched_to_query(query, edge.tgt)) {
468  unmatched_nodes.insert(edge.tgt);
469  continue;
470  }
471  if (!is_matched_to_query(query.edge_query, edge.p)) {
472  continue;
473  }
474  ++out_degree;
475  }
476  ei.out_degree_num = out_degree;
477  }
478 
479  qdiff[node_it->first] = ei;
480  }
481  }
482 }
483 
485  const eigen_vector_query_diff& mixed) {
486  eigen_scores_ = mixed;
487  if (eigen_scores_.size() == 0) {
488  return;
489  }
490 
491  // normalize
492  for (eigen_vector_query_diff::iterator model_it = eigen_scores_.begin();
493  model_it != eigen_scores_.end(); ++model_it) {
494  normalize(model_it->second);
495  }
496 }
497 
499  const preset_query& query,
500  spt_edges& se,
501  node_id_t landmark,
502  bool is_out) {
503  se[landmark] = std::make_pair(0, landmark);
504  for (node_info_map::const_iterator it = local_nodes_.begin();
505  it != local_nodes_.end(); ++it) {
506  if (!is_out) {
507  update_spt_node(query, it->second.out_edges, se, is_out);
508  } else {
509  update_spt_node(query, it->second.in_edges, se, is_out);
510  }
511  }
512 }
513 
515  const preset_query& query,
516  const std::vector<edge_id_t>& edges,
517  spt_edges& se,
518  bool is_out) {
519  for (size_t i = 0; i < edges.size(); ++i) {
520  edge_info& edge = local_edges_[edges[i]];
521  const node_id_t from = is_out ? edge.src : edge.tgt;
522  const node_id_t to = is_out ? edge.tgt : edge.src;
523 
524  if (!is_matched_to_query(query.edge_query, edge.p)
525  || !is_node_matched_to_query(query, from)
526  || !is_node_matched_to_query(query, to)) {
527  continue;
528  }
529 
530  spt_edges::iterator tr_it = se.find(from);
531  if (tr_it != se.end()) {
532  uint64_t dist = tr_it->second.first + 1;
533  spt_edges::iterator tr_jt = se.find(to);
534  if (tr_jt != se.end()) {
535  if (dist < tr_jt->second.first) {
536  tr_jt->second.first = dist;
537  tr_jt->second.second = from;
538  }
539  } else {
540  se.insert(std::make_pair(to, std::make_pair(dist, from)));
541  }
542  }
543  }
544 }
545 
547  const preset_query& query,
548  node_id_t id) const {
549  node_info_map::const_iterator it = local_nodes_.find(id);
550  if (it == local_nodes_.end()) {
551  return true;
552  }
553  return is_matched_to_query(query.node_query, it->second.property);
554 }
555 
557  for (spt_query_diff::iterator it = spts_.begin(); it != spts_.end(); ++it) {
558  spt_diff& mixed = it->second;
559  for (size_t i = 0; i < mixed.size(); ++i) {
560  shortest_path_tree& spt = mixed[i];
561  update_spt_edges(it->first, spt.to_root, spt.landmark, false);
562  update_spt_edges(it->first, spt.from_root, spt.landmark, true);
563  }
564  }
565 }
566 
568  spt_query_diff& all_diff) const {
569  all_diff.clear();
570 
571  for (spt_query_diff::const_iterator it = spts_.begin(); it != spts_.end();
572  ++it) {
573  const spt_diff& mixed = it->second;
574  spt_diff& diff = all_diff[it->first];
575  diff.resize(mixed.size());
576 
577  for (uint64_t i = 0; i < mixed.size(); ++i) {
578  const shortest_path_tree& spt = mixed[i];
579  if (spt.landmark == LLONG_MAX) {
580  continue;
581  }
582  diff[i].landmark = spt.landmark;
583 
584  for (node_info_map::const_iterator it = local_nodes_.begin();
585  it != local_nodes_.end(); ++it) {
586  const node_id_t id = it->first;
587 
588  spt_edges::const_iterator from_it = spt.from_root.find(id);
589  if (from_it != spt.from_root.end()) {
590  diff[i].from_root[id] = from_it->second;
591  }
592 
593  spt_edges::const_iterator to_it = spt.to_root.find(id);
594  if (to_it != spt.to_root.end()) {
595  diff[i].to_root[id] = to_it->second;
596  }
597  }
598  }
599  }
600 }
601 
603  const spt_query_diff& mixed) {
604  spts_ = mixed;
605 }
606 
608  // get_diff should be constant
609  const_cast<graph_wo_index*>(this)->update_spt();
610 
613 }
614 
618  return true;
619 }
620 
621 void graph_wo_index::get_status(map<string, string>& status) const {
622  status["local_node_num"] = lexical_cast<string>(local_nodes_.size());
623  status["global_node_num"] = lexical_cast<string>(global_nodes_.size());
624  status["local_edge_num"] = lexical_cast<string>(local_edges_.size());
625 }
626 
627 void graph_wo_index::mix(const diff_type& diff, diff_type& mixed) {
630 }
631 
633  const eigen_vector_query_diff& diff,
634  eigen_vector_query_diff& mixed) {
635  for (eigen_vector_query_diff::const_iterator model_it = diff.begin();
636  model_it != diff.end(); ++model_it) {
637  eigen_vector_diff& evm = mixed[model_it->first];
638  for (eigen_vector_diff::const_iterator it = model_it->second.begin();
639  it != model_it->second.end(); ++it) {
640  evm[it->first] = it->second;
641  }
642  }
643 }
644 
646  const shortest_path_tree& diff,
647  shortest_path_tree& mixed) {
648  for (spt_edges::const_iterator it = diff.from_root.begin();
649  it != diff.from_root.end(); ++it) {
650  mixed.from_root[it->first] = it->second;
651  }
652 
653  for (spt_edges::const_iterator it = diff.to_root.begin();
654  it != diff.to_root.end(); ++it) {
655  mixed.to_root[it->first] = it->second;
656  }
657 }
658 
660  const spt_query_diff& all_diff,
661  spt_query_diff& all_mixed,
662  size_t landmark_num) {
663  for (spt_query_diff::const_iterator it = all_diff.begin();
664  it != all_diff.end(); ++it) {
665  const spt_diff& diff = it->second;
666  spt_diff& mixed = all_mixed[it->first];
667 
668  map<node_id_t, uint64_t> diff_landmark2ind;
669  for (uint64_t i = 0; i < diff.size(); ++i) {
670  if (diff[i].landmark != LLONG_MAX) {
671  diff_landmark2ind[diff[i].landmark] = i;
672  }
673  }
674 
675  map<node_id_t, uint64_t> mixed_landmark2ind;
676  for (uint64_t i = 0; i < mixed.size(); ++i) {
677  if (mixed[i].landmark != LLONG_MAX) {
678  mixed_landmark2ind[mixed[i].landmark] = i;
679  }
680  }
681 
682  for (map<node_id_t, uint64_t>::const_iterator it
683  = diff_landmark2ind.begin(); it != diff_landmark2ind.end(); ++it) {
684  map<node_id_t, uint64_t>::iterator jt
685  = mixed_landmark2ind.find(it->first);
686  if (jt != mixed_landmark2ind.end()) {
687  mix_spt(diff[it->second], mixed[jt->second]);
688  } else if (mixed.size() < landmark_num) {
689  mixed.push_back(diff[it->second]);
690  }
691  }
692  }
693 }
694 
696  std::vector<edge_id_t>& edges,
697  edge_id_t eid) {
698  for (size_t i = 0; i < edges.size(); ++i) {
699  if (edges[i] == eid) {
700  if (i + 1 < edges.size()) {
701  swap(edges[i], edges.back());
702  }
703  edges.resize(edges.size() - 1);
704  return;
705  }
706  }
707 }
708 
709 } // namespace graph
710 } // namespace core
711 } // namespace jubatus
void update_spt_node(const preset_query &query, const std::vector< edge_id_t > &edges, spt_edges &se, bool is_out)
jubatus::util::data::unordered_map< node_id_t, eigen_vector_info > eigen_vector_diff
Definition: graph_type.hpp:53
std::vector< std::pair< std::string, std::string > > edge_query
Definition: graph_type.hpp:73
jubatus::util::data::unordered_map< preset_query, eigen_vector_diff > eigen_vector_query_diff
Definition: graph_type.hpp:97
void shortest_path(node_id_t src, node_id_t tgt, uint64_t max_hop, std::vector< node_id_t > &ret, const preset_query &) const
void get_diff_shortest_path_tree(spt_query_diff &diff) const
void get_status(std::map< std::string, std::string > &status) const
double dist(const common::sfv_t &p1, const common::sfv_t &p2)
Definition: util.cpp:151
void get_edge(edge_id_t eid, edge_info &ret) const
void add_centrality_query(const preset_query &)
std::vector< std::pair< std::string, std::string > > node_query
Definition: graph_type.hpp:74
static void mix_spt(const shortest_path_tree &diff, shortest_path_tree &mixed)
void mix(const diff_type &diff, diff_type &mixed)
std::vector< edge_id_t > in_edges
Definition: graph_type.hpp:57
jubatus::util::data::unordered_map< preset_query, spt_diff > spt_query_diff
Definition: graph_type.hpp:100
static void remove_by_swap(std::vector< edge_id_t > &edges, edge_id_t eid)
#define JUBATUS_EXCEPTION(e)
Definition: exception.hpp:79
void remove_shortest_path_query(const preset_query &)
jubatus::util::data::unordered_map< node_id_t, uint8_t > global_nodes_
void update_node(node_id_t id, const property &p)
std::vector< shortest_path_tree > spt_diff
Definition: graph_type.hpp:94
std::map< std::string, std::string > property
Definition: graph_type.hpp:39
double centrality(node_id_t id, centrality_type ct, const preset_query &) const
void swap(weighted_point &p1, weighted_point &p2)
Definition: types.hpp:47
void pack(framework::packer &packer) const
bool put_diff(const diff_type &mixed)
void get_node(node_id_t id, node_info &ret) const
msgpack::packer< jubatus_packer > packer
Definition: bandit_base.hpp:31
void update_spt_edges(const preset_query &query, spt_edges &se, node_id_t landmark, bool is_out)
void update_edge(edge_id_t eid, const property &p)
std::vector< edge_id_t > out_edges
Definition: graph_type.hpp:58
void create_edge(edge_id_t eid, node_id_t src, node_id_t tgt)
std::vector< T > v(size)
double sum(const common::sfv_t &p)
Definition: util.cpp:47
void put_diff_eigen_score(const eigen_vector_query_diff &mixed)
void remove_centrality_query(const preset_query &)
void put_diff_shortest_path_tree(const spt_query_diff &mixed)
eigen_vector_query_diff eigen_scores_
void get_diff(diff_type &diff) const
jubatus::util::data::unordered_map< node_id_t, std::pair< uint64_t, node_id_t > > spt_edges
Definition: graph_type.hpp:84
void get_diff_eigen_score(eigen_vector_query_diff &diff) const
bool is_node_matched_to_query(const preset_query &query, node_id_t id) const
void add_shortest_path_query(const preset_query &)