#include #include #include #include #include #include #include #include #include #include #include #include using namespace std; class PageRank { public: map Nodes; /* This helps to read in nodes */ vector Names; /* Nodes are numbers, so this is the name of each node. */ vector < vector > Adj; /* The Adjacency List */ vector < vector > H_Ind; /* Sparse representation of H - Indices */ vector < vector > H_Val; /* Sparse representation of H - Values */ vector I; /* The stationary vector I */ int Get_Node(const string &name); /* Return a node's number. Create it if it doesn't exist. */ void Read(); /* Create the graph from standard input. */ void Make_H(); /* This converts the adjacency list into the matrix */ void Find_I(); /* Find the stationary vector. */ }; /* Find the stationary vector */ void PageRank::Find_I() { vector New_I; int i, j, done, row; double p; double threshold; double alpha; threshold = 0.000000001; alpha = 0.85; New_I.resize(H_Ind.size()); I.resize(H_Ind.size(), 0); I[0] = 1; done = 0; while (!done) { /* First calculate the sum of I values for all of the nodes with no edges coming out of their adjacency lists. */ p = 0; for (i = 0; i < Adj.size(); i++) { if (Adj[i].size() == 0) p += I[i]; } p /= (double) I.size(); New_I.clear(); New_I.resize(I.size(), p); for (i = 0; i < I.size(); i++) { /* Calculate the new values of I */ p = 0; for (j = 0; j < H_Ind[i].size(); j++) { row = H_Ind[i][j]; p += H_Val[i][j] * I[row]; } New_I[i] += p; } p = (1 - alpha) / (double) I.size(); /* Scale by alpha */ for (i = 0; i < I.size(); i++) { New_I[i] = (alpha * New_I[i]) + p; } // for (i = 0; i < I.size(); i++) printf(" %5.3lf", I[i]); // printf("\n"); /* See if the new and old values */ done = 1; /* are close enough to quit. */ for (i = 0; done && i < I.size(); i++) { if (I[i] - New_I[i] > threshold || New_I[i] - I[i] > threshold) done = 0; } I = New_I; /* Yes, I have been seduced by evil in C++ */ } } /* Make the matrix from the adjacency list */ void PageRank::Make_H() { int i, j; double p; H_Ind.resize(Adj.size()); H_Val.resize(Adj.size()); /* Now run through the adjacency list, adding node i to the entry for row j */ for (i = 0; i < Adj.size(); i++) { if (Adj[i].size() != 0) { p = 1 / (double) Adj[i].size(); for (j = 0; j < Adj[i].size(); j++) { H_Ind[Adj[i][j]].push_back(i); H_Val[Adj[i][j]].push_back(p); } } } } /* If we've seen this name before, return the number of its node. Otherwise, add the node to Nodes, the name to Names, and make room in the Adjacency List */ int PageRank::Get_Node(const string &name) { int number; if (Nodes.find(name) != Nodes.end()) return Nodes[name]; number = Adj.size(); Nodes[name] = number; Adj.resize(number+1); Names.push_back(name); return number; } /* Read the graph from standard input */ void PageRank::Read() { string line, from, to; int separator; int f, t; while (getline(cin, line)) { if (line.size() == 0 || line[0] != '#') { /* Ignore comments */ separator = line.find(" -> "); if (separator != string::npos) { /* Ignore lines without -> " */ from = line.substr(0, separator); to = line.substr(separator + 4); f = Get_Node(from); /* Get the node numbers, and put t onto */ t = Get_Node(to); /* f's adjacency list. */ Adj[f].push_back(t); } } } } int main() { PageRank PR; int i, j; PR.Read(); PR.Make_H(); PR.Find_I(); /* Print out I */ for (i = 0; i < PR.I.size(); i++) { printf("%10.8lf %s\n", PR.I[i], PR.Names[i].c_str()); } exit(0); }