
Έχω πάντα intrigued από Χάρτης δρομολόγησης, αλλά ποτέ δεν έχω βρει κανένα καλό εισαγωγικό (ή ακόμα και προηγμένες!) Επίπεδο tutorials για αυτό. Πιστεύει κανείς έχει οποιεσδήποτε υποδείξεις, συμβουλές, κλπ;


**Ενημέρωση:** Είμαι κατά κύριο λόγο αναζητούν ενδείξεις για το πώς εφαρμόζεται ένα σύστημα χάρτη (δομές δεδομένων, αλγορίθμων, κλπ).

 
Χάρτης δρομολόγησης, ένα Maps la Google;
========================================



Ρίξτε μια ματιά στο [έργο ανοικτού δρόμου χάρτη](http://www.openstreetmap.org/) για να δούμε πώς αυτό το είδος του πράγματος αντιμετωπίζεται σε ένα έργο αληθινά ελεύθερο λογισμικό με τη χρήση μόνο των χρηστών που παρέχεται και με άδεια τα δεδομένα και να έχουν ένα [wiki που περιέχει πράγματα που μπορεί να σας ενδιαφέρουν](http://wiki.openstreetmap.org/index.php/Main_Page) .


Λίγα χρόνια πίσω τα παιδιά που συμμετέχουν, όπου αρκετά εύκολο και θα απαντήσει σε πολλές ερωτήσεις που είχα τόσο βλέπω κανένα λόγο γιατί ακόμα δεν είναι ένα ωραίο μπουκέτο.

 

Αντί της εκμάθησης APIs για κάθε πάροχο υπηρεσιών χαρτών (όπως gmaps, Ymaps api) καλό να μάθουν του [Mapstraction](http://www.mapstraction.com/doc/)


«Mapstraction είναι μια βιβλιοθήκη που παρέχει ένα κοινό API για διάφορα javascript APIs χαρτογράφηση»


Θα ήθελα να προτείνω να πάτε στο URL και να μάθουν ένα γενικό API. Υπάρχει καλό ποσό για το πώς-ΟΤ πάρα πολύ.

 

Με χάρτη δρομολόγησης, που σημαίνει την εύρεση της συντομότερης διαδρομής κατά μήκος ενός δικτύου δρόμο;


Dijkstra αλγόριθμο συντομότερης διαδρομής είναι το πιο γνωστό. Wikipedia δεν έχει μια κακή intro: <http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm>


Υπάρχει μια βοηθητική εφαρμογή Java εδώ, όπου μπορείτε να το δείτε σε δράση: <http://www.dgp.toronto.edu/people/JamesStewart/270/9798s/Laffra/DijkstraApplet.html> και η Google θα σας οδηγήσει στον πηγαίο κώδικα ακριβώς για οποιοδήποτε Γλώσσα.


Κάθε πραγματική εφαρμογή για τη δημιουργία διαδρομών οδήγηση θα περιλαμβάνει αρκετά στοιχεία σχετικά με το οδικό δίκτυο που περιγράφει ο συνεργάτης του κόστους με διέρχονται συνδέσμους και την ιεραρχία τους κόμβους-οδικού δικτύου, μέση ταχύτητα, προτεραιότητα διασταύρωση, που συνδέει σήμα κυκλοφορίας, απαγορευμένες στροφές κ.λπ.

 

Έχω ακόμα να βρούμε ένα καλό φροντιστήριο για τη δρομολόγηση, αλλά υπάρχουν πολλά κώδικα ως εξής:


Υπάρχουν GPL εφαρμογές δρομολόγησης που χρησιμοποιούν τα δεδομένα Openstreetmap, π.χ. [Gosmore](http://wiki.openstreetmap.org/index.php/Gosmore) που λειτουργεί σε Windows (+ κινητό) και Linux. Υπάρχουν μια σειρά από ενδιαφέρουσες [εφαρμογών που χρησιμοποιούν τα ίδια δεδομένα, αλλά έχει Gosmore μερικές δροσερό χρησιμοποιεί [π.χ. διασύνδεση με τις ιστοσελίδες](http://tile.openstreetmap.nl/~lambertus/routing-world/index.php) .


Το μεγαλύτερο πρόβλημα με δρομολόγηση είναι κακό δεδομένα, και δεν μπορείτε ποτέ να πάρετε αρκετά καλά στοιχεία. Έτσι, αν θέλετε να δοκιμάσετε το κρατήσει το τεστ πολύ τοπική, ώστε να μπορείτε να ελέγχετε καλύτερα τα δεδομένα.

 

Barry Brumitt, ένας από τους μηχανικούς της Google Maps, χαρακτηριστικό εύρημα διαδρομή, έγραψε μια θέση για το θέμα που μπορεί να ενδιαφέρουν:


[Ο δρόμος για την καλύτερη πορεία εύρεσης](http://googleblog.blogspot.com/2007/11/road-to-better-path-finding.html) 
11/06/2007 3:47:00 PM

 

Α * είναι στην πραγματικότητα πολύ πιο κοντά σε αλγορίθμους χαρτογράφησης της παραγωγής. Απαιτεί πολύ λίγο λιγότερο εξερεύνηση σε σύγκριση με το αρχικό αλγόριθμο Dijikstra του.

 

Από εννοιολογικής απόψεως, φανταστείτε ρίχνοντας μια πέτρα σε μια λίμνη και βλέποντας τα κύματα. Οι διαδρομές θα αποτελέσει τη λίμνη και την πέτρα αρχική θέση σας. 


Φυσικά ο αλγόριθμος θα πρέπει να αναζητήσετε κάποιο ποσοστό των n ^ 2 διαδρομές, τα απόσταση n αυξάνεται. Θα σας μεταφέρει στην αρχική θέση και να ελέγξει όλες τις διαθέσιμες διαδρομές από εκείνο το σημείο. Στη συνέχεια, αναδρομικά καλέστε για τα σημεία στο τέλος αυτών των μονοπατιών και ούτω καθεξής.


Μπορείτε να αυξήσετε την απόδοση του, με το να μην διπλή υποστήριξη σε μια πορεία, με το να μην εκ νέου τον έλεγχο των διαδρομών σε ένα σημείο αν έχει ήδη καλυφθεί και από την εγκατάλειψη σε μονοπάτια που παίρνουν πάρα πολύ καιρό.


Ένας εναλλακτικός τρόπος είναι να χρησιμοποιήσετε την προσέγγιση μυρμήγκι φερομόνης, όπου τα μυρμήγκια σέρνεται τυχαία από το σημείο εκκίνησης και να αφήσει ένα ίχνος μυρωδιάς, η οποία κατασκευάζει τα περισσότερα μυρμήγκια περάσουν πάνω από μια συγκεκριμένη διαδρομή. Αν στείλετε (αρκετά) μυρμήγκια τόσο από το σημείο εκκίνησης και τα τελικά σημεία τότε τελικά η διαδρομή με το ισχυρότερο άρωμα θα είναι η συντομότερη. Αυτό οφείλεται στο γεγονός ότι η συντομότερη διαδρομή θα έχει επισκεφθεί περισσότερες φορές σε μια δεδομένη χρονική περίοδο, δεδομένου ότι τα μυρμήγκια με τα πόδια σε ένα ομοιόμορφο ρυθμό.


**EDIT @ Spikie**


Ως περαιτέρω εξήγηση για το πώς να εφαρμόσουν τον αλγόριθμο λίμνη - πιθανές δομές δεδομένων που απαιτούνται τονίζονται:


Θα πρέπει να αποθηκεύσετε το χάρτη ως δίκτυο. Αυτό είναι απλά ένα σύνολο `nodes`και `edges`μεταξύ τους. Ένα σύνολο `nodes`αποτελούν ένα `route`. Μια ακμή ενώνει δύο κόμβους (ενδεχομένως τόσο το ίδιο κόμβο), και έχει ένα συνδεδεμένο `cost`όπως `distance`ή `time`να διασχίσει την άκρη. Μια ακμή μπορεί να είναι είτε είτε να είναι αμφίδρομη ή μονής κατεύθυνσης. Μάλλον πιο απλό να έχουν μόνο αυτοί μονής κατεύθυνσης και να διπλασιαστεί για δύο απλή μετάβαση μεταξύ των κόμβων (δηλαδή το ένα άκρο από το Α στο Β και ένα διαφορετικό για το Β στο Α).


Ως παράδειγμα φανταστείτε τρεις σιδηροδρομικούς σταθμούς τοποθετημένα σε ένα ισόπλευρο τρίγωνο δείχνει προς τα πάνω. Υπάρχουν επίσης τρεις ακόμη σταθμοί καθένα στα μισά του δρόμου μεταξύ τους. Τα άκρα ενταχθούν όλα τα γειτονικά σταθμούς από κοινού, το τελικό διάγραμμα θα έχει τριγώνου που κάθεται στο εσωτερικό του μεγαλύτερου τριγώνου.


κόμβοι Label ξεκινώντας από κάτω αριστερά, που πηγαίνει αριστερά προς τα δεξιά και επάνω, όπως Α, Β, C, D, Ε, F (F στο επάνω μέρος).


Υποθέστε οι ακμές μπορούν να διασχίζονται προς οποιαδήποτε κατεύθυνση. Κάθε ακμή έχει κόστος 1 km.


Εντάξει, έτσι θέλουμε να διαδρομή από το κάτω αριστερά Α στην κορυφή του σταθμού F. Υπάρχουν πολλές πιθανές διαδρομές, συμπεριλαμβανομένων εκείνων που διπλασιαστεί ξανά στον εαυτό τους, π.χ. ABCEBDEF.


Έχουμε λόγο ρουτίνα, `NextNode`που δέχεται ένα `node`και ένα `cost`και το ίδιο απαιτεί για κάθε κόμβο μπορεί να ταξιδέψει σε.


Είναι σαφές ότι αν αφήσουμε αυτή την ρουτίνα χρόνου θα ανακαλύψουν τελικά όλα τα δρομολόγια, συμπεριλαμβανομένων και εκείνων που είναι δυνητικά άπειρο μήκος (π.χ. ABABABAB κλπ). Σταματάμε να συμβεί αυτό, ελέγχοντας κατά το `cost`. Κάθε φορά που επισκέπτεστε ένα κόμβο που δεν έχει επισκεφτεί στο παρελθόν, έχουμε θέσει τόσο το κόστος και τον κόμβο που προήλθε από κατά αυτόν τον κόμβο. Αν ένας κόμβος έχει επισκεφθεί πριν ελέγξετε κατά το υπάρχον κόστος και αν είμαστε φθηνότερα τότε θα ενημερώσει τον κόμβο και να συνεχίσει (αναδρομική ανάκτηση). Αν είμαστε πιο ακριβά, τότε παραλείψτε τη κόμβο. Αν όλοι οι κόμβοι παραλείπονται τότε θα βγείτε από τη ρουτίνα. 


Αν χτυπήσει τον κόμβο-στόχο μας, τότε θα βγείτε από τη ρουτίνα πάρα πολύ.


Με αυτό τον τρόπο όλα τα βιώσιμα δρομολόγια που ελέγχθηκαν, αλλά ουσιαστικά μόνο εκείνοι με το χαμηλότερο κόστος. Μέχρι το τέλος της διαδικασίας κάθε κόμβος θα έχει το χαμηλότερο κόστος για να πάρει σε αυτόν τον κόμβο, συμπεριλαμβανομένου του κόμβου στόχου μας.


Για να πάρετε τη διαδρομή που εργάζονται πίσω από τον κόμβο-στόχο μας. Από τη στιγμή που αποθηκεύεται στον κόμβο που ήρθε μαζί με το κόστος, εμείς απλά hop προς τα πίσω δημιουργώντας τη διαδρομή. Για παράδειγμα μας, θα καταλήξουμε με κάτι σαν:


Κόμβος Α - (Σύνολο) Κόστος 0 - από τον κόμβο Κανένας   

κόμβος Β - Κόστος 1 - από τον κόμβο Α   

Κόμβος Γ - Κόστος 2 - από τον κόμβο Β   

κόμβος D - Κόστος 1 - από τον κόμβο Α   

Κόμβος E - Κόστος 2 - από τον κόμβο D / Κόστος 2 - από τον κόμβο Β (αυτό αποτελεί εξαίρεση, καθώς υπάρχει ίση κόστος)   

Κόμβος F - κόστος 2 - από τον κόμβο D  



Έτσι, η συντομότερη διαδρομή είναι ADF.

 

Μια άλλη σκέψη συμβεί σε μένα σχετικά με το κόστος της κάθε διάσχισης, αλλά θα αυξήσει το χρόνο και την επεξεργαστική ισχύ που απαιτείται για τον υπολογισμό. 


**Παράδειγμα:** Υπάρχουν 3 τρόποι μπορώ να πάρω (όπου ζω) για να πάει από το σημείο Α στο σημείο Β, σύμφωνα με το GoogleMaps. Μονάδες Garmin προσφέρουν κάθε μία από αυτές τις 3 διαδρομές στο `Quickest`υπολογισμό της διαδρομής. Μετά διέρχονται από κάθε μία από αυτές τις διαδρομές πολλές φορές και κατά μέσο όρο (προφανώς θα υπάρξουν λάθη, ανάλογα με την ώρα της ημέρας, ποσότητα καφεΐνης κλπ), πιστεύω ότι οι αλγόριθμοι θα μπορούσαν να λάβουν υπόψη τον αριθμό των στροφές στο δρόμο για το υψηλό επίπεδο της ακρίβειας , **π.χ.**  *ίσιο δρόμο του 1 μιλίου θα είναι πιο γρήγορα από ό, τι σε ένα μίλι δρόμος με απότομες στροφές σε αυτό* . Δεν είναι μια πρακτική πρόταση, αλλά σίγουρα εκείνη που θα χρησιμοποιήσετε για να βελτιώσει το σύνολο λόγω της καθημερινής μου μετακίνηση.

 

Από την εμπειρία μου που εργάζονται σε αυτόν τον τομέα, A * κάνει τη δουλειά του πολύ καλά. Είναι (όπως αναφέρθηκε παραπάνω) πιο γρήγορα από ό, τι ο αλγόριθμος του Dijkstra, αλλά εξακολουθεί να είναι αρκετά απλό για έναν κανόνα αρμόδιο προγραμματιστή να υλοποιήσει και να κατανοήσουν.


Η οικοδόμηση του δικτύου διαδρομή είναι το πιο δύσκολο κομμάτι, αλλά αυτό μπορεί να αναλυθεί σε μια σειρά από απλά βήματα: να πάρει όλους τους δρόμους? ταξινομήσετε τα σημεία σε τάξη? κάνουν ομάδες των ίδιων σημείων σε διαφορετικούς δρόμους σε διασταυρώσεις (κόμβους)? προσθέστε τόξα και στις δύο κατευθύνσεις, όπου οι κόμβοι συνδέουν (ή προς μία κατεύθυνση μόνο για μονόδρομος).


Η Α * ίδιος ο αλγόριθμος είναι [καλά τεκμηριωμένη στη Wikipedia](http://en.wikipedia.org/wiki/A%2a) . Το κλειδί θέση να βελτιστοποιήσει είναι η επιλογή του καλύτερου κόμβου από την ανοικτή λίστα, για το οποίο θα πρέπει να έχετε μια ουρά προτεραιότητας υψηλής απόδοσης. Αν χρησιμοποιείτε C ++ μπορείτε να χρησιμοποιήσετε τον προσαρμογέα STL priority\_queue.


Προσαρμογή του αλγορίθμου σε διαδρομή πάνω από διάφορα μέρη του δικτύου (π.χ., πεζών, αυτοκίνητο, μέσα μαζικής μεταφοράς, κλπ) της ταχύτητας υπέρ, εξ αποστάσεως ή άλλα κριτήρια είναι αρκετά εύκολο. Μπορείτε να το κάνετε αυτό με το γράψιμο φίλτρα για να ελέγξει ποια τμήματα διαδρομής είναι διαθέσιμα, κατά την κατασκευή του δικτύου, και η οποία βάρος έχει εκχωρηθεί σε κάθε μία.

 