COMBINATORIAL_BLAS 1.6
 
Loading...
Searching...
No Matches
BPMaximalMatching.h
Go to the documentation of this file.
1#ifndef BP_MAXIMAL_MATCHING_H
2#define BP_MAXIMAL_MATCHING_H
3
4#include "CombBLAS.h"
5#include <iostream>
6#include <functional>
7#include <algorithm>
8#include <vector>
9#include <limits>
10#include "Utility.h"
11#include "MatchingDefs.h"
12
13#define NO_INIT 0
14#define GREEDY 1
15#define KARP_SIPSER 2
16#define DMD 3
17
18namespace combblas {
19
20// This is not tested with CSC yet
21// TODO: test with CSC and Setting SPA (similar to Weighted Greedy)
22template <typename Par_DCSC_Bool, typename IT>
25{
26 static MTRand GlobalMT(123); // for reproducible result
28 int nprocs, myrank;
31 int nthreads = 1;
32#ifdef _OPENMP
33#pragma omp parallel
34 {
35 nthreads = omp_get_num_threads();
36 }
37#endif
38
40
41 //unmatched row and column vertices
43 FullyDistSpVec<IT, IT> degColSG(A.getcommgrid(), A.getncol());
44 //FullyDistVec<IT, IT> degCol(A.getcommgrid());
45 //A.Reduce(degCol, Column, plus<IT>(), static_cast<IT>(0)); // Reduce is not multithreaded
46
47
48 FullyDistSpVec<IT, VertexType> unmatchedCol(A.getcommgrid(), A.getncol());
49 // every veretx is unmatched. keep non-isolated vertices
51 [](VertexType vtx, IT deg){return VertexType();},
52 [](VertexType vtx, IT deg){return deg>0;},
53 true, VertexType());
54
55
56 FullyDistSpVec<IT, VertexType> fringeRow(A.getcommgrid(), A.getnrow());
57 FullyDistSpVec<IT, IT> fringeRow2(A.getcommgrid(), A.getnrow());
58 FullyDistSpVec<IT, VertexType> deg1Col(A.getcommgrid(), A.getncol());
59
60
63 IT newlyMatched = 1; // ensure the first pass of the while loop
64 int iteration = 0;
65 double tStart = MPI_Wtime();
66 std::vector<std::vector<double> > timing;
67
68#ifdef DETAIL_STATS
69 if(myrank == 0)
70 {
71 cout << "=======================================================\n";
72 cout << "@@@@@@ Number of processes: " << nprocs << endl;
73 cout << "=======================================================\n";
74 cout << "It | UMRow | UMCol | newlyMatched | Time "<< endl;
75 cout << "=======================================================\n";
76 }
77#endif
79
80
81 while(curUnmatchedCol !=0 && curUnmatchedRow!=0 && newlyMatched != 0 )
82 {
83 unmatchedCol.ApplyInd([](VertexType vtx, IT idx){return VertexType(idx,idx);});
84 if(type==DMD)
85 {
87 [](VertexType vtx, IT deg){return VertexType(vtx.parent,deg);},
88 [](VertexType vtx, IT deg){return true;},
89 false, VertexType());
90 }
91 else if(rand)
92 {
93 unmatchedCol.Apply([](VertexType vtx){return VertexType(vtx.parent, static_cast<IT>((GlobalMT.rand() * 9999999)+1));});
94 }
95
96 // ======================== step1: One step of BFS =========================
97 std::vector<double> times;
98 double t1 = MPI_Wtime();
99 if(type==GREEDY)
100 {
102 }
103 else if(type==DMD)
104 {
106 }
107 else //(type==KARP_SIPSER)
108 {
110 [](VertexType vtx, IT deg){return vtx;},
111 [](VertexType vtx, IT deg){return deg==1;},
112 false, VertexType());
113
114 if(deg1Col.getnnz()>9)
116 else
118 }
119 // Remove matched row vertices
121 [](VertexType vtx, IT mate){return vtx;},
122 [](VertexType vtx, IT mate){return mate==-1;},
123 false, VertexType());
124
125 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
126 // ===========================================================================
127
128
129 // ======================== step2: Update matching =========================
130
132 [](VertexType vtx, IT mate){return vtx.parent;},
133 [](VertexType vtx, IT mate){return true;},
134 false, VertexType());
135
140 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
141 // ===========================================================================
142
143
144 // =============== step3: Update degree of unmatched columns =================
145 unmatchedRow.Select(mateRow2Col, [](IT mate){return mate==-1;});
146 unmatchedCol.Select(mateCol2Row, [](IT mate){return mate==-1;});
147
148 if(type!=GREEDY)
149 {
150 // update degree
151 newMatchedRows.Apply([](IT val){return 1;}); // needed if the matrix is Boolean since the SR::multiply isn't called
152 SpMV< SelectPlusSR<bool, IT>>(AT, newMatchedRows, degColSG, false); // degree of column vertices to matched rows
153 // subtract degree of column vertices
154 degCol.EWiseApply(degColSG,
155 [](IT old_deg, IT new_deg){return old_deg-new_deg;},
156 [](IT old_deg, IT new_deg){return true;},
157 false, static_cast<IT>(0));
158 // remove isolated vertices
160 [](VertexType vtx, IT deg){return vtx;},
161 [](VertexType vtx, IT deg){return deg>0;},
162 false, VertexType());
163 }
164 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
165 // ===========================================================================
166
167
168 ++iteration;
169 newlyMatched = newMatchedCols.getnnz();
170 times.push_back(std::accumulate(times.begin(), times.end(), 0.0));
171 timing.push_back(times);
172#ifdef DETAIL_STATS
173 if(myrank == 0)
174 {
175 printf("%3d %10lld %10lld %10lld %18lf\n", iteration , curUnmatchedRow, curUnmatchedCol, newlyMatched, times.back());
176 }
177#endif
178 curUnmatchedCol = unmatchedCol.getnnz();
179 curUnmatchedRow = unmatchedRow.getnnz();
181
182 }
183
184 IT cardinality = mateRow2Col.Count([](IT mate){return mate!=-1;});
185 std::vector<double> totalTimes(timing[0].size(),0);
186 for(int i=0; i<timing.size(); i++)
187 {
188 for(int j=0; j<timing[i].size(); j++)
189 {
190 totalTimes[j] += timing[i][j];
191 }
192 }
193
194
195 if(myrank == 0)
196 {
197#ifdef DETAIL_STATS
198 cout << "==========================================================\n";
199 cout << "\n================individual timings =======================\n";
200 cout << " SpMV Update-Match Update-UMC Total "<< endl;
201 cout << "==========================================================\n";
202 for(int i=0; i<timing.size(); i++)
203 {
204 for(int j=0; j<timing[i].size(); j++)
205 {
206 printf("%12.5lf ", timing[i][j]);
207 }
208 cout << endl;
209 }
210
211 cout << "-------------------------------------------------------\n";
212 for(int i=0; i<totalTimes.size(); i++)
213 printf("%12.5lf ", totalTimes[i]);
214 cout << endl;
215#endif
216 std::cout << "****** maximal matching runtime ********\n";
217 std::cout << "nprocesses nthreads ncores algorithm Unmatched-Rows Cardinality Total Time***\n";
218 std::cout << nprocs << " " << nthreads << " " << nprocs * nthreads << " ";
219 if(type == DMD) std::cout << "DMD";
220 else if(type == GREEDY) std::cout << "Greedy";
221 else if(type == KARP_SIPSER) std::cout << "Karp-Sipser";
222 if(rand && (type == KARP_SIPSER || type == GREEDY) ) std::cout << "-rand";
223 std::cout << " ";
224 printf("%lld %lld %lf\n", curUnmatchedRow, cardinality, totalTimes.back());
225 std::cout << "-------------------------------------------------------\n\n";
226 }
227 //isMatching(mateCol2Row, mateRow2Col);
228}
229
230
231
232// Special version of the greedy algorithm (works for both CSC (multithreaded) and DCSC)
233// That uses WeightMaxSR semiring
234// TODO: check if this is 1/2 approx of the weighted matching (probably no)
235// TODO: should we remove degCol?
236// TODO: can be merged with the generalized MaximalMatching
237template <typename Par_MAT_Double, typename IT>
240{
241
243 int nthreads=1;
244#ifdef THREADED
245#pragma omp parallel
246 {
247 nthreads = omp_get_num_threads();
248 }
249#endif
251 int nprocs, myrank;
254
255 double tStart = MPI_Wtime();
256
257 //unmatched row and column vertices
259
260
261
262 FullyDistSpVec<IT, VertexType> unmatchedCol(A.getcommgrid(), A.getncol());
263 // every veretx is unmatched. keep non-isolated vertices
265 [](VertexType vtx, IT deg){return VertexType();},
266 [](VertexType vtx, IT deg){return deg>0;},
267 true, VertexType());
268
269
270 FullyDistSpVec<IT, VertexType> fringeRow(A.getcommgrid(), A.getnrow());
271 FullyDistSpVec<IT, IT> fringeRow2(A.getcommgrid(), A.getnrow());
272 FullyDistSpVec<IT, VertexType> fringeRow3(A.getcommgrid(), A.getnrow());
273
276 IT newlyMatched = 1; // ensure the first pass of the while loop
277 int iteration = 0;
278
279 std::vector<std::vector<double> > timing;
280
281#ifdef DETAIL_STATS
282 if(myrank == 0)
283 {
284 cout << "=======================================================\n";
285 cout << "@@@@@@ Number of processes: " << nprocs << endl;
286 cout << "=======================================================\n";
287 cout << "It | UMRow | UMCol | newlyMatched | Time "<< endl;
288 cout << "=======================================================\n";
289 }
290#endif
292
293
294 while(curUnmatchedCol !=0 && curUnmatchedRow!=0 && newlyMatched != 0 )
295 {
296 // anything is fine in the second argument
297 unmatchedCol.ApplyInd([](VertexType vtx, IT idx){return VertexType(idx,idx);});
298
299
300 // ======================== step1: One step of BFS =========================
301 std::vector<double> times;
302 double t1 = MPI_Wtime();
303
305
306 // Remove matched row vertices
308 [](VertexType vtx, IT mate){return vtx;},
309 [](VertexType vtx, IT mate){return mate==-1;},
310 false, VertexType());
311
312 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
313 // ===========================================================================
314
315
316 // ======================== step2: Update matching =========================
317
319 [](VertexType vtx, IT mate){return vtx.parent;},
320 [](VertexType vtx, IT mate){return true;},
321 false, VertexType());
322
327 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
328 // ===========================================================================
329
330
331 // =============== step3: Update unmatched columns and rows =================
332
333 unmatchedRow.Select(mateRow2Col, [](IT mate){return mate==-1;});
334 unmatchedCol.Select(mateCol2Row, [](IT mate){return mate==-1;});
335 if(myrank == 0){times.push_back(MPI_Wtime()-t1); t1 = MPI_Wtime();}
336 // ===========================================================================
337
338
339 ++iteration;
340 newlyMatched = newMatchedCols.getnnz();
341 times.push_back(std::accumulate(times.begin(), times.end(), 0.0));
342 timing.push_back(times);
343#ifdef DETAIL_STATS
344 if(myrank == 0)
345 {
346 printf("%3d %10lld %10lld %10lld %18lf\n", iteration , curUnmatchedRow, curUnmatchedCol, newlyMatched, times.back());
347 }
348#endif
349 curUnmatchedCol = unmatchedCol.getnnz();
350 curUnmatchedRow = unmatchedRow.getnnz();
352
353 }
354
355 IT cardinality = mateRow2Col.Count([](IT mate){return mate!=-1;});
356 std::vector<double> totalTimes(timing[0].size(),0);
357 for(int i=0; i<timing.size(); i++)
358 {
359 for(int j=0; j<timing[i].size(); j++)
360 {
361 totalTimes[j] += timing[i][j];
362 }
363 }
364
365
366 if(myrank == 0)
367 {
368#ifdef DETAIL_STATS
369 cout << "==========================================================\n";
370 cout << "\n================individual timings =======================\n";
371 cout << " SpMV Update-Match Update-UMC Total "<< endl;
372 cout << "==========================================================\n";
373 for(int i=0; i<timing.size(); i++)
374 {
375 for(int j=0; j<timing[i].size(); j++)
376 {
377 printf("%12.5lf ", timing[i][j]);
378 }
379 cout << endl;
380 }
381
382 cout << "-------------------------------------------------------\n";
383 for(int i=0; i<totalTimes.size(); i++)
384 printf("%12.5lf ", totalTimes[i]);
385 cout << endl;
386#endif
387 std::cout << "****** maximal matching runtime ********\n";
388 std::cout << "Unmatched-Rows Cardinality Total Time***\n";
389 printf("%lld %lld %lf\n", curUnmatchedRow, cardinality, totalTimes.back());
390 std::cout << "-------------------------------------------------------\n\n";
391 }
392 //isMatching(mateCol2Row, mateRow2Col);
393}
394
395
396
397
398template <class Par_DCSC_Bool, class IT, class NT>
400{
402 int myrank;
404 FullyDistSpVec<IT, IT> fringeRow(A.getcommgrid(), A.getnrow());
405 FullyDistSpVec<IT, IT> fringeCol(A.getcommgrid(), A.getncol());
408 unmatchedRow.setNumToInd();
409 unmatchedCol.setNumToInd();
410
411
414 if(fringeRow.getnnz() != 0)
415 {
416 if(myrank == 0)
417 std::cout << "Not maximal matching!!\n";
418 return false;
419 }
420
422 tA.Transpose();
425 if(fringeCol.getnnz() != 0)
426 {
427 if(myrank == 0)
428 std::cout << "Not maximal matching**!!\n";
429 return false;
430 }
431 return true;
432}
433
434}
435
436#endif
437
SpParMat< int64_t, bool, SpDCCols< int64_t, bool > > Par_DCSC_Bool
#define GREEDY
#define KARP_SIPSER
#define DMD
MTRand GlobalMT
double rand()
int size
Definition common.h:20
void MaximalMatching(Par_DCSC_Bool &A, Par_DCSC_Bool &AT, FullyDistVec< IT, IT > &mateRow2Col, FullyDistVec< IT, IT > &mateCol2Row, FullyDistVec< IT, IT > &degColRecv, int type, bool rand=true)
bool isMaximalmatching(Par_DCSC_Bool &A, FullyDistVec< IT, NT > &mateRow2Col, FullyDistVec< IT, NT > &mateCol2Row)
void WeightedGreedy(Par_MAT_Double &A, FullyDistVec< IT, IT > &mateRow2Col, FullyDistVec< IT, IT > &mateCol2Row, FullyDistVec< IT, IT > &degCol)
Dcsc< IU, typename promote_trait< NU1, NU2 >::T_promote > EWiseMult(const Dcsc< IU, NU1 > &A, const Dcsc< IU, NU2 > *B, bool exclude)
Definition Friends.h:694
double A