दिजाकस्ट्रा के एल्गोरिथ्म और ए-स्टार की तुलना कैसे होती है?


154

मैं देख रहा था कि मारियो एआई प्रतियोगिता में लोग क्या कर रहे हैं और उनमें से कुछ ने ए * (ए-स्टार) पाथिंग एलगोरिदम का उपयोग करते हुए कुछ बहुत साफ-सुथरे मारियो बॉट बनाए हैं।

वैकल्पिक शब्द
( मारियो ए * बॉट इन एक्शन का वीडियो )

मेरा सवाल यह है कि ए-स्टार की तुलना दिज्क्स्त्र से कैसे की जाती है? उन्हें देखते हुए, वे समान लगते हैं।

कोई एक के ऊपर एक प्रयोग क्यों करेगा? खासतौर पर खेलों में पाथिंग के संदर्भ में?



@ एसएलएस ए * डिजास्ट्रा से अधिक मेमोरी का उपयोग करता है? अगर dkkstra उन सब को आज़माता है तो * एक ही रास्ता आशाजनक नोड्स कैसे आता है?
पौटराथोर

जवाबों:


177

दिज्क्स्त्र ए * (जब उत्तराधिकार शून्य है) के लिए एक विशेष मामला है।


1
दिज्क्स्त्र में, हम केवल स्रोत से दूरी को सही मानते हैं? और न्यूनतम शीर्ष को ध्यान में रखा जाता है?
क्रैकन

4
मुझे लगा कि ए * दिज्क्स्त्र के लिए एक विशेष मामला है जहां वे एक विधर्मी का उपयोग करते हैं। चूंकि दिक्जस्त्र पहले एफिक था।
Madmenyo

46
@ मेनोउगॉव: हाँ दिज्क्स्ट्रा का एल्गोरिथम पहले विकसित किया गया था; लेकिन यह अधिक सामान्य एल्गोरिथ्म ए * का एक विशेष मामला है। विशेष मामलों के लिए पहले खोजा जाना, और फिर बाद में सामान्यीकृत किया जाना बिल्कुल भी असामान्य नहीं है (वास्तव में, शायद आदर्श)।
पीटर गेकरेंस

1
किसी के लिए भी महान उत्तर, जो
आंकड़े


113

डिज्कस्ट्रा:

इसमें एक लागत फ़ंक्शन है, जो स्रोत से प्रत्येक नोड के लिए वास्तविक लागत मूल्य है f(x)=g(x):।
यह केवल वास्तविक लागत पर विचार करके स्रोत से हर दूसरे नोड के लिए सबसे छोटा रास्ता ढूंढता है।

एक खोज:

यह दो लागत समारोह है।

  1. g(x): दीजकस्त्र के समान। एक नोड तक पहुंचने के लिए वास्तविक लागत x
  2. h(x): नोड xसे लक्ष्य नोड तक अनुमानित लागत । यह एक हेयुरिस्टिक फ़ंक्शन है। इस हेयुरेशनल फ़ंक्शन को कभी भी लागत को कम नहीं करना चाहिए। इसका मतलब है, नोड से लक्ष्य नोड तक पहुंचने की वास्तविक लागत xअधिक से अधिक या बराबर होनी चाहिए h(x)। इसे स्वीकार्य हेयुरिस्टिक कहा जाता है।

प्रत्येक नोड की कुल लागत की गणना द्वारा की जाती है f(x)=g(x)+h(x)

ए * सर्च केवल एक नोड का विस्तार करता है यदि यह आशाजनक लगता है। यह केवल वर्तमान नोड से लक्ष्य नोड तक पहुंचने के लिए केंद्रित है, न कि हर दूसरे नोड तक पहुंचने के लिए। यह इष्टतम है, यदि हेयुरिस्टिक फ़ंक्शन स्वीकार्य है।

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


20

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


17
यदि कई संभावित लक्ष्य नोड्स हैं, तो कोई भी उन सभी को शामिल करने के लिए लक्ष्य परीक्षण फ़ंक्शन को बदल सकता है। इस तरह, A * को केवल एक बार चलाने की आवश्यकता होगी।
ब्रैड लार्सन

9

डायजेक्स्ट्रा का एल्गोरिथ्म कभी भी पथ-प्रदर्शक के लिए उपयोग नहीं किया जाएगा। ए * का उपयोग करना एक बिना दिमाग वाला है यदि आप एक सभ्य विधर्मी के साथ आ सकते हैं (आमतौर पर खेल के लिए आसान है, खासकर 2 डी दुनिया में)। खोज स्थान के आधार पर, Iterative Deepening A * कभी-कभी बेहतर होता है क्योंकि यह कम मेमोरी का उपयोग करता है।


5
डायजेक्स्ट्रा का इस्तेमाल कभी भी पथप्रदर्शक के लिए क्यों नहीं किया जाएगा? क्या आप विस्तार से समझा सकते हैं?
KingNestor

2
क्योंकि भले ही आप एक घटिया विधर्मी के साथ आ सकते हैं, आप दिक्जस्त्र से बेहतर करेंगे। कभी-कभी भले ही यह बेवजह हो। यह डोमेन पर निर्भर करता है। Dijkstra कम-मेमोरी स्थितियों में भी काम नहीं करेगा, जबकि IDA * होगा।
झबरा मेंढक

मुझे यहाँ स्लाइड्स मिलीं
davidtbernal

7

दिजाक्षर A * के लिए एक विशेष मामला है।

दिज्क्स्त्र आरंभ नोड से अन्य सभी के लिए न्यूनतम लागत पाता है। A * प्रारंभ नोड से लक्ष्य नोड तक न्यूनतम लागत पाता है।

डिज्कस्ट्रा के एल्गोरिथ्म का उपयोग पथ खोजने के लिए कभी नहीं किया जाएगा। ए * का उपयोग करके एक सभ्य विधर्मी के साथ आ सकता है। खोज स्थान के आधार पर, पुनरावृत्ति A * बेहतर है क्योंकि यह कम मेमोरी का उपयोग करता है।

दिज्क्स्ट्रा के एल्गोरिथ्म का कोड है:

// A C / C++ program for Dijkstra's single source shortest path algorithm.
// The program is for adjacency matrix representation of the graph

#include <stdio.h>
#include <limits.h>

// Number of vertices in the graph
#define V 9

// A utility function to find the vertex with minimum distance value, from
// the set of vertices not yet included in shortest path tree
int minDistance(int dist[], bool sptSet[])
{
 // Initialize min value
 int min = INT_MAX, min_index;

  for (int v = 0; v < V; v++)
   if (sptSet[v] == false && dist[v] <= min)
     min = dist[v], min_index = v;

   return min_index;
}

 int printSolution(int dist[], int n)
 {
  printf("Vertex   Distance from Source\n");
  for (int i = 0; i < V; i++)
     printf("%d \t\t %d\n", i, dist[i]);
  }

void dijkstra(int graph[V][V], int src)
{
 int dist[V];     // The output array.  dist[i] will hold the shortest
                  // distance from src to i

 bool sptSet[V]; // sptSet[i] will true if vertex i is included in shortest
                 // path tree or shortest distance from src to i is finalized

 // Initialize all distances as INFINITE and stpSet[] as false
 for (int i = 0; i < V; i++)
    dist[i] = INT_MAX, sptSet[i] = false;

 // Distance of source vertex from itself is always 0
 dist[src] = 0;

 // Find shortest path for all vertices
 for (int count = 0; count < V-1; count++)
 {
   // Pick the minimum distance vertex from the set of vertices not
   // yet processed. u is always equal to src in first iteration.
   int u = minDistance(dist, sptSet);

   // Mark the picked vertex as processed
   sptSet[u] = true;

   // Update dist value of the adjacent vertices of the picked vertex.
   for (int v = 0; v < V; v++)

     // Update dist[v] only if is not in sptSet, there is an edge from 
     // u to v, and total weight of path from src to  v through u is 
     // smaller than current value of dist[v]
     if (!sptSet[v] && graph[u][v] && dist[u] != INT_MAX 
                                   && dist[u]+graph[u][v] < dist[v])
        dist[v] = dist[u] + graph[u][v];
 }

 // print the constructed distance array
 printSolution(dist, V);
 }

// driver program to test above function
int main()
 {
 /* Let us create the example graph discussed above */
 int graph[V][V] = {{0, 4, 0, 0, 0, 0, 0, 8, 0},
                  {4, 0, 8, 0, 0, 0, 0, 11, 0},
                  {0, 8, 0, 7, 0, 4, 0, 0, 2},
                  {0, 0, 7, 0, 9, 14, 0, 0, 0},
                  {0, 0, 0, 9, 0, 10, 0, 0, 0},
                  {0, 0, 4, 14, 10, 0, 2, 0, 0},
                  {0, 0, 0, 0, 0, 2, 0, 1, 6},
                  {8, 11, 0, 0, 0, 0, 1, 0, 7},
                  {0, 0, 2, 0, 0, 0, 6, 7, 0}
                 };

dijkstra(graph, 0);

return 0;
}

A * एल्गोरिथ्म का कोड है:

class Node:
def __init__(self,value,point):
    self.value = value
    self.point = point
    self.parent = None
    self.H = 0
    self.G = 0
def move_cost(self,other):
    return 0 if self.value == '.' else 1

def children(point,grid):
x,y = point.point
links = [grid[d[0]][d[1]] for d in [(x-1, y),(x,y - 1),(x,y + 1),(x+1,y)]]
return [link for link in links if link.value != '%']
def manhattan(point,point2):
return abs(point.point[0] - point2.point[0]) + abs(point.point[1]-point2.point[0])
def aStar(start, goal, grid):
#The open and closed sets
openset = set()
closedset = set()
#Current point is the starting point
current = start
#Add the starting point to the open set
openset.add(current)
#While the open set is not empty
while openset:
    #Find the item in the open set with the lowest G + H score
    current = min(openset, key=lambda o:o.G + o.H)
    #If it is the item we want, retrace the path and return it
    if current == goal:
        path = []
        while current.parent:
            path.append(current)
            current = current.parent
        path.append(current)
        return path[::-1]
    #Remove the item from the open set
    openset.remove(current)
    #Add it to the closed set
    closedset.add(current)
    #Loop through the node's children/siblings
    for node in children(current,grid):
        #If it is already in the closed set, skip it
        if node in closedset:
            continue
        #Otherwise if it is already in the open set
        if node in openset:
            #Check if we beat the G score 
            new_g = current.G + current.move_cost(node)
            if node.G > new_g:
                #If so, update the node to have a new parent
                node.G = new_g
                node.parent = current
        else:
            #If it isn't in the open set, calculate the G and H score for the node
            node.G = current.G + current.move_cost(node)
            node.H = manhattan(node, goal)
            #Set the parent to our current item
            node.parent = current
            #Add it to the set
            openset.add(node)
    #Throw an exception if there is no path
    raise ValueError('No Path Found')
def next_move(pacman,food,grid):
#Convert all the points to instances of Node
for x in xrange(len(grid)):
    for y in xrange(len(grid[x])):
        grid[x][y] = Node(grid[x][y],(x,y))
#Get the path
path = aStar(grid[pacman[0]][pacman[1]],grid[food[0]][food[1]],grid)
#Output the path
print len(path) - 1
for node in path:
    x, y = node.point
    print x, y
pacman_x, pacman_y = [ int(i) for i in raw_input().strip().split() ]
food_x, food_y = [ int(i) for i in raw_input().strip().split() ]
x,y = [ int(i) for i in raw_input().strip().split() ]

grid = []
for i in xrange(0, x):
grid.append(list(raw_input().strip()))

next_move((pacman_x, pacman_y),(food_x, food_y), grid)

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

5

दिज्क्स्त्र आरंभ नोड से अन्य सभी के लिए न्यूनतम लागत पाता है। A * प्रारंभ नोड से लक्ष्य नोड तक न्यूनतम लागत पाता है।

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


2
यह सच नहीं है। दो बिंदुओं के बीच सबसे छोटा रास्ता देने के लिए मानक दिज्क्स्त्र का प्रयोग किया जाता है।
एमिल

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

मैं दूसरा @ ईमिल टिप्पणी करता हूं। आपको बस गंतव्य नोड को प्राथमिकता कतार से हटाते समय रोकना है और आपके पास स्रोत से गंतव्य तक का सबसे छोटा रास्ता है। यह वास्तव में मूल एल्गोरिथ्म था।
3

अधिक सटीक रूप से: यदि कोई लक्ष्य निर्दिष्ट किया गया है, तो डायजेक्स्ट्रा उन सभी नोड्स के लिए सबसे छोटा रास्ता खोजता है जो निर्दिष्ट लक्ष्य के पथ से छोटे पथ पर स्थित हैं। A * में हेयुरिस्टिक का उद्देश्य इनमें से कुछ रास्तों को बनाना है। विधर्मी की प्रभावशीलता निर्धारित करती है कि कितने छंटे हुए हैं।
वेल्लोन फ्लिन

@seteropere, लेकिन क्या होगा यदि आपके गंतव्य नोड को खोजा गया अंतिम नोड है? यह निश्चित रूप से कम कुशल है, क्योंकि ए * के आंकड़े और प्राथमिकता वाले नोड्स चुनने से क्या होता है जो यह सुनिश्चित करने में मदद करता है कि खोजा गया नोड नोड सूची में अंतिम नोड नहीं है
नाइट0फैड्रैगन

5

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

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


2

दिज्क्स्ट्रा का एल्गोरिदम निश्चित रूप से सबसे छोटा रास्ता ढूंढता है। दूसरी ओर A * अनुमानी पर निर्भर करता है। इस कारण से ए * डीजकस्ट्रा के एल्गोरिथ्म की तुलना में तेज है और यदि आपके पास एक अच्छा अनुमान है तो अच्छे परिणाम देगा।


4
A * एक ही परिणाम देता है जैसे कि दिक्जस्त्र, लेकिन तेजी से जब आप एक अच्छे विधर्मी का उपयोग करते हैं। A * एल्गोरिदम सही ढंग से काम करने के लिए कुछ शर्तें लगाता है जैसे कि वर्तमान नोड के बीच अनुमानित दूरी और अंतिम नोड वास्तविक दूरी से कम होनी चाहिए।
अलेक्जेंड्रू

4
A * को सबसे छोटा रास्ता देने की गारंटी दी जाती है, जब उत्तराधिकारी को हमेशा स्वीकार किया जाता है (
रॉबर्ट को

1

यदि आप एस्टार के लिए psuedocode को देखते हैं:

foreach y in neighbor_nodes(x)
             if y in closedset
                 continue

जबकि, यदि आप दिज्कस्त्र के लिए समान देखते हैं :

for each neighbor v of u:         
             alt := dist[u] + dist_between(u, v) ;

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

OTOH, दिज्क्स्ट्रा का एल्गोरिथ्म अपने आप को सही करने से कतराता नहीं है, अगर
नोड फिर से पॉप अप होता है।

जो पथ खोजने के लिए एस्टार को तेज और अधिक उपयुक्त बनाना चाहिए


7
यह सच नहीं है: ए * एक से अधिक बार नोड्स को देख सकता है। वास्तव में, दिक्जस्त्र ए * का एक विशेष मामला है ...
एमिल

2
स्पष्टीकरण के लिए इसे जांचें: stackoverflow.com/questions/21441662/…
सर्पिलमून

सभी खोज एल्गोरिदम में एक "फ्रंटियर" और एक "विज़िट सेट" है। विज़िट किए गए सेट में होने के बाद न तो अल्गोरिद्म नोड को पथ को सही करता है: डिज़ाइन द्वारा, वे प्राथमिकता क्रम में सेट किए गए सीमा से सीमा रेखा से नोड्स को स्थानांतरित करते हैं। नोड्स के लिए न्यूनतम ज्ञात दूरी केवल तभी अपडेट की जा सकती है जब वे सीमा पर हों। दिज्क्स्ट्रा का सबसे अच्छा खोज का एक रूप है, और एक बार "विज़िट किए गए" सेट में रखे जाने के बाद एक नोड को कभी भी दोबारा नहीं देखा जाएगा। ए * इस संपत्ति को साझा करता है, और यह एक सहायक अनुमानक का उपयोग करता है जो यह चुनता है कि कौन सी सीमा को प्राथमिकता देना है। en.wikipedia.org/wiki/Dijkstra%27s_algorithm
pygosceles

0

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

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

ए * आमतौर पर डिजास्टर की तुलना में तेज होता है, हालांकि यह हमेशा ऐसा नहीं होगा। वीडियो गेम में आप अक्सर "एक गेम के लिए पर्याप्त पास" उपसर्ग करते हैं। इसलिए A से "करीब पर्याप्त" इष्टतम पथ आमतौर पर पर्याप्त है।


-1

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

A* searchदूसरी तरफ, हेयुरिस्टिक वैल्यूज के साथ मायने रखता है, जिसे आप अपने लक्ष्य के करीब पहुंचने के लिए परिभाषित कर सकते हैं, जैसे कि लक्ष्य के प्रति मैनहट्टन की दूरी। यह या तो इष्टतम या पूर्ण हो सकता है जो हेयुरिस्टिक कारकों पर निर्भर करता है। यदि आपके पास एकल लक्ष्य नोड है, तो यह निश्चित रूप से तेज़ है।

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