Project (Option 2) - PageRank

Authors:

v1.0 (2014 Fall) Rishi Sharma *, Sahaana Suri *, Kangwook Lee **, Kannan Ramchandran **
v1.1 (2015 Fall) Kabir Chandrasekher *, Max Kanwal *, Kangwook Lee **, Kannan Ramchandran **
v1.2 (2016 Spring) Kabir Chandrasekher, Tony Duan, David Marn, Ashvin Nair, Kangwook Lee, Kannan Ramchandran
v1.3 (2017 Spring) Tavor Baharav, Kabir Chandrasekhar, Sinho Chewi, Andrew Liu, Kamil Nar, David Wang, and Kannan Ramchandran

Introduction

From Wikipedia:

PageRank is an algorithm used by Google Search to rank websites in their search engine results. PageRank was named after Larry Page, one of the founders of Google. PageRank is a way of measuring the importance of website pages. According to Google:

PageRank works by counting the number and quality of links to a page to determine a rough estimate of how important the website is. The underlying assumption is that more important websites are likely to receive more links from other websites.

There are four common frameworks by which academics view Google's PageRank algorithm. The first looks at the social impact, both positive and negative, of immediate access to previously unimaginable knowledge through one centralized terminal. The second, and most mathematical, sees PageRank as a computation of the Singular Value Decomposition (SVD) of the adjacency matrix of the graph formed by the internet, with particular emphasis paid to the first few singular vectors. The third, and most far-reaching, practical technical implication of Google's work is the implementation of algorithms and computation at enormous scale. Much of the computing infrastructure which operates at a global scale deployed today can trace its origins to Google's need to perform SVD on an object as enormous as the Internet. Finally, a more intuitive way to look at the PageRank algorithm is through the lens of a web crawler (or many web crawler) acting as an agent (or agents) in a Markov Chain the size of the web. We will investigate this viewpoint.

This crawler is searching for an approximate "invariant" distribution (why does a true invariant distribution almost certainly not exist?) and will rank pages based on their "probability" in this generated distribution. In order to do so, our crawler chooses to follow a link uniformly at random from the page it is on in order to arrive at a new page, keeping tally of how many times it has visited each page. If this crawler runs for a really, really long time, the fraction of time it has spent on each webpage will approximately be the probability of being on that page (assuming we account for pathologies in the Markov chain which we will discuss soon). We then rank pages in decreasing order of probability.

Alright, great! Let's do stuff. First, visit the following webpage, and see how many web pages can be reached by clicking the links on each page. http://www.eecs.berkeley.edu/~kw1jjang/ee126/1.html

There are total of $8$ pages, and they are connected as follows.

Since we choose a link at uniform from each page, the probability of going between pages $x$ and $y$ is $\Large \frac{\text{# of pages from x to y}}{\text{# of pages leaving x}}$

Thus the Markov chain generated by the web pages above is

and the transition matrix of the Markov chain is

$$ \left( \begin{array}{cccccccc} 0 & \frac{1}{5} & \frac{1}{5} & \frac{1}{5} & \frac{1}{5} & 0 & 0 & \frac{1}{5} \\ \frac{1}{2} & 0 & 0 & 0 & \frac{1}{2} & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \\ 0 & \frac{1}{3} & \frac{1}{3} & \frac{1}{3} & 0 & 0 & 0 & 0 \\ \frac{1}{4} & 0 & \frac{1}{4} & 0 & 0 & 0 & \frac{1}{4} & \frac{1}{4} \\ \frac{1}{4} & \frac{1}{4} & 0 & 0 & \frac{1}{4} & \frac{1}{4} & 0 & 0 \\ \frac{1}{5} & \frac{1}{5} & \frac{1}{5} & \frac{1}{5} & 0 & 0 & \frac{1}{5} & 0 \end{array} \right) $$

$\mathcal{Q}$1. Find the steady-state (invariant/stationary) distribution $\pi$ of the Markov chain above. How do you know that it exists?

The Markov matrix is copied in code below. This might make your computation easier, but you can solve this in any way you wish. (Note: don't forget about the difference between right and left eigenvectors)


In [1]:
import numpy as np
from __future__ import division

P = np.matrix([[0, 1/5, 1/5, 1/5, 1/5, 0, 0, 1/5],
               [1/2, 0, 0, 0, 1/2, 0, 0, 0],
               [0, 1, 0, 0, 0, 0, 0, 0],
               [0, 0, 0, 0, 1, 0, 0, 0],
               [0, 1/3, 1/3, 1/3, 0, 0, 0, 0],
               [1/4,0,1/4,0,0,0,1/4,1/4],
               [1/4, 1/4, 0, 0, 1/4, 1/4, 0, 0],
               [1/5, 1/5, 1/5, 1/5, 0, 0, 1/5, 0]])

P_transpose = P.T

print P


[[ 0.          0.2         0.2         0.2         0.2         0.          0.
   0.2       ]
 [ 0.5         0.          0.          0.          0.5         0.          0.
   0.        ]
 [ 0.          1.          0.          0.          0.          0.          0.
   0.        ]
 [ 0.          0.          0.          0.          1.          0.          0.
   0.        ]
 [ 0.          0.33333333  0.33333333  0.33333333  0.          0.          0.
   0.        ]
 [ 0.25        0.          0.25        0.          0.          0.          0.25
   0.25      ]
 [ 0.25        0.25        0.          0.          0.25        0.25        0.
   0.        ]
 [ 0.2         0.2         0.2         0.2         0.          0.          0.2
   0.        ]]

In [16]:
# Your code here
#I know that the steady state exists because the markov chain is aperiodic, ttma
v, w = np.linalg.eig(P.T)
steadyState = -w.T[np.isclose(np.absolute(v),1)]
print steadyState


[[ 0.30450811-0.j  0.57609642-0.j  0.28681372-0.j  0.28599072-0.j
   0.63823253-0.j  0.00329198-0.j  0.01316792-0.j  0.06172462-0.j]]

In [17]:
np.isclose(steadyState.dot(P),steadyState)


Out[17]:
matrix([[ True,  True,  True,  True,  True,  True,  True,  True]], dtype=bool)

Simulation time!

We now want to empirically test what we solved above by modeling a random user hopping along those webpages.

We will start the user at "1.html" and behave as per the Markov chain above. In the code below, we simulate this and keep track of the average amount of time a user spends in each state. We will expect that after enough iterations, the fraction of time spent in each state should approach the stationary distribution.

We use the parse_links() method to parse all hyperlinks in a page. We use the library Beautiful Soup in order to complete this portion of the lab in order to easiliy parse pages. Once you download the latest release, you must build and install setup.py. Alternatively, use pip or easy_install (help).

Note that this code relies on having Python 2 installed -- it will not work with Python 3.


In [7]:
import re
import sys
import urllib
import urlparse
import random
from bs4 import BeautifulSoup

class MyOpener(urllib.FancyURLopener):
   version = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15'

def domain(url):
    """
    Parse a url to give you the domain.
    """
    # urlparse breaks down the url passed it, and you split the hostname up 
    # ex: hostname="www.google.com" becomes ['www', 'google', 'com']
    hostname = urlparse.urlparse(url).hostname.split(".")
    hostname = ".".join(len(hostname[-2]) < 4 and hostname[-3:] or hostname[-2:])
    return hostname
    
def parse_links(url, url_start):
    """
    Return all the URLs on a page and return the start URL if there is an error or no URLS.
    """
    url_list = []
    myopener = MyOpener()
    try:
        # open, read, and parse the text using beautiful soup
        page = myopener.open(url)
        text = page.read()
        page.close()
        soup = BeautifulSoup(text, "html")

        # find all hyperlinks using beautiful soup
        for tag in soup.findAll('a', href=True):
            # concatenate the base url with the path from the hyperlink
            tmp = urlparse.urljoin(url, tag['href'])
            # we want to stay in the berkeley EECS domain (more relevant later)...
            if domain(tmp).endswith('berkeley.edu') and 'eecs' in tmp:
                url_list.append(tmp)
        if len(url_list) == 0:
            return [url_start]
        return url_list
    except:
        return [url_start]

In [10]:
url_start = "http://www.eecs.berkeley.edu/~kw1jjang/ee126/1.html"
parse_links(url_start,url_start)


Out[10]:
['http://www.eecs.berkeley.edu/~kw1jjang/ee126/2.html',
 'http://www.eecs.berkeley.edu/~kw1jjang/ee126/3.html',
 'http://www.eecs.berkeley.edu/~kw1jjang/ee126/4.html',
 'http://www.eecs.berkeley.edu/~kw1jjang/ee126/5.html',
 'http://www.eecs.berkeley.edu/~kw1jjang/ee126/8.html']

$\mathcal{Q}$2. Simulating a Random Walk

In the following code block, use the above functions to surf the web pages described by the Markov chain above. This code block may take a while to run. If it is taking more than a couple of minutes, maybe try reducing num_of_visits in order to at least get results. Also, running your code while connected to AirBears may help if you have a slow internet connection at home.


In [11]:
import random

# the url we want to begin with 
url_start = "http://www.eecs.berkeley.edu/~kw1jjang/ee126/1.html"
current_url = url_start

# parameter to set the number of transitions you make/different pages you visit
num_of_visits = 1000

# dictionary of pages visited so far
visit_history = {}

# initialize dictionary since we know exactly where we'll end up
for i in range(1, 9):
    page = "http://www.eecs.berkeley.edu/~kw1jjang/ee126/" + str(i) + ".html"
    visit_history[page] = 0

for i in range(num_of_visits):
    # Your code here
    if i % 10 == 0:
        print i
    visit_history[current_url] += 1
    current_url = np.random.choice(parse_links(current_url,url_start))


0
10
20
30
40
50
60
70
80
90
100
110
120
130
140
150
160
170
180
190
200
210
220
230
240
250
260
270
280
290
300
310
320
330
340
350
360
370
380
390
400
410
420
430
440
450
460
470
480
490
500
510
520
530
540
550
560
570
580
590
600
610
620
630
640
650
660
670
680
690
700
710
720
730
740
750
760
770
780
790
800
810
820
830
840
850
860
870
880
890
900
910
920
930
940
950
960
970
980
990

Print your results:


In [12]:
for i in range(1, 9):
    page = "http://www.eecs.berkeley.edu/~kw1jjang/ee126/" + str(i) + ".html"
    print 'Fraction of time staying on page %d is %f' % (i, float(visit_history[page])/num_of_visits)


Fraction of time staying on page 1 is 0.148000
Fraction of time staying on page 2 is 0.260000
Fraction of time staying on page 3 is 0.112000
Fraction of time staying on page 4 is 0.142000
Fraction of time staying on page 5 is 0.301000
Fraction of time staying on page 6 is 0.000000
Fraction of time staying on page 7 is 0.008000
Fraction of time staying on page 8 is 0.029000

In [27]:
print steadyState/np.sum(steadyState)


[[ 0.14033757-0.j  0.26550351-0.j  0.13218282-0.j  0.13180353-0.j
   0.29413996-0.j  0.00151716-0.j  0.00606865-0.j  0.02844680-0.j]]

Does this approximately match the invariant distribution you expected?

Generalizing to the Web

The toy websites given above conveniently form an irreducible Markov chain (look up what this means if you do not remember from class), but most of the web will not look like this. There will be fringes of the internet containing only self-loops, or some web pages which do not link to others at all. In order to account for such pathologies in the web, we need to make a more intelligent surfer. The simplest idea would be to just jump back to the starting page if there are no links found on the page you are on, and to always return to a "good" starting point with probability $p$ on every page.

This is a very naive scheme, and there are many more intelligent methods by which you can sample from the distribution of the Internet, accounting for its pathologies and all.

Ranking Berkeley Professors

The following code is a (weak) attempt to rank the Berkeley faculty based on a crawler which begins on the EECS research homepage.


In [28]:
url_start = "http://www.eecs.berkeley.edu/Research/"
current_url = url_start
num_of_visits = 200

#List of professors obtained from the EECS page
profs = ['Abbeel','Agrawala','Alon','Anantharam','Arcak','Arias','Asanović','Bachrach','Bajcsy','Bodik','Bokor','Boser','Brewer','Canny','Chang-Hasnain','Culler','Darrell','Demmel','Fearing','Fox','Franklin','Garcia','Goldberg','Hartmann','Harvey','Hellerstein','Javey','Joseph','Katz','Keutzer','Liu','Klein','Kubiatowicz','Lee','Lustig','Maharbiz','Malik','Nguyen','Niknejad','Nikolic',"O'Brien",'Parekh','Patterson','Paxson','Pisano','Rabaey','Ramchandran','Roychowdhury','Russell','Sahai','Salahuddin','Sanders','Sangiovanni-Vincentelli','Sastry','Sen','Seshia','Shenker','Song','Song','Spanos','Stoica','Stojanovic','Tomlin','Tygar','Walrand','Wawrzynek','Wu','Yablonovitch','Yelick','Zakhor']
#Bad URLs help take care of some pathologies that ruin our surfing
bad_urls = ['http://www.erso.berkeley.edu/','http://www.eecs.berkeley.edu/Rosters/roster.name.nostudentee.html','http://www.eecs.berkeley.edu/Resguide/admin.shtml#aliases','http://www.eecs.berkeley.edu/department/EECSbrochure/c1-s3.html']

#Creating a dictionary to keep track of how often we come across a professor
profdict = {}
for i in profs:
    profdict[i] = 0

for i in range(num_of_visits):
    print  i , ' Visiting... ', current_url
    if random.random() < 0.95: #follow a link!
        url_list = parse_links(current_url, url_start)
        updated = False
        while not updated:
            current_url = random.choice(url_list)
            updated = True
            if current_url in bad_urls or "iris" in current_url or "Deptonly" in current_url or "anchor" in current_url or "erso" in current_url: #dealing with more pathologies:
                updated = False
        myopener = MyOpener()
        page = myopener.open(current_url)
        text = page.read()
        page.close()
        #Figuring out which professor is mentioned on a page.
        for p in profs:
            profdict[p]+= 1 if " " + p + " " in text else 0 #can use regex re.findall(i,text), but it's overkill
    else: #click the "home" button!
        current_url = url_start


0  Visiting...  http://www.eecs.berkeley.edu/Research/
1  Visiting...  http://www.eecs.berkeley.edu/about/by-the-numbers
2  Visiting...  https://www2.eecs.berkeley.edu/Faculty/Awards/#91
3  Visiting...  https://www2.eecs.berkeley.edu/Faculty/Awards/#16
4  Visiting...  https://eecs.berkeley.edu/resources/students
5  Visiting...  https://eecs.berkeley.edu/resources/undergrads/research
6  Visiting...  http://www.eecs.berkeley.edu/Research/
7  Visiting...  http://www.eecs.berkeley.edu/academics/courses
8  Visiting...  https://eecs.berkeley.edu/industry
9  Visiting...  https://eecs.berkeley.edu/about/visiting
10  Visiting...  http://www.eecs.berkeley.edu/Research/
11  Visiting...  http://www.eecs.berkeley.edu/about/principles-community
12  Visiting...  http://www.eecs.berkeley.edu/Research/
13  Visiting...  http://www.eecs.berkeley.edu/people
14  Visiting...  http://www.eecs.berkeley.edu/academics/undergraduate
15  Visiting...  http://www.eecs.berkeley.edu/Research/
16  Visiting...  http://www.eecs.berkeley.edu/research
17  Visiting...  http://www.eecs.berkeley.edu/connect
18  Visiting...  http://www.eecs.berkeley.edu/connect/support
19  Visiting...  http://www.eecs.berkeley.edu/Research/
20  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/
21  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/Faculty/nikolic.html
22  Visiting...  http://www.eecs.berkeley.edu/Research/
23  Visiting...  http://www.eecs.berkeley.edu/industry/recruit-students
24  Visiting...  http://www.eecs.berkeley.edu/Research/
25  Visiting...  http://www.eecs.berkeley.edu/connect
26  Visiting...  https://eecs.berkeley.edu/resources
27  Visiting...  https://eecs.berkeley.edu/events
28  Visiting...  https://eecs.berkeley.edu/news
29  Visiting...  https://eecs.berkeley.edu/events
30  Visiting...  https://eecs.berkeley.edu/about/history
31  Visiting...  http://www.eecs.berkeley.edu/Research/
32  Visiting...  http://www.eecs.berkeley.edu/Research/
33  Visiting...  http://www.eecs.berkeley.edu/people/leadership
34  Visiting...  http://www.eecs.berkeley.edu/Research/
35  Visiting...  https://eecs.berkeley.edu/
36  Visiting...  https://eecs.berkeley.edu/connect/support
37  Visiting...  http://www.eecs.berkeley.edu/Research/
38  Visiting...  http://www.eecs.berkeley.edu/Research/#main-content
39  Visiting...  http://www.eecs.berkeley.edu/Research/
40  Visiting...  http://www.eecs.berkeley.edu/news
41  Visiting...  https://eecs.berkeley.edu/
42  Visiting...  https://eecs.berkeley.edu/about/history
43  Visiting...  https://eecs.berkeley.edu/resources/facilities
44  Visiting...  http://www.eecs.berkeley.edu/Research/
45  Visiting...  http://www.eecs.berkeley.edu/people/staff
46  Visiting...  http://www.eecs.berkeley.edu/resources/faculty-staff
47  Visiting...  http://www.eecs.berkeley.edu/Research/
48  Visiting...  http://www.eecs.berkeley.edu/people/alumni
49  Visiting...  http://www.eecs.berkeley.edu/Research/
50  Visiting...  https://eecs.berkeley.edu/news
51  Visiting...  https://www2.eecs.berkeley.edu/Directories/directory-nostudents.html
52  Visiting...  http://www.eecs.berkeley.edu/Research/
53  Visiting...  http://www.eecs.berkeley.edu/research
54  Visiting...  http://www.eecs.berkeley.edu/people/students
55  Visiting...  https://eecs.berkeley.edu/
56  Visiting...  https://www2.eecs.berkeley.edu/Research/Areas/
57  Visiting...  https://eecs.berkeley.edu/events
58  Visiting...  https://www2.eecs.berkeley.edu/Research/Areas/Centers/
59  Visiting...  http://www-bsac.eecs.berkeley.edu/
60  Visiting...  http://www-bsac.eecs.berkeley.edu/privateAbstracts
61  Visiting...  https://www-bsac.eecs.berkeley.edu/login/login.php?returnurl=%2FprivateAbstracts&plevel=
62  Visiting...  https://www-bsac.eecs.berkeley.edu/forus/
63  Visiting...  https://www-bsac.eecs.berkeley.edu/login/login.php?returnurl=%2Fforus%2F&plevel=
64  Visiting...  https://www-bsac.eecs.berkeley.edu/
65  Visiting...  https://www-bsac.eecs.berkeley.edu/mysite/otl/
66  Visiting...  https://www-bsac.eecs.berkeley.edu/login/login.php?returnurl=%2Fmysite%2Fotl%2F&plevel=
67  Visiting...  https://www-bsac.eecs.berkeley.edu/calendar/
68  Visiting...  https://www-bsac.eecs.berkeley.edu/calendar/?year=2017&month=04&
69  Visiting...  https://www-bsac.eecs.berkeley.edu/calendar/add_entry.php?date=20170419
70  Visiting...  https://www-bsac.eecs.berkeley.edu/login/login.php?returnurl=%2Fcalendar%2Fadd_entry.php%3Fdate%3D20170419&plevel=
71  Visiting...  https://www-bsac.eecs.berkeley.edu/
72  Visiting...  https://www-bsac.eecs.berkeley.edu/events/8518261163/
73  Visiting...  http://www.eecs.berkeley.edu/Research/
74  Visiting...  http://www.eecs.berkeley.edu/research/colloquium
75  Visiting...  http://www.eecs.berkeley.edu/resources/grads
76  Visiting...  http://www.eecs.berkeley.edu/people/leadership
77  Visiting...  http://www.eecs.berkeley.edu/Research/
78  Visiting...  http://www.eecs.berkeley.edu/Research/
79  Visiting...  http://www.eecs.berkeley.edu/Research/
80  Visiting...  https://www2.eecs.berkeley.edu/Pubs/TechRpts/
81  Visiting...  https://www2.eecs.berkeley.edu/Pubs/TechRpts/Faculty/hodges.html
82  Visiting...  https://eecs.berkeley.edu/about/visiting
83  Visiting...  http://www.eecs.berkeley.edu/Research/
84  Visiting...  http://www.eecs.berkeley.edu/resources/facilities/room-reservations
85  Visiting...  http://www.eecs.berkeley.edu/about/history
86  Visiting...  http://www.eecs.berkeley.edu/academics/courses
87  Visiting...  https://eecs.berkeley.edu/industry
88  Visiting...  https://eecs.berkeley.edu/events
89  Visiting...  https://eecs.berkeley.edu/connect/k-12
90  Visiting...  https://eecs.berkeley.edu/people/faculty
91  Visiting...  https://eecs.berkeley.edu/news
92  Visiting...  https://eecs.berkeley.edu/resources/facilities/room-reservations
93  Visiting...  https://eecs.berkeley.edu/people/leadership
94  Visiting...  http://www.eecs.berkeley.edu/Research/
95  Visiting...  http://www.eecs.berkeley.edu/resources/students
96  Visiting...  https://eecs.berkeley.edu/
97  Visiting...  https://eecs.berkeley.edu/academics
98  Visiting...  https://eecs.berkeley.edu/people/alumni
99  Visiting...  http://www.eecs.berkeley.edu/Research/
100  Visiting...  http://www.eecs.berkeley.edu/academics
101  Visiting...  http://www.eecs.berkeley.edu/research
102  Visiting...  https://www2.eecs.berkeley.edu/Pubs/Patents/
103  Visiting...  https://eecs.berkeley.edu/industry/entrepreneurship
104  Visiting...  http://www.eecs.berkeley.edu/Research/
105  Visiting...  http://www.eecs.berkeley.edu/people/faculty
106  Visiting...  http://www.eecs.berkeley.edu/resources/students
107  Visiting...  http://www.eecs.berkeley.edu/connect/k-12
108  Visiting...  http://www.eecs.berkeley.edu/about
109  Visiting...  https://eecs.berkeley.edu/about/history
110  Visiting...  https://eecs.berkeley.edu/academics/graduate
111  Visiting...  https://eecs.berkeley.edu/connect/support
112  Visiting...  http://www.eecs.berkeley.edu/Research/
113  Visiting...  http://www.eecs.berkeley.edu/connect/support
114  Visiting...  http://www.eecs.berkeley.edu/Research/
115  Visiting...  http://www.eecs.berkeley.edu/academics/courses
116  Visiting...  http://www.eecs.berkeley.edu/Research/
117  Visiting...  http://www.eecs.berkeley.edu/Research/
118  Visiting...  https://www2.eecs.berkeley.edu/Pubs/Patents/
119  Visiting...  http://www.eecs.berkeley.edu/Research/
120  Visiting...  https://eecs.berkeley.edu/academics
121  Visiting...  https://eecs.berkeley.edu/
122  Visiting...  https://eecs.berkeley.edu/events/2017/03/better-understanding-non-convex-methods-machine-learning
123  Visiting...  https://eecs.berkeley.edu/about
124  Visiting...  https://eecs.berkeley.edu/industry
125  Visiting...  https://eecs.berkeley.edu/about
126  Visiting...  https://eecs.berkeley.edu/events
127  Visiting...  https://eecs.berkeley.edu/connect
128  Visiting...  https://eecs.berkeley.edu/people/students
129  Visiting...  https://eecs.berkeley.edu/people/students/awards
130  Visiting...  https://eecs.berkeley.edu/about
131  Visiting...  https://eecs.berkeley.edu/connect/contact
132  Visiting...  http://www.eecs.berkeley.edu/Research/
133  Visiting...  http://www.eecs.berkeley.edu/resources/facilities
134  Visiting...  http://www.eecs.berkeley.edu/Research/
135  Visiting...  http://www.eecs.berkeley.edu/people/staff
136  Visiting...  http://www.eecs.berkeley.edu/people/faculty
137  Visiting...  http://www.eecs.berkeley.edu/research/bears
138  Visiting...  http://www.eecs.berkeley.edu/Research/
139  Visiting...  http://www.eecs.berkeley.edu/Research/
140  Visiting...  http://www.eecs.berkeley.edu/industry/entrepreneurship
141  Visiting...  http://www.eecs.berkeley.edu/Research/
142  Visiting...  http://www.eecs.berkeley.edu/Research/
143  Visiting...  http://www.eecs.berkeley.edu/research/colloquium
144  Visiting...  http://www.eecs.berkeley.edu/resources/visiting-scholars
145  Visiting...  http://www.eecs.berkeley.edu/about/by-the-numbers
146  Visiting...  http://www.eecs.berkeley.edu/academics
147  Visiting...  http://www.eecs.berkeley.edu/connect
148  Visiting...  http://www.eecs.berkeley.edu/academics
149  Visiting...  http://www.eecs.berkeley.edu/connect
150  Visiting...  http://www.eecs.berkeley.edu/people/faculty
151  Visiting...  https://www2.eecs.berkeley.edu/Faculty/Lists/new.html
152  Visiting...  http://www.eecs.berkeley.edu/Research/
153  Visiting...  http://www.eecs.berkeley.edu/Research/
154  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/
155  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/Areas/GR.html
156  Visiting...  http://www.eecs.berkeley.edu/Research/
157  Visiting...  http://www.eecs.berkeley.edu/resources/facilities
158  Visiting...  http://www.eecs.berkeley.edu/Research/
159  Visiting...  http://www.eecs.berkeley.edu/people/faculty
160  Visiting...  https://eecs.berkeley.edu/news?field_eecs_news_topics_target_id_entityreference_filter=66
161  Visiting...  https://eecs.berkeley.edu/connect/k-12
162  Visiting...  https://eecs.berkeley.edu/academics/prospective-women
163  Visiting...  http://www.eecs.berkeley.edu/Research/
164  Visiting...  https://www2.eecs.berkeley.edu/Research/Areas/
165  Visiting...  https://eecs.berkeley.edu/resources/faculty-staff
166  Visiting...  http://www.eecs.berkeley.edu/Research/
167  Visiting...  https://eecs.berkeley.edu/events
168  Visiting...  https://eecs.berkeley.edu/news
169  Visiting...  https://eecs.berkeley.edu/resources/undergrads
170  Visiting...  https://eecs.berkeley.edu/people/students
171  Visiting...  https://eecs.berkeley.edu/people
172  Visiting...  https://eecs.berkeley.edu/
173  Visiting...  https://eecs.berkeley.edu/academics
174  Visiting...  https://www2.eecs.berkeley.edu/Research/Areas/Centers/
175  Visiting...  https://eecs.berkeley.edu/connect/support
176  Visiting...  http://www.eecs.berkeley.edu/Research/
177  Visiting...  http://www.eecs.berkeley.edu/people/alumni
178  Visiting...  http://www.eecs.berkeley.edu/Research/
179  Visiting...  http://www.eecs.berkeley.edu/about/visiting
180  Visiting...  http://www.eecs.berkeley.edu/Research/
181  Visiting...  http://www.eecs.berkeley.edu/connect/contact
182  Visiting...  http://www.eecs.berkeley.edu/Research/
183  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/
184  Visiting...  https://eecs.berkeley.edu/resources/gsis
185  Visiting...  https://eecs.berkeley.edu/events
186  Visiting...  https://eecs.berkeley.edu/research
187  Visiting...  https://www2.eecs.berkeley.edu/Research/Projects/
188  Visiting...  https://eecs.berkeley.edu/
189  Visiting...  https://eecs.berkeley.edu/connect/contact
190  Visiting...  http://www.eecs.berkeley.edu/Research/
191  Visiting...  http://www.eecs.berkeley.edu/about/diversity
192  Visiting...  http://www.eecs.berkeley.edu/Research/
193  Visiting...  http://www.eecs.berkeley.edu/research
194  Visiting...  http://www.eecs.berkeley.edu/about/diversity
195  Visiting...  http://www.eecs.berkeley.edu/Research/
196  Visiting...  https://eecs.berkeley.edu/connect/contact
197  Visiting...  http://www.eecs.berkeley.edu/Research/
198  Visiting...  http://www.eecs.berkeley.edu/resources/facilities
199  Visiting...  http://www.eecs.berkeley.edu/Research/

In [29]:
prof_ranks = [pair[0] for pair in sorted(profdict.items(), key = lambda item: item[1], reverse=True)]
top_score = profdict[prof_ranks[0]]
for i in range(len(prof_ranks)):
    print "%d %f: %s" % (i+1,profdict[prof_ranks[i]]/top_score, prof_ranks[i])


1 1.000000: Patterson
2 0.779661: Arias
3 0.762712: Russell
4 0.271186: Liu
5 0.237288: Zakhor
6 0.220339: Maharbiz
7 0.169492: Joseph
8 0.152542: Javey
9 0.118644: Katz
10 0.118644: Abbeel
11 0.101695: Yelick
12 0.101695: Stoica
13 0.050847: Boser
14 0.050847: Nguyen
15 0.050847: O'Brien
16 0.033898: Nikolic
17 0.033898: Garcia
18 0.033898: Goldberg
19 0.016949: Lee
20 0.016949: Sahai
21 0.016949: Darrell
22 0.016949: Sen
23 0.000000: Walrand
24 0.000000: Niknejad
25 0.000000: Harvey
26 0.000000: Fox
27 0.000000: Shenker
28 0.000000: Sangiovanni-Vincentelli
29 0.000000: Anantharam
30 0.000000: Hellerstein
31 0.000000: Seshia
32 0.000000: Stojanovic
33 0.000000: Sanders
34 0.000000: Paxson
35 0.000000: Ramchandran
36 0.000000: Klein
37 0.000000: Song
38 0.000000: Roychowdhury
39 0.000000: Culler
40 0.000000: Wu
41 0.000000: Rabaey
42 0.000000: Agrawala
43 0.000000: Canny
44 0.000000: Asanović
45 0.000000: Arcak
46 0.000000: Lustig
47 0.000000: Chang-Hasnain
48 0.000000: Keutzer
49 0.000000: Kubiatowicz
50 0.000000: Sastry
51 0.000000: Yablonovitch
52 0.000000: Alon
53 0.000000: Demmel
54 0.000000: Franklin
55 0.000000: Malik
56 0.000000: Bajcsy
57 0.000000: Wawrzynek
58 0.000000: Parekh
59 0.000000: Tomlin
60 0.000000: Bachrach
61 0.000000: Fearing
62 0.000000: Brewer
63 0.000000: Bokor
64 0.000000: Hartmann
65 0.000000: Bodik
66 0.000000: Spanos
67 0.000000: Salahuddin
68 0.000000: Tygar
69 0.000000: Pisano

In [30]:
print 'Top score: ', top_score


Top score:  59

$\mathcal{Q}$3. Try your hand at applying the above idea to a website you personally visit (somewhat) frequently! Do a simple crawl (similar to the above) and see if you can figure out something interesting. (Keep it simple.)


In [ ]:
# Your code here