मैं एक मौलिक स्तर पर समझना चाहूंगा कि ए * पाथफाइंडिंग किस तरह से काम करता है। कोई भी कोड या पेसो-कोड कार्यान्वयन और साथ ही विज़ुअलाइज़ेशन सहायक होंगे।
मैं एक मौलिक स्तर पर समझना चाहूंगा कि ए * पाथफाइंडिंग किस तरह से काम करता है। कोई भी कोड या पेसो-कोड कार्यान्वयन और साथ ही विज़ुअलाइज़ेशन सहायक होंगे।
जवाबों:
ऑनलाइन पाए जाने वाले A * के कोड-उदाहरण और स्पष्टीकरण के टन हैं। इस सवाल को बहुत सारे उपयोगी लिंक के साथ बहुत सारे शानदार उत्तर भी मिले हैं। अपने जवाब में, मैं एल्गोरिथ्म का एक सचित्र उदाहरण प्रदान करने की कोशिश करूँगा, जिसे कोड या विवरणों की तुलना में समझना आसान हो सकता है।
ए * को समझने के लिए, मेरा सुझाव है कि आप पहले दिक्जस्ट्रा के एल्गोरिथ्म पर एक नज़र डालें । मुझे दीजकस्ट्रा के एल्गोरिदम एक खोज के लिए प्रदर्शन करेगा चरणों के माध्यम से मार्गदर्शन करते हैं।
हमारा स्टार्ट-नोड है A
और हम सबसे छोटा रास्ता खोजना चाहते हैं F
। ग्राफ़ के प्रत्येक किनारे पर एक आंदोलन लागत जुड़ा होता है (जिसे किनारों के बगल में काले अंकों के रूप में चिह्नित किया जाता है)। हमारा लक्ष्य ग्राफ के प्रत्येक शीर्ष (या नोड) के लिए न्यूनतम यात्रा लागत का मूल्यांकन करना है जब तक कि हम अपने लक्ष्य नोड से नहीं टकराते।
यह हमारा शुरुआती बिंदु है। हमारे पास जाँच करने के लिए एक सूची नोड है, वर्तमान में यह सूची है:
{ A(0) }
A
की लागत है 0
, अन्य सभी नोड्स अनन्तता के लिए सेट हैं (एक विशिष्ट कार्यान्वयन में, यह कुछ इस तरह int.MAX_VALUE
या समान होगा)।
हम नोड्स की हमारी सूची से सबसे कम लागत के साथ नोड लेते हैं (चूंकि हमारी सूची में केवल A
यही है, यह हमारा उम्मीदवार है) और इसके सभी पड़ोसियों का दौरा करें। हम प्रत्येक पड़ोसी की लागत निर्धारित करते हैं :
Cost_of_Edge + Cost_of_previous_Node
और पिछले नोड का ध्यान रखें (नोड के नीचे छोटे गुलाबी अक्षर के रूप में दिखाया गया है)। A
अब (लाल) हल के रूप में चिह्नित किया जा सकता है, ताकि हम इसे फिर से यात्रा न करें। अब हमारे उम्मीदवारों की सूची इस तरह दिखती है:
{ B(2), D(3), C(4) }
फिर, हम अपनी सूची से सबसे कम लागत के साथ नोड लेते हैं ( B
) और इसके पड़ोसियों का मूल्यांकन करते हैं। पथ के लिए D
की वर्तमान लागत से ज्यादा महंगा है D
, इसलिए इस मार्ग खारिज किया जा सकता है। E
हमारे उम्मीदवारों की सूची में जोड़ा जाएगा, जो अब इस तरह दिखता है:
{ D(3), C(4), E(4) }
अब जांच करने वाला अगला नोड है D
। कनेक्शन को C
छोड़ दिया जा सकता है, क्योंकि मौजूदा लागत से रास्ता छोटा नहीं है । हमें E
हालांकि एक छोटा रास्ता मिल गया था , इसलिए E
इसके पिछले नोड की लागत और अद्यतन की जाएगी। हमारी सूची अब इस तरह दिखती है:
{ E(3), C(4) }
तो जैसा कि हमने पहले किया था, हम अपनी सूची से सबसे कम लागत के साथ नोड की जांच करते हैं, जो अब है E
। E
केवल एक अनसुलझा पड़ोसी है, जो लक्ष्य नोड भी है। लक्ष्य नोड तक पहुंचने की लागत 10
और इसके पिछले नोड के लिए निर्धारित है E
। अब हमारे उम्मीदवारों की सूची इस तरह दिखती है:
{ C(4), F(10) }
आगे हम जांच करते हैं C
। हम लागत और पिछले नोड को अपडेट कर सकते हैं F
। चूंकि हमारी सूची में अब F
सबसे कम लागत के साथ नोड है, हम कर रहे हैं। हमारे पथ का निर्माण पिछले सबसे छोटे नोड्स को पीछे करके किया जा सकता है।
तो आपको आश्चर्य हो सकता है कि मैंने ए * एल्गोरिथ्म के बजाय दिज्क्स्ट्रा को क्यों समझाया ? ठीक है, केवल अंतर यह है कि आप अपने उम्मीदवारों को कैसे (या क्रमबद्ध) तौलते हैं। दिज्कस्त्र के साथ यह है:
Cost_of_Edge + Cost_of_previous_Node
A * के साथ:
Cost_of_Edge + Cost_of_previous_Node + Estimated_Cost_to_reach_Target_from(Node)
जहां Estimated_Cost_to_reach_Target_from
आमतौर पर एक Heuristic फ़ंक्शन कहा जाता है । यह एक फ़ंक्शन है जो लक्ष्य-नोड तक पहुंचने के लिए लागत का अनुमान लगाने की कोशिश करेगा। एक अच्छा हेयुरिस्टिक फ़ंक्शन प्राप्त करेगा कि लक्ष्य को खोजने के लिए कम नोड्स का दौरा करना होगा। जबकि दिज्क्स्ट्रा का एल्गोरिदम सभी पक्षों तक विस्तृत होगा, लक्ष्य की दिशा में A * वसीयत (उत्तराधिकारी के लिए धन्यवाद) खोज।
हेयूरिस्टिक्स के बारे में अमित के पेज में आम ह्यूरिस्टिक्स पर अच्छा अवलोकन है।
ए * पाथ फाइंडिंग एक सर्वश्रेष्ठ-प्रथम प्रकार की खोज है जो एक अतिरिक्त हेयुरिस्टिक का उपयोग करती है।
पहली चीज जो आपको करने की ज़रूरत है वह है आपके खोज क्षेत्र को विभाजित करना। इस स्पष्टीकरण के लिए मानचित्र टाइलों का एक वर्ग ग्रिड है, क्योंकि अधिकांश 2D गेम टाइलों के ग्रिड का उपयोग करते हैं और क्योंकि यह कल्पना करना सरल है। ध्यान दें कि खोज क्षेत्र को आप चाहते हैं कि किसी भी तरह से तोड़ा जा सकता है: हेक्स ग्रिड शायद, या यहां तक कि मनमाने आकार जैसे जोखिम। विभिन्न मानचित्र पदों को "नोड्स" के रूप में संदर्भित किया जाता है और यह एल्गोरिदम किसी भी समय काम करेगा जब आपके पास ट्रैवस करने के लिए नोड्स का एक गुच्छा होगा और नोड्स के बीच कनेक्शन परिभाषित होगा।
वैसे भी, किसी दी हुई शुरुआती टाइल पर शुरू करना:
शुरुआती टाइल के चारों ओर 8 टाइलें "रन" पर आधारित हैं) वर्तमान टाइल से अगली टाइल तक जाने की लागत (आमतौर पर क्षैतिज या ऊर्ध्वाधर आंदोलनों के लिए 1, विकर्ण आंदोलन के लिए sqrt (2))।
प्रत्येक टाइल को तब एक अतिरिक्त "हेयुरिस्टिक" स्कोर सौंपा जाता है - प्रत्येक टाइल पर जाने के सापेक्ष मूल्य का एक अनुमान। अलग-अलग heuristics का उपयोग किया जाता है, दिए गए टाइल और अंत टाइल के केंद्रों के बीच सीधी रेखा की दूरी सबसे सरल है।
वर्तमान टाइल तब "बंद" है, और एजेंट पड़ोसी टाइल पर जाता है जो खुला है, सबसे कम आंदोलन स्कोर है, और सबसे कम अंक स्कोर है।
यह प्रक्रिया तब तक दोहराई जाती है जब तक कि लक्ष्य नोड तक नहीं पहुंच जाता है, या अधिक खुले नोड्स नहीं होते हैं (जिसका अर्थ है कि एजेंट अवरुद्ध है)।
इन चरणों को दर्शाने वाले आरेखों के लिए, इस अच्छे शुरुआती ट्यूटोरियल का संदर्भ लें ।
कुछ सुधार किए जा सकते हैं, जो मुख्य रूप से सुधारवादी में सुधार कर सकते हैं:
भू-अंतर, खुरदरापन, खुरदरापन आदि को ध्यान में रखते हुए।
उदाहरण के लिए, एजेंट का सामना करना पड़ने वाला यू आकार: मानचित्र के क्षेत्रों को ब्लॉक करने के लिए ग्रिड के पार "स्वीप" करना भी कभी-कभी उपयोगी होता है। स्वीप टेस्ट के बिना, एजेंट पहले यू में प्रवेश करेगा, चारों ओर घूमेगा, फिर छोड़ देगा और यू के किनारे के चारों ओर चला जाएगा। "वास्तविक" बुद्धिमान एजेंट यू आकार के जाल को नोट करेगा और बस इससे बचें। स्वीपिंग इसे अनुकरण करने में मदद कर सकता है।
यह सबसे अच्छा से दूर है, लेकिन यह एक कार्यान्वयन मैंने कुछ साल पहले सी ++ में ए * का किया था।
यह शायद बेहतर है कि मैं आपको संपूर्ण एल्गोरिथ्म को समझाने के प्रयास से संसाधनों की ओर इशारा करता हूं। इसके अलावा, जैसा कि आप विकी लेख के माध्यम से पढ़ते हैं, डेमो के साथ खेलते हैं और देखें कि क्या आप कल्पना कर सकते हैं कि यह कैसे काम कर रहा है। यदि आपके पास कोई विशिष्ट प्रश्न है तो टिप्पणी छोड़ दें।
आपको पाथ फाइंडिंग पर ActiveTut का लेख उपयोगी लग सकता है। यह A * और Dijkstra के एल्गोरिथ्म और उनके बीच के अंतर दोनों पर जाता है। यह फ़्लैश डेवलपर्स की ओर सक्षम है, लेकिन यह सिद्धांत पर कुछ अच्छी जानकारी प्रदान करना चाहिए भले ही आप फ्लैश का उपयोग न करें।
ए * और डीजकस्ट्रा के एल्गोरिथ्म के साथ काम करते समय कल्पना करना महत्वपूर्ण है कि ए * निर्देशित है; यह किसी विशेष बिंदु पर "अनुमान लगाने" के लिए सबसे छोटा रास्ता खोजने की कोशिश करता है कि किस दिशा को देखना है। दिज्क्स्ट्रा के एल्गोरिथ्म में / हर / बिंदु पर सबसे छोटा रास्ता मिलता है।
तो बस एक पहले बयान के रूप में, ए * दिल में एक ग्राफ अन्वेषण एल्गोरिथ्म है। आमतौर पर खेल में हम ग्राफ़ के रूप में टाइल या अन्य विश्व ज्यामिति का उपयोग करते हैं, लेकिन आप अन्य चीजों के लिए A * का उपयोग कर सकते हैं। ग्राफ ट्रैवर्सल के लिए दो उर-एल्गोरिदम गहराई-पहले-खोज और चौड़ाई-पहली-खोज हैं। DFS में आप हमेशा वर्तमान नोड के भाई-बहनों को देखने से पहले अपनी वर्तमान शाखा का पूरी तरह से पता लगा लेते हैं, और BFS में आप हमेशा पहले भाई-बहनों और फिर बच्चों को देखते हैं। ए * इन दोनों के बीच एक मध्य-भूमि को खोजने की कोशिश करता है जहां आप एक शाखा (जैसे डीएफएस की तरह) का पता लगाते हैं, जब आप इच्छित लक्ष्य के करीब पहुंच रहे हैं लेकिन कभी-कभी रुकें और एक सिबलिंग की कोशिश करें यदि इसके शाखा के बेहतर परिणाम हो सकते हैं। वास्तविक गणित यह है कि आप अगले नोड का पता लगाने के लिए संभावित नोड्स की एक सूची रखते हैं जहां प्रत्येक में "अच्छाई" होती है यह दर्शाता है कि यह लक्ष्य के कितने करीब है (किसी प्रकार के अमूर्त अर्थ में), कम स्कोर बेहतर होना (0 मतलब आपको लक्ष्य मिला)। आप चयन करते हैं कि स्कोर का न्यूनतम और प्लस नोड्स को रूट से दूर (जो कि आमतौर पर वर्तमान कॉन्फ़िगरेशन, या पाथफाइंडिंग में वर्तमान स्थिति) का पता लगाकर अगले का उपयोग करना है। हर बार जब आप एक नोड का पता लगाते हैं तो आप अपने सभी बच्चों को इस सूची में जोड़ते हैं और फिर नया सबसे अच्छा उठाते हैं।
अमूर्त स्तर पर, A * इस तरह काम करता है: