Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
164 commits
Select commit Hold shift + click to select a range
b0ad740
remove GxB_SelectOp
DrTimothyAldenDavis Jul 21, 2023
e4f71b4
`#ifdef __GLIBC__` for musl compatibility
M-PERSIC Jul 22, 2023
91de87a
Merge pull request #232 from M-PERSIC/musl-fix
DrTimothyAldenDavis Aug 2, 2023
a589335
revisions: date, remove #if 0
DrTimothyAldenDavis Aug 18, 2023
4e6ee03
macos: remove version # for libomp for build.yml
DrTimothyAldenDavis Aug 21, 2023
c2d1324
libomp again for github CI
DrTimothyAldenDavis Aug 21, 2023
10b5841
github brew, again
DrTimothyAldenDavis Aug 21, 2023
4f3b2ad
.
DrTimothyAldenDavis Aug 21, 2023
7154366
try build.hml from dev branch
DrTimothyAldenDavis Aug 21, 2023
013a09d
build.yml again
DrTimothyAldenDavis Aug 21, 2023
efad2e1
macos brew again
DrTimothyAldenDavis Aug 21, 2023
01b19ad
revert to build.yml for v1.0.1
DrTimothyAldenDavis Aug 21, 2023
78bdf12
CI: Remove brew extract
szarnyasg Aug 21, 2023
24e8060
CI: Create brew tap for libomp 14
szarnyasg Aug 21, 2023
9290ed4
CI: Adjust brew instructions
szarnyasg Aug 21, 2023
1340799
enable LAGraph v1.0.2 to work with draft SS:GrB v8.1.0
DrTimothyAldenDavis Aug 22, 2023
7887f54
Merge pull request #229 from GraphBLAS/v1.0.2
DrTimothyAldenDavis Aug 29, 2023
58d229e
LAGraph v1.1.0: changes required for SuiteSparse integration
DrTimothyAldenDavis Nov 29, 2023
575c387
LAGraph v1.1: allow it to use GraphBLAS v7.1.0 or later
DrTimothyAldenDavis Nov 29, 2023
852485f
ditto
DrTimothyAldenDavis Nov 29, 2023
3d8fb25
remove /usr/local/include
DrTimothyAldenDavis Nov 29, 2023
2a760e6
comments
DrTimothyAldenDavis Nov 29, 2023
049205a
change name of project from "lagraph" to "LAGraph"
DrTimothyAldenDavis Nov 29, 2023
37823e3
GraphBLAS version: check in LAGraph.h, not find_package
DrTimothyAldenDavis Nov 30, 2023
f5eade2
add manual workflow trigger
DrTimothyAldenDavis Nov 30, 2023
4a73cba
include files for C++
DrTimothyAldenDavis Nov 30, 2023
72c9c39
fix some issues with other versions of GraphBLAS (vanilla case)
DrTimothyAldenDavis Nov 30, 2023
01f7a58
sync
DrTimothyAldenDavis Dec 5, 2023
482897a
creating GraphBLAS:: target for older GraphBLAS
DrTimothyAldenDavis Dec 5, 2023
1f11d73
workaround for GraphBLAS 8.2.x
DrTimothyAldenDavis Dec 5, 2023
8d0a627
sync
DrTimothyAldenDavis Dec 5, 2023
de51a91
sync again
DrTimothyAldenDavis Dec 5, 2023
a92165c
full test coverage
DrTimothyAldenDavis Dec 5, 2023
e0ca734
make LG_init_has_been_called a static value
DrTimothyAldenDavis Dec 6, 2023
d5c547a
replace LAGr_Reset with LG_get/set
DrTimothyAldenDavis Dec 6, 2023
b177d27
sync
DrTimothyAldenDavis Dec 6, 2023
a667148
only add /Include workaround if the directory exists
DrTimothyAldenDavis Dec 6, 2023
a81ffa5
diagnostics in FindGraphBLAS.cmake
DrTimothyAldenDavis Dec 6, 2023
199e050
turn of LAGRAPH_DUMP
DrTimothyAldenDavis Dec 6, 2023
c23fa85
more FindGraphBLAS
DrTimothyAldenDavis Dec 6, 2023
d12f65e
FindGraphBLAS: for module case, no default path (to avoid stumbling i…
DrTimothyAldenDavis Dec 6, 2023
6a797b9
readme for LAGraph/src/benchmark
DrTimothyAldenDavis Dec 8, 2023
17ef14c
revise *.pc, handle "undef I"
DrTimothyAldenDavis Dec 9, 2023
55ad380
updates to build system
DrTimothyAldenDavis Dec 9, 2023
f7a2d5d
Update config/LAGraph.pc.in
DrTimothyAldenDavis Dec 12, 2023
edcdfe1
Dec 13 LAGraph meeting: fix copyright, remove LG_init.h
DrTimothyAldenDavis Dec 13, 2023
a5d2eea
set RPATH for compiled binaries
DrTimothyAldenDavis Dec 13, 2023
221146e
cleanup comments
DrTimothyAldenDavis Dec 13, 2023
15a49b3
sync with SuiteSparse 7.4.0
DrTimothyAldenDavis Dec 20, 2023
ac7f239
fix local_install
DrTimothyAldenDavis Dec 20, 2023
210fc10
consistent use of _USE_ and _HAS_ variables
DrTimothyAldenDavis Dec 22, 2023
283f27f
Merge branch 'v1.1_branch' of https://github.com/GraphBLAS/LAGraph in…
DrTimothyAldenDavis Dec 22, 2023
54e4c96
typo in SuiteSparsePolicy.cmake
DrTimothyAldenDavis Dec 22, 2023
1041a57
SUITESPARSE_USE_STRICT
DrTimothyAldenDavis Dec 22, 2023
deeb691
SUITESPARSE_USE_OPENMP option moved to SuiteSparsePolicy.cmake
DrTimothyAldenDavis Dec 22, 2023
4284b1b
policy
DrTimothyAldenDavis Dec 23, 2023
c7653aa
openmp policy
DrTimothyAldenDavis Dec 24, 2023
6997192
report openmp
DrTimothyAldenDavis Dec 24, 2023
c636bc0
remove "set ( CMAKE_MACOSX_RPATH TRUE )" from all cmake scripts
DrTimothyAldenDavis Dec 25, 2023
3f0cf78
cmake reports
DrTimothyAldenDavis Dec 29, 2023
c6dcf33
Merge pull request #243 from GraphBLAS/v1.1_branch
DrTimothyAldenDavis Dec 30, 2023
1614afc
minor build updates for LAGraph 1.1.1
DrTimothyAldenDavis Jan 9, 2024
a1a1381
Merge pull request #245 from GraphBLAS/v1.1_branch
DrTimothyAldenDavis Jan 10, 2024
1beaf9d
LAGraph 1.1.2: minor updates to build system
DrTimothyAldenDavis Jan 24, 2024
3b461aa
Merge pull request #246 from GraphBLAS/v1.1_branch
DrTimothyAldenDavis Jan 25, 2024
275a986
bug fix for MMWrite (invalid output on array format)
tweska Jun 26, 2024
64a629f
Merge pull request #253 from tweska/knobel
DrTimothyAldenDavis Jul 1, 2024
0fca67e
minor updates to build system for Windows, and bug fix for MMWrite wh…
DrTimothyAldenDavis Aug 12, 2024
960b5e7
add GraphBLAS 9.1.0 to the workflow
DrTimothyAldenDavis Aug 12, 2024
8187e9b
FindGraphBLAS for SuiteSparse v9.x and later
DrTimothyAldenDavis Aug 12, 2024
f752e20
FindGraphBLAS: looking for GraphBLAS.h
DrTimothyAldenDavis Aug 12, 2024
b672b44
Finding GraphBLAS, try 3
DrTimothyAldenDavis Aug 13, 2024
1990a1a
Finding GraphBLAS, try 4
DrTimothyAldenDavis Aug 13, 2024
b240531
workflow
DrTimothyAldenDavis Aug 13, 2024
458abc5
on the mac
DrTimothyAldenDavis Aug 13, 2024
be7d698
turn off LAGRAPH_DUMP in FindGraphBLAS.cmake
DrTimothyAldenDavis Aug 13, 2024
3973dfe
restore original FindGraphBLAS.cmake
DrTimothyAldenDavis Aug 13, 2024
5906d78
take stab and builtin graphblas build.
michelp Aug 14, 2024
e9693f9
make compact.
michelp Aug 14, 2024
10d4de0
change path names for lagraph build, not necessary since make install…
michelp Aug 15, 2024
3a1ce93
stab at macos
michelp Aug 15, 2024
8d3d762
remove debug printfs from test_BF.c
DrTimothyAldenDavis Aug 15, 2024
89bf3a0
move new build over to build.
michelp Aug 15, 2024
dd43e4f
Merge pull request #256 from GraphBLAS/michelp/v1.1-builtin-graphblas…
DrTimothyAldenDavis Aug 15, 2024
fa693bc
CI: deploy test coverage for only one entry in the CI matrix
DrTimothyAldenDavis Aug 21, 2024
8a1cfcf
Merge pull request #255 from GraphBLAS/v1.1_branch
DrTimothyAldenDavis Aug 23, 2024
432aa33
Add os config for rtd build.
michelp Aug 29, 2024
1bd0c3d
Merge pull request #257 from GraphBLAS/fix-docs-stable
DrTimothyAldenDavis Aug 29, 2024
414ec31
update sphinx version to work with python312
michelp Aug 30, 2024
a0f545a
unpin all requirements see if we can get it to work with PR.
michelp Aug 30, 2024
cc56ed4
Merge pull request #258 from GraphBLAS/test-docs-pr
DrTimothyAldenDavis Aug 30, 2024
3040ccd
Fix: spell mistake in hello_world demo sources
homka122 Oct 12, 2024
afeb9df
Merge pull request #259 from homka122/fix/hellohell
DrTimothyAldenDavis Oct 16, 2024
8c7c5fa
Feat: Add MTX_reach_basic algorithm and rule_CNF struct
homka122 Nov 9, 2024
44d3d02
Feat: add example of mtx_reach_basic usage
homka122 Nov 9, 2024
c422370
Refactor: add dots to the error messages
homka122 Nov 10, 2024
e98e0ca
Feat: add processing rules
homka122 Nov 10, 2024
e699763
Fix: fix code for debugging
homka122 Nov 10, 2024
b5747bf
Refactor: set element with 'true' keyword instead of '1'
homka122 Nov 10, 2024
40c4924
Docs: add warning to rule_WCNF struct
homka122 Nov 10, 2024
38be111
Docs: add description of function MTX_reach and rename it
homka122 Nov 10, 2024
787fc5f
Feat: add const keyword to function parameters
homka122 Nov 10, 2024
bc82963
Fix: Now matrices in function free correctly
homka122 Nov 10, 2024
e5e283c
Refactor: change index in the adj_matrices comment
homka122 Nov 13, 2024
2b6c6b8
Docs: add info about start nonterminal
homka122 Nov 13, 2024
897003f
Docs: add info about result path in output matrix
homka122 Nov 13, 2024
3542556
Docs: update conditons of rules in rule_WCNF
homka122 Nov 13, 2024
2b457ce
Fix: wrong condition in LG_ASSERT_MSG
homka122 Nov 13, 2024
b6f5fda
Rename: rename algorithm
homka122 Nov 13, 2024
3ba63e9
Docs: add link to paper
homka122 Nov 13, 2024
fefb0f2
Feat: now algorithm return array of output matrices with result
homka122 Nov 13, 2024
3128de6
Docs: update description of function in LAGraphX.h
homka122 Nov 13, 2024
12ae6a4
Feat: add error macro and additional rule checks
homka122 Nov 13, 2024
1beb012
Fix: wrong signature of function
homka122 Nov 13, 2024
72a9a56
Fix: error_rule macro specificator
homka122 Nov 13, 2024
c9aca53
Feat: add invalid_rules test for algorithm
homka122 Nov 13, 2024
633f3a7
Test: add new grammars and graphs
homka122 Nov 18, 2024
3673f7e
Fix: range rule check now works fine
homka122 Nov 18, 2024
a657110
Feat: Add macroses for tests
homka122 Nov 21, 2024
c8502ca
Fix: Now check matrix creation
homka122 Nov 21, 2024
20dc020
Feat: add tests with valid result
homka122 Nov 21, 2024
423bb34
Refactor: redesign macro for checking errors
homka122 Nov 21, 2024
63de82d
Fix(test): free_workspace() do not make segmetation fault now
homka122 Nov 21, 2024
a689f91
Feat(test): add null pointers test
homka122 Nov 21, 2024
38e2630
Refactor: set name to graphs and grammars
homka122 Nov 22, 2024
6cf2a7c
Fix: incorrect memory free. Output matrices stay in memory
homka122 Nov 22, 2024
6dd2747
Feat: add null pointer checks
homka122 Nov 22, 2024
fe251c8
Feat: add null check on rules array
homka122 Nov 22, 2024
3f6e4b7
Docs: add example to description of algorithm
homka122 Nov 22, 2024
d79aa7f
Docs: improve text of comments
homka122 Nov 22, 2024
98234de
Docs: add license to header of files
homka122 Nov 22, 2024
7cfcec5
Docs: change example graph description
homka122 Nov 27, 2024
731eb39
Docs: improve readablitity of function description
homka122 Nov 27, 2024
bed4711
Docs: make error msgs more clearly
homka122 Nov 28, 2024
34c9d60
Feat: now print all indecies of null adjancency matrices
homka122 Nov 28, 2024
f5d65a9
Refactor: Now msg about lagraph failure in macro
homka122 Nov 28, 2024
c429b30
Refactor: move headers to the top of file
homka122 Nov 28, 2024
55d971a
Feat: processing rules now more complex and useful
homka122 Nov 28, 2024
018d249
Refactor: add comments
homka122 Nov 28, 2024
4c7763c
Feat: add two_nodes_cycle test
homka122 Nov 28, 2024
e991de1
Refactor: remove do while statement in macro
homka122 Nov 30, 2024
74c530f
Refactor: make function definition more clearly
homka122 Nov 30, 2024
08953a3
Feat: Use eWiseAdd method instead of cycle of setElements
homka122 Dec 2, 2024
108ab2f
Feat: add eWiseAdd with edintity matrix now
homka122 Dec 2, 2024
fefb305
Fix: move free macros above
homka122 Dec 8, 2024
bd9f14e
Fix: nonterms and terms count now int32_t
homka122 Dec 8, 2024
ca4e5c7
Feat: add flag for debug iso status of matrices
homka122 Dec 8, 2024
090e1f1
Feat: use WiseUnion method for add matrices
homka122 Dec 8, 2024
7793076
Fix: terms and nonterms count in header now int32_t
homka122 Dec 8, 2024
583f826
Fix: memory leaks
homka122 Dec 8, 2024
e6b25a3
Feat: array for T matrices now allocate with calloc
homka122 Dec 8, 2024
42b5c9b
Fix: indexes now free in macro
homka122 Dec 8, 2024
dfb46dc
Refactor: rename nnz to nnsz
homka122 Dec 8, 2024
c94e1bf
Refactor: GxB_print now have non-numerical priority
homka122 Dec 8, 2024
31f8e75
Fix: replace eWiseAdd to eWiseUnion to debug msgs
homka122 Dec 8, 2024
a6cb0de
Feat: now use Lagraph malloc instead of c calloc
homka122 Dec 20, 2024
dab2982
Fix: delete unused nnz calculation
homka122 Dec 22, 2024
b50d46d
Feat: create identity matrix with diag method
homka122 Dec 22, 2024
77e3cb7
Feat: Use Lagraph calloc instead of C calloc
homka122 Dec 22, 2024
c9848e7
Feat: add empty matrix check
homka122 Jan 27, 2025
9b0a060
Refactor: change DEBUG flag to DEBUG_CFL_REACHABILITY
homka122 Jan 27, 2025
5cf40c5
Merge remote-tracking branch 'origin/v1.2' into feat/mtx_reach
homka122 Feb 16, 2025
a9bc838
Sync v1.2 branch, get new commits
homka122 Feb 16, 2025
176bdd4
Fix: change files according to v1.2 version
homka122 Feb 16, 2025
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
365 changes: 365 additions & 0 deletions experimental/algorithm/LAGraph_CFL_reachability.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,365 @@
//------------------------------------------------------------------------------
// LAGraph_CFL_reachability.c: Context-Free Language Reachability Matrix-Based Algorithm
//------------------------------------------------------------------------------
//
// LAGraph, (c) 2019-2024 by The LAGraph Contributors, All Rights Reserved.
// SPDX-License-Identifier: BSD-2-Clause

// Contributed by Ilhom Kombaev, Semyon Grigoriev, St. Petersburg State University.

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

// Code is based on the "A matrix-based CFPQ algorithm" described in the following paper:
// * Rustam Azimov, Semyon Grigorev, "Context-Free Path Querying Using Linear Algebra"
// * URL: https://disser.spbu.ru/files/2022/disser_azimov.pdf

#define LG_FREE_WORK \
{ \
free(nnzs); \
GrB_free(&true_scalar); \
GrB_free(&identity_matrix); \
free(T); \
free(indexes); \
}

#define LG_FREE_ALL \
{ \
for (size_t i = 0; i < nonterms_count; i++) { \
GrB_free(&T[i]); \
} \
\
LG_FREE_WORK; \
}

#include "LG_internal.h"
#include <LAGraphX.h>

#define ERROR_RULE(msg) \
{ \
LG_ASSERT_MSGF(false, GrB_INVALID_VALUE, "Rule with index %ld is invalid. " msg, \
i); \
}

#define ADD_TO_MSG(...) \
{ \
if (msg_len == 0) { \
msg_len += \
snprintf(msg, LAGRAPH_MSG_LEN, \
"LAGraph failure (file %s, line %d): ", __FILE__, __LINE__); \
} \
if (msg_len < LAGRAPH_MSG_LEN) { \
msg_len += snprintf(msg + msg_len, LAGRAPH_MSG_LEN - msg_len, __VA_ARGS__); \
} \
}

#define ADD_INDEX_TO_ERROR_RULE(rule, i) \
{ \
rule.len_indexes_str += snprintf(rule.indexes_str + rule.len_indexes_str, \
LAGRAPH_MSG_LEN - rule.len_indexes_str, \
rule.count == 0 ? "%ld" : ", %ld", i); \
rule.count++; \
}



// LAGraph_CFL_reachability: Context-Free Language Reachability Matrix-Based Algorithm
//
// This function determines the set of vertex pairs (u, v) in a graph (represented by
// adjacency matrices) such that there is a path from u to v, where the edge labels form a
// word from the language generated by the context-free grammar (represented by `rules`).
//
// Terminals and non-terminals are enumerated by integers starting from zero.
// The start non-terminal is the non-terminal with index 0.
//
// Example:
//
// Graph:
// ┌───┐ ┌───┐ ┌───┐ ┌───┐ ┌───┐
// │ 0 ├───► 1 ├───► 2 ├───► 3 ├───► 4 │
// └───┘ a └─┬─┘ a └─▲─┘ b └───┘ b └───┘
// │ │
// │ ┌───┐ │
// a└─► 5 ├─┘b
// └───┘
//
// Grammar: S -> aSb | ab
//
// There are paths from node [1] to node [3] and from node [1] to node [2] that form the
// word "ab" ([1]-a->[2]-b->[3] and [1]-a->[5]-b->[2]). The word "ab" is in the language
// generated by our context-free grammar, so the pairs (1, 3) and (1, 2) will be included
// in the result.
//
// Note: It doesn't matter how many paths exist from node [A] to node [B] that form a word
// in the language. If at least one path exists, the pair ([A], [B]) will be included in
// the result.
//
// In contrast, the path from node [1] to node [4] forms the word "abb"
// ([1]-a->[2]-b->[3]-b->[4]) and the word "abbb" ([1]-a->[5]-b->[2]-b->[3]-b->[4]).
// The words "aab" and "abbb" are not in the language, so the pair (1, 4) will not be
// included in the result.
//
// With this graph and grammar, we obtain the following results:
// (0, 4) - because there exists a path (0-1-2-3-4) that forms the word "aabb"
// (1, 3) - because there exists a path (1-2-3) that forms "ab"
// (1, 2) - because there exists a path (1-5-2) that forms the word "ab"
// (0, 3) - because there exists a path (0-1-5-2-3) that forms the word "aabb"
GrB_Info LAGraph_CFL_reachability
(
// Output
GrB_Matrix *outputs, // Array of matrices containing results.
// The size of the array must be equal to nonterms_count.
//
// outputs[k]: (i, j) = true if and only if there is a path
// from node i to node j whose edge labels form a word
// derivable from the non-terminal 'k' of the specified CFG.
// Input
const GrB_Matrix *adj_matrices, // Array of adjacency matrices representing the graph.
// The length of this array is equal to the count of
// terminals (terms_count).
//
// adj_matrices[t]: (i, j) == 1 if and only if there
// is an edge between nodes i and j with the label of
// the terminal corresponding to index 't' (where t is
// in the range [0, terms_count - 1]).
int32_t terms_count, // The total number of terminal symbols in the CFG.
int32_t nonterms_count, // The total number of non-terminal symbols in the CFG.
const LAGraph_rule_WCNF *rules, // The rules of the CFG.
size_t rules_count, // The total number of rules in the CFG.
char *msg // Message string for error reporting.
)
{
// Declare workspace and clear the msg string, if not NULL
GrB_Matrix *T;
bool t_empty_flags[nonterms_count]; // t_empty_flags[i] == true <=> T[i] is empty
GrB_Matrix identity_matrix = NULL;
uint64_t *nnzs = NULL;
LG_CLEAR_MSG;
size_t msg_len = 0; // For error formatting
bool iso_flag = false;
GrB_Index *indexes = NULL;


GrB_Scalar true_scalar;
GrB_Scalar_new(&true_scalar, GrB_BOOL);
GrB_Scalar_setElement_BOOL(true_scalar, true);

LG_TRY(LAGraph_Calloc((void **) &T, nonterms_count, sizeof(GrB_Matrix), msg));

LG_ASSERT_MSG(terms_count > 0, GrB_INVALID_VALUE,
"The number of terminals must be greater than zero.");
LG_ASSERT_MSG(nonterms_count > 0, GrB_INVALID_VALUE,
"The number of non-terminals must be greater than zero.");
LG_ASSERT_MSG(rules_count > 0, GrB_INVALID_VALUE,
"The number of rules must be greater than zero.");
LG_ASSERT_MSG(outputs != NULL, GrB_NULL_POINTER, "The outputs array cannot be null.");
LG_ASSERT_MSG(rules != NULL, GrB_NULL_POINTER, "The rules array cannot be null.");
LG_ASSERT_MSG(adj_matrices != NULL, GrB_NULL_POINTER,
"The adjacency matrices array cannot be null.");

// Find null adjacency matrices
bool found_null = false;
for (int32_t i = 0; i < terms_count; i++) {
if (adj_matrices[i] != NULL)
continue;

if (!found_null) {
ADD_TO_MSG("Adjacency matrices with these indexes are null: ");
ADD_TO_MSG("%d", i);
} else {
ADD_TO_MSG(", %d", i);
}

found_null = true;
}

if (found_null) {
LG_FREE_ALL;
return GrB_NULL_POINTER;
}

GrB_Index n;
GRB_TRY(GrB_Matrix_ncols(&n, adj_matrices[0]));

// Create nonterms matrices
for (int32_t i = 0; i < nonterms_count; i++) {
GRB_TRY(GrB_Matrix_new(&T[i], GrB_BOOL, n, n));
t_empty_flags[i] = true;
}

// Arrays for processing rules
size_t eps_rules[rules_count], eps_rules_count = 0; // [Variable -> eps]
size_t term_rules[rules_count], term_rules_count = 0; // [Variable -> term]
size_t bin_rules[rules_count], bin_rules_count = 0; // [Variable -> AB]

// Process rules
typedef struct {
size_t count;
size_t len_indexes_str;
char indexes_str[LAGRAPH_MSG_LEN];
} rule_error_s;
rule_error_s term_err = {0};
rule_error_s nonterm_err = {0};
rule_error_s invalid_err = {0};
for (size_t i = 0; i < rules_count; i++) {
LAGraph_rule_WCNF rule = rules[i];

bool is_rule_eps = rule.prod_A == -1 && rule.prod_B == -1;
bool is_rule_term = rule.prod_A != -1 && rule.prod_B == -1;
bool is_rule_bin = rule.prod_A != -1 && rule.prod_B != -1;

// Check that all rules are well-formed
if (rule.nonterm < 0 || rule.nonterm >= nonterms_count) {
ADD_INDEX_TO_ERROR_RULE(nonterm_err, i);
}

// [Variable -> eps]
if (is_rule_eps) {
eps_rules[eps_rules_count++] = i;

continue;
}

// [Variable -> term]
if (is_rule_term) {
term_rules[term_rules_count++] = i;

if (rule.prod_A < -1 || rule.prod_A >= terms_count) {
ADD_INDEX_TO_ERROR_RULE(term_err, i);
}

continue;
}

// [Variable -> A B]
if (is_rule_bin) {
bin_rules[bin_rules_count++] = i;

if (rule.prod_A < -1 || rule.prod_A >= nonterms_count || rule.prod_B < -1 ||
rule.prod_B >= nonterms_count) {
ADD_INDEX_TO_ERROR_RULE(nonterm_err, i);
}

continue;
}

// [Variable -> _ B]
ADD_INDEX_TO_ERROR_RULE(invalid_err, i);
}

if (term_err.count + nonterm_err.count + invalid_err.count > 0) {
ADD_TO_MSG("Count of invalid rules: %ld.\n",
term_err.count + nonterm_err.count + invalid_err.count);

if (nonterm_err.count > 0) {
ADD_TO_MSG("Non-terminals must be in range [0, nonterms_count). ");
ADD_TO_MSG("Indexes of invalid rules: %s\n", nonterm_err.indexes_str)
}
if (term_err.count > 0) {
ADD_TO_MSG("Terminals must be in range [-1, nonterms_count). ");
ADD_TO_MSG("Indexes of invalid rules: %s\n", term_err.indexes_str)
}
if (invalid_err.count > 0) {
ADD_TO_MSG("[Variable -> _ B] type of rule is not acceptable. ");
ADD_TO_MSG("Indexes of invalid rules: %s\n", invalid_err.indexes_str)
}

LG_FREE_ALL;
return GrB_INVALID_VALUE;
}

// Rule [Variable -> term]
for (size_t i = 0; i < term_rules_count; i++) {
LAGraph_rule_WCNF term_rule = rules[term_rules[i]];
GrB_Index adj_matrix_nnz = 0;
GRB_TRY(GrB_Matrix_nvals(&adj_matrix_nnz, adj_matrices[term_rule.prod_A]));

if (adj_matrix_nnz == 0) {
continue;
}

GxB_eWiseUnion(
T[term_rule.nonterm], GrB_NULL, GrB_NULL, GxB_PAIR_BOOL,
T[term_rule.nonterm], true_scalar, adj_matrices[term_rule.prod_A], true_scalar, GrB_NULL
);

t_empty_flags[term_rule.nonterm] = false;

#ifdef DEBUG_CFL_REACHBILITY
GxB_Matrix_iso(&iso_flag, T[term_rule.nonterm]);
printf("[TERM] eWiseUnion: NONTERM: %d (ISO: %d)\n", term_rule.nonterm, iso_flag);
#endif
}

GrB_Vector v_diag;
GRB_TRY(GrB_Vector_new(&v_diag, GrB_BOOL, n));
GRB_TRY(GrB_Vector_assign_BOOL(v_diag, GrB_NULL, GrB_NULL, true, GrB_ALL, n, NULL));
GRB_TRY(GrB_Matrix_diag(&identity_matrix, v_diag, 0));
GRB_TRY(GrB_free(&v_diag));

// Rule [Variable -> eps]
for (size_t i = 0; i < eps_rules_count; i++) {
LAGraph_rule_WCNF eps_rule = rules[eps_rules[i]];

GxB_eWiseUnion (
T[eps_rule.nonterm],GrB_NULL,GxB_PAIR_BOOL,GxB_PAIR_BOOL,
T[eps_rule.nonterm],true_scalar,identity_matrix,true_scalar,GrB_NULL
);

t_empty_flags[eps_rule.nonterm] = false;

#ifdef DEBUG_CFL_REACHBILITY
GxB_Matrix_iso(&iso_flag, T[eps_rule.nonterm]);
printf("[EPS] eWiseUnion: NONTERM: %d (ISO: %d)\n",
eps_rule.nonterm, iso_flag);
#endif
}

// Rule [Variable -> Variable1 Variable2]
LG_TRY(LAGraph_Calloc((void **) &nnzs, nonterms_count, sizeof(uint64_t), msg));
bool changed = true;
while (changed) {
changed = false;
for (size_t i = 0; i < bin_rules_count; i++) {
LAGraph_rule_WCNF bin_rule = rules[bin_rules[i]];

// If one of matrices is empty then their product will be empty
if (t_empty_flags[bin_rule.prod_A] || t_empty_flags[bin_rule.prod_B]) {
continue;
}

GrB_BinaryOp acc_op = t_empty_flags[bin_rule.nonterm] ? GrB_NULL : GxB_ANY_BOOL;
GRB_TRY(GrB_mxm(T[bin_rule.nonterm], GrB_NULL, acc_op,
GxB_ANY_PAIR_BOOL, T[bin_rule.prod_A], T[bin_rule.prod_B],
GrB_NULL))

GrB_Index new_nnz;
GRB_TRY(GrB_Matrix_nvals(&new_nnz, T[bin_rule.nonterm]));
if (new_nnz != 0) t_empty_flags[bin_rule.nonterm] = false;

changed = changed || (nnzs[bin_rule.nonterm] != new_nnz);
nnzs[bin_rule.nonterm] = new_nnz;

#ifdef DEBUG_CFL_REACHBILITY
GxB_Matrix_iso(&iso_flag, T[bin_rule.nonterm]);
printf("[TERM1 TERM2] MULTIPLY, S: %d, A: %d, B: %d, "
"I: %ld (ISO: %d)\n",
bin_rule.nonterm, bin_rule.prod_A, bin_rule.prod_B, i, iso_flag);
#endif

}
}

#ifdef DEBUG_CFL_REACHBILITY
for (int32_t i = 0; i < nonterms_count; i++) {
printf("MATRIX WITH INDEX %d:\n", i);
GxB_print(T[i], GxB_SUMMARY);
}
#endif

for (int32_t i = 0; i < nonterms_count; i++) {
outputs[i] = T[i];
}

LG_FREE_WORK;
return GrB_SUCCESS;
}
Loading
Loading