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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
alg.h
Go to the documentation of this file.
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