एक ग्राफ़ में सबसे छोटा रास्ता खोजें जो कुछ नोड्स का दौरा करता है


84

मेरे पास लगभग 100 नोड्स और लगभग 200 किनारों के साथ एक अप्रत्यक्ष ग्राफ है। एक नोड को 'प्रारंभ', एक को 'अंत', और एक दर्जन लेबल 'मस्टपास' के बारे में बताया गया है।

मुझे इस ग्राफ के माध्यम से सबसे छोटा रास्ता खोजने की जरूरत है जो 'शुरू' से शुरू होता है, 'अंत' पर समाप्त होता है, और सभी 'मस्टपास' नोड्स (किसी भी क्रम में) से गुजरता है।

( http://3e.org/local/maize-graph.png / http://3e.org/local/maize-graph.dot.txt प्रश्न में ग्राफ है - यह लैंकेस्टर, पीए में एक मकई भूलभुलैया का प्रतिनिधित्व करता है)

जवाबों:


78

हर कोई इसकी तुलना ट्रैवलिंग सेल्समैन समस्या से कर रहा है, शायद आपने अपने सवाल को ध्यान से नहीं पढ़ा है। टीएसपी में, उद्देश्य सबसे छोटा चक्र ढूंढना है जो सभी कोने (एक हैमिल्टन चक्र) का दौरा करता है - यह 'मस्टपास' लेबल वाले प्रत्येक नोड से मेल खाता है ।

आपके मामले में, यह देखते हुए कि आपके पास केवल एक दर्जन लेबल 'मस्टपास' हैं, और उसने 12 दिए हैं! बल्कि छोटा (479001600) है, आप बस केवल 'मस्टपास' नोड्स के सभी क्रमांकन की कोशिश कर सकते हैं, और 'स्टार्ट' से 'एंड' तक के सबसे छोटे रास्ते को देख सकते हैं जो उस क्रम में 'मस्टपास' नोड्स पर जाता है - यह बस होगा उस सूची में हर दो लगातार नोड्स के बीच सबसे छोटे रास्तों का संयोजन होना चाहिए।

दूसरे शब्दों में, पहले प्रत्येक जोड़ी के बीच की सबसे छोटी दूरी पाते हैं (आप दिज्क्स्ट्रा के एल्गोरिथ्म या अन्य का उपयोग कर सकते हैं, लेकिन उन छोटी संख्याओं (100 नोड्स) के साथ, यहां तक ​​कि सबसे सरल-टू-कोड फ्लोयड-वारशॉल एल्गोरिथ्म समय में चलेगा)। फिर, एक बार जब आपके पास यह तालिका होती है, तो अपने 'मस्टपास' नोड्स, और बाकी के सभी क्रमपरिवर्तन का प्रयास करें।

कुछ इस तरह:

//Precomputation: Find all pairs shortest paths, e.g. using Floyd-Warshall
n = number of nodes
for i=1 to n: for j=1 to n: d[i][j]=INF
for k=1 to n:
    for i=1 to n:
        for j=1 to n:
            d[i][j] = min(d[i][j], d[i][k] + d[k][j])
//That *really* gives the shortest distance between every pair of nodes! :-)

//Now try all permutations
shortest = INF
for each permutation a[1],a[2],...a[k] of the 'mustpass' nodes:
    shortest = min(shortest, d['start'][a[1]]+d[a[1]][a[2]]+...+d[a[k]]['end'])
print shortest

(निश्चित रूप से यह वास्तविक कोड नहीं है, और यदि आप चाहते हैं कि वास्तविक पथ आपको ट्रैक करना होगा जिसमें क्रमचय कम से कम दूरी देता है, और यह भी कि सभी जोड़े सबसे छोटे पथ क्या हैं, लेकिन आपको यह विचार मिलता है।)

यह किसी भी वाजिब भाषा में कुछ सेकंड में चलेगा :)
[अगर आपके पास n नोड्स और k 'मस्टपास' नोड्स हैं, तो इसका रनिंग टाइम फ्लोयड-वारशॉल भाग के लिए O (n 3 ) है, और O (k! N! ) सभी क्रमपरिवर्तन भाग के लिए, और 100 ^ 3 + (12!) (100) व्यावहारिक रूप से मूंगफली है जब तक कि आपके पास वास्तव में कुछ प्रतिबंधात्मक बाधाएं नहीं हैं।]


6
छोटे इनपुट आकार को देखते हुए, मैं उत्तर से सहमत हूं। लेकिन मुझे इस बात में दिलचस्पी है कि आप दूसरों के दावे को क्यों खारिज करते हैं कि यह टीएसपी का मामला है। जिस तरह से मैं इसे समझता हूं, आप सभी आवश्यक-पास नोड्स निकाल सकते हैं और इसका उपयोग उप-ग्राफ़ बनाने के लिए कर सकते हैं। उप-ग्राफ़ में नोड्स के बीच के किनारों का मूल ग्राफ पर APSP समाधान के अनुरूप वजन होता है। तो फिर सवाल सबग्राफ पर टीएसपी का उदाहरण नहीं बन जाता है? आपका समाधान उस समस्या (जो ठीक है) के लिए एक क्रूर-बल समाधान प्रतीत होता है ।
पागलपन

7
@maditya: सबसे पहले, मुझे आशा है कि आप सहमत हैं कि (एक अन्य उत्तर पर स्टीवन ए लोवे की टिप्पणी को उद्धृत करने के लिए) "टीएसपी कठिन है, बावाहाहा" जैसे उत्तर किसी के लिए एक उपयुक्त उत्तर नहीं है, जिसे हल करने के लिए एक वास्तविक समस्या है, खासकर एक बहुत आसानी से। पिछले कुछ दशकों से किसी भी कंप्यूटर पर हल किया गया। दूसरे, यह तुच्छ कारणों (अलग इनपुट प्रारूप) के लिए टीएसपी के समान नहीं है: टीएसपी के छोटे उदाहरण में यह एक छोटे ग्राफ के लिए होता है, इनपुट आकार एन में से एक नहीं। तो एनपी-पूर्णता इस बात पर निर्भर करती है कि कितने 'मस्ट' नोड्स वहाँ समान रूप से कर रहे हैं: अगर यह हमेशा 12 है, या हे (लॉग एन), यह एनपी-पूर्ण नहीं है, आदि
ShreevatsaR

1
मुझे यकीन नहीं है कि परिणाम एक रास्ता होगा। से जाने के लिए कल्पना कीजिए aकरने cके माध्यम से b। हो सकता है कि कम से कम से रास्तों bको aऔर cबढ़त को साझा करें। उस स्थिति में, किनारे को दो बार दोहराया जाएगा। दो रास्तों में से एक को चक्र उत्पन्न करने के लिए इष्टतम से भी बदतर होना चाहिए।
Spak

1
@PietroSaccardi प्रश्न में विवरण से ऐसा लगता है कि लक्ष्य बस उन सभी नोड्स से गुजरने का सबसे छोटा "रास्ता" ढूंढना है, और यदि कुछ बढ़त दोहराई जाती है तो यह ठीक हो सकता है। यही है, "रास्ता" एक ढीले अर्थ में इस्तेमाल किया जा रहा है। वास्तव में, यदि बार-बार किनारों की अनुमति नहीं है, तो एक उत्तर भी नहीं हो सकता है (उदाहरण के लिए एक ग्राफ बी-ए-सी पर विचार करें जहां आपको बी से गुजरते समय ए से सी तक जाने के लिए कहा जाता है: दोहराने का कोई तरीका नहीं है ब- एक किनारा)।
श्रीवत्सआर

फ्लोयड-वारशाल एल्गोरिथ्म को यहां सही ढंग से लागू नहीं किया गया है: चूंकि सरणी के सभी सेल के साथ आरंभीकरण होता है INF, लाइन d[i][j] = min(d[i][j], d[i][k] + d[k][j])बन जाती है d[i][j] = min(INF, INF + INF)और सभी कोशिकाएं हमेशा बराबर रहती हैं INF। ग्राफ़ से किनारे की लंबाई के साथ इस सरणी को भरने के लिए आपको एक कदम जोड़ने की आवश्यकता है।
स्टेफ

25

सभी महत्वपूर्ण नोड्स (प्रारंभ, अंत और पास-पास) के बीच सबसे छोटे पथ को खोजने के लिए Djikstra के एल्गोरिथ्म को चलाएं , फिर एक गहराई-पहला ट्रैवर्सल आपको बताए गए सबग्राफ के माध्यम से सबसे छोटा रास्ता बताता है जो सभी नोड्स को स्पर्श करता है .. ,


ऐसा लगता है कि इसमें चयनित समाधान की तुलना में अधिक कुशल होने की क्षमता है। मैं शर्त लगाता हूं कि अगर आपने इसे थोड़ा और आउट कर दिया होता तो यह अधिक स्कोर बन जाता। मुझे पहले यह सोचना था कि क्या सभी जोड़ों के बीच एक छोटा रास्ता सभी आवश्यक नोड्स के बीच एक पथ की गारंटी देता है .. लेकिन मेरा मानना ​​है कि यह (अप्रत्यक्ष मानकर) होगा।
गल्तिकुह

मुझे लगता है कि यह काम नहीं करता है यदि कोई रास्ता किनारों को दोहराना नहीं चाहिए।
tuket

1
कोड-डे 24 के Advent के उदाहरण में सबसे पहला रास्ता गहराई-पहला ट्रैवर्सल कैसे मिलेगा? adventofcode.com/2016/day/24
एरविन रूइजाक्कर्स 23

16

यह दो समस्याएं हैं ... स्टीवन लोव ने इसे इंगित किया, लेकिन समस्या के उत्तरार्ध को पर्याप्त सम्मान नहीं दिया।

आपको पहले अपने सभी महत्वपूर्ण नोड्स (शुरू, अंत, मस्टपास) के बीच सबसे छोटे रास्तों की खोज करनी चाहिए। एक बार इन रास्तों की खोज हो जाने के बाद, आप एक सरलीकृत ग्राफ़ बना सकते हैं, जहाँ नए ग्राफ़ में प्रत्येक किनारे मूल ग्राफ में एक महत्वपूर्ण नोड से दूसरे तक एक पथ है। कई पाथफाइंग एल्गोरिदम हैं जिनका उपयोग आप यहां सबसे छोटा रास्ता खोजने के लिए कर सकते हैं।

एक बार जब आपके पास यह नया ग्राफ होता है, हालांकि, आपके पास बिल्कुल ट्रैवलिंग विक्रेता समस्या है (ठीक है, लगभग ... आपके शुरुआती बिंदु पर लौटने की कोई आवश्यकता नहीं है)। इससे संबंधित कोई भी पद, जो ऊपर वर्णित है, लागू होगा।


14

दरअसल, आपके द्वारा पोस्ट की गई समस्या ट्रैवलिंग सेल्समैन के समान है, लेकिन मुझे लगता है कि यह एक आसान पाथफाइंडिंग समस्या है। प्रत्येक और प्रत्येक नोड पर जाने की आवश्यकता के बजाय, आपको बस कम से कम समय (दूरी) में नोड्स के एक विशेष सेट पर जाने की आवश्यकता है।

इसका कारण यह है कि, यात्रा सेल्समैन की समस्या के विपरीत, एक मकई भूलभुलैया आपको नक्शे पर किसी भी एक बिंदु से किसी भी बिंदु पर सीधे यात्रा करने की अनुमति नहीं देगा, वहां जाने के लिए अन्य नोड्स से गुजरने की आवश्यकता नहीं है।

मैं वास्तव में विचार करने के लिए एक तकनीक के रूप में ए * पाथफाइंग की सिफारिश करूंगा। आप इसे यह तय करके सेट करते हैं कि किस नोड की पहुंच सीधे दूसरे नोड्स तक है, और किसी विशेष नोड से प्रत्येक हॉप की "लागत" क्या है। इस मामले में, ऐसा लगता है कि प्रत्येक "हॉप" समान लागत का हो सकता है, क्योंकि आपके नोड्स अपेक्षाकृत बारीकी से लगते हैं। A * इस जानकारी का उपयोग किसी भी दो बिंदुओं के बीच न्यूनतम लागत पथ को खोजने के लिए कर सकता है। चूँकि आपको बिंदु A से बिंदु B तक जाने और 12 inbetween की यात्रा करने की आवश्यकता है, यहां तक ​​कि पाथफाइंडिंग का उपयोग करने वाला एक क्रूर बल दृष्टिकोण भी चोट नहीं पहुंचाएगा।

बस एक विकल्प पर विचार करें। यह ट्रैवलिंग सेल्समैन समस्या की तरह उल्लेखनीय रूप से दिखता है, और वे पढ़ने के लिए अच्छे पेपर हैं, लेकिन करीब से देखें और आप देखेंगे कि इसकी केवल ओवरक्लिपिक चीजें हैं। ^ _ ^ यह वीडियो गेम प्रोग्रामर के दिमाग से आ रहा है, जो पहले इस प्रकार की चीजों से निपटता है।


2
+1 - यह 'सलमान की मुश्किल यात्रा, बवहहा' की तुलना में बहुत बेहतर उत्तर है
स्टीवन ए। लोवे

5

एंड्रयू टॉप का सही विचार है:

1) जिक्स्ट्रा का एल्गोरिथम 2) कुछ टीएसपी अनुमानी।

मैं लिन-कर्निघन हेयुरिस्टिक की सिफारिश करता हूं: यह किसी भी एनपी पूर्ण समस्या के लिए जाना जाता है। याद रखने वाली एकमात्र बात यह है कि चरण 2 के बाद आपने ग्राफ़ का फिर से विस्तार करने के बाद, आपके विस्तारित पथ में लूप हो सकते हैं, इसलिए आपको उन शॉर्ट-सर्कुलेटिंग के आसपास जाना चाहिए (अपने पथ के साथ कोने की डिग्री देखें)।

मुझे वास्तव में यकीन नहीं है कि यह समाधान इष्टतम के सापेक्ष कितना अच्छा होगा। शॉर्ट सर्किटिंग के साथ करने के लिए संभवतः कुछ रोग संबंधी मामले हैं। सब के बाद, यह समस्या स्टेनर ट्री की तरह बहुत सी दिखती है: http://en.wikipedia.org/wiki/Steiner_tree और आप निश्चित रूप से अपने ग्राफ को अनुबंधित करके और क्रुस्कल के उदाहरण के लिए चलकर स्टेनर ट्री को अनुमानित नहीं कर सकते।


5

यह वह जगह है नहीं एक TSP समस्या और नहीं एनपी कठिन है क्योंकि मूल प्रश्न है कि जरूरी-पास नोड्स केवल एक बार दौरा कर रहे हैं की आवश्यकता नहीं है। यह दीजकस्ट्रा के एल्गोरिथ्म के माध्यम से सभी पास-पास नोड्स के बीच सबसे छोटे रास्तों की एक सूची को संकलित करने के बाद उत्तर को बहुत सरल बना देता है। वहाँ जाने के लिए एक बेहतर तरीका हो सकता है, लेकिन एक साधारण बस एक बाइनरी ट्री को पीछे की ओर काम करना होगा। नोड्स की एक सूची की कल्पना करें [प्रारंभ, ए, बी, सी, अंत]। सरल दूरी [प्रारंभ-> a-> b-> c-> अंत] यह आपकी नई लक्ष्य दूरी है। अब कोशिश करें [शुरू-> a-> c-> b-> अंत] और अगर यह बेहतर है कि लक्ष्य के रूप में सेट करें (और याद रखें कि यह नोड्स के उस पैटर्न से आया है)। क्रमपरिवर्तन पर पीछे की ओर काम करें:

  • [प्रारंभ> a-> बी> ग> अंत]
  • [प्रारंभ> a-> ग> बी> अंत]
  • [प्रारंभ> बी> a-> ग> अंत]
  • [प्रारंभ> बी> ग> a-> अंत]
  • [प्रारंभ> ग> a-> बी> अंत]
  • [प्रारंभ> ग> बी> a-> अंत]

उनमें से एक सबसे छोटा होगा।

(जहां 'कई बार देखे गए' नोड्स हैं, यदि कोई हो? वे अभी-अभी सबसे कम पथ-प्रारंभिक आरंभीकरण चरण में छिपे हुए हैं। a और b के बीच के सबसे कम पथ में c या अंतिम बिंदु भी हो सकता है। आपको देखभाल करने की आवश्यकता नहीं है। )


केवल एक बार दिखाई देने से यह आवश्यक है कि यह सबसे छोटा रास्ता हो।
अज़ीथ

हुह। मैं एक मिनट पहले काफी निश्चित था, लेकिन हाँ, आप सही हैं। जाहिर है एक पेड़ में कई शाखाओं के साथ नहीं। लेकिन, बात यह है कि अगर हम समस्या को एक नए ग्राफ में समेटते हैं जिसमें केवल मस्टपास नोड होते हैं जो पूरी तरह से जुड़े होते हैं, तो मूल ग्राफ में सबसे कम पथ की दूरी वाले नोड्स के साथ, हम टीएसपी पर पहुंचते हैं। तो, क्या आप सुनिश्चित हैं कि यह एनपी-हार्ड नहीं है? मुझे लगता है कि सामान्य समस्या में, मस्ट नोड्स की मात्रा कुल नोड्स की मात्रा पर निर्भर करती है, और यदि, उदाहरण के लिए, कुल राउंड के एक बहुपद हैं, तो हमें एनपी-कठोरता मिलती है, है ना?
अज़ीथ

मार्ग, से कहता है, a-> b, c से होकर गुजर सकता है। अतः कोई भी ब्राह्मण किसी अन्य को रोकता नहीं है। यह सिर्फ क्रमचय है।
bjorke

हाँ? लेकिन क्रमपरिवर्तन हे (n!) यदि हम मानते हैं कि मस्टोड नोड्स की मात्रा का कुल नोड्स की राशि से कुछ संबंध है, जैसे "कुल नोड्स मस्टोड नोड्स के एक बहुपद हैं"। आपने सिर्फ क्रूर बल द्वारा TSP को हल किया।
अज़ीथ

2

नोड्स और किनारों की मात्रा को ध्यान में रखते हुए अपेक्षाकृत कम परिमित है, आप शायद हर संभव पथ की गणना कर सकते हैं और सबसे छोटा ले सकते हैं।

आम तौर पर इसे ट्रैवलिंग सेल्समैन समस्या के रूप में जाना जाता है, और इसमें एक गैर-नियतात्मक बहुपद रनटाइम होता है, इससे कोई फर्क नहीं पड़ता कि आप किस एल्गोरिथ्म का उपयोग करते हैं।

http://en.wikipedia.org/wiki/Traveling_salesman_problem


1

प्रश्न किसी भी क्रम में पास होने की बात करता है । मैं पास-पास नोड्स के परिभाषित क्रम के बारे में समाधान खोजने की कोशिश कर रहा हूं। मुझे मेरा उत्तर मिल गया लेकिन चूंकि StackOverflow पर कोई प्रश्न नहीं था, इसलिए मैं एक ऐसा ही प्रश्न यहाँ पोस्ट कर रहा हूँ जिससे अधिकतम लोग इससे लाभान्वित हो सकें।

यदि आदेश या पास-पास परिभाषित किया गया है, तो आप कई बार dijkstra के एल्गोरिथ्म को चला सकते हैं। उदाहरण के लिए मान लें कि आपको पास से शुरू sकरना है k1, k2और k3(संबंधित क्रम में) और रुकना है e। तब आप जो कर सकते थे, वह है dijkstra के एल्गोरिथ्म के प्रत्येक लगातार जोड़े के बीच। लागत और पथ से दी जाएगी:

dijkstras(s, k1) + dijkstras(k1, k2) + dijkstras(k2, k3) + dijkstras(k3, 3)


0

दर्जन भर 'ब्रूट फोर्स' का उपयोग करने के बारे में कैसे 'नोड्स' पर जाना चाहिए। आप 12 नोड्स के सभी संभावित संयोजनों को आसानी से पर्याप्त रूप से कवर कर सकते हैं, और यह आपको एक इष्टतम सर्किट के साथ छोड़ देता है जिसे आप उन्हें कवर करने के लिए अनुसरण कर सकते हैं।

अब आपकी समस्या शुरू नोड से सर्किट तक इष्टतम मार्गों को खोजने में से एक के लिए सरल है, जिसे आप तब तक का पालन करते हैं जब तक आप उन्हें कवर नहीं करते हैं, और फिर उस से अंत तक का मार्ग खोजें।

अंतिम पथ से बना है:

प्रारंभ -> सर्किट के लिए पथ * -> सर्किट को नोड्स पर जाना चाहिए -> अंत का रास्ता * -> अंत

आपको मेरे द्वारा इस तरह से चिह्नित पथ मिलते हैं

प्रारंभ ए नोड से सर्किट पर प्रत्येक बिंदु के लिए ए * खोज करें प्रत्येक ए के लिए सर्किट पर अगले और पिछले नोड से अंत तक ए * खोज करें (क्योंकि आप किसी भी दिशा में सर्किट दौर का पालन कर सकते हैं) क्या आप अंत तक बहुत सारे खोज पथ हैं, और आप सबसे कम लागत वाले को चुन सकते हैं।

खोजों को कैशिंग करके अनुकूलन के लिए बहुत जगह है, लेकिन मुझे लगता है कि यह अच्छा समाधान उत्पन्न करेगा।

हालांकि यह एक इष्टतम समाधान की तलाश में कहीं भी नहीं जाता है, क्योंकि इसमें खोज के भीतर अवश्य ही सर्किट को छोड़ना शामिल हो सकता है।


0

एक बात जो कहीं भी उल्लिखित नहीं है, वह यह है कि क्या एक ही शिखर के लिए पथ में एक से अधिक बार जाना ठीक है। यहाँ अधिकांश उत्तर यह मानते हैं कि एक ही किनारे पर कई बार जाना ठीक है, लेकिन मेरे द्वारा दिए गए प्रश्न (एक पथ को एक ही बार में एक से अधिक बार नहीं जाना चाहिए!) यह है कि एक ही शीर्ष पर दो बार जाना ठीक नहीं है

तो एक बल बल दृष्टिकोण अभी भी लागू होगा, लेकिन जब आप पथ के प्रत्येक सबसेट की गणना करने का प्रयास करते हैं, तो आपको पहले से उपयोग किए जाने वाले वर्टीकल्स को निकालना होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.