डीजेकस्ट्रा के एल्गोरिथ्म का उपयोग करते हुए ऋणात्मक भार


113

मैं यह समझने की कोशिश कर रहा हूं कि क्यों डायजेक्स्ट्रा का एल्गोरिदम नकारात्मक भार के साथ काम नहीं करेगा। सबसे छोटे रास्तों पर एक उदाहरण पढ़कर , मैं निम्नलिखित परिदृश्य का पता लगाने की कोशिश कर रहा हूं:

    2
A-------B
 \     /
3 \   / -2
   \ /
    C

वेबसाइट से:

किनारों को मानकर सभी को बाएं से दाएं निर्देशित किया जाता है, अगर हम A से शुरू करते हैं, तो दिक्जस्ट्रा का एल्गोरिथ्म किनारे (A, x) को कम से कम d (A, A) + लंबाई (एज), अर्थात् (A, B) का चयन करेगा। यह तब d (A, B) = 2 सेट करता है और दूसरा किनारा (y, C) चुनता है d (A, y) + d (y, C); एकमात्र विकल्प (ए, सी) है और यह डी (ए, सी) = 3 सेट करता है। लेकिन यह कभी भी ए से बी तक, सी के माध्यम से, कुल लंबाई 1 के साथ सबसे छोटा रास्ता नहीं ढूंढता है।

मुझे समझ में नहीं आ रहा है कि दिक्जस्ट्रा के निम्नलिखित कार्यान्वयन का उपयोग करते हुए, d [B] को अपडेट नहीं किया जाएगा 1(जब एल्गोरिथ्म शीर्ष C पर पहुंचता है, तो यह B पर एक आराम चलाएगा, देखें कि d [B] के बराबर है 2, और इसलिए अद्यतन करें इसका मूल्य 1)।

Dijkstra(G, w, s)  {
   Initialize-Single-Source(G, s)
   S ← Ø
   Q ← V[G]//priority queue by d[v]
   while Q ≠ Ø do
      u ← Extract-Min(Q)
      S ← S U {u}
      for each vertex v in Adj[u] do
         Relax(u, v)
}

Initialize-Single-Source(G, s) {
   for each vertex v  V(G)
      d[v] ← ∞
      π[v] ← NIL
   d[s] ← 0
}

Relax(u, v) {
   //update only if we found a strictly shortest path
   if d[v] > d[u] + w(u,v) 
      d[v] ← d[u] + w(u,v)
      π[v] ← u
      Update(Q, v)
}

धन्यवाद,

मीर


नकारात्मक बढ़त भार के साथ सामान्य रूप से पथ-निर्धारण अत्यंत कठिन है। कोई फर्क नहीं पड़ता कि आपको कौन सा मार्ग मिल रहा है, वहाँ हमेशा एक अनियंत्रित रूप से बड़े नकारात्मक किनारे के वजन के साथ लंबे समय तक मार्ग की संभावना होती है। अगर यह एनपी पूरा हो गया तो मुझे आश्चर्य नहीं होगा।
निक जॉनसन

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

जवाबों:


202

आपके द्वारा सुझाया गया एल्गोरिदम वास्तव में इस ग्राफ़ में सबसे छोटा रास्ता ढूंढेगा, लेकिन सामान्य रूप से सभी ग्राफ़ नहीं। उदाहरण के लिए, इस ग्राफ पर विचार करें:

ग्राफ का चित्र

मान लें कि किनारों को आपके उदाहरण के अनुसार बाएं से दाएं निर्देशित किया गया है,

आपका एल्गोरिथ्म निम्नानुसार काम करेगा:

  1. सबसे पहले, आप d(A)को zeroऔर दूसरी दूरियों को सेट करते हैं infinity
  2. इसके बाद आप नोड बाहर का विस्तार A, की स्थापना d(B)करने के लिए 1, d(C)करने के लिए zero, और d(D)करने के लिए 99
  3. अगला, आप Cबिना किसी शुद्ध परिवर्तन के विस्तार करते हैं।
  4. आप फिर विस्तार करते हैं B, जिसका कोई प्रभाव नहीं है।
  5. अंत में, आप विस्तार करते हैं D, जिसमें परिवर्तन d(B)होता है -201

ध्यान दें कि इस के अंत में, हालांकि, वह d(C)अभी भी है 0, भले ही Cलंबाई के लिए सबसे छोटा रास्ता है -200 इस प्रकार आपका एल्गोरिथ्म कुछ मामलों में दूरी की सही गणना करने में विफल रहता है। इसके अलावा, भले ही आप वापस कह कैसे प्राप्त करने के लिए शुरू नोड के लिए प्रत्येक नोड से संकेत स्टोर करने के लिए थे A, तो आप से गलत रास्ता वापस लेने पहुंचते हैं Cकरने के लिए A


35
अपने उत्कृष्ट उत्तर को जोड़ने के लिए: दिज्क्स्ट्रा एक लालची एल्गोरिथ्म है जो इसकी अदूरदर्शी पसंद का कारण है।
blubb

4
मैं यह बताना चाहूंगा कि तकनीकी रूप से, इस ग्राफ के सभी रास्तों में ऋणात्मक चक्र A, D, B, A के नकारात्मक अनंत सौजन्य की लागत है।
नैट

2
@ नैट- स्पष्ट करने के लिए, ग्राफ़ के सभी किनारों को बाएं से दाएं निर्देशित किया गया है। यह मेरी उच्च-गुणवत्ता वाली ASCII कला में तीरों को प्रस्तुत करना कठिन था। :-)
टेम्प्लेटेटेपीडिफ

2
उन लोगों के लिए जिन्होंने पहले नकारात्मक किनारों के साथ रेखांकन नहीं देखा है, मैं टोल सड़कों का एक नेटवर्क होने के लिए इस ग्राफ की एक उपयोगी व्याख्या पाता हूं, जहां किनारे का वजन आपके द्वारा भुगतान किए जाने वाले टोल देता है। -300 रोड एक पागल पीछे की ओर टोल रोड है जहां वे आपको इसके बदले $ 300 देते हैं।
डी। कोटिजी

3
@ SchwitJanwityanujit- यह दिज्क्स्ट्रा का एल्गोरिदम कैसे काम करता है। एल्गोरिथ्म पथ का पता नहीं लगाता , बल्कि नोड्स को संसाधित करके काम करता है । प्रत्येक नोड को ठीक एक बार संसाधित किया जाता है, इसलिए जैसे ही हम बी नोड को संसाधित करते हैं और प्राप्त करते हैं कि इसकी दूरी 1 है, हम नोड बी को फिर से नहीं देखेंगे या इसकी दूरी को अपडेट करने का प्रयास नहीं करेंगे।
टेम्प्लेटेटपेडिफ

25

ध्यान दें, कि दिक्जस्ट्रा नकारात्मक भारों के लिए भी काम करता है, यदि ग्राफ में कोई नकारात्मक चक्र नहीं है, अर्थात चक्र जिनका वजन कम है शून्य से कम है।

बेशक कोई भी पूछ सकता है कि टेम्प्लेटपेटेडफ डीजकस्ट्रा द्वारा बनाए गए उदाहरण में क्यों कोई नकारात्मक चक्र नहीं होने के बावजूद विफल रहता है, चक्र भी नहीं। ऐसा इसलिए है क्योंकि वह एक और स्टॉप मानदंड का उपयोग कर रहा है, जो कि टारगेट नोड तक पहुँचते ही अल्गोरिद्म धारण करता है (या सभी नोड्स एक बार निपट चुके हैं, उसने यह निर्दिष्ट नहीं किया है)। नकारात्मक भार के बिना एक ग्राफ में यह ठीक काम करता है।

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

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


2. यह स्पष्ट नहीं है कि आपको क्यों लगता है कि समय मुझे "बेलमैन-फोर्ड की तरह" होगा और न ही घातांक (जो कि बेलमैन-फोर्ड से भी बदतर है)। क्या आपके पास एक ठोस एल्गोरिदम और मन में एक सबूत है?
गस्सा

3
1 के लिए: जैसा कि आप उल्लेख स्टॉप मानदंड के साथ dijkstra के बिल्कुल उसी कार्यान्वयन का उपयोग कर सकते हैं, जो तब रुकता है जब कतार खाली हो जाती है (मूल प्रश्न में pseudocode देखें), यह अभी भी अलग-अलग व्यवहार करता है, भले ही छोटे रास्तों के लिए dijkstras एल्गोरिथ्म हो। नोड्स को कई बार निपटाना (लेबल सही करना)।
infty10000101

1
2 तक: यह सिर्फ एक अनुमान था इसलिए मैं इसे हटाने जा रहा हूं। मुझे लगता है कि आप घातीय समय के साथ सही हैं, क्योंकि घातीय रूप से कई रास्ते हैं, जिन्हें तलाशना होगा।
infty10000101

11

आपने अपने एल्गोरिथ्म में कहीं भी एस का उपयोग नहीं किया (इसके अलावा इसे संशोधित करके)। दिक्स्ट्रा का विचार एक बार एक शीर्ष पर है, एस पर है, इसे फिर से संशोधित नहीं किया जाएगा। इस स्थिति में, एक बार B, S के अंदर है, तो आप C के माध्यम से फिर से नहीं पहुंचेंगे।

यह तथ्य O (E + VlogV) की जटिलता को सुनिश्चित करता है [अन्यथा, आप किनारों को एक बार फिर से दोहराएंगे, और उसके बाद कोने को सीधा करेंगे]

दूसरे शब्दों में, आपके द्वारा पोस्ट किया गया एल्गोरिथ्म, ओ (ई + VlogV) में नहीं हो सकता है, जैसा कि डिक्स्ट्रा के एल्गोरिदम द्वारा वादा किया गया था।


इसके अलावा, नकारात्मक वजन के किनारों के बिना शीर्ष को संशोधित करने की कोई आवश्यकता नहीं है, जो इस धारणा को पूरी तरह से तोड़ देता है कि पथ की लागत केवल दोहराया किनारों के साथ बढ़ सकती है
prusswan

यह धारणा ठीक वही है जो हमें एस का उपयोग करने की अनुमति देता है, और एक बार एक शीर्ष एस में होने के बाद 'जानना', इसे फिर से संशोधित नहीं किया जाएगा।
अमित

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

7

चूंकि दिक्जस्त्र एक लालची दृष्टिकोण है, एक बार जब इस लूप के लिए एक कोने के रूप में चिह्नित किया जाता है, तो इसे फिर से कभी भी फिर से मूल्यांकन नहीं किया जा सकता है, भले ही बाद में उस तक पहुंचने के लिए कम लागत वाला कोई अन्य मार्ग हो। और ऐसा मुद्दा केवल तभी हो सकता है जब ग्राफ में नकारात्मक किनारे मौजूद हों।


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


4

टीएल; डीआर: उत्तर आपके कार्यान्वयन पर निर्भर करता है। आपके द्वारा पोस्ट किए गए छद्म कोड के लिए, यह नकारात्मक भार के साथ काम करता है।


दिजाकस्ट्रा के एल्गोरिथ्म के वेरिएंट

कुंजी दिक्क्स्ट्रा के एल्गोरिथ्म के कार्यान्वयन के 3 प्रकार हैं , लेकिन इस प्रश्न के तहत सभी उत्तर इन वेरिएंट के बीच अंतर को अनदेखा करते हैं।

  1. एक का उपयोग करना नेस्टेड for-loop कोने आराम करने के लिए। यह दिज्क्स्ट्रा के एल्गोरिथ्म को लागू करने का सबसे आसान तरीका है। समय जटिलता O (V ^ 2) है।
  2. प्राथमिकता-कतार / ढेर आधारित कार्यान्वयन + पुन: प्रवेश की अनुमति नहीं है, जहां फिर से प्रवेश करने का मतलब है कि एक आराम से बरामदे को प्राथमिकता-कतार में फिर से बाद में आराम से धकेल दिया जा सकता है
  3. प्राथमिकता-कतार / ढेर आधारित कार्यान्वयन + पुन: प्रवेश की अनुमति है।

संस्करण 1 और 2 नकारात्मक भार के साथ रेखांकन पर विफल होंगे (यदि आपको ऐसे मामलों में सही उत्तर मिलता है, तो यह सिर्फ एक संयोग है), लेकिन संस्करण 3 अभी भी काम करता है

मूल समस्या के तहत पोस्ट किया गया छद्म कोड संस्करण 3 ऊपर है, इसलिए यह नकारात्मक भार के साथ काम करता है।

यहाँ एल्गोरिथ्म (4 वें संस्करण) से एक अच्छा संदर्भ दिया गया है , जो कहता है (और संस्करण 2 और 3 के जावा कार्यान्वयन में ऊपर शामिल है):

प्र। क्या दिक्जस्ट्रा का एल्गोरिदम नकारात्मक भार के साथ काम करता है?

A. हां और नहीं। दो सबसे छोटे पथ एल्गोरिदम हैं जिन्हें दीजकस्ट्रा के एल्गोरिथ्म के रूप में जाना जाता है, इस पर निर्भर करता है कि क्या एक शीर्ष प्राथमिकता को एक से अधिक बार कतार में लगाया जा सकता है। जब वज़न नॉनगेटिव हो जाता है, तो दो संस्करण मेल खाते हैं (जैसा कि कोई वर्टेक्स एक बार से अधिक नहीं होगा)। DijkstraSP.java में लागू किया गया संस्करण (जो एक वर्टेक्स को एक से अधिक बार एनकेच करने की अनुमति देता है) नेगेटिव एज वेट (लेकिन कोई नकारात्मक चक्र) की उपस्थिति में सही नहीं है लेकिन इसका रनिंग टाइम सबसे खराब स्थिति में घातीय है। (हम ध्यान देते हैं कि DijkstraSP.java एक अपवाद फेंकता है यदि किनारे-भार वाले डिग्राफ में नकारात्मक वजन के साथ एक किनारे होता है, ताकि एक प्रोग्रामर इस घातीय व्यवहार से आश्चर्यचकित न हो।) यदि हम DijkstraSP.java को संशोधित करते हैं, ताकि एक वर्टेक्स को नहीं लगाया जा सके। एक से अधिक बार (जैसे, चिह्नित किए गए [] सरणी का उपयोग करके उन कोने को चिह्नित किया जाता है जिन्हें आराम दिया गया है),


अधिक कार्यान्वयन विवरण और बेलमैन-फोर्ड एल्गोरिथ्म के साथ संस्करण 3 के कनेक्शन के लिए, कृपया यह उत्तर झिहू से देखें । यह मेरा उत्तर भी है (लेकिन चीनी भाषा में)। वर्तमान में मेरे पास इसका अंग्रेजी में अनुवाद करने का समय नहीं है। मैं वास्तव में इसकी सराहना करता हूं अगर कोई ऐसा कर सकता है और स्टैकओवरफ्लो पर इस उत्तर को संपादित कर सकता है।


1

गौर कीजिए कि यदि आप B और C के बीच आगे और पीछे जाते हैं तो क्या होता है ... वोइला

(प्रासंगिक केवल अगर ग्राफ निर्देशित नहीं है)

संपादित: मेरा मानना ​​है कि समस्या को इस तथ्य के साथ करना है कि एसी * के साथ पथ केवल नकारात्मक वजन के किनारों के अस्तित्व के साथ एबी से बेहतर हो सकता है, इसलिए यह मायने नहीं रखता है कि आप एसी के बाद कहां जाते हैं, गैर की धारणा के साथ। नकारात्मक भार किनारों के लिए एबी से बेहतर रास्ता खोजना असंभव है जब आप एसी जाने के बाद बी तक पहुंचने के लिए चुनते हैं।


यह संभव नहीं है, ग्राफ निर्देशित है।
amit

@amit: अच्छी बात है, मैं चूक गया। समस्या पर पुनर्विचार करने का समय
uss३३:३

1

"2) क्या हम नकारात्मक वज़न वाले ग्राफ़ के लिए कम से कम रास्तों के लिए दिक्षक्ष के एल्गोरिथ्म का उपयोग कर सकते हैं - एक विचार हो सकता है, न्यूनतम वजन मूल्य की गणना करें, सभी वज़न के लिए एक सकारात्मक मान (न्यूनतम वजन मूल्य के निरपेक्ष मूल्य के बराबर) जोड़ें और दीक्षरा के एल्गोरिथ्म को चलाएं। संशोधित ग्राफ़ के लिए। क्या यह एल्गोरिथम काम करेगा? "

यह बिल्कुल काम नहीं करता है जब तक कि सभी छोटे पथों की लंबाई समान न हो। उदाहरण के लिए, दो किनारों की लंबाई का सबसे छोटा रास्ता दिया गया है, और प्रत्येक किनारे के लिए निरपेक्ष मूल्य को जोड़ने के बाद, तो कुल पथ लागत 2 * | अधिकतम नकारात्मक भार से होती है। दूसरी ओर लंबाई का एक और रास्ता तीन किनारों, इसलिए पथ की लागत 3 * से बढ़ जाती है। अधिकतम नकारात्मक वजन | इसलिए, सभी अलग-अलग रास्तों को अलग-अलग राशियों द्वारा बढ़ाया जाता है।


0

आप नकारात्मक चक्रों के साथ नकारात्मक चक्र के एल्गोरिथ्म का उपयोग कर सकते हैं, जिसमें नकारात्मक चक्र शामिल नहीं है, लेकिन आपको अनुमति देना चाहिए कि किसी शीर्ष को कई बार देखा जा सकता है और यह संस्करण खो देगा, यह समय की जटिलता है।

उस मामले में व्यावहारिक रूप से मैंने देखा है कि एसपीएफए ​​एल्गोरिदम का उपयोग करना बेहतर है, जिसमें सामान्य कतार होती है और नकारात्मक किनारों को संभाल सकती है।

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