2

我在 Clojure 的 core.logic 中表示一个简单的数据库。

有两个谓词:page(p) 和 link(p,q)。

page(p) 表示在名为 p 的 wiki 中存在页面

link(p,q) 表示页面 p 包含到页面 q 的链接。

我现在正在尝试查询此数据库以查找

  • a) 断开的链接(即页面 ​​p 中的链接,没有页面 q),以及
  • b) 孤立页面(没有链接的页面)

我的这些查询代码是这样的:

(defn broken-links []
  (pldb/with-db @facts
    (logic/run* [p q]
      (link p q)
      (logic/nafc page q)
      )))

(defn orphans []
  (pldb/with-db @facts
    (logic/run* [p q]
      (logic/nafc link p q)
      (page q)
      )))

断开的链接按预期工作,但孤儿给了我一个 :- 符号列表。

我假设这与 nafc 的限制有关。根据文档:

实验:否定作为失败约束。目标 c 的所有论据都必须有依据。如果某些论点不成立,则此约束的执行将被延迟。

这些是“延迟的”,因为它们不是“地面”。

有人可以解释一下 ground 的真正含义吗?我知道它“没有自由变量”,但我仍然不明白在这种情况下这意味着什么。

其次,我应该如何编写这个孤儿查询?

4

1 回答 1

1

在 的上下文中nafc,非接地输入是通过提供非接地输出来处理的,因此要获得有意义的答案,您的输入“必须接地”。它不能否定涉及非地面值的约束。

例如,这个程序给出了qwhereq满足的所有可能值emptyo

(run* [q]
  (emptyo q))
;=> (())

如果我们要求所有q不满足的可能值,emptyo我们会得到:

(run* [q]
  (nafc emptyo q))
;=> ((_0 :- (clojure.core.logic/nafc #object[clojure.core.logic$emptyo 0x212442c1 "clojure.core.logic$emptyo@212442c1"] _0)))

一个简化的措辞是((_0 :- (nafc emptyo _0))),这意味着只有一个答案,但它可以是任何满足 RHS 约束的值。逻辑程序不能给我们基本值,因为它不知道所有可能的非空列表。

这是一个完整的示例数据库设置:

(pldb/db-rel page q)
(pldb/db-rel link p q)
(def facts
  (pldb/db
    [page 'a]
    [page 'b]
    [page 'z]
    [link 'a 'b]
    [link 'b 'c]))

还有你工作的断链程序:

;; find links to non-pages
(pldb/with-db facts
  (run* [p q]
    (link p q)
    (nafc page q)))
;=> ([b c])

这是编写孤立页面程序的一种方法:

;; find pages without incoming links
(pldb/with-db facts
  (run* [q]
    (fresh [p]
      (page q)
      (conda
        [(link p q) fail]
        [succeed]))))
;=> (a z)

这里的否定用 表示,conda形成一种if-else逻辑:如果有指向页面的链接qwe fail else we succeed

还要注意使用fresh来引入p不属于所需答案输出的逻辑变量,因为我们只关心孤立的页面值。

于 2020-03-04T13:46:27.540 回答