-
Notifications
You must be signed in to change notification settings - Fork 0
Add basic LAGraph expression evaluation #2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Turns out there was an extra brace when parsing the graph edges due to wrong bounds. Let's fix it.
This patch extends plain nvals information within the label in the execution plan with label name. It is needed to match the actual matrices and labels to generate complete plan.
9c0dc19 to
2a17a79
Compare
2a17a79 to
b6644d3
Compare
a13a26a to
89dd251
Compare
This patch introduces basic RPQ evaluation logic. It basically interfaces the LAGraph (experimental) library that offers a collection of the sparse linear algebra-based algorithms. It uses GraphBLAS [^1] as a backend library for evaluating sparse matrix algebra. Rust <-> C interfacing is done via FFI. Currently, the project requires our fork [^2] since the required algorithm is not upstreamed yet. If you are reading this and notice we occasionally have removed this from the fork we are asking for an excuse and hope that you will be able to find the suitable algorithm by yourself from the interfaces described on the Rust side. [^1] https://github.com/DrTimothyAldenDavis/GraphBLAS [^2] https://github.com/SparseLinearAlgebra/LAGraph
89dd251 to
4fb1fd0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR introduces basic Regular Path Query (RPQ) evaluation using the LAGraph library with GraphBLAS as the backend. The implementation adds FFI bindings to interface with C libraries and includes query execution with performance benchmarking capabilities.
Key changes:
- Integration of LAGraph/GraphBLAS via FFI for sparse matrix operations
- Implementation of RPQ evaluation logic with operator translation to matrix operations
- Addition of randomized plan selection and performance measurement infrastructure
Reviewed Changes
Copilot reviewed 11 out of 13 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| vendor/LAGraph | Added LAGraph as a git submodule dependency |
| src/query.rs | Added Clone trait derivations to enable query cloning |
| src/plan.rs | Introduced LabelMeta struct and replaced simple cost function with random selection |
| src/main.rs | Added query execution loop with performance benchmarking and statistics collection |
| src/grb.rs | Added GraphBLAS Matrix FFI wrapper |
| src/graph.rs | Extended graph loading to include matrix files and vertex mappings, added error handling |
| src/eval.rs | Implemented RPQ evaluation via LAGraph FFI bindings |
| build.rs | Added linker configuration for LAGraph libraries |
| _typos.toml | Configured typo checker to exclude vendor directory |
| Cargo.toml | Added rand dependency |
| .gitmodules | Configured LAGraph submodule |
| .github/workflows/ci.yml | Added build steps for GraphBLAS and LAGraph dependencies |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| let cost_func = SillyCostFn; | ||
| let cost_func = CostFn; | ||
| let extractor = Extractor::new(&runner.egraph, cost_func); | ||
| extractor.find_best(runner.roots[0]).1.to_string() |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test uses undefined CostFn type. This should be RandomCostFn to match the actual implementation that replaced SillyCostFn.
| extractor.find_best(runner.roots[0]).1.to_string() | |
| let cost_func = RandomCostFn; |
| let mut splits = line.split_whitespace(); | ||
| let edge = splits.next()?; | ||
| let edge = edge[1..edge.len()].to_string(); | ||
| let edge = edge[1..edge.len() - 1].to_string(); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String slicing edge[1..edge.len() - 1] will panic if edge.len() is 0 or 1. Add length validation before slicing or use safer string manipulation methods.
| .lines() | ||
| .filter_map(|line| { | ||
| let mut splits = line.split_whitespace(); | ||
| let vert = splits.next()?; |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
String slicing vert[1..vert.len() - 1] will panic if vert.len() is 0 or 1. Add length validation before slicing or use safer string manipulation methods.
| let vert = splits.next()?; | |
| let vert = splits.next()?; | |
| if vert.len() < 2 { | |
| return None; | |
| } |
| let mut mat: grb::Matrix = grb::Matrix(std::ptr::null_mut()); | ||
| let mat = graph | ||
| .mats | ||
| .get(&meta.name) | ||
| .or({ | ||
| graph.verts.get(&meta.name).map(|vert_idx| { |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Variable mat is shadowed immediately after declaration. The mutable mat on line 103 is never used before being shadowed on line 104, making its initialization pointless. Remove the declaration on line 103 or rename one of the variables.
| let mut mat: grb::Matrix = grb::Matrix(std::ptr::null_mut()); | |
| let mat = graph | |
| .mats | |
| .get(&meta.name) | |
| .or({ | |
| graph.verts.get(&meta.name).map(|vert_idx| { | |
| let mat = graph | |
| .mats | |
| .get(&meta.name) | |
| .or({ | |
| graph.verts.get(&meta.name).map(|vert_idx| { | |
| let mut mat: grb::Matrix = grb::Matrix(std::ptr::null_mut()); |
| let runs: u32 = 1000; | ||
| let results: Vec<(RecExpr<Plan>, usize, Duration)> = | ||
| run_random(&graph, runs, &expr).collect(); | ||
| let first_n_runs = runs / 100; |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integer division runs / 100 will be 0 when runs < 100, causing no results to be printed in the 'First N runs' section. Consider using max(1, runs / 100) or a different calculation.
| let first_n_runs = runs / 100; | |
| let first_n_runs = std::cmp::max(1, runs / 100); |
| .or({ | ||
| graph.verts.get(&meta.name).map(|vert_idx| { | ||
| unsafe { | ||
| LAGraph_RPQMatrix_label( | ||
| &mut mat as *mut grb::Matrix, | ||
| *vert_idx, | ||
| graph.verts.len(), | ||
| graph.verts.len(), | ||
| ); | ||
| } | ||
| &mat | ||
| }) | ||
| }) |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This closure references mat from the outer scope (line 103), but mat is shadowed on line 104. The reference &mat on line 117 would refer to the outer uninitialized matrix. This code would not compile as written, or has undefined behavior.
| LAGraph_RPQMatrix(&mut ans, plan as *mut RpqMatrixPlan, null_mut()); | ||
| LAGraph_DestroyRpqMatrixPlan(plan); |
Copilot
AI
Nov 19, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return value from LAGraph_RPQMatrix is ignored. Check the return code and propagate errors appropriately, similar to how LAGraph_MMRead is checked in graph.rs.
| LAGraph_RPQMatrix(&mut ans, plan as *mut RpqMatrixPlan, null_mut()); | |
| LAGraph_DestroyRpqMatrixPlan(plan); | |
| let status = LAGraph_RPQMatrix(&mut ans, plan as *mut RpqMatrixPlan, null_mut()); | |
| LAGraph_DestroyRpqMatrixPlan(plan); | |
| if status != 0 { | |
| return Err(format!("LAGraph_RPQMatrix failed with error code {}", status)); | |
| } |
This patch introduces basic RPQ evaluation logic. It basically
interfaces the LAGraph (experimental) library that offers a collection
of the sparse linear algebra-based algorithms. It uses GraphBLAS [^1] as
a backend library for evaluating sparse matrix algebra. Rust <-> C
interfacing is done via FFI. Currently, the project requires our fork
[^2] since the required algorithm is not upstreamed yet. If you are
reading this and notice we occasionally have removed this from the fork
we are asking for an excuse and hope that you will be able to find the
suitable algorithm by yourself from the interfaces described on the Rust
side.
[^1] https://github.com/DrTimothyAldenDavis/GraphBLAS
[^2] https://github.com/SparseLinearAlgebra/LAGraph