Clojure core.logic:nafc 和地面
Clojure core.logic : nafc and ground
我在 Clojure 中表示一个简单的数据库 core.logic。
有两个谓词:page(p) 和 link(p,q)。
page(p) 表示在名为 p
的 wiki 中存在的页面
link(p,q)表示p页包含一个link到q页
我现在正在尝试查询此数据库以查找
- a) 损坏的 links(即第 p 页中的 links,没有第 q 页),以及
- b) 孤立页面(没有 link 的页面)
我的这些查询代码是这样的:
(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)
)))
broken-links 按预期工作,但孤儿给了我一个列表:- 符号。
我假设这与 nafc 的限制有关。根据文档:
EXPERIMENTAL: negation as failure constraint. All arguments to the
goal c must be ground. If some argument is not ground the execution
of this constraint will be delayed.
而这些是 "delayed" 因为它们不是 "ground"。
谁能解释一下地面在这里的真正含义。我知道它是 "has no free variables",但我仍然不太明白在这种情况下这意味着什么。
其次,这个孤儿查询应该怎么写?
在 nafc
的上下文中,非地面输入通过提供非地面输出来处理,因此要获得有意义的答案,您的输入 "must be ground." 它不能否定涉及非地面值的约束.
例如,这个程序给出了q
所有可能的值,其中q
满足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]))
你的工作坏了-link程序:
;; 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逻辑:if有一个link 到第 q
页,我们 fail
else 我们 succeed
.
还要注意使用 fresh
引入逻辑变量 p
,它不是所需答案输出的一部分,因为我们只关心孤立的页面值。
我在 Clojure 中表示一个简单的数据库 core.logic。
有两个谓词:page(p) 和 link(p,q)。
page(p) 表示在名为 p
的 wiki 中存在的页面link(p,q)表示p页包含一个link到q页
我现在正在尝试查询此数据库以查找
- a) 损坏的 links(即第 p 页中的 links,没有第 q 页),以及
- b) 孤立页面(没有 link 的页面)
我的这些查询代码是这样的:
(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)
)))
broken-links 按预期工作,但孤儿给了我一个列表:- 符号。
我假设这与 nafc 的限制有关。根据文档:
EXPERIMENTAL: negation as failure constraint. All arguments to the goal c must be ground. If some argument is not ground the execution of this constraint will be delayed.
而这些是 "delayed" 因为它们不是 "ground"。
谁能解释一下地面在这里的真正含义。我知道它是 "has no free variables",但我仍然不太明白在这种情况下这意味着什么。
其次,这个孤儿查询应该怎么写?
在 nafc
的上下文中,非地面输入通过提供非地面输出来处理,因此要获得有意义的答案,您的输入 "must be ground." 它不能否定涉及非地面值的约束.
例如,这个程序给出了q
所有可能的值,其中q
满足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]))
你的工作坏了-link程序:
;; 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逻辑:if有一个link 到第 q
页,我们 fail
else 我们 succeed
.
还要注意使用 fresh
引入逻辑变量 p
,它不是所需答案输出的一部分,因为我们只关心孤立的页面值。