Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
95d7319
feat: collect metada from mm format
suvorovrain Jun 24, 2026
bf06e96
feat: [wip] add optimizer based on metadata
suvorovrain Jul 7, 2026
632c3c1
feat: create rpqmatrix submodule
suvorovrain Jul 15, 2026
beb681c
feat: support optimizer for rpqmatrix in cli
suvorovrain Jul 15, 2026
96883d5
feat: add unit tests for cardinality-based optimizer
suvorovrain Jul 18, 2026
4cb4e60
feat: add integration tests
suvorovrain Jul 18, 2026
9782423
feat: add tests for metadata
suvorovrain Jul 18, 2026
73331c4
feat: add fixed number of runs benchmark mode
suvorovrain Jul 18, 2026
0c509e1
feat: save results for each run in fixed-runs bench mode
suvorovrain Jul 19, 2026
a10faff
feat: update vendor
suvorovrain Jul 21, 2026
d8e2650
feat: update vendor
suvorovrain Jul 21, 2026
a7bedf1
feat: update vendor. recompile project if lagraph changed
suvorovrain Jul 23, 2026
adcb7e6
feat: update vendor (optimize rpqmatrix algo)
suvorovrain Jul 25, 2026
688b56c
feat: supprot csc matrix format for any-con queries
suvorovrain Aug 14, 2026
9607002
update vendor
suvorovrain Sep 3, 2026
45b60c4
feat: update vendor - dynamicly closyre
suvorovrain Sep 5, 2026
cc14755
feat: compile egg rules only ones
suvorovrain Sep 6, 2026
0615f4f
feat: update vendor - another dynamic kleene change
suvorovrain Sep 6, 2026
f205659
update vendor: frontier kleene
suvorovrain Sep 6, 2026
4d99334
vendor: update vendor
suvorovrain Sep 26, 2026
3e3eb3c
feat: simple meta optimizers
suvorovrain Sep 26, 2026
2506053
feat: stats module for optimizers
suvorovrain Sep 26, 2026
77f34c6
feat: change join estimation
suvorovrain Sep 28, 2026
19660b6
vendor: add pang and sampling cost functions
suvorovrain Oct 2, 2026
668ffec
feat: add pang and sampling optimizers
suvorovrain Oct 2, 2026
16f8443
fix: ci, docs and other
suvorovrain Oct 6, 2026
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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.vscode
Cargo.lock
# Generated by Cargo
# will have compiled files and executables
debug
Expand Down
581 changes: 271 additions & 310 deletions AGENTS.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[workspace]
resolver = "2"
resolver = "3"
members = ["pathrex-sys", "pathrex"]

[workspace.package]
edition = "2024"
rust-version = "1.85"
rust-version = "1.90"
license = "MIT"
repository = "https://github.com/SparseLinearAlgebra/pathrex"
homepage = "https://github.com/SparseLinearAlgebra/pathrex"
Expand Down
83 changes: 82 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,84 @@

## Architecture

[Architecture diagram](docs/arc.png)
The workspace contains the Rust API and CLI in `pathrex/` and the native
build and FFI bindings in `pathrex-sys/`. See the
[architecture and contributor guide](AGENTS.md#architecture--key-abstractions)
for the current module layout and query preparation pipeline.

## Local build (Linux)

The minimum supported Rust version (MSRV) is **1.90**, not merely the version
that introduced edition 2024. The current dependency set includes
`ordered-float 5.5.0`, which requires Rust 1.90; the RDF/SPARQL dependencies
also require a newer compiler than 1.85. Both workspace crates inherit the
`rust-version` declared in the root `Cargo.toml`.
The workspace uses [Cargo resolver 3](https://doc.rust-lang.org/edition-guide/rust-2024/cargo-resolver.html),
which prefers dependency versions compatible with that declared Rust version.

On Debian/Ubuntu, install the native build tools:

```bash
sudo apt-get update
sudo apt-get install -y build-essential cmake git git-lfs
rustup toolchain install 1.90.0 --profile minimal
```

Run the following commands **from the Pathrex workspace root** (the directory
containing this README; `Databases/pathrex` when using RPQ_bench):

```bash
git submodule update --init --recursive
git lfs pull

# CLI and benchmark support; the bench feature is required for the binary.
cargo +1.90.0 build --release --features bench
./target/release/pathrex --help
./target/release/pathrex bench --help

# Unit, integration, and documentation tests, including the CLI.
cargo +1.90.0 test --workspace --features bench
```

For library-only development, use `cargo +1.90.0 build --workspace` instead of
the CLI build above.

Git LFS supplies the integration-test fixtures. An ordinary build uses the
checked-in FFI bindings and **does not require Clang/libclang**. The build script
fetches SuiteSparse:GraphBLAS at the pinned tag `v10.3.1`, builds it and the
LAGraph submodule as static libraries, and links them automatically. No
system-wide GraphBLAS/LAGraph installation or `LD_LIBRARY_PATH` is needed;
the GCC OpenMP runtime (`libgomp` on Linux) remains a dynamic dependency.
The first build requires network access for Cargo dependencies and GraphBLAS
and performs a substantial native compilation. Subsequent builds reuse the
files under `target/`. Reduce Cargo's job count with `-j 2` if memory is limited.

When building from the **RPQ_bench root**, the equivalent CLI build is:

```bash
cargo +1.90.0 build --release --manifest-path Databases/pathrex/Cargo.toml --features bench
Databases/pathrex/target/release/pathrex --help
```

`Cargo.lock` is currently ignored by this repository. Preserve the generated
lockfile with the experiment artifacts and use `--locked` for subsequent builds
and tests to keep dependency versions unchanged. The MSRV statement refers to
the current dependency set, not to every future version allowed by the manifests.

### Optional binding regeneration

Only regenerate bindings when the native API changes:

```bash
sudo apt-get install -y clang libclang-dev
cargo +1.90.0 build --workspace --features pathrex-sys/regenerate-bindings
```

This command rewrites `pathrex-sys/src/lagraph_sys_generated.rs`. Do not edit that
file manually. If bindgen reports `stddef.h` missing, check that Clang and
libclang come from compatible installations and remove stale include-path
overrides such as `BINDGEN_EXTRA_CLANG_ARGS`; ordinary builds can use the
checked-in bindings without regenerating them.

## Features

Expand All @@ -23,6 +100,8 @@
RDF (Turtle / N-Triples).
- **SPARQL frontend**: parses `SELECT` queries with a single triple/property-path
pattern.
- **RPQMatrix endpoint constraints**: variable endpoints, a fixed subject, a
fixed object, or both fixed endpoints; endpoint selectors are part of the plan.
- **Benchmarking** with [`criterion`](https://crates.io/crates/criterion):
per-query timing, JSON output, checkpoint/resume, optional HTML plots.
- **Reusable Rust library** with backend-agnostic `Graph<B>`, `GraphSource`,
Expand Down Expand Up @@ -97,6 +176,8 @@ Subcommands:
| `-q`, `--queries <FILE>` | Queries file (see format below). |
| `-a`, `--algo <nfarpq\|rpqmatrix>` | Algorithm(s). Repeat to run several. |
| `-b`, `--base-iri [<IRI>]` | Optional `BASE <iri>` to prepend to each query. Bare `--base-iri` uses `http://example.org/`. |
| `-p`, `--rpqmatrix-optimizer <NAME>` | RPQMatrix optimizer: `none`, `join`, `metaac`, `mnc`, `hybrid`, `pang-hybrid`, or `sampling`. |


`query` adds `-o, --output <FILE>` to write JSON.

Expand Down
4 changes: 4 additions & 0 deletions pathrex-sys/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ directory.

## System requirements

The workspace MSRV is Rust 1.90. See the
[local build guide](../README.md#local-build-linux) for installation, CLI build,
and test commands.

| Dependency | Purpose |
|---|---|
| **cmake** | Building GraphBLAS and LAGraph from source |
Expand Down
48 changes: 48 additions & 0 deletions pathrex-sys/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ fn main() {

let lagraph_src = manifest_dir.join(LAGRAPH_REL_PATH);
assert_lagraph_submodule_present(&lagraph_src);
watch_lagraph_sources(&lagraph_src);

let graphblas_src = fetch_graphblas(&out_dir);
let graphblas_install = build_graphblas_static(&graphblas_src);
Expand All @@ -77,6 +78,44 @@ fn assert_lagraph_submodule_present(lagraph_src: &Path) {
}
}

fn watch_lagraph_sources(lagraph_src: &Path) {
println!(
"cargo:rerun-if-changed={}",
lagraph_src.join("CMakeLists.txt").display()
);

for rel_dir in ["Config", "cmake_modules", "include", "src", "experimental"] {
let dir = lagraph_src.join(rel_dir);
if dir.exists() {
watch_files_with_extensions(&dir, &["c", "h", "cmake", "in", "txt"]);
}
}
}

fn watch_files_with_extensions(dir: &Path, extensions: &[&str]) {
let entries = std::fs::read_dir(dir)
.unwrap_or_else(|e| panic!("failed to read directory {}: {e}", dir.display()));

for entry in entries {
let path = entry
.unwrap_or_else(|e| panic!("failed to read entry in {}: {e}", dir.display()))
.path();

if path.is_dir() {
watch_files_with_extensions(&path, extensions);
continue;
}

let Some(ext) = path.extension().and_then(|ext| ext.to_str()) else {
continue;
};

if extensions.contains(&ext) {
println!("cargo:rerun-if-changed={}", path.display());
}
}
}

/// Clone SuiteSparse:GraphBLAS at [`GRAPHBLAS_TAG`] into
/// `$OUT_DIR/graphblas-src/`. Returns the path to the source tree.
///
Expand Down Expand Up @@ -292,6 +331,7 @@ fn regenerate_bindings(graphblas_install: &Path) {
.allowlist_item("GrB_Info")
.allowlist_function("GrB_Matrix_new")
.allowlist_function("GrB_Matrix_nvals")
.allowlist_function("GrB_Matrix_nrows")
.allowlist_function("GrB_Matrix_dup")
.allowlist_function("GrB_Matrix_free")
.allowlist_function("GrB_Matrix_extractElement_BOOL")
Expand All @@ -304,6 +344,7 @@ fn regenerate_bindings(graphblas_install: &Path) {
.allowlist_function("GrB_vxm")
.allowlist_item("LAGRAPH_MSG_LEN")
.allowlist_item("RPQMatrixOp")
.allowlist_item("RPQMatrixStorage")
.allowlist_type("RPQMatrixPlan")
.allowlist_type("LAGraph_Graph")
.allowlist_type("LAGraph_Kind")
Expand All @@ -317,7 +358,14 @@ fn regenerate_bindings(graphblas_install: &Path) {
.allowlist_function("LAGraph_Cached_AT")
.allowlist_function("LAGraph_MMRead")
.allowlist_function("LAGraph_RPQMatrix")
.allowlist_function("LAGraph_RPQMatrix_SetGlobalStorageOrientation")
.allowlist_function("LAGraph_RPQMatrix_SetStorageOrientation")
.allowlist_function("LAGraph_RPQMatrix_DupWithStorageOrientation")
.allowlist_function("LAGraph_RPQMatrix_reduce")
.allowlist_function("LAGraph_RPQMatrix_sample_.*")
.allowlist_function("LAGraph_RPQMatrix_reduce_count_vector")
.allowlist_function("LAGraph_RPQMatrix_extended_count_vectors")
.allowlist_function("LAGraph_RPQMatrix_count_vector_.*")
.allowlist_function("LAGraph_DestroyRpqMatrixPlan")
.allowlist_function("LAGraph_RPQMatrix_label")
.allowlist_function("LAGraph_RPQMatrix_Free")
Expand Down
2 changes: 1 addition & 1 deletion pathrex-sys/deps/LAGraph
Submodule LAGraph updated 47 files
+1 −0 .github/workflows/build.yml
+2 −2 CMakeLists.txt
+5 −1 ChangeLog
+12 −10 Makefile
+39 −1 cmake_modules/SuiteSparsePolicy.cmake
+95 −0 data/cycle_flow.mtx
+23 −0 data/matrix_random_flow.mtx
+38 −0 data/rand.mtx
+9 −0 data/wiki.mtx
+4 −4 experimental/algorithm/LAGr_EdgeBetweennessCentrality.c
+1,203 −0 experimental/algorithm/LAGr_MaxFlow.c
+53 −53 experimental/algorithm/LAGr_MaximumMatching.c
+82 −82 experimental/algorithm/LAGr_SwapEdges.c
+2 −2 experimental/algorithm/LAGraph_Coarsen_Matching.c
+9 −9 experimental/algorithm/LAGraph_EstimateDiameter.c
+2 −2 experimental/algorithm/LAGraph_FastGraphletTransform.c
+49 −5 experimental/algorithm/LAGraph_RPQMatrix.c
+505 −0 experimental/algorithm/LAGraph_RPQMatrixSampling.c
+14 −14 experimental/algorithm/LAGraph_RichClubCoefficient.c
+28 −28 experimental/algorithm/LAGraph_lcc.c
+930 −184 experimental/algorithm/LAGraph_msf.c
+176 −91 experimental/algorithm/LAGraph_scc.c
+2 −0 experimental/algorithm/README.md
+0 −0 experimental/benchmark/coarsening-tests/.gitignore
+0 −71 experimental/benchmark/coarsening-tests/CMakeLists.txt
+0 −84 experimental/benchmark/coarsening-tests/Makefile
+0 −4 experimental/benchmark/coarsening-tests/build/.gitignore
+0 −54 experimental/benchmark/coarsening-tests/coarsen.cpp
+0 −10,001 experimental/benchmark/coarsening-tests/parent.mtx
+17 −0 experimental/benchmark/do_maxflow
+9 −9 experimental/benchmark/matching-tests/CMakeLists.txt
+5 −3 experimental/benchmark/matching-tests/Makefile
+81 −0 experimental/benchmark/maxflow_demo.c
+112 −0 experimental/benchmark/msf_demo.c
+6 −6 experimental/benchmark/rcc_demo.c
+196 −0 experimental/benchmark/scc_demo.c
+38 −0 experimental/test/LG_check_flow.c
+6 −0 experimental/test/include/LG_Xtest.h
+176 −0 experimental/test/test_MaxFlow.c
+193 −54 experimental/test/test_msf.c
+110 −83 experimental/test/test_scc.c
+94 −0 experimental/utility/LAGraph_Matrix_Hash.c
+5 −5 experimental/utility/LAGraph_Random_Matrix.c
+2 −2 include/LAGraph.h
+69 −19 include/LAGraphX.h
+ − papers/MaxFlow_HPEC25.pdf
+3 −3 src/benchmark/t1_demo.c
113 changes: 113 additions & 0 deletions pathrex-sys/src/lagraph_sys_generated.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ unsafe extern "C" {
unsafe extern "C" {
pub fn GrB_Matrix_dup(C: *mut GrB_Matrix, A: GrB_Matrix) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_Matrix_nrows(nrows: *mut GrB_Index, A: GrB_Matrix) -> GrB_Info;
}
unsafe extern "C" {
pub fn GrB_Matrix_nvals(nvals: *mut GrB_Index, A: GrB_Matrix) -> GrB_Info;
}
Expand Down Expand Up @@ -320,6 +323,28 @@ pub struct RPQMatrixPlan {
pub mat: GrB_Matrix,
pub res_mat: GrB_Matrix,
}
#[repr(u32)]
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
pub enum RPQMatrixStorage {
RPQ_MATRIX_STORAGE_CSC = 1,
RPQ_MATRIX_STORAGE_CSR = 2,
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_SetGlobalStorageOrientation(storage: RPQMatrixStorage) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_SetStorageOrientation(
mat: GrB_Matrix,
storage: RPQMatrixStorage,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_DupWithStorageOrientation(
dst: *mut GrB_Matrix,
src: GrB_Matrix,
storage: RPQMatrixStorage,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix(
nnz: *mut GrB_Index,
Expand Down Expand Up @@ -348,3 +373,91 @@ unsafe extern "C" {
reduce_type: u8,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_sample_submatrix(
result: *mut GrB_Matrix,
source: GrB_Matrix,
vertices: *const GrB_Index,
count: GrB_Index,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_sample_identity(result: *mut GrB_Matrix, n: GrB_Index) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_sample_apply(
result: *mut GrB_Matrix,
lhs: GrB_Matrix,
rhs: GrB_Matrix,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_sample_union(
result: *mut GrB_Matrix,
lhs: GrB_Matrix,
rhs: GrB_Matrix,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_sample_stats(
nvals: *mut GrB_Index,
active_rows: *mut GrB_Index,
active_cols: *mut GrB_Index,
diagonal_nvals: *mut GrB_Index,
sample: GrB_Matrix,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_reduce_count_vector(
res: *mut GrB_Vector,
mat: GrB_Matrix,
reduce_type: u8,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_extended_count_vectors(
row_extended: *mut GrB_Vector,
col_extended: *mut GrB_Vector,
mat: GrB_Matrix,
row_counts: GrB_Vector,
col_counts: GrB_Vector,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_count_vector_dot(
res: *mut f64,
lhs: GrB_Vector,
rhs: GrB_Vector,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_count_vector_mnc_matmul_nnz(
res: *mut f64,
lhs_rows: GrB_Vector,
lhs_cols: GrB_Vector,
rhs_rows: GrB_Vector,
rhs_cols: GrB_Vector,
lhs_col_extended: GrB_Vector,
rhs_row_extended: GrB_Vector,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_count_vector_sum(res: *mut f64, vector: GrB_Vector) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_count_vector_scale(
res: *mut GrB_Vector,
vector: GrB_Vector,
scale: f64,
cap: f64,
) -> GrB_Info;
}
unsafe extern "C" {
pub fn LAGraph_RPQMatrix_count_vector_mnc_add(
res: *mut GrB_Vector,
lhs: GrB_Vector,
rhs: GrB_Vector,
lambda: f64,
cap: f64,
) -> GrB_Info;
}
2 changes: 2 additions & 0 deletions pathrex/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ memmap2 = "0.9"
oxrdf = "0.3.3"
oxttl = "0.2.3"
rayon = "1"
rand = "0.9.5"
rustfst = "1.2"
spargebra = "0.4.6"
thiserror = "1.0"
Expand All @@ -45,6 +46,7 @@ bench = ["clap", "serde", "serde_json", "chrono", "criterion", "tempfile"]

[dev-dependencies]
tempfile = "3"
expect-test = "1.5.1"

[[bin]]
name = "pathrex"
Expand Down
Loading
Loading