Hi! I’m exploring how to using processes and tasks to optimize code, and wanted to ask the how you’d go about this for the Elixir version of Google’s PageRank below.
I tried modifying the rank(pages, i)
function to use Task.async
and Task.async_stream
, but both versions took longer to finish than this one (using elixir’s time
functionality).
All help and ideas are appreciated!
pages = [
%{id: 1, links: [2,3], rank: 0.25},
%{id: 2, links: [3], rank: 0.25},
%{id: 3, links: [1], rank: 0.25},
%{id: 4, links: [3], rank: 0.25}
]
# Iterate over pages 60 times
Pagerank.rank(pages, 60)
defmodule Pagerank do
# If iterated 60 times, inspect
def rank(pages, 0), do: IO.inspect(pages)
# Iterate through pages, creating a new list with updated rank each time
def rank(pages, i) do
pages
|> Enum.map(&(calculate_pagerank(&1, pages)))
|> rank(i - 1)
end
# Calculate a page's rank based on pages that link to it, and update
def calculate_pagerank(page, pages) do
d= 0.85
sum =
pages
|> Enum.filter(&(Enum.member?(&1.links, page.id)))
|> Enum.reduce(0, &((&1.rank/length(&1.links)) + &2))
Map.put(page, :rank, (1-d) + (d * sum))
end
end