Skip to content

Commit fb56470

Browse files
Merge pull request #390 from dperry17/Min-Cut-dev
Min cut dev
2 parents df49066 + 7cd79f4 commit fb56470

File tree

7 files changed

+211
-8
lines changed

7 files changed

+211
-8
lines changed

data/test_zero_cap.mtx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
%%MatrixMarket matrix coordinate real general
2+
% Example weighted directed graph adjacency (1-indexed)
3+
% All weights are positive; some edges explicitly have zero weight
4+
5 5 9
5+
1 2 0.500000
6+
1 4 0.000000
7+
2 3 1.250000
8+
2 5 2.000000
9+
3 1 0.000000
10+
3 4 3.141590
11+
4 2 0.750000
12+
5 4 0.125000
13+
5 5 1.000000

experimental/algorithm/LAGr_MaxFlow.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,7 @@ int LAGr_MaxFlow
612612
// output:
613613
double *f, // max flow from src node to sink node
614614
GrB_Matrix *flow_mtx, // optional output flow matrix
615+
GrB_Matrix *res_mtx, // optional output for the residual matrix. Used in the min-cut
615616
// input:
616617
LAGraph_Graph G, // graph to compute maxflow on
617618
GrB_Index src, // source node
@@ -711,6 +712,10 @@ int LAGr_MaxFlow
711712
{
712713
(*flow_mtx) = NULL ;
713714
}
715+
if (res_mtx != NULL)
716+
{
717+
(*res_mtx) = NULL ;
718+
}
714719
LG_TRY(LAGraph_CheckGraph(G, msg));
715720
LG_ASSERT (f != NULL, GrB_NULL_POINTER) ;
716721
(*f) = 0;
@@ -720,6 +725,7 @@ int LAGr_MaxFlow
720725
LG_ASSERT_MSG(nrows == n, GrB_INVALID_VALUE, "Matrix must be square");
721726
LG_ASSERT_MSG(src < n && src >= 0 && sink < n && sink >= 0,
722727
GrB_INVALID_VALUE, "src and sink must be a value between [0, n)");
728+
LG_ASSERT(G->emin_state != LAGraph_BOOLEAN_UNKNOWN, GrB_UNINITIALIZED_OBJECT) ;
723729
LG_ASSERT_MSG(G->emin > 0, GrB_INVALID_VALUE,
724730
"the edge weights (capacities) must be greater than 0");
725731

@@ -1160,6 +1166,13 @@ int LAGr_MaxFlow
11601166
GRB_TRY(GrB_select(*flow_mtx, NULL, NULL, GrB_VALUEGT_FP64, *flow_mtx, 0, NULL));
11611167
}
11621168

1169+
if(res_mtx != NULL){
1170+
GRB_TRY(GrB_Matrix_new(res_mtx, GrB_FP64, n, n));
1171+
GRB_TRY(GrB_apply(*res_mtx, NULL, NULL, GetResidual, R, NULL)) ;
1172+
// prune zeros and negative entries from R_hat
1173+
GRB_TRY(GrB_select(*res_mtx, NULL, NULL, GrB_VALUEGT_FP64, *res_mtx, 0, NULL)) ;
1174+
}
1175+
11631176
//----------------------------------------------------------------------------
11641177
// for test coverage only
11651178
//----------------------------------------------------------------------------
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#include <LAGraph.h>
2+
#include "LG_internal.h"
3+
#include <LAGraph.h>
4+
5+
#undef LG_FREE_ALL
6+
#undef LG_FREE_WORK
7+
8+
#define LG_FREE_WORK \
9+
{ \
10+
GrB_free(&S_diag); \
11+
GrB_free(&S_bar_diag); \
12+
LAGraph_Delete(&G, msg); \
13+
}
14+
15+
#define LG_FREE_ALL \
16+
{ LG_FREE_WORK }
17+
18+
int LAGraph_MinCut
19+
(
20+
// outputs
21+
GrB_Vector* S,
22+
GrB_Vector* S_bar,
23+
GrB_Matrix* cut_set,
24+
// inputs
25+
LAGraph_Graph G_origin,
26+
GrB_Matrix R,
27+
GrB_Index s,
28+
GrB_Index t,
29+
char *msg
30+
)
31+
{
32+
//do a bfs from the source to the sink, stop if the frontier is empty
33+
34+
LAGraph_Graph G = NULL;
35+
GrB_Matrix S_diag=NULL, S_bar_diag=NULL;
36+
GrB_Index n = 0;
37+
GrB_Matrix_nrows(&n, R);
38+
39+
LG_TRY(LAGraph_CheckGraph(G_origin, msg));
40+
LG_ASSERT (S != NULL, GrB_NULL_POINTER) ;
41+
LG_ASSERT (S_bar != NULL, GrB_NULL_POINTER) ;
42+
LG_ASSERT (cut_set != NULL, GrB_NULL_POINTER) ;
43+
LG_ASSERT (s >= 0 && t >= 0, GrB_INVALID_VALUE) ;
44+
45+
// printf("hit\n");
46+
GrB_Matrix A = G_origin->A;
47+
48+
LG_TRY(GrB_Matrix_new(cut_set, GrB_FP64, n, n));
49+
LG_TRY(GrB_Vector_new(S_bar, GrB_INT64, n));
50+
//S is allocated during the bfs
51+
52+
LG_TRY(LAGraph_New(&G, &R, LAGraph_ADJACENCY_DIRECTED, msg));
53+
LG_TRY(LAGr_BreadthFirstSearch(S, NULL, G, s, msg));
54+
55+
56+
LG_TRY(GrB_assign(*S_bar, *S, NULL, 1, GrB_ALL, n, GrB_DESC_SC));
57+
LG_TRY(GrB_assign(*S, *S, NULL, 1, GrB_ALL, n, GrB_DESC_S));
58+
59+
GRB_TRY(GrB_Matrix_diag(&S_diag, *S, 0));
60+
GRB_TRY(GrB_Matrix_diag(&S_bar_diag, *S_bar, 0));
61+
62+
63+
GRB_TRY(GrB_mxm(*cut_set, NULL, NULL, GxB_PLUS_TIMES_INT64, A, S_bar_diag, NULL));
64+
GRB_TRY(GrB_mxm(*cut_set, NULL, NULL, GxB_PLUS_TIMES_INT64, S_diag, *cut_set, NULL));
65+
66+
67+
LG_FREE_ALL;
68+
return (GrB_SUCCESS);
69+
}

experimental/benchmark/maxflow_demo.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,15 @@ int main (int argc, char ** argv){
5858

5959
// LG_SET_BURBLE(1);
6060
double time = LAGraph_WallClockTime();
61-
LAGRAPH_TRY(LAGr_MaxFlow(&flow, NULL, G, S, T, msg));
61+
LAGRAPH_TRY(LAGr_MaxFlow(&flow, NULL, NULL, G, S, T, msg));
6262
time = LAGraph_WallClockTime() - time;
6363
printf("Time for LAGraph_MaxFlow: %g sec\n", time);
6464
printf("Max Flow is: %lf\n", flow);
6565

6666
printf("Starting max flow from %" PRIu64 " to %" PRIu64
6767
", with flow_matrix returned\n", S, T);
6868
time = LAGraph_WallClockTime();
69-
LAGRAPH_TRY(LAGr_MaxFlow(&flow, &flow_matrix, G, S, T, msg));
69+
LAGRAPH_TRY(LAGr_MaxFlow(&flow, &flow_matrix, NULL, G, S, T, msg));
7070
time = LAGraph_WallClockTime() - time;
7171
printf("Time for LAGraph_MaxFlow with flow matrix: %g sec\n", time);
7272
printf("Max Flow is: %lf\n", flow);

experimental/test/test_MaxFlow.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ GrB_Matrix A = NULL;
3030
#ifdef GRAPHBLAS_HAS_CUDA
3131
#define NTESTS 4
3232
#else
33-
#define NTESTS 7
33+
#define NTESTS 8
3434
#endif
3535
char filename[LEN + 1];
3636

@@ -47,6 +47,7 @@ test_info tests[] = {
4747
{"matrix_random_flow.mtx", 0,9, 22, LAGraph_ADJACENCY_DIRECTED},
4848
{"rand.mtx", 0, 19, 37, LAGraph_ADJACENCY_DIRECTED},
4949
{"mcl.mtx", 0, 9, 0, LAGraph_ADJACENCY_DIRECTED},
50+
{"test_zero_cap.mtx", 0, 4, 0.5, LAGraph_ADJACENCY_DIRECTED},
5051
#ifndef GRAPHBLAS_HAS_CUDA
5152
// FIXME: the CUDA cases are currently very slow for these matrices,
5253
// when the GPU is hacked to always be used regardless of problem size:
@@ -84,14 +85,14 @@ void test_MaxFlow(void) {
8485
// test with JIT
8586
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_ON));
8687
double flow = 0;
87-
OK(LAGr_MaxFlow(&flow, NULL, G, tests[test].S, tests[test].T, msg));
88+
OK(LAGr_MaxFlow(&flow, NULL, NULL, G, tests[test].S, tests[test].T, msg));
8889
printf("%s\n", msg);
8990
printf("flow is: %lf\n", flow);
9091
TEST_CHECK(flow == tests[test].F);
9192

9293
// test without JIT
9394
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_OFF));
94-
OK(LAGr_MaxFlow(&flow, NULL, G, tests[test].S, tests[test].T, msg));
95+
OK(LAGr_MaxFlow(&flow, NULL, NULL, G, tests[test].S, tests[test].T, msg));
9596
TEST_CHECK(flow == tests[test].F);
9697
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_ON));
9798

@@ -107,7 +108,7 @@ void test_MaxFlow(void) {
107108
{
108109
printf("src: %d, dest: %d\n", (int) src, (int) dest);
109110
if (src == dest) continue ;
110-
OK(LAGr_MaxFlow(&flow, NULL, G, src, dest, msg));
111+
OK(LAGr_MaxFlow(&flow, NULL, NULL, G, src, dest, msg));
111112
}
112113
}
113114
}
@@ -152,7 +153,7 @@ void test_MaxFlowMtx(void) {
152153
// test with JIT
153154
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_ON));
154155
double flow = 0;
155-
OK(LAGr_MaxFlow(&flow, &flow_mtx, G, tests[test].S, tests[test].T, msg));
156+
OK(LAGr_MaxFlow(&flow, &flow_mtx, NULL, G, tests[test].S, tests[test].T, msg));
156157
TEST_CHECK (flow_mtx != NULL) ;
157158
GxB_print (flow_mtx, 2) ;
158159
int status = LG_check_flow(flow_mtx, msg);
@@ -165,7 +166,7 @@ void test_MaxFlowMtx(void) {
165166

166167
// test without JIT
167168
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_OFF));
168-
OK(LAGr_MaxFlow(&flow, &flow_mtx, G, tests[test].S, tests[test].T, msg));
169+
OK(LAGr_MaxFlow(&flow, &flow_mtx, NULL, G, tests[test].S, tests[test].T, msg));
169170
TEST_CHECK (flow_mtx != NULL) ;
170171
status = LG_check_flow(flow_mtx, msg);
171172
TEST_CHECK (status == GrB_SUCCESS) ;

experimental/test/test_MinCut.c

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
#include <stdio.h>
2+
#include <acutest.h>
3+
#include <LAGraphX.h>
4+
#include <LAGraph_test.h>
5+
#include <LG_Xtest.h>
6+
7+
8+
char msg[LAGRAPH_MSG_LEN];
9+
LAGraph_Graph G = NULL;
10+
GrB_Matrix A = NULL;
11+
#define LEN 512
12+
#define NTESTS 7
13+
char filename[LEN + 1];
14+
15+
16+
typedef struct {
17+
char* filename;
18+
GrB_Index s;
19+
GrB_Index t;
20+
LAGraph_Kind kind;
21+
} test_case;
22+
23+
test_case tests[] = {
24+
{"wiki.mtx", 0, 5, LAGraph_ADJACENCY_DIRECTED},
25+
{"matrix_random_flow.mtx", 0,9, LAGraph_ADJACENCY_DIRECTED},
26+
{"rand.mtx", 0, 19, LAGraph_ADJACENCY_DIRECTED},
27+
{"mcl.mtx", 0, 9, LAGraph_ADJACENCY_DIRECTED},
28+
{"cycle_flow.mtx", 0, 89, LAGraph_ADJACENCY_DIRECTED},
29+
{"random_weighted_general2.mtx", 0, 299, LAGraph_ADJACENCY_UNDIRECTED},
30+
{"random_weighted_general1.mtx", 0, 499, LAGraph_ADJACENCY_UNDIRECTED}
31+
};
32+
33+
34+
void test_MinCut() {
35+
36+
LAGraph_Init(msg);
37+
#if LG_SUITESPARSE_GRAPHBLAS_V10
38+
OK(LG_SET_BURBLE(0));
39+
for(uint8_t test = 0; test < NTESTS; test++){
40+
GrB_Matrix A=NULL, R=NULL, cut_set=NULL;
41+
GrB_Vector S=NULL, S_bar=NULL;
42+
double min_cut = 0;
43+
GrB_Index n = 0;
44+
printf ("\nMatrix: %s\n", tests[test].filename);
45+
TEST_CASE(tests[test].filename);
46+
47+
snprintf(filename, LEN, LG_DATA_DIR "%s", tests[test].filename);
48+
FILE* f = fopen(filename, "r");
49+
TEST_CHECK(f != NULL);
50+
51+
OK(LAGraph_MMRead(&A, f, msg));
52+
53+
OK(fclose(f));
54+
LAGraph_Kind kind = tests [test].kind ;
55+
OK(LAGraph_New(&G, &A, kind, msg));
56+
if (kind == LAGraph_ADJACENCY_DIRECTED)
57+
{
58+
OK(LAGraph_Cached_AT(G, msg));
59+
}
60+
61+
OK(LAGraph_Cached_EMin(G, msg));
62+
63+
// test with JIT
64+
OK(GxB_Global_Option_set(GxB_JIT_C_CONTROL, GxB_JIT_ON));
65+
double flow = 0;
66+
OK(LAGr_MaxFlow(&flow, NULL, &R, G, tests[test].s, tests[test].t, msg));
67+
printf("%s\n", msg);
68+
printf("flow is: %lf\n", flow);
69+
70+
OK(LAGraph_MinCut(&S, &S_bar, &cut_set, G, R, tests[test].s, tests[test].t, msg));
71+
printf("%s\n", msg);
72+
73+
OK(GrB_reduce(&min_cut, NULL, GrB_PLUS_MONOID_FP64, cut_set, NULL));
74+
75+
TEST_CHECK(flow == min_cut);
76+
printf("The min cut: %lf\n", min_cut);
77+
78+
GrB_free(&A);
79+
GrB_free(&R);
80+
GrB_free(&S);
81+
GrB_free(&S_bar);
82+
GrB_free(&cut_set);
83+
LAGraph_Delete(&G, msg);
84+
}
85+
86+
#endif
87+
88+
89+
LAGraph_Finalize(msg);
90+
91+
}
92+
93+
TEST_LIST = {{"MinCut", test_MinCut}, {NULL, NULL}};

include/LAGraphX.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1507,6 +1507,7 @@ int LAGr_MaxFlow(
15071507
//outputs
15081508
double* f,
15091509
GrB_Matrix* flow_mtx,
1510+
GrB_Matrix* res_mtx,
15101511
//inputs
15111512
LAGraph_Graph G,
15121513
GrB_Index src, //source node index
@@ -1515,6 +1516,19 @@ int LAGr_MaxFlow(
15151516
char* msg
15161517
);
15171518

1519+
LAGRAPHX_PUBLIC
1520+
int LAGraph_MinCut(
1521+
//outputs
1522+
GrB_Vector* S,
1523+
GrB_Vector* S_bar,
1524+
GrB_Matrix* cut_set,
1525+
// inputs
1526+
LAGraph_Graph G_origin, //original graph with capacities
1527+
GrB_Matrix R, //residual graph
1528+
GrB_Index s, //source node index
1529+
GrB_Index t, //sink node index
1530+
char *msg
1531+
);
15181532

15191533
#if defined ( __cplusplus )
15201534
}

0 commit comments

Comments
 (0)