【问题标题】:Clojure backward chaining for factsClojure 反向链接事实
【发布时间】:2020-08-28 19:40:58
【问题描述】:

我们正在使用前向链接规则系统,我们必须向系统灌输决策所需的数据。我希望规则系统可以提出问题以获取决策所需的数据。在Jess 中,这似乎可以通过神奇的“need-”前缀实现:

(defrule create-member
    (need-member $?)
    =>
    (assert (member A B))) ; eg. DB call to check membership, if needed for goal finding.

(defrule rule-1
    (member ?A ?B)
    =>
    (printout t member crlf))

使用此解决方案,不需要的事实不会被提取。此外,显着性可用于帮助避免更昂贵的事实查找(例如远程调用),还可以保留代码DRY

虽然 Jess 似乎可以解决这个问题,但首选免许可的 Clojure 解决方案。但是,例如 clojure.logic 如何实现这一点却很模糊。 Clara 使用前向链接,这似乎是不行的,但可能通过规则生成,类似 Jess 的 hack 是可能的?

真的在寻找一个在 Clojure 中做类似的例子。

【问题讨论】:

    标签: clojure clojure-core.logic clara-rule-engine


    【解决方案1】:

    就这样从这里链接,有人在 Ask Clojure 上回答了 Joel 这个问题:Ask Clojure: Can core.logic ask questions?

    答案如下:

    不是一个伟大的 minikanren 或 core.logic 用户,我能够哄 以这种方式解决一个小问题:

    (ns logos.demo
      (:require [clojure.core.logic :as l]
                [clojure.core.logic.pldb :as pldb]))
    
    
    ;; guilty(X) :-
    ;; commits(X,Y),
    ;; crime(Y).
    ;; crime(murder).
    ;; crime(theft)
    
    (pldb/db-rel person x)
    (pldb/db-rel crime x)
    (pldb/db-rel commits x y)
    
    (def facts
      (pldb/db-facts pldb/empty-db
                     [person "bill"]
                     [crime :murder]
                     [crime :theft]
                     [commits "bill" :theft]))
    
    (defn ask! [person act]
      (println  (str "Does " person " commit " act "?"))
      (-> (read-line)
          clojure.string/trim
          clojure.string/lower-case
          #{"y" "yes"}
          some? ))
    
    (defn commitso
      [p act]
      (l/conda
       [(person p) (commits p act)]
       [(l/project [p act]
                 (l/==  (ask! p act) true))]))
    
    (defn crimes [name]
      (->> (l/run-db* facts [p c]
                    (l/== p name)
                    (crime c)
                    (commitso p c))
           (map second)))
    

    如果你在 repl 上评估它,你应该得到一个交互式提示 如果名称与已知人无关:

    logos.demo=> (crimes "bill")
    (:theft)
    logos.demo=> (crimes "tom")
    Does tom commit :theft?  
    y
    Does tom commit :murder?
    y
    (:theft :murder)
    logos.demo=> (crimes "tom")
    Does tom commit :theft?
    n
    Does tom commit :murder?
    n
    ()
    

    我相信也有一种方法可以保留以交互方式收集的事实 (也许这个术语是表格),或者理想情况下,更新事实数据库 随着搜索的进行实时。不过我目前不知道。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-29
      • 2020-07-21
      • 2015-08-31
      • 1970-01-01
      • 2023-03-03
      相关资源
      最近更新 更多