|
| 1 | +// |
| 2 | +// Created by Islam, Abdullah Al Raqibul on 9/6/22. |
| 3 | +// |
| 4 | + |
| 5 | +#include "graph.h" |
| 6 | +#include "command_line.h" |
| 7 | + |
| 8 | +/// small file |
| 9 | +//#define INPUT_GRAPH "test-graphs/lma_c.txt" |
| 10 | +//#define UNFILLED_PROPERTY_FILE "test-graphs/up_lma_c.txt" |
| 11 | +//#define NUM_VERTICES 4 |
| 12 | +//#define NUM_EDGES 5 |
| 13 | +//#define MAX_ITERATION 20 |
| 14 | + |
| 15 | +typedef float ScoreT; |
| 16 | +using namespace std::chrono; |
| 17 | + |
| 18 | +/// Sugar for printing the rank-values (@id_rank and @p_rank) after @iter iterations |
| 19 | +void print_ranks(const Graph &g, const Graph &rg, int iter, vector<ScoreT>& id_rank, vector<ScoreT>& p_rank) { |
| 20 | + cout << "\nafter " << iter << " iteration" << endl; |
| 21 | + cout << "id-rank: "; |
| 22 | + for(NodeID u=0; u<g.num_nodes(); u+=1) cout << id_rank[u] << " "; |
| 23 | + cout << endl; |
| 24 | + |
| 25 | + cout << "p-rank: "; |
| 26 | + for(NodeID u=0; u<rg.num_nodes(); u+=1) cout << p_rank[u] << " "; |
| 27 | + cout << endl; |
| 28 | +} |
| 29 | + |
| 30 | +void print_graph_property(const Graph &g, const Graph &rg) { |
| 31 | + int64_t count_isolated_nodes = 0; |
| 32 | + int64_t count_zero_in_g = 0; |
| 33 | + int64_t count_zero_in_rg = 0; |
| 34 | + |
| 35 | + for (NodeID u=0; u < g.num_nodes(); u++) { |
| 36 | + if(g.out_degree(u) == 0 && rg.out_degree(u) == 0) count_isolated_nodes += 1; |
| 37 | + else if(g.out_degree(u)) count_zero_in_g += 1; |
| 38 | + else if(rg.out_degree(u)) count_zero_in_rg += 1; |
| 39 | + else { |
| 40 | + cout << "ERROR: Should not happen!" << endl; |
| 41 | + exit(-1); |
| 42 | + } |
| 43 | + } |
| 44 | + |
| 45 | + cout << "The graph have: " << count_isolated_nodes << " isolated nodes, "; |
| 46 | + cout << count_zero_in_g << " zero-degree nodes in G, and "; |
| 47 | + cout << count_zero_in_rg << " zero-degree nodes in RG" << endl; |
| 48 | +} |
| 49 | + |
| 50 | +void FaultyPageRank(const Graph &g, const Graph &rg, |
| 51 | + int max_iters, double epsilon = 0) { |
| 52 | + const ScoreT init_score = 1.0f; |
| 53 | + const ScoreT zero_score = 0.0f; |
| 54 | + |
| 55 | + vector<ScoreT> p_rank_prev(g.num_nodes(), init_score); |
| 56 | + vector<ScoreT> id_rank(g.num_nodes(),zero_score); |
| 57 | + vector<ScoreT> p_rank(g.num_nodes(),zero_score); |
| 58 | + |
| 59 | + /// going to update @id_rank values from Graph @G |
| 60 | + for (int iter=0; iter < max_iters; iter+=1) { |
| 61 | + ///update id rank |
| 62 | + for (NodeID u=0; u < g.num_nodes(); u++) { |
| 63 | + if (g.out_degree(u) == 0) { |
| 64 | + cout<<"Sink node in G"<<u<<endl; |
| 65 | + ScoreT share = p_rank_prev[u] / (g.num_nodes() - 1); |
| 66 | + for(NodeID v=0; v < g.num_nodes(); v++) { |
| 67 | + if (u != v) id_rank[v] += share; |
| 68 | + } |
| 69 | + } |
| 70 | + else { |
| 71 | + cout<<"Nodes except sink node in G"<<u<<endl; |
| 72 | + ScoreT share = p_rank_prev[u] / g.out_degree(u); |
| 73 | + for (EdgeItem neigh: g.graph_[u].neighbors) { |
| 74 | + id_rank[neigh.v] += share; |
| 75 | + } |
| 76 | + } |
| 77 | + } |
| 78 | + ///update property rank |
| 79 | + for (NodeID u=0; u < rg.num_nodes(); u++) { |
| 80 | + if (rg.out_degree(u) == 0) { |
| 81 | + cout<<"Sink node in RG"<<u<<endl; |
| 82 | + ScoreT share = id_rank[u] / (rg.num_nodes() - 1); |
| 83 | + for(NodeID v=0; v < rg.num_nodes(); v++) { |
| 84 | + if (u != v) p_rank[v] += share; |
| 85 | + } |
| 86 | + } |
| 87 | + else if (rg.out_degree(u) > rg.out_degree_paired(u) && !rg.graph_[u].unfilled_property_flag && rg.out_degree_paired(u)) { |
| 88 | + cout<<"Weighted node in RG"<<u<<endl; |
| 89 | + ScoreT share = id_rank[u] / rg.out_degree_paired(u); |
| 90 | + for (EdgeItem neigh: rg.graph_[u].neighbors) { |
| 91 | + if(neigh.paired_flag) p_rank[neigh.v] += share; |
| 92 | + } |
| 93 | + } |
| 94 | + else { |
| 95 | + cout<<"remaining node in RG"<<u<<endl; |
| 96 | + ScoreT share = id_rank[u] / rg.out_degree(u); |
| 97 | + for (EdgeItem neigh: rg.graph_[u].neighbors) { |
| 98 | + p_rank[neigh.v] += share; |
| 99 | + } |
| 100 | + } |
| 101 | + } |
| 102 | + |
| 103 | + print_ranks(g, rg, iter, id_rank, p_rank); |
| 104 | + //#pragma omp parallel for |
| 105 | + for (NodeID u=0; u < g.num_nodes(); u++) { |
| 106 | + p_rank_prev[u] = p_rank[u]; |
| 107 | + p_rank[u] = 0.0; |
| 108 | + id_rank[u] = 0.0; |
| 109 | + } |
| 110 | + |
| 111 | + cout << "Done " << iter << " iteration." << endl; |
| 112 | + } |
| 113 | +} |
| 114 | + |
| 115 | +int main(int argc, char* argv[]) { |
| 116 | + CLApp cli(argc, argv); |
| 117 | + if (!cli.ParseArgs()) return -1; |
| 118 | + |
| 119 | + /// building the graph from @file |
| 120 | + auto start_g = std::chrono::high_resolution_clock::now(); |
| 121 | + Graph G(cli.input_filename(), cli.num_nodes(), cli.num_edges()); |
| 122 | + G.PrintTopology(); |
| 123 | + auto end_g = std::chrono::high_resolution_clock::now(); |
| 124 | + double duration_g = std::chrono::duration_cast<std::chrono::nanoseconds>(end_g - start_g).count(); |
| 125 | + cout << "time to build the original graph: " << duration_g/1000000000 << " seconds." << endl; |
| 126 | + |
| 127 | + /// building the reverse graph of Graph @G |
| 128 | + auto start_rg = std::chrono::high_resolution_clock::now(); |
| 129 | + Graph RG(G); |
| 130 | + if(cli.has_unfilled_property()) RG.mark_unfilled_property_vertices(cli.up_filename()); |
| 131 | + RG.PrintTopology(); |
| 132 | + auto end_rg = std::chrono::high_resolution_clock::now(); |
| 133 | + double duration_rg = std::chrono::duration_cast<std::chrono::nanoseconds>(end_rg - start_rg).count(); |
| 134 | + cout << "time to build the reverse graph: " << duration_rg/1000000000 << " seconds." << endl; |
| 135 | + |
| 136 | + /// call faulty page-rank algorithm |
| 137 | + auto start = std::chrono::high_resolution_clock::now(); |
| 138 | + FaultyPageRank(G, RG, cli.max_iters()); |
| 139 | + auto end = std::chrono::high_resolution_clock::now(); |
| 140 | + double duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count(); |
| 141 | + cout << "time to run the faulty-rank algorithm: " << duration/1000000000 << " seconds." << endl; |
| 142 | +} |
0 commit comments