2009-06-02 10 views
11

मैंने हाल ही में अपनी परियोजना में एकल स्रोत के सबसे कम पथ के लिए डिजस्ट्रा एल्गोरिदम का तीसरा संस्करण संलग्न किया था।सबसे तेज़ डिजस्ट्रा कार्यान्वयन क्या है जिसे आप जानते हैं (सी ++ में)?

मुझे एहसास है कि कई अलग-अलग कार्यान्वयन हैं जो प्रदर्शन में दृढ़ता से भिन्न होते हैं और बड़े ग्राफ में परिणाम की गुणवत्ता में भिन्न होते हैं। मेरे डेटा सेट (> 100.000 शिखर) के साथ रनटाइम 20 मिनट से कुछ सेकंड तक भिन्न होता है। सबसे कम पथ भी 1-2% से भिन्न होते हैं।

आपको सबसे अच्छा कार्यान्वयन कौन सा पता है?

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

मैं परिणामों में मामूली मतभेदों की व्याख्या नहीं कर सकता। मुझे पता है कि डिजस्ट्रा ह्युरिस्टिक नहीं है, लेकिन सभी कार्यान्वयन सही प्रतीत होते हैं। तेज समाधानों के परिणाम कम पथ के साथ होते हैं। मैं विशेष रूप से डबल परिशुद्धता गणित का उपयोग करता हूं।

संपादित 2: मुझे पता चला कि पाए गए पथ में अंतर वास्तव में मेरी गलती है। मैंने कुछ शिखर (केवल एक दिशा में मान्य) के लिए विशेष हैंडलिंग डाली थी और इसके बारे में अन्य कार्यान्वयन में भूल गए थे।

लेकिन im अभी भी आश्चर्य की तुलना में अधिक है कि डिज्कस्ट्रा निम्नलिखित परिवर्तन से नाटकीय रूप से त्वरित किया जा सकता है:, यह आप इस एक छोटा सा बदल लेते हैं

MyListType toDoList; // List sorted by smallest distance 
InsertAllNodes(toDoList); 
while(! toDoList.empty()) 
{ 
    MyNodeType *node = *toDoList.first(); 
    toDoList.erase(toDoList.first()); 
    ... 
} 

: सामान्य एक डिज्कस्ट्रा एल्गोरिथ्म में की तरह एक पाश में शामिल है बेहतर ही काम करता है, लेकिन करता है:

MyListType toDoList; // List sorted by smallest distance 
toDoList.insert(startNode); 
while(! toDoList.empty()) 
{ 
    MyNodeType *node = *toDoList.first(); 
    toDoList.erase(toDoList.first()); 
    for(MyNeigborType *x = node.Neigbors; x != NULL; x++) 
    { 
     ... 
     toDoList.insert(x->Node); 
    } 
} 

ऐसा लगता है, कि इस संशोधन परिमाण के एक आदेश से क्रम, लेकिन प्रतिपादक के एक आदेश कम करता है। इसने मेरे रनटाइम फॉर्म 30 सेकेंड से 2 से कम कर दिया। मुझे किसी भी साहित्य में यह संशोधन नहीं मिल रहा है। यह भी स्पष्ट है कि कारण क्रमबद्ध सूची में निहित है। सम्मिलित/मिटाने से 100,000 तत्वों के साथ बहुत खराब प्रदर्शन होता है।

उत्तर:

मैं यह पाया googling अपने आप का एक बहुत कुछ करने के बाद। उत्तर स्पष्ट रूप से है: boost graph lib। आश्चर्यजनक - मुझे यह थोड़ी देर के लिए नहीं मिला था। यदि आपको लगता है कि डिजस्ट्रा कार्यान्वयन के बीच कोई प्रदर्शन भिन्नता नहीं है, तो wikipedia देखें।

+26

मेरा एक दोस्त लगभग 3 मिनट में सी ++ में डिजस्ट्रा को कार्यान्वित कर सकता है। मैंने किसी भी तेजी से कार्यान्वयन के बारे में नहीं सुना है। – jbasko

+5

मैं सुझाव दूंगा कि आप उन कार्यान्वयनों को जांचना चाहेंगे ... यदि वे सही हैं तो उन्हें सभी को एक ही सबसे छोटा रास्ता वापस करना चाहिए ... डिजस्ट्रा का एल्गोरिदम हेरिस्टिक नहीं है ... – jerryjvl

+2

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

उत्तर

11

सड़क नेटवर्क (> 1 मिलियन नोड्स) के लिए जाने वाले सर्वोत्तम कार्यान्वयन में माइक्रो सेकेंड में व्यक्त किए गए प्रश्नों का समय होता है। 9वीं डीआईएमएसीएस कार्यान्वयन चैलेंज (2006) के बारे में अधिक जानकारी के लिए देखें। ध्यान दें कि ये केवल डिजस्ट्रा नहीं हैं, बेशक, क्योंकि पूरे बिंदु को परिणाम तेजी से प्राप्त करना था।

+2

मुझे http://www.dis.uniroma1.it/~challenge9/papers.shtml बहुत प्रभावशाली के तहत उल्लिखित चुनौती मिली। धन्यवाद। –

+1

कंट्राक्शन पदानुक्रम विधि के लिए http://algo2.iti.uni-karlsruhe.de/english/1087.php भी देखें। –

0

यह कई चीजों पर निर्भर होने जा रहा है। आप अपने इनपुट डेटा के बारे में कितना जानते हैं? क्या यह घना, या स्पैस है? यह बदलेगा कि एल्गोरिदम के कौन से संस्करण सबसे तेज़ हैं।

यदि यह घना है, तो बस एक मैट्रिक्स का उपयोग करें। यदि इसका स्पैस है, तो आप अगले निकटतम चरम को खोजने के लिए अधिक कुशल डेटा संरचनाओं को देखना चाहेंगे। यदि आपके पास ग्राफ कनेक्टिविटी की तुलना में आपके डेटा सेट के बारे में अधिक जानकारी है, तो देखें कि एक अलग एल्गोरिदम ए * की तरह बेहतर काम करेगा या नहीं।

समस्या यह है कि एल्गोरिदम का "सबसे तेज़" संस्करण नहीं है।

1

पिछली बार मैंने चेक किया, डिजस्ट्रा के एल्गोरिदम एक इष्टतम समाधान देता है। डिजस्ट्रा के सभी "सत्य" कार्यान्वयन को हर बार एक ही परिणाम वापस करना चाहिए।

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

+0

बिल्कुल। एकमात्र अंतर तब हो सकता है जब उसके साथ कई "सबसे छोटे पथ" होते हैं (एक गोलाकार त्रुटि के भीतर) लंबाई (लागत)। यदि कुछ कार्यान्वयन एक छोटा रास्ता खोजने में विफल रहता है, तो यह छोटी गाड़ी है। जब तक नोड दूरी का आपका अनुपात बहुत अधिक न हो (जैसे 1e20 या अधिक), आपको निश्चित रूप से 1-2% प्रतिशत अंतर नहीं देखना चाहिए, यहां तक ​​कि फ्लोट के साथ, युगल के बारे में बात नहीं करना चाहिए। – Suma

3

हो सकता है कि मैं आपके प्रश्न का उत्तर नहीं दे रहा हूं। मेरा मुद्दा यह है कि आपकी समस्या के लिए बहुत अधिक कुशल एल्गोरिदम होने पर डिजस्ट्रा का उपयोग क्यों करें। यदि आपका ग्राफ त्रिभुज संपत्ति को पूरा करता है (यह एक यूक्लिडियन ग्राफ है)

| ab | + | बीसी | > | एसी |

(नोड से नोड बी प्लस दूरी से नोड बी से नोड सी तक की दूरी नोड से नोड सी तक की दूरी से बड़ी है) तो आप ए * एल्गोरिदम लागू कर सकते हैं। यह एल्गोरिदम बहुत कुशल है। अन्यथा हेरिस्टिक का उपयोग करने पर विचार करें। कार्यान्वयन प्रमुख मुद्दा नहीं है। इस्तेमाल करने के लिए एल्गोरिदम मायने रखता है।

+0

मुझे नहीं लगता कि आपको * त्रिकोणीय संपत्ति की भी आवश्यकता है। आपको बस एक अच्छा ह्युरिस्टिक फ़ंक्शन चाहिए। एक गरीब लेकिन वैध ह्युरिस्टिक के साथ, ए * डिजस्ट्रा में गिरावट आई है। – MSalters

+0

सच है। तुम सही हो। जो मैं कह रहा था वह संभव स्वीकार्य ह्युरिस्टिक था। – Luixv

2

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

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

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

2) डिजस्ट्रा एल्गोरिदम (और ए * जैसे अन्य) अगली नोड को एक्सप्लोर करने के लिए प्राथमिकता कतार का उपयोग करते हैं। एक अच्छा कार्यान्वयन एक कतार के बजाय एक ढेर का उपयोग कर सकता है, और एक बेहतर भी एक फाइबोनैकी ढेर का उपयोग कर सकते हैं। यह विभिन्न रन टाइम समझा सकता है।

संबंधित मुद्दे