Clojure core.logi c: naf c и молотый - PullRequest
2 голосов
/ 04 марта 2020

Я представляю простую базу данных в corejlogi Clojure c.

Есть два предиката: страница (p) и ссылка (p, q).

page (p) представляет существование страниц в вики с именем p

link (p, q) представляет, что страница p содержит ссылку на страницу q.

I сейчас пытаюсь запросить эту базу данных, чтобы найти

  • 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)
      )))

неработающие ссылки работают, как и ожидалось, но сироты дают мне список из: - символов.

Я предполагаю, что это как-то связано с ограничением naf c. Согласно документации:

ЭКСПЕРИМЕНТАЛЬНО: отрицание как ограничение отказа. Все аргументы к цели c должны быть обоснованы. Если какой-либо аргумент не является основанием, выполнение этого ограничения будет отложено.

И они «задерживаются», потому что они не являются «основанием».

Может кто-нибудь объяснить, какое обоснование действительно значит здесь. Я знаю, что у него «нет свободных переменных», но я все еще не совсем понимаю, что это значит в этом контексте.

Во-вторых, как мне написать этот запрос сирот?

1 Ответ

1 голос
/ 04 марта 2020

В контексте nafc входы без заземления обрабатываются путем предоставления выходов без заземления, поэтому для получения значимых ответов ваши входы "должны быть заземлены". Он не может отменить ограничение, включающее неосновные значения.

Например, эта программа выдает все возможные значения 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. Программа logi c не может дать нам базовые значения, потому что она не знает всех возможных непустых списков.

Вот пример настройки БД для полноты:

(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 logi c: если есть ссылка на страницу q we fail else we succeed.

Также обратите внимание на использование fresh, чтобы ввести переменную logi c p, которая не является частью желаемого вывода ответа, так как мы заботимся только о потерянных значениях страницы.

...