| 0 | 1 // File: graph.cpp | 
|  | 2 // -- simple graph handling source file | 
|  | 3 //----------------------------------------------------------------------------- | 
|  | 4 // Community detection | 
|  | 5 // Based on the article "Fast unfolding of community hierarchies in large networks" | 
|  | 6 // Copyright (C) 2008 V. Blondel, J.-L. Guillaume, R. Lambiotte, E. Lefebvre | 
|  | 7 // | 
|  | 8 // This program must not be distributed without agreement of the above mentionned authors. | 
|  | 9 //----------------------------------------------------------------------------- | 
|  | 10 // Author   : E. Lefebvre, adapted by J.-L. Guillaume | 
|  | 11 // Email    : jean-loup.guillaume@lip6.fr | 
|  | 12 // Location : Paris, France | 
|  | 13 // Time	    : February 2008 | 
|  | 14 //----------------------------------------------------------------------------- | 
|  | 15 // see readme.txt for more details | 
|  | 16 | 
|  | 17 #include "graph.h" | 
|  | 18 | 
|  | 19 using namespace std; | 
|  | 20 | 
|  | 21 Graph::Graph(char *filename, int type) { | 
|  | 22   ifstream finput; | 
|  | 23   finput.open(filename,fstream::in); | 
|  | 24 | 
|  | 25   int nb_links=0; | 
|  | 26 | 
|  | 27   while (!finput.eof()) { | 
|  | 28     unsigned int src, dest; | 
|  | 29     double weight=1.; | 
|  | 30 | 
|  | 31     if (type==WEIGHTED) { | 
|  | 32       finput >> src >> dest >> weight; | 
|  | 33     } else { | 
|  | 34       finput >> src >> dest; | 
|  | 35     } | 
|  | 36 | 
|  | 37     if (finput) { | 
|  | 38       if (links.size()<=max(src,dest)+1) { | 
|  | 39         links.resize(max(src,dest)+1); | 
|  | 40       } | 
|  | 41 | 
|  | 42       links[src].push_back(make_pair(dest,weight)); | 
|  | 43       if (src!=dest) | 
|  | 44         links[dest].push_back(make_pair(src,weight)); | 
|  | 45 | 
|  | 46       nb_links++; | 
|  | 47     } | 
|  | 48   } | 
|  | 49 | 
|  | 50   finput.close(); | 
|  | 51 } | 
|  | 52 | 
|  | 53 void | 
|  | 54 Graph::renumber(int type) { | 
|  | 55   vector<int> linked(links.size(),-1); | 
|  | 56   vector<int> renum(links.size(),-1); | 
|  | 57   int nb=0; | 
|  | 58 | 
|  | 59   for (unsigned int i=0 ; i<links.size() ; i++) { | 
|  | 60     for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 61       linked[i]=1; | 
|  | 62       linked[links[i][j].first]=1; | 
|  | 63     } | 
|  | 64   } | 
|  | 65 | 
|  | 66   for (unsigned int i=0 ; i<links.size() ; i++) { | 
|  | 67     if (linked[i]==1) | 
|  | 68       renum[i]=nb++; | 
|  | 69   } | 
|  | 70 | 
|  | 71   for (unsigned int i=0 ; i<links.size() ; i++) { | 
|  | 72     if (linked[i]==1) { | 
|  | 73       for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 74 	links[i][j].first = renum[links[i][j].first]; | 
|  | 75       } | 
|  | 76       links[renum[i]]=links[i]; | 
|  | 77     } | 
|  | 78   } | 
|  | 79   links.resize(nb); | 
|  | 80 } | 
|  | 81 | 
|  | 82 void | 
|  | 83 Graph::clean(int type) { | 
|  | 84   for (unsigned int i=0 ; i<links.size() ; i++) { | 
|  | 85     map<int, float> m; | 
|  | 86     map<int, float>::iterator it; | 
|  | 87 | 
|  | 88     for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 89       it = m.find(links[i][j].first); | 
|  | 90       if (it==m.end()) | 
|  | 91 	m.insert(make_pair(links[i][j].first, links[i][j].second)); | 
|  | 92       else if (type==WEIGHTED) | 
|  | 93       	it->second+=links[i][j].second; | 
|  | 94     } | 
|  | 95 | 
|  | 96     vector<pair<int,float> > v; | 
|  | 97     for (it = m.begin() ; it!=m.end() ; it++) | 
|  | 98       v.push_back(*it); | 
|  | 99     links[i].clear(); | 
|  | 100     links[i]=v; | 
|  | 101   } | 
|  | 102 } | 
|  | 103 | 
|  | 104 void | 
|  | 105 Graph::display(int type) { | 
|  | 106   for (unsigned int i=0 ; i<links.size() ; i++) { | 
|  | 107     for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 108       int dest   = links[i][j].first; | 
|  | 109       float weight = links[i][j].second; | 
|  | 110       if (type==WEIGHTED) | 
|  | 111 	cout << i << " " << dest << " " << weight << endl; | 
|  | 112       else | 
|  | 113 	cout << i << " " << dest << endl; | 
|  | 114     } | 
|  | 115   } | 
|  | 116 } | 
|  | 117 | 
|  | 118 void | 
|  | 119 Graph::display_binary(char *filename, char *filename_w, int type) { | 
|  | 120   ofstream foutput; | 
|  | 121   foutput.open(filename, fstream::out | fstream::binary); | 
|  | 122 | 
|  | 123   unsigned int s = links.size(); | 
|  | 124 | 
|  | 125   // outputs number of nodes | 
|  | 126   foutput.write((char *)(&s),4); | 
|  | 127 | 
|  | 128   // outputs cumulative degree sequence | 
|  | 129   long tot=0; | 
|  | 130   for (unsigned int i=0 ; i<s ; i++) { | 
|  | 131     tot+=(long)links[i].size(); | 
|  | 132     foutput.write((char *)(&tot),8); | 
|  | 133   } | 
|  | 134 | 
|  | 135   // outputs links | 
|  | 136   for (unsigned int i=0 ; i<s ; i++) { | 
|  | 137     for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 138       int dest = links[i][j].first; | 
|  | 139       foutput.write((char *)(&dest),4); | 
|  | 140     } | 
|  | 141   } | 
|  | 142   foutput.close(); | 
|  | 143 | 
|  | 144   // outputs weights in a separate file | 
|  | 145   if (type==WEIGHTED) { | 
|  | 146     ofstream foutput_w; | 
|  | 147     foutput_w.open(filename_w,fstream::out | fstream::binary); | 
|  | 148     for (unsigned int i=0 ; i<s ; i++) { | 
|  | 149       for (unsigned int j=0 ; j<links[i].size() ; j++) { | 
|  | 150 	float weight = links[i][j].second; | 
|  | 151 	foutput_w.write((char *)(&weight),4); | 
|  | 152       } | 
|  | 153     } | 
|  | 154     foutput_w.close(); | 
|  | 155   } | 
|  | 156 } | 
|  | 157 |