Skip to content
Merged
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
2 changes: 1 addition & 1 deletion interactive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ workspace = true
[dependencies]
columnar = { workspace = true }
# The columnar kernels for the interpreted backend, pinned by git rev.
corgi = { git = "https://github.com/frankmcsherry/WIP", rev = "4b1d23bfc4ffc8a4ee51e2230216426a17f880a4", features = ["serde"] }
corgi = { git = "https://github.com/frankmcsherry/WIP", rev = "9737792dd5db4b99e8299898ff917b174d37778b", features = ["serde"] }
differential-dataflow = { workspace = true }
serde = { version = "1.0", features = ["derive"] }
smallvec = "1.15.1"
Expand Down
4 changes: 2 additions & 2 deletions interactive/examples/programs/adt.ddp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
-- carrying the field-sum as payload, then matched back out to a (bucket; sum)
-- and counted per bucket. (Contrived — exercises sum intro/outro + fold.)

type Dir = Fwd u64 -- src < dst
| Bwd u64; -- otherwise
type Dir = Fwd int -- src < dst
| Bwd int; -- otherwise

let edges = input 0 : ((int, int) ; ()) | key($0[0] ; $0[1]);

Expand Down
2 changes: 1 addition & 1 deletion interactive/examples/programs/ast.ddp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
-- `$0[0] - $1[0] + 32768` stays non-negative -- corgi's structural order is unsigned at the
-- integer leaf, so signed values are out of contract for `min`.

type Dir = Fwd u64 | Bwd u64;
type Dir = Fwd int | Bwd int;

let rows = input 0 : ((int, int) ; ()) | key($0[0] ; $0[1]);

Expand Down
2 changes: 1 addition & 1 deletion interactive/examples/programs/binders.ddp
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
-- Depth-tracking test: a pattern binder `xs` used INSIDE a fold step. Correct
-- de Bruijn resolution => xs is the case payload at Bound(2) inside the fold;
-- a wrong index would hit the fold's Int element and panic on Proj.
type Node = Node List(u64);
type Node = Node List(int);

let rows = input 0 : ((int, int) ; ()) | key($0[0] ; Node(list($0[0], $0[1])));

Expand Down
2 changes: 1 addition & 1 deletion interactive/examples/programs/tour.ddp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
-- fixtures under tests/programs/ pin individual lowerings and their fallback
-- routing; this program pins that the constructs work TOGETHER.

type Dir = Fwd u64 | Bwd u64;
type Dir = Fwd int | Bwd int;

let edges = input 0 : ((int, int) ; ()) | key($0[0] ; $0[1]);
let roots = input 1 : ((int) ; ()) | key($0[0] ;);
Expand Down
5 changes: 2 additions & 3 deletions interactive/server/bench/ldbc/SNB.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,9 +181,8 @@ independent semantic oracle here. The older four-query panel
retains independent traversal/counting oracles. Official conformance validation
is still separate work.

Floating results use explicit IEEE f64 newtypes with total ordering, not the
specification's Float32 API representation. They are preserved as tagged values
in reports. Shortest-path maintenance uses a hop-indexed bound of `|V|-1` so
Floating results are DDIR Floats (IEEE f64, totally ordered), not the
specification's Float32 API representation. Shortest-path maintenance uses a hop-indexed bound of `|V|-1` so
deletions terminate; this can be expensive on large connected graphs. General
aggregates currently use `collect`/`fold`; nested and ranked outputs are fully
materialized. These are deliberate visible baseline costs, not tuned plans.
Expand Down
3 changes: 3 additions & 0 deletions interactive/server/bench/ldbc/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ def parse(node):
if type(tag) is int and tag >= 0:
return dict(tag=tag, payload=payload)
if isinstance(node, ast.Call) and isinstance(node.func, ast.Name) and not node.keywords and len(node.args) == 1:
if node.func.id == 'Float':
# Rust's shortest round-trip form, which `float` reads exactly (`NaN` and `inf` too).
return float(ast.unparse(node.args[0]))
arg = parse(node.args[0])
if node.func.id == 'Int' and type(arg) is int:
return arg
Expand Down
6 changes: 0 additions & 6 deletions interactive/server/bench/ldbc/snb/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
from collections import Counter
from datetime import datetime, timezone
import itertools
import struct

from .data import millis
from .rel import evaluate
Expand Down Expand Up @@ -68,11 +67,6 @@ def parameters(graph, query=None):


def json_value(value):
if isinstance(value,float):
bits=struct.unpack('>Q',struct.pack('>d',value))[0]
ordered=(~bits & ((1<<64)-1)) if bits>>63 else bits^(1<<63)
payload=ordered^(1<<63)
return dict(tag=0,payload=payload if payload < 1<<63 else payload-(1<<64))
if isinstance(value,tuple): return [json_value(v) for v in value]
if isinstance(value,bool): return int(value)
return value
Expand Down
17 changes: 5 additions & 12 deletions interactive/server/bench/ldbc/test_snb.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""Read-suite witnesses, hand-checked answers, and both engine backends."""
import struct
import unittest

from snb.queries import Context,QUERIES
Expand All @@ -8,12 +7,6 @@
from snb import witness


def decode_float(encoded):
ordered=(encoded['payload'] & ((1<<64)-1))^(1<<63)
bits=ordered^(1<<63) if ordered>>63 else ~ordered & ((1<<64)-1)
return struct.unpack('>d',struct.pack('>Q',bits))[0]


class SuiteTests(unittest.TestCase):
@classmethod
def setUpClass(cls): cls.graph=witness.graph()
Expand All @@ -39,11 +32,11 @@ def test_hand_checked_graph_answers(self):
self.assertEqual(self.rows('ic13'),[[2]])
self.assertEqual(self.rows('ic13',p2=1),[[0]])
self.assertEqual(self.rows('ic14'),[[[1,2,5],78]])
self.assertEqual(decode_float(self.rows('bi15')[0][0]),1.0)
self.assertEqual(self.rows('bi15')[0][0],1.0)
changed=witness.changed(self.graph)
self.assertEqual(self.rows('ic13',changed),[[3]])
self.assertEqual(self.rows('ic14',changed),[])
self.assertAlmostEqual(decode_float(self.rows('bi15',changed)[0][0]),8/3)
self.assertAlmostEqual(self.rows('bi15',changed)[0][0],8/3)

def test_hand_checked_ranking_and_optional_matches(self):
self.assertEqual([r[3] for r in self.rows('ic2')],list(range(10100,10120)))
Expand Down Expand Up @@ -75,9 +68,9 @@ def test_ic3_depends_on_request_and_foreign_messages(self):
def test_hand_checked_floating_aggregates(self):
rows=self.rows('bi1')
self.assertEqual([(r[0],r[1],r[2],r[3],r[5]) for r in rows],[(2012,0,0,31,120),(2012,1,0,4,16)])
self.assertAlmostEqual(decode_float(rows[0][4]),120/31)
self.assertAlmostEqual(decode_float(rows[0][6]),3100/35)
self.assertEqual([(r[0],r[1],r[2],decode_float(r[3])) for r in self.rows('bi13')],[(7,1,1,1.0),(2,0,1,0.0),(5,0,0,0.0)])
self.assertAlmostEqual(rows[0][4],120/31)
self.assertAlmostEqual(rows[0][6],3100/35)
self.assertEqual([(r[0],r[1],r[2],r[3]) for r in self.rows('bi13')],[(7,1,1,1.0),(2,0,1,0.0),(5,0,0,0.0)])



Expand Down
15 changes: 8 additions & 7 deletions interactive/src/backend/corgi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ fn apply_ops(mut c: CC, ops: &[LinearOp], level: usize, plans: &mut [Plan]) -> C
}
LinearOp::Filter(_) => {
let g = plan.graph(op, kshape, vshape);
let mask = corgi::eval_graph(g, CValue::Prod(vec![c.keys.clone(), c.vals.clone()])).into_u64("filter mask").unwrap();
let mask = corgi::eval_graph(g, CValue::Prod(vec![c.keys.clone(), c.vals.clone()]));
let mask = mask.as_i64("filter mask").unwrap();
let keep: Vec<usize> = (0..mask.len()).filter(|&i| mask[i] != 0).collect();
let keys = gather(&c.keys, &keep);
let vals = gather(&c.vals, &keep);
Expand All @@ -126,15 +127,15 @@ fn apply_ops(mut c: CC, ops: &[LinearOp], level: usize, plans: &mut [Plan]) -> C
LinearOp::EnterAt(_) => {
let g = plan.graph(op, kshape, vshape);
// The key and val columns are IDENTITY here — only times change. Evaluate the
// delay field to a `U64` column and join it into each time in place. Joining
// delay field to an `Int` column and join it into each time in place. Joining
// `Product(0, PointStamp([0,..,0, delay]))` is, coordinate-wise, `max` at index
// `level-1` and identity everywhere else (u64's minimum is 0), so the delta
// never has to be built. The epoch is lane 0, so PointStamp index `level-1` is
// lane `level`, and the join is one lane-wise max.
let raw = corgi::eval_graph(g, CValue::Prod(vec![c.keys.clone(), c.vals.clone()]))
.into_u64("enter_at delay")
.into_i64("enter_at delay")
.unwrap();
let delays: Vec<u64> = raw.iter().map(|r| 256 * (64 - r.leading_zeros() as u64)).collect();
let delays: Vec<u64> = raw.iter().map(|&r| 256 * (64 - (r as u64).leading_zeros() as u64)).collect();
c.times.lane_max(level.saturating_sub(1) + 1, &delays);
c
}
Expand All @@ -150,7 +151,7 @@ fn apply_ops(mut c: CC, ops: &[LinearOp], level: usize, plans: &mut [Plan]) -> C
// PointStamp index `level-1` is lane `level`; at the root there is no iteration
// coordinate and the value is zero.
let iters: Vec<u64> = if level == 0 { vec![0; c.times.len()] } else { c.times.lane(level) };
let lane = CValue::u64(iters);
let lane = CValue::i64(iters.into_iter().map(|i| i as i64).collect());
let vals = match c.vals {
CValue::Prod(mut fields) => { fields.push(lane); CValue::Prod(fields) }
CValue::Unit(_) => CValue::Prod(vec![lane]),
Expand All @@ -173,13 +174,13 @@ fn apply_ops(mut c: CC, ops: &[LinearOp], level: usize, plans: &mut [Plan]) -> C
for (row, end) in ends.into_iter().enumerate() {
for p in 0..(end - start) {
reps.push(row);
pos.push(p as u64);
pos.push(p as i64);
}
start = end;
}
CorgiContainer {
keys: gather(&c.keys, &reps),
vals: CValue::Prod(vec![CValue::u64(pos), elems]),
vals: CValue::Prod(vec![CValue::i64(pos), elems]),
times: c.times.gather(&reps),
diffs: reps.iter().map(|&r| c.diffs[r]).collect(),
}
Expand Down
4 changes: 2 additions & 2 deletions interactive/src/corgi/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -197,8 +197,8 @@ mod test {
/// The declared shapes of each family — what a program's schema would pin (a variant carries
/// only its tag, so a family with sums cannot be pinned from a row).
fn shapes_of(name: &str) -> (corgi::Shape, corgi::Shape) {
use corgi::Shape::{List, Prim, Prod, Sum};
let u = || Prim(64);
use corgi::Shape::{Int, List, Prod, Sum};
let u = || Int;
let pair = || Prod(vec![u(), u()]);
match name {
"scalars" => (u(), u()),
Expand Down
Loading
Loading