Я моделирую семейное дерево с core.logic. Я хотел бы run*
запросить и вернуть все результаты без дублирования. Замена всего defn
на def tabled
дает мне результаты, которые я ожидаю (на данный момент, по крайней мере), и я знаю, что condu
и onceo
могут уменьшить количество результатов, но я не уверен, что любой из этих являются лучшим способом устранения дубликатов.
Меня особенно беспокоит мой нынешний подход, потому что это похоже на дублирующую работу, чтобы объявить как отношения, так и функции. Я знаю, что некоторые из моих отношений "взаимно рекурсивные" (mothero
и womano
ссылаются друг на друга), но я сделал это, потому что в будущем я мог бы добавить новый (defrel mother*)
, который должен позволить ему сделать вывод о том, что мать является родителем и женщиной.
(defrel man* person)
(defrel woman* person)
(defrel parent* child father)
(fact man* :Father)
(fact woman* :Mother)
(fact man* :Son)
(fact woman* :Daughter)
(fact parent* :Son :Father)
(fact parent* :Son :Mother)
(fact parent* :Daughter :Father)
(fact parent* :Daughter :Mother)
(defn mano [person]
(conde
[(man* person)]
[(fresh [c]
(fathero c person))]))
(defn womano [person]
(conde
[(woman* person)]
[(fresh [c]
(mothero c person))]))
(defn parento [child person]
(conde
[(parent* child person)]
[(mothero child person)]
[(fathero child person)]))
(defn fathero [child father]
(all
(mano father)
(parento child father)))
(defn mothero [child mother]
(all
(womano mother)
(parento child mother)))
(defn siblingso [c1 c2 mother father]
(all
(mothero c1 mother)
(mothero c2 mother)
(fathero c1 father)
(fathero c2 father)
(!= c1 c2)))
(run 10 [q]
(fresh [child parent]
(parento child parent)
(== q [child parent])))
(run 10 [q]
(fresh [c1 c2 p1 p2]
(siblingso c1 c2 p1 p2)
(== q [c1 c2 p1 p2])))