COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
BPMaximalMatching.cpp
Go to the documentation of this file.
1#include "CombBLAS/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
22using namespace std;
23using namespace combblas;
24
25
27int init;
29bool fewexp;
30
31template <typename PARMAT>
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
42struct VertexType
43{
44public:
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 comm = A.getcommgrid()->GetWorld();
75 MPI_Comm_rank(comm,&myrank);
76
77
80 FullyDistVec<int64_t, int64_t> nonisoRowV; // id's of non-isolated (connected) Row vertices
81 FullyDistVec<int64_t, int64_t> nonisoColV; // id's of non-isolated (connected) Col vertices
82 FullyDistVec<int64_t, int64_t> nonisov; // id's of non-isolated (connected) vertices
83
84 A.Reduce(*ColSums, Column, plus<int64_t>(), static_cast<int64_t>(0));
85 A.Reduce(*RowSums, Row, plus<int64_t>(), static_cast<int64_t>(0));
86
87 // this steps for general graph
88 /*
89 ColSums->EWiseApply(*RowSums, plus<int64_t>()); not needed for bipartite graph
90 nonisov = ColSums->FindInds(bind2nd(greater<int64_t>(), 0));
91 nonisov.RandPerm(); // so that A(v,v) is load-balanced (both memory and time wise)
92 A.operator()(nonisov, nonisov, true); // in-place permute to save memory
93 */
94
95 // this steps for bipartite graph
96 nonisoColV = ColSums->FindInds(bind2nd(greater<int64_t>(), 0));
97 nonisoRowV = RowSums->FindInds(bind2nd(greater<int64_t>(), 0));
98 delete ColSums;
99 delete RowSums;
100
101
102 {
103 nonisoColV.RandPerm();
104 nonisoRowV.RandPerm();
105 }
106
107
108 int64_t nrows1=A.getnrow(), ncols1=A.getncol(), nnz1 = A.getnnz();
109 double avgDeg1 = (double) nnz1/(nrows1+ncols1);
110
111
112 A.operator()(nonisoRowV, nonisoColV, true);
113
114 int64_t nrows2=A.getnrow(), ncols2=A.getncol(), nnz2 = A.getnnz();
115 double avgDeg2 = (double) nnz2/(nrows2+ncols2);
116
117
118 if(myrank == 0)
119 {
120 cout << "ncol nrows nedges deg \n";
121 cout << nrows1 << " " << ncols1 << " " << nnz1 << " " << avgDeg1 << " \n";
122 cout << nrows2 << " " << ncols2 << " " << nnz2 << " " << avgDeg2 << " \n";
123 }
124
126
127
128}
129
130
131
132
133
134
135
137{
138 int myrank;
140 if(myrank == 0)
141 {
142 cout << "\n-------------- usage --------------\n";
143 cout << "Usage (random matrix): ./maximal <er|g500|ssca> <Scale> <EDGEFACTOR> <algo><rand><moreSplit>\n";
144 cout << "Usage (input matrix): ./maximal <input> <matrix> <algo><rand><moreSplit>\n\n";
145
146 cout << " \n-------------- meaning of arguments ----------\n";
147 cout << "** er: Erdos-Renyi, g500: Graph500 benchmark, ssca: SSCA benchmark\n";
148 cout << "** scale: matrix dimention is 2^scale\n";
149 cout << "** edgefactor: average degree of vertices\n";
150 cout << "** algo : maximal matching algorithm used to initialize\n ";
151 cout << " greedy: greedy init , ks: Karp-Sipser, dmd: dynamic mindegree\n";
152 cout << " default: dynamic mindegree\n";
153 cout << "** (optional) rand: random parent selection in greedy/Karp-Sipser\n" ;
154 cout << "** (optional) moreSplit: more splitting of Matrix.\n" ;
155 cout << "(order of optional arguments does not matter)\n";
156
157 cout << " \n-------------- examples ----------\n";
158 cout << "Example: mpirun -np 4 ./maximal g500 18 16 ks rand" << endl;
159 cout << "Example: mpirun -np 4 ./maximal input cage12.mtx dmd\n" << endl;
160 }
161}
162
163void GetOptions(char* argv[], int argc)
164{
165 string allArg="";
166 for(int i=0; i<argc; i++)
167 {
168 allArg += string(argv[i]);
169 }
170
171 if(allArg.find("moreSplit")!=string::npos)
172 moreSplit = true;
173 if(allArg.find("randMaximal")!=string::npos)
174 randMaximal = true;
175 if(allArg.find("greedy")!=string::npos)
176 init = GREEDY;
177 else if(allArg.find("ks")!=string::npos)
179 else if(allArg.find("dmd")!=string::npos)
180 init = DMD;
181 else
182 init = DMD;
183
184}
185
187{
189 tinfo.str("");
190 tinfo << "\n---------------------------------\n";
191 tinfo << " Maximal matching algorithm options: ";
192 if(init == KARP_SIPSER) tinfo << " Karp-Sipser, ";
193 if(init == DMD) tinfo << " dynamic mindegree, ";
194 if(init == GREEDY) tinfo << " greedy, ";
195 if(randMaximal) tinfo << " random parent selection in greedy/Karp-Sipser, ";
196 if(