2017-05-28 9 views
1

私はハスケルを初めて利用しています。私はコードをコンパイルし、メインシェルが開きます。私はグラフの端を入力して出力を得る方法を知らない。どんな助けもありがとう。ハスケルで書かれたベルマンフォードコードで入力と出力を与える方法がわかりません

グラフでソース頂点srcを指定すると、与えられたグラフのsrcからすべての頂点までの最短パスを見つけることができます。グラフには負のウェイトエッジが含まれている場合があります。

{-# LANGUAGE BangPatterns #-} 
module Main where 

import Control.DeepSeq 
import Data.Functor 
import Data.Int 
import Data.Vector.Unboxed ((//)) 
import qualified Data.Vector.Unboxed as V 

--import Debug.Trace 

type Vertex = Int 
type Dist = Int32 
type Edge = (Vertex, Vertex, Dist) 
type EdgeVec = V.Vector Edge 
type CostVec = V.Vector Dist 

readEdge :: String -> Edge 
readEdge s = let [v1, v2, w] = words s 
       in (read v1, read v2, read w) 

bfStep :: EdgeVec -> CostVec -> CostVec 
bfStep edges !prev = V.unsafeAccumulate min prev $ V.map mincost edges 
    where 
    mincost :: Edge -> (Int, Int32) 
    mincost (s, h, c) = (h, cost s c) 
    cost w c = let precost = prev `V.unsafeIndex` w 
       in if precost == maxBound then maxBound else precost + c 

mkEdgeVec :: Int -> [String] -> EdgeVec 
mkEdgeVec nvert inp = V.unfoldr step (nvert, inp) 
    where 
    step (n, s:xs) = Just (readEdge s, (n, xs)) 
    step (0, []) = Nothing 
    step (!n, []) = Just ((0, n, 0), (n - 1, [])) 

main :: IO() 
main = do 
    header:body <- lines <$> getContents 
    let nvert = read $ head $ words header 
    let edgelist = mkEdgeVec nvert body 

    let bfbase = V.replicate (nvert + 1) maxBound // [(0, 0)] 
    print $ edgelist `deepseq` "running" 
    let bfout = iterate (bfStep edgelist) bfbase !! nvert 

    let bfcheck = bfStep edgelist bfout 
    let hasCycle = V.any id $ V.zipWith (/=) bfout bfcheck 

    putStrLn $ if hasCycle then "Cycle" else show $ V.minimum bfout 
+0

私はそれを取る "ベルマンフォード"ベルマンフォードのアルゴリズムですか?これは宿題のように聞こえるので、完全な答えではありませんが、割り当ては入力形式を指定していますか? – Davislor

+0

データを含む入力ファイルを作成し、プログラムと同じディレクトリに 'input.txt'と呼んで、コンソールを起動し、実行可能ファイルの名前が' bellmanford'の場合はプログラムを 'bellmanford ' Davislor

答えて

0

見た目では、グラフの表現を含むファイルが必要です。私はそれを自分でテストすることはできませんでしたが、入力にはグラフの頂点の数を持つヘッダーが必要であり、各エッジを記述する各行にトリプルが必要です:原点、終点、終点その縁の重さ。

例えば、3つの頂点のグラフを記述するデータセットは次のようになります:

3  // The graph has 3 vertices 
1 2 0 // The edge from vertex 1 to vertex 2 has a weight of 0 
2 1 5 // The edges are directed, so 2 to 1 has a weight of 5 
1 3 1 
2 3 0 
... 

(私は書いたコメントは、プログラムで解析することができない、彼らはより明確にすることがあることに注意してください

また、ghciを使用することはできません.REPLでは、コンテンツがhGetContentsを使用して消費されている可能性があり、おそらく入力が混乱するためです。 Davislorのように、グラフ入力をテキストファイル(graph.txtと言う)に書き込んで、を使ってプログラムをコンパイルし、./bellman-ford < graph.txt

を使用してテキストファイルを入力します。デイビスラー氏によると、これは何らかの宿題のように見えるので、割り当てに何らかの入力ファイルが必要かどうかを再確認してみてください。

関連する問題