Graph* Graph::Shrink() { root_ = source_vertices_[0]; MarkArticulationPoints(); // Clean all the articulation points on the paths between every pair of source // vertices to ensure that all the source vertices will not be merged into // pseudo vertices. for (auto source_vertex : source_vertices_) { if (source_vertex != root_) { Vertex* vertex = source_vertex; while (vertex != root_) { assert(vertex != nullptr); vertex->SetIsArticulate(false); vertex = vertex->GetParent(); } } } // Clean all the articulation points connecting to a resident directly to // avoid making useless pseudo vertices each containing just a single // resident. for (auto pair : vertices_) { Vertex* vertex = pair.second; for (int i = 0; i < vertex->GetIncidentEdgesNum(); ++i) { Vertex* neighbor = vertex->GetIncidentEdge(i)->GetNeighbor(vertex); if (neighbor->GetType() == Vertex::Type::RESIDENT) { vertex->SetIsArticulate(false); break; } } } Graph* tmp = ShrinkByArticulationPoints(); Graph* shrinked_graph = tmp->ShrinkBySwitches(); delete tmp; //shrinked_graph->Print(); return shrinked_graph; }
Graph* Graph::ShrinkByArticulationPoints() { Graph* shrinked_graph = new Graph(grid_); const string pseudo_vertex_prefix("PAV"); int pseudo_vertex_counter = 0; ResetVerticesMarks(); map<Vertex*, PseudoVertex*> pseudo_vertices; queue<Vertex*> bfs_queue; root_->SetIsVisted(); bfs_queue.push(root_); while (!bfs_queue.empty()) { Vertex* front = bfs_queue.front(); bfs_queue.pop(); shrinked_graph->AddVertex(front); for (int i = 0; i < front->GetIncidentEdgesNum(); ++i) { Edge* incident_edge = front->GetIncidentEdge(i); Vertex* child = incident_edge->GetNeighbor(front); if (child != front->GetParent()) { if (!child->GetIsVisited()) { child->SetIsVisted(); front->AddChild(child); child->SetParent(front); if (child->GetIsArticulate()) { const string pseudo_vertex_name(pseudo_vertex_prefix + to_string(pseudo_vertex_counter++)); Node* new_node = new Node(pseudo_vertex_name); grid_->GetSmartGrid()->AddEquipment(new_node); PseudoVertex* pseudo_vertex = new PseudoVertex(new_node); Edge* new_edge = new Edge(incident_edge->GetRaw()); pseudo_vertex->AddBoundaryVertex(new_edge, child); pseudo_vertex->AddIncidentEdge(new_edge); new_edge->AddIncidentVertex(front); new_edge->AddIncidentVertex(pseudo_vertex); front->SetIncidentEdge(i, new_edge); shrinked_graph->AddVertex(pseudo_vertex); shrinked_graph->AddEdge(new_edge); pseudo_vertices.insert(make_pair(child, pseudo_vertex)); } else { bfs_queue.push(child); shrinked_graph->AddVertex(child); shrinked_graph->AddEdge(incident_edge); } } else { if (child->GetIsArticulate()) { assert(pseudo_vertices.count(child) == 1); PseudoVertex* pseudo_vertex = pseudo_vertices.find(child)->second; Edge* new_edge = new Edge(incident_edge->GetRaw()); pseudo_vertex->AddBoundaryVertex(new_edge, child); pseudo_vertex->AddIncidentEdge(new_edge); new_edge->AddIncidentVertex(front); new_edge->AddIncidentVertex(pseudo_vertex); front->SetIncidentEdge(i, new_edge); shrinked_graph->AddEdge(new_edge); } else { shrinked_graph->AddEdge(incident_edge); } } } } } for (auto pair : pseudo_vertices) { pair.second->MergeDescendants(pair.first); } return shrinked_graph; }