#clojure #clojure-core.logic #clara-rule-engine
#clojure #clojure-core.logic #clara-механизм правил
Вопрос:
Мы используем систему правил с прямой цепочкой, в которой мы должны кормить систему данными, необходимыми для принятия решения. Я бы предпочел, чтобы система правил могла задавать вопросы, чтобы получить данные, необходимые для принятия решений. В 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))
С помощью этого решения ненужные факты не извлекаются. Кроме того, значимость может быть использована, чтобы помочь избежать более дорогостоящего поиска фактов (например, удаленных вызовов), а также сохранить код СУХИМ
Хотя Jess, похоже, решает эту проблему, предпочтительнее решение Clojure без лицензии. Однако неясно, как это осуществить, например, с помощью clojure.logic. Клара использует прямую цепочку, которая кажется бесполезной, но, возможно, с генерацией правил возможен взлом, подобный Jess?
Действительно ищу пример выполнения аналогичного в Clojure.
Ответ №1:
Просто чтобы это было связано отсюда, кто-то ответил Джоэлу на этот самый вопрос в Ask Clojure: Спросите Clojure: Может ли core.logic задавать вопросы?
Ответ заключается в следующем:
Не будучи отличным пользователем 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
()
Я уверен, что есть способ сохранить факты, собранные в интерактивном режиме
(возможно, термин — таблица) или, в идеале, для обновления базы данных фактов
в режиме реального времени по мере продвижения поиска. Однако в настоящее время я не знаю.