Assignment 3

Numerical Optimization & Large Scale Linear Algebra

Professor: P. Vassalos

Stratos Gounidellis, DS3517005

In [1]:
# import necessary libraries
import numpy as np
from scipy import sparse
from numpy.linalg import norm
import time
np.seterr(divide='ignore')
Out[1]:
{'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'}

Methods' Definitions

In [2]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data(data):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    # dictionary having as a key a webpage and as value
    # the number of its invoming edges
    dict_out = {}
    dict_in = {}
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            # fill the dictionary by counting how many times
            # each destination-page has appeared.
            if from_page not in dict_out.keys():
                dict_out[from_page] = 1
            else:
                dict_out[from_page] += 1
            if to_page not in dict_in.keys():
                dict_in[to_page] = [from_page]
            else:
                dict_in[to_page].append(from_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    
    for node in range(nodes):  
        if node not in dict_in.keys():
            dict_in[node] = []

    # initialize a row-based linked list sparse matrix
    # that matrix will be used for the Gauss-Seidel implementation
    # of the PageRank
    D = sparse.lil_matrix((nodes, 1))
    for key in dict_out.keys():
        D[key] = 1/dict_out[key]
    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes, nodes))
    # return the two created matrices
    return csr_m, D, dict_in
In [3]:
def pagerank_galgo(G, alpha=0.85, tol=10**-8):
    # The following implementation is based on: http://infolab.stanford.edu/~ullman/mmds/ch5.pdf.
    # Additionaly, the implementation is based on the lectures of the coures "Data Mining" of 
    # the professor Yannis Kotidis (AUEB).
    # The matrix G is the adjacency matrix with dead-ends and closed communities or spidertraps.
    # Those problems will be tackled during the iterations of the algorithm. In other words, we do  
    # not pre-adjust the matrix P. Instead we reinsert leaked page-rank back into computation.
    
    # compute the number of nodes, the matrix is symmetric
    n = G.shape[0]
    # compute the ratio of the out degree of each node
    # to the alpha
    out_alpha = G.sum(axis=0).T/alpha
    r = np.ones((n,1))/n
    error = 1
    t = 0
    while error > tol:
        t += 1
        r_new = G.dot((r/out_alpha))
        #  L≤alpha due to dead-ends
        L = r_new.sum()
        # re-insert leaked page-rank
        # now all ranks add to one
        r_new += (1-L)/n
        # compute the error as the euclidean norm of the
        # previous ranks and the new ranks
        error = np.linalg.norm(r-r_new)
        # store the new ranks as the ranks of the current
        # iteration
        if t == 2:
            # list to return the nodes that converged from the
            # second iteration
            list_conv = []
            for i in range(r.shape[0]):
                if np.linalg.norm(r[i]-r_new[i]) < tol:
                    list_conv.append(i)
        r = r_new
    return r, t, list_conv
In [4]:
def pagerank_gs(tol, G, D, dict_in, alpha):
    # in that approach a linear system approach is used to solve
    # get the ranks of each webpage
    
    # the initial solution is again given from the uniform distribution
    # i.e. we give equal weights to each webpage
    x_old = np.ones(G.shape[0])/G.shape[0]
    t = 0
    error = 1
    b = 1/G.shape[0]
    D = alpha*D
    x = x_old.copy()
    
    # apply the element-wise formula for the Gauss–Seidel method for 
    # the pagerank. That formula looks a lot like the Jacobi formula 
    # and it is the same with SOR for omega equals to 1. As input it
    # is used the initial matrix P without any preadjustments as well
    # as a dictionary showing all the in-edged of each webpage. In general,
    # the following implementation scheme is based on the paper:
    # http://www.ece.ucsb.edu/~hespanha/published/2018ACC_0753_MS.pdf
    while error > tol:
        t += 1
        for i in range(G.shape[0]):

            sum_before = 0
            sum_after = 0
            for j in dict_in[i]:
                if j < i:
                    sum_before += D.data[j][0] * x[j]

                if j > i:
                    sum_after += D.data[j][0] * x_old[j]

            x[i] = b + sum_before + sum_after

        error = np.linalg.norm(x-x_old)/np.linalg.norm(x)
        if t == 2:
            # list to return the nodes that converged from the
            # second iteration
            list_conv = []
            for i in range(x.shape[0]):
                if np.linalg.norm(x[i]-x_old[i]) < tol:
                    list_conv.append(i)

        print('Iteration:', t, '==> Relative Error:', error)
        x_old = x.copy()

    return x, list_conv

Data Loading

In [5]:
csr_m, D, dict_in = load_data("stanweb.dat")

Question 1a

i. Google's Algorithm - Power method

In [6]:
start_time = time.time()
pr, t, list_conv = pagerank_galgo(csr_m)
print("Time of Pagerank with Google's Algorithm:",
      time.time() - start_time, "seconds")
print ("Number of iterations:", t)
mat_prg = np.asarray(pr).ravel()
Time of Pagerank with Google's Algorithm: 12.071921825408936 seconds
Number of iterations: 72

ii. Solution of the corresponding system - Gauss Seidel

In [40]:
start_time = time.time()
gs, list_convgs = pagerank_gs(10**-8, csr_m, D, dict_in, 0.85)
print("Time of Pagerank with Gauss-Seidel:",
      time.time() - start_time, "seconds")
mat_prgs = np.asarray(gs).ravel()
Iteration: 1 ==> Relative Error: 0.997605864804
Iteration: 2 ==> Relative Error: 0.405410982604
Iteration: 3 ==> Relative Error: 0.220473733399
Iteration: 4 ==> Relative Error: 0.140081576635
Iteration: 5 ==> Relative Error: 0.091657994247
Iteration: 6 ==> Relative Error: 0.0620818940228
Iteration: 7 ==> Relative Error: 0.0428958007111
Iteration: 8 ==> Relative Error: 0.0300712256227
Iteration: 9 ==> Relative Error: 0.0213046475688
Iteration: 10 ==> Relative Error: 0.0152100110466
Iteration: 11 ==> Relative Error: 0.0109212481268
Iteration: 12 ==> Relative Error: 0.00787490996276
Iteration: 13 ==> Relative Error: 0.00569654013327
Iteration: 14 ==> Relative Error: 0.00413075162436
Iteration: 15 ==> Relative Error: 0.00300091286783
Iteration: 16 ==> Relative Error: 0.0021832470942
Iteration: 17 ==> Relative Error: 0.00159017458923
Iteration: 18 ==> Relative Error: 0.00115924626687
Iteration: 19 ==> Relative Error: 0.000845713825258
Iteration: 20 ==> Relative Error: 0.000617347001675
Iteration: 21 ==> Relative Error: 0.000450871954604
Iteration: 22 ==> Relative Error: 0.000329428218355
Iteration: 23 ==> Relative Error: 0.000240785555673
Iteration: 24 ==> Relative Error: 0.000176052019679
Iteration: 25 ==> Relative Error: 0.000128760165195
Iteration: 26 ==> Relative Error: 9.41971535803e-05
Iteration: 27 ==> Relative Error: 6.89295635546e-05
Iteration: 28 ==> Relative Error: 5.04514751382e-05
Iteration: 29 ==> Relative Error: 3.69354300863e-05
Iteration: 30 ==> Relative Error: 2.70460425939e-05
Iteration: 31 ==> Relative Error: 1.98088565102e-05
Iteration: 32 ==> Relative Error: 1.45110989143e-05
Iteration: 33 ==> Relative Error: 1.06324551869e-05
Iteration: 34 ==> Relative Error: 7.79198333925e-06
Iteration: 35 ==> Relative Error: 5.71155359947e-06
Iteration: 36 ==> Relative Error: 4.18734574823e-06
Iteration: 37 ==> Relative Error: 3.0705514705e-06
Iteration: 38 ==> Relative Error: 2.25200887779e-06
Iteration: 39 ==> Relative Error: 1.65203654351e-06
Iteration: 40 ==> Relative Error: 1.21211433199e-06
Iteration: 41 ==> Relative Error: 8.89544911073e-07
Iteration: 42 ==> Relative Error: 6.52927446958e-07
Iteration: 43 ==> Relative Error: 4.79367636949e-07
Iteration: 44 ==> Relative Error: 3.52000716052e-07
Iteration: 45 ==> Relative Error: 2.58543509617e-07
Iteration: 46 ==> Relative Error: 1.89929640488e-07
Iteration: 47 ==> Relative Error: 1.39565521165e-07
Iteration: 48 ==> Relative Error: 1.02572250883e-07
Iteration: 49 ==> Relative Error: 7.54087847464e-08
Iteration: 50 ==> Relative Error: 5.54468211518e-08
Iteration: 51 ==> Relative Error: 4.07839508046e-08
Iteration: 52 ==> Relative Error: 3.00026327694e-08
Iteration: 53 ==> Relative Error: 2.20805210411e-08
Iteration: 54 ==> Relative Error: 1.6252093715e-08
Iteration: 55 ==> Relative Error: 1.19678562618e-08
Iteration: 56 ==> Relative Error: 8.81379738048e-09
Time of Pagerank with Gauss-Seidel: 150.11813950538635 seconds

Comments

The Power method seems to be much faster than the version with the Gauss-Seidel. The results are not the same for both methods. They differ in 121562 ranks.

In [8]:
indices_pr = mat_prg.argsort()[-len(mat_prg):][::-1]
indices_prs = mat_prgs.argsort()[-len(mat_prgs):][::-1]
print("The two aforementioned methods differ in:",
      np.sum(indices_prs[:] != indices_pr[:]), "ranks.")
The two aforementioned methods differ in: 121652 ranks.

Question 1b

In [9]:
start_time = time.time()
pr_99, t, list_conv99 = pagerank_galgo(csr_m, 0.99, 10**-8)
print("Time of Pagerank with Google's Algorithm:",
      time.time() - start_time, "seconds")
print ("Number of iterations:", t)
mat_prg_99 = np.asarray(pr_99).ravel()
Time of Pagerank with Google's Algorithm: 53.69683909416199 seconds
Number of iterations: 1141
In [10]:
start_time = time.time()
gs_99, list_convgs99 = pagerank_gs(10**-8, csr_m, D, dict_in, 0.99)
Iteration: 1 ==> Relative Error: 0.998167825934
Iteration: 2 ==> Relative Error: 0.471859823725
Iteration: 3 ==> Relative Error: 0.310083212753
Iteration: 4 ==> Relative Error: 0.235281331
Iteration: 5 ==> Relative Error: 0.18625685865
Iteration: 6 ==> Relative Error: 0.153530704972
Iteration: 7 ==> Relative Error: 0.130047786617
Iteration: 8 ==> Relative Error: 0.112523707714
Iteration: 9 ==> Relative Error: 0.0989970283992
Iteration: 10 ==> Relative Error: 0.0882611511428
Iteration: 11 ==> Relative Error: 0.0795438356095
Iteration: 12 ==> Relative Error: 0.0723243491142
Iteration: 13 ==> Relative Error: 0.0662486802254
Iteration: 14 ==> Relative Error: 0.0610631684006
Iteration: 15 ==> Relative Error: 0.0565845822735
Iteration: 16 ==> Relative Error: 0.0526761843855
Iteration: 17 ==> Relative Error: 0.0492351293424
Iteration: 18 ==> Relative Error: 0.04618138419
Iteration: 19 ==> Relative Error: 0.0434529686897
Iteration: 20 ==> Relative Error: 0.0410001447924
Iteration: 21 ==> Relative Error: 0.038783299195
Iteration: 22 ==> Relative Error: 0.0367697610242
Iteration: 23 ==> Relative Error: 0.0349330882773
Iteration: 24 ==> Relative Error: 0.0332509992612
Iteration: 25 ==> Relative Error: 0.0317050078645
Iteration: 26 ==> Relative Error: 0.0302793022319
Iteration: 27 ==> Relative Error: 0.0289606303527
Iteration: 28 ==> Relative Error: 0.0277374303979
Iteration: 29 ==> Relative Error: 0.0265999157815
Iteration: 30 ==> Relative Error: 0.0255394503196
Iteration: 31 ==> Relative Error: 0.0245486277087
Iteration: 32 ==> Relative Error: 0.0236207912053
Iteration: 33 ==> Relative Error: 0.0227502805234
Iteration: 34 ==> Relative Error: 0.0219319560202
Iteration: 35 ==> Relative Error: 0.0211613380139
Iteration: 36 ==> Relative Error: 0.0204343560668
Iteration: 37 ==> Relative Error: 0.0197474787723
Iteration: 38 ==> Relative Error: 0.0190974415133
Iteration: 39 ==> Relative Error: 0.0184814071825
Iteration: 40 ==> Relative Error: 0.0178967470655
Iteration: 41 ==> Relative Error: 0.0173411532645
Iteration: 42 ==> Relative Error: 0.0168124437935
Iteration: 43 ==> Relative Error: 0.0163087549872
Iteration: 44 ==> Relative Error: 0.0158283135837
Iteration: 45 ==> Relative Error: 0.0153695497758
Iteration: 46 ==> Relative Error: 0.0149309829619
Iteration: 47 ==> Relative Error: 0.0145113224764
Iteration: 48 ==> Relative Error: 0.0141093244086
Iteration: 49 ==> Relative Error: 0.0137239071477
Iteration: 50 ==> Relative Error: 0.0133540311434
Iteration: 51 ==> Relative Error: 0.0129987813887
Iteration: 52 ==> Relative Error: 0.0126572550262
Iteration: 53 ==> Relative Error: 0.0123286933658
Iteration: 54 ==> Relative Error: 0.0120123436931
Iteration: 55 ==> Relative Error: 0.0117075392372
Iteration: 56 ==> Relative Error: 0.0114136302009
Iteration: 57 ==> Relative Error: 0.0111300553102
Iteration: 58 ==> Relative Error: 0.0108562518045
Iteration: 59 ==> Relative Error: 0.0105917359619
Iteration: 60 ==> Relative Error: 0.0103360262514
Iteration: 61 ==> Relative Error: 0.0100887019587
Iteration: 62 ==> Relative Error: 0.00984932997672
Iteration: 63 ==> Relative Error: 0.00961755584964
Iteration: 64 ==> Relative Error: 0.0093930126905
Iteration: 65 ==> Relative Error: 0.00917537767704
Iteration: 66 ==> Relative Error: 0.00896432580267
Iteration: 67 ==> Relative Error: 0.00875958079347
Iteration: 68 ==> Relative Error: 0.00856085438462
Iteration: 69 ==> Relative Error: 0.00836790306041
Iteration: 70 ==> Relative Error: 0.00818047568172
Iteration: 71 ==> Relative Error: 0.00799835553242
Iteration: 72 ==> Relative Error: 0.00782130994456
Iteration: 73 ==> Relative Error: 0.00764915416231
Iteration: 74 ==> Relative Error: 0.00748168870456
Iteration: 75 ==> Relative Error: 0.00731873987714
Iteration: 76 ==> Relative Error: 0.00716012711203
Iteration: 77 ==> Relative Error: 0.00700569974529
Iteration: 78 ==> Relative Error: 0.00685529440535
Iteration: 79 ==> Relative Error: 0.0067087756964
Iteration: 80 ==> Relative Error: 0.00656599913714
Iteration: 81 ==> Relative Error: 0.0064268418207
Iteration: 82 ==> Relative Error: 0.00629116655223
Iteration: 83 ==> Relative Error: 0.00615886748187
Iteration: 84 ==> Relative Error: 0.00602982576449
Iteration: 85 ==> Relative Error: 0.00590393914278
Iteration: 86 ==> Relative Error: 0.00578109809173
Iteration: 87 ==> Relative Error: 0.00566121285983
Iteration: 88 ==> Relative Error: 0.00554418271295
Iteration: 89 ==> Relative Error: 0.00542992564871
Iteration: 90 ==> Relative Error: 0.00531835143552
Iteration: 91 ==> Relative Error: 0.00520938438163
Iteration: 92 ==> Relative Error: 0.00510293713701
Iteration: 93 ==> Relative Error: 0.00499894389293
Iteration: 94 ==> Relative Error: 0.0048973282631
Iteration: 95 ==> Relative Error: 0.00479802528952
Iteration: 96 ==> Relative Error: 0.00470096356045
Iteration: 97 ==> Relative Error: 0.00460608545451
Iteration: 98 ==> Relative Error: 0.00451332442752
Iteration: 99 ==> Relative Error: 0.00442262711087
Iteration: 100 ==> Relative Error: 0.00433393324757
Iteration: 101 ==> Relative Error: 0.00424719291052
Iteration: 102 ==> Relative Error: 0.00416234694693
Iteration: 103 ==> Relative Error: 0.00407935154888
Iteration: 104 ==> Relative Error: 0.00399815452409
Iteration: 105 ==> Relative Error: 0.00391871196026
Iteration: 106 ==> Relative Error: 0.00384097452714
Iteration: 107 ==> Relative Error: 0.00376490289835
Iteration: 108 ==> Relative Error: 0.00369045064229
Iteration: 109 ==> Relative Error: 0.00361758094147
Iteration: 110 ==> Relative Error: 0.00354625136375
Iteration: 111 ==> Relative Error: 0.00347642711007
Iteration: 112 ==> Relative Error: 0.0034080661386
Iteration: 113 ==> Relative Error: 0.003341137644
Iteration: 114 ==> Relative Error: 0.0032756042159
Iteration: 115 ==> Relative Error: 0.00321143467302
Iteration: 116 ==> Relative Error: 0.00314859337087
Iteration: 117 ==> Relative Error: 0.00308705214505
Iteration: 118 ==> Relative Error: 0.00302677719317
Iteration: 119 ==> Relative Error: 0.00296774193123
Iteration: 120 ==> Relative Error: 0.00290991522898
Iteration: 121 ==> Relative Error: 0.00285327176966
Iteration: 122 ==> Relative Error: 0.00279778053956
Iteration: 123 ==> Relative Error: 0.00274341893836
Iteration: 124 ==> Relative Error: 0.00269015914785
Iteration: 125 ==> Relative Error: 0.00263797817358
Iteration: 126 ==> Relative Error: 0.00258684935803
Iteration: 127 ==> Relative Error: 0.00253675177377
Iteration: 128 ==> Relative Error: 0.00248766000195
Iteration: 129 ==> Relative Error: 0.00243955416974
Iteration: 130 ==> Relative Error: 0.002392410715
Iteration: 131 ==> Relative Error: 0.00234621061093
Iteration: 132 ==> Relative Error: 0.00230093032009
Iteration: 133 ==> Relative Error: 0.00225655272405
Iteration: 134 ==> Relative Error: 0.00221305655307
Iteration: 135 ==> Relative Error: 0.00217042435939
Iteration: 136 ==> Relative Error: 0.00212863567941
Iteration: 137 ==> Relative Error: 0.00208767452791
Iteration: 138 ==> Relative Error: 0.00204752131469
Iteration: 139 ==> Relative Error: 0.00200816079354
Iteration: 140 ==> Relative Error: 0.00196957470535
Iteration: 141 ==> Relative Error: 0.00193174839947
Iteration: 142 ==> Relative Error: 0.00189466362214
Iteration: 143 ==> Relative Error: 0.00185830709789
Iteration: 144 ==> Relative Error: 0.00182266221836
Iteration: 145 ==> Relative Error: 0.00178771546019
Iteration: 146 ==> Relative Error: 0.00175345080125
Iteration: 147 ==> Relative Error: 0.00171985577979
Iteration: 148 ==> Relative Error: 0.00168691501391
Iteration: 149 ==> Relative Error: 0.00165461658095
Iteration: 150 ==> Relative Error: 0.00162294607738
Iteration: 151 ==> Relative Error: 0.00159189201847
Iteration: 152 ==> Relative Error: 0.00156144001271
Iteration: 153 ==> Relative Error: 0.00153157958646
Iteration: 154 ==> Relative Error: 0.00150229756352
Iteration: 155 ==> Relative Error: 0.00147358329644
Iteration: 156 ==> Relative Error: 0.00144542405132
Iteration: 157 ==> Relative Error: 0.00141780996721
Iteration: 158 ==> Relative Error: 0.00139072879432
Iteration: 159 ==> Relative Error: 0.00136417107767
Iteration: 160 ==> Relative Error: 0.00133812530127
Iteration: 161 ==> Relative Error: 0.00131258234342
Iteration: 162 ==> Relative Error: 0.00128753071333
Iteration: 163 ==> Relative Error: 0.00126296204487
Iteration: 164 ==> Relative Error: 0.00123886575804
Iteration: 165 ==> Relative Error: 0.00121523337261
Iteration: 166 ==> Relative Error: 0.00119205465204
Iteration: 167 ==> Relative Error: 0.00116932170847
Iteration: 168 ==> Relative Error: 0.00114702468041
Iteration: 169 ==> Relative Error: 0.00112515599344
Iteration: 170 ==> Relative Error: 0.00110370634552
Iteration: 171 ==> Relative Error: 0.0010826684226
Iteration: 172 ==> Relative Error: 0.00106203296
Iteration: 173 ==> Relative Error: 0.00104179321583
Iteration: 174 ==> Relative Error: 0.00102194061633
Iteration: 175 ==> Relative Error: 0.0010024683506
Iteration: 176 ==> Relative Error: 0.000983368117492
Iteration: 177 ==> Relative Error: 0.000964633558307
Iteration: 178 ==> Relative Error: 0.000946256667973
Iteration: 179 ==> Relative Error: 0.000928231334404
Iteration: 180 ==> Relative Error: 0.000910549984841
Iteration: 181 ==> Relative Error: 0.000893206714617
Iteration: 182 ==> Relative Error: 0.000876193997083
Iteration: 183 ==> Relative Error: 0.000859506365571
Iteration: 184 ==> Relative Error: 0.000843136822978
Iteration: 185 ==> Relative Error: 0.000827079866245
Iteration: 186 ==> Relative Error: 0.000811328718207
Iteration: 187 ==> Relative Error: 0.00079587822479
Iteration: 188 ==> Relative Error: 0.00078072184598
Iteration: 189 ==> Relative Error: 0.000765854624515
Iteration: 190 ==> Relative Error: 0.000751270358204
Iteration: 191 ==> Relative Error: 0.000736964257351
Iteration: 192 ==> Relative Error: 0.000722930170941
Iteration: 193 ==> Relative Error: 0.000709163647641
Iteration: 194 ==> Relative Error: 0.000695658945918
Iteration: 195 ==> Relative Error: 0.000682411600712
Iteration: 196 ==> Relative Error: 0.000669416050059
Iteration: 197 ==> Relative Error: 0.000656668100695
Iteration: 198 ==> Relative Error: 0.00064416238271
Iteration: 199 ==> Relative Error: 0.000631894861561
Iteration: 200 ==> Relative Error: 0.000619860433799
Iteration: 201 ==> Relative Error: 0.000608055201592
Iteration: 202 ==> Relative Error: 0.000596474114596
Iteration: 203 ==> Relative Error: 0.000585113538364
Iteration: 204 ==> Relative Error: 0.000573968741646
Iteration: 205 ==> Relative Error: 0.000563036091383
Iteration: 206 ==> Relative Error: 0.000552311004208
Iteration: 207 ==> Relative Error: 0.000541790060336
Iteration: 208 ==> Relative Error: 0.000531468833237
Iteration: 209 ==> Relative Error: 0.000521344032104
Iteration: 210 ==> Relative Error: 0.000511411442236
Iteration: 211 ==> Relative Error: 0.000501667885117
Iteration: 212 ==> Relative Error: 0.000492109198682
Iteration: 213 ==> Relative Error: 0.000482732410751
Iteration: 214 ==> Relative Error: 0.000473533609609
Iteration: 215 ==> Relative Error: 0.000464509834021
Iteration: 216 ==> Relative Error: 0.000455657294818
Iteration: 217 ==> Relative Error: 0.000446973199157
Iteration: 218 ==> Relative Error: 0.000438453886755
Iteration: 219 ==> Relative Error: 0.000430096670144
Iteration: 220 ==> Relative Error: 0.000421898058556
Iteration: 221 ==> Relative Error: 0.000413855457167
Iteration: 222 ==> Relative Error: 0.000405965425689
Iteration: 223 ==> Relative Error: 0.000398225531811
Iteration: 224 ==> Relative Error: 0.000390632532852
Iteration: 225 ==> Relative Error: 0.00038318401301
Iteration: 226 ==> Relative Error: 0.000375876831599
Iteration: 227 ==> Relative Error: 0.000368708706458
Iteration: 228 ==> Relative Error: 0.000361676603316
Iteration: 229 ==> Relative Error: 0.000354778326416
Iteration: 230 ==> Relative Error: 0.000348010977909
Iteration: 231 ==> Relative Error: 0.000341372438676
Iteration: 232 ==> Relative Error: 0.00033485985811
Iteration: 233 ==> Relative Error: 0.000328471245668
Iteration: 234 ==> Relative Error: 0.000322203907552
Iteration: 235 ==> Relative Error: 0.000316055872515
Iteration: 236 ==> Relative Error: 0.000310024531907
Iteration: 237 ==> Relative Error: 0.000304108020983
Iteration: 238 ==> Relative Error: 0.000298303819266
Iteration: 239 ==> Relative Error: 0.00029261013303
Iteration: 240 ==> Relative Error: 0.000287024552111
Iteration: 241 ==> Relative Error: 0.000281545346272
Iteration: 242 ==> Relative Error: 0.000276170148735
Iteration: 243 ==> Relative Error: 0.00027089733137
Iteration: 244 ==> Relative Error: 0.000265724652436
Iteration: 245 ==> Relative Error: 0.000260650503994
Iteration: 246 ==> Relative Error: 0.000255672715534
Iteration: 247 ==> Relative Error: 0.000250789764277
Iteration: 248 ==> Relative Error: 0.000245999552967
Iteration: 249 ==> Relative Error: 0.000241300617274
Iteration: 250 ==> Relative Error: 0.000236690949509
Iteration: 251 ==> Relative Error: 0.000232169137963
Iteration: 252 ==> Relative Error: 0.000227733214209
Iteration: 253 ==> Relative Error: 0.000223381847875
Iteration: 254 ==> Relative Error: 0.000219113170668
Iteration: 255 ==> Relative Error: 0.000214925872069
Iteration: 256 ==> Relative Error: 0.000210818143455
Iteration: 257 ==> Relative Error: 0.000206788742588
Iteration: 258 ==> Relative Error: 0.000202835921818
Iteration: 259 ==> Relative Error: 0.000198958487042
Iteration: 260 ==> Relative Error: 0.00019515476359
Iteration: 261 ==> Relative Error: 0.000191423600957
Iteration: 262 ==> Relative Error: 0.000187763359591
Iteration: 263 ==> Relative Error: 0.000184172953941
Iteration: 264 ==> Relative Error: 0.000180650824956
Iteration: 265 ==> Relative Error: 0.000177195905841
Iteration: 266 ==> Relative Error: 0.000173806687575
Iteration: 267 ==> Relative Error: 0.00017048215822
Iteration: 268 ==> Relative Error: 0.000167220859583
Iteration: 269 ==> Relative Error: 0.000164021819367
Iteration: 270 ==> Relative Error: 0.000160883639022
Iteration: 271 ==> Relative Error: 0.000157805382351
Iteration: 272 ==> Relative Error: 0.000154785681911
Iteration: 273 ==> Relative Error: 0.000151823653478
Iteration: 274 ==> Relative Error: 0.000148917994563
Iteration: 275 ==> Relative Error: 0.000146067838162
Iteration: 276 ==> Relative Error: 0.000143271923755
Iteration: 277 ==> Relative Error: 0.000140529428484
Iteration: 278 ==> Relative Error: 0.000137839134245
Iteration: 279 ==> Relative Error: 0.000135200250807
Iteration: 280 ==> Relative Error: 0.000132611608942
Iteration: 281 ==> Relative Error: 0.000130072448274
Iteration: 282 ==> Relative Error: 0.000127581626914
Iteration: 283 ==> Relative Error: 0.000125138426137
Iteration: 284 ==> Relative Error: 0.000122741756632
Iteration: 285 ==> Relative Error: 0.000120390915158
Iteration: 286 ==> Relative Error: 0.000118084847622
Iteration: 287 ==> Relative Error: 0.000115822886344
Iteration: 288 ==> Relative Error: 0.000113604012659
Iteration: 289 ==> Relative Error: 0.000111427585721
Iteration: 290 ==> Relative Error: 0.000109292627008
Iteration: 291 ==> Relative Error: 0.000107198520329
Iteration: 292 ==> Relative Error: 0.000105144311036
Iteration: 293 ==> Relative Error: 0.000103129416353
Iteration: 294 ==> Relative Error: 0.000101152924318
Iteration: 295 ==> Relative Error: 9.9214265851e-05
Iteration: 296 ==> Relative Error: 9.73125585499e-05
Iteration: 297 ==> Relative Error: 9.54472620006e-05
Iteration: 298 ==> Relative Error: 9.36175234125e-05
Iteration: 299 ==> Relative Error: 9.18228244107e-05
Iteration: 300 ==> Relative Error: 9.0062345248e-05
Iteration: 301 ==> Relative Error: 8.83355878758e-05
Iteration: 302 ==> Relative Error: 8.66417532795e-05
Iteration: 303 ==> Relative Error: 8.49803702384e-05
Iteration: 304 ==> Relative Error: 8.33506744919e-05
Iteration: 305 ==> Relative Error: 8.17522067721e-05
Iteration: 306 ==> Relative Error: 8.01842276324e-05
Iteration: 307 ==> Relative Error: 7.864630092e-05
Iteration: 308 ==> Relative Error: 7.713771195e-05
Iteration: 309 ==> Relative Error: 7.56580426467e-05
Iteration: 310 ==> Relative Error: 7.42066055761e-05
Iteration: 311 ==> Relative Error: 7.27829993882e-05
Iteration: 312 ==> Relative Error: 7.13865545733e-05
Iteration: 313 ==> Relative Error: 7.00168913271e-05
Iteration: 314 ==> Relative Error: 6.86733685097e-05
Iteration: 315 ==> Relative Error: 6.73556166341e-05
Iteration: 316 ==> Relative Error: 6.60630153931e-05
Iteration: 317 ==> Relative Error: 6.47952139373e-05
Iteration: 318 ==> Relative Error: 6.35516126763e-05
Iteration: 319 ==> Relative Error: 6.23318755635e-05
Iteration: 320 ==> Relative Error: 6.11354255213e-05
Iteration: 321 ==> Relative Error: 5.99619402361e-05
Iteration: 322 ==> Relative Error: 5.88108580702e-05
Iteration: 323 ==> Relative Error: 5.76818740143e-05
Iteration: 324 ==> Relative Error: 5.65744496444e-05
Iteration: 325 ==> Relative Error: 5.54882887743e-05
Iteration: 326 ==> Relative Error: 5.44228704718e-05
Iteration: 327 ==> Relative Error: 5.33779135708e-05
Iteration: 328 ==> Relative Error: 5.23529144817e-05
Iteration: 329 ==> Relative Error: 5.13476041372e-05
Iteration: 330 ==> Relative Error: 5.03614975756e-05
Iteration: 331 ==> Relative Error: 4.93943369809e-05
Iteration: 332 ==> Relative Error: 4.84456506497e-05
Iteration: 333 ==> Relative Error: 4.75151946587e-05
Iteration: 334 ==> Relative Error: 4.6602516345e-05
Iteration: 335 ==> Relative Error: 4.57073792658e-05
Iteration: 336 ==> Relative Error: 4.48293454479e-05
Iteration: 337 ==> Relative Error: 4.39681905467e-05
Iteration: 338 ==> Relative Error: 4.31234911126e-05
Iteration: 339 ==> Relative Error: 4.2295032668e-05
Iteration: 340 ==> Relative Error: 4.1482407202e-05
Iteration: 341 ==> Relative Error: 4.06854094325e-05
Iteration: 342 ==> Relative Error: 3.99036427035e-05
Iteration: 343 ==> Relative Error: 3.91369128801e-05
Iteration: 344 ==> Relative Error: 3.83848389581e-05
Iteration: 345 ==> Relative Error: 3.76472330988e-05
Iteration: 346 ==> Relative Error: 3.69237266371e-05
Iteration: 347 ==> Relative Error: 3.62141414668e-05
Iteration: 348 ==> Relative Error: 3.55181210941e-05
Iteration: 349 ==> Relative Error: 3.48354954408e-05
Iteration: 350 ==> Relative Error: 3.41659208275e-05
Iteration: 351 ==> Relative Error: 3.3509234671e-05
Iteration: 352 ==> Relative Error: 3.28651029978e-05
Iteration: 353 ==> Relative Error: 3.22333721584e-05
Iteration: 354 ==> Relative Error: 3.16137210737e-05
Iteration: 355 ==> Relative Error: 3.10060013586e-05
Iteration: 356 ==> Relative Error: 3.04099023e-05
Iteration: 357 ==> Relative Error: 2.98252833329e-05
Iteration: 358 ==> Relative Error: 2.92518439493e-05
Iteration: 359 ==> Relative Error: 2.86894500986e-05
Iteration: 360 ==> Relative Error: 2.81378119254e-05
Iteration: 361 ==> Relative Error: 2.75968014708e-05
Iteration: 362 ==> Relative Error: 2.70661371606e-05
Iteration: 363 ==> Relative Error: 2.65456981877e-05
Iteration: 364 ==> Relative Error: 2.60352136223e-05
Iteration: 365 ==> Relative Error: 2.55345670286e-05
Iteration: 366 ==> Relative Error: 2.50434961922e-05
Iteration: 367 ==> Relative Error: 2.45618909479e-05
Iteration: 368 ==> Relative Error: 2.40894976423e-05
Iteration: 369 ==> Relative Error: 2.36262113832e-05
Iteration: 370 ==> Relative Error: 2.31717873854e-05
Iteration: 371 ==> Relative Error: 2.27261256912e-05
Iteration: 372 ==> Relative Error: 2.22889885729e-05
Iteration: 373 ==> Relative Error: 2.18602817875e-05
Iteration: 374 ==> Relative Error: 2.1439776413e-05
Iteration: 375 ==> Relative Error: 2.10273818144e-05
Iteration: 376 ==> Relative Error: 2.0622876398e-05
Iteration: 377 ==> Relative Error: 2.02261745477e-05
Iteration: 378 ==> Relative Error: 1.98370618587e-05
Iteration: 379 ==> Relative Error: 1.9455456967e-05
Iteration: 380 ==> Relative Error: 1.90811528613e-05
Iteration: 381 ==> Relative Error: 1.87140721622e-05
Iteration: 382 ==> Relative Error: 1.8354013867e-05
Iteration: 383 ==> Relative Error: 1.80009051526e-05
Iteration: 384 ==> Relative Error: 1.76545523158e-05
Iteration: 385 ==> Relative Error: 1.73148854916e-05
Iteration: 386 ==> Relative Error: 1.69817171445e-05
Iteration: 387 ==> Relative Error: 1.66549814163e-05
Iteration: 388 ==> Relative Error: 1.63344968109e-05
Iteration: 389 ==> Relative Error: 1.60202008882e-05
Iteration: 390 ==> Relative Error: 1.57119183259e-05
Iteration: 391 ==> Relative Error: 1.54095898884e-05
Iteration: 392 ==> Relative Error: 1.51130453648e-05
Iteration: 393 ==> Relative Error: 1.48222291432e-05
Iteration: 394 ==> Relative Error: 1.45369770756e-05
Iteration: 395 ==> Relative Error: 1.42572359616e-05
Iteration: 396 ==> Relative Error: 1.39828468465e-05
Iteration: 397 ==> Relative Error: 1.37137597178e-05
Iteration: 398 ==> Relative Error: 1.3449820701e-05
Iteration: 399 ==> Relative Error: 1.31909825195e-05
Iteration: 400 ==> Relative Error: 1.29370964612e-05
Iteration: 401 ==> Relative Error: 1.26881178157e-05
Iteration: 402 ==> Relative Error: 1.24439022188e-05
Iteration: 403 ==> Relative Error: 1.22044078316e-05
Iteration: 404 ==> Relative Error: 1.19694953361e-05
Iteration: 405 ==> Relative Error: 1.17391248463e-05
Iteration: 406 ==> Relative Error: 1.15131614201e-05
Iteration: 407 ==> Relative Error: 1.12915677003e-05
Iteration: 408 ==> Relative Error: 1.10742130207e-05
Iteration: 409 ==> Relative Error: 1.08610622037e-05
Iteration: 410 ==> Relative Error: 1.06519889076e-05
Iteration: 411 ==> Relative Error: 1.04469599993e-05
Iteration: 412 ==> Relative Error: 1.02458528342e-05
Iteration: 413 ==> Relative Error: 1.00486365471e-05
Iteration: 414 ==> Relative Error: 9.85519270161e-06
Iteration: 415 ==> Relative Error: 9.66549200168e-06
Iteration: 416 ==> Relative Error: 9.47941970308e-06
Iteration: 417 ==> Relative Error: 9.29694850602e-06
Iteration: 418 ==> Relative Error: 9.11796726928e-06
Iteration: 419 ==> Relative Error: 8.94245042036e-06
Iteration: 420 ==> Relative Error: 8.77029044634e-06
Iteration: 421 ==> Relative Error: 8.60146339524e-06
Iteration: 422 ==> Relative Error: 8.43586489676e-06
Iteration: 423 ==> Relative Error: 8.27347278169e-06
Iteration: 424 ==> Relative Error: 8.11418619705e-06
Iteration: 425 ==> Relative Error: 7.95798422495e-06
Iteration: 426 ==> Relative Error: 7.80476913031e-06
Iteration: 427 ==> Relative Error: 7.65452156206e-06
Iteration: 428 ==> Relative Error: 7.50714682553e-06
Iteration: 429 ==> Relative Error: 7.36262693125e-06
Iteration: 430 ==> Relative Error: 7.22087023184e-06
Iteration: 431 ==> Relative Error: 7.08186001298e-06
Iteration: 432 ==> Relative Error: 6.94550730137e-06
Iteration: 433 ==> Relative Error: 6.81179677632e-06
Iteration: 434 ==> Relative Error: 6.68064240963e-06
Iteration: 435 ==> Relative Error: 6.55202986975e-06
Iteration: 436 ==> Relative Error: 6.42587576396e-06
Iteration: 437 ==> Relative Error: 6.30216698402e-06
Iteration: 438 ==> Relative Error: 6.18082270546e-06
Iteration: 439 ==> Relative Error: 6.06183088386e-06
Iteration: 440 ==> Relative Error: 5.94511326038e-06
Iteration: 441 ==> Relative Error: 5.83065878626e-06
Iteration: 442 ==> Relative Error: 5.71839147816e-06
Iteration: 443 ==> Relative Error: 5.60830136973e-06
Iteration: 444 ==> Relative Error: 5.50031494783e-06
Iteration: 445 ==> Relative Error: 5.39442302087e-06
Iteration: 446 ==> Relative Error: 5.29055430705e-06
Iteration: 447 ==> Relative Error: 5.18870056071e-06
Iteration: 448 ==> Relative Error: 5.08879267303e-06
Iteration: 449 ==> Relative Error: 4.9908232233e-06
Iteration: 450 ==> Relative Error: 4.8947252648e-06
Iteration: 451 ==> Relative Error: 4.80049214764e-06
Iteration: 452 ==> Relative Error: 4.7080588633e-06
Iteration: 453 ==> Relative Error: 4.61741959419e-06
Iteration: 454 ==> Relative Error: 4.52851140916e-06
Iteration: 455 ==> Relative Error: 4.44132908958e-06
Iteration: 456 ==> Relative Error: 4.35581159577e-06
Iteration: 457 ==> Relative Error: 4.27195443486e-06
Iteration: 458 ==> Relative Error: 4.18969840703e-06
Iteration: 459 ==> Relative Error: 4.10903965145e-06
Iteration: 460 ==> Relative Error: 4.02992079529e-06
Iteration: 461 ==> Relative Error: 3.95233856758e-06
Iteration: 462 ==> Relative Error: 3.87623724596e-06
Iteration: 463 ==> Relative Error: 3.80161419343e-06
Iteration: 464 ==> Relative Error: 3.72841543948e-06
Iteration: 465 ==> Relative Error: 3.65663880288e-06
Iteration: 466 ==> Relative Error: 3.58623191728e-06
Iteration: 467 ==> Relative Error: 3.51719315223e-06
Iteration: 468 ==> Relative Error: 3.44947170215e-06
Iteration: 469 ==> Relative Error: 3.38306641466e-06
Iteration: 470 ==> Relative Error: 3.31792802998e-06
Iteration: 471 ==> Relative Error: 3.25405583938e-06
Iteration: 472 ==> Relative Error: 3.19140199209e-06
Iteration: 473 ==> Relative Error: 3.12996625561e-06
Iteration: 474 ==> Relative Error: 3.06970225769e-06
Iteration: 475 ==> Relative Error: 3.01061010689e-06
Iteration: 476 ==> Relative Error: 2.95264479487e-06
Iteration: 477 ==> Relative Error: 2.89580684075e-06
Iteration: 478 ==> Relative Error: 2.84005256241e-06
Iteration: 479 ==> Relative Error: 2.785382834e-06
Iteration: 480 ==> Relative Error: 2.73175528347e-06
Iteration: 481 ==> Relative Error: 2.67917111355e-06
Iteration: 482 ==> Relative Error: 2.62758915489e-06
Iteration: 483 ==> Relative Error: 2.57701096157e-06
Iteration: 484 ==> Relative Error: 2.52739661605e-06
Iteration: 485 ==> Relative Error: 2.47874792093e-06
Iteration: 486 ==> Relative Error: 2.43102611913e-06
Iteration: 487 ==> Relative Error: 2.38423331363e-06
Iteration: 488 ==> Relative Error: 2.33833187595e-06
Iteration: 489 ==> Relative Error: 2.29332416685e-06
Iteration: 490 ==> Relative Error: 2.24917367039e-06
Iteration: 491 ==> Relative Error: 2.20588298357e-06
Iteration: 492 ==> Relative Error: 2.16341661947e-06
Iteration: 493 ==> Relative Error: 2.12177742765e-06
Iteration: 494 ==> Relative Error: 2.08093098224e-06
Iteration: 495 ==> Relative Error: 2.04088030848e-06
Iteration: 496 ==> Relative Error: 2.00159197059e-06
Iteration: 497 ==> Relative Error: 1.96306920585e-06
Iteration: 498 ==> Relative Error: 1.92527954125e-06
Iteration: 499 ==> Relative Error: 1.88822639491e-06
Iteration: 500 ==> Relative Error: 1.85187823981e-06
Iteration: 501 ==> Relative Error: 1.8162386587e-06
Iteration: 502 ==> Relative Error: 1.78127700508e-06
Iteration: 503 ==> Relative Error: 1.7469970378e-06
Iteration: 504 ==> Relative Error: 1.71336901179e-06
Iteration: 505 ==> Relative Error: 1.68039680317e-06
Iteration: 506 ==> Relative Error: 1.64805151228e-06
Iteration: 507 ==> Relative Error: 1.61633716053e-06
Iteration: 508 ==> Relative Error: 1.58522566935e-06
Iteration: 509 ==> Relative Error: 1.55472117998e-06
Iteration: 510 ==> Relative Error: 1.5247964223e-06
Iteration: 511 ==> Relative Error: 1.49545564414e-06
Iteration: 512 ==> Relative Error: 1.46667233028e-06
Iteration: 513 ==> Relative Error: 1.4384508452e-06
Iteration: 514 ==> Relative Error: 1.4107654412e-06
Iteration: 515 ==> Relative Error: 1.3836205543e-06
Iteration: 516 ==> Relative Error: 1.35699116013e-06
Iteration: 517 ==> Relative Error: 1.33088178694e-06
Iteration: 518 ==> Relative Error: 1.30526811315e-06
Iteration: 519 ==> Relative Error: 1.28015473998e-06
Iteration: 520 ==> Relative Error: 1.25551803603e-06
Iteration: 521 ==> Relative Error: 1.23136266624e-06
Iteration: 522 ==> Relative Error: 1.20766564635e-06
Iteration: 523 ==> Relative Error: 1.18443171138e-06
Iteration: 524 ==> Relative Error: 1.1616385333e-06
Iteration: 525 ==> Relative Error: 1.13929088257e-06
Iteration: 526 ==> Relative Error: 1.1173670512e-06
Iteration: 527 ==> Relative Error: 1.09587186134e-06
Iteration: 528 ==> Relative Error: 1.07478420708e-06
Iteration: 529 ==> Relative Error: 1.05410894813e-06
Iteration: 530 ==> Relative Error: 1.03382556884e-06
Iteration: 531 ==> Relative Error: 1.0139389581e-06
Iteration: 532 ==> Relative Error: 9.94429158015e-07
Iteration: 533 ==> Relative Error: 9.75301092267e-07
Iteration: 534 ==> Relative Error: 9.56535362921e-07
Iteration: 535 ==> Relative Error: 9.38136903203e-07
Iteration: 536 ==> Relative Error: 9.20086847533e-07
Iteration: 537 ==> Relative Error: 9.02390148854e-07
Iteration: 538 ==> Relative Error: 8.85028459463e-07
Iteration: 539 ==> Relative Error: 8.68006742517e-07
Iteration: 540 ==> Relative Error: 8.51307156237e-07
Iteration: 541 ==> Relative Error: 8.34934667478e-07
Iteration: 542 ==> Relative Error: 8.18871914699e-07
Iteration: 543 ==> Relative Error: 8.03123873069e-07
Iteration: 544 ==> Relative Error: 7.87673661323e-07
Iteration: 545 ==> Relative Error: 7.72526242671e-07
Iteration: 546 ==> Relative Error: 7.576651944e-07
Iteration: 547 ==> Relative Error: 7.43095477234e-07
Iteration: 548 ==> Relative Error: 7.2880111272e-07
Iteration: 549 ==> Relative Error: 7.14787051385e-07
Iteration: 550 ==> Relative Error: 7.01037749903e-07
Iteration: 551 ==> Relative Error: 6.87558143753e-07
Iteration: 552 ==> Relative Error: 6.74333103593e-07
Iteration: 553 ==> Relative Error: 6.61367552786e-07
Iteration: 554 ==> Relative Error: 6.4864677518e-07
Iteration: 555 ==> Relative Error: 6.36175667875e-07
Iteration: 556 ==> Relative Error: 6.2393990905e-07
Iteration: 557 ==> Relative Error: 6.11944375996e-07
Iteration: 558 ==> Relative Error: 6.0017513029e-07
Iteration: 559 ==> Relative Error: 5.88637023632e-07
Iteration: 560 ==> Relative Error: 5.7731649253e-07
Iteration: 561 ==> Relative Error: 5.66218360033e-07
Iteration: 562 ==> Relative Error: 5.55329419848e-07
Iteration: 563 ==> Relative Error: 5.44654468882e-07
Iteration: 564 ==> Relative Error: 5.34180656527e-07
Iteration: 565 ==> Relative Error: 5.23912742361e-07
Iteration: 566 ==> Relative Error: 5.1383821665e-07
Iteration: 567 ==> Relative Error: 5.03961806658e-07
Iteration: 568 ==> Relative Error: 4.94271333733e-07
Iteration: 569 ==> Relative Error: 4.84771489006e-07
Iteration: 570 ==> Relative Error: 4.75450417431e-07
Iteration: 571 ==> Relative Error: 4.66312771258e-07
Iteration: 572 ==> Relative Error: 4.57347005164e-07
Iteration: 573 ==> Relative Error: 4.48557734834e-07
Iteration: 574 ==> Relative Error: 4.39933721404e-07
Iteration: 575 ==> Relative Error: 4.31479536599e-07
Iteration: 576 ==> Relative Error: 4.23184235788e-07
Iteration: 577 ==> Relative Error: 4.15052350418e-07
Iteration: 578 ==> Relative Error: 4.07073222285e-07
Iteration: 579 ==> Relative Error: 3.99251339193e-07
Iteration: 580 ==> Relative Error: 3.91576322472e-07
Iteration: 581 ==> Relative Error: 3.84052615157e-07
Iteration: 582 ==> Relative Error: 3.76670106804e-07
Iteration: 583 ==> Relative Error: 3.69433196706e-07
Iteration: 584 ==> Relative Error: 3.62332039943e-07
Iteration: 585 ==> Relative Error: 3.55370986981e-07
Iteration: 586 ==> Relative Error: 3.48540447898e-07
Iteration: 587 ==> Relative Error: 3.41844727082e-07
Iteration: 588 ==> Relative Error: 3.35274482438e-07
Iteration: 589 ==> Relative Error: 3.28833970857e-07
Iteration: 590 ==> Relative Error: 3.22514092495e-07
Iteration: 591 ==> Relative Error: 3.16319054985e-07
Iteration: 592 ==> Relative Error: 3.10239991184e-07
Iteration: 593 ==> Relative Error: 3.04281061547e-07
Iteration: 594 ==> Relative Error: 2.98433628712e-07
Iteration: 595 ==> Relative Error: 2.92701800982e-07
Iteration: 596 ==> Relative Error: 2.8707716293e-07
Iteration: 597 ==> Relative Error: 2.81563773068e-07
Iteration: 598 ==> Relative Error: 2.76153431782e-07
Iteration: 599 ==> Relative Error: 2.70850147372e-07
Iteration: 600 ==> Relative Error: 2.65645930169e-07
Iteration: 601 ==> Relative Error: 2.60544737337e-07
Iteration: 602 ==> Relative Error: 2.55538781337e-07
Iteration: 603 ==> Relative Error: 2.5063197017e-07
Iteration: 604 ==> Relative Error: 2.45816715537e-07
Iteration: 605 ==> Relative Error: 2.41096872324e-07
Iteration: 606 ==> Relative Error: 2.36465045372e-07
Iteration: 607 ==> Relative Error: 2.31925038516e-07
Iteration: 608 ==> Relative Error: 2.27469643584e-07
Iteration: 609 ==> Relative Error: 2.23102613809e-07
Iteration: 610 ==> Relative Error: 2.1881692348e-07
Iteration: 611 ==> Relative Error: 2.14616273523e-07
Iteration: 612 ==> Relative Error: 2.10493815248e-07
Iteration: 613 ==> Relative Error: 2.06453198983e-07
Iteration: 614 ==> Relative Error: 2.02487749241e-07
Iteration: 615 ==> Relative Error: 1.98601063784e-07
Iteration: 616 ==> Relative Error: 1.94786634869e-07
Iteration: 617 ==> Relative Error: 1.91048009438e-07
Iteration: 618 ==> Relative Error: 1.8737884305e-07
Iteration: 619 ==> Relative Error: 1.83782631079e-07
Iteration: 620 ==> Relative Error: 1.80253188567e-07
Iteration: 621 ==> Relative Error: 1.76793959791e-07
Iteration: 622 ==> Relative Error: 1.73398913235e-07
Iteration: 623 ==> Relative Error: 1.70071443217e-07
Iteration: 624 ==> Relative Error: 1.66805669254e-07
Iteration: 625 ==> Relative Error: 1.63604933818e-07
Iteration: 626 ==> Relative Error: 1.60463503614e-07
Iteration: 627 ==> Relative Error: 1.57384670866e-07
Iteration: 628 ==> Relative Error: 1.54362843944e-07
Iteration: 629 ==> Relative Error: 1.51401265028e-07
Iteration: 630 ==> Relative Error: 1.48494481631e-07
Iteration: 631 ==> Relative Error: 1.45645686396e-07
Iteration: 632 ==> Relative Error: 1.42849561278e-07
Iteration: 633 ==> Relative Error: 1.40109248779e-07
Iteration: 634 ==> Relative Error: 1.37419563414e-07
Iteration: 635 ==> Relative Error: 1.34783598624e-07
Iteration: 636 ==> Relative Error: 1.3219629603e-07
Iteration: 637 ==> Relative Error: 1.29660699904e-07
Iteration: 638 ==> Relative Error: 1.2717187717e-07
Iteration: 639 ==> Relative Error: 1.24732824015e-07
Iteration: 640 ==> Relative Error: 1.22338727908e-07
Iteration: 641 ==> Relative Error: 1.19992537023e-07
Iteration: 642 ==> Relative Error: 1.17689556814e-07
Iteration: 643 ==> Relative Error: 1.15432688153e-07
Iteration: 644 ==> Relative Error: 1.13217351585e-07
Iteration: 645 ==> Relative Error: 1.11046400448e-07
Iteration: 646 ==> Relative Error: 1.08915367471e-07
Iteration: 647 ==> Relative Error: 1.06827058803e-07
Iteration: 648 ==> Relative Error: 1.04777116331e-07
Iteration: 649 ==> Relative Error: 1.02768299881e-07
Iteration: 650 ==> Relative Error: 1.00796358274e-07
Iteration: 651 ==> Relative Error: 9.88640048288e-08
Iteration: 652 ==> Relative Error: 9.69670910947e-08
Iteration: 653 ==> Relative Error: 9.51082859541e-08
Iteration: 654 ==> Relative Error: 9.32835418337e-08
Iteration: 655 ==> Relative Error: 9.14954823021e-08
Iteration: 656 ==> Relative Error: 8.97401579415e-08
Iteration: 657 ==> Relative Error: 8.80201479238e-08
Iteration: 658 ==> Relative Error: 8.63315981373e-08
Iteration: 659 ==> Relative Error: 8.46770439079e-08
Iteration: 660 ==> Relative Error: 8.30527248334e-08
Iteration: 661 ==> Relative Error: 8.14611327345e-08
Iteration: 662 ==> Relative Error: 7.98985973169e-08
Iteration: 663 ==> Relative Error: 7.83675675617e-08
Iteration: 664 ==> Relative Error: 7.68644622437e-08
Iteration: 665 ==> Relative Error: 7.53916879088e-08
Iteration: 666 ==> Relative Error: 7.39457487964e-08
Iteration: 667 ==> Relative Error: 7.25290094664e-08
Iteration: 668 ==> Relative Error: 7.1138058991e-08
Iteration: 669 ==> Relative Error: 6.97752203665e-08
Iteration: 670 ==> Relative Error: 6.84371640639e-08
Iteration: 671 ==> Relative Error: 6.71261723624e-08
Iteration: 672 ==> Relative Error: 6.58389954256e-08
Iteration: 673 ==> Relative Error: 6.45778753358e-08
Iteration: 674 ==> Relative Error: 6.33396403203e-08
Iteration: 675 ==> Relative Error: 6.21264924076e-08
Iteration: 676 ==> Relative Error: 6.09353350372e-08
Iteration: 677 ==> Relative Error: 5.97683315601e-08
Iteration: 678 ==> Relative Error: 5.86224592892e-08
Iteration: 679 ==> Relative Error: 5.74998425553e-08
Iteration: 680 ==> Relative Error: 5.63975307434e-08
Iteration: 681 ==> Relative Error: 5.53176102137e-08
Iteration: 682 ==> Relative Error: 5.42572003726e-08
Iteration: 683 ==> Relative Error: 5.32183498438e-08
Iteration: 684 ==> Relative Error: 5.21982463422e-08
Iteration: 685 ==> Relative Error: 5.11989015363e-08
Iteration: 686 ==> Relative Error: 5.02175699477e-08
Iteration: 687 ==> Relative Error: 4.92562263743e-08
Iteration: 688 ==> Relative Error: 4.83121905019e-08
Iteration: 689 ==> Relative Error: 4.73874008553e-08
Iteration: 690 ==> Relative Error: 4.64792407076e-08
Iteration: 691 ==> Relative Error: 4.55896132276e-08
Iteration: 692 ==> Relative Error: 4.47159632105e-08
Iteration: 693 ==> Relative Error: 4.38601588077e-08
Iteration: 694 ==> Relative Error: 4.30197053313e-08
Iteration: 695 ==> Relative Error: 4.21964363379e-08
Iteration: 696 ==> Relative Error: 4.13879157248e-08
Iteration: 697 ==> Relative Error: 4.05959431537e-08
Iteration: 698 ==> Relative Error: 3.9818139841e-08
Iteration: 699 ==> Relative Error: 3.90562723726e-08
Iteration: 700 ==> Relative Error: 3.83080174782e-08
Iteration: 701 ==> Relative Error: 3.75751087055e-08
Iteration: 702 ==> Relative Error: 3.68552778496e-08
Iteration: 703 ==> Relative Error: 3.61502256942e-08
Iteration: 704 ==> Relative Error: 3.54577368268e-08
Iteration: 705 ==> Relative Error: 3.47794807679e-08
Iteration: 706 ==> Relative Error: 3.41132935905e-08
Iteration: 707 ==> Relative Error: 3.34608136919e-08
Iteration: 708 ==> Relative Error: 3.28199274682e-08
Iteration: 709 ==> Relative Error: 3.2192242223e-08
Iteration: 710 ==> Relative Error: 3.15756944517e-08
Iteration: 711 ==> Relative Error: 3.0971860558e-08
Iteration: 712 ==> Relative Error: 3.03787250293e-08
Iteration: 713 ==> Relative Error: 2.97978346802e-08
Iteration: 714 ==> Relative Error: 2.9227220879e-08
Iteration: 715 ==> Relative Error: 2.86684004709e-08
Iteration: 716 ==> Relative Error: 2.81194516424e-08
Iteration: 717 ==> Relative Error: 2.75818620895e-08
Iteration: 718 ==> Relative Error: 2.70537536904e-08
Iteration: 719 ==> Relative Error: 2.65365867756e-08
Iteration: 720 ==> Relative Error: 2.60285265994e-08
Iteration: 721 ==> Relative Error: 2.55310050808e-08
Iteration: 722 ==> Relative Error: 2.50422303308e-08
Iteration: 723 ==> Relative Error: 2.45636068878e-08
Iteration: 724 ==> Relative Error: 2.4093384197e-08
Iteration: 725 ==> Relative Error: 2.36329396122e-08
Iteration: 726 ==> Relative Error: 2.31805636513e-08
Iteration: 727 ==> Relative Error: 2.27376066785e-08
Iteration: 728 ==> Relative Error: 2.23023983648e-08
Iteration: 729 ==> Relative Error: 2.18762635895e-08
Iteration: 730 ==> Relative Error: 2.14575703763e-08
Iteration: 731 ==> Relative Error: 2.10476178563e-08
Iteration: 732 ==> Relative Error: 2.06448119259e-08
Iteration: 733 ==> Relative Error: 2.02504260039e-08
Iteration: 734 ==> Relative Error: 1.98629031328e-08
Iteration: 735 ==> Relative Error: 1.94834919765e-08
Iteration: 736 ==> Relative Error: 1.9110671068e-08
Iteration: 737 ==> Relative Error: 1.8745665048e-08
Iteration: 738 ==> Relative Error: 1.83869874997e-08
Iteration: 739 ==> Relative Error: 1.8035838587e-08
Iteration: 740 ==> Relative Error: 1.76907665401e-08
Iteration: 741 ==> Relative Error: 1.73529481971e-08
Iteration: 742 ==> Relative Error: 1.70209643983e-08
Iteration: 743 ==> Relative Error: 1.66959693666e-08
Iteration: 744 ==> Relative Error: 1.63765768005e-08
Iteration: 745 ==> Relative Error: 1.60639174861e-08
Iteration: 746 ==> Relative Error: 1.57566373122e-08
Iteration: 747 ==> Relative Error: 1.54558448846e-08
Iteration: 748 ==> Relative Error: 1.51602167962e-08
Iteration: 749 ==> Relative Error: 1.4870839984e-08
Iteration: 750 ==> Relative Error: 1.45864214268e-08
Iteration: 751 ==> Relative Error: 1.43080261411e-08
Iteration: 752 ==> Relative Error: 1.40343908588e-08
Iteration: 753 ==> Relative Error: 1.37665598228e-08
Iteration: 754 ==> Relative Error: 1.35032982805e-08
Iteration: 755 ==> Relative Error: 1.32456298008e-08
Iteration: 756 ==> Relative Error: 1.29923480169e-08
Iteration: 757 ==> Relative Error: 1.2744455622e-08
Iteration: 758 ==> Relative Error: 1.25007744919e-08
Iteration: 759 ==> Relative Error: 1.22622871504e-08
Iteration: 760 ==> Relative Error: 1.20278417936e-08
Iteration: 761 ==> Relative Error: 1.17984015141e-08
Iteration: 762 ==> Relative Error: 1.15728410237e-08
Iteration: 763 ==> Relative Error: 1.1352104334e-08
Iteration: 764 ==> Relative Error: 1.11350916132e-08
Iteration: 765 ==> Relative Error: 1.0922727866e-08
Iteration: 766 ==> Relative Error: 1.07139377114e-08
Iteration: 767 ==> Relative Error: 1.05096283429e-08
Iteration: 768 ==> Relative Error: 1.03087490962e-08
Iteration: 769 ==> Relative Error: 1.01121883519e-08
Iteration: 770 ==> Relative Error: 9.91891941678e-09
In [11]:
print("Time of Pagerank with Gauss-Seidel:",
      time.time() - start_time, "seconds")
mat_prgs_99 = np.asarray(gs_99).ravel()
Time of Pagerank with Gauss-Seidel: 3000.5469558238983 seconds

Comments

We observe that both methods converge slower for alpha=0.99. The Gauss Seidel method for the iterative solution of the system converges much slower that time. Again, the power method seems to be much faster than the version with the Gauss-Seidel.Tthe ranking of the first 50 nodes changed. Apart from the fist most important node, which remains 89072, all the others changed position.

In [12]:
indices_pr_99 = mat_prg_99.argsort()[-len(mat_prg):][::-1]
indices_prs_99 = mat_prgs_99.argsort()[-len(mat_prg):][::-1]
print("The two aforementioned methods differ in:",
      sum(indices_prs_99[:] != indices_pr_99[:]), "ranks.")
The two aforementioned methods differ in: 138038 ranks.
In [13]:
print("We observe differences in:",
      sum(indices_pr[:50] != indices_pr_99[:50]),
      "ranks (power method).")
We observe differences in: 49 ranks (power method).
In [14]:
print("We observe differences in:",
      sum(indices_prs[:50] != indices_prs_99[:50]),
      "ranks (Gauss Seidel).")
We observe differences in: 49 ranks (Gauss Seidel).

Question 1c

We observe that the components of π that correspond to non important converge faster, as it is shown below.

In [15]:
print("When we use the power method",
      len(list_conv),
      "components of π converge at the second iteration.")
When we use the power method 42904 components of π converge at the second iteration.
In [16]:
counter = 0
for node in list_conv:
    if node in indices_pr[:1000]:
        counter += 1
print("From those components of π that converged faster",
      counter,
      "component(s) correspond to the top (1000) ranked nodes (Power method).")
From those components of π that converged faster 0 component(s) correspond to the top (1000) ranked nodes (Power method).
In [17]:
print("When we find π through the solution of the linear system",
      len(list_convgs),
      "components of π converge at the second iteration.")
When we find π through the solution of the linear system 34367 components of π converge at the second iteration.
In [18]:
counter = 0
for node in list_convgs:
    if node in indices_prs[:1000]:
        counter += 1
print("From those components of π that converged faster", counter,
      "component(s) correspond to the top (1000) ranked nodes (Gauss Seidel).")
From those components of π that converged faster 1 component(s) correspond to the top (1000) ranked nodes (Gauss Seidel).

Question 2a

New method definition

In [19]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data1(data):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    

    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    # increase the size of the array by introducing a dangling node, i.e.
    # X
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes + 1, nodes + 1))
    # return the adjacency sparse matrix
    return csr_m
In [20]:
csr_m1 = load_data1("stanweb.dat")
pr1, t1, list_conv1 = pagerank_galgo(csr_m1)

Comments

We observe that the PageRanks of the older pages due to the addition of the new page remain almost unchanged, as they are not connected at all to the newly added page. Additionally, we should also bear in mind that the number of nodes is a very large number. The PageRank of the newly added page is expected from the formula the PageRank is calculated. It is basically only the part (1 - alpha)/n = 0.15/281904.

In [21]:
pageRank_X = np.asarray(pr1[csr_m1.shape[0] - 1]).ravel()[0]
print("The PageRank of page X is:", pageRank_X)
The PageRank of page X is: 5.33365878148e-07
In [22]:
norm_diff = np.linalg.norm(np.asarray(pr[:csr_m.shape[0]].ravel()) - np.asarray(pr1[:csr_m1.shape[0] - 1].ravel()))
print("Change in PageRank of the other pages due to the addition of the new page:", norm_diff)

mat_prg = np.asarray(pr).ravel()
mat_prg1 = np.asarray(pr1[:csr_m1.shape[0] - 1]).ravel()

indices_pr = mat_prg.argsort()[-len(mat_prg):][::-1]
indices_pr1 = mat_prg1.argsort()[-len(mat_prg1):][::-1]
print("Changes in:",
      np.sum(indices_pr[:] != indices_pr1[:]), "ranks.")
Change in PageRank of the other pages due to the addition of the new page: 1.20480863548e-08
Changes in: 50570 ranks.

Question 2b

New method definition

In [23]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data2(data):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    
    # add a new edge Y -> X
    from_pages.append(nodes)
    to_pages.append(nodes + 1)
    # increase the number of nodes by two for X, Y
    nodes += 2
    # increase the number of edges by one
    edges += 1
    
    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes, nodes))
    # return the adjacency sparse matrix
    return csr_m
In [24]:
csr_m2 = load_data2("stanweb.dat")
pr2, t2, list_conv2 = pagerank_galgo(csr_m2)

Comments

We observe that the PageRanks of the older pages changed more that time due to the addition of the new pages. Additionally, we should also bear in mind that the number of nodes is a very large number. The PageRank of the newly added page is expected from the formula the PageRank is calculated. The PageRank of X is obviously improved while the PageRank of Y is the same as page X in the previous question.

In [25]:
pageRank_Xb = np.asarray(pr2[csr_m2.shape[0] - 1]).ravel()[0]
print("The PageRank of page X is:", pageRank_Xb)
The PageRank of page X is: 9.8672590097e-07
In [26]:
pageRank_Yb = np.asarray(pr2[csr_m2.shape[0] - 2]).ravel()[0]
print("The PageRank of page Y is:", pageRank_Yb)
The PageRank of page Y is: 5.33365351862e-07
In [27]:
norm_diff = np.linalg.norm(np.asarray(pr[:csr_m.shape[0]].ravel()) - np.asarray(pr2[:csr_m2.shape[0] - 2].ravel()))
print("Change in PageRank of the other pages due to the addition of the new page:", norm_diff)

mat_prg = np.asarray(pr).ravel()
mat_prg2 = np.asarray(pr2[:csr_m2.shape[0] - 2]).ravel()

indices_pr = mat_prg.argsort()[-len(mat_prg):][::-1]
indices_pr2 = mat_prg2.argsort()[-len(mat_prg2):][::-1]
print("Changes in:",
      np.sum(indices_pr[:] != indices_pr2[:]), "ranks.")
Change in PageRank of the other pages due to the addition of the new page: 3.43370136746e-08
Changes in: 51477 ranks.

Question 2c

In [28]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data3(data):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    
    # add a new edge Y -> X
    from_pages.append(nodes)
    to_pages.append(nodes + 2)
    
    # add a new edge Z -> X
    from_pages.append(nodes + 1)
    to_pages.append(nodes + 2)

    # increases as needed the number of nodes and edges
    nodes += 3
    edges += 2
    
    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes, nodes))
    # return the adjacency sparse matrix
    return csr_m
In [29]:
csr_m3 = load_data3("stanweb.dat")
pr3, t3, list_conv3 = pagerank_galgo(csr_m3)

Comments

In order to to maximize the PageRank of X, both Y and Z should point only to X, according to logic behind PageRank. This is implemented and the results are presented below. Obviously, the PageRank of X is now again improved.

In [30]:
pageRank_Xc = np.asarray(pr3[csr_m3.shape[0] - 1]).ravel()[0]
print("The PageRank of page X is:", pageRank_Xc)
The PageRank of page X is: 1.44008502911e-06
In [31]:
pageRank_Yc = np.asarray(pr3[csr_m3.shape[0] - 2]).ravel()[0]
print("The PageRank of page Y is:", pageRank_Yc)
The PageRank of page Y is: 5.33364825577e-07
In [32]:
pageRank_Zc = np.asarray(pr3[csr_m3.shape[0] - 3]).ravel()[0]
print("The PageRank of page Z is:", pageRank_Zc)
The PageRank of page Z is: 5.33364825577e-07
In [33]:
norm_diff = np.linalg.norm(np.asarray(pr[:csr_m.shape[0]].ravel()) - np.asarray(pr3[:csr_m3.shape[0] - 3].ravel()))
print("Changes in PageRank of the other pages due to the addition of the new page:", norm_diff)

mat_prg = np.asarray(pr).ravel()
mat_prg3 = np.asarray(pr3[:csr_m3.shape[0] - 3]).ravel()

indices_pr = mat_prg.argsort()[-len(mat_prg):][::-1]
indices_pr3 = mat_prg3.argsort()[-len(mat_prg3):][::-1]
print("Changes in:",
      np.sum(indices_pr[:] != indices_pr3[:]), "ranks.")
Changes in PageRank of the other pages due to the addition of the new page: 5.66258974095e-08
Changes in: 52911 ranks.

Question 2d

In [34]:
# determine top 100 - most popular pages - here as popular are considered
# pages with high PageRank, because PageRank can be seen as a measure of
# popularity
top_100 = indices_pr[0:100]

# determine top 100 - most popular pages - here as popular are considered
# pages with high in-degree
list_degree = np.asarray([len(dict_in[x]) for x in sorted(list(dict_in.keys()))])
indices_degree = list_degree.argsort()[-len(list_degree):][::-1]
popular_100 = list_degree[0:100]
In [35]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data4(data, top100):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    
    # add a new edge Y -> X
    from_pages.append(nodes)
    to_pages.append(nodes + 2)
    
    # add a new edge Z -> X
    from_pages.append(nodes + 1)
    to_pages.append(nodes + 2)
    
    # add links from X to older, popular pages
    for node in top_100:
        from_pages.append(nodes + 2)
        to_pages.append(node)
    
    # increase number of nodes and edges as needed
    nodes += 3
    edges += 102
    
    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes, nodes))
    # return the adjacency sparse matrix
    return csr_m
In [36]:
# method to parse the data. The input file contains
# in compressed form the connectivity matrix for the webpages
# of Stanford University. Obviously, storing all that information
# naively in a numpy array would lead to memory error. Thus, sparse
# matrix is used.
def load_data5(data, top100):
    # list to store the origin pages,
    # i.e. the pages showing to other pages
    from_pages = []
    # list to store the destination pages,
    # i.e. the pages being showed by other pages
    to_pages = []
    with open(data, 'r') as f:
        # for each line of the initial data file
        for line in f.readlines():
            # get the item of the first column
            # and substract one. This is done because the ids of webpages
            # begin from 1 but the indexes for matrices begine from 0. So
            # 1 will stand for 0.
            from_page = int(line.split()[0]) - 1
            # Apply the same logic as above for the element of the second
            # column.
            to_page = int(line.split()[1]) - 1
            # append the the from page to the relative list
            from_pages.append(from_page)
            # append the the to page to the relative list
            to_pages.append(to_page)
            
    # compute number of edges
    edges = len(from_pages)
    # compute number of nodes
    nodes = len(set(from_pages) | set(to_pages))
    
    # add a new edge Y -> X
    from_pages.append(nodes)
    to_pages.append(nodes + 2)
    
    # add a new edge Z -> X
    from_pages.append(nodes + 1)
    to_pages.append(nodes + 2)
    
    # add links from Y (or Z) to older, popular pages
    for node in top_100:
        from_pages.append(nodes + 1)
        to_pages.append(node)

    # increase number of nodes and edges as needed
    nodes += 3
    edges += 102
    
    # fill the connectivity matrix, adjacency matrix. A sparse structure 
    # is used. That way the implementation is extremely memory efficient.
    csr_m = sparse.csr_matrix(([1]*edges,
                               (to_pages, from_pages)),
                              shape=(nodes, nodes))
    # return the adjacency sparse matrix
    return csr_m
In [37]:
csr_m4 = load_data4("stanweb.dat", top_100)
pr4, t4, list_conv4 = pagerank_galgo(csr_m4)

csr_m5 = load_data5("stanweb.dat", top_100)
pr5, t4, list_conv5 = pagerank_galgo(csr_m5)

Comments

We observe that if we add links from X to older, popular pages (top 100) the PageRank is slightly worse and if we add links from Y (or Z) to older, popular pages (top 100) the PageRank of X is even worse. This is rational as the PageRank of Y (or Z) is now split to more webpages. Consequently, this is not an effective way of increasing the PageRank of X, as in general the PageRank of a webpage is increasing as the webpages pointing to that webpage increases.

In [39]:
# if we add links from X to older, popular pages
pageRank_Xd = np.asarray(pr4[csr_m4.shape[0] - 1]).ravel()[0]
print("If we add links from X to older, popular pages the PageRank of page X is:", pageRank_Xd)

# if we add links from Y to older, popular pages
pageRank_Xd2 = np.asarray(pr5[csr_m5.shape[0] - 1]).ravel()[0]
print("If we add links from Y to older, popular pages the PageRank of page X is:", pageRank_Xd2)
If we add links from X to older, popular pages the PageRank of page X is: 1.44007329858e-06
If we add links from Y to older, popular pages the PageRank of page X is: 9.91211125315e-07

Question 2e

Based on the previous questions it is obvious that increasing the PageRank of a webpage is a tough task. However, that does not mean it is also impossible. The PageRank of a webpage can be increased if more and more pages point to that to webpage. Of course, if those webpages have high PageRank then their contribution will be even more significant. Nevertheless, in general, the more pages pointing to a webpage, the higher the PageRank of that page. Moreover, interconnections amongst those pages could also be helpful.