#Input parameters
d = 0.85 #Damping factor

class Page:
   def __init__(self):
       self.links = set()
       self.pagerank = None

   def addLink(self,page):
       self.links.add(page)

   def PageRank(self):
       if not self.pagerank:
           raise('Pagerank not set')
       return self.pagerank

page_a = Page()
page_b = Page()
page_c = Page()
page_d = Page()
page_e = Page()
page_f = Page()
page_g = Page()
page_h = Page()

allpages = [page_a,page_b,page_c,page_d,page_e,page_f,page_g,page_h]

#Creating links from page B
page_b.addLink(page_a)
page_b.addLink(page_d)
page_b.addLink(page_e)
page_b.addLink(page_f)

#Creating links from page C
page_c.addLink(page_a)
page_c.addLink(page_g)
page_c.addLink(page_h)

#Giving already known pageranks
page_b.pagerank = 0.6
page_c.pagerank = 0.3


#Finding pagerank for page A.

#Finding pages thank link to page a
linkstoa = [page for page in allpages if page_a in page.links]
pagerank_a = (1-d) + d*(sum([page.PageRank()/len(page.links) for page in linkstoa]))
page_a.pagerank = pagerank_a

print 'The pagerank of page A is',page_a.pagerank

#Add another link from page A to B creating a circular reference
page_a.addLink(page_b)

linkstoa = [page for page in allpages if page_a in page.links]
linkstob = [page for page in allpages if page_b in page.links]

lastpagea = 0
lastpageb = 0
#Running the pagerank algorithm until it converges
while (not lastpagea==page_a.pagerank) or (not lastpageb==page_b.pagerank):
    lastpagea = page_a.pagerank
    lastpageb = page_b.pagerank
    page_a.pagerank = (1-d) + d*(sum([page.PageRank()/len(page.links) for page in linkstoa]))
    page_b.pagerank = (1-d) + d*(sum([page.PageRank()/len(page.links) for page in linkstob]))
    #print 'a',page_a.pagerank
   # print 'b',page_b.pagerank

print 'The pagerank of page A with a circular reference is',page_a.pagerank
print 'The pagerank of page B with a circular reference is',page_b.pagerank
