/** * @brief Perform a single source of the BC calculation per Brandes. * * Note that this follows the approach suggested by Green and Bader in which * parent lists are not maintained, but instead the neighbors are searched * to rediscover parents. * * Note also that found count will not include the source and that increments * to this array are handled atomically. * * Operations to the bc array are NOT ATOMIC * * @param S The STINGER graph * @param nv The maximum vertex ID in the graph plus one. * @param source The vertex from where this search will start. * @param bc The array into which the partial BCs will be added. * @param found_count An array to track how many times a vertex is found for normalization. */ void single_bc_search(stinger_t * S, int64_t nv, int64_t source, double * bc, int64_t * found_count) { int64_t * paths = (int64_t * )xcalloc(nv * 2, sizeof(int64_t)); int64_t * q = paths + nv; double * partial = (double *)xcalloc(nv, sizeof(double)); int64_t * d = (int64_t *)xmalloc(nv * sizeof(int64_t)); for(int64_t i = 0; i < nv; i ++) d[i] = -1; int64_t q_front = 1; int64_t q_rear = 0; q[0] = source; d[source] = 0; paths[source] = 1; while(q_rear != q_front) { int64_t v = q[q_rear++]; int64_t d_next = d[v] + 1; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { if(d[STINGER_EDGE_DEST] < 0) { d[STINGER_EDGE_DEST] = d_next; paths[STINGER_EDGE_DEST] = paths[v]; q[q_front++] = STINGER_EDGE_DEST; stinger_int64_fetch_add(found_count + STINGER_EDGE_DEST, 1); } else if(d[STINGER_EDGE_DEST] == d_next) { paths[STINGER_EDGE_DEST] += paths[v]; } } STINGER_FORALL_EDGES_OF_VTX_END(); } /* don't process source */ while(q_front > 1) { int64_t w = q[--q_front]; /* don't maintain parents, do search instead */ STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, w) { if(d[STINGER_EDGE_DEST] == (d[w] - 1)) { partial[STINGER_EDGE_DEST] += frac(paths[STINGER_EDGE_DEST],paths[w]) * (1 + partial[w]); } } STINGER_FORALL_EDGES_OF_VTX_END(); bc[w] += partial[w]; } free(d); free(partial); free(paths); }
int64_t //count_intersections (stinger_t * S, int64_t a, int64_t b) count_intersections (stinger_t * S, int64_t a, int64_t b, int64_t * neighbors, int64_t d) { size_t out = 0; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, b) { if (STINGER_EDGE_DEST != a) { int64_t first = 0; int64_t last = d-1; int64_t middle = (first + last)/2; while (first <= last) { if (neighbors[middle] < STINGER_EDGE_DEST) { first = middle + 1; } else if (neighbors[middle] == STINGER_EDGE_DEST) { out++; break; } else { last = middle - 1; } middle = (first + last)/2; } //out += stinger_has_typed_successor (S, 0, STINGER_EDGE_DEST, a); } } STINGER_FORALL_EDGES_OF_VTX_END(); return out; }
static uint64_t count_triangles(int_ht_seq_t * ht, stinger_t * S, int64_t v) { uint64_t count = 0; uint64_t count_check = 0; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { uint64_t neigh = STINGER_EDGE_DEST; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, neigh) { if(STINGER_EDGE_DEST != v) { count += int_ht_seq_exists(ht, STINGER_EDGE_DEST); } } STINGER_FORALL_EDGES_OF_VTX_END(); /* STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, neigh) { if(STINGER_EDGE_DEST != v) { uint64_t neigh_neigh = STINGER_EDGE_DEST; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { count_check += (neigh_neigh == STINGER_EDGE_DEST); } STINGER_FORALL_EDGES_OF_VTX_END(); } } STINGER_FORALL_EDGES_OF_VTX_END(); */ int_ht_seq_insert(ht, STINGER_EDGE_DEST); } STINGER_FORALL_EDGES_OF_VTX_END();
void betCentStinger_TraverseNeig_BFSqueue(struct stinger* sStinger,uint32_t currRoot,float* totalBC,bcTree* tree) { for(uint32_t j = 0; j < tree->NV; j++) { tree->level[j] = INFINITY_MY; tree->pathsToRoot[j] = INFINITY_MY; tree->delta[j] = 0; } tree->level[currRoot] = 0; tree->pathsToRoot[currRoot] = 1; uint32_t Stack[tree->NV]; uint32_t Queue[tree->NV]; Queue[0] = currRoot; int32_t qStart=0,qEnd=1; int32_t sStart=0; // While queue is not empty while(qStart!=qEnd) { uint32_t currElement = Queue[qStart]; Stack[sStart] = currElement; sStart++; qStart++; STINGER_FORALL_EDGES_OF_VTX_BEGIN(sStinger,currElement) { uint32_t k = STINGER_EDGE_DEST; // If this is a neighbor and has not been found if(tree->level[k] > tree->level[currElement]) { // Checking if "k" has been found. if(tree->level[k]==INFINITY_MY) { tree->level[k] = tree->level[currElement]+1; Queue[qEnd++] = k; tree->delta[k]=0; } if(tree->pathsToRoot[k] == INFINITY_MY) { // k has not been found and therefore its paths to the roots are through its parent. tree->pathsToRoot[k] = tree->pathsToRoot[currElement]; } else { // k has been found and has multiple paths to the root as it has multiple parents. tree->pathsToRoot[k] += tree->pathsToRoot[currElement]; } } } STINGER_FORALL_EDGES_OF_VTX_END(); }
int64_t pagerank (stinger_t * S, int64_t NV, double * pr, double * tmp_pr_in, double epsilon, double dampingfactor, int64_t maxiter) { double * tmp_pr = NULL; if(tmp_pr_in) { tmp_pr = tmp_pr_in; } else { tmp_pr = (double *) xmalloc (sizeof(double) * NV); } int64_t iter = maxiter; double delta = 1; while (delta > epsilon && iter > 0) { OMP("omp parallel for") for (uint64_t v = 0; v < NV; v++) { tmp_pr[v] = 0; STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { tmp_pr[v] += (((double)pr[STINGER_EDGE_DEST]) / ((double) stinger_outdegree_get(S, STINGER_EDGE_DEST))); } STINGER_FORALL_EDGES_OF_VTX_END(); } OMP("omp parallel for") for (uint64_t v = 0; v < NV; v++) { tmp_pr[v] = tmp_pr[v] * dampingfactor + (((double)(1-dampingfactor)) / ((double)NV)); } delta = 0; OMP("omp parallel for reduction(+:delta)") for (uint64_t v = 0; v < NV; v++) { double mydelta = tmp_pr[v] - pr[v]; if(mydelta < 0) mydelta = -mydelta; delta += mydelta; } OMP("omp parallel for") for (uint64_t v = 0; v < NV; v++) { pr[v] = tmp_pr[v]; } } if (!tmp_pr_in) free(tmp_pr); }
int64_t parallel_breadth_first_search (struct stinger * S, int64_t nv, int64_t source, int64_t * marks, int64_t * queue, int64_t * Qhead, int64_t * level) { for (int64_t i = 0; i < nv; i++) { level[i] = -1; marks[i] = 0; } int64_t nQ, Qnext, Qstart, Qend; /* initialize */ queue[0] = source; level[source] = 0; marks[source] = 1; Qnext = 1; /* next open slot in the queue */ nQ = 1; /* level we are currently processing */ Qhead[0] = 0; /* beginning of the current frontier */ Qhead[1] = 1; /* end of the current frontier */ Qstart = Qhead[nQ-1]; Qend = Qhead[nQ]; while (Qstart != Qend) { OMP ("omp parallel for") for (int64_t j = Qstart; j < Qend; j++) { STINGER_FORALL_EDGES_OF_VTX_BEGIN (S, queue[j]) { int64_t d = level[STINGER_EDGE_DEST]; if (d < 0) { if (stinger_int64_fetch_add (&marks[STINGER_EDGE_DEST], 1) == 0) { level[STINGER_EDGE_DEST] = nQ; int64_t mine = stinger_int64_fetch_add(&Qnext, 1); queue[mine] = STINGER_EDGE_DEST; } } } STINGER_FORALL_EDGES_OF_VTX_END(); } Qstart = Qhead[nQ-1]; Qend = Qnext; Qhead[nQ++] = Qend; }
// NE number of undirected edges. csrGraph* CreateCSRFromStinger(struct stinger* stingerGraph,int64_t NV,int64_t NE) { csrGraph* newGraph = (csrGraph*)malloc(sizeof(csrGraph)); newGraph->NV = NV; newGraph->NE = NE*2; newGraph->vertexPointerArray=(int64_t*)malloc(sizeof(int64_t)*(NV+1)); newGraph->edgeArray=(int64_t*)malloc(sizeof(int64_t)*NE); int64_t edgeCounter=0; newGraph->vertexPointerArray[0]=0; for(int64_t v=0; v<NV;v++) { newGraph->vertexPointerArray[v+1]= newGraph->vertexPointerArray[v]+stinger_outdegree(stingerGraph,v); STINGER_FORALL_EDGES_OF_VTX_BEGIN(stingerGraph,v) { newGraph->edgeArray[edgeCounter]=STINGER_EDGE_DEST; edgeCounter++; } STINGER_FORALL_EDGES_OF_VTX_END(); }
int64_t count_triangles (stinger_t * S, uint64_t v) { int64_t out = 0; int64_t deg = stinger_outdegree(S, v); int64_t * neighbors = xmalloc(deg * sizeof(int64_t)); size_t d; stinger_gather_typed_successors(S, 0, v, &d, neighbors, deg); qsort(neighbors, d, sizeof(int64_t), compare); STINGER_FORALL_EDGES_OF_VTX_BEGIN(S, v) { if (STINGER_EDGE_DEST != v) { //out += count_intersections (S, v, STINGER_EDGE_DEST); out += count_intersections (S, v, STINGER_EDGE_DEST, neighbors, d); } } STINGER_FORALL_EDGES_OF_VTX_END(); free (neighbors); return out; }