void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { if(gcontext.iteration == 0){ VertexDataType vertexdata = vertex.get_data(); if(!vertexdata.confirmed || !vertexdata.reconfirmed) return ; assert(vertex.num_inedges() * vertex.num_outedges() <= product); for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edgedata = vertex.outedge(i)->get_data(); if(edgedata.is_equal()){ /* if(edgedata.smaller_one != 0) std::cout<<edgedata.smaller_one<<" \t"<<edgedata.larger_one<<"\t root="<<root<<std::endl; */ if(root == edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid)){ lock.lock(); fprintf(fpout, "%u\t%u\n", vertex.id(), vertex.outedge(i)->vertexid); lock.unlock(); continue; } } /* lock.lock(); fprintf(fpout1, "%u\t%u\n", vertex.id(), vertex.outedge(i)->vertexid); lock.unlock(); */ } } }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType > &vertex, graphchi_context &gcontext) { if (gcontext.iteration == 0) { for(int i=0; i < vertex.num_outedges(); i++) { chivector<vid_t> * evector = vertex.outedge(i)->get_vector(); evector->clear(); assert(evector->size() == 0); evector->add(vertex.id()); assert(evector->size() == 1); assert(evector->get(0) == vertex.id()); } } else { for(int i=0; i < vertex.num_inedges(); i++) { graphchi_edge<EdgeDataType> * edge = vertex.inedge(i); chivector<vid_t> * evector = edge->get_vector(); assert(evector->size() >= gcontext.iteration); for(int j=0; j < evector->size(); j++) { vid_t expected = edge->vertex_id() + j; vid_t has = evector->get(j); if (has != expected) { std::cout << "Mismatch: " << has << " != " << expected << std::endl; } assert(has == expected); } } for(int i=0; i < vertex.num_outedges(); i++) { vertex.outedge(i)->get_vector()->add(vertex.id() + gcontext.iteration); } } vertex.set_data(gcontext.iteration + 1); }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { if (first_iteration) { vertex.set_data(SCCinfo(vertex.id())); } if (vertex.get_data().confirmed) { return; } /* Vertices with only in or out edges cannot be part of a SCC (Trimming) */ if (vertex.num_inedges() == 0 || vertex.num_outedges() == 0) { if (vertex.num_edges() > 0) { // TODO: check this logic! vertex.set_data(SCCinfo(vertex.id())); } vertex.remove_alledges(); return; } remainingvertices = true; VertexDataType vertexdata = vertex.get_data(); bool propagate = false; if (gcontext.iteration == 0) { vertexdata = vertex.id(); propagate = true; /* Clean up in-edges. This would be nicer in the messaging abstraction... */ for(int i=0; i < vertex.num_inedges(); i++) { bidirectional_label edgedata = vertex.inedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = vertex.id(); vertex.inedge(i)->set_data(edgedata); } } else { /* Loop over in-edges and choose minimum color */ vid_t minid = vertexdata.color; for(int i=0; i < vertex.num_inedges(); i++) { minid = std::min(minid, vertex.inedge(i)->get_data().neighbor_label(vertex.id(), vertex.inedge(i)->vertexid)); } if (minid != vertexdata.color) { vertexdata.color = minid; propagate = true; } } vertex.set_data(vertexdata); if (propagate) { for(int i=0; i < vertex.num_outedges(); i++) { bidirectional_label edgedata = vertex.outedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid) = vertexdata.color; vertex.outedge(i)->set_data(edgedata); gcontext.scheduler->add_task(vertex.outedge(i)->vertexid, true); } } }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { if (vertex.get_data().confirmed) { return; } VertexDataType vertexdata = vertex.get_data(); bool propagate = false; if (gcontext.iteration == 0) { /* "Leader" of the SCC */ if (vertexdata.color == vertex.id()) { propagate = true; vertex.remove_alloutedges(); } } else { /* Loop over in-edges and see if there is a match */ bool match = false; for(int i=0; i < vertex.num_outedges(); i++) { if (!vertex.outedge(i)->get_data().deleted()) { if (vertex.outedge(i)->get_data().neighbor_label(vertex.id(), vertex.outedge(i)->vertexid) == vertexdata.color) { match = true; break; } } } if (match) { propagate = true; vertex.remove_alloutedges(); vertex.set_data(SCCinfo(vertexdata.color, true)); } else { vertex.set_data(SCCinfo(vertex.id(), false)); } } if (propagate) { for(int i=0; i < vertex.num_inedges(); i++) { bidirectional_label edgedata = vertex.inedge(i)->get_data(); if (!edgedata.deleted()) { edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = vertexdata.color; vertex.inedge(i)->set_data(edgedata); gcontext.scheduler->add_task(vertex.inedge(i)->vertexid, true); } } } }
void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { assert(vertex.num_inedges() * vertex.num_outedges() <= product); for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edgedata = vertex.outedge(i)->get_data(); if(edgedata.is_equal()){ if(root == edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid)){ lock.lock(); fprintf(fpout, "%u\t%u\n", vertex.id(), vertex.outedge(i)->vertexid); lock.unlock(); continue; } } lock.lock(); fprintf(fpout1, "%u\t%u\n", vertex.id(), vertex.outedge(i)->vertexid); lock.unlock(); } }
void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { if (gcontext.iteration == 0){ //Vertexinfo vdata = vertex.get_data(); //id_th = vertex.id(); vid_t row = vertex.id() / nshards; //vid_t new_id = row * nshards + prefix_sum[vertex.id() % nshards]; vid_t new_id = row + prefix_sum[vertex.id() % nshards]; vertex.set_data(new_id); //source vertex in each CC //vdata.level = 0; //vertex.set_data(vdata); //vid_t new_id = getNewId(vdata.ccid, vdata.level); for(int i=0; i<vertex.num_edges(); i++){ bidirectional_label edata = vertex.edge(i)->get_data(); edata.my_label(vertex.id(), vertex.edge(i)->vertex_id()) = new_id; vertex.edge(i)->set_data(edata); } lock.lock(); fprintf(vfout, "%u\t%u\n", new_id, vertex.id()); lock.unlock(); }else{ for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edata = vertex.outedge(i)->get_data(); vid_t my_id = edata.my_label(vertex.id(), vertex.outedge(i)->vertex_id()); vid_t nb_id = edata.neighbor_label(vertex.id(), vertex.outedge(i)->vertex_id()); if(my_id == nb_id){ std::cout<<"my_id="<<vertex.id()<<"\tmy_label="<<my_id <<"\tnb_label="<<nb_id <<"\tnb_vid="<<vertex.outedge(i)->vertex_id()<<std::endl; assert(my_id != nb_id); } if(!flag_weight){ lock.lock(); fprintf(efout, "%u\t%u\n", my_id, nb_id); lock.unlock(); }else{ lock.lock(); fprintf(efout, "%u\t%u\t%.3f\n", my_id, nb_id, edata.weight); lock.unlock(); } } } }
/** * Pagerank update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &v, graphchi_context &ginfo) { float sum=0; if (ginfo.iteration == 0) { /* On first iteration, initialize vertex and out-edges. The initialization is important, because on every run, GraphChi will modify the data in the edges on disk. */ for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<float> * edge = v.outedge(i); edge->set_data(1.0 / v.num_outedges()); } v.set_data(RANDOMRESETPROB); } else { /* Compute the sum of neighbors' weighted pageranks by reading from the in-edges. */ for(int i=0; i < v.num_inedges(); i++) { float val = v.inedge(i)->get_data(); sum += val; } /* Compute my pagerank */ float pagerank = RANDOMRESETPROB + (1 - RANDOMRESETPROB) * sum; /* Write my pagerank divided by the number of out-edges to each of my out-edges. */ if (v.num_outedges() > 0) { float pagerankcont = pagerank / v.num_outedges(); for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<float> * edge = v.outedge(i); edge->set_data(pagerankcont); } } /* Keep track of the progression of the computation. GraphChi engine writes a file filename.deltalog. */ ginfo.log_change(std::abs(pagerank - v.get_data())); /* Set my new pagerank as the vertex value */ v.set_data(pagerank); } }
/** * Update the weigthed edge chivector * We first obtain the edge weight from the first element, sum them, then update the * second item by eacg edge's weight */ void update_edge_data(graphchi_vertex<VertexDataType, EdgeDataType> &v, float quota, bool first){ float sum = 0.0; //if(first) for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<EdgeDataType> * edge = v.outedge(i); if (edge != NULL) { chivector<float> * evector = edge->get_vector(); //std::cout << evector->size() << std::endl; /*if (first) assert(evector->size() == 1); else assert(evector->size() == 2); assert(evector->size() == 2);*/ std::cout << v.id() << " with data: " << evector->get(0) << std::endl; sum += evector->get(0); /*if (first){ evector->add(sum); assert(evector->size() == 2); }*/ } } for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<EdgeDataType> * edge = v.outedge(i); if (edge != NULL) { chivector<float> * evector = edge->get_vector(); // assert(evector->size() == 2); float val = quota * evector->get(0) / sum; //evector->set(1, val); if(first && (evector->size() == 1)) evector->add(val); evector->set(1, val); //std::cout << v.id() << " with data: " << evector->get(0) << std::endl; } } }
/** * Update the weigthed edge chivector * We first obtain the edge weight from the first element, sum them, then update the * second item by eacg edge's weight */ void update_edge_data(graphchi_vertex<VertexDataType, EdgeDataType> &v, float quota){ float sum = 0.0; for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<EdgeDataType> * edge = v.outedge(i); //We store the weight value to the edge->weight field and then sum them /*if(first) edge->set_weight(edge->get_data());*/ struct weightE eData = edge->get_data(); //sum += eData.weight; sum ++; //if(!first) // std::cout << v.id() << " with data: " << edge->get_data() << " with weight " << edge->get_weight() << std::endl; } for(int i=0; i < v.num_outedges(); i++) { graphchi_edge<EdgeDataType> * edge = v.outedge(i); struct weightE eData = edge->get_data(); //eData.pagerank = quota * eData.weight / sum; eData.pagerank = quota * 1.0 / sum; edge->set_data(eData); if (v.id() == 3845) std::cout << v.id() << " -> " << edge->vertex_id() << " with data: " << eData.pagerank << " with weight " << eData.weight << std::endl; } }
/** The actual LambdaRank implementation. */ virtual void compute_gradients( graphchi_vertex<TypeVertex, FeatureEdge> &query, Gradient* umodel) { std::vector<double> lambdas(query.num_outedges()); std::vector<double> s_is(query.num_outedges()); /* First, we compute all the outputs... */ for (int i = 0; i < query.num_outedges(); i++) { s_is[i] = get_score(query.outedge(i)); // std::cout << "s[" << i << "] == " << s_is[i] << std::endl; } /* ...and the retrieval measure scores. */ opt.compute(query); /* Now, we compute the errors (lambdas). */ for (int i = 0; i < query.num_outedges() - 1; i++) { int rel_i = get_relevance(query.outedge(i)); for (int j = i + 1; j < query.num_outedges(); j++) { int rel_j = get_relevance(query.outedge(j)); if (rel_i != rel_j) { double S_ij = rel_i > rel_j ? 1 : -1; double lambda_ij = dC_per_ds_i(S_ij, s_is[i], s_is[j]) * fabs(opt.delta(query, i, j)); /* lambda_ij = -lambda_ji */ lambdas[i] += lambda_ij; lambdas[j] -= lambda_ij; } } } /* Finally, the model update. */ for (int i = 0; i < query.num_outedges(); i++) { // -lambdas[i], as C is a utility function in this case umodel->update(query.outedge(i)->get_vector()->get_data(), s_is[i], lambdas[i]); } }
/** Scores all documents for the query. The first step in update(). */ void score_documents(graphchi_vertex<TypeVertex, FeatureEdge> &query, graphchi_context &ginfo) { // XXX // std::map<double, FeatureEdge> scores; for (int doc = 0; doc < query.num_outedges(); doc++) { FeatureEdge* fe = query.outedge(doc)->get_vector(); fe->header().score = model->score(fe->get_data()); // query.outedge(doc)->set_vector(fe); // scores[fe.score] = fe; } // for (auto rit = scores.crbegin(); rit != scores.crend(); ++rit) { // std::cout << "Score " << query.id() // << ": " << rit->second.str() << std::endl; // } }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { int ninedges = 0; if (gcontext.iteration == 0) { for(int i=0; i < vertex.num_inedges(); i++) { vertex.inedge(i)->set_data(vertex.id()); ninedges++; } } else { // Keep track of the number of edegs to ensure that // deletion works fine. if (vertex.get_data() != vertex.num_inedges()) { logstream(LOG_ERROR) << "Discrepancy in edge counts: " << vertex.get_data() << " != " << vertex.num_inedges() << std::endl; } assert(vertex.get_data() == vertex.num_inedges()); for(int i=0; i < vertex.num_outedges(); i++) { graphchi_edge<vid_t> * edge = vertex.outedge(i); vid_t outedgedata = edge->get_data(); vid_t expected = edge->vertex_id() + gcontext.iteration - (edge->vertex_id() > vertex.id()); if (!is_deleted_edge_value(edge->get_data())) { if (outedgedata != expected) { logstream(LOG_ERROR) << outedgedata << " != " << expected << std::endl; assert(false); } } } for(int i=0; i < vertex.num_inedges(); i++) { vertex.inedge(i)->set_data(vertex.id() + gcontext.iteration); if (std::rand() % 4 == 1) { vertex.remove_inedge(i); __sync_add_and_fetch(&ndeleted, 1); } else { ninedges++; } } } if (gcontext.iteration == gcontext.num_iterations - 1) { vertex.set_data(gcontext.iteration + 1); } else { vertex.set_data(ninedges); } }
/** * Pagerank update function. */ void update(graphchi_vertex<VType, EType> &v, graphchi_context &ginfo) { //array[v.id()]++; if(v.num_edges() == 0) return; if (ginfo.iteration == 0) { //int partid = getPId(v.id()); vid_t newid = getNewId(v.id()); v.set_data(newid); for(int i=0; i<v.num_edges(); i++){ graphchi_edge<EType> * edge = v.edge(i); EType edata = edge->get_data(); edata.my_label(v.id(), edge->vertex_id()) = newid; edge->set_data(edata); } } else if(ginfo.iteration == 1){ /* if(v.id() == 0){ fprintf(fp_list, "%u %u\n", num_vertices, num_edges); } */ if(v.num_outedges() > 0){ vid_t mylabel = v.get_data(); for(int i=0; i<v.num_outedges(); i++){ graphchi_edge<EType> * edge = v.outedge(i); EType edata = edge->get_data(); vid_t nblabel = edata.nb_label(v.id(), edge->vertex_id()); //vid_t nb_id = edge->vertex_id(); assert(mylabel != nblabel); if(!flag_weight){ lock.lock(); fprintf(fp_list, "%u\t%u\n", mylabel, nblabel); lock.unlock(); }else{ lock.lock(); fprintf(fp_list, "%u\t%u\t%.3f\n", mylabel, nblabel, edata.weight); lock.unlock(); } //edge->set_data(edata); } }/*else{ fprintf(fp_list, "\n"); }*/ } }
void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { /* * Concurrent accessor to access the rvec value corresponding to the current vertex. */ tbb::concurrent_hash_map<unsigned int, nlohmann::json>::accessor ac; rvec_map.insert(ac,vertex.id()); nlohmann::json rvec = ac->second; int dependencies; //The number of active dependencies of the current vertex. /* * vertex_false to keep track of all the query vertices marked false for the vertex in the current iteration */ std::vector<vid_t> vertex_false; /* * If the vertex has a null rvec, it is being computed for the first time. * Compare the vertex with each of the vertices in the query graph. * If the current node matches the query node, add the dependencies of the query node to the rvec. * If the query node does not have any dependencies, set rvec[i] as true. (This implies a direct match) * If the query node and the current node don't match, set rvec[i] to false and add i to vertex_false. */ if(rvec.is_null()){ dependencies = 0; //Vertex is being computed for the first time and hence has zero dependencies. for(unsigned int i=0; i < query_json["node"].size(); i++) { if(check_equal(vertex_json[vertex.id()],query_json["node"][i])) { unsigned int out_d = query_json["node"][i]["out_degree"]; if(out_d == 0){ rvec[i] = true; } else if(vertex.num_outedges() == 0) { rvec[i] = false; vertex_false.push_back(i); } else { for(unsigned int j=0; j <query_json["edge"].size(); j++){ unsigned int source = query_json["edge"][j]["source"], target = query_json["edge"][j]["target"]; if(i == source ) rvec[i][target] = vertex.num_outedges(); } dependencies++; } } else { rvec[i] = false; vertex_false.push_back(i); } } /* * If the vertex has dependencies, schedule the children of the current vertex (outedges). */ if(dependencies != 0){ for(int i = 0; i <vertex.num_outedges();i++) gcontext.scheduler->add_task(vertex.outedge(i)->vertex_id()); } /* * Vertex data is set to the number of dependencies. * If the vertex data is greater than 0, then it is processed whenever it is scheduled in the subsequent iterations. * If the vertex data is 0, it is not processed in the subsequent iterations. */ vertex.set_data(dependencies); } dependencies = vertex.get_data(); /* * If the current vertex has dependencies, it has to be processed. * Collect the edge data of all it's outgoing edges and for each outgoing edge which is updated, update the corresponding dependency. * Else, clear all the outedges. */ if(dependencies != 0 ) { nlohmann::json updates; for(int i = 0; i < vertex.num_outedges(); i++){ chivector<vid_t> * e_vector = vertex.outedge(i)->get_vector(); int evector_size = e_vector->size(); for( int j =0; j < evector_size; j++){ vid_t t = e_vector->get(j); if(updates[t].is_null()) updates[t] = 1; else { int n = updates[t]; updates[t] = n +1; } } e_vector->clear(); } for(vid_t i = 0; i < updates.size(); i++ ) { if(updates[i].is_null()) continue; int cur_updates = updates[i]; for(size_t j = 0; j < rvec.size(); j++){ if(rvec[j].is_boolean()) continue; if(rvec[j][i].is_number()){ int prev_dep = rvec[j][i]; if(prev_dep <= cur_updates) { rvec[j] = false; vertex_false.push_back(j); dependencies --; } else rvec[j][i] = prev_dep - cur_updates; } } } vertex.set_data(dependencies); } else { for(int i = 0; i < vertex.num_outedges(); i++){ chivector<vid_t> * e_vector = vertex.outedge(i)->get_vector(); if(e_vector->size()) e_vector ->clear(); } } /* * If a node has been set to false in the current iteration, propagate the update through all the inedges. */ if(vertex_false.size() != 0){ for(int i=0; i < vertex.num_inedges(); i++){ chivector<vid_t> * e_vector = vertex.inedge(i) -> get_vector(); for(unsigned int j = 0; j < vertex_false.size(); j++) e_vector->add(vertex_false[j]); gcontext.scheduler->add_task(vertex.inedge(i)->vertex_id()); } } // Update the result vector and release the accsessor. ac->second = rvec; ac.release(); }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { VertexDataType vertexdata; //= vertex.get_data(); //bool propagate = false; if (gcontext.iteration == 0) { //vertex.set_data(SCCinfo(vertex.id())); vertexdata = vertex.get_data(); /* vertices that is not visited in Fw phase is not in the giant SCC! * minor improve by mzj 2016/3/13 */ if(!vertexdata.confirmed) return; //assert(vertexdata.color == root); if(vertex.id() == root){ //vertexdata.confirmed = true; vertexdata.color = vertex.id(); vertexdata.reconfirmed = true; for(int i=0; i<vertex.num_inedges(); i++){ bidirectional_label edgedata = vertex.inedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = vertex.id(); vertex.inedge(i)->set_data(edgedata); if(scheduler) gcontext.scheduler->add_task(vertex.inedge(i)->vertexid); vertex.inedge(i)->set_data(edgedata); } vertex.set_data(vertexdata); }else{ vertexdata.reconfirmed = false; vertexdata.color = vertex.id(); for(int i=0; i<vertex.num_inedges(); i++){ bidirectional_label edgedata = vertex.inedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = vertex.id(); vertex.inedge(i)->set_data(edgedata); //if(scheduler) gcontext.scheduler->add_task(vertex.outedge(i)->vertexid); } vertex.set_data(vertexdata); } //vertex.set_data(vertexdata); } else { vertexdata = vertex.get_data(); if(!vertexdata.confirmed) return ; vid_t min_color = vertexdata.color; for(int i=0; i<vertex.num_outedges(); i++){ //min_color = std::min(min_color, vertexdata.inedge(i)->get_data().neighbor_label(vertex.id(), vertex.inedge(i)->vertexid)); if(root == (vertex.outedge(i)->get_data()).neighbor_label(vertex.id(), vertex.outedge(i)->vertexid)){ min_color = root; break; } } if(min_color != vertexdata.color){ converged = false; //vertexdata.confirmed = true; vertexdata.reconfirmed = true; vertexdata.color = min_color; for(int i=0; i<vertex.num_inedges(); i++){ bidirectional_label edgedata = vertex.inedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = min_color; if(scheduler) gcontext.scheduler->add_task(vertex.inedge(i)->vertexid); vertex.inedge(i)->set_data(edgedata); } vertex.set_data(vertexdata); } } }
/** * Vertex update function. */ void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { VertexDataType vertexdata; //= vertex.get_data(); bool propagate = false; if (gcontext.iteration == 0) { //vertex.set_data(SCCinfo(vertex.id())); vertexdata = vertex.get_data(); vertexdata.color = vertex.id(); if(vertex.id() == root){ product = vertex.num_inedges() * vertex.num_outedges(); vertexdata.confirmed = true; vertex.set_data(vertexdata); for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edgedata = vertex.outedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid) = vertex.id(); if(scheduler) gcontext.scheduler->add_task(vertex.outedge(i)->vertexid); vertex.outedge(i)->set_data(edgedata); } }else{ vertexdata.confirmed = false; vertex.set_data(vertexdata); for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edgedata = vertex.outedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid) = vertex.id(); //if(scheduler) gcontext.scheduler->add_task(vertex.outedge(i)->vertexid); vertex.outedge(i)->set_data(edgedata); } // initialize labels on in and out edges for(int i=0; i<vertex.num_inedges(); i++){ bidirectional_label edgedata = vertex.inedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.inedge(i)->vertexid) = vertex.id(); //if(scheduler) gcontext.scheduler->add_task(vertex.outedge(i)->vertexid); vertex.inedge(i)->set_data(edgedata); } } } else { if(true == vertexdata.confirmed) return ; vertexdata = vertex.get_data(); vid_t min_color = vertexdata.color; for(int i=0; i<vertex.num_inedges(); i++){ //min_color = std::min(min_color, vertexdata.inedge(i)->get_data().neighbor_label(vertex.id(), vertex.inedge(i)->vertexid)); if(root == (vertex.inedge(i)->get_data()).neighbor_label(vertex.id(), vertex.inedge(i)->vertexid)){ min_color = root; break; } } if(min_color != vertexdata.color){ converged = false; vertexdata.confirmed = true; vertexdata.color = min_color; for(int i=0; i<vertex.num_outedges(); i++){ bidirectional_label edgedata = vertex.outedge(i)->get_data(); edgedata.my_label(vertex.id(), vertex.outedge(i)->vertexid) = min_color; if(scheduler) gcontext.scheduler->add_task(vertex.outedge(i)->vertexid); vertex.outedge(i)->set_data(edgedata); } vertex.set_data(vertexdata); } } }
void update(graphchi_vertex<VertexDataType, EdgeDataType> &vertex, graphchi_context &gcontext) { //For iteration 0 if (gcontext.iteration == 0) { chivector<vid_t> * v_vector = vertex.get_vector(); v_vector->clear(); /* Initialize a json object, rvec to maintain the result vector of the current node. * Maintain the list of outedges of the current vector. * These outedges are the children and must match the children of the query node. * Maintain a vector for all the nodes set to false in the current iteraion. */ nlohmann::json rvec; std::vector<vid_t> vertex_outedges; std::vector<vid_t> vertex_false; for (int i = 0; i < vertex.num_outedges(); i++) { vertex_outedges.push_back(vertex.outedge(i)->vertex_id()); } /* * Iterate through all the query nodes, and check the equality with the current node. * If the current node matches the query node, add the dependencies of the query node to the rvec. * If the query node does not have any dependencies, set rvec[i] as true. (This implies a direct match) * If the query node and the current node don't match, set rvec[i] to false and add i to vertex_false. */ for(unsigned int i=0; i < query_json["node"].size(); i++) { if(check_equal(vertex_json[vertex.id()],query_json["node"][i])) { unsigned int out_d = query_json["node"][i]["out_degree"]; if(out_d == 0){ rvec[i] = true; v_vector->add(i); } else if(vertex_outedges.size() == 0) { rvec[i] = false; vertex_false.push_back(i); } else { for(unsigned int j=0; j <query_json["edge"].size(); j++){ unsigned int source = query_json["edge"][j]["source"], target = query_json["edge"][j]["target"]; if(i == source ) rvec[i][target] = vertex_outedges; } v_vector->add(i); } } else { rvec[i] = false; vertex_false.push_back(i); } } // Access the element of rvec_map with key equal to current vertex id. // Assign rvec as the value for current vertex id. tbb::concurrent_hash_map<unsigned int, nlohmann::json>::accessor ac; rvec_map.insert(ac,vertex.id()); ac->second = rvec; ac.release(); /* * If the size of vertex_false is not zero, changes have been made in the current iteration. * For all the inedges, add the all the elements of vertex_false to the edge vector. * Schedule all the inedges for the next iteration. * */ if(vertex_false.size() != 0) { for(int i = 0; i < vertex.num_inedges(); i++) { chivector<vid_t> * e_vector = vertex.inedge(i)->get_vector(); e_vector->clear(); for(unsigned int j = 0; j< vertex_false.size(); j++){ e_vector->add(vertex_false[j]); } gcontext.scheduler->add_task(vertex.inedge(i)->vertex_id()); } } } //For iteration 1..n else{ /* * Retrieve the rvec for the current node from the rvec_map. * Intialize vertex_false to maintain the vertices set to false. */ tbb::concurrent_hash_map<unsigned int, nlohmann::json>::accessor ac; rvec_map.find(ac,vertex.id()); nlohmann::json rvec = ac->second; std::vector<vid_t> vertex_false; chivector<vid_t> * v_vector = vertex.get_vector(); /* * Iterate through all the outedges. * Iterate through each edge vector (e_vector). * Get the target value, t from each element in the edge vector. * If rvec[k] isn't a bool and rvec[k] has dependencies on t, remove j from rvec[k][t]. * If rvec[k][t] is now empty, set rvec[k] = false and add it to vertex_false. * Else update rvec[k][t]. */ for(int i = 0; i < vertex.num_outedges(); i++){ chivector<vid_t> * e_vector = vertex.outedge(i)->get_vector(); if(e_vector->size() != 0 ) { for(unsigned int j =0; j < e_vector->size(); j++){ vid_t t = e_vector->get(j); for(unsigned int k = 0; k < rvec.size(); k++ ) { if(rvec[k].is_boolean()) continue; if(rvec[k][t].is_null()) continue; std::vector <vid_t> desc(rvec[k][t].begin(),rvec[k][t].end()); std::vector <vid_t>::iterator it = std::find(desc.begin(), desc.end(), vertex.outedge(i)->vertex_id()); if(it != desc.end()) { desc.erase(it); if(desc.size() == 0){ rvec[k] = false; vertex_false.push_back(k); } else rvec[k][t] = desc; } } } } e_vector->clear(); } /* * If the size of vertex_false is not zero, changes have been made in the current iteration. * Update the vertex vector. * For all the inedges, add the all the elements of vertex_false to the edge vector. * Schedule all the inedges for the next iteration. */ if(vertex_false.size() != 0){ //Update the new match nodes for the vertex by adding only the current matches to the vertex vector. v_vector->clear(); for(unsigned int i = 0; i < rvec.size(); i++){ if(!rvec[i].is_boolean()) v_vector->add(i); else if(rvec[i]) v_vector->add(i); } for(int i=0; i < vertex.num_inedges(); i++){ chivector<vid_t> * e_vector = vertex.inedge(i) -> get_vector(); for(unsigned int j = 0; j < vertex_false.size(); j++) e_vector->add(vertex_false[j]); gcontext.scheduler->add_task(vertex.inedge(i)->vertex_id()); } } ac -> second = rvec; ac.release(); } }