From 9054fe983d1a06d8432fd7b0b108f5b95435e033 Mon Sep 17 00:00:00 2001 From: giles Date: Fri, 8 May 2026 09:20:23 +0000 Subject: [PATCH] datalog: tag co-occurrence demo (169/169) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds (cotagged P T1 T2) — P has both T1 and T2 with T1 != T2 — and (tag-pair-count T1 T2 N) which counts posts cotagged with each distinct (T1, T2) pair. Demonstrates count aggregation against a recursive-then-aggregated stream of derived tuples. 2 new demo tests: cooking + vegetarian co-occurrence on a small data set, and a count-of-co-occurrences query. --- lib/datalog/demo.sx | 20 ++++++++++++++++++++ lib/datalog/scoreboard.json | 8 ++++---- lib/datalog/scoreboard.md | 4 ++-- lib/datalog/tests/demo.sx | 23 +++++++++++++++++++++++ 4 files changed, 49 insertions(+), 6 deletions(-) diff --git a/lib/datalog/demo.sx b/lib/datalog/demo.sx index 407facd4..d4a9a29a 100644 --- a/lib/datalog/demo.sx +++ b/lib/datalog/demo.sx @@ -84,6 +84,26 @@ (authored Author P) (tagged P cooking))))) +;; ── Demo 5: tag co-occurrence ─────────────────────────────────── +;; "Posts tagged with both T1 AND T2." Useful for narrowed-down +;; recommendations like "vegetarian cooking" posts. +;; +;; EDB: +;; (tagged POST TAG) +;; IDB: +;; (cotagged POST T1 T2) — post has both T1 and T2 (T1 != T2) +;; (popular-pair T1 T2 N) — count of posts cotagged (T1, T2) +(define + dl-demo-tag-cooccur-rules + (quote + ((cotagged P T1 T2 <- (tagged P T1) (tagged P T2) (!= T1 T2)) + ;; Distinct (T1, T2) pairs that occur somewhere. + (tag-pair T1 T2 <- (cotagged P T1 T2)) + (tag-pair-count T1 T2 N + <- + (tag-pair T1 T2) + (count N P (cotagged P T1 T2)))))) + ;; ── Loader stub ────────────────────────────────────────────────── ;; Wiring to PostgreSQL would replace these helpers with calls into ;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...). diff --git a/lib/datalog/scoreboard.json b/lib/datalog/scoreboard.json index 2b5d08f2..2545002b 100644 --- a/lib/datalog/scoreboard.json +++ b/lib/datalog/scoreboard.json @@ -1,8 +1,8 @@ { "lang": "datalog", - "total_passed": 167, + "total_passed": 169, "total_failed": 0, - "total": 167, + "total": 169, "suites": [ {"name":"tokenize","passed":26,"failed":0,"total":26}, {"name":"parse","passed":18,"failed":0,"total":18}, @@ -13,7 +13,7 @@ {"name":"negation","passed":10,"failed":0,"total":10}, {"name":"aggregates","passed":16,"failed":0,"total":16}, {"name":"api","passed":11,"failed":0,"total":11}, - {"name":"demo","passed":13,"failed":0,"total":13} + {"name":"demo","passed":15,"failed":0,"total":15} ], - "generated": "2026-05-08T09:16:59+00:00" + "generated": "2026-05-08T09:20:09+00:00" } diff --git a/lib/datalog/scoreboard.md b/lib/datalog/scoreboard.md index 639f393a..70c2fe0f 100644 --- a/lib/datalog/scoreboard.md +++ b/lib/datalog/scoreboard.md @@ -1,6 +1,6 @@ # datalog scoreboard -**167 / 167 passing** (0 failure(s)). +**169 / 169 passing** (0 failure(s)). | Suite | Passed | Total | Status | |-------|--------|-------|--------| @@ -13,4 +13,4 @@ | negation | 10 | 10 | ok | | aggregates | 16 | 16 | ok | | api | 11 | 11 | ok | -| demo | 13 | 13 | ok | +| demo | 15 | 15 | ok | diff --git a/lib/datalog/tests/demo.sx b/lib/datalog/tests/demo.sx index 968da0bd..c594a63d 100644 --- a/lib/datalog/tests/demo.sx +++ b/lib/datalog/tests/demo.sx @@ -214,6 +214,29 @@ (quote (cooking-post-by-network me P))) (list)) + ;; ── Tag co-occurrence ────────────────────────────────── + (dl-demo-test-set! "cotagged posts" + (dl-query + (dl-demo-make + (quote + ((tagged p1 cooking) (tagged p1 vegetarian) + (tagged p2 cooking) (tagged p2 quick) + (tagged p3 vegetarian))) + dl-demo-tag-cooccur-rules) + (quote (cotagged P cooking vegetarian))) + (list {:P (quote p1)})) + + (dl-demo-test-set! "tag pair count" + (dl-query + (dl-demo-make + (quote + ((tagged p1 cooking) (tagged p1 vegetarian) + (tagged p2 cooking) (tagged p2 quick) + (tagged p3 cooking) (tagged p3 vegetarian))) + dl-demo-tag-cooccur-rules) + (quote (tag-pair-count cooking vegetarian N))) + (list {:N 2})) + (dl-demo-test-set! "no access without grant" (dl-query (dl-demo-make