无法想象如何在用Haskell编写的Bellmanford代码中给出输入和输出

时间:2017-05-28 16:44:56

标签: haskell io bellman-ford

我是Haskell的新手。我编译了代码并打开了主shell。我不知道如何输入图形的边缘并获得输出。任何帮助将不胜感激。

给定图中的图形和源顶点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

1 个答案:

答案 0 :(得分: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消费的,并且可能会使用ghc -o bellman-ford <your-file>.hs搞砸输入。最好的方法是,作为Davislor,通过在文本文件中编写图形输入(比如说,graph.txt),使用./bellman-ford < graph.txt编译程序,然后将文本文件输入到使用g = new ListenableUndirectedWeightedGraph <String, MyEdge>(MyEdge.class); graphAdapter = new JGraphXAdapter<String, MyEdge>(g); layout = new mxOrganicLayout(graphAdapter); layout.execute(graphAdapter.getDefaultParent()); mxGraphComponent component = new mxGraphComponent(graphAdapter); component.setPreferredSize(new Dimension(dim.width - 50, dim.height - 200)); add(component);

执行

再次,正如Davislor所说,这看起来像某种家庭作业,所以试着仔细检查作业中是否已经需要某种输入文件或类似的东西。