2012-12-23 11 views
9

मेरे अध्ययनों के लिए मुझे निम्नलिखित कार्य लिखना है जो दो देशों के बीच सबसे छोटा रास्ता प्राप्त करता है। मैंने पहले से ही एक फ़ंक्शन लिखा है रूट जो जांचता है कि क्या दो देशों के बीच कोई कनेक्शन है, और फ़ंक्शन उपज रूट जो केवल दो देशों के बीच कनेक्शन देता है। अब मुझे एक फ़ंक्शन कोड करना है जो दो देशों के बीच सबसे छोटा मार्ग लौटाता है।हास्केल में डिजस्ट्रा एल्गोरिदम को कैसे कार्यान्वित करें

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

हम इन प्रकार का उपयोग करने के

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) 

मेरे उपज मार्ग समारोह है जो केवल पहले खोज चौड़ाई (हम उन्हें बदलने की अनुमति नहीं कर रहे हैं, लेकिन हम नए प्रकार जोड़ने की अनुमति है ओएफसी।): (Sry

yieldFastestRoute :: Connections -> Country -> Country -> Itinerary 

Dijkst: जर्मन टिप्पणी के लिए)

-- 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 

यह एक मैं अब लिखना होगा रा एल्गोरिथ्म: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm

मेरा पहला दृष्टिकोण यह था: (जैसा कि मैंने कहा मैं 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 

मैं मूल रूप से पता करने के लिए क्या हास्केल में डिज्कस्ट्रा लागू करने के लिए सबसे अच्छा तरीका चाहते हैं, या अगर एक और दृष्टिकोण है जिसका मैं पालन कर सकता हूं।

+4

1. डिजस्ट्रा एल्गोरिदम क्या है? 2. इसे लागू करने के लिए हमें अपना प्रयास दिखाएं। 3. स्पष्ट करें कि इसे लागू करने का कौन सा हिस्सा आपको मुश्किल लग रहा है। – dave4420

+0

मैं चाहता हूं कि हैकेल में डिजस्ट्रा को कार्यान्वित करने के लिए अत्यधिक कठिन तरीका नहीं है या यदि समस्या को हल करने के लिए कुछ आसान स्वीकृतियां हैं: http://en.wikipedia.org/wiki/Dijkstra%27s_algorithm –

+0

मुझे लगता है कि यह प्रश्न होगा यदि आप उचित ग्राफ डेटा संरचनाओं को बनाने के तरीके पर विचार करने पर ध्यान केंद्रित करते हैं तो बेहतर जवाबदेह बनें। उसके बाद, डिजस्ट्रा को लागू करना कठिन नहीं होना चाहिए। इसके अलावा आपके पास कोड का एक टन है और यह निगलने में थोड़ा मुश्किल है, विशेष रूप से जर्मन टिप्पणियों के साथ – hugomg

उत्तर

8

वहाँ देने के लिए मदद मिल सकती है वह यह है कि लगता है एंड्रयू गोल्डबर्ग और साइमन पेटन जोन्स द्वारा इस विषय के लिए एक अद्भुत और शानदार परिचय है: http://www.ukuug.org/events/agm2010/ShortestPath.pdf

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

+1

क्या आप उत्तर में प्रासंगिक कोड/बिट्स शामिल कर सकते हैं? –

6

आप एल्गोरिथ्म

यहाँ के महान हिस्सा कोडित की है, हास्केल में मार्टिन Erwig द्वारा एक परियोजना आप कुछ विचारों

-- SP.hs -- Dijkstra's Shortest Path Algorithm (c) 2000 by Martin Erwig 
module SP (
    spTree,spLength,sp,  -- shortest paths 
    dijkstra 
) where 

import qualified Heap as H 
import Graph 
import RootPath 
expand :: Real b => b -> LPath b -> Context a b -> [H.Heap (LPath b)] 
expand d p (_,_,_,s) = map (\(l,v)->H.unit ((v,l+d):p)) s 
dijkstra :: Real b => H.Heap (LPath b) -> Graph a b -> LRTree b 
dijkstra h g | H.isEmpty h || isEmpty g = [] 
dijkstra h g = 
    case match v g of 
     (Just c,g') -> p:dijkstra (H.mergeAll (h':expand d p c)) g' 
     (Nothing,g') -> dijkstra h' g' 
    where ([email protected]((v,d):_),h') = H.splitMin h 

spTree :: Real b => Node -> Graph a b -> LRTree b 
spTree v = dijkstra (H.unit [(v,0)]) 
spLength :: Real b => Node -> Node -> Graph a b -> b 
spLength s t = getDistance t . spTree s 
sp :: Real b => Node -> Node -> Graph a b -> Path 
sp s t = map fst . getLPath t . spTree s 

बाकी modules are here

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