diff --git a/core/incremental/ddTests.ts b/core/incremental/ddTests.ts index 5d780ebd..e4330dfe 100644 --- a/core/incremental/ddTests.ts +++ b/core/incremental/ddTests.ts @@ -33,6 +33,7 @@ export function incrTests(writeResults: boolean): Suite { ["contracts", evalTest], ["transitiveClosure", evalTest], ["transitiveClosureMultiSupport", evalTest], + ["singleSourceReach", evalTest], ["sccs", evalTest], ["parse", evalTest], ["aggregation", evalTest], diff --git a/core/incremental/operators/distinct.ts b/core/incremental/operators/distinct.ts index 3a1385cc..ec92e0f6 100644 --- a/core/incremental/operators/distinct.ts +++ b/core/incremental/operators/distinct.ts @@ -15,3 +15,13 @@ export function processDistinct( desc.state.update(data.bindings.bindings, payload.multiplicity); return [{ ...payload, multiplicity: multDiff }]; } + +function getMultDiff(curMult: number, newMult: number): number { + if (curMult < 1 && newMult >= 1) { + return 1; + } + if (curMult >= 1 && newMult < 1) { + return -1; + } + return 0; +} diff --git a/core/incremental/testdata/singleSourceReach.dd.txt b/core/incremental/testdata/singleSourceReach.dd.txt new file mode 100644 index 00000000..ede66d42 --- /dev/null +++ b/core/incremental/testdata/singleSourceReach.dd.txt @@ -0,0 +1,126 @@ +.table edge +---- +application/datalog + +.table start +---- +application/datalog + +start{node: "x"}. +---- +incremental-datalog/trace +start: [start{node: "x"}+1] + +reach{node: B} :- + start{node: B} | + reach{node: A} & + edge{from: A, to: B}. +---- +application/datalog + +reach{}? +---- +application/datalog +reach{node: "x"}. + +.ruleGraph +---- +application/graphviz +digraph G { + "edge" [fillcolor="darksalmon" fontname="Courier" label="edge: []" shape="box" style="filled"]; + "start" [fillcolor="darksalmon" fontname="Courier" label="start: []" shape="box" style="filled"]; + "0" [fillcolor="moccasin" fontname="Courier" label="0: Union []" shape="box" style="filled"]; + "1" [fillcolor="darkseagreen2" fontname="Courier" label="1: Match(start{node: B}) []" shape="box" style="filled"]; + "2" [fillcolor="darkseagreen2" fontname="Courier" label="2: Match(reach{node: A}) [A]" shape="box" style="filled"]; + "3" [fillcolor="darkseagreen2" fontname="Courier" label="3: Match(edge{from: A, to: B}) [A]" shape="box" style="filled"]; + "4" [fillcolor="thistle" fontname="Courier" label="4: Join(A) []" shape="box" style="filled"]; + "5" [fillcolor="" fontname="Courier" label="5: Distinct []" shape="box" style="filled"]; + "reach" [fillcolor="lightblue" fontname="Courier" label="reach: Subst(reach{node: B}) []" shape="box" style="filled"]; + "start" -> "1" []; + "1" -> "0" []; + "reach" -> "2" []; + "edge" -> "3" []; + "3" -> "4" []; + "2" -> "4" []; + "4" -> "0" []; + "0" -> "5" []; + "5" -> "reach" []; +} + +reach{}? +---- +application/datalog +reach{node: "x"}. + +edge{from: "x", to: "a"}. +---- +incremental-datalog/trace +edge: [edge{from: "x", to: "a"}+1] +3: [{A: "x", B: "a"}+1] +4: [{A: "x", B: "a"}+1] +0: [{A: "x", B: "a"}+1] +5: [{A: "x", B: "a"}+1] +reach: [reach{node: "a"}+1] +2: [{A: "a"}+1] +4: [] + +edge{from: "a", to: "b"}. +---- +incremental-datalog/trace +edge: [edge{from: "a", to: "b"}+1] +3: [{A: "a", B: "b"}+1] +4: [{A: "a", B: "b"}+1] +0: [{A: "a", B: "b"}+1] +5: [{A: "a", B: "b"}+1] +reach: [reach{node: "b"}+1] +2: [{A: "b"}+1] +4: [] + +edge{from: "b", to: "c"}. +---- +incremental-datalog/trace +edge: [edge{from: "b", to: "c"}+1] +3: [{A: "b", B: "c"}+1] +4: [{A: "b", B: "c"}+1] +0: [{A: "b", B: "c"}+1] +5: [{A: "b", B: "c"}+1] +reach: [reach{node: "c"}+1] +2: [{A: "c"}+1] +4: [] + +edge{from: "c", to: "b"}. +---- +incremental-datalog/trace +edge: [edge{from: "c", to: "b"}+1] +3: [{A: "c", B: "b"}+1] +4: [{A: "c", B: "b"}+1] +0: [{A: "c", B: "b"}+1] +5: [{A: "c", B: "b"}+1] +reach: [reach{node: "b"}+1] +2: [{A: "b"}+1] +4: [{A: "b", B: "c"}+1] +0: [{A: "b", B: "c"}+1] +5: [] + +-edge{from: "x", to: "a"}. +---- +incremental-datalog/trace +edge: [edge{from: "x", to: "a"}-1] +3: [{A: "x", B: "a"}-1] +4: [{A: "x", B: "a"}-1] +0: [{A: "x", B: "a"}-1] +5: [{A: "x", B: "a"}-1] +reach: [reach{node: "a"}-1] +2: [{A: "a"}-1] +4: [{A: "a", B: "b"}-1] +0: [{A: "a", B: "b"}-1] +5: [{A: "a", B: "b"}-1] +reach: [reach{node: "b"}-1] +2: [{A: "b"}-1] +4: [{A: "b", B: "c"}-1] +0: [{A: "b", B: "c"}-1] +5: [] + +reach{}? +---- +application/datalog