Skip to content

Instantly share code, notes, and snippets.

@konn
Created June 23, 2010 12:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save konn/449888 to your computer and use it in GitHub Desktop.
Save konn/449888 to your computer and use it in GitHub Desktop.
import Control.Monad.RWS
import Data.Graph.Inductive
import Prelude hiding (map, lookup)
import Data.Map hiding (map)
import Data.Maybe (fromJust)
import Control.Monad
map :: (Functor f) => (a -> b) -> f a -> f b
map = fmap
data Env = Env {node :: [Node], from :: Map Node [Node], outdegrees :: Map Node Int}
type RankDic = Map Node Double
type PRMachine = RWS Env () RankDic
lookupEnv :: (Ord a) => (Env -> Map a b) -> a -> PRMachine b
lookupEnv f a = do{ dic<-asks f; return $ fromJust $ lookup a dic}
outdegree :: Node -> PRMachine Int
outdegree = lookupEnv outdegrees
froms :: Node -> PRMachine [Node]
froms = lookupEnv from
currentRank :: Node -> PRMachine Double
currentRank nd = gets (fromJust.lookup nd)
pageRanks :: (Graph gr) => gr a b -> Double -> Double -> RankDic
pageRanks gr epsilon error = fst $ execRWS steps Env{node=nds, from=froms, outdegrees=outdegs} initRanks
where nds = nodes gr
count :: (Num a) => a
count = fromIntegral $ noNodes gr
froms = fromList $ zip nds $ map (pre gr) nds
outdegs = fromList $ zip nds $ map (outdeg gr) nds
initRanks = fromList $ zip nds $ replicate count (1/count)
steps = do
old <- get
new <- calcPageRank epsilon
let cond = foldWithKey (\k a b -> b && ((findWithDefault (1/0) k new)-a < error)) True old
if cond then return new else steps
calcPageRank :: Double -> PRMachine RankDic
calcPageRank epsilon = do
nds <- asks node
dic <- forM nds $ \n -> do
frms <- froms n
ranks <- forM frms $ \m -> do
deg <- outdegree m
rank <- currentRank m
return (rank/fromIntegral deg)
count <- liftM (fromIntegral.length) $ asks node
return (n, epsilon/count + (1-epsilon)*(sum ranks))
let rdic = fromList dic
put rdic
return rdic
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment