COMBINATORIAL_BLAS  1.6
BPMaximalMatching.cpp
Go to the documentation of this file.
1 #include "../CombBLAS.h"
2 #include <mpi.h>
3 #include <sys/time.h>
4 #include <iostream>
5 #include <functional>
6 #include <algorithm>
7 #include <vector>
8 #include <string>
9 #include <sstream>
10 #include "BPMaximalMatching.h"
11 
12 
13 #ifdef THREADED
14  #ifndef _OPENMP
15  #define _OPENMP
16  #endif
17 
18  #include <omp.h>
19  int cblas_splits = 1;
20 #endif
21 
22 using namespace std;
23 using namespace combblas;
24 
25 
27 int init;
29 bool fewexp;
30 
31 template <typename PARMAT>
32 void Symmetricize(PARMAT & A)
33 {
34  // boolean addition is practically a "logical or"
35  // therefore this doesn't destruct any links
36  PARMAT AT = A;
37  AT.Transpose();
38  A += AT;
39 }
40 
41 
42 struct VertexType
43 {
44 public:
45  VertexType(int64_t p=-1, int64_t r=-1, int16_t pr=0){parent=p; root = r; prob = pr;};
46 
47  friend bool operator<(const VertexType & vtx1, const VertexType & vtx2 )
48  {
49  if(vtx1.prob==vtx2.prob) return vtx1.parent<vtx2.parent;
50  else return vtx1.prob<vtx2.prob;
51  };
52  friend bool operator==(const VertexType & vtx1, const VertexType & vtx2 ){return vtx1.parent==vtx2.parent;};
53  friend ostream& operator<<(ostream& os, const VertexType & vertex ){os << "(" << vertex.parent << "," << vertex.root << ")"; return os;};
54  //private:
57  int16_t prob; // probability of selecting an edge
58 
59 };
60 
61 
62 
63 
65 
66 /*
67  Remove isolated vertices and purmute
68  */
70 {
71 
72  int nprocs, myrank;
73  MPI_Comm_size(MPI_COMM_WORLD,&nprocs);
74  MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
75 
76 
79  FullyDistVec<int64_t, int64_t> nonisoRowV; // id's of non-isolated (connected) Row vertices
80  FullyDistVec<int64_t, int64_t> nonisoColV; // id's of non-isolated (connected) Col vertices
81  FullyDistVec<int64_t, int64_t> nonisov; // id's of non-isolated (connected) vertices
82 
83  A.Reduce(*ColSums, Column, plus<int64_t>(), static_cast<int64_t>(0));
84  A.Reduce(*RowSums, Row, plus<int64_t>(), static_cast<int64_t>(0));
85 
86  // this steps for general graph
87  /*
88  ColSums->EWiseApply(*RowSums, plus<int64_t>()); not needed for bipartite graph
89  nonisov = ColSums->FindInds(bind2nd(greater<int64_t>(), 0));
90  nonisov.RandPerm(); // so that A(v,v) is load-balanced (both memory and time wise)
91  A.operator()(nonisov, nonisov, true); // in-place permute to save memory
92  */
93 
94  // this steps for bipartite graph
95  nonisoColV = ColSums->FindInds(bind2nd(greater<int64_t>(), 0));
96  nonisoRowV = RowSums->FindInds(bind2nd(greater<int64_t>(), 0));
97  delete ColSums;
98  delete RowSums;
99 
100 
101  {
102  nonisoColV.RandPerm();
103  nonisoRowV.RandPerm();
104  }
105 
106 
107  int64_t nrows1=A.getnrow(), ncols1=A.getncol(), nnz1 = A.getnnz();
108  double avgDeg1 = (double) nnz1/(nrows1+ncols1);
109 
110 
111  A.operator()(nonisoRowV, nonisoColV, true);
112 
113  int64_t nrows2=A.getnrow(), ncols2=A.getncol(), nnz2 = A.getnnz();
114  double avgDeg2 = (double) nnz2/(nrows2+ncols2);
115 
116 
117  if(myrank == 0)
118  {
119  cout << "ncol nrows nedges deg \n";
120  cout << nrows1 << " " << ncols1 << " " << nnz1 << " " << avgDeg1 << " \n";
121  cout << nrows2 << " " << ncols2 << " " << nnz2 << " " << avgDeg2 << " \n";
122  }
123 
124  MPI_Barrier(MPI_COMM_WORLD);
125 
126 
127 }
128 
129 
130 
131 
132 
133 
134 
135 void ShowUsage()
136 {
137  int myrank;
138  MPI_Comm_rank(MPI_COMM_WORLD,&myrank);
139  if(myrank == 0)
140  {
141  cout << "\n-------------- usage --------------\n";
142  cout << "Usage (random matrix): ./maximal <er|g500|ssca> <Scale> <EDGEFACTOR> <algo><rand><moreSplit>\n";
143  cout << "Usage (input matrix): ./maximal <input> <matrix> <algo><rand><moreSplit>\n\n";
144 
145  cout << " \n-------------- meaning of arguments ----------\n";
146  cout << "** er: Erdos-Renyi, g500: Graph500 benchmark, ssca: SSCA benchmark\n";
147  cout << "** scale: matrix dimention is 2^scale\n";
148  cout << "** edgefactor: average degree of vertices\n";
149  cout << "** algo : maximal matching algorithm used to initialize\n ";
150  cout << " greedy: greedy init , ks: Karp-Sipser, dmd: dynamic mindegree\n";
151  cout << " default: dynamic mindegree\n";
152  cout << "** (optional) rand: random parent selection in greedy/Karp-Sipser\n" ;
153  cout << "** (optional) moreSplit: more splitting of Matrix.\n" ;
154  cout << "(order of optional arguments does not matter)\n";
155 
156  cout << " \n-------------- examples ----------\n";
157  cout << "Example: mpirun -np 4 ./maximal g500 18 16 ks rand" << endl;
158  cout << "Example: mpirun -np 4 ./maximal input cage12.mtx dmd\n" << endl;
159  }
160 }
161 
162 void GetOptions(char* argv[], int argc)
163 {
164  string allArg="";
165  for(int i=0; i<argc; i++)
166  {
167  allArg += string(argv[i]);
168  }
169 
170  if(allArg.find("moreSplit")!=string::npos)
171  moreSplit = true;
172  if(allArg.find("randMaximal")!=string::npos)
173  randMaximal = true;
174  if(allArg.find("greedy")!=string::npos)
175  init = GREEDY;
176  else if(allArg.find("ks")!=string::npos)
177  init = KARP_SIPSER;
178  else if(allArg.find("dmd")!=string::npos)
179  init = DMD;
180  else
181  init = DMD;
182 
183 }
184 
186 {
187  ostringstream tinfo;
188  tinfo.str("");
189  tinfo << "\n---------------------------------\n";
190  tinfo << " Maximal matching algorithm options: ";
191  if(init == KARP_SIPSER) tinfo << " Karp-Sipser, ";
192  if(init == DMD) tinfo << " dynamic mindegree, ";
193  if(init == GREEDY) tinfo << " greedy, ";
194  if(randMaximal) tinfo << " random parent selection in greedy/Karp-Sipser, ";
195  if(moreSplit) tinfo << " moreSplit ";
196  tinfo << "\n---------------------------------\n\n";