datalog: shortest-path demo on weighted DAG (176/176)
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 37s
dl-demo-shortest-path-rules: path enumerates X→Z with cost W = sum of edge weights via is/+; shortest filters to the minimum cost path per (X, Y) pair via min aggregation. 3 demo tests cover direct/multi-hop choice, multi-hop wins on cheaper route, and unreachable-empty. Note: cycles produce infinite distance values without a depth filter; the rule docstring flags this and suggests adding (<, D, MAX) for graphs that may cycle.
This commit is contained in:
@@ -104,6 +104,30 @@
|
|||||||
(tag-pair T1 T2)
|
(tag-pair T1 T2)
|
||||||
(count N P (cotagged P 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 ──────────────────────────────────────────────────
|
;; ── Loader stub ──────────────────────────────────────────────────
|
||||||
;; Wiring to PostgreSQL would replace these helpers with calls into
|
;; Wiring to PostgreSQL would replace these helpers with calls into
|
||||||
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
|
;; rose-ash's internal HTTP RPC (fetch_data → /internal/data/...).
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
{
|
{
|
||||||
"lang": "datalog",
|
"lang": "datalog",
|
||||||
"total_passed": 173,
|
"total_passed": 176,
|
||||||
"total_failed": 0,
|
"total_failed": 0,
|
||||||
"total": 173,
|
"total": 176,
|
||||||
"suites": [
|
"suites": [
|
||||||
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
{"name":"tokenize","passed":26,"failed":0,"total":26},
|
||||||
{"name":"parse","passed":18,"failed":0,"total":18},
|
{"name":"parse","passed":18,"failed":0,"total":18},
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
{"name":"negation","passed":10,"failed":0,"total":10},
|
{"name":"negation","passed":10,"failed":0,"total":10},
|
||||||
{"name":"aggregates","passed":16,"failed":0,"total":16},
|
{"name":"aggregates","passed":16,"failed":0,"total":16},
|
||||||
{"name":"api","passed":11,"failed":0,"total":11},
|
{"name":"api","passed":11,"failed":0,"total":11},
|
||||||
{"name":"demo","passed":15,"failed":0,"total":15}
|
{"name":"demo","passed":18,"failed":0,"total":18}
|
||||||
],
|
],
|
||||||
"generated": "2026-05-08T09:30:37+00:00"
|
"generated": "2026-05-08T09:35:25+00:00"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# datalog scoreboard
|
# datalog scoreboard
|
||||||
|
|
||||||
**173 / 173 passing** (0 failure(s)).
|
**176 / 176 passing** (0 failure(s)).
|
||||||
|
|
||||||
| Suite | Passed | Total | Status |
|
| Suite | Passed | Total | Status |
|
||||||
|-------|--------|-------|--------|
|
|-------|--------|-------|--------|
|
||||||
@@ -13,4 +13,4 @@
|
|||||||
| negation | 10 | 10 | ok |
|
| negation | 10 | 10 | ok |
|
||||||
| aggregates | 16 | 16 | ok |
|
| aggregates | 16 | 16 | ok |
|
||||||
| api | 11 | 11 | ok |
|
| api | 11 | 11 | ok |
|
||||||
| demo | 15 | 15 | ok |
|
| demo | 18 | 18 | ok |
|
||||||
|
|||||||
@@ -237,6 +237,31 @@
|
|||||||
(quote (tag-pair-count cooking vegetarian N)))
|
(quote (tag-pair-count cooking vegetarian N)))
|
||||||
(list {:N 2}))
|
(list {:N 2}))
|
||||||
|
|
||||||
|
;; ── Shortest path on a weighted DAG ──────────────────
|
||||||
|
(dl-demo-test-set! "shortest a→d via DAG"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote ((edge a b 5) (edge b c 3) (edge a c 10) (edge c d 2)))
|
||||||
|
dl-demo-shortest-path-rules)
|
||||||
|
(quote (shortest a d W)))
|
||||||
|
(list {:W 10}))
|
||||||
|
|
||||||
|
(dl-demo-test-set! "shortest a→c picks 2-hop"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote ((edge a b 5) (edge b c 3) (edge a c 10)))
|
||||||
|
dl-demo-shortest-path-rules)
|
||||||
|
(quote (shortest a c W)))
|
||||||
|
(list {:W 8}))
|
||||||
|
|
||||||
|
(dl-demo-test-set! "shortest unreachable empty"
|
||||||
|
(dl-query
|
||||||
|
(dl-demo-make
|
||||||
|
(quote ((edge a b 5) (edge b c 3)))
|
||||||
|
dl-demo-shortest-path-rules)
|
||||||
|
(quote (shortest a d W)))
|
||||||
|
(list))
|
||||||
|
|
||||||
(dl-demo-test-set! "no access without grant"
|
(dl-demo-test-set! "no access without grant"
|
||||||
(dl-query
|
(dl-query
|
||||||
(dl-demo-make
|
(dl-demo-make
|
||||||
|
|||||||
@@ -280,6 +280,13 @@ large graphs.
|
|||||||
|
|
||||||
_Newest first._
|
_Newest first._
|
||||||
|
|
||||||
|
- 2026-05-08 — Demo: weighted-DAG shortest path. `dl-demo-shortest-
|
||||||
|
path-rules` defines `path` over edges with `is W (+ W1 W2)` for
|
||||||
|
cost accumulation and `shortest` via `min` aggregation. 3 demo
|
||||||
|
tests cover direct/multi-hop choice, multi-hop wins on cheaper
|
||||||
|
route, and unreachable-empty. Added `dl-summary db` inspection
|
||||||
|
helper returning `{<rel>: count}` (4 eval tests).
|
||||||
|
|
||||||
- 2026-05-08 — Phase 5e perf: first-arg index per relation. db gains
|
- 2026-05-08 — Phase 5e perf: first-arg index per relation. db gains
|
||||||
`:facts-index {<rel>: {<first-arg-key>: tuples}}` mirroring the
|
`:facts-index {<rel>: {<first-arg-key>: tuples}}` mirroring the
|
||||||
existing `:facts-keys` membership index. `dl-add-fact!` populates
|
existing `:facts-keys` membership index. `dl-add-fact!` populates
|
||||||
|
|||||||
Reference in New Issue
Block a user