core.logic을 사용하여 패밀리 트리를 모델링했습니다. run*
에 쿼리를 입력하고 의 모든 결과를없이 반환하도록하고 싶습니다. defn
을 def tabled
으로 바꾸면 나는 (적어도 현재는) 기대하는 결과를 얻었으며, condu
과 onceo
은 결과의 수를 줄일 수 있지만 그 중 하나가 중복을 제거하는 가장 좋은 방법인지 잘 모르겠습니다.core.logic을 사용하여 패밀리 트리를 쿼리 할 때 중복 결과 제거
저는 특히 관계와 기능을 선언하는 작업이 중복 된 것처럼 보이기 때문에 현재의 접근 방법에 대해 걱정하고 있습니다. 내 관계 중 일부는 '상호 재귀 적'이라는 것을 알고 있습니다. (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])))
parento, fathero, siblingso 등의 함수를 정의한 이유는 더 큰 관계를 정의하는 빌딩 블록으로 사용하기 위해서입니다. 사촌과 마찬가지로 형제와 부모를 사용하여 정의하는 것이 쉬울 것입니다. 그냥 부모로 제한하는 대신 *. 형제, 삼촌, 두 번째 사촌, 조상, 자손, 관계형 등 모든 유형의 관계 함수를 구축하고 싶습니다. 이러한 관계를 정의하는 방법을 알지 못해서 다음과 같은 새로운 관계를 받아 들일 수 없습니다. 자매 * 또한 run *으로 달릴 때 종료됩니다. – WuHoUnited
'brothero'의 (단순화 된 버전) 예제를 포함하도록 답변을 업데이트했습니다. 목표 달성에 도움이되기를 바랍니다. ;-) –
이 예제에서는'defne'을 사용할 필요가 없으므로 마지막 예제에서 약간의 변경을했습니다. –