1515
1616//------------------------------------------------------------------------------
1717
18+ // TODO: work in progress (flow_matrix and global relabel)
19+
1820// LAGr_MaxFlow is a GraphBLAS implementation of the push-relabel algorithm
1921// of Baumstark et al. [1]
2022//
2729#include "LG_internal.h"
2830#include <LAGraph.h>
2931
32+ //#define DBG
3033#if LG_SUITESPARSE_GRAPHBLAS_V10
3134
3235//------------------------------------------------------------------------------
@@ -90,6 +93,8 @@ static GrB_Info LG_global_relabel
9093 GrB_Index sink , // sink node
9194 GrB_Vector src_and_sink , // mask vector, with just [src sink]
9295 GrB_UnaryOp GetResidual , // unary op to compute resid=capacity-flow
96+ GrB_BinaryOp global_relabel_accum , // accum for the disconnected assign
97+ GrB_Index relabel_value , // value to relabel the disconnected nodes
9398 // input/output:
9499 GrB_Vector d , // d(i) = height/label of node i
95100 // outputs:
@@ -116,10 +121,10 @@ static GrB_Info LG_global_relabel
116121 LG_TRY (LAGraph_Cached_OutDegree (G2 , msg ));
117122 // compute lvl using bfs on G2, starting at sink node
118123 LG_TRY (LAGr_BreadthFirstSearch (lvl , NULL , G2 , sink , msg ));
119- // d<!struct([src,sink])> = lvl
120- GRB_TRY (GrB_assign (d , src_and_sink , NULL , * lvl , GrB_ALL , n , GrB_DESC_SC ));
121- // d<!struct(lvl)> = n
122- GRB_TRY (GrB_assign (d , * lvl , NULL , n , GrB_ALL , n , GrB_DESC_SC ));
124+ // d<!struct([src,sink])> = max(d(i), lvl)
125+ GRB_TRY (GrB_assign (d , src_and_sink , global_relabel_accum , * lvl , GrB_ALL , n , GrB_DESC_SC ));
126+ // d<!struct(lvl)> = max(d(i), relabel_value)
127+ GRB_TRY (GrB_assign (d , * lvl , global_relabel_accum , relabel_value , GrB_ALL , n , GrB_DESC_SC ));
123128 LG_FREE_WORK ;
124129 return (GrB_SUCCESS ) ;
125130}
@@ -459,7 +464,7 @@ JIT_STR(void LG_MF_MxeMult32(LG_MF_resultTuple32 * z,
459464 bool j_active = ((* y ) > 0 ) ;
460465 if ((x -> di < x -> dj - 1 ) /* case a */
461466 || (x -> di == x -> dj - 1 && !j_active ) /* case b */
462- || (x -> di == x -> dj && (!j_active || (j_active && (i < j )))) /* case c */
467+ || (x -> di == x -> dj && (!j_active || (j_active && (i < j )))) /* case c */
463468 || (x -> di == x -> dj + 1 )) /* case d */
464469 {
465470 z -> residual = x -> residual ;
@@ -564,6 +569,28 @@ JIT_STR(void LG_MF_ExtractMatrixFlow(double* flow, const LG_MF_flowEdge* edge){*
564569
565570#endif
566571
572+ #ifdef DBG
573+ void print_compareVec (const GrB_Vector vec ) {
574+ GxB_Iterator iter ;
575+ GxB_Iterator_new (& iter );
576+ GrB_Info info = GxB_Vector_Iterator_attach (iter , vec , NULL );
577+ if (info < 0 ){
578+ printf ("error with matrix passed in" );
579+ }
580+ info = GxB_Vector_Iterator_seek (iter , 0 );
581+ while (info != GxB_EXHAUSTED ){
582+ GrB_Index i ;
583+ i = GxB_Vector_Iterator_getIndex (iter );
584+ LG_MF_compareTuple32 e ;
585+ GxB_Iterator_get_UDT (iter , & e );
586+ printf ("(%ld, 0) (di: %d, dj: %d, J: %d, residual: %lf) \n" , i , e .di , e .dj , e .j , e .residual );
587+ info = GxB_Vector_Iterator_next (iter );
588+ }
589+ GrB_free (& iter );
590+ }
591+ #endif
592+
593+
567594//------------------------------------------------------------------------------
568595// LAGraph_MaxFlow
569596//------------------------------------------------------------------------------
@@ -766,6 +793,9 @@ int LAGr_MaxFlow
766793
767794 GrB_Type Integer_Type = NULL ;
768795
796+ //accum operator for the global relabel
797+ GrB_BinaryOp global_relabel_accum = NULL ;
798+
769799 #ifdef COVERAGE
770800 // Just for test coverage, use 64-bit ints for n > 100. Do not use this
771801 // rule in production!
@@ -782,6 +812,9 @@ int LAGr_MaxFlow
782812
783813 Integer_Type = GrB_INT64 ;
784814
815+ // use the 64 bit max operator
816+ global_relabel_accum = GrB_MAX_INT64 ;
817+
785818 // create types for computation
786819 GRB_TRY (GxB_Type_new (& ResultTuple , sizeof (LG_MF_resultTuple64 ),
787820 "LG_MF_resultTuple64" , RESULTTUPLE_STR64 ));
@@ -852,6 +885,9 @@ int LAGr_MaxFlow
852885
853886 Integer_Type = GrB_INT32 ;
854887
888+ // use 32 bit max op
889+ global_relabel_accum = GrB_MAX_INT32 ;
890+
855891 // create types for computation
856892 GRB_TRY (GxB_Type_new (& ResultTuple , sizeof (LG_MF_resultTuple32 ),
857893 "LG_MF_resultTuple32" , RESULTTUPLE_STR32 ));
@@ -943,8 +979,14 @@ int LAGr_MaxFlow
943979 GRB_TRY (GrB_apply (R , A , NULL , ResidualBackward , AT , GrB_DESC_SC ));
944980
945981 // initial global relabeling
946- LG_TRY (LG_global_relabel (R , sink , src_and_sink , GetResidual , d , & lvl , msg )) ;
947-
982+ // relabel to 2*n to prevent any flow from going to the
983+ // disconnected nodes.
984+ GrB_Index relabel_value = 2 * n ;
985+ LG_TRY (LG_global_relabel (R , sink , src_and_sink , GetResidual , global_relabel_accum , relabel_value , d , & lvl , msg )) ;
986+
987+ // reset to n
988+ relabel_value = n ;
989+
948990 // create excess vector e and initial flows from the src to its neighbors
949991 // e<struct(lvl)> = A (src,:)
950992 GRB_TRY (GrB_Vector_new (& e , GrB_FP64 , n ));
@@ -968,20 +1010,27 @@ int LAGr_MaxFlow
9681010
9691011 for (int64_t iter = 0 ; n_active > 0 ; iter ++ )
9701012 {
971-
1013+ #ifdef DBG
1014+ printf ("iter: %ld, n_active %ld\n" , iter , n_active ) ;
1015+ #endif
9721016 //--------------------------------------------------------------------------
9731017 // Part 1: global relabeling
9741018 //--------------------------------------------------------------------------
9751019
976- if ((iter > 0 ) && ( flow_mtx != NULL ) && (iter % 12 == 0 ))
1020+ if ((iter > 0 ) && (iter % 12 == 0 ))
9771021 {
978- LG_TRY (LG_global_relabel (R , sink , src_and_sink , GetResidual , d , & lvl , msg )) ;
979- // delete nodes in e that cannot be reached from the sink
980- // e<!struct(lvl)> = empty scalar
981- GrB_assign (e , lvl , NULL , empty , GrB_ALL , n , GrB_DESC_SC ) ;
1022+ #ifdef DBG
1023+ printf ("relabel at : %ld\n" , iter ) ;
1024+ #endif
1025+ LG_TRY (LG_global_relabel (R , sink , src_and_sink , GetResidual , global_relabel_accum , relabel_value , d , & lvl , msg )) ;
1026+ if (flow_mtx == NULL ){
1027+ // delete nodes in e that cannot be reached from the sink
1028+ // e<!struct(lvl)> = empty scalar
1029+ GrB_assign (e , lvl , NULL , empty , GrB_ALL , n , GrB_DESC_SC ) ;
1030+ GRB_TRY (GrB_Vector_nvals (& n_active , e ));
1031+ if (n_active == 0 ) break ;
1032+ }
9821033 GrB_free (& lvl );
983- GRB_TRY (GrB_Vector_nvals (& n_active , e ));
984- if (n_active == 0 ) break ;
9851034 }
9861035
9871036 //--------------------------------------------------------------------------
@@ -1001,6 +1050,14 @@ int LAGr_MaxFlow
10011050 // create Map matrix from pattern and values of yd
10021051 // yd = CreateCompareVec (y,d) using eWiseMult
10031052 GRB_TRY (GrB_eWiseMult (yd , NULL , NULL , CreateCompareVec , y , d , NULL ));
1053+
1054+ #ifdef DBG
1055+ print_compareVec (yd );
1056+ GxB_print (d , 3 );
1057+ GxB_print (e , 3 );
1058+ #endif
1059+
1060+
10041061 // Jvec = ExtractJ (yd), where Jvec(i) = yd(i)->j
10051062 GRB_TRY (GrB_apply (Jvec , NULL , NULL , ExtractJ , yd , NULL ));
10061063 GRB_TRY (GrB_Matrix_clear (Map ));
@@ -1043,7 +1100,12 @@ int LAGr_MaxFlow
10431100 // create the Delta matrix from delta_vec and y
10441101 // note that delta_vec has the same structure as y
10451102 // Jvec = ExtractYJ (y), where Jvec(i) = y(i)->j
1103+ // if Jvec has no values, then there is no possible
1104+ // candidates to push to, so the algorithm terminates
10461105 GRB_TRY (GrB_apply (Jvec , NULL , NULL , ExtractYJ , y , NULL ));
1106+ GrB_Index J_n ;
1107+ GRB_TRY (GrB_Vector_nvals (& J_n , Jvec ));
1108+ if (J_n == 0 ) break ;
10471109 GRB_TRY (GrB_Matrix_clear (Delta ));
10481110 GRB_TRY (GrB_Matrix_build (Delta , delta_vec , Jvec , delta_vec , GxB_IGNORE_DUP , desc ));
10491111
@@ -1057,14 +1119,15 @@ int LAGr_MaxFlow
10571119
10581120 // reduce Delta to delta_vec
10591121 // delta_vec = sum (Delta), summing up each row of Delta
1060- GRB_TRY (GrB_reduce (delta_vec , NULL , NULL , GrB_PLUS_FP64 , Delta , GrB_DESC_T0 ));
1122+ GRB_TRY (GrB_reduce (delta_vec , NULL , NULL , GrB_PLUS_MONOID_FP64 , Delta , GrB_DESC_T0 ));
10611123
10621124 // add delta_vec to e
10631125 // e<struct(delta_vec)> += delta_vec
10641126 GRB_TRY (GrB_assign (e , delta_vec , GrB_PLUS_FP64 , delta_vec , GrB_ALL , n , GrB_DESC_S ));
10651127
10661128 // augment maxflow for all active nodes
10671129 LG_TRY (LG_augment_maxflow (f , e , sink , src_and_sink , & n_active , msg )) ;
1130+
10681131 }
10691132
10701133 //----------------------------------------------------------------------------
0 commit comments