I'm modeling a family tree with core.logic. I would like to run*
the queries and have them return all the results without duplication. Replacing all defn
with def tabled
gives me the results I expect (for now at least), and I know that condu
and onceo
can reduce the number of results, but I'm not sure if either of those are the best way to eliminate duplicates.
I'm particularly worried about my current approach because it seems like duplicate work to declare both the relations and the functions. I know that some of my relations are 'mutually recursive' (mothero
and womano
reference each other), but I did this because in the future I might add a new (defrel mother*)
, which should allow it to infer that a mother is both a parent and a woman.
(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])))