| 
0
 | 
     1 // File: main_hierarchy.cpp
 | 
| 
 | 
     2 // -- output community structure handling (number of levels, communities of one level)
 | 
| 
 | 
     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 <stdlib.h>
 | 
| 
 | 
    18 #include <stdio.h>
 | 
| 
 | 
    19 #include <iostream>
 | 
| 
 | 
    20 #include <iomanip>
 | 
| 
 | 
    21 #include <fstream>
 | 
| 
 | 
    22 #include <vector>
 | 
| 
 | 
    23 #include <map>
 | 
| 
 | 
    24 #include <set>
 | 
| 
 | 
    25 #include <algorithm>
 | 
| 
 | 
    26 
 | 
| 
 | 
    27 using namespace std;
 | 
| 
 | 
    28 
 | 
| 
 | 
    29 int display_level = -1;
 | 
| 
 | 
    30 char *filename = NULL;
 | 
| 
 | 
    31 
 | 
| 
 | 
    32 void
 | 
| 
 | 
    33 usage(char *prog_name, const char *more) {
 | 
| 
 | 
    34   cerr << more;
 | 
| 
 | 
    35   cerr << "usage: " << prog_name << " input_file [options]" << endl << endl;
 | 
| 
 | 
    36   cerr << "input_file: read the community tree from this file." << endl;
 | 
| 
 | 
    37   cerr << "-l xx\t display the community structure for the level xx." << endl;
 | 
| 
 | 
    38   cerr << "\t outputs the community for each node." << endl;
 | 
| 
 | 
    39   cerr << "\t xx must belong to [-1,N] if N is the number of levels." << endl;
 | 
| 
 | 
    40   cerr << "-n\t displays the number of levels and the size of each level." << endl;
 | 
| 
 | 
    41   cerr << "\t equivalent to -l -1." << endl;
 | 
| 
 | 
    42   cerr << "-h\tshow this usage message." << endl;
 | 
| 
 | 
    43   exit(0);
 | 
| 
 | 
    44 }
 | 
| 
 | 
    45 
 | 
| 
 | 
    46 void
 | 
| 
 | 
    47 parse_args(int argc, char **argv) {
 | 
| 
 | 
    48   if (argc<2)
 | 
| 
 | 
    49     usage(argv[0], "Bad arguments number\n");
 | 
| 
 | 
    50 
 | 
| 
 | 
    51   for (int i = 1; i < argc; i++) {
 | 
| 
 | 
    52     if(argv[i][0] == '-') {
 | 
| 
 | 
    53       switch(argv[i][1]) {
 | 
| 
 | 
    54       case 'l':
 | 
| 
 | 
    55 	display_level = atoi(argv[i+1]);
 | 
| 
 | 
    56 	i++;
 | 
| 
 | 
    57 	break;
 | 
| 
 | 
    58       case 'n':
 | 
| 
 | 
    59 	display_level = -1;
 | 
| 
 | 
    60 	break;
 | 
| 
 | 
    61       default:
 | 
| 
 | 
    62 	usage(argv[0], "Unknown option\n");
 | 
| 
 | 
    63       }
 | 
| 
 | 
    64     } else {
 | 
| 
 | 
    65       if (filename==NULL)
 | 
| 
 | 
    66         filename = argv[i];
 | 
| 
 | 
    67       else
 | 
| 
 | 
    68         usage(argv[0], "More than one filename\n");
 | 
| 
 | 
    69     }
 | 
| 
 | 
    70   }
 | 
| 
 | 
    71   if (filename==NULL)
 | 
| 
 | 
    72     usage(argv[0], "No input file has been provided.\n");
 | 
| 
 | 
    73 }
 | 
| 
 | 
    74 int
 | 
| 
 | 
    75 main(int argc, char **argv) {
 | 
| 
 | 
    76   parse_args(argc, argv);
 | 
| 
 | 
    77 
 | 
| 
 | 
    78   vector<vector<int> >levels;
 | 
| 
 | 
    79 
 | 
| 
 | 
    80   ifstream finput;
 | 
| 
 | 
    81   finput.open(filename,fstream::in);
 | 
| 
 | 
    82 
 | 
| 
 | 
    83   int l=-1;
 | 
| 
 | 
    84   while (!finput.eof()) {
 | 
| 
 | 
    85     int node, nodecomm;
 | 
| 
 | 
    86     finput >> node >> nodecomm;
 | 
| 
 | 
    87 
 | 
| 
 | 
    88     if (finput) {
 | 
| 
 | 
    89       if (node==0) {
 | 
| 
 | 
    90 	l++;
 | 
| 
 | 
    91 	levels.resize(l+1);
 | 
| 
 | 
    92       }
 | 
| 
 | 
    93       levels[l].push_back(nodecomm);
 | 
| 
 | 
    94     }
 | 
| 
 | 
    95   }
 | 
| 
 | 
    96 
 | 
| 
 | 
    97   if (display_level==-1) {
 | 
| 
 | 
    98     cout << "Number of levels: " << levels.size() << endl;
 | 
| 
 | 
    99     for (unsigned int i=0 ; i<levels.size();i++)
 | 
| 
 | 
   100       cout << "level " << i << ": " << levels[i].size() << " nodes" << endl;
 | 
| 
 | 
   101   } else if (display_level<0 || (unsigned)display_level>=levels.size()) {
 | 
| 
 | 
   102     cerr << "Incorrect level\n";
 | 
| 
 | 
   103   } else {
 | 
| 
 | 
   104     vector<int> n2c(levels[0].size());
 | 
| 
 | 
   105 
 | 
| 
 | 
   106     for (unsigned int i=0 ; i<levels[0].size() ; i++)
 | 
| 
 | 
   107       n2c[i]=i;
 | 
| 
 | 
   108     
 | 
| 
 | 
   109     for (l=0 ; l<display_level ; l++)
 | 
| 
 | 
   110       for (unsigned int node=0 ; node<levels[0].size() ; node++)
 | 
| 
 | 
   111 	n2c[node] = levels[l][n2c[node]];
 | 
| 
 | 
   112     
 | 
| 
 | 
   113     for (unsigned int node=0 ; node<levels[0].size() ; node++)
 | 
| 
 | 
   114       cout << node << " " << n2c[node] << endl;
 | 
| 
 | 
   115   }
 | 
| 
 | 
   116 }
 |