Skip to content

Commit 7a4d700

Browse files
committed
Added RPQ algorithm
1 parent a9759a9 commit 7a4d700

37 files changed

+590
-0
lines changed

.gitmodules

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[submodule "cuBool"]
2+
path = cuBool
3+
url = https://github.com/mitya-y/cuBool
4+
[submodule "deps/googletest"]
5+
path = deps/googletest
6+
url = https://github.com/google/googletest
7+
[submodule "deps/fast_matrix_market"]
8+
path = deps/fast_matrix_market
9+
url = https://github.com/alugowski/fast_matrix_market

CMakeLists.txt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
cmake_minimum_required(VERSION 3.25)
2+
3+
set(CMAKE_CXX_STANDARD 20)
4+
5+
set(CUBOOL_GRAPH_LIB_NAME cuboolgraph)
6+
project(${CUBOOL_GRAPH_LIB_NAME} LANGUAGES CXX CUDA)
7+
8+
add_library(${CUBOOL_GRAPH_LIB_NAME} SHARED "")
9+
10+
set(CUBOOL_COPY_TO_PY_PACKAGE OFF)
11+
set(CUBOOL_BUILD_TESTS OFF)
12+
add_subdirectory(cuBool)
13+
14+
# cubool is a name of CMakeTarget cmake target
15+
target_link_libraries(${CUBOOL_GRAPH_LIB_NAME} PUBLIC cubool)
16+
17+
target_include_directories(${CUBOOL_GRAPH_LIB_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include)
18+
19+
add_subdirectory(src)
20+
21+
option(CUBOOL_GRAPH_ENABLE_TESTING "Compile tests for algorithms" OFF)
22+
23+
if(CUBOOL_GRAPH_ENABLE_TESTING)
24+
add_subdirectory(deps/googletest)
25+
add_subdirectory(deps/fast_matrix_market)
26+
add_subdirectory(tests)
27+
endif()
28+

cuBool

Submodule cuBool added at 69d38a6

deps/fast_matrix_market

Submodule fast_matrix_market added at b6172c9

deps/googletest

Submodule googletest added at 35b75a2

include/regular_path_query.hpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#include <vector>
2+
3+
#include <cubool/cubool.h>
4+
5+
cuBool_Matrix regular_path_query_with_transposed(
6+
// vector of sparse graph matrices for each label
7+
const std::vector<cuBool_Matrix> &graph, const std::vector<cuBool_Index> &source_vertices,
8+
// vector of sparse automat matrices for each label
9+
const std::vector<cuBool_Matrix> &automat, const std::vector<cuBool_Index> &start_states,
10+
// transposed matrices for graph and automat
11+
const std::vector<cuBool_Matrix> &graph_transposed,
12+
const std::vector<cuBool_Matrix> &automat_transposed,
13+
14+
const std::vector<bool> &inversed_labels = {}, bool all_labels_are_inversed = false);
15+
16+
cuBool_Matrix regular_path_query(
17+
// vector of sparse graph matrices for each label
18+
const std::vector<cuBool_Matrix> &graph, const std::vector<cuBool_Index> &source_vertices,
19+
// vector of sparse automat matrices for each label
20+
const std::vector<cuBool_Matrix> &automat, const std::vector<cuBool_Index> &start_states,
21+
22+
const std::vector<bool> &inversed_labels = {}, bool all_labels_are_inversed = false);

src/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
target_sources(${CUBOOL_GRAPH_LIB_NAME} PRIVATE regular_path_query.cpp)

src/regular_path_query.cpp

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
#include <cassert>
2+
#include <cstdint>
3+
#include <iostream>
4+
#include <print>
5+
#include <set>
6+
7+
#include "regular_path_query.hpp"
8+
9+
cuBool_Matrix regular_path_query_with_transposed(
10+
// vector of sparse graph matrices for each label
11+
const std::vector<cuBool_Matrix> &graph, const std::vector<cuBool_Index> &source_vertices,
12+
// vector of sparse automat matrices for each label
13+
const std::vector<cuBool_Matrix> &automat, const std::vector<cuBool_Index> &start_states,
14+
// transposed matrices for graph and automat
15+
const std::vector<cuBool_Matrix> &graph_transposed,
16+
const std::vector<cuBool_Matrix> &automat_transposed,
17+
18+
const std::vector<bool> &inversed_labels_input, bool all_labels_are_inversed) {
19+
cuBool_Status status;
20+
21+
auto inversed_labels = inversed_labels_input;
22+
inversed_labels.resize(std::max(graph.size(), automat.size()));
23+
24+
for (uint32_t i = 0; i < inversed_labels.size(); i++) {
25+
bool is_inverse = inversed_labels[i];
26+
is_inverse ^= all_labels_are_inversed;
27+
inversed_labels[i] = is_inverse;
28+
}
29+
30+
cuBool_Index graph_nodes_number = 0;
31+
cuBool_Index automat_nodes_number = 0;
32+
33+
// get number of graph nodes
34+
for (auto label_matrix : graph) {
35+
if (label_matrix != nullptr) {
36+
cuBool_Matrix_Nrows(label_matrix, &graph_nodes_number);
37+
break;
38+
}
39+
}
40+
41+
// get number of automat nodes
42+
for (auto label_matrix : automat) {
43+
if (label_matrix != nullptr) {
44+
cuBool_Matrix_Nrows(label_matrix, &automat_nodes_number);
45+
break;
46+
}
47+
}
48+
49+
// this will be answer
50+
cuBool_Matrix reacheble {};
51+
status = cuBool_Matrix_New(&reacheble, automat_nodes_number, graph_nodes_number);
52+
assert(status == CUBOOL_STATUS_SUCCESS);
53+
54+
// allocate neccessary for algorithm matrices
55+
cuBool_Matrix frontier {}, symbol_frontier {}, next_frontier {};
56+
status = cuBool_Matrix_New(&next_frontier, automat_nodes_number, graph_nodes_number);
57+
assert(status == CUBOOL_STATUS_SUCCESS);
58+
status = cuBool_Matrix_New(&frontier, automat_nodes_number, graph_nodes_number);
59+
assert(status == CUBOOL_STATUS_SUCCESS);
60+
status = cuBool_Matrix_New(&symbol_frontier, automat_nodes_number, graph_nodes_number);
61+
assert(status == CUBOOL_STATUS_SUCCESS);
62+
63+
// init start values of algorithm matricies
64+
for (const auto state : start_states) {
65+
for (const auto vert : source_vertices) {
66+
assert(state < automat_nodes_number);
67+
assert(vert < graph_nodes_number);
68+
cuBool_Matrix_SetElement(next_frontier, state, vert);
69+
cuBool_Matrix_SetElement(reacheble, state, vert);
70+
}
71+
}
72+
73+
cuBool_Index states = source_vertices.size();
74+
75+
// temporary matrix for write result of cubool functions
76+
cuBool_Matrix result;
77+
status = cuBool_Matrix_New(&result, automat_nodes_number, graph_nodes_number);
78+
assert(status == CUBOOL_STATUS_SUCCESS);
79+
80+
const auto label_number = std::min(graph.size(), automat.size());
81+
while (states > 0) {
82+
std::swap(frontier, next_frontier);
83+
84+
// clear next_frontier
85+
status = cuBool_Matrix_Build(next_frontier, nullptr, nullptr, 0, CUBOOL_HINT_NO);
86+
assert(status == CUBOOL_STATUS_SUCCESS);
87+
88+
for (int i = 0; i < label_number; i++) {
89+
if (graph[i] == nullptr || automat[i] == nullptr) {
90+
continue;
91+
}
92+
93+
cuBool_Matrix automat_matrix = all_labels_are_inversed ? automat[i] : automat_transposed[i];
94+
status = cuBool_MxM(symbol_frontier, automat_matrix, frontier, CUBOOL_HINT_NO);
95+
assert(status == CUBOOL_STATUS_SUCCESS);
96+
97+
// next_frontier += (symbol_frontier * graph[i]) & (!reachible)
98+
// multiply 2 matrices
99+
cuBool_Matrix graph_matrix = inversed_labels[i] ? graph_transposed[i] : graph[i];
100+
status = cuBool_MxM(next_frontier, symbol_frontier, graph_matrix, CUBOOL_HINT_ACCUMULATE);
101+
assert(status == CUBOOL_STATUS_SUCCESS);
102+
// apply invert mask
103+
status = cuBool_Matrix_EWiseMulInverted(result, next_frontier, reacheble, CUBOOL_HINT_NO);
104+
assert(status == CUBOOL_STATUS_SUCCESS);
105+
std::swap(result, next_frontier);
106+
}
107+
108+
// this must be accumulate with mask and save old value: reacheble += next_frontier & reacheble
109+
status = cuBool_Matrix_EWiseAdd(result, reacheble, next_frontier, CUBOOL_HINT_NO);
110+
assert(status == CUBOOL_STATUS_SUCCESS);
111+
std::swap(result, reacheble);
112+
113+
cuBool_Matrix_Nvals(next_frontier, &states);
114+
}
115+
116+
// free matrix necessary for algorithm
117+
cuBool_Matrix_Free(next_frontier);
118+
cuBool_Matrix_Free(frontier);
119+
cuBool_Matrix_Free(symbol_frontier);
120+
cuBool_Matrix_Free(result);
121+
122+
return reacheble;
123+
}
124+
125+
126+
cuBool_Matrix regular_path_query(
127+
// vector of sparse graph matrices for each label
128+
const std::vector<cuBool_Matrix> &graph, const std::vector<cuBool_Index> &source_vertices,
129+
// vector of sparse automat matrices for each label
130+
const std::vector<cuBool_Matrix> &automat, const std::vector<cuBool_Index> &start_states,
131+
// work with inverted labels
132+
const std::vector<bool> &inversed_labels_input, bool all_labels_are_inversed) {
133+
cuBool_Status status;
134+
135+
// transpose graph matrices
136+
std::vector<cuBool_Matrix> graph_transposed;
137+
graph_transposed.reserve(graph.size());
138+
for (uint32_t i = 0; i < graph.size(); i++) {
139+
graph_transposed.emplace_back();
140+
141+
auto label_matrix = graph[i];
142+
if (label_matrix == nullptr) {
143+
continue;
144+
}
145+
146+
cuBool_Index nrows, ncols;
147+
cuBool_Matrix_Nrows(label_matrix, &nrows);
148+
cuBool_Matrix_Ncols(label_matrix, &ncols);
149+
150+
status = cuBool_Matrix_New(&graph_transposed.back(), ncols, nrows);
151+
assert(status == CUBOOL_STATUS_SUCCESS);
152+
status = cuBool_Matrix_Transpose(graph_transposed.back(), label_matrix, CUBOOL_HINT_NO);
153+
assert(status == CUBOOL_STATUS_SUCCESS);
154+
}
155+
156+
// transpose automat matrices
157+
std::vector<cuBool_Matrix> automat_transposed;
158+
automat_transposed.reserve(automat.size());
159+
for (auto label_matrix : automat) {
160+
automat_transposed.emplace_back();
161+
if (label_matrix == nullptr) {
162+
continue;
163+
}
164+
165+
cuBool_Index nrows, ncols;
166+
cuBool_Matrix_Nrows(label_matrix, &nrows);
167+
cuBool_Matrix_Ncols(label_matrix, &ncols);
168+
169+
status = cuBool_Matrix_New(&automat_transposed.back(), ncols, nrows);
170+
assert(status == CUBOOL_STATUS_SUCCESS);
171+
status = cuBool_Matrix_Transpose(automat_transposed.back(), label_matrix, CUBOOL_HINT_NO);
172+
assert(status == CUBOOL_STATUS_SUCCESS);
173+
}
174+
175+
auto result = regular_path_query_with_transposed(
176+
graph, source_vertices,
177+
automat, start_states,
178+
graph_transposed, automat_transposed,
179+
inversed_labels_input, all_labels_are_inversed);
180+
181+
for (cuBool_Matrix matrix : graph_transposed) {
182+
if (matrix != nullptr) {
183+
cuBool_Matrix_Free(matrix);
184+
}
185+
}
186+
for (cuBool_Matrix matrix : automat_transposed) {
187+
if (matrix != nullptr) {
188+
cuBool_Matrix_Free(matrix);
189+
}
190+
}
191+
192+
return result;
193+
}

tests/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
set(TESTS_TARGET cuboolgraph_tests)
2+
3+
add_executable(${TESTS_TARGET} "main.cpp")
4+
5+
target_link_libraries(${TESTS_TARGET} PUBLIC ${CUBOOL_GRAPH_LIB_NAME})
6+
target_link_libraries(${TESTS_TARGET} PUBLIC gtest)
7+
target_link_libraries(${TESTS_TARGET} PUBLIC fast_matrix_market)
8+
9+
target_compile_definitions(${TESTS_TARGET} PUBLIC
10+
TESTS_DATA_PATH="${CMAKE_CURRENT_SOURCE_DIR}/test_data/")
11+
12+
# tests files
13+
target_sources(${TESTS_TARGET} PUBLIC "rpq_tests.cpp")

tests/main.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#include <gtest/gtest.h>
2+
3+
int main(int argc, char **argv) {
4+
::testing::InitGoogleTest(&argc, argv);
5+
return RUN_ALL_TESTS();
6+
}

0 commit comments

Comments
 (0)