void derivatives() { Graph *graph = sub->subgraph; for (unsigned k = 0; k < pnum; k++) { unsigned iter = 0; bool stop = false; // We are done when maxiteration is reached // or the error is small enough. while (iter < maxiter && !stop) { iter++; // copy last iteration #pragma omp parallel for for (unsigned i = 0; i < nvert; i++) { dlast[i][k] = deriv[i][k]; deriv[i][k] = 0.0; } #pragma omp parallel for for (unsigned id = 0; id < nvert; id++) { for (Graph::iterator e = graph->iterate_outgoing_edges(id); !e.end(); e++) { user_id fr = (*e).v2; double calc = sub->score(id, fr) * dlast[id][k] + pagerank[id] * (1.0-alpha) * params->qderiv(id, fr, k); #pragma omp atomic deriv[fr][k] += calc; } } stop = true; for (unsigned d = 0; d < sub->positive.size(); d++) { unsigned pos = sub->positive[d]; if (fabs(deriv[pos][k] - dlast[pos][k]) > tolerance) stop = false; } for (unsigned l = 0; l < sub->negative.size(); l++) { unsigned neg = sub->negative[l]; if (fabs(deriv[neg][k] - dlast[neg][k]) > tolerance) stop = false; } } cout << "Derivative iterations: " << iter << endl; } }
// Personalized pagerank starting from vertex start (at index 0) void pers_pagerank() { Graph *graph = sub->subgraph; unsigned iter = 0; double err = 1.0; // We are done when maxiteration is reached // or the error is small enough. while (iter++ < maxiter && err > tolerance) { // copy last iteration to last array // and clear pagerank array #pragma omp parallel for for (unsigned i = 0; i < nvert; i++) { last[i] = pagerank[i]; pagerank[i] = 0.0; } // sum up the nodes without outgoing edges ("dangling nodes"). // their pagerank sum will be uniformly distributed among all nodes. double zsum = 0.0; #pragma omp parallel for reduction(+:zsum) for (unsigned i = 0; i < sub->zerodeg.size(); i++) zsum += last[ sub->zerodeg[i] ]; double nolinks = (1.0-alpha) * zsum / nvert; pagerank[0] += alpha; // add teleport probability to the start vertex #pragma omp parallel for for (unsigned id = 0; id < nvert; id++) { double update = (1.0-alpha) * last[id]; for (Graph::iterator e = graph->iterate_outgoing_edges(id); !e.end(); e++) { #pragma omp atomic pagerank[(*e).v2] += (update * sub->score(id, (*e).v2)); } #pragma omp atomic pagerank[id] += nolinks; // pagerank from "dangling nodes" } // sum the pagerank double sum = 0.0; #pragma omp parallel for reduction(+:sum) for (unsigned i = 0; i < nvert; i++) sum += pagerank[i]; // normalize to valid probabilities, from 0 to 1. sum = 1.0 / sum; #pragma omp parallel for for (unsigned i = 0; i < nvert; i++) pagerank[i] *= sum; // sum up the error err = 0.0; #pragma omp parallel for reduction(+:err) for (unsigned i = 0; i < nvert; i++) err += fabs(pagerank[i] - last[i]); //cout << "Iteration " << iter << endl; //cout << "Error: " << err << endl; } //cout << "PageRank iterations: " << iter << endl; }