Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 26s
144 lines
5.5 KiB
Plaintext
144 lines
5.5 KiB
Plaintext
;; lib/datalog/demo.sx — example programs over rose-ash-shaped data.
|
|
;;
|
|
;; Phase 10 prototypes Datalog as a rose-ash query language. Wiring
|
|
;; the EDB to actual PostgreSQL is out of scope for this loop (it
|
|
;; would touch service code outside lib/datalog/), but the programs
|
|
;; below show the shape of queries we want, and the test suite runs
|
|
;; them against synthetic in-memory tuples loaded via dl-program-data.
|
|
;;
|
|
;; Six thematic demos:
|
|
;;
|
|
;; 1. Federation — follow graph, transitive reach, mutuals, FOAF.
|
|
;; 2. Content — posts, tags, likes, popularity, "for you" feed.
|
|
;; 3. Permissions — group membership and resource access.
|
|
;; 4. Cooking-posts — canonical "posts about cooking by people I
|
|
;; follow (transitively)" multi-domain query.
|
|
;; 5. Tag co-occurrence — distinct (T1, T2) pairs with counts.
|
|
;; 6. Shortest path — weighted-DAG path enumeration + min agg.
|
|
|
|
;; ── Demo 1: federation follow graph ─────────────────────────────
|
|
;; EDB: (follows ACTOR-A ACTOR-B) — A follows B.
|
|
;; IDB:
|
|
;; (mutual A B) — A follows B and B follows A
|
|
;; (reachable A B) — transitive follow closure
|
|
;; (foaf A C) — friend of a friend (mutual filter)
|
|
(define
|
|
dl-demo-federation-rules
|
|
(quote
|
|
((mutual A B <- (follows A B) (follows B A))
|
|
(reachable A B <- (follows A B))
|
|
(reachable A C <- (follows A B) (reachable B C))
|
|
(foaf A C <- (follows A B) (follows B C) (!= A C)))))
|
|
|
|
;; ── Demo 2: content recommendation ──────────────────────────────
|
|
;; EDB:
|
|
;; (authored ACTOR POST)
|
|
;; (tagged POST TAG)
|
|
;; (liked ACTOR POST)
|
|
;; IDB:
|
|
;; (post-likes POST N) — count of likes per post
|
|
;; (popular POST) — posts with >= 3 likes
|
|
;; (tagged-by-mutual ACTOR POST) — post tagged TOPIC by someone
|
|
;; A's mutuals follow.
|
|
(define
|
|
dl-demo-content-rules
|
|
(quote
|
|
((post-likes P N <- (authored Author P) (count N L (liked L P)))
|
|
(popular P <- (authored Author P) (post-likes P N) (>= N 3))
|
|
(interesting Me P
|
|
<-
|
|
(follows Me Buddy)
|
|
(authored Buddy P)
|
|
(popular P)))))
|
|
|
|
;; ── Demo 3: role-based permissions ──────────────────────────────
|
|
;; EDB:
|
|
;; (member ACTOR GROUP)
|
|
;; (subgroup CHILD PARENT)
|
|
;; (allowed GROUP RESOURCE)
|
|
;; IDB:
|
|
;; (in-group ACTOR GROUP) — direct or via subgroup chain
|
|
;; (can-access ACTOR RESOURCE) — actor inherits group permission
|
|
(define
|
|
dl-demo-perm-rules
|
|
(quote
|
|
((in-group A G <- (member A G))
|
|
(in-group A G <- (member A H) (subgroup-trans H G))
|
|
(subgroup-trans X Y <- (subgroup X Y))
|
|
(subgroup-trans X Z <- (subgroup X Y) (subgroup-trans Y Z))
|
|
(can-access A R <- (in-group A G) (allowed G R)))))
|
|
|
|
;; ── Demo 4: cooking-posts (the canonical Phase 10 query) ────────
|
|
;; "Posts about cooking by people I follow (transitively)."
|
|
;; Combines federation (follows + transitive reach), authoring,
|
|
;; tagging — the rose-ash multi-domain join.
|
|
;;
|
|
;; EDB:
|
|
;; (follows ACTOR-A ACTOR-B)
|
|
;; (authored ACTOR POST)
|
|
;; (tagged POST TAG)
|
|
(define
|
|
dl-demo-cooking-rules
|
|
(quote
|
|
((reach Me Them <- (follows Me Them))
|
|
(reach Me Them <- (follows Me X) (reach X Them))
|
|
(cooking-post-by-network Me P
|
|
<-
|
|
(reach Me Author)
|
|
(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))))))
|
|
|
|
;; ── Demo 6: weighted-DAG shortest path ─────────────────────────
|
|
;; "What's the cheapest way from X to Y?" Edge weights with `is`
|
|
;; arithmetic to sum costs, then `min` aggregation to pick the
|
|
;; shortest. Termination requires the graph to be a DAG (cycles
|
|
;; would produce infinite distances without a bound; programs
|
|
;; built on this should add a depth filter `(<, D, MAX)` if cycles
|
|
;; are possible).
|
|
;;
|
|
;; EDB:
|
|
;; (edge FROM TO COST)
|
|
;; IDB:
|
|
;; (path FROM TO COST) — any path
|
|
;; (shortest FROM TO COST) — minimum cost path
|
|
(define
|
|
dl-demo-shortest-path-rules
|
|
(quote
|
|
((path X Y W <- (edge X Y W))
|
|
(path X Z W
|
|
<-
|
|
(edge X Y W1)
|
|
(path Y Z W2)
|
|
(is W (+ W1 W2)))
|
|
(shortest X Y W <- (path X Y _) (min W C (path X Y C))))))
|
|
|
|
;; ── Loader stub ──────────────────────────────────────────────────
|
|
;; Wiring to PostgreSQL would replace these helpers with calls into
|
|
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
|
|
;; The shape returned by dl-load-from-edb! is the same in either case.
|
|
(define
|
|
dl-demo-make
|
|
(fn
|
|
(facts rules)
|
|
(dl-program-data facts rules)))
|