Skip to content

Commit 5aa0567

Browse files
maxflow: more clarifications and simplifications
1 parent 89f8031 commit 5aa0567

File tree

1 file changed

+85
-111
lines changed

1 file changed

+85
-111
lines changed

experimental/algorithm/LAGr_MaxFlow.c

Lines changed: 85 additions & 111 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,8 @@ static GrB_Info LG_augment_maxflow
8484
GrB_free(&d); \
8585
GrB_free(&theta); \
8686
GrB_free(&R); \
87-
GrB_free(&delta); \
87+
GrB_free(&Delta); \
8888
GrB_free(&delta_vec); \
89-
GrB_free(&delta_mat); \
9089
GrB_free(&Map); \
9190
GrB_free(&y); \
9291
GrB_free(&yd); \
@@ -119,8 +118,7 @@ static GrB_Info LG_augment_maxflow
119118
GrB_free(&CheckInvariant); \
120119
GrB_free(&check); \
121120
GrB_free(&extractYJ); \
122-
GrB_free(&extract_desc); \
123-
GrB_free(&residual_vec); \
121+
GrB_free(&desc); \
124122
GrB_free(&MakeFlow); \
125123
GrB_free(&GetResidual); \
126124
GrB_free(&lvl) ; \
@@ -169,15 +167,15 @@ JIT_STR(typedef struct{
169167
// type of the Map matrix and yd vector: MF_compareTuple64/32 (CompareTuple)
170168
JIT_STR(typedef struct{
171169
double residual; /* residual = capacity - flow for the edge (i,j) */
172-
int64_t di;
173-
int64_t y_dmin;
174-
int64_t j;
170+
int64_t di; /* d(i) for node i */
171+
int64_t dj; /* d(j) for node j */
172+
int64_t j; /* node id for node j */
175173
} MF_compareTuple64;, COMPARETUPLE_STR64)
176174
JIT_STR(typedef struct{
177175
double residual; /* residual = capacity - flow for the edge (i,j) */
178-
int32_t di;
179-
int32_t y_dmin;
180-
int32_t j;
176+
int32_t di; /* d(i) for node i */
177+
int32_t dj; /* d(j) for node j */
178+
int32_t j; /* node id for node j */
181179
int32_t unused; /* to pad the struct to 24 bytes */
182180
} MF_compareTuple32;, COMPARETUPLE_STR32) // 24 bytes: padded
183181

@@ -187,30 +185,30 @@ JIT_STR(typedef struct{
187185

188186
// unary op for R = CreateResidualForward (A)
189187
JIT_STR(void MF_CreateResidualForward(MF_flowEdge *z, const double *y) {
190-
z->flow = 0;
191188
z->capacity = (*y);
189+
z->flow = 0;
192190
}, CRF_STR)
193191

194192
// unary op for R<!struct(A)> = CreateResidualBackward (AT)
195193
JIT_STR(void MF_CreateResidualBackward(MF_flowEdge *z, const double *y) {
196-
z->flow = 0;
197194
z->capacity = 0;
195+
z->flow = 0;
198196
}, CRB_STR)
199197

200198
//------------------------------------------------------------------------------
201199
// R*d semiring
202200
//------------------------------------------------------------------------------
203201

204-
// multiplicative operator, z = R(i,k) * d(k), 64-bit case
202+
// multiplicative operator, z = R(i,j) * d(j), 64-bit case
205203
JIT_STR(void MF_RxdMult64(MF_resultTuple64 *z,
206-
const MF_flowEdge *x, GrB_Index ix, GrB_Index jx,
204+
const MF_flowEdge *x, GrB_Index i, GrB_Index j,
207205
const int64_t *y, GrB_Index iy, GrB_Index jy,
208206
const int64_t* theta) {
209207
double r = x->capacity - x->flow;
210208
if(r > 0){
211209
z->residual = r;
212-
z->d = *y;
213-
z->j = jx;
210+
z->d = (*y);
211+
z->j = j;
214212
}
215213
else{
216214
z->residual = 0;
@@ -219,16 +217,16 @@ JIT_STR(void MF_RxdMult64(MF_resultTuple64 *z,
219217
}
220218
}, RXDMULT_STR64)
221219

222-
// multiplicative operator, z = R(i,k) * d(k), 32-bit case
220+
// multiplicative operator, z = R(i,j) * d(j), 32-bit case
223221
JIT_STR(void MF_RxdMult32(MF_resultTuple32 *z,
224-
const MF_flowEdge *x, GrB_Index ix, GrB_Index jx,
222+
const MF_flowEdge *x, GrB_Index i, GrB_Index j,
225223
const int32_t *y, GrB_Index iy, GrB_Index jy,
226224
const int32_t* theta) {
227225
double r = x->capacity - x->flow;
228226
if(r > 0){
229227
z->residual = r;
230-
z->d = *y;
231-
z->j = jx;
228+
z->d = (*y);
229+
z->j = j;
232230
}
233231
else{
234232
z->residual = 0;
@@ -293,7 +291,7 @@ JIT_STR(void MF_RxdAdd32(MF_resultTuple32 * z,
293291
}, RXDADD_STR32)
294292

295293
//------------------------------------------------------------------------------
296-
// unary ops for residual_vec = ExtractResidualFlow (y)
294+
// unary ops for delta_vec = ExtractResidualFlow (y)
297295
//------------------------------------------------------------------------------
298296

299297
JIT_STR(void MF_ExtractResidualFlow64(double *z, const MF_resultTuple64 *x)
@@ -303,7 +301,7 @@ JIT_STR(void MF_ExtractResidualFlow32(double *z, const MF_resultTuple32 *x)
303301
{ (*z) = x->residual; }, EXTRACTRESIDUALFLOW_STR32)
304302

305303
//------------------------------------------------------------------------------
306-
// binary op for R<delta_mat> = UpdateFlow (R, delta_mat) using eWiseMult
304+
// binary op for R<Delta> = UpdateFlow (R, Delta) using eWiseMult
307305
//------------------------------------------------------------------------------
308306

309307
JIT_STR(void MF_UpdateFlow(MF_flowEdge *z,
@@ -358,8 +356,8 @@ JIT_STR(void MF_extractYJ32(int32_t *z, const MF_resultTuple32 *x) { (*z) = x->j
358356

359357
JIT_STR(void MF_InitForwardFlow(MF_flowEdge * z,
360358
const MF_flowEdge * x, const MF_flowEdge * y){
361-
z->flow = y->flow + x->flow;
362359
z->capacity = x->capacity;
360+
z->flow = y->flow + x->flow;
363361
}, INITFLOWF_STR)
364362

365363
//------------------------------------------------------------------------------
@@ -368,79 +366,59 @@ JIT_STR(void MF_InitForwardFlow(MF_flowEdge * z,
368366

369367
JIT_STR(void MF_InitBackwardFlow(MF_flowEdge * z,
370368
const MF_flowEdge * x, const MF_flowEdge * y){
371-
z->flow = x->flow - y->flow;
372369
z->capacity = x->capacity;
370+
z->flow = x->flow - y->flow;
373371
}, INITFLOWB_STR)
374372

375373
//------------------------------------------------------------------------------
376-
// yd = Map*e semiring
374+
// y = Map*e semiring
377375
//------------------------------------------------------------------------------
378376

377+
// multiplicative operator, z = Map(i,j)*e(j), 64-bit case
379378
JIT_STR(void MF_MxeMult64(MF_resultTuple64 * z,
380-
const MF_compareTuple64 * x, GrB_Index ix, GrB_Index jx,
379+
const MF_compareTuple64 * x, GrB_Index i, GrB_Index j,
381380
const double * y, GrB_Index iy, GrB_Index jy,
382381
const int64_t* theta){
383-
if(x->di == x->y_dmin && (*y) > 0){
384-
if(ix < jx){
385-
z->d = x->y_dmin;
382+
bool j_active = ((*y) > 0) ;
383+
if ((x->di < x->dj-1) /* case a */
384+
|| (x->di == x->dj-1 && !j_active) /* case b */
385+
|| (x->di == x->dj && (!j_active || (j_active && (i < j)))) /* case c */
386+
|| (x->di == x->dj+1)) /* case d */
387+
{
386388
z->residual = x->residual;
389+
z->d = x->dj;
387390
z->j = x->j;
388-
}
389-
else{
390-
z->d = INT64_MAX;
391+
}
392+
else
393+
{
391394
z->residual = 0;
395+
z->d = INT64_MAX;
392396
z->j = -1;
393-
}
394-
}
395-
else if(x->di == x->y_dmin - 1 && (*y) > 0){
396-
z->d = INT64_MAX;
397-
z->residual = 0;
398-
z->j = -1;
399-
}
400-
else if(x->di <= x->y_dmin-1 || x->di == x->y_dmin+1 || x->di == x->y_dmin){
401-
z->d = x->y_dmin;
402-
z->residual = x->residual;
403-
z->j = x->j;
404-
}
405-
else{
406-
z->d = INT64_MAX;
407-
z->residual = 0;
408-
z->j = -1;
409397
}
410-
}, MXEMULT_STR64)
398+
}, MXEMULT_STR64)
411399

400+
// multiplicative operator, z = Map(i,j)*e(j), 32-bit case
412401
JIT_STR(void MF_MxeMult32(MF_resultTuple32 * z,
413-
const MF_compareTuple32 * x, GrB_Index ix, GrB_Index jx,
402+
const MF_compareTuple32 * x, GrB_Index i, GrB_Index j,
414403
const double * y, GrB_Index iy, GrB_Index jy,
415404
const int32_t* theta){
416-
if(x->di == x->y_dmin && (*y) > 0){
417-
if(ix < jx){
418-
z->d = x->y_dmin;
405+
bool j_active = ((*y) > 0) ;
406+
if ((x->di < x->dj-1) /* case a */
407+
|| (x->di == x->dj-1 && !j_active) /* case b */
408+
|| (x->di == x->dj && (!j_active || (j_active && (i < j)))) /* case c */
409+
|| (x->di == x->dj+1)) /* case d */
410+
{
419411
z->residual = x->residual;
412+
z->d = x->dj;
420413
z->j = x->j;
421-
}
422-
else{
423-
z->d = INT32_MAX;
414+
}
415+
else
416+
{
424417
z->residual = 0;
418+
z->d = INT32_MAX;
425419
z->j = -1;
426-
}
427-
}
428-
else if(x->di == x->y_dmin - 1 && (*y) > 0){
429-
z->d = INT32_MAX;
430-
z->residual = 0;
431-
z->j = -1;
432420
}
433-
else if(x->di <= x->y_dmin-1 || x->di == x->y_dmin+1 || x->di == x->y_dmin){
434-
z->d = x->y_dmin;
435-
z->residual = x->residual;
436-
z->j = x->j;
437-
}
438-
else{
439-
z->d = INT32_MAX;
440-
z->residual = 0;
441-
z->j = -1;
442-
}
443-
}, MXEMULT_STR32)
421+
}, MXEMULT_STR32)
444422

445423
// Note: the additive monoid is not actually used in the call to GrB_mxv below,
446424
// because any given node only pushes to one neighbor at a time. As a result,
@@ -463,32 +441,32 @@ JIT_STR(void MF_MxeAdd32(MF_resultTuple32 * z,
463441
JIT_STR(void MF_CreateCompareVec64(MF_compareTuple64 *comp,
464442
const MF_resultTuple64 *res, const int64_t *height) {
465443
comp->di = (*height);
466-
comp->j = res->j;
467444
comp->residual = res->residual;
468-
comp->y_dmin = res->d;
445+
comp->dj = res->d;
446+
comp->j = res->j;
469447
}, CREATECOMPAREVEC_STR64)
470448

471449
JIT_STR(void MF_CreateCompareVec32(MF_compareTuple32 *comp,
472450
const MF_resultTuple32 *res, const int32_t *height) {
473451
comp->di = (*height);
474-
comp->j = res->j;
475452
comp->residual = res->residual;
476-
comp->y_dmin = res->d;
453+
comp->dj = res->d;
454+
comp->j = res->j;
477455
comp->unused = 0 ;
478456
}, CREATECOMPAREVEC_STR32)
479457

480458
//------------------------------------------------------------------------------
481-
// select op to remove empty tuples from y (for which y->j is -1)
459+
// index unary op to remove empty tuples from y (for which y->j is -1)
482460
//------------------------------------------------------------------------------
483461

484462
JIT_STR(void MF_Prune64(bool * z, const MF_resultTuple64 * x,
485463
GrB_Index ix, GrB_Index jx, const int64_t * theta){
486-
*z = (x->j != *theta) ;
464+
*z = (x->j != -1) ;
487465
}, PRUNE_STR64)
488466

489467
JIT_STR(void MF_Prune32(bool * z, const MF_resultTuple32 * x,
490468
GrB_Index ix, GrB_Index jx, const int32_t * theta){
491-
*z = (x->j != *theta) ;
469+
*z = (x->j != -1) ;
492470
}, PRUNE_STR32)
493471

494472
//------------------------------------------------------------------------------
@@ -605,14 +583,13 @@ int LAGr_MaxFlow
605583
GrB_BinaryOp MxeAdd = NULL, MxeMult = NULL ;
606584
GxB_IndexBinaryOp MxeIndexMult = NULL ;
607585

608-
// residual flow vector
609-
GrB_Vector residual_vec = NULL ;
586+
// to extract the residual flow
610587
GrB_UnaryOp ExtractResidualFlow = NULL ;
611588
GrB_UnaryOp ExtractMatrixFlow = NULL ;
612589

613-
// delta structures
590+
// Delta structures
614591
GrB_Vector delta_vec = NULL ;
615-
GrB_Matrix delta = NULL, delta_mat = NULL ;
592+
GrB_Matrix Delta = NULL ;
616593

617594
// update height
618595
GrB_BinaryOp UpdateHeight = NULL ;
@@ -631,7 +608,7 @@ int LAGr_MaxFlow
631608
bool check_raw;
632609

633610
// descriptor for matrix building
634-
GrB_Descriptor extract_desc = NULL ;
611+
GrB_Descriptor desc = NULL ;
635612

636613
//----------------------------------------------------------------------------
637614
// check inputs
@@ -709,11 +686,8 @@ int LAGr_MaxFlow
709686
GRB_TRY (GrB_Vector_setElement (src_and_sink, true, sink)) ;
710687
GRB_TRY (GrB_Vector_setElement (src_and_sink, true, src)) ;
711688

712-
//create flow vec
713-
GRB_TRY(GrB_Vector_new(&residual_vec, GrB_FP64, n));
714-
715-
GRB_TRY(GrB_Matrix_new(&delta_mat, GrB_FP64, n, n));
716-
GRB_TRY(GrB_Matrix_new(&delta, GrB_FP64, n, n));
689+
// create delta vector and Delta matrix
690+
GRB_TRY(GrB_Matrix_new(&Delta, GrB_FP64, n, n));
717691
GRB_TRY(GrB_Vector_new(&delta_vec, GrB_FP64, n));
718692

719693
// operator to update R structure
@@ -899,9 +873,9 @@ int LAGr_MaxFlow
899873

900874
int64_t iter = 0;
901875

902-
// create descriptor for building the Map and delta matrices
903-
GRB_TRY(GrB_Descriptor_new(&extract_desc));
904-
GRB_TRY(GrB_set(extract_desc, GxB_USE_INDICES, GxB_ROWINDEX_LIST));
876+
// create descriptor for building the Map and Delta matrices
877+
GRB_TRY(GrB_Descriptor_new(&desc));
878+
GRB_TRY(GrB_set(desc, GxB_USE_INDICES, GxB_ROWINDEX_LIST));
905879

906880
//----------------------------------------------------------------------------
907881
// compute the max flow
@@ -972,8 +946,8 @@ int LAGr_MaxFlow
972946
// y<struct(e),replace> = R*d using the RxdSemiring
973947
GRB_TRY(GrB_mxv(y, e, NULL, RxdSemiring, R, d, GrB_DESC_RS));
974948

975-
// remove empty tuples from y
976-
GRB_TRY(GrB_select(y, NULL, NULL, Prune, y, -1, NULL));
949+
// remove empty tuples (0,inf,-1) from y
950+
GRB_TRY(GrB_select(y, NULL, NULL, Prune, y, 0, NULL));
977951

978952
//--------------------------------------------------------------------------
979953
// Part 3: verifying the pushes
@@ -986,7 +960,7 @@ int LAGr_MaxFlow
986960
// Jvec = extractJ (yd), where Jvec(i) = yd(i)->j
987961
GRB_TRY(GrB_apply(Jvec, NULL, NULL, extractJ, yd, NULL));
988962
GRB_TRY(GrB_Matrix_clear(Map));
989-
GRB_TRY(GxB_Matrix_build_Vector(Map, yd, Jvec, yd, GxB_IGNORE_DUP, extract_desc));
963+
GRB_TRY(GrB_Matrix_build(Map, yd, Jvec, yd, GxB_IGNORE_DUP, desc));
990964

991965
// make e dense for Map computation
992966
// TODO: consider keeping e in bitmap/full format only,
@@ -1016,30 +990,30 @@ int LAGr_MaxFlow
1016990
//--------------------------------------------------------------------------
1017991

1018992
// extract residual flows from y
1019-
// residual_vec = ExtractResidualFlow (y), obtaining just the residual flows
1020-
GRB_TRY(GrB_apply(residual_vec, NULL, NULL, ExtractResidualFlow, y, NULL));
993+
// delta_vec = ExtractResidualFlow (y), obtaining just the residual flows
994+
GRB_TRY(GrB_apply(delta_vec, NULL, NULL, ExtractResidualFlow, y, NULL));
1021995

1022-
// delta_vec = min (residual_vec, e), where e is dense
1023-
GRB_TRY(GrB_eWiseMult(delta_vec, NULL, NULL, GrB_MIN_FP64, residual_vec, e, NULL));
996+
// delta_vec = min (delta_vec, e), where e is dense
997+
GRB_TRY(GrB_eWiseMult(delta_vec, NULL, NULL, GrB_MIN_FP64, delta_vec, e, NULL));
1024998

1025-
// create the delta matrix from delta_vec and y
999+
// create the Delta matrix from delta_vec and y
10261000
// note that delta_vec has the same structure as y
10271001
// Jvec = extractYJ (y), where Jvec(i) = y(i)->j
10281002
GRB_TRY(GrB_apply(Jvec, NULL, NULL, extractYJ, y, NULL));
1029-
GRB_TRY(GrB_Matrix_clear(delta));
1030-
GRB_TRY(GxB_Matrix_build_Vector(delta, delta_vec, Jvec, delta_vec, GxB_IGNORE_DUP, extract_desc));
1003+
GRB_TRY(GrB_Matrix_clear(Delta));
1004+
GRB_TRY(GrB_Matrix_build(Delta, delta_vec, Jvec, delta_vec, GxB_IGNORE_DUP, desc));
10311005

1032-
// make delta anti-symmetric
1033-
// delta_mat = (delta - delta')
1034-
GRB_TRY(GxB_eWiseUnion(delta_mat, NULL, NULL, GrB_MINUS_FP64, delta, zero, delta, zero, GrB_DESC_T1));
1006+
// make Delta anti-symmetric
1007+
// Delta = (Delta - Delta')
1008+
GRB_TRY(GxB_eWiseUnion(Delta, NULL, NULL, GrB_MINUS_FP64, Delta, zero, Delta, zero, GrB_DESC_T1));
10351009

10361010
// update R
1037-
// R<delta_mat> = UpdateFlow (R, delta_mat) using eWiseMult
1038-
GRB_TRY(GrB_eWiseMult(R, delta_mat, NULL, UpdateFlow, R, delta_mat, GrB_DESC_S));
1011+
// R<Delta> = UpdateFlow (R, Delta) using eWiseMult
1012+
GRB_TRY(GrB_eWiseMult(R, Delta, NULL, UpdateFlow, R, Delta, GrB_DESC_S));
10391013

1040-
// reduce delta_mat to delta_vec
1041-
// delta_vec = sum (delta_mat), summing up each row of delta_mat
1042-
GRB_TRY(GrB_reduce(delta_vec, NULL, NULL, GrB_PLUS_FP64, delta_mat, GrB_DESC_T0));
1014+
// reduce Delta to delta_vec
1015+
// delta_vec = sum (Delta), summing up each row of Delta
1016+
GRB_TRY(GrB_reduce(delta_vec, NULL, NULL, GrB_PLUS_FP64, Delta, GrB_DESC_T0));
10431017

10441018
// add delta_vec to e
10451019
// e<struct(delta_vec)> += delta_vec

0 commit comments

Comments
 (0)