Skip to content

Commit 23c4c87

Browse files
committed
modules, antijoin
1 parent e1d26e8 commit 23c4c87

File tree

4 files changed

+147
-199
lines changed

4 files changed

+147
-199
lines changed

src/bin/graspan1.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@ use datalog::Iteration;
33

44
fn main() {
55

6+
// Make space for input data.
67
let mut nodes = Vec::new();
78
let mut edges = Vec::new();
89

10+
// Read input data from a handy file.
911
use std::io::{BufRead, BufReader};
1012
use std::fs::File;
1113

@@ -26,21 +28,23 @@ fn main() {
2628
}
2729
}
2830

31+
// Create a new iteration context, ...
2932
let mut iteration = Iteration::new();
3033

34+
// .. some variables, ..
3135
let variable1 = iteration.variable::<(u32,u32)>("nodes");
3236
let variable2 = iteration.variable::<(u32,u32)>("edges");
3337

38+
// .. load them with some initial values, ..
3439
variable1.insert(nodes.into());
3540
variable2.insert(edges.into());
3641

42+
// .. and then start iterating rules!
3743
while iteration.changed() {
38-
3944
// N(a,c) <- N(a,b), E(b,c)
4045
variable1.from_join(&variable1, &variable2, |_b, &a, &c| (c,a));
41-
4246
}
4347

44-
let reachable = variable1.complete();
48+
// let _reachable = variable1.complete();
4549

4650
}

src/join.rs

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
use super::{Variable, Relation};
2+
3+
pub fn join_into<Key: Ord, Val1: Ord, Val2: Ord, Result: Ord, F: Fn(&Key, &Val1, &Val2)->Result>(
4+
input1: &Variable<(Key, Val1)>,
5+
input2: &Variable<(Key, Val2)>,
6+
output: &Variable<Result>,
7+
logic: F) {
8+
9+
let mut results = Vec::new();
10+
11+
// Read-only access to each variable.
12+
let tuples1 = input1.tuples.borrow();
13+
let tuples2 = input2.tuples.borrow();
14+
15+
let recent1 = input1.recent.borrow();
16+
let recent2 = input2.recent.borrow();
17+
18+
for batch2 in tuples2.iter() {
19+
join_helper(&recent1, &batch2, |k,v1,v2| results.push(logic(k,v1,v2)));
20+
}
21+
22+
for batch1 in tuples1.iter() {
23+
join_helper(&batch1, &recent2, |k,v1,v2| results.push(logic(k,v1,v2)));
24+
}
25+
26+
join_helper(&recent1, &recent2, |k,v1,v2| results.push(logic(k,v1,v2)));
27+
28+
output.insert(results.into());
29+
}
30+
31+
pub fn antijoin_into<Key: Ord, Val: Ord, Result: Ord, F: Fn(&Key, &Val)->Result>(
32+
input1: &Variable<(Key, Val)>,
33+
input2: &Relation<Key>,
34+
output: &Variable<Result>,
35+
logic: F) {
36+
37+
let mut results = Vec::new();
38+
let mut tuples2 = &input2[..];
39+
40+
for &(ref key, ref val) in input1.recent.borrow().iter() {
41+
tuples2 = gallop(tuples2, |k| k < key);
42+
if tuples2.first() == Some(key) {
43+
results.push(logic(key, val));
44+
}
45+
}
46+
47+
// elements should be in-order, as just a filter.
48+
let relation = Relation { elements: results };
49+
output.insert(relation);
50+
}
51+
52+
fn join_helper<K: Ord, V1, V2, F: FnMut(&K, &V1, &V2)>(mut slice1: &[(K,V1)], mut slice2: &[(K,V2)], mut result: F) {
53+
54+
while !slice1.is_empty() && !slice2.is_empty() {
55+
56+
if slice1[0].0 == slice2[0].0 {
57+
58+
let mut key1_count = 0;
59+
while key1_count < slice1.len() && slice1[0].0 == slice1[key1_count].0 {
60+
key1_count += 1;
61+
}
62+
63+
let mut key2_count = 0;
64+
while key2_count < slice2.len() && slice2[0].0 == slice2[key2_count].0 {
65+
key2_count += 1;
66+
}
67+
68+
for index1 in 0 .. key1_count {
69+
for index2 in 0 .. key2_count {
70+
result(&slice1[0].0, &slice1[index1].1, &slice2[index2].1);
71+
}
72+
}
73+
74+
slice1 = &slice1[key1_count..];
75+
slice2 = &slice2[key2_count..];
76+
77+
}
78+
else {
79+
80+
if slice1[0].0 < slice2[0].0 {
81+
slice1 = gallop(slice1, |x| &x.0 < &slice2[0].0);
82+
}
83+
else {
84+
slice2 = gallop(slice2, |x| &x.0 < &slice1[0].0);
85+
}
86+
87+
}
88+
}
89+
}
90+
91+
#[inline(always)]
92+
pub fn gallop<'a, T, F: Fn(&T)->bool>(mut slice: &'a [T], cmp: F) -> &'a [T] {
93+
// if empty slice, or already >= element, return
94+
if slice.len() > 0 && cmp(&slice[0]) {
95+
let mut step = 1;
96+
while step < slice.len() && cmp(&slice[step]) {
97+
slice = &slice[step..];
98+
step = step << 1;
99+
}
100+
101+
step = step >> 1;
102+
while step > 0 {
103+
if step < slice.len() && cmp(&slice[step]) {
104+
slice = &slice[step..];
105+
}
106+
step = step >> 1;
107+
}
108+
109+
slice = &slice[1..]; // advance one, as we always stayed < value
110+
}
111+
112+
return slice;
113+
}

src/lib.rs

Lines changed: 12 additions & 196 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
use std::rc::Rc;
1010
use std::cell::RefCell;
1111

12+
mod map;
13+
mod join;
14+
1215
/// A static, ordered list of key-value pairs.
1316
///
1417
/// A relation represents a fixed set of key-value pairs. In many places in a
@@ -100,6 +103,15 @@ impl<Tuple: Ord> Variable<Tuple> {
100103
{
101104
join::join_into(input1, input2, self, logic)
102105
}
106+
pub fn from_antijoin<K: Ord,V: Ord, F: Fn(&K,&V)->Tuple>(
107+
&self,
108+
input1: &Variable<(K,V)>,
109+
input2: &Relation<K>,
110+
logic: F)
111+
{
112+
join::antijoin_into(input1, input2, self, logic)
113+
}
114+
103115
pub fn from_map<T2: Ord, F: Fn(&T2)->Tuple>(&self, input: &Variable<T2>, logic: F) {
104116
map::map_into(input, self, logic)
105117
}
@@ -177,200 +189,4 @@ impl<Tuple: Ord> VariableTrait for Variable<Tuple> {
177189

178190
!self.recent.borrow().is_empty()
179191
}
180-
}
181-
182-
183-
// fn antijoin_into<Key: Ord, Val: Ord>(
184-
// input1: &Variable<(Key, Val)>,
185-
// input2: &Relation<Key>,
186-
// output: &Variable<Result>) {
187-
188-
// let mut results = Vec::new();
189-
190-
// // Scoped so that we don't write to `output` while holding any borrows.
191-
// {
192-
// // Read-only access to each variable.
193-
// let tuples1 = input1.tuples.borrow();
194-
// let tuples2 = input2.tuples.borrow();
195-
196-
// let recent1 = input1.recent.borrow();
197-
// let recent2 = input2.recent.borrow();
198-
199-
// // Iterate through each new input1 batch.
200-
// for &(ref key1, ref val1) in recent1.iter() {
201-
// for batch2 in tuples2.iter() {
202-
// for &(ref key2, ref val2) in batch2.iter() {
203-
// if key1 == key2 {
204-
// results.push(key1, val1, val2));
205-
// }
206-
// }
207-
// }
208-
// }
209-
// }
210-
211-
// output.insert(results.into());
212-
// }
213-
214-
// fn main() {
215-
216-
// let mut nodes = Vec::new();
217-
// let mut edges = Vec::new();
218-
219-
// use std::io::{BufRead, BufReader};
220-
// use std::fs::File;
221-
222-
// let filename = std::env::args().nth(1).unwrap();
223-
// let file = BufReader::new(File::open(filename).unwrap());
224-
// for readline in file.lines() {
225-
// let line = readline.ok().expect("read error");
226-
// if !line.starts_with('#') && line.len() > 0 {
227-
// let mut elts = line[..].split_whitespace();
228-
// let src: u32 = elts.next().unwrap().parse().ok().expect("malformed src");
229-
// let dst: u32 = elts.next().unwrap().parse().ok().expect("malformed dst");
230-
// let typ: &str = elts.next().unwrap();
231-
// match typ {
232-
// "n" => { nodes.push((dst, src)); },
233-
// "e" => { edges.push((src, dst)); },
234-
// unk => { panic!("unknown type: {}", unk)},
235-
// }
236-
// }
237-
// }
238-
239-
// let mut iteration = Iteration::new();
240-
241-
// let variable1 = iteration.variable::<(u32,u32)>("nodes");
242-
// let variable2 = iteration.variable::<(u32,u32)>("edges");
243-
244-
// variable1.insert(nodes.into());
245-
// variable2.insert(edges.into());
246-
247-
// while iteration.changed() {
248-
249-
// // N(a,c) <- N(a,b), E(b,c)
250-
// variable1.from_join(&variable1, &variable2, |_b, &a, &c| (c,a));
251-
252-
// }
253-
254-
// let reachable = variable1.complete();
255-
256-
// }
257-
258-
mod map {
259-
260-
use super::Variable;
261-
262-
pub fn map_into<T1: Ord, T2: Ord, F: Fn(&T1)->T2>(
263-
input: &Variable<T1>,
264-
output: &Variable<T2>,
265-
logic: F) {
266-
267-
let mut results = Vec::new();
268-
let recent = input.recent.borrow();
269-
for tuple in recent.iter() {
270-
results.push(logic(tuple));
271-
}
272-
273-
output.insert(results.into());
274-
}
275-
276-
}
277-
278-
mod join {
279-
280-
use super::Variable;
281-
282-
pub fn join_into<Key: Ord, Val1: Ord, Val2: Ord, Result: Ord, F: Fn(&Key, &Val1, &Val2)->Result>(
283-
input1: &Variable<(Key, Val1)>,
284-
input2: &Variable<(Key, Val2)>,
285-
output: &Variable<Result>,
286-
logic: F) {
287-
288-
let mut results = Vec::new();
289-
290-
// Scoped so that we don't write to `output` while holding any borrows.
291-
{
292-
// Read-only access to each variable.
293-
let tuples1 = input1.tuples.borrow();
294-
let tuples2 = input2.tuples.borrow();
295-
296-
let recent1 = input1.recent.borrow();
297-
let recent2 = input2.recent.borrow();
298-
299-
for batch2 in tuples2.iter() {
300-
join_helper(&recent1, &batch2, |k,v1,v2| results.push(logic(k,v1,v2)))
301-
}
302-
303-
for batch1 in tuples1.iter() {
304-
join_helper(&batch1, &recent2, |k,v1,v2| results.push(logic(k,v1,v2)))
305-
}
306-
307-
join_helper(&recent1, &recent2, |k,v1,v2| results.push(logic(k,v1,v2)))
308-
}
309-
310-
output.insert(results.into());
311-
}
312-
313-
fn join_helper<K: Ord, V1, V2, F: FnMut(&K, &V1, &V2)>(mut slice1: &[(K,V1)], mut slice2: &[(K,V2)], mut result: F) {
314-
315-
while !slice1.is_empty() && !slice2.is_empty() {
316-
317-
if slice1[0].0 == slice2[0].0 {
318-
319-
let mut key1_count = 0;
320-
while key1_count < slice1.len() && slice1[0].0 == slice1[key1_count].0 {
321-
key1_count += 1;
322-
}
323-
324-
let mut key2_count = 0;
325-
while key2_count < slice2.len() && slice2[0].0 == slice2[key2_count].0 {
326-
key2_count += 1;
327-
}
328-
329-
for index1 in 0 .. key1_count {
330-
for index2 in 0 .. key2_count {
331-
result(&slice1[0].0, &slice1[index1].1, &slice2[index2].1);
332-
}
333-
}
334-
335-
slice1 = &slice1[key1_count..];
336-
slice2 = &slice2[key2_count..];
337-
338-
}
339-
else {
340-
341-
if slice1[0].0 < slice2[0].0 {
342-
slice1 = gallop(slice1, |x| &x.0 < &slice2[0].0);
343-
}
344-
else {
345-
slice2 = gallop(slice2, |x| &x.0 < &slice1[0].0);
346-
}
347-
348-
}
349-
}
350-
}
351-
352-
353-
#[inline(always)]
354-
pub fn gallop<'a, T, F: Fn(&T)->bool>(mut slice: &'a [T], cmp: F) -> &'a [T] {
355-
// if empty slice, or already >= element, return
356-
if slice.len() > 0 && cmp(&slice[0]) {
357-
let mut step = 1;
358-
while step < slice.len() && cmp(&slice[step]) {
359-
slice = &slice[step..];
360-
step = step << 1;
361-
}
362-
363-
step = step >> 1;
364-
while step > 0 {
365-
if step < slice.len() && cmp(&slice[step]) {
366-
slice = &slice[step..];
367-
}
368-
step = step >> 1;
369-
}
370-
371-
slice = &slice[1..]; // advance one, as we always stayed < value
372-
}
373-
374-
return slice;
375-
}
376192
}

src/map.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
use super::Variable;
2+
3+
pub fn map_into<T1: Ord, T2: Ord, F: Fn(&T1)->T2>(
4+
input: &Variable<T1>,
5+
output: &Variable<T2>,
6+
logic: F) {
7+
8+
let mut results = Vec::new();
9+
let recent = input.recent.borrow();
10+
for tuple in recent.iter() {
11+
results.push(logic(tuple));
12+
}
13+
14+
output.insert(results.into());
15+
}

0 commit comments

Comments
 (0)