Skip to content
Open
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
42 changes: 41 additions & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ pathrex/
│ │ ├── mod.rs # Core traits (GraphBuilder, GraphDecomposition, GraphSource,
│ │ │ # Backend, Graph<B>), error types, RAII wrappers, GrB init
│ │ └── inmemory.rs # InMemory marker, InMemoryBuilder, InMemoryGraph
│ ├── rpq/
│ │ ├── mod.rs # RpqEvaluator (assoc. Result), RpqQuery, Endpoint, PathExpr, RpqError
│ │ └── rpqmatrix.rs # Matrix-plan RPQ evaluator
│ ├── sparql/
│ │ └── mod.rs # parse_rpq / extract_rpq → RpqQuery (spargebra)
│ └── formats/
Expand All @@ -32,7 +35,8 @@ pathrex/
│ └── mm.rs # MatrixMarket directory loader (vertices.txt, edges.txt, *.txt)
├── tests/
│ ├── inmemory_tests.rs # Integration tests for InMemoryBuilder / InMemoryGraph
│ └── mm_tests.rs # Integration tests for MatrixMarket format
│ ├── mm_tests.rs # Integration tests for MatrixMarket format
│ └── rpqmatrix_tests.rs # Integration tests for matrix-plan RPQ evaluator
├── deps/
│ └── LAGraph/ # Git submodule (SparseLinearAlgebra/LAGraph)
└── .github/workflows/ci.yml # CI: build GraphBLAS + LAGraph, cargo build & test
Expand Down Expand Up @@ -274,6 +278,42 @@ and the parsed query contains full IRIs sharing a common prefix.
The module handles spargebra's desugaring of sequence paths (`?x <a>/<b>/<c> ?y`)
from a chain of BGP triples back into a single path expression.

### RPQ evaluation (`src/rpq/`)

The [`rpq`](src/rpq/mod.rs) module provides an abstraction for evaluating
Regular Path Queries (RPQs) over edge-labeled graphs using GraphBLAS/LAGraph.

Key public items:

- [`Endpoint`](src/rpq/mod.rs) — `Variable(String)` or `Named(String)` (IRI string).
- [`PathExpr`](src/rpq/mod.rs) — `Label`, `Sequence`, `Alternative`, `ZeroOrMore`,
`OneOrMore`, `ZeroOrOne`.
- [`RpqQuery`](src/rpq/mod.rs) — `{ subject, path, object }` using the types above;
[`strip_base(&mut self, base)`](src/rpq/mod.rs) removes a shared IRI prefix from
named endpoints and labels.
- [`RpqEvaluator`](src/rpq/mod.rs) — trait with associated type `Result` and
[`evaluate(query, graph)`](src/rpq/mod.rs) taking `&RpqQuery` and
[`GraphDecomposition`], returning `Result<Self::Result, RpqError>`.
Each concrete evaluator exposes its own output type (see below).
- [`RpqError`](src/rpq/mod.rs) — unified error type for RPQ parsing and evaluation:
`Parse` (SPARQL syntax), `Extract` (query extraction), `UnsupportedPath`,
`VertexNotFound`, and `Graph` (wraps [`GraphError`](src/graph/mod.rs) for
label-not-found and GraphBLAS/LAGraph failures).

[`NfaRpqResult`](src/rpq/nfarpq.rs) wraps a [`GraphblasVector`] of reachable **target**
vertices. When the subject is a variable, every vertex is used as a source and
`LAGraph_RegularPathQuery` returns the union of targets — individual `(source, target)`
pairs are not preserved.

#### `RpqMatrixEvaluator` (`src/rpq/rpqmatrix.rs`)

[`RpqMatrixEvaluator`](src/rpq/rpqmatrix.rs) compiles [`PathExpr`] into a Boolean matrix plan
over label adjacency matrices and runs [`LAGraph_RPQMatrix`]. It returns
[`RpqMatrixResult`](src/rpq/rpqmatrix.rs): the path-relation `nnz` plus a
[`GraphblasMatrix`] duplicate of the result matrix (full reachability relation for the path).
Subject/object do not filter the matrix; a named subject is only validated to exist.
Bound objects are not supported yet ([`RpqError::UnsupportedPath`]).

### FFI layer

[`lagraph_sys`](src/lagraph_sys.rs) exposes raw C bindings for GraphBLAS and
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ edition = "2024"

[dependencies]
csv = "1.4.0"
egg = "0.10.0"
libc = "0.2"
oxrdf = "0.3.3"
oxttl = "0.2.3"
Expand Down
8 changes: 8 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ fn regenerate_bindings() {
.allowlist_function("GrB_Matrix_new")
.allowlist_function("GrB_Matrix_nvals")
.allowlist_function("GrB_Matrix_free")
.allowlist_function("GrB_Matrix_extractElement_BOOL")
.allowlist_function("GrB_Matrix_build_BOOL")
.allowlist_function("GrB_Vector_new")
.allowlist_function("GrB_Vector_free")
Expand All @@ -74,6 +75,8 @@ fn regenerate_bindings() {
.allowlist_function("GrB_Vector_extractTuples_BOOL")
.allowlist_function("GrB_vxm")
.allowlist_item("LAGRAPH_MSG_LEN")
.allowlist_item("RPQMatrixOp")
.allowlist_type("RPQMatrixPlan")
.allowlist_type("LAGraph_Graph")
.allowlist_type("LAGraph_Kind")
.allowlist_function("LAGraph_CheckGraph")
Expand All @@ -83,6 +86,11 @@ fn regenerate_bindings() {
.allowlist_function("LAGraph_Delete")
.allowlist_function("LAGraph_Cached_AT")
.allowlist_function("LAGraph_MMRead")
.allowlist_function("LAGraph_RPQMatrix")
.allowlist_function("LAGraph_DestroyRpqMatrixPlan")
.allowlist_function("LAGraph_RPQMatrix_label")
.allowlist_function("LAGraph_RPQMatrix_Free")
.allowlist_function("LAGraph_RegularPathQuery")
.default_enum_style(bindgen::EnumVariation::Rust {
non_exhaustive: false,
})
Expand Down
1 change: 1 addition & 0 deletions src/graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ impl Drop for LagraphGraph {
unsafe impl Send for LagraphGraph {}
unsafe impl Sync for LagraphGraph {}

#[derive(Debug)]
pub struct GraphblasVector {
pub inner: GrB_Vector,
}
Expand Down
51 changes: 51 additions & 0 deletions src/lagraph_sys_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ unsafe extern "C" {
ncols: GrB_Index,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_Matrix_dup(C: *mut GrB_Matrix, A: GrB_Matrix) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_Matrix_nvals(nvals: *mut GrB_Index, A: GrB_Matrix) -> GrB_Info;
}
Expand All @@ -168,6 +171,14 @@ unsafe extern "C" {
dup: GrB_BinaryOp,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_Matrix_extractElement_BOOL(
x: *mut bool,
A: GrB_Matrix,
i: GrB_Index,
j: GrB_Index,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_vxm(
w: GrB_Vector,
Expand Down Expand Up @@ -261,3 +272,43 @@ unsafe extern "C" {
msg: *mut ::std::os::raw::c_char,
) -> ::std::os::raw::c_int;
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum RPQMatrixOp {
RPQ_MATRIX_OP_LABEL = 0,
RPQ_MATRIX_OP_LOR = 1,
RPQ_MATRIX_OP_CONCAT = 2,
RPQ_MATRIX_OP_KLEENE = 3,
RPQ_MATRIX_OP_KLEENE_L = 4,
RPQ_MATRIX_OP_KLEENE_R = 5,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct RPQMatrixPlan {
pub op: RPQMatrixOp,
pub lhs: *mut RPQMatrixPlan,
pub rhs: *mut RPQMatrixPlan,
pub mat: GrB_Matrix,
pub res_mat: GrB_Matrix,
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix(
nnz: *mut GrB_Index,
plan: *mut RPQMatrixPlan,
msg: *mut ::std::os::raw::c_char,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_label(
mat: *mut GrB_Matrix,
x: GrB_Index,
i: GrB_Index,
j: GrB_Index,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_DestroyRpqMatrixPlan(plan: *mut RPQMatrixPlan) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_Free(mat: *mut GrB_Matrix) -> GrB_Info;
}
2 changes: 2 additions & 0 deletions src/rpq/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
//! let result: NfaRpqResult = NfaRpqEvaluator.evaluate(&query, &graph)?;
//! ```

pub mod rpqmatrix;

use crate::graph::{GraphDecomposition, GraphError};
use crate::sparql::ExtractError;
use spargebra::SparqlSyntaxError;
Expand Down
Loading
Loading