मैं पिछले कुछ दिनों से खेल रहा हूं।
मैंने पहली बार प्रत्येक नोड को किनारों पर रेफरी का सेट रखने की कोशिश की, और प्रत्येक किनारे नोड्स को रेफरी का एक सेट रखती है। मैंने उन्हें एक दूसरे के बराबर (dosync... (ref-set...))
ऑपरेशन के प्रकार में सेट किया है। मुझे यह पसंद नहीं आया क्योंकि एक नोड को बदलने के लिए बड़ी संख्या में अपडेट की आवश्यकता होती है, और ग्राफ को प्रिंट करना थोड़ा मुश्किल था। मुझे print-method
मल्टीमीड को ओवरराइड करना था ताकि प्रतिलिपि ओवरफ़्लो ढेर न हो। साथ ही, जब भी मैं किसी मौजूदा नोड में किनारे जोड़ना चाहता था, मुझे पहले ग्राफ से वास्तविक नोड निकालना पड़ा, फिर किनारे के अपडेट के सभी प्रकार और उस तरह की चीज करें ताकि यह सुनिश्चित किया जा सके कि हर कोई नवीनतम संस्करण पर हो रहा है दूसरी बात का। इसके अलावा, क्योंकि चीजें एक रेफरी में थीं, यह निर्धारित करना कि क्या कुछ और से जुड़ा हुआ था, एक रैखिक-समय ऑपरेशन था, जो कि सुरुचिपूर्ण लग रहा था।मुझे यह निर्धारित करने से पहले बहुत दूर नहीं मिला कि वास्तव में इस विधि के साथ कोई उपयोगी एल्गोरिदम प्रदर्शन करना मुश्किल होगा।
फिर मैंने एक और दृष्टिकोण की कोशिश की जो कहीं और संदर्भित मैट्रिक्स का एक भिन्नता है। ग्राफ एक क्लोजर नक्शा है, जहां कुंजी नोड्स (नोड्स से refs नहीं) हैं, और मान एक और नक्शा हैं जिसमें कुंजी पड़ोसी नोड्स हैं और प्रत्येक कुंजी का एकल मान उस नोड के किनारे है, या तो एक संख्यात्मक मूल्य किनारे की ताकत, या किनारे की संरचना को इंगित करता है जिसे मैंने कहीं और परिभाषित किया है।
यह इस तरह दिखता है, एक तरह से, 1->2, 1->3, 2->5, 5->2
(def graph {node-1 {node-2 edge12, node-3 edge13},
node-2 {node-5 edge25},
node-3 nil ;;no edge leaves from node 3
node-5 {node-2 edge52}) ;; nodes 2 and 5 have an undirected edge
नोड -1 के पड़ोसियों तुम जाओ (keys (graph node-1))
पहुंच सकता है या समारोह कहीं परिभाषित (neighbors graph node-1)
कॉल करने के लिए, या आप ((graph node-1) node-2)
कहना से बढ़त पाने के लिए कर सकते हैं 1->2
।
कई फायदे:
- ग्राफ में और एक पड़ोसी नोड के एक नोड की लगातार समय देखने, या नहीं के बराबर है, तो यह मौजूद नहीं है लौटने।
- सरल और लचीली किनार परिभाषा। जब आप मानचित्र में नोड एंट्री में पड़ोसी जोड़ते हैं, तो इसका निर्देशित किनारा निश्चित रूप से मौजूद होता है, और इसका मूल्य (या अधिक जानकारी के लिए संरचना) स्पष्ट रूप से प्रदान किया जाता है, या शून्य।
- आपको इसे करने के लिए मौजूदा नोड को देखने की ज़रूरत नहीं है। यह अपरिवर्तनीय है, इसलिए आप इसे ग्राफ में जोड़ने से पहले इसे परिभाषित कर सकते हैं और फिर चीजों को बदलने पर आपको नवीनतम संस्करण प्राप्त करने के लिए इसका पीछा नहीं करना पड़ता है। यदि ग्राफ़ में कोई कनेक्शन बदलता है, तो आप ग्राफ संरचना को बदलते हैं, न कि नोड/किनारों को स्वयं।
- यह मैट्रिक्स प्रतिनिधित्व की सर्वोत्तम विशेषताओं को जोड़ता है (ग्राफ़ टोपोलॉजी ग्राफ़ मैप में नोड्स और किनारों, निरंतर समय लुकअप, और गैर-उत्परिवर्तनीय नोड्स और किनारों में एन्कोड नहीं किया गया है), और आसन्नता-सूची (प्रत्येक नोड "पड़ोसी" की पड़ोसी नोड्स की एक सूची है, अंतरिक्ष कुशल है क्योंकि आपके पास कैनोलिक स्पैस मैट्रिक्स की तरह कोई "रिक्त स्थान" नहीं है)।
- आप नोड्स के बीच गुणक किनारों को प्राप्त कर सकते हैं, और यदि आप गलती से एक किनारे को परिभाषित करते हैं जो पहले से मौजूद है, तो नक्शा संरचना यह सुनिश्चित करने का ख्याल रखती है कि आप इसे डुप्लिकेट नहीं कर रहे हैं।
- नोड और किनारे की पहचान क्लोजर द्वारा रखी जाती है। मुझे किसी भी प्रकार की इंडेक्सिंग योजना या सामान्य संदर्भ बिंदु के साथ आने की ज़रूरत नहीं है। मानचित्रों की कुंजी और मान हैं जो वे प्रतिनिधित्व करते हैं, न कि कहीं और लुकअप नहीं। आपकी नोड संरचना सभी नाइल्स हो सकती है, और जब तक यह अद्वितीय हो, इसे ग्राफ में प्रदर्शित किया जा सकता है।
एकमात्र बड़ा-आश नुकसान मुझे लगता है कि किसी दिए गए ऑपरेशन (जोड़ने, निकालने, किसी भी एल्गोरिदम) के लिए, आप इसे केवल एक प्रारंभिक नोड पास नहीं कर सकते हैं। आपको पूरे ग्राफ मैप और एक शुरुआती नोड को पास करना होगा, जो शायद पूरी चीज की सादगी के लिए भुगतान करने के लिए एक उचित मूल्य है। एक और मामूली नुकसान (या शायद नहीं) यह है कि एक अप्रत्यक्ष किनारे के लिए आपको प्रत्येक दिशा में किनारे को परिभाषित करना होगा। यह वास्तव में ठीक है क्योंकि कभी-कभी किनारे के प्रत्येक दिशा के लिए एक अलग मूल्य होता है और यह योजना आपको ऐसा करने की अनुमति देती है।
एकमात्र अन्य चीज़ जो मैं यहां देखता हूं वह यह है कि नक्शा में एक महत्वपूर्ण मूल्य जोड़ी के अस्तित्व में किनारे अंतर्निहित है, आप एक हाइपर्रेड (यानी 2 से अधिक नोड्स को जोड़ते हैं) को परिभाषित नहीं कर सकते हैं। मुझे नहीं लगता कि यह एक बड़ा सौदा जरूरी है क्योंकि अधिकांश ग्राफ एल्गोरिदम मैं आया हूं (सभी?) केवल 2 किनारे को जोड़ने वाले किनारे से निपटते हैं।
आपको किस तरह की ग्रॅन्युलरिटी की अपर्याप्तता की आवश्यकता है?यदि आप किसी फ़ंक्शन के भीतर अपने चक्रीय ग्राफ का निर्माण करते हैं तो नोड्स का आवश्यक उत्परिवर्तन "कभी नहीं देखा गया" है, तो आप फ़ंक्शन द्वारा लौटाए गए एक अपरिवर्तनीय चक्रीय ग्राफ प्राप्त करते हैं। Http://clojure.org/transients –
@Alex देखें: यह वास्तव में एक दिलचस्प दृष्टिकोण की तरह लगता है। यदि आवश्यक हो तो निर्माण के दौरान ग्राफ को उत्परिवर्तनीय होने के साथ मैं ठीक हूं। मैं मुख्य रूप से यह सुनिश्चित करना चाहता हूं कि निर्माण के बाद यह अपरिवर्तनीय है, इसलिए मैं बिना किसी चिंता के कॉलर्स को सौंप सकता हूं। हालांकि, मैं 'क्षणिक' के साथ चक्रीय डेटा संरचना को कैसे विकसित करना है, यह समझने में सक्षम नहीं हूं। क्या आपके पास कोई उदाहरण कोड है जो इस विचार को दिखाता है, यहां तक कि एक तत्व के रूप में स्वयं के साथ एक वेक्टर के रूप में सरल कुछ भी? –