packages feed

accelerate-examples-1.3.0.0: examples/pagerank/Step.hs

module Step (

  stepRank, Update, PageGraph

) where

import Page
import Data.Array.Accelerate                    as A

type PageGraph = Vector Link

type Update = (PageId, Rank)

{--
-- | Find the page rank contribution of one edge in the page graph.
contribution
        :: Acc (Vector Int)    -- ^ Number of outgoing links for each page.
        -> Acc (Vector Rank)   -- ^ Old ranks vector.
        -> Exp Link   -- ^ A link.
        -> Exp Update -- ^ New rank.
contribution sizes ranks link
  = let (from, to) = unlift link :: (Exp PageId, Exp PageId)
    in lift (to, ranks ! index1 (A.fromIntegral from) / A.fromIntegral (sizes ! index1 (A.fromIntegral from))) :: Exp Update

-- | Updates a vector of ranks by a given vector of updates.
addUpdates
        :: Acc (Vector Rank)   -- ^ Old partial ranks.
        -> Acc (Vector Update) -- ^ Updates.
        -> Acc (Vector Rank)   -- ^ New partial ranks.
addUpdates parRanks updates
 = let
        (to, contr) = A.unzip updates
   in A.permute (+) parRanks (index1 . A.fromIntegral . (to !)) contr

stepRankSeq :: PageGraph
            -> Acc (Vector Int)  -- Sizes.
            -> Acc (Vector Rank) -- Initial ranks.
            -> Acc (Vector Rank) -- Final ranks.
stepRankSeq p sizes ranks
  = let
      zeroes :: Acc (Vector Rank)
      zeroes = A.fill (shape ranks) 0.0

      -- Ignore shape vector.
      addUpdates' :: Acc (Vector Rank) -> Acc (Vector Z) -> Acc (Vector Update) -> Acc (Vector Rank)
      addUpdates' = const . addUpdates

    in A.collect
     $ A.foldSeqFlatten addUpdates' zeroes
     $ A.mapSeq (A.map (contribution sizes ranks))
         (A.toSeq (Z :. Split) (use p))
--}

-- | Perform one iteration step for the internal Page Rank algorithm.
stepRank
        :: Acc PageGraph       -- ^ Part of the pages graph.
        -> Acc (Vector Int)    -- ^ Number of outgoing links for each page.
        -> Acc (Vector Rank)   -- ^ Old ranks vector.
        -> Acc (Vector Rank)   -- ^ Partial ranks vector
        -> Acc (Vector Rank)   -- ^ New ranks vector.

stepRank links sizes ranks parRanks
 = let
        -- pageCount  = A.size sizes

        -- For every link supplied, calculate it's contribution to the page it points to.
        contribution :: Acc (Vector Float)
        contribution = A.generate (A.shape links)
                                  (\ix -> let (from, _) = unlift $ links ! ix :: (Exp PageId, Exp PageId)
                                          in ranks ! index1 (A.fromIntegral from) / A.fromIntegral (sizes ! index1 (A.fromIntegral from)))

        -- Add to the partial ranks the contribution of the supplied links.
        ranks' = A.permute (+) parRanks (\ix -> let (_, to) = unlift $ links ! ix :: (Exp PageId, Exp PageId)
                                                 in Just_ (index1 (A.fromIntegral to))) contribution
        in ranks'