|
SNAP Library 2.1, User Reference
2013-09-12 18:08:55
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 namespace TSnap { 00002 00004 // Node Degrees 00005 00007 template <class PGraph> int CntInDegNodes(const PGraph& Graph, const int& NodeInDeg); 00009 template <class PGraph> int CntOutDegNodes(const PGraph& Graph, const int& NodeOutDeg); 00011 template <class PGraph> int CntDegNodes(const PGraph& Graph, const int& NodeDeg); 00013 template <class PGraph> int CntNonZNodes(const PGraph& Graph); 00014 // TODO ROK document CntEdgesToSet() 00015 template <class PGraph> int CntEdgesToSet(const PGraph& Graph, const int& NId, const TIntSet& NodeSet); 00016 00018 template <class PGraph> int GetMxDegNId(const PGraph& Graph); 00020 template <class PGraph> int GetMxInDegNId(const PGraph& Graph); 00022 template <class PGraph> int GetMxOutDegNId(const PGraph& Graph); 00023 00024 // degree histograms 00025 // TODO ROK document GetInDegCnt() 00026 template <class PGraph> void GetInDegCnt(const PGraph& Graph, TIntPrV& DegToCntV); 00027 // TODO ROK document GetInDegCnt() 00028 template <class PGraph> void GetInDegCnt(const PGraph& Graph, TFltPrV& DegToCntV); 00029 // TODO ROK document GetOutDegCnt() 00030 template <class PGraph> void GetOutDegCnt(const PGraph& Graph, TIntPrV& DegToCntV); 00031 // TODO ROK document GetOutDegCnt() 00032 template <class PGraph> void GetOutDegCnt(const PGraph& Graph, TFltPrV& DegToCntV); 00033 // TODO ROK document GetDegCnt() 00034 template <class PGraph> void GetDegCnt(const PGraph& Graph, TIntPrV& DegToCntV); 00035 // TODO ROK document GetDegCnt() 00036 template <class PGraph> void GetDegCnt(const PGraph& Graph, TFltPrV& DegToCntV); 00037 // TODO ROK document GetDegSeqV() 00038 template <class PGraph> void GetDegSeqV(const PGraph& Graph, TIntV& DegV); 00039 // TODO ROK document GetDegSeqV() 00040 template <class PGraph> void GetDegSeqV(const PGraph& Graph, TIntV& InDegV, TIntV& OutDegV); 00041 00042 template <class PGraph> void GetNodeInDegV(const PGraph& Graph, TIntPrV& NIdInDegV); 00043 template <class PGraph> void GetNodeOutDegV(const PGraph& Graph, TIntPrV& NIdOutDegV); 00044 00045 template <class PGraph> int CntUniqUndirEdges(const PGraph& Graph); 00046 template <class PGraph> int CntUniqDirEdges(const PGraph& Graph); 00047 template <class PGraph> int CntUniqBiDirEdges(const PGraph& Graph); 00048 template <class PGraph> int CntSelfEdges(const PGraph& Graph); 00049 00051 // Manipulation 00052 template <class PGraph> PGraph GetUnDir(const PGraph& Graph); 00053 template <class PGraph> void MakeUnDir(const PGraph& Graph); 00054 template <class PGraph> void AddSelfEdges(const PGraph& Graph); 00055 template <class PGraph> void DelSelfEdges(const PGraph& Graph); 00056 // TODO implement DelBiDirEdges() 00057 //template <class PGraph> void DelBiDirEdges(const PGraph& Graph); 00058 00059 template <class PGraph> void DelNodes(PGraph& Graph, const TIntV& NIdV); 00060 template <class PGraph> void DelZeroDegNodes(PGraph& Graph); 00061 template <class PGraph> void DelDegKNodes(PGraph& Graph, const int& OutDegK, const int& InDegK); 00062 00064 // Tree Routines 00065 template <class PGraph> bool IsTree(const PGraph& Graph, int& RootNId); 00066 template <class PGraph> int GetTreeRootNId(const PGraph& Graph) { int RootNId; bool Tree; Tree = IsTree(Graph, RootNId); Assert(Tree); return RootNId; } 00067 template <class PGraph> void GetTreeSig(const PGraph& Graph, const int& RootNId, TIntV& Sig); 00068 template <class PGraph> void GetTreeSig(const PGraph& Graph, const int& RootNId, TIntV& Sig, TIntPrV& NodeMap); 00069 00071 // Implementation 00072 template <class PGraph> 00073 int CntInDegNodes(const PGraph& Graph, const int& NodeInDeg) { 00074 int Cnt = 0; 00075 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00076 if (NI.GetInDeg() == NodeInDeg) Cnt++; 00077 } 00078 return Cnt; 00079 } 00080 00081 template <class PGraph> 00082 int CntOutDegNodes(const PGraph& Graph, const int& NodeOutDeg) { 00083 int Cnt = 0; 00084 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00085 if (NI.GetOutDeg() == NodeOutDeg) Cnt++; 00086 } 00087 return Cnt; 00088 } 00089 00090 template <class PGraph> 00091 int CntDegNodes(const PGraph& Graph, const int& NodeDeg) { 00092 int Cnt = 0; 00093 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00094 if (NI.GetDeg() == NodeDeg) Cnt++; 00095 } 00096 return Cnt; 00097 } 00098 00099 template <class PGraph> 00100 int CntNonZNodes(const PGraph& Graph) { 00101 int Cnt = 0; 00102 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00103 if (NI.GetDeg() > 0) Cnt++; 00104 } 00105 return Cnt; 00106 } 00107 00108 template <class PGraph> 00109 int CntEdgesToSet(const PGraph& Graph, const int& NId, const TIntSet& NodeSet) { 00110 if (! Graph->IsNode(NId)) { return 0; } 00111 const bool IsDir = Graph->HasFlag(gfDirected); 00112 const typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId); 00113 if (! IsDir) { 00114 int EdgesToSet = 0; 00115 for (int e = 0; e < NI.GetOutDeg(); e++) { 00116 if (NodeSet.IsKey(NI.GetOutNId(e))) { EdgesToSet++; } } 00117 return EdgesToSet; 00118 } else { 00119 TIntSet Set(NI.GetDeg()); 00120 for (int e = 0; e < NI.GetOutDeg(); e++) { 00121 if (NodeSet.IsKey(NI.GetOutNId(e))) { Set.AddKey(NI.GetOutNId(e)); } } 00122 for (int e = 0; e < NI.GetInDeg(); e++) { 00123 if (NodeSet.IsKey(NI.GetInNId(e))) { Set.AddKey(NI.GetInNId(e)); } } 00124 return Set.Len(); 00125 } 00126 } 00127 00128 template <class PGraph> 00129 int GetMxDegNId(const PGraph& Graph) { 00130 TIntV MxDegV; 00131 int MxDeg=-1; 00132 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00133 if (MxDeg < NI.GetDeg()) { MxDegV.Clr(); MxDeg = NI.GetDeg(); } 00134 if (MxDeg == NI.GetDeg()) { MxDegV.Add(NI.GetId()); } 00135 } 00136 EAssertR(! MxDegV.Empty(), "Input graph is empty!"); 00137 return MxDegV[TInt::Rnd.GetUniDevInt(MxDegV.Len())]; 00138 } 00139 00140 template <class PGraph> 00141 int GetMxInDegNId(const PGraph& Graph) { 00142 TIntV MxDegV; 00143 int MxDeg=-1; 00144 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00145 if (MxDeg < NI.GetInDeg()) { MxDegV.Clr(); MxDeg = NI.GetInDeg(); } 00146 if (MxDeg == NI.GetInDeg()) { MxDegV.Add(NI.GetId()); } 00147 } 00148 EAssertR(! MxDegV.Empty(), "Input graph is empty!"); 00149 return MxDegV[TInt::Rnd.GetUniDevInt(MxDegV.Len())]; 00150 } 00151 00152 template <class PGraph> 00153 int GetMxOutDegNId(const PGraph& Graph) { 00154 TIntV MxDegV; 00155 int MxDeg=-1; 00156 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00157 if (MxDeg < NI.GetOutDeg()) { MxDegV.Clr(); MxDeg = NI.GetOutDeg(); } 00158 if (MxDeg == NI.GetOutDeg()) { MxDegV.Add(NI.GetId()); } 00159 } 00160 EAssertR(! MxDegV.Empty(), "Input graph is empty!"); 00161 return MxDegV[TInt::Rnd.GetUniDevInt(MxDegV.Len())]; 00162 } 00163 00164 template <class PGraph> 00165 void GetInDegCnt(const PGraph& Graph, TIntPrV& DegToCntV) { 00166 TIntH DegToCntH; 00167 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00168 DegToCntH.AddDat(NI.GetInDeg())++; } 00169 DegToCntV.Gen(DegToCntH.Len(), 0); 00170 for (int i = 0; i < DegToCntH.Len(); i++) { 00171 DegToCntV.Add(TIntPr(DegToCntH.GetKey(i), DegToCntH[i])); } 00172 DegToCntV.Sort(); 00173 } 00174 00175 template <class PGraph> 00176 void GetInDegCnt(const PGraph& Graph, TFltPrV& DegToCntV) { 00177 TIntH DegToCntH; 00178 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00179 DegToCntH.AddDat(NI.GetInDeg())++; } 00180 DegToCntV.Gen(DegToCntH.Len(), 0); 00181 for (int i = 0; i < DegToCntH.Len(); i++) { 00182 DegToCntV.Add(TFltPr(DegToCntH.GetKey(i).Val, DegToCntH[i].Val)); } 00183 DegToCntV.Sort(); 00184 } 00185 00186 template <class PGraph> 00187 void GetOutDegCnt(const PGraph& Graph, TIntPrV& DegToCntV) { 00188 TIntH DegToCntH; 00189 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00190 DegToCntH.AddDat(NI.GetOutDeg())++; } 00191 DegToCntV.Gen(DegToCntH.Len(), 0); 00192 for (int i = 0; i < DegToCntH.Len(); i++) { 00193 DegToCntV.Add(TIntPr(DegToCntH.GetKey(i), DegToCntH[i])); } 00194 DegToCntV.Sort(); 00195 } 00196 00197 template <class PGraph> 00198 void GetOutDegCnt(const PGraph& Graph, TFltPrV& DegToCntV) { 00199 TIntH DegToCntH; 00200 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00201 DegToCntH.AddDat(NI.GetOutDeg())++; } 00202 DegToCntV.Gen(DegToCntH.Len(), 0); 00203 for (int i = 0; i < DegToCntH.Len(); i++) { 00204 DegToCntV.Add(TFltPr(DegToCntH.GetKey(i).Val, DegToCntH[i].Val)); } 00205 DegToCntV.Sort(); 00206 } 00207 00208 template <class PGraph> 00209 void GetDegCnt(const PGraph& Graph, TIntPrV& DegToCntV) { 00210 TIntH DegToCntH; 00211 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00212 DegToCntH.AddDat(NI.GetDeg())++; } 00213 DegToCntV.Gen(DegToCntH.Len(), 0); 00214 for (int i = 0; i < DegToCntH.Len(); i++) { 00215 DegToCntV.Add(TIntPr(DegToCntH.GetKey(i), DegToCntH[i])); } 00216 DegToCntV.Sort(); 00217 } 00218 00219 template <class PGraph> 00220 void GetDegCnt(const PGraph& Graph, TFltPrV& DegToCntV) { 00221 TIntH DegToCntH; 00222 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00223 DegToCntH.AddDat(NI.GetDeg())++; } 00224 DegToCntV.Gen(DegToCntH.Len(), 0); 00225 for (int i = 0; i < DegToCntH.Len(); i++) { 00226 DegToCntV.Add(TFltPr(DegToCntH.GetKey(i).Val, DegToCntH[i].Val)); } 00227 DegToCntV.Sort(); 00228 } 00229 00230 template <class PGraph> 00231 void GetDegSeqV(const PGraph& Graph, TIntV& DegV) { 00232 DegV.Gen(Graph->GetNodes(), 0); 00233 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00234 DegV.Add(NI.GetDeg()); 00235 } 00236 } 00237 00238 template <class PGraph> 00239 void GetDegSeqV(const PGraph& Graph, TIntV& InDegV, TIntV& OutDegV) { 00240 InDegV.Gen(Graph->GetNodes(), 0); 00241 OutDegV.Gen(Graph->GetNodes(), 0); 00242 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00243 InDegV.Add(NI.GetInDeg()); 00244 OutDegV.Add(NI.GetOutDeg()); 00245 } 00246 } 00247 00248 template <class PGraph> 00249 void GetNodeInDegV(const PGraph& Graph, TIntPrV& NIdInDegV) { 00250 NIdInDegV.Reserve(Graph->GetNodes(), 0); 00251 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00252 NIdInDegV.Add(TIntPr(NI.GetId(), NI.GetInDeg())); 00253 } 00254 } 00255 00256 template <class PGraph> 00257 void GetNodeOutDegV(const PGraph& Graph, TIntPrV& NIdOutDegV) { 00258 NIdOutDegV.Reserve(Graph->GetNodes(), 0); 00259 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00260 NIdOutDegV.Add(TIntPr(NI.GetId(), NI.GetOutDeg())); 00261 } 00262 } 00263 00265 template <class PGraph> 00266 int CntUniqUndirEdges(const PGraph& Graph) { 00267 TIntSet NbrSet; 00268 int Cnt = 0; 00269 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00270 NbrSet.Clr(false); 00271 for (int e = 0; e < NI.GetDeg(); e++) { // unique neighbors of a node 00272 NbrSet.AddKey(NI.GetNbrNId(e)); 00273 } 00274 Cnt += NbrSet.Len(); 00275 } 00276 return Cnt / 2; 00277 } 00278 00280 template <class PGraph> 00281 int CntUniqDirEdges(const PGraph& Graph) { 00282 TIntSet NbrSet; 00283 int Cnt = 0; 00284 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00285 NbrSet.Clr(false); 00286 for (int e = 0; e < NI.GetOutDeg(); e++) { // unique out-neighbors of a node 00287 NbrSet.AddKey(NI.GetOutNId(e)); 00288 } 00289 Cnt += NbrSet.Len(); 00290 } 00291 return Cnt; 00292 } 00293 00295 template <class PGraph> 00296 int CntUniqBiDirEdges(const PGraph& Graph) { 00297 if (! Graph->HasFlag(gfDirected)) { // graph is undirected 00298 return CntUniqUndirEdges(Graph); // then every edge is bi-directional 00299 } 00300 TIntSet NbrSet; 00301 int Cnt = 0; 00302 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00303 const int SrcId = NI.GetId(); 00304 for (int e = 0; e < NI.GetOutDeg(); e++) { 00305 const int DstId = NI.GetOutNId(e); 00306 if (DstId <= SrcId) { continue; } // count each un-dir edge only once 00307 if (Graph->IsEdge(DstId, SrcId)) { Cnt++; } 00308 } 00309 } 00310 return 2*Cnt; 00311 } 00312 00313 template <class PGraph> 00314 int CntSelfEdges(const PGraph& Graph) { 00315 int Cnt = 0; 00316 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00317 if (Graph->IsEdge(NI.GetId(), NI.GetId())) { Cnt++; } 00318 } 00319 return Cnt; 00320 } 00321 00322 template <class PGraph> 00323 PGraph GetUnDir(const PGraph& Graph) { 00324 PGraph NewGraphPt = PGraph::New(); 00325 *NewGraphPt = *Graph; 00326 MakeUnDir(NewGraphPt); 00327 return NewGraphPt; 00328 } 00329 00330 template <class PGraph> 00331 void MakeUnDir(const PGraph& Graph) { 00332 CAssert(HasGraphFlag(typename PGraph::TObj, gfDirected)); // graph has to be directed 00333 TIntPrV EdgeV; 00334 for (typename PGraph::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { 00335 const int SrcNId = EI.GetSrcNId(); 00336 const int DstNId = EI.GetDstNId(); 00337 if (! Graph->IsEdge(DstNId, SrcNId)) { 00338 EdgeV.Add(TIntPr(DstNId, SrcNId)); 00339 } 00340 } 00341 for (int i = 0; i < EdgeV.Len(); i++) { 00342 Graph->AddEdge(EdgeV[i].Val1, EdgeV[i].Val2); 00343 } 00344 } 00345 00346 template <class PGraph> 00347 void AddSelfEdges(const PGraph& Graph) { 00348 TIntV EdgeV; 00349 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00350 const int NId = NI.GetId(); 00351 if (! Graph->IsEdge(NId, NId)) { 00352 EdgeV.Add(NId); 00353 } 00354 } 00355 for (int i = 0; i < EdgeV.Len(); i++) { 00356 Graph->AddEdge(EdgeV[i], EdgeV[i]); 00357 } 00358 } 00359 00360 namespace TSnapDetail { 00361 00362 template <class PGraph, bool IsMultiGraph> 00363 struct TDelSelfEdges { // not a multigraph graph 00364 static void Do(const PGraph& Graph) { 00365 TIntV EdgeV; 00366 // node graph, no explicit edge ids 00367 for (typename PGraph::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { 00368 if (EI.GetSrcNId() == EI.GetDstNId()) { 00369 EdgeV.Add(EI.GetSrcNId()); 00370 } 00371 } 00372 for (int i = 0; i < EdgeV.Len(); i++) { 00373 Graph->DelEdge(EdgeV[i], EdgeV[i]); 00374 } 00375 } 00376 }; 00377 00378 template <class PGraph> 00379 struct TDelSelfEdges<PGraph, true> { // mutligraph specialization 00380 static void Do(const PGraph& Graph) { 00381 TIntV EdgeV; 00382 for (typename PGraph::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { 00383 if (EI.GetSrcNId() == EI.GetDstNId()) { 00384 IAssert(EI.GetId() >= 0); // real edge id 00385 EdgeV.Add(EI.GetId()); 00386 } 00387 } 00388 for (int i = 0; i < EdgeV.Len(); i++) { // delete all edges between a pair of nodes 00389 Graph->DelEdge(EdgeV[i]); 00390 } 00391 } 00392 }; 00393 00394 } // namespace TSnapDetail 00395 00396 template <class PGraph> 00397 void DelSelfEdges(const PGraph& Graph) { 00398 TSnapDetail::TDelSelfEdges<PGraph, HasGraphFlag(typename PGraph::TObj, gfMultiGraph)> 00399 ::Do(Graph); 00400 } 00401 00402 template <class PGraph> 00403 void DelNodes(PGraph& Graph, const TIntV& NIdV) { 00404 for (int n = 0; n < NIdV.Len(); n++) { 00405 Graph->DelNode(NIdV[n]); 00406 } 00407 } 00408 00409 template <class PGraph> 00410 void DelZeroDegNodes(PGraph& Graph) { 00411 TIntV DelNIdV; 00412 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00413 if (NI.GetDeg() == 0) { 00414 DelNIdV.Add(NI.GetId()); 00415 } 00416 } 00417 for (int i = 0; i < DelNIdV.Len(); i++) { 00418 Graph->DelNode(DelNIdV[i]); 00419 } 00420 } 00421 00422 template <class PGraph> 00423 void DelDegKNodes(PGraph& Graph, const int& OutDegK, const int& InDegK) { 00424 TIntV DelNIdV; 00425 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00426 if (NI.GetOutDeg() == OutDegK || NI.GetInDeg() == InDegK) { 00427 DelNIdV.Add(NI.GetId()); 00428 } 00429 } 00430 for (int i = 0; i < DelNIdV.Len(); i++) { 00431 Graph->DelNode(DelNIdV[i]); 00432 } 00433 } 00434 00435 // tree has directed edges -- so root is a well-defined 00436 // children point to a parent 00437 template <class PGraph> 00438 bool IsTree(const PGraph& Graph, int& RootNId) { 00439 if (Graph->GetNodes() == 1 && Graph->GetEdges() == 0) { 00440 RootNId = Graph->BegNI().GetId(); 00441 return true; 00442 } 00443 RootNId = -1; 00444 if (Graph->GetNodes() != Graph->GetEdges()+1) { return false; } 00445 int NZeroOutDeg = 0; 00446 int ZeroOutDegN = -1; 00447 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00448 if (NI.GetOutDeg() == 0) { 00449 ZeroOutDegN = NI.GetId(); NZeroOutDeg++; 00450 } 00451 if (NI.GetDeg() == 0) { return false; } // isolated nodes 00452 } 00453 if (NZeroOutDeg==1) { 00454 if (! TSnap::IsConnected(Graph)) { return false; } 00455 RootNId = ZeroOutDegN; return true; 00456 } 00457 return false; 00458 } 00459 00460 // tree signature -- for each level we sort the node in-degrees and concatenate them into a vector 00461 template <class PGraph> 00462 void GetTreeSig(const PGraph& Graph, const int& RootNId, TIntV& Sig) { 00463 CAssert(HasGraphFlag(typename PGraph::TObj, gfDirected)); 00464 Sig.Gen(Graph->GetNodes(), 0); 00465 TSnapQueue<int> NIdQ(Graph->GetNodes()); 00466 NIdQ.Push(RootNId); 00467 int LastPos = 0, NodeCnt = 1; 00468 while (! NIdQ.Empty()) { 00469 const typename PGraph::TObj::TNodeI Node = Graph->GetNI(NIdQ.Top()); NIdQ.Pop(); 00470 IAssert(Node.GetInDeg()==0 || Node.GetOutDeg()==0); // child points or is-pointed to by the parent 00471 if (Node.GetInDeg() != 0) { 00472 for (int e = 0; e < Node.GetInDeg(); e++) { 00473 NIdQ.Push(Node.GetInNId(e)); } 00474 } else if (Node.GetOutDeg() != 0) { 00475 for (int e = 0; e < Node.GetOutDeg(); e++) { 00476 NIdQ.Push(Node.GetOutNId(e)); } 00477 } 00478 Sig.Add(Node.GetInDeg()); 00479 if (--NodeCnt == 0) { 00480 for (int i = LastPos; i < Sig.Len(); i++) NodeCnt += Sig[i]; 00481 Sig.QSort(LastPos, Sig.Len()-1, false); 00482 LastPos = Sig.Len(); 00483 } 00484 } 00485 } 00486 00487 // tree signature -- for each level we sort the node in-degrees and concatenate them into a vector 00488 template <class PGraph> 00489 void GetTreeSig(const PGraph& Graph, const int& RootNId, TIntV& Sig, TIntPrV& NodeMap) { 00490 CAssert(HasGraphFlag(typename PGraph::TObj, gfDirected)); 00491 NodeMap.Gen(Graph->GetNodes(), 0); 00492 Sig.Gen(Graph->GetNodes(), 0); 00493 TSnapQueue<int> NIdQ(Graph->GetNodes()); 00494 NIdQ.Push(RootNId); 00495 int LastPos = 0, NodeCnt = 1; 00496 while (! NIdQ.Empty()) { 00497 const typename PGraph::TObj::TNodeI Node = Graph->GetNI(NIdQ.Top()); NIdQ.Pop(); 00498 IAssert(Node.GetInDeg()==0 || Node.GetOutDeg()==0); // child points or is-pointed to by the parent 00499 if (Node.GetInDeg() != 0) { 00500 for (int e = 0; e < Node.GetInDeg(); e++) { 00501 NIdQ.Push(Node.GetInNId(e)); } 00502 NodeMap.Add(TIntPr(Node.GetInDeg(), Node.GetId())); 00503 } else if (Node.GetOutDeg() != 0) { 00504 for (int e = 0; e < Node.GetOutDeg(); e++) { 00505 NIdQ.Push(Node.GetOutNId(e)); } 00506 NodeMap.Add(TIntPr(Node.GetOutDeg(), Node.GetId())); 00507 } 00508 if (--NodeCnt == 0) { 00509 for (int i = LastPos; i < NodeMap.Len(); i++) { 00510 NodeCnt += NodeMap[i].Val1; } 00511 NodeMap.QSort(LastPos, NodeMap.Len()-1, false); 00512 LastPos = NodeMap.Len(); 00513 } 00514 } 00515 for (int i = 0; i < NodeMap.Len(); i++) { 00516 Sig.Add(NodeMap[i].Val1); // degree dignature 00517 NodeMap[i].Val1 = NodeMap[i].Val2; 00518 NodeMap[i].Val2 = i; 00519 } 00520 } 00521 00522 }; // namespace TSnap