From 4c90003d4d4b49846124fd0367a2e987a0ba10fe Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Fri, 6 Mar 2026 19:22:09 +0300 Subject: [PATCH 1/6] init_commit_reachability --- experimental/algorithm/LAGraph_CFL_Kron.c | 138 ++++++++++++++++++++++ 1 file changed, 138 insertions(+) create mode 100644 experimental/algorithm/LAGraph_CFL_Kron.c diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c new file mode 100644 index 0000000000..af5e72ab8e --- /dev/null +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -0,0 +1,138 @@ +#include +#include +#include +#include + +typedef struct { + GrB_Index state_count; + GrB_Index terminal_count; + GrB_Index nonterminal_count; + GrB_Index start_nonterminal; + GrB_Matrix* terminal_matrices; + GrB_Matrix* nonterminal_matrices; + GrB_Index* start_states; + GrB_Vector* final_states; +} RSM; + +#define LG_FREE_WORK \ + { \ + GrB_free(&M3); \ + LAGraph_Free((void**) &i, NULL); \ + LAGraph_Free((void**) &j, NULL); \ + LAGraph_Free((void**) &V, NULL); \ + } + +GrB_Info transitive_closure_inplace(GrB_Matrix A) { + GrB_Index nvals_old = 0, nvals_new = 0; + GrB_Matrix_nvals(&nvals_old, A); + while (true) { + GrB_mxm(A, NULL, GrB_LOR, GrB_LOR_LAND_SEMIRING_BOOL, A, A, NULL); + GrB_Matrix_nvals(&nvals_new, A); + if (nvals_new == nvals_old) break; + nvals_old = nvals_new; + } + return GrB_SUCCESS; +} + +GrB_Info LAGraph_CFL_AllPaths_Kronecker +( + GrB_Matrix *outputs, + const GrB_Matrix *adj_matrices, + int64_t terms_count, + RSM *rsm, + char *msg +) +{ + GrB_Matrix M3 = NULL; + GrB_Index *i = NULL, *j = NULL; + bool *V = NULL; + + GrB_Index g_dim; + GrB_Matrix_ncols(&g_dim, adj_matrices[0]); + GrB_Index r_dim = rsm->state_count; + GrB_Index kronecker_dim = r_dim * g_dim; + + for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_Matrix_new(&outputs[nt], GrB_BOOL, g_dim, g_dim); + + GrB_Index s = rsm->start_states[nt]; + bool is_final = false; + GrB_Vector_extractElement_BOOL(&is_final, rsm->final_states[nt], s); + + if (is_final) { + for (GrB_Index v = 0; v < g_dim; ++v) { + GrB_Matrix_setElement_BOOL(outputs[nt], true, v, v); + } + } + } + + GrB_Matrix_new(&M3, GrB_BOOL, kronecker_dim, kronecker_dim); + + GrB_Index nvals_old = 0, nvals_new = 0; + bool changed = true; + + while (changed) { + nvals_old = 0; + for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_Index vals; + GrB_Matrix_nvals(&vals, outputs[nt]); + nvals_old += vals; + } + + GrB_Matrix_clear(M3); + + for (int64_t t = 0; t < terms_count; ++t) { + GrB_kronecker(M3, NULL, GrB_LOR, GrB_LAND, + rsm->terminal_matrices[t], adj_matrices[t], NULL); + } + + for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_kronecker(M3, NULL, GrB_LOR, GrB_LAND, + rsm->nonterminal_matrices[nt], outputs[nt], NULL); + } + + transitive_closure_inplace(M3); + + GrB_Index m3_nvals; + GrB_Matrix_nvals(&m3_nvals, M3); + + if (m3_nvals > 0) { + i = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); + j = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); + V = (bool*)malloc(m3_nvals * sizeof(bool)); + + GrB_Matrix_extractTuples_BOOL(i, j, V, &m3_nvals, M3); + + for (GrB_Index k = 0; k < m3_nvals; ++k) { + GrB_Index s = i[k] / g_dim; + GrB_Index f = j[k] / g_dim; + GrB_Index x = i[k] % g_dim; + GrB_Index y = j[k] % g_dim; + + for (GrB_Index nt = 0; nt < rsm->nonterminal_count; ++nt) { + if (rsm->start_states[nt] == s) { + bool is_final = false; + GrB_Vector_extractElement_BOOL(&is_final, rsm->final_states[nt], f); + if (is_final) { + GrB_Matrix_setElement_BOOL(outputs[nt], true, x, y); + } + } + } + } + free(i); free(j); free(V); + i = NULL; j = NULL; V = NULL; + } + + nvals_new = 0; + for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_Index vals; + GrB_Matrix_nvals(&vals, outputs[nt]); + nvals_new += vals; + } + changed = (nvals_new != nvals_old); + } + + LG_FREE_WORK; + return GrB_SUCCESS; +} + From 419123853950df278a6d95008ba9800a9cc7ad0a Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Fri, 6 Mar 2026 20:08:40 +0300 Subject: [PATCH 2/6] Update LAGraph_CFL_Kron.c --- experimental/algorithm/LAGraph_CFL_Kron.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c index af5e72ab8e..205b96d6e2 100644 --- a/experimental/algorithm/LAGraph_CFL_Kron.c +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -1,7 +1,8 @@ #include #include #include -#include +#include +#include typedef struct { GrB_Index state_count; From 043d17c9487ff242b9e2ea69044c761f882b5797 Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Wed, 11 Mar 2026 17:59:46 +0300 Subject: [PATCH 3/6] LOR_LAND -> ANY_PAIR --- experimental/algorithm/LAGraph_CFL_Kron.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c index 205b96d6e2..8c6a48cfe1 100644 --- a/experimental/algorithm/LAGraph_CFL_Kron.c +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -27,7 +27,7 @@ GrB_Info transitive_closure_inplace(GrB_Matrix A) { GrB_Index nvals_old = 0, nvals_new = 0; GrB_Matrix_nvals(&nvals_old, A); while (true) { - GrB_mxm(A, NULL, GrB_LOR, GrB_LOR_LAND_SEMIRING_BOOL, A, A, NULL); + GrB_mxm(A, NULL, GrB_LOR, GxB_ANY_PAIR_BOOL, A, A, NULL); GrB_Matrix_nvals(&nvals_new, A); if (nvals_new == nvals_old) break; nvals_old = nvals_new; @@ -83,13 +83,13 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker GrB_Matrix_clear(M3); for (int64_t t = 0; t < terms_count; ++t) { - GrB_kronecker(M3, NULL, GrB_LOR, GrB_LAND, - rsm->terminal_matrices[t], adj_matrices[t], NULL); + GrB_kronecker(M3, NULL, GrB_LOR, GxB_PAIR_BOOL, + rsm->terminal_matrices[t], adj_matrices[t], NULL); } for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { - GrB_kronecker(M3, NULL, GrB_LOR, GrB_LAND, - rsm->nonterminal_matrices[nt], outputs[nt], NULL); + GrB_kronecker(M3, NULL, GrB_LOR, GxB_PAIR_BOOL, + rsm->nonterminal_matrices[nt], outputs[nt], NULL); } transitive_closure_inplace(M3); From c1c32f8a696b1b661d7758d3916aa6e3a8619481 Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Sat, 14 Mar 2026 22:53:45 +0300 Subject: [PATCH 4/6] the_idea_of_extracting_blocks --- experimental/algorithm/LAGraph_CFL_Kron.c | 43 +++++++++++++++++++---- 1 file changed, 37 insertions(+), 6 deletions(-) diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c index 8c6a48cfe1..58025d6bca 100644 --- a/experimental/algorithm/LAGraph_CFL_Kron.c +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -18,9 +18,9 @@ typedef struct { #define LG_FREE_WORK \ { \ GrB_free(&M3); \ - LAGraph_Free((void**) &i, NULL); \ - LAGraph_Free((void**) &j, NULL); \ - LAGraph_Free((void**) &V, NULL); \ + GrB_free(&TempBlock); \ + LAGraph_Free((void**) &row_indices, NULL); \ + LAGraph_Free((void**) &col_indices, NULL); \ } GrB_Info transitive_closure_inplace(GrB_Matrix A) { @@ -45,8 +45,6 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker ) { GrB_Matrix M3 = NULL; - GrB_Index *i = NULL, *j = NULL; - bool *V = NULL; GrB_Index g_dim; GrB_Matrix_ncols(&g_dim, adj_matrices[0]); @@ -72,6 +70,12 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker GrB_Index nvals_old = 0, nvals_new = 0; bool changed = true; + GrB_Matrix TempBlock; + GrB_Matrix_new(&TempBlock, GrB_BOOL, g_dim, g_dim); + + GrB_Index* row_indices = (GrB_Index*)malloc(g_dim * sizeof(GrB_Index)); + GrB_Index* col_indices = (GrB_Index*)malloc(g_dim * sizeof(GrB_Index)); + while (changed) { nvals_old = 0; for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { @@ -97,7 +101,7 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker GrB_Index m3_nvals; GrB_Matrix_nvals(&m3_nvals, M3); - if (m3_nvals > 0) { + /*if (m3_nvals > 0) { i = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); j = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); V = (bool*)malloc(m3_nvals * sizeof(bool)); @@ -122,6 +126,33 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker } free(i); free(j); free(V); i = NULL; j = NULL; V = NULL; + }*/ + + if (m3_nvals > 0) { + for (GrB_Index nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_Index s = rsm->start_states[nt]; + + for (GrB_Index v = 0; v < g_dim; ++v) { + row_indices[v] = s * g_dim + v; + } + + for (GrB_Index f = 0; f < rsm->state_count; ++f) { + bool is_final = false; + GrB_Vector_extractElement_BOOL(&is_final, rsm->final_states[nt], f); + + if (is_final) { + for (GrB_Index v = 0; v < g_dim; ++v) { + col_indices[v] = f * g_dim + v; + } + + GrB_Matrix_extract(TempBlock, NULL, NULL, M3, + row_indices, g_dim, col_indices, g_dim, NULL); + + GrB_eWiseAdd(outputs[nt], NULL, NULL, GrB_LOR, + outputs[nt], TempBlock, NULL); + } + } + } } nvals_new = 0; From f41e334a006950424c18c4606e0ab445986bcc1b Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Sun, 15 Mar 2026 09:44:47 +0300 Subject: [PATCH 5/6] naming --- experimental/algorithm/LAGraph_CFL_Kron.c | 34 +++++++++++------------ 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c index 58025d6bca..222c220f4f 100644 --- a/experimental/algorithm/LAGraph_CFL_Kron.c +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -17,7 +17,7 @@ typedef struct { #define LG_FREE_WORK \ { \ - GrB_free(&M3); \ + GrB_free(&CombinedGraph); \ GrB_free(&TempBlock); \ LAGraph_Free((void**) &row_indices, NULL); \ LAGraph_Free((void**) &col_indices, NULL); \ @@ -44,7 +44,7 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker char *msg ) { - GrB_Matrix M3 = NULL; + GrB_Matrix CombinedGraph = NULL; GrB_Index g_dim; GrB_Matrix_ncols(&g_dim, adj_matrices[0]); @@ -65,7 +65,7 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker } } - GrB_Matrix_new(&M3, GrB_BOOL, kronecker_dim, kronecker_dim); + GrB_Matrix_new(&CombinedGraph, GrB_BOOL, kronecker_dim, kronecker_dim); GrB_Index nvals_old = 0, nvals_new = 0; bool changed = true; @@ -84,31 +84,31 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker nvals_old += vals; } - GrB_Matrix_clear(M3); + GrB_Matrix_clear(CombinedGraph); for (int64_t t = 0; t < terms_count; ++t) { - GrB_kronecker(M3, NULL, GrB_LOR, GxB_PAIR_BOOL, + GrB_kronecker(CombinedGraph, NULL, GrB_LOR, GxB_PAIR_BOOL, rsm->terminal_matrices[t], adj_matrices[t], NULL); } for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { - GrB_kronecker(M3, NULL, GrB_LOR, GxB_PAIR_BOOL, + GrB_kronecker(CombinedGraph, NULL, GrB_LOR, GxB_PAIR_BOOL, rsm->nonterminal_matrices[nt], outputs[nt], NULL); } - transitive_closure_inplace(M3); + transitive_closure_inplace(CombinedGraph); - GrB_Index m3_nvals; - GrB_Matrix_nvals(&m3_nvals, M3); + GrB_Index CombinedGraph_nvals; + GrB_Matrix_nvals(&CombinedGraph_nvals, CombinedGraph); - /*if (m3_nvals > 0) { - i = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); - j = (GrB_Index*)malloc(m3_nvals * sizeof(GrB_Index)); - V = (bool*)malloc(m3_nvals * sizeof(bool)); + /*if (CombinedGraph_nvals > 0) { + i = (GrB_Index*)malloc(CombinedGraph_nvals * sizeof(GrB_Index)); + j = (GrB_Index*)malloc(CombinedGraph_nvals * sizeof(GrB_Index)); + V = (bool*)malloc(CombinedGraph_nvals * sizeof(bool)); - GrB_Matrix_extractTuples_BOOL(i, j, V, &m3_nvals, M3); + GrB_Matrix_extractTuples_BOOL(i, j, V, &CombinedGraph_nvals, CombinedGraph); - for (GrB_Index k = 0; k < m3_nvals; ++k) { + for (GrB_Index k = 0; k < CombinedGraph_nvals; ++k) { GrB_Index s = i[k] / g_dim; GrB_Index f = j[k] / g_dim; GrB_Index x = i[k] % g_dim; @@ -128,7 +128,7 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker i = NULL; j = NULL; V = NULL; }*/ - if (m3_nvals > 0) { + if (CombinedGraph_nvals > 0) { for (GrB_Index nt = 0; nt < rsm->nonterminal_count; ++nt) { GrB_Index s = rsm->start_states[nt]; @@ -145,7 +145,7 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker col_indices[v] = f * g_dim + v; } - GrB_Matrix_extract(TempBlock, NULL, NULL, M3, + GrB_Matrix_extract(TempBlock, NULL, NULL, CombinedGraph, row_indices, g_dim, col_indices, g_dim, NULL); GrB_eWiseAdd(outputs[nt], NULL, NULL, GrB_LOR, From efc0df4f2f563da39638f9db38153330e6dab087 Mon Sep 17 00:00:00 2001 From: Mamontyonok Date: Sun, 15 Mar 2026 10:17:09 +0300 Subject: [PATCH 6/6] using_the_GrB_LOR_accumulator_replaces_the_need_for_GrB_eWiseAdd --- experimental/algorithm/LAGraph_CFL_Kron.c | 39 +++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/experimental/algorithm/LAGraph_CFL_Kron.c b/experimental/algorithm/LAGraph_CFL_Kron.c index 222c220f4f..a648829cb4 100644 --- a/experimental/algorithm/LAGraph_CFL_Kron.c +++ b/experimental/algorithm/LAGraph_CFL_Kron.c @@ -155,6 +155,45 @@ GrB_Info LAGraph_CFL_AllPaths_Kronecker } } + /*if (CombinedGraph_nvals > 0) { + // if there is enough memory, you can move it out of the while loop + GrB_Index* row_indices = (GrB_Index*)malloc(g_dim * sizeof(GrB_Index)); + GrB_Index* col_indices = (GrB_Index*)malloc(g_dim * sizeof(GrB_Index)); + + for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { + GrB_Index s = rsm->start_states[nt]; + + for (GrB_Index i = 0; i < g_dim; ++i) { + row_indices[i] = s * g_dim + i; + } + + // extract all final states for the given nonterminal + GrB_Index f_nvals; + GrB_Vector_nvals(&f_nvals, rsm->final_states[nt]); + GrB_Index* f_indices = (GrB_Index*)malloc(f_nvals * sizeof(GrB_Index)); + bool* f_values = (bool*)malloc(f_nvals * sizeof(bool)); + GrB_Vector_extractTuples_BOOL(f_indices, f_values, &f_nvals, rsm->final_states[nt]); + + // for each final state, extract the corresponding block + for (GrB_Index k = 0; k < f_nvals; ++k) { + if (f_values[k]) { + GrB_Index f = f_indices[k]; + + for (GrB_Index j = 0; j < g_dim; ++j) { + col_indices[j] = f * g_dim + j; + } + + // using the GrB_LOR accumulator replaces the need for GrB_eWiseAdd + GrB_Matrix_extract(outputs[nt], NULL, GrB_LOR, CombinedGraph, row_indices, g_dim, col_indices, g_dim, NULL); + } + } + free(f_indices); + free(f_values); + } + free(row_indices); + free(col_indices); + }*/ + nvals_new = 0; for (int64_t nt = 0; nt < rsm->nonterminal_count; ++nt) { GrB_Index vals;