Я пытаюсь реализовать алгоритм графа Косараджу, на 3.5m файл строки, где каждая строка - две (разделенные пробелами) Ints, представляющие граф край. Для начала мне нужно создать сводную структуру данных, которая имеет node и списки ее входящих и исходящих ребер. Код ниже достигает этого, но занимает больше минуты, тогда как из сообщений на форуме MOOC видно, что люди, использующие другие языки, заканчивают на < 10 < 10с. (getLines
занимает 10 с по сравнению с менее 1 сек в тестах, о которых я читал.)
Я новичок в Haskell и реализовал метод накопления с использованием foldl'
('
стал прорывом в его завершении вообще), но он чувствует себя довольно императивным в стиле, и я надеюсь, что это причина, по которой он работает медленно. Более того, я в настоящее время планирую использовать аналогичную модель для проведения поиска по глубине, и я боюсь, что все это станет слишком медленным.
Я нашел эту презентацию и blog которые говорят об этих проблемах, но на слишком высоком уровне.
import System.IO
import Control.Monad
import Data.Map.Strict as Map
import Data.List as L
type NodeName = Int
type Edges = [NodeName]
type Explored = Bool
data Node = Node Explored (Edges, Edges) deriving (Show)
type Graph1 = Map NodeName Node
getLines :: FilePath -> IO [[Int]]
getLines = liftM (fmap (fmap read . words) . lines) . readFile
getLines' :: FilePath -> IO [(Int,Int)]
getLines' = liftM (fmap (tuplify2 . fmap read . words) . lines) . readFile
tuplify2 :: [a] -> (a,a)
tuplify2 [x,y] = (x,y)
main = do
list <- getLines "testdata.txt" -- [String]
--list <- getLines "SCC.txt" -- [String]
let
list' = createGraph list
return list'
createGraph :: [[Int]] -> Graph1
createGraph xs = L.foldl' build Map.empty xs
where
build :: Graph1-> [Int] -> Graph1
build = \acc (x:y:_) ->
let tmpAcc = case Map.lookup x acc of
Nothing -> Map.insert x (Node False ([y],[])) acc
Just a -> Map.adjust (\(Node _ (fwd, bck)) -> (Node False ((y:fwd), bck))) x acc
in case Map.lookup y tmpAcc of
Nothing -> Map.insert y (Node False ([],[x])) tmpAcc
Just a -> Map.adjust (\(Node _ (fwd, bck)) -> (Node False (fwd, (x:bck)))) y tmpAcc