Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 26 additions & 13 deletions experimental/algorithm/LAGraph_MinCut.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,22 @@
// [2] D. Peries and T. Davis, "A parallel push-relabel maximum flow algorithm
// in LAGraph and GraphBLAS", IEEE HPEC'25, Sept 2025.

// FIXME: add more discussion here. Something about the algorithm, and
// document inputs and outputs.
// [10] A. V. Goldberg and R. E. Tarjan, “A new approach to the maximum
// flow problem,” in Proc. 18th Annual ACM Symp. Theory of Computing,
// STOC ’86, p. 136–146, ACM, 1986.

// The algorithm takes the residual graph produced by the max flow and runs a
// single breadth-first search from the original source node used in the
// Max Flow. The algorithm returns the set of nodes, S, which are reachable
// from the source, and the set of nodes, S_bar, that are not. Additionally
// The algorithm returns the set of weigthed edges that are included in cut.


// Example: First use the max flow algorithm on a weighted graph with no
// negative edge weights. The optional parameter to generate the R matrix must
// be set. Then take the original graph, the R matrix, and the original
// source node and input them into the parameters of the algorithm.

// Give example of use

//------------------------------------------------------------------------------

Expand Down Expand Up @@ -61,13 +73,9 @@ int LAGraph_MinCut
GrB_Vector* S_bar,
GrB_Matrix* cut_set,
// inputs
LAGraph_Graph G_origin, // swap G_origin and R
GrB_Matrix R,

// inputs (also to MaxFlow):
// G_origin
GrB_Index s, // src: FIXME
GrB_Index t, // sink: FIXME delete me!
LAGraph_Graph G_origin, // swap G_origin and R
GrB_Index src, // src: FIXME
char *msg
)
{
Expand All @@ -79,29 +87,34 @@ int LAGraph_MinCut
GrB_Index n = 0;
GrB_Matrix_nrows(&n, R);

// Input checks
LG_TRY(LAGraph_CheckGraph(G_origin, msg));
LG_ASSERT (S != NULL, GrB_NULL_POINTER) ;
LG_ASSERT (S_bar != NULL, GrB_NULL_POINTER) ;
LG_ASSERT (cut_set != NULL, GrB_NULL_POINTER) ;
LG_ASSERT (s < n && t < n, GrB_INVALID_VALUE) ;
LG_ASSERT (src < n, GrB_INVALID_VALUE) ;

GrB_Matrix A = G_origin->A;


// construct the outputs
LG_TRY(GrB_Matrix_new(cut_set, GrB_FP64, n, n));
LG_TRY(GrB_Vector_new(S_bar, GrB_FP64, n));
LG_TRY(GrB_Vector_new(S, GrB_FP64, n));

// create graph from R for the BFS
LG_TRY(LAGraph_New(&G, &R, LAGraph_ADJACENCY_DIRECTED, msg));

//S_bfs is allocated during the bfs
LG_TRY(LAGr_BreadthFirstSearch(&S_bfs, NULL, G, s, msg));
// S_bfs is allocated during the bfs
LG_TRY(LAGr_BreadthFirstSearch(&S_bfs, NULL, G, src, msg));

LG_TRY(GrB_assign(*S_bar, S_bfs, NULL, 1, GrB_ALL, n, GrB_DESC_SC));
// set compliment for unreachable nodes.
LG_TRY(GrB_assign(*S, S_bfs, NULL, 1, GrB_ALL, n, GrB_DESC_S));

GRB_TRY(GrB_Matrix_diag(&S_diag, *S, 0));
GRB_TRY(GrB_Matrix_diag(&S_bar_diag, *S_bar, 0));

// used to compute the set of cut edges.
GRB_TRY(GrB_mxm(*cut_set, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, A, S_bar_diag, NULL));
GRB_TRY(GrB_mxm(*cut_set, NULL, NULL, GrB_PLUS_TIMES_SEMIRING_FP64, S_diag, *cut_set, NULL));

Expand Down
21 changes: 19 additions & 2 deletions experimental/test/test_MinCut.c
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
//------------------------------------------------------------------------------
// experimental/test/test_MinCut: tests for LAGraph_MinCut
//------------------------------------------------------------------------------

// LAGraph, (c) 2019-2022 by The LAGraph Contributors, All Rights Reserved.
// SPDX-License-Identifier: BSD-2-Clause
//
// For additional details (including references to third party source code and
// other files) see the LICENSE file or contact permission@sei.cmu.edu. See
// Contributors.txt for a full list of contributors. Created, in part, with
// funding and support from the U.S. Government (see Acknowledgments.txt file).
// DM22-0790

// Contributed by Darin Peries and Tim Davis, Texas A&M University

//------------------------------------------------------------------------------


#include <stdio.h>
#include <acutest.h>
#include <LAGraphX.h>
Expand Down Expand Up @@ -67,15 +85,14 @@ void test_MinCut() {
printf("%s\n", msg);
printf("flow is: %lf\n", flow);

OK(LAGraph_MinCut(&S, &S_bar, &cut_set, G, R, tests[test].s, tests[test].t, msg));
OK(LAGraph_MinCut(&S, &S_bar, &cut_set, R, G, tests[test].s, msg));
printf("%s\n", msg);

OK(GrB_reduce(&min_cut, NULL, GrB_PLUS_MONOID_FP64, cut_set, NULL));

TEST_CHECK(flow == min_cut);
printf("The min cut: %lf\n", min_cut);

GrB_free(&A);
GrB_free(&R);
GrB_free(&S);
GrB_free(&S_bar);
Expand Down
5 changes: 2 additions & 3 deletions include/LAGraphX.h
Original file line number Diff line number Diff line change
Expand Up @@ -1523,10 +1523,9 @@ int LAGraph_MinCut(
GrB_Vector* S_bar,
GrB_Matrix* cut_set,
// inputs
LAGraph_Graph G_origin, //original graph with capacities
GrB_Matrix R, //residual graph
GrB_Index s, //source node index
GrB_Index t, //sink node index
LAGraph_Graph G_origin, //original graph with capacities
GrB_Index src, //source node index from max flow
char *msg
);

Expand Down
78 changes: 78 additions & 0 deletions src/utility/LAGraph_DMRead.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "LG_internal.h"

#define BUFF_SIZE 1024

#undef LG_FREE_ALL
#undef LG_FREE_WORK

#define LG_FREE_WORK LG_FREE_ALL
#define LG_FREE_ALL \
{ \
free(rows) ; \
free(cols) ; \
free(weights); \
}

static int LAGraph_DMRead(
GrB_Matrix* A,
GrB_Index* s,
GrB_Index* t,
FILE* f,
char* msg
)
{
ASSERT(file != NULL) ;

int32_t n_nodes = 0, n_edges = 0 ;
GrB_Index *rows = NULL, *cols = NULL, *weights = NULL ; //what data type whould the weights be?? Should this be in 32 or 64 bit?

char buff[BUFF_SIZE];

int64_t line_count = 0 ;

while (fgets(buff, BUFF_SIZE, f))
{
if (buff[0] == 'c' || buff[0] == '\0' || buff[0] == '\n') continue;

if (buff[0] == 'p')
{
ASSERT(scanf(buff, "p max %d %d", n_nodes, n_edges) != 2) ;
rows = (GrB_Index *) malloc(n_edges * sizeof(GrB_Index)) ;
cols = (GrB_Index *) malloc(n_edges * sizeof(GrB_Index)) ;
weights = (GrB_Index *) malloc(n_edges * sizeof(GrB_Index)) ;
}

if (buff[0] == 'n')
{
GrB_Index value = 0 ;
char which = ' ';
ASSERT(scanf(buff, "n %d, %c", value, which) != 2) ;

switch (which) {
case 's':
*s = value ;
break ;
case 't':
*t = value ;
break;
default:
break;
}
}

if (buff[0] == 'a')
{
GrB_Index r = 0, c = 0, w = 0 ;
ASSERT(scanf(buff, "a %d %d %d", r, c, w) != 2) ;
rows[line_count] = r ;
cols[line_count] = c ;
weights[line_count] = w ;
line_count++ ;
}
}

GRB_TRY(GrB_Matrix_build_INT64(*A, rows, cols, weights, n_edges, NULL)) ;

LG_FREE_ALL ;
return (GrB_SUCCESS) ;
}
Loading