Skip to content

Commit a13a26a

Browse files
Add basic LAGraph expression evaluation
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
1 parent 0dca9e7 commit a13a26a

File tree

13 files changed

+485
-68
lines changed

13 files changed

+485
-68
lines changed

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,22 @@ jobs:
1515
runs-on: ubuntu-latest
1616
steps:
1717
- uses: actions/checkout@v4
18+
with:
19+
submodules: recursive
1820
- uses: crate-ci/typos@master
1921
- run: rustup update stable && rustup default stable
2022
- run: cargo fmt --check
2123
- run: cargo clippy
24+
- run: |
25+
git clone --depth 1 https://github.com/DrTimothyAldenDavis/GraphBLAS.git
26+
cd GraphBLAS
27+
make compact
28+
sudo make install
29+
cd ..
30+
- run: |
31+
cd vendor/LAGraph
32+
make
33+
sudo make install
34+
cd ../..
2235
- run: cargo build --verbose
2336
- run: cargo test --verbose

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "vendor/LAGraph"]
2+
path = vendor/LAGraph
3+
url = https://github.com/SparseLinearAlgebra/LAGraph.git

Cargo.lock

Lines changed: 71 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ egg = "0.10.0"
1010
nom = "7.1"
1111
expect-test = "1.5.1"
1212
libc = "0.2.0"
13+
rand = "0.8"

_typos.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[files]
2+
extend-exclude = ["vendor/"]

build.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
println!("cargo:rustc-link-lib=dylib=lagraphx");
3+
println!("cargo:rustc-link-search=native=vendor/LAGraph/build/experimental");
4+
5+
println!("cargo:rustc-link-lib=dylib=lagraph");
6+
println!("cargo:rustc-link-search=native=vendor/LAGraph/build/src");
7+
}

src/eval.rs

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
use std::ptr::null_mut;
2+
3+
use crate::graph::Graph;
4+
use crate::grb;
5+
use crate::plan::Plan;
6+
7+
#[repr(C)]
8+
#[derive(Clone)]
9+
pub enum RpqMatrixOp {
10+
Label,
11+
Lor,
12+
Concat,
13+
Kleene,
14+
KleeneL,
15+
KleeneR,
16+
}
17+
18+
#[repr(C)]
19+
#[derive(Clone)]
20+
pub struct RpqMatrixPlan {
21+
pub op: RpqMatrixOp,
22+
pub lhs: *mut RpqMatrixPlan,
23+
pub rhs: *mut RpqMatrixPlan,
24+
pub mat: grb::Matrix,
25+
pub res_mat: grb::Matrix,
26+
}
27+
28+
#[link(name = "lagraphx")]
29+
extern "C" {
30+
pub fn LAGraph_Init(msg: *mut libc::c_char) -> libc::c_int;
31+
pub fn LAGraph_DestroyRpqMatrixPlan(plan: *mut RpqMatrixPlan);
32+
pub fn LAGraph_RPQMatrix(
33+
ans: *mut usize,
34+
plan: *mut RpqMatrixPlan,
35+
msg: *mut libc::c_char,
36+
) -> libc::c_longlong;
37+
pub fn LAGraph_RPQMatrix_label(
38+
mat: *mut grb::Matrix,
39+
x: usize,
40+
i: usize,
41+
j: usize,
42+
) -> libc::c_longlong;
43+
}
44+
45+
#[link(name = "lagraph")]
46+
extern "C" {
47+
pub fn LAGraph_MMRead(
48+
mat: *mut grb::Matrix,
49+
f: *mut libc::FILE,
50+
msg: *mut libc::c_char,
51+
) -> libc::c_int;
52+
}
53+
54+
pub fn eval(graph: &Graph, expr: egg::RecExpr<Plan>) -> Result<usize, String> {
55+
let mut plans: Vec<RpqMatrixPlan> = vec![
56+
RpqMatrixPlan {
57+
op: RpqMatrixOp::Label,
58+
lhs: null_mut(),
59+
rhs: null_mut(),
60+
mat: grb::Matrix::null(),
61+
res_mat: grb::Matrix::null()
62+
};
63+
expr.len()
64+
];
65+
expr.items().for_each(|(id, plan)| {
66+
let eval_plan = match plan {
67+
&Plan::Seq([lhs, rhs]) => RpqMatrixPlan {
68+
op: RpqMatrixOp::Concat,
69+
lhs: plans.get_mut::<usize>(lhs.into()).unwrap() as *mut RpqMatrixPlan,
70+
rhs: plans.get_mut::<usize>(rhs.into()).unwrap() as *mut RpqMatrixPlan,
71+
res_mat: grb::Matrix::null(),
72+
mat: grb::Matrix::null(),
73+
},
74+
&Plan::Alt([lhs, rhs]) => RpqMatrixPlan {
75+
op: RpqMatrixOp::Lor,
76+
lhs: plans.get_mut::<usize>(lhs.into()).unwrap() as *mut RpqMatrixPlan,
77+
rhs: plans.get_mut::<usize>(rhs.into()).unwrap() as *mut RpqMatrixPlan,
78+
res_mat: grb::Matrix::null(),
79+
mat: grb::Matrix::null(),
80+
},
81+
&Plan::Star([lhs]) => RpqMatrixPlan {
82+
op: RpqMatrixOp::Kleene,
83+
lhs: null_mut(),
84+
rhs: plans.get_mut::<usize>(lhs.into()).unwrap() as *mut RpqMatrixPlan,
85+
res_mat: grb::Matrix::null(),
86+
mat: grb::Matrix::null(),
87+
},
88+
&Plan::LStar([lhs, rhs]) => RpqMatrixPlan {
89+
op: RpqMatrixOp::KleeneL,
90+
lhs: plans.get_mut::<usize>(lhs.into()).unwrap() as *mut RpqMatrixPlan,
91+
rhs: plans.get_mut::<usize>(rhs.into()).unwrap() as *mut RpqMatrixPlan,
92+
res_mat: grb::Matrix::null(),
93+
mat: grb::Matrix::null(),
94+
},
95+
&Plan::RStar([lhs, rhs]) => RpqMatrixPlan {
96+
op: RpqMatrixOp::KleeneR,
97+
lhs: plans.get_mut::<usize>(lhs.into()).unwrap() as *mut RpqMatrixPlan,
98+
rhs: plans.get_mut::<usize>(rhs.into()).unwrap() as *mut RpqMatrixPlan,
99+
res_mat: grb::Matrix::null(),
100+
mat: grb::Matrix::null(),
101+
},
102+
Plan::Label(meta) => {
103+
let mut mat: grb::Matrix = grb::Matrix(std::ptr::null_mut());
104+
let mat = graph
105+
.mats
106+
.get(&meta.name)
107+
.or({
108+
graph.verts.get(&meta.name).map(|vert_idx| {
109+
unsafe {
110+
LAGraph_RPQMatrix_label(
111+
&mut mat as *mut grb::Matrix,
112+
*vert_idx,
113+
graph.verts.len(),
114+
graph.verts.len(),
115+
);
116+
}
117+
&mat
118+
})
119+
})
120+
.unwrap()
121+
.clone();
122+
RpqMatrixPlan {
123+
op: RpqMatrixOp::Label,
124+
lhs: null_mut(),
125+
rhs: null_mut(),
126+
res_mat: grb::Matrix::null(),
127+
mat,
128+
}
129+
}
130+
};
131+
plans[std::convert::Into::<usize>::into(id)] = eval_plan;
132+
});
133+
let plan = plans.iter_mut().last().unwrap();
134+
let mut ans: usize = 0;
135+
unsafe {
136+
LAGraph_RPQMatrix(&mut ans, plan as *mut RpqMatrixPlan, null_mut());
137+
LAGraph_DestroyRpqMatrixPlan(plan);
138+
}
139+
Ok(ans)
140+
}

0 commit comments

Comments
 (0)