Per i miei studi, devo scrivere la seguente funzione che ottiene il percorso più breve tra due paesi. Ho già già scritto una funzione isRoute che controlla se esiste una connessione tra due paesi e una funzione yieldRoute che restituisce solo una connessione tra due paesi. Ora devo codificare una funzione che restituisce il percorso più breve tra due paesi.Come implementare l'algoritmo Dijkstra in Haskell
Il mio primo approccio era quello di ottenere tutte le connessioni tra i due paesi e quindi ottenere quello più breve, ma ottenere tutte le connessioni è un po 'fastidioso per programmare a mio parere. Ora mi viene in mente l'idea di implementare un algoritmo dijstra, ma in realtà lo trovo abbastanza difficile. Ragazzi, potete darmi qualche idea su come farlo?
Dobbiamo utilizzare questi tipi
type Country = String
type Countries = [Country]
type TravelTime = Integer -- Travel time in minutes
data Connection = Air Country Country TravelTime
| Sea Country Country TravelTime
| Rail Country Country TravelTime
| Road Country Country TravelTime deriving (Eq,Ord,Show)
type Connections = [Connection]
data Itinerary = NoRoute | Route (Connections,TravelTime) deriving (Eq,Ord,Show)
La mia funzione percorso di rendimento che è semplicemente ricerca in ampiezza (non c'è permesso di cambiarle, ma OFC c'è permesso di aggiungere nuovi tipi.): (Sry per i commenti tedeschi)
-- Liefert eine Route falls es eine gibt
yieldRoute :: Connections -> Country -> Country -> Connections
yieldRoute cons start goal
| isRoute cons start goal == False = []
| otherwise = getRoute cons start [] [start] goal
getRoute :: Connections -> Country -> Connections -> Countries -> Country -> Connections
getRoute cons c gone visited target
| (c == target) = gone
| otherwise = if (visit cons c visited) then (getRoute cons (deeper cons c visited) (gone ++ get_conn cons c (deeper cons c visited)) (visited ++ [(deeper cons c visited)]) target) else (getRoute cons (back (drop (length gone -1) gone)) (take (length gone -1) gone) visited target)
-- Geht ein Land zurück
back :: Connections -> Country
back ((Air c1 c2 _):xs) = c1
back ((Sea c1 c2 _):xs) = c1
back ((Rail c1 c2 _):xs) = c1
back ((Road c1 c2 _):xs) = c1
-- Liefert das nächste erreichbare Country
deeper :: Connections -> Country -> Countries -> Country
deeper ((Air c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Sea c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Rail c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
deeper ((Road c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (deeper xs c visited) else c2
| (c2 == c) = if (c1 `elem` visited) then (deeper xs c visited) else c1
| otherwise = deeper xs c visited
-- Liefert eine Connection zwischen zwei Countries
get_conn :: Connections -> Country -> Country -> Connections
get_conn [] _ _ = error "Something went terribly wrong"
get_conn ((Air c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Sea c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Road c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
get_conn ((Rail c1 c2 t):xs) c3 c4
| (c1 == c3) && (c2 == c4) = [(Air c1 c2 t)]
| (c1 == c4) && (c2 == c3) = [(Air c1 c2 t)]
| otherwise = get_conn xs c3 c4
-- Überprüft ob eine besuchbare Connection exestiert
visit :: Connections -> Country -> Countries -> Bool
visit [] _ _ = False
visit ((Air c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Sea c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Rail c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
| otherwise = visit xs c visited
visit ((Road c1 c2 _):xs) c visited
| (c1 == c) = if (c2 `elem` visited) then (visit xs c visited) else True
| (c2 == c) = if (c1 `elem` visited) then (visit xs c visited) else True
Questo devo scrivere ora:
yieldFastestRoute :: Connections -> Country -> Country -> Itinerary
Dijkst ra Algoritmo: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
Il mio primo approccio è stato questo: (come ho detto ho avuto problemi con le getallRoutes)
yieldFastestRoute :: Connections -> Country -> Country -> Itinerary
yieldFastestRoute cons start targ
|(isRoute start targ == False) = NoRoute
|otherwise = (Route (getFastest (getAllRoutes cons start targ)) (sumTT (getFastest (getAllRoutes cons start targ))))
-- Liefert alle Routen zwischen zwei Ländern
getAllRoutes :: Connections -> Country -> Country -> [Connections]
-- Liefert aus einer Reihe von Connections die schnellste zurück
getFastest :: [Connections] -> Connections
getFastest (x:xs) = if ((sumTT x) < sumTT (getFastest xs) || null (getFastest xs)) then x else (getFastest xs)
sumTT :: Connections -> TravelTime
sumTT [] = 0
sumTT ((Air _ _ t): xs) = t ++ sumTT xs
sumTT ((Rail _ _ t): xs) = t ++ sumTT xs
sumTT ((Road _ _ t): xs) = t ++ sumTT xs
sumTT ((Sea _ _ t): xs) = t ++ sumTT xs
Io fondamentalmente voglio sapere che cosa è il modo migliore per attuare Dijkstra in Haskell, o se c'è un altro approccio che potrei seguire.
1. Che cos'è l'algoritmo Dijkstra? 2. Mostraci il tuo tentativo di implementarlo. 3. Chiarisci quale parte della sua implementazione stai trovando difficile. – dave4420
Voglio se c'è un modo non estremamente difficile per implementare dijstra in haskell o se ci sono alcuni approcci più facili per risolvere il problema: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm –
Penso che questa domanda sarebbe essere meglio rispondente se ci si concentra sul chiedere come creare le strutture di dati del grafico appropriate. dopo di ciò, l'implementazione di Dijkstra non dovrebbe essere difficile. Inoltre hai un sacco di codice e questo è un po 'difficile da digerire, specialmente con i commenti tedeschi – hugomg