ATSuite C++  v1.0
Scientific C++ routines originally developed by Alexis Tantet
atgraph.hpp
1 #ifndef ATGRAPH_HPP
2 #define ATGRAPH_HPP
3 
4 #include <cstdio>
5 #include <cstdlib>
6 #include <stack>
7 #include <vector>
8 #include <iostream>
9 #include <igraph/igraph.h>
10 #include <Eigen/Dense>
11 #include <Eigen/Sparse>
12 #include <atio.hpp>
13 
14 typedef Eigen::SparseMatrix<double> SpMat;
15 typedef Eigen::SparseMatrix<double, RowMajor> SpMatCSR;
16 typedef Eigen::Triplet<double> Tri;
17 
18 
19 int pajek2igraph(FILE *f, igraph_t * dst_graph){
20  char label[20];
21  int N, E;
22  int vertex_id, vertex_id2, vertex_id0;
23  double edge_weight;
24 
25  igraph_vector_t vertices, edges, weights;
26 
27 
28  // Read vertices
29  fscanf(f, "%s %d", label, &N);
30  igraph_vector_init(&vertices, N);
31  // Read first (assume monotonous)
32  fscanf(f, "%d %s", &vertex_id0, label);
33  igraph_vector_set(&vertices, 0, 0.);
34  for (long int i = 1; i < N; i++){
35  fscanf(f, "%d %s", &vertex_id, label);
36  igraph_vector_set(&vertices, i, vertex_id - vertex_id0);
37  }
38 
39  // Initialize empty directed graph
40  igraph_empty(dst_graph, N, IGRAPH_DIRECTED);
41 
42  // Read Edges
43  fscanf(f, "%s %d", label, &E);
44  igraph_vector_init(&edges, E * 2);
45  igraph_vector_init(&weights, E);
46 
47  for (long int i = 0; i < E; i++){
48  fscanf(f, "%d %d %lf", &vertex_id, &vertex_id2, &edge_weight);
49  igraph_vector_set(&edges, i*2, vertex_id - vertex_id0);
50  igraph_vector_set(&edges, i*2+1, vertex_id2 - vertex_id0);
51  igraph_vector_set(&weights, i, edge_weight);
52  }
53 
54  // Add edges
55  igraph_add_edges(dst_graph, &edges, 0);
56 
57  // Add weight attribute
58  igraph_cattribute_EAN_setv(dst_graph, "weight", &weights);
59 
60  // Clean-up
61  fclose(f);
62  igraph_vector_destroy(&edges);
63  igraph_vector_destroy(&vertices);
64 
65  return 0;
66 }
67 
68 
69 int pajek2igraphNoVertices(FILE *f, igraph_t * dst_graph, int vertex_id0){
70  char label[20];
71  int N, E;
72  int vertex_id, vertex_id2;
73  double edge_weight;
74 
75  igraph_vector_t vertices, edges, weights;
76 
77 
78  // Read vertices
79  fscanf(f, "%s %d", label, &N);
80  igraph_vector_init(&vertices, N);
81  // Read first (assume monotonous)
82  for (long int i = 0; i < N; i++){
83  igraph_vector_set(&vertices, i, i);
84  }
85 
86  // Initialize empty directed graph
87  igraph_empty(dst_graph, N, IGRAPH_DIRECTED);
88 
89  // Read Edges
90  fscanf(f, "%s %d", label, &E);
91  igraph_vector_init(&edges, E * 2);
92  igraph_vector_init(&weights, E);
93 
94  for (long int i = 0; i < E; i++){
95  fscanf(f, "%d %d %lf", &vertex_id, &vertex_id2, &edge_weight);
96  igraph_vector_set(&edges, i*2, vertex_id - vertex_id0);
97  igraph_vector_set(&edges, i*2+1, vertex_id2 - vertex_id0);
98  igraph_vector_set(&weights, i, edge_weight);
99  }
100 
101  // Add edges
102  igraph_add_edges(dst_graph, &edges, 0);
103 
104  // Add weight attribute
105  igraph_cattribute_EAN_setv(dst_graph, "weight", &weights);
106 
107  // Clean-up
108  fclose(f);
109  igraph_vector_destroy(&edges);
110  igraph_vector_destroy(&vertices);
111 
112  return 0;
113 }
114 
115 
116 int pajek2igraphSym(FILE *f, igraph_t * dst_graph){
117  char label[20];
118  int N, E;
119  int vertex_id, vertex_id2, vertex_id0;
120  double edge_weight;
121 
122  igraph_vector_t vertices, edges, weights;
123 
124 
125  // Read vertices
126  fscanf(f, "%s %d", label, &N);
127  igraph_vector_init(&vertices, N);
128  // Read first (assume monotonous)
129  fscanf(f, "%d %s", &vertex_id0, label);
130  igraph_vector_set(&vertices, 0, 0.);
131  for (long int i = 1; i < N; i++){
132  fscanf(f, "%d %s", &vertex_id, label);
133  igraph_vector_set(&vertices, i, vertex_id - vertex_id0);
134  }
135 
136  // Initialize empty directed graph
137  igraph_empty(dst_graph, N, IGRAPH_UNDIRECTED);
138 
139  // Read Edges
140  fscanf(f, "%s %d", label, &E);
141  igraph_vector_init(&edges, E * 2);
142  igraph_vector_init(&weights, E);
143 
144  for (long int i = 0; i < E; i++){
145  fscanf(f, "%d %d %lf", &vertex_id, &vertex_id2, &edge_weight);
146  igraph_vector_set(&edges, i*2, vertex_id - vertex_id0);
147  igraph_vector_set(&edges, i*2+1, vertex_id2 - vertex_id0);
148  igraph_vector_set(&weights, i, edge_weight);
149  }
150 
151  // Add edges
152  igraph_add_edges(dst_graph, &edges, 0);
153 
154  // Add weight attribute
155  igraph_cattribute_EAN_setv(dst_graph, "weight", &weights);
156 
157  // Clean-up
158  fclose(f);
159  igraph_vector_destroy(&edges);
160  igraph_vector_destroy(&vertices);
161 
162  return 0;
163 }
164 
165 
166 SpMat * pajek2EigenSparse(FILE *f){
167  char label[20];
168  int N, E;
169  int i, j, i0;
170  double x;
171 
172  vector<Tri> tripletList;
173 
174  // Read vertices
175  fscanf(f, "%s %d", label, &N);
176 
177  // Define sparse matrix
178  SpMat *T = new SpMat(N, N);
179 
180  // Read first (assume monotonous)
181  fscanf(f, "%d %s", &i0, label);
182  for (int k = 1; k < N; k++){
183  fscanf(f, "%d %s", &i, label);
184  }
185 
186  // Read Edges
187  fscanf(f, "%s %d", label, &E);
188 
189  // Reserve triplet capacity
190  tripletList.reserve(E);
191 
192  for (int k = 0; k < E; k++){
193  fscanf(f, "%d %d %lf", &i, &j, &x);
194  tripletList.push_back(Tri(i - i0, j - i0, x));
195  }
196 
197  // Assign matrix elements
198  T->setFromTriplets(tripletList.begin(), tripletList.end());
199 
200  return T;
201 }
202 
203 
204 void EigenSparse2Pajek(FILE *f, SpMatCSR *P){
205  int N = P->rows();
206  int E = P->nonZeros();
207 
208  // Write vertices
209  fprintf(f, "*Vertices %d\n", N);
210  for (int k = 0; k < N; k++)
211  fprintf(f, "%d ""%d""\n", k, k);
212 
213  // Write Edges
214  fprintf(f, "Edges %d\n", E);
215  for (int i = 0; i < P->rows(); i++)
216  for (SpMatCSR::InnerIterator it(*P, i); it; ++it)
217  fprintf(f, "%d %d %lf\n", i, it.col(), it.value());
218 
219  return;
220 }
221 
222 
223 SpMat * igraph2EigenSparse(igraph_t *srcGraph)
224 {
225  igraph_integer_t N, E;
226  igraph_vector_t edges, weights;
227 
228  // Get edge list and weights
229  N = igraph_vcount(srcGraph);
230  E = igraph_ecount(srcGraph);
231  igraph_vector_init(&edges, E * 2);
232  igraph_vector_init(&weights, E);
233  igraph_get_edgelist(srcGraph, &edges, true);
234  if ((bool) igraph_cattribute_has_attr(srcGraph, IGRAPH_ATTRIBUTE_EDGE, "weight"))
235  EANV(srcGraph, "weight", &weights);
236  else
237  igraph_vector_fill(&weights, 1.);
238 
239  // Get triplet list from igraph graph
240  vector<Tri> tripletList;
241  for (int k = 0; k < E; k++)
242  tripletList.push_back(Tri(VECTOR(edges)[k], VECTOR(edges)[E+k],
243  VECTOR(weights)[k]));
244 
245  // Define sparse matrix
246  SpMat *T = new SpMat(N, N);
247  // Assign matrix elements
248  T->setFromTriplets(tripletList.begin(), tripletList.end());
249 
250  igraph_vector_destroy(&edges);
251 
252  return T;
253 }
254 
255 
256 int array2igraph(FILE *f, int N, igraph_t * dst_graph){
257  double edge_weight;
258  int i, j;
259 
260  igraph_vector_t vertices, edges, weights;
261 
262  // Initialize empty directed graph
263  igraph_vector_init(&vertices, N);
264  igraph_vector_init(&edges, N*N*2);
265  igraph_vector_init(&weights, N*N);
266  igraph_empty(dst_graph, N, IGRAPH_DIRECTED);
267 
268  for (i = 0; i < N; i++){
269  igraph_vector_set(&vertices, i, i);
270  for (j = 0; j < N; j++){
271  fscanf(f, "%lf", &edge_weight);
272  igraph_vector_set(&edges, (i*N+j)*2, i);
273  igraph_vector_set(&edges, (i*N+j)*2+1, j);
274  igraph_vector_set(&weights, i*N+j, edge_weight);
275  }
276  }
277 
278  // Add edges
279  igraph_add_edges(dst_graph, &edges, 0);
280  // Add weight attribute
281  igraph_cattribute_EAN_setv(dst_graph, "weight", &weights);
282 
283  // Clean-up
284  fclose(f);
285  igraph_vector_destroy(&edges);
286  igraph_vector_destroy(&vertices);
287 
288  return 0;
289 }
290 
291 void addCol2Col(SpMat *T, int j_src, int j_dst)
292 {
293  stack<double> insertValue;
294  stack<int> insertRow;
295 
296  // Iterate over elements of column j_src
297  for (SpMat::InnerIterator it_src(*T, j_src); it_src; ++it_src){
298  // Try to find element (i_src = it_src.row(), j_dst)
299  SpMat::InnerIterator it_dst(*T, j_dst);
300  for (; it_dst && (it_dst.row() < it_src.row()); ++it_dst);
301  if (it_dst && (it_dst.row() == it_src.row()))
302  it_dst.valueRef() = it_dst.value() + it_src.value();
303  else{
304  insertValue.push(it_src.value());
305  insertRow.push(it_src.row());
306  }
307  }
308  while (insertValue.size() > 0){
309  T->insert(insertRow.top(), j_dst) = insertValue.top();
310  insertValue.pop();
311  insertRow.pop();
312  }
313 
314  return;
315 }
316 
317 
318 void addCol2ColTriplet(SpMat *T, int jSrc, int jDst)
319 {
320  // Number of columns
321  int N = T->cols();
322  // Triplets
323  vector<Tri> tripletT, tripletInsert;
324 
325  // Reserve space for a maximum number of insertions
326  tripletInsert.reserve(N);
327 
328  // Iterate over elements of column jSrc
329  for (SpMat::InnerIterator itSrc(*T, jSrc); itSrc; ++itSrc){
330  // Try to find element (i_src = itSrc.row(), jDst)
331  SpMat::InnerIterator itDst(*T, jDst);
332  for (; itDst && (itDst.row() < itSrc.row()); ++itDst);
333  if (itDst && (itDst.row() == itSrc.row()))
334  itDst.valueRef() += itSrc.value();
335  else
336  tripletInsert.push_back(Tri(itSrc.row(), jDst, itSrc.value()));
337  }
338 
339  // Get original triplet list with modifications of existing elements
340  tripletT = EigenSparse2Triplet(T);
341 
342  // Reserve space for the elements to insert to triplet list
343  tripletT.reserve(tripletT.size() + tripletInsert.size());
344 
345  // Insert new elements to triplet list
346  for (unsigned int alpha = 0; alpha < tripletInsert.size(); alpha++)
347  tripletT.push_back(tripletInsert.at(alpha));
348 
349  // Update matrix
350  T->setFromTriplets(tripletT.begin(), tripletT.end());
351 
352  return;
353 }
354 
355 
356 void addRow2Row(SpMat *T, int i_src, int i_dst)
357 {
358  double val;
359  bool flag;
360  stack<double> insertValue;
361  stack<int> insertCol;
362  for (int j = 0; j < T->outerSize(); j++){
363  flag = false;
364  // Try to find element (i_src, j)
365  SpMat::InnerIterator it(*T, j);
366  for(; it && (it.row() < i_src); ++it);
367  if (it && (it.row() == i_src)){
368  val = it.value();
369  flag = true;
370  }
371 
372  // If (i_src, j) exists
373  if (flag){
374  // Try to find element (i_dst, j)
375  SpMat::InnerIterator it(*T, j);
376  for (; it && (it.row() < i_dst); ++it);
377  // If element exists, just add
378  if (it && (it.row() == i_dst)){
379  it.valueRef() += val;
380  }
381  // Otherwise insert it
382  else{
383  insertValue.push(val);
384  insertCol.push(it.col());
385  }
386  }
387  }
388  while (insertValue.size() > 0){
389  T->insert(i_dst, insertCol.top()) = insertValue.top();
390  insertValue.pop();
391  insertCol.pop();
392  }
393 
394  return;
395 }
396 
397 
398 void addRow2RowTriplet(SpMat *T, int iSrc, int iDst)
399 {
400  // Number of rows
401  int N = T->rows();
402  // Triplets
403  vector<Tri> tripletT, tripletInsert;
404 
405  // Reserve space for a maximum number of insertions
406  tripletInsert.reserve(N);
407 
408  for (int j = 0; j < T->outerSize(); j++){
409  // Try to find element (iSrc, j)
410  SpMat::InnerIterator itSrc(*T, j);
411  for(; itSrc && (itSrc.row() < iSrc); ++itSrc);
412  if (itSrc && (itSrc.row() == iSrc)){
413  // (iSrc, j) found, now try to find element (iDst, j)
414  SpMat::InnerIterator itDst(*T, j);
415  for (; itDst && (itDst.row() < iDst); ++itDst);
416  // If element exists, just add
417  if (itDst && (itDst.row() == iDst))
418  itDst.valueRef() += itSrc.value();
419  // Otherwise insert it
420  else
421  tripletInsert.push_back(Tri(iDst, j, itSrc.value()));
422  }
423  }
424 
425  // Get original triplet list with modifications of existing elements
426  tripletT = EigenSparse2Triplet(T);
427 
428  // Reserve space for the elements to insert to triplet list
429  tripletT.reserve(tripletT.size() + tripletInsert.size());
430 
431  // Insert new elements to triplet list
432  for (unsigned int alpha = 0; alpha < tripletInsert.size(); alpha++)
433  tripletT.push_back(tripletInsert.at(alpha));
434 
435  // Update matrix
436  T->setFromTriplets(tripletT.begin(), tripletT.end());
437 
438  return;
439 }
440 
441 
442 void addRow2RowTriplet(SpMat *T, int iSrc, int iDst, SpMatCSR *TCSR)
443 {
444  // Number of rows
445  int N = T->rows();
446  // Triplets
447  vector<Tri> tripletT, tripletInsert;
448 
449  // Reserve space for a maximum number of insertions
450  tripletInsert.reserve(N);
451 
452  // Iterate the elevents of row jSrc
453  for(SpMat::InnerIterator itSrc(*TCSR, iSrc); itSrc; ++itSrc){
454  //Try to find element (iDst, iSrc == itSrc.col())
455  SpMat::InnerIterator itDst(*TCSR, iDst);
456  for (; itDst && (itDst.col() < itSrc.col()); ++itDst);
457  if (itDst && (itDst.col() == itSrc.col()))
458  itDst.valueRef() += itSrc.value();
459  // Otherwise insert it
460  else
461  tripletInsert.push_back(Tri(iDst, itSrc.col(), itSrc.value()));
462  }
463 
464  // Get original triplet list with modifications of existing elements
465  tripletT = EigenSparse2Triplet(T);
466 
467  // Reserve space for the elements to insert to triplet list
468  tripletT.reserve(tripletT.size() + tripletInsert.size());
469 
470  // Insert new elements to triplet list
471  for (unsigned int alpha = 0; alpha < tripletInsert.size(); alpha++)
472  tripletT.push_back(tripletInsert.at(alpha));
473 
474  // Update matrix
475  T->setFromTriplets(tripletT.begin(), tripletT.end());
476 
477  return;
478 }
479 
480 
481 void scalProdInner(SpMat *T, int outer, double coef)
482 {
483  for (SpMat::InnerIterator it(*T, outer); it; ++it)
484  it.valueRef() *= coef;
485 
486  return;
487 }
488 
489 
490 void scalProdOuter(SpMat *T, int inner, double coef)
491 {
492  for (int j = 0; j < T->outerSize(); j++)
493  for (SpMat::InnerIterator it(*T, j); it; ++it)
494  if (it.index() == inner)
495  it.valueRef() *= coef;
496 
497  return;
498 }
499 
500 
501 double getModularity(SpMat *T)
502 {
503  int N = T->innerSize();
504  double modularity;
505  VectorXd self = VectorXd::Zero(T->innerSize());
506 
507  // Gets strength and self-loops
508  for (int j = 0; j < T->outerSize(); j++){
509  for (SpMat::InnerIterator it(*T, j); it; ++it){
510  if (it.index() == j)
511  self(j) = it.value();
512  }
513  }
514 
515  // Compute modularity
516  modularity = (self.sum() - 1) / N;
517 
518  return modularity;
519 }
520 
521 
522 #endif
Eigen::Triplet< double > Tri
Eigen triplet of double.
Definition: atio.hpp:29
Eigen::SparseMatrix< double, Eigen::RowMajor > SpMatCSR
Eigen sparse CSR matrix of double type.
Definition: atio.hpp:25
Input, output and conversion routines.