From 43fa31375d5496d410834812e5e9007907d57d00 Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 10:13:13 +0000 Subject: [PATCH] datalog: magic-vs-semi work-shape test on chain-12 (209/209) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Demonstrates the practical effect of goal-directed evaluation: chain of 12 nodes, semi-naive derives the full ancestor closure (78 = 12·13/2 tuples), while a magic-rooted query at node 0 returns only its 12 descendants. Concrete check that magic limits derivation to the query's transitive cone. --- lib/datalog/scoreboard.json | 8 ++++---- lib/datalog/scoreboard.md | 4 ++-- lib/datalog/tests/magic.sx | 29 +++++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 6 deletions(-) diff --git a/lib/datalog/scoreboard.json b/lib/datalog/scoreboard.json index 2884cc4d..1a302808 100644 --- a/lib/datalog/scoreboard.json +++ b/lib/datalog/scoreboard.json @@ -1,8 +1,8 @@ { "lang": "datalog", - "total_passed": 208, + "total_passed": 209, "total_failed": 0, - "total": 208, + "total": 209, "suites": [ {"name":"tokenize","passed":26,"failed":0,"total":26}, {"name":"parse","passed":18,"failed":0,"total":18}, @@ -13,8 +13,8 @@ {"name":"negation","passed":10,"failed":0,"total":10}, {"name":"aggregates","passed":18,"failed":0,"total":18}, {"name":"api","passed":17,"failed":0,"total":17}, - {"name":"magic","passed":21,"failed":0,"total":21}, + {"name":"magic","passed":22,"failed":0,"total":22}, {"name":"demo","passed":18,"failed":0,"total":18} ], - "generated": "2026-05-08T10:06:36+00:00" + "generated": "2026-05-08T10:13:00+00:00" } diff --git a/lib/datalog/scoreboard.md b/lib/datalog/scoreboard.md index 850f96c0..1e78dc45 100644 --- a/lib/datalog/scoreboard.md +++ b/lib/datalog/scoreboard.md @@ -1,6 +1,6 @@ # datalog scoreboard -**208 / 208 passing** (0 failure(s)). +**209 / 209 passing** (0 failure(s)). | Suite | Passed | Total | Status | |-------|--------|-------|--------| @@ -13,5 +13,5 @@ | negation | 10 | 10 | ok | | aggregates | 18 | 18 | ok | | api | 17 | 17 | ok | -| magic | 21 | 21 | ok | +| magic | 22 | 22 | ok | | demo | 18 | 18 | ok | diff --git a/lib/datalog/tests/magic.sx b/lib/datalog/tests/magic.sx index c9e82183..6527aa42 100644 --- a/lib/datalog/tests/magic.sx +++ b/lib/datalog/tests/magic.sx @@ -227,6 +227,35 @@ ;; Magic-sets benefit: query touches only one cluster of a ;; multi-component graph. Semi-naive derives the full closure ;; over both clusters; magic only the seeded one. + ;; Magic-vs-semi work shape: chain of 12. Semi-naive + ;; derives the full closure (78 = 12·13/2). A magic query + ;; rooted at node 0 returns the 12 descendants only — + ;; demonstrating that magic limits derivation to the + ;; query's transitive cone. + (dl-mt-test! "magic vs semi work-shape on chain-12" + (let + ((source (str + "parent(0, 1). parent(1, 2). parent(2, 3). " + "parent(3, 4). parent(4, 5). parent(5, 6). " + "parent(6, 7). parent(7, 8). parent(8, 9). " + "parent(9, 10). parent(10, 11). parent(11, 12). " + "ancestor(X, Y) :- parent(X, Y). " + "ancestor(X, Z) :- parent(X, Y), ancestor(Y, Z)."))) + (let + ((db1 (dl-make-db)) (db2 (dl-make-db))) + (do + (dl-load-program! db1 source) + (dl-saturate! db1) + (dl-load-program! db2 source) + (let + ((semi-count (len (dl-relation db1 "ancestor"))) + (magic-count + (len (dl-magic-query + db2 (list (quote ancestor) 0 (quote X)))))) + ;; Magic returns only descendants of 0 (12 of them). + (and (= semi-count 78) (= magic-count 12)))))) + true) + (dl-mt-test! "magic skips irrelevant clusters" (let ;; Two disjoint chains. Query is rooted in cluster 1.