size_t scn::MRTofRandomWalk(UGraph::pGraph graph) { size_t total_steps = 0; vector<size_t> neighbors; srand(size_t(time(00))); //#pragma omp parallel for shared(total_steps) private(neighbors) for(size_t source = 0; source < graph->GetNumberOfNodes(); source++) { // if(omp_get_thread_num() == 0) // cout<<"Random walk on "<<source<<"/"<<graph->GetNumberOfNodes() / omp_get_num_procs()<<endl; size_t next = source; size_t steps = 0; do { neighbors.assign(graph->find(next)->begin(), graph->find(next)->end()); next = neighbors[rand() % neighbors.size()]; steps++; }while(next != source); //#pragma omp critical { total_steps += steps; } } return static_cast<double>(total_steps) / static_cast<double>(graph->GetNumberOfNodes()); }
void scn::RunSPFA(UGraph::pGraph graph,size_t indexOfSource, std::unordered_map<size_t,size_t> &distance) { assert(graph->HasNode(indexOfSource)); // Map<size_t>& distance = distance_sssp; //distance, stored the distance information of each node //init for(auto node = graph->begin(); node != graph->end(); node++) { distance[*node] = Graph::NaF; } distance[indexOfSource] = 0; queue<size_t> queue_buffer; unordered_set<size_t> in_queue; queue_buffer.push(indexOfSource);//push source node size_t front; while(!queue_buffer.empty()) { front = queue_buffer.front(); queue_buffer.pop(); in_queue.erase(front); auto node = graph->find(front); for(auto other = node->begin(); other != node->end(); other++) { if(in_queue.find(*other) == in_queue.end() && distance[front] + 1 < distance[*other]) { distance[*other] = distance[front] + 1; queue_buffer.push(*other); in_queue.insert(*other); } } } }
size_t scn::RandomWalkBySARW(UGraph::pGraph graph,size_t indexOfSource, size_t indexOfTarget) { unordered_set<size_t> neighbors_of_target(graph->find(indexOfTarget)->begin(), graph->find(indexOfTarget)->end()); vector<size_t> neighbors; size_t steps = 0; size_t next = indexOfSource; unordered_set<size_t> history; stack<size_t> precessors; history.insert(indexOfSource); precessors.push(indexOfSource); srand(size_t(time(00))); // judge first if(graph->HasEdge(indexOfSource, indexOfTarget)) return 1; do { auto other = graph->find(next); neighbors.clear(); for(auto iter = other->begin(); iter != other->end(); iter++) { if(history.find(*iter) == history.end()) neighbors.push_back(*iter); } if(neighbors.empty()) { history.insert(*other); precessors.pop(); next = precessors.top(); history.insert(next); steps++; continue; } do { next = neighbors[rand() % neighbors.size()]; }while(history.find(next) != history.end()); steps++; history.insert(next); precessors.push(next); }while(neighbors_of_target.find(next) == neighbors_of_target.end()); return steps; }
size_t scn::RandomWalkByURW(UGraph::pGraph graph,size_t indexOfSource, size_t indexOfTarget) { unordered_set<size_t> neighbors_of_target(graph->find(indexOfTarget)->begin(), graph->find(indexOfTarget)->end()); vector<size_t> neighbors; size_t steps = 0; size_t next = indexOfSource; srand(size_t(time(00))); do { neighbors.assign(graph->find(next)->begin(), graph->find(next)->end()); next = neighbors[rand() % neighbors.size()]; steps++; }while(neighbors_of_target.find(next) == neighbors_of_target.end()); return steps; }
void scn::RunDjikstra(UGraph::pGraph graph,size_t indexOfSource,std::unordered_map<size_t,size_t> &distance) { //auto& distance = distance_sssp;//using distance_sssp eariler assert(graph->HasNode(indexOfSource)); //init //distance.reserve(graph->GetNumberOfNodes()); for(auto node = graph->begin(); node != graph->end(); node++) { distance[*node] = Graph::NaF; } distance[indexOfSource] = 0; list<size_t> queue; //fill index of nodes into queue for(size_t i = 0; i < graph->GetNumberOfNodes(); i++) { queue.push_back(i); } //begin size_t next_distance; while(!queue.empty()) { //get min one auto min = min_element(queue.begin(), queue.end(), [&](const size_t &one, const size_t &two)->bool { if(distance[one] < distance[two]) return true; else return false; }); auto node = graph->find(*min); if(distance[*node] < Graph::NaF) next_distance = distance[*node] + 1; else next_distance = Graph::NaF; //relax neighbors for(auto other = node->begin(); other != node->end(); other++) { if(distance[*other] > next_distance) { distance[*other] = next_distance; } } queue.erase(min); } }
double scn::GetClusteringCoeff(UGraph::pGraph graph,size_t indexOfNode) { if(indexOfNode == UGraph::NaF) {//the whole network double coefficient = 0; for(auto node = graph->begin(); node != graph->end(); node++) { size_t numberOfTriangles = 0; for(auto other1 = node->begin(); other1 != node->end(); other1++) { for(auto other2 = other1 + 1; other2 != node->end(); other2++) { if(graph->HasEdge(*other1, *other2)) numberOfTriangles++; } } if(node->GetDegree()>1) { coefficient += 2 * static_cast<double>(numberOfTriangles) / (node->GetDegree() * (node->GetDegree() - 1)); } } return coefficient / graph->GetNumberOfNodes(); } else {//one vertex auto node = graph->find(indexOfNode); double numberOfTriangles = 0; for(auto other1 = node->begin(); other1 != node->end(); other1++) { for(auto other2 = other1 + 1; other2 != node->end(); other2++) { if(graph->HasEdge(*other1, *other2)) numberOfTriangles++; } } if(node->GetDegree()>1) return 2 * numberOfTriangles / (node->GetDegree() * (node->GetDegree() - 1)); else return 0.0; } }
IndexList scn::FindClosureGroup(UGraph::pGraph graph,size_t indexOfSeed, size_t length) { unordered_set<size_t> list; list.insert(indexOfSeed); //breadth-first search to find adjacent nodes queue<size_t> search_queue; unordered_set<size_t> in_queue; //init search_queue.push(indexOfSeed); in_queue.insert(indexOfSeed); //begin size_t front; while(!search_queue.empty()) { front = search_queue.front(); search_queue.pop(); in_queue.erase(front); auto node = graph->find(front); for(auto other = node->begin(); other != node->end(); other++) { if(in_queue.find(*other) != in_queue.end()) continue; if(list.find(*other) != list.end()) continue; if(all_of(list.begin(), list.end(), [&](size_t i)->bool { if(GetShortestDistance(graph,i, *other) < length) return true; else return false; })) { search_queue.push(*other); in_queue.insert(*other); list.insert(*other); } } } return IndexList(list.begin(), list.end()); }
size_t scn::GetShortestDistance(UGraph::pGraph graph,size_t indexOfSource, size_t indexOfTarget) { assert(graph->HasNode(indexOfSource) && graph->HasNode(indexOfTarget)); //breadth-first search queue<size_t> search_queue; std::unordered_map<size_t,size_t> distance; unordered_set<size_t> in_queue; size_t front; //initial distance[indexOfSource] = 0; search_queue.push(indexOfSource); in_queue.insert(indexOfSource); while(!search_queue.empty()) { front = search_queue.front(); search_queue.pop(); in_queue.erase(front); auto node = graph->find(front); for(auto other = node->begin(); other != node->end(); other++) { if(*other == indexOfTarget) return distance[*node] + 1; if(in_queue.find(*other) == in_queue.end() && (distance.find(*other) == distance.end() || distance[front] + 1 < distance[*other])) { distance[*other] = distance[front] + 1; search_queue.push(*other); in_queue.insert(*other); } } } //if this point is reached, the indexOfTarget is an isolated node return Graph::NaF; }
pair<size_t, size_t> scn::GetNumberOfShortestPath(UGraph::pGraph graph,size_t indexOfSource, size_t indexOfTarget, size_t indexOfThrough) { assert(graph->HasNode(indexOfSource)); assert(graph->HasNode(indexOfTarget)); //find shortest path std::unordered_map<size_t,size_t> distance; //auto& distance = distance_sssp; RunSPFA(graph,indexOfSource,distance); if(indexOfThrough == UGraph::NaF) {//no passing through any specified node size_t sum = 0; queue<size_t> path; path.push(indexOfTarget); //breadth-first search while(!path.empty()) { if(indexOfSource == path.front()) sum++; else { auto current = graph->find(path.front()); size_t current_distance = distance[*current]; for(auto other = current->begin(); other != current->end(); other++) { if(distance[*other] == current_distance - 1) path.push(*other); } } path.pop(); } return make_pair(sum, sum); } else { assert(graph->HasNode(indexOfThrough)); assert(indexOfSource != indexOfThrough); assert(indexOfTarget != indexOfThrough); size_t sum_all = 0; size_t sum_through = 0; queue<pair<size_t, bool>> path;//pair(indexOfNode, Does it Pass //through the give node? path.push(make_pair(indexOfTarget, false)); //breadth-first search while(!path.empty()) { auto current = path.front(); if(current.first == indexOfThrough) current.second = true; if(indexOfSource == current.first) { sum_all++; if(current.second) sum_through++; } else { size_t current_distance = distance[current.first]; auto current_node = graph->find(current.first); for(auto other = current_node->begin(); other != current_node->end(); other++) { if(distance[*other] == current_distance - 1) path.push(make_pair(*other, current.second)); } } path.pop(); } return make_pair(sum_all, sum_through); } }