Clojure core.logic:nafc和ground
我在Clojure的core.logic中表示一个简单的数据库 有两个谓词:page(p)和link(p,q) 页面(p)表示在称为p的wiki中存在页面 link(p,q)表示p页包含到q页的链接 我现在正试图查询此数据库以查找Clojure core.logic:nafc和ground,clojure,logic-programming,minikanren,negation-as-failure,Clojure,Logic Programming,Minikanren,Negation As Failure,我在Clojure的core.logic中表示一个简单的数据库 有两个谓词:page(p)和link(p,q) 页面(p)表示在称为p的wiki中存在页面 link(p,q)表示p页包含到q页的链接 我现在正试图查询此数据库以查找 a) 断开的链接(即p页中的链接,没有q页),以及 b) 孤立页面(没有链接的页面) 我的查询代码如下: (defn broken-links [] (pldb/with-db @facts (logic/run* [p q] (link
- 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必须落地。如果某个论据不成立,执行就会失败
此约束的执行将被延迟
这些都是“延迟”的,因为它们不是“地面”
有人能解释一下地面在这里的真正含义吗。我知道它是“没有自由变量”,但我仍然不太明白这在上下文中意味着什么
其次,我应该如何编写这个孤儿查询?在nafc的上下文中,非接地输入通过提供非接地输出来处理,因此要获得有意义的答案,您的输入“必须接地”。它不能否定涉及非接地值的约束 例如,该程序给出了
q
的所有可能值,其中q
满足emptyo
:
(run* [q]
(emptyo q))
;=> (())
如果我们要求所有不满足emptyo
的q
的可能值,我们得到以下结果:
(run* [q]
(nafc emptyo q))
;=> ((_0 :- (clojure.core.logic/nafc #object[clojure.core.logic$emptyo 0x212442c1 "clojure.core.logic$emptyo@212442c1"] _0)))
简化的短语是(((u0:-(nafc emptyo\u0))
,这意味着只有一个答案,但可以是满足RHS约束的任何值。逻辑程序不能给我们基础值,因为它不知道所有可能的非空列表
下面是一个完整的DB设置示例:
(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逻辑:如果有指向页面q
wefail
else的链接,我们成功
还要注意使用
fresh
引入逻辑变量p
,该变量不是所需答案输出的一部分,因为我们只关心孤立的页面值。OK。如果我理解正确的话,在我的孤儿中,问题是p可以是无穷多个事物中的任意一个。“什么都不是”需要你在测试“什么都不是”之前实例化(即使是懒散地)它?@interstar是的,我认为你的直觉是正确的,但我很难用正确的术语来描述其中的一些概念。强烈推荐通过!