2012-03-15 8 views
11

के साथ पारिवारिक पेड़ से पूछताछ करते समय डुप्लिकेट परिणामों को खत्म करना मैं core.logic के साथ एक पारिवारिक पेड़ का मॉडल कर रहा हूं। मैं run* प्रश्नों को देखना चाहूंगा और उन्हें डुप्लिकेशंस के बिना सभी परिणाम वापस कर दूंगा। को 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]))) 

उत्तर

5

सुनिश्चित नहीं हैं कि वास्तव में क्या हासिल करने की कोशिश कर रहे हैं, लेकिन लक्ष्य ('o' में समाप्त होने वाले सामान) लगता है (जैसा कि आप ने कहा) निरर्थक और वे कर रहे हैं। इसके अलावा, run* के साथ चलाने के लिए आपको parento नहीं मिल सकता है क्योंकि आपके प्रश्नों पर कोई बाधा नहीं है। यह बाल-अभिभावक जोड़े की अनंत सूची वापस करने का प्रयास करेगा। यहाँ अपने संबंधों का उपयोग कर कुछ उदाहरण प्रश्नों हैं:

;; find all child-parent pairs 
(run* [q] (fresh [c p] (parent* c p) (== q [c p]))) 
;=> ([:Daughter :Mother] [:Son :Mother] [:Daughter :Father] [:Son :Father]) 

;; find all child-father pairs 
(run* [q] (fresh [c p] (parent* c p) (man* p) (== q [c p]))) 
;=> ([:Daughter :Father] [:Son :Father]) 

;; find all daughter-father pairs 
(run* [q] (fresh [c p] (parent* c p) (man* p) (woman* c) (== q [c p]))) 
;=> ([:Daughter :Father]) 

;; some new facts 
(fact parent* :grand-child :Son) 
(fact parent* :great-grand-child :grand-child) 

;; find all people who are grandparent 
(run* [q] (fresh [c p gp] (parent* c p) (parent* p gp) (== q [gp]))) 
;=> ([:Mother] [:Father] [:Son]) 

और तुम थोड़ी देर के लिए उस तरह पर जा सकते हैं। लॉजिक प्रोग्रामिंग केवल अपने आप पर एक बहुत ही शक्तिशाली क्वेरी भाषा बनाता है जब भी केवल सरल संबंधों के साथ उपयोग किया जाता है।

अद्यतन: यहाँ brothero का एक उदाहरण है, जहां दूसरा तर्क भाई होना चाहिए:

(defn brothero [a b] 
    (fresh [f] 
    (!= a b) 
    (parent* a f) 
    (parent* b f) 
    (man* f) 
    (man* b)))) 

(run* [q] (fresh [a b] (brothero a b) (== q [a b]))) 
;=> ([:Daughter :Son]) 

जैसा कि आप देख मैं के रूप में यह अनावश्यक है एक parento लक्ष्य को परिभाषित करने के लिए परेशान नहीं है। आपको ध्यान रखना चाहिए कि (!= a b) को दो बार एक ही व्यक्ति वाले जोड़े नहीं मिलना चाहिए और उत्तर को दोगुना रोकने के लिए माता-पिता पर बाधा है। जाहिर है कि यह उदाहरण काम नहीं करेगा यदि आपके पिता को रिकॉर्ड नहीं किया गया है या ऐसे व्यक्ति के लिए जिसमें कई महिलाओं के बच्चे हैं।

+0

कारण मैंने पैरेंटो, पिताो, सिब्लिंगो इत्यादि को परिभाषित किया है, इसलिए मैं बड़े संबंधों को परिभाषित करने के लिए उन्हें ब्लॉक बनाने के रूप में उपयोग करना चाहता हूं। Cousinso की तरह siblingso और parento का उपयोग परिभाषित करना आसान होगा। इसे सिर्फ माता-पिता * पर सीमित करने के बजाय। मैं किसी भी प्रकार के रिश्ते, भाइयों, चाचा, दूसरे चचेरे भाई, पूर्वजों, वंशजों, संबंधित इत्यादि के लिए निर्माण कार्यों को समाप्त करना चाहता हूं। मुझे नहीं पता कि इन्हें कैसे परिभाषित किया जाए ताकि वे नए संबंधों को स्वीकार कर सकें। बहन * रन * के साथ दौड़ते समय भी समाप्त हो रही है। – WuHoUnited

+0

मैंने 'भाई' के उदाहरण (सरलीकृत संस्करण) का एक उदाहरण शामिल करने के लिए अपना उत्तर अपडेट किया है, उम्मीद है कि इससे आपको अपने लक्ष्यों को प्राप्त करने में मदद मिलेगी! ;-) –

+0

मैंने पिछले उदाहरण में एक और छोटा बदलाव किया है, क्योंकि इस मामले में 'defne' का उपयोग करने की आवश्यकता नहीं थी। –

0

आप पुनरावर्ती संबंध का उपयोग करना चाहते हैं, तो आप * यूनिफाई होता है-जाँच

इस विस्तार की तरह इस विस्तार https://github.com/niitsuma/Racket-miniKanren/tree/recursive

शायद पुनर्लेखन

की पैदल दूरी की पैदल दूरी पर उपयोग कर सकते हैं, भी पुनरावर्ती संबंध में सक्षम बनाता है क्लोजर