/* * Just a helper method to avoid ugly code in Parser#readEdges method. It just * populates \a nodes list with either a given \a v node (if not nullptr) or all * nodes in certain cluster found by performing a lookup with given \a id in * \a clusterId association. */ static inline bool edgeNodes( node v, const std::string &id, const HashArray<std::string, cluster> &clusterId, List<node> &nodes) { if(v) { nodes.clear(); nodes.pushBack(v); } else { const cluster c = clusterId[id]; if(!c) { return false; } c->getClusterNodes(nodes); } return true; }
//todo: is called only once, but could be sped up the same way as the co-conn check void MaxCPlanarMaster::clusterConnection(cluster c, GraphCopy &gc, double &upperBoundC) { // For better performance, a node array is used to indicate which nodes are contained // in the currently considered cluster. NodeArray<bool> vInC(gc,false); // First check, if the current cluster \a c is a leaf cluster. // If so, compute the number of edges that have at least to be added // to make the cluster induced graph connected. if (c->cCount()==0) { //cluster \a c is a leaf cluster GraphCopy *inducedC = new GraphCopy((const Graph&)gc); List<node> clusterNodes; c->getClusterNodes(clusterNodes); // \a clusterNodes now contains all (original) nodes of cluster \a c. for (node w : clusterNodes) { vInC[gc.copy(w)] = true; } // Delete all nodes from \a inducedC that do not belong to the cluster, // in order to obtain the cluster induced graph. node v = inducedC->firstNode(); while (v!=nullptr) { node w = v->succ(); if (!vInC[inducedC->original(v)]) inducedC->delNode(v); v = w; } // Determine number of connected components of cluster induced graph. //Todo: check could be skipped if (!isConnected(*inducedC)) { NodeArray<int> conC(*inducedC); int nCC = connectedComponents(*inducedC,conC); //at least #connected components - 1 edges have to be added. upperBoundC -= (nCC-1)*m_largestConnectionCoeff; } delete inducedC; // Cluster \a c is an "inner" cluster. Process all child clusters first. } else { //c->cCount is != 0, process all child clusters first for (cluster ci : c->children) { clusterConnection(ci, gc, upperBoundC); } // Create cluster induced graph. GraphCopy *inducedC = new GraphCopy((const Graph&)gc); List<node> clusterNodes; c->getClusterNodes(clusterNodes); //\a clusterNodes now contains all (original) nodes of cluster \a c. for (node w : clusterNodes) { vInC[gc.copy(w)] = true; } node v = inducedC->firstNode(); while (v!=nullptr) { node w = v->succ(); if (!vInC[inducedC->original(v)]) inducedC->delNode(v); v = w; } // Now collapse each child cluster to one node and determine #connected components of \a inducedC. List<node> oChildClusterNodes; List<node> cChildClusterNodes; for (cluster ci : c->children) { ci->getClusterNodes(oChildClusterNodes); // Compute corresponding nodes of graph \a inducedC. for (node u : oChildClusterNodes) { node copy = inducedC->copy(gc.copy(u)); cChildClusterNodes.pushBack(copy); } inducedC->collapse(cChildClusterNodes); oChildClusterNodes.clear(); cChildClusterNodes.clear(); } // Now, check \a inducedC for connectivity. if (!isConnected(*inducedC)) { NodeArray<int> conC(*inducedC); int nCC = connectedComponents(*inducedC,conC); //at least #connected components - 1 edges have to added. upperBoundC -= (nCC-1)*m_largestConnectionCoeff; } delete inducedC; } }//clusterConnection