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); } } } }
double scn::GetSearchInfo(UGraph::pGraph graph,size_t indexOfSource, size_t indexOfTarget) { assert(graph->HasNode(indexOfSource)); assert(graph->HasNode(indexOfTarget)); assert(indexOfSource != indexOfTarget); std::unordered_map<size_t,size_t> distance; //get shortest distance //auto& distance = distance_sssp; RunSPFA(graph,indexOfSource,distance); double sum = 0; //search in breadth-first way queue<pair<size_t, double>> path_queue;//pair : indexOfNode, //probability of path path_queue.push(make_pair(indexOfTarget, 1.0)); while(!path_queue.empty()) { auto current = path_queue.front(); auto node = (*graph)[current.first]; path_queue.pop(); for(auto other = node->begin(); other != node->end(); other++) {//put all of previous-node in path into queue if(distance[*other] == distance[*node] - 1) { if(distance[*other] == 0) sum += current.second / static_cast<double>(node->GetDegree()); else path_queue.push(make_pair(*other, current.second / static_cast<double>((*graph)[*other]->GetDegree() - 1))); } } } return - log(sum)/log(2.0); }
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; }
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); } }
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); } }