SNAP Library 2.0, User Reference  2013-05-13 16:33:57
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
bfsdfs.h
Go to the documentation of this file.
00001 namespace TSnap {
00002 
00004 // BFS and DFS
00006 
00009   template <class PGraph> PNGraph GetBfsTree(const PGraph& Graph, const int& StartNId, const bool& FollowOut, const bool& FollowIn);
00011 template <class PGraph> int GetSubTreeSz(const PGraph& Graph, const int& StartNId, const bool& FollowOut, const bool& FollowIn, int& TreeSz, int& TreeDepth);
00013 
00015 template <class PGraph> int GetNodesAtHop(const PGraph& Graph, const int& StartNId, const int& Hop, TIntV& NIdV, const bool& IsDir=false);
00017 
00019 template <class PGraph> int GetNodesAtHops(const PGraph& Graph, const int& StartNId, TIntPrV& HopCntV, const bool& IsDir=false);
00020 
00022 // Shortest paths
00024 
00026 template <class PGraph> int GetShortPath(const PGraph& Graph, const int& SrcNId, const int& DstNId, const bool& IsDir=false);
00028 
00032 template <class PGraph> int GetShortPath(const PGraph& Graph, const int& SrcNId, TIntH& NIdToDistH, const bool& IsDir=false, const int& MaxDist=TInt::Mx);
00033 
00035 // Diameter
00036 
00038 
00040 template <class PGraph> int GetBfsFullDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir=false);
00042 
00044 template <class PGraph> double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir=false);
00046 
00048 template <class PGraph> double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam);
00050 template <class PGraph> double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam, double& AvgSPL);
00052 template <class PGraph> double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const TIntV& SubGraphNIdV, const bool& IsDir, double& EffDiam, int& FullDiam);
00053 
00054 // TODO: Implement in the future
00055 //template <class PGraph> int GetRangeDist(const PGraph& Graph, const int& SrcNId, const int& DstNId, const bool& IsDir=false);
00056 //template <class PGraph> int GetShortPath(const PGraph& Graph, const int& SrcNId, TIntH& NIdToDistH, const bool& IsDir=false, const int& MaxDist=1000);
00057 //template <class PGraph> int GetShortPath(const PGraph& Graph, const int& SrcNId, const TIntSet& TargetSet, const bool& IsDir, TIntV& PathNIdV);
00058 //template <class PGraph> int GetShortPath(TIntH& NIdPrnH, TCcQueue<int>& NIdQ, const PGraph& Graph, const int& SrcNId, const TIntSet& TargetSet, const bool& IsDir, TIntV& PathNIdV);
00059 //template <class PGraph> int GetMxShortDist(const PGraph& Graph, const int& SrcNId, const bool& IsDir=false);
00060 //template <class PGraph> int GetMxShortDist(const PGraph& Graph, const int& SrcNId, const bool& IsDir, int& MxDistNId);
00061 //template <class PGraph> int GetMxShortDist(const PGraph& Graph, const int& SrcNId, const bool& IsDir, int& MxDistNId, TCcQueue<int>& NIdQ, TCcQueue<int>& DistQ, TIntSet& VisitedH);
00062 //template <class PGraph> int GetMxGreedyDist(const PGraph& Graph, const int& SrcNId, const bool& IsDir=false);
00063 //template <class PGraph> int GetMxGreedyDist(const PGraph& Graph, const int& SrcNId, const bool& IsDir, TCcQueue<int>& NIdQ, TCcQueue<int>& DistQ, TIntSet& VisitedH);
00064 //template <class PGraph> PNGraph GetShortPathsSubGraph(const PGraph& Graph, const TIntV& SubGraphNIdV);
00065 //template <class PGraph> PGraph GetWccPathsSubGraph(const PGraph& Graph, const TIntV& NIdV);
00066 //template <class PGraph> void GetSubTreeSz(const PGraph& Graph, const int& StartNId, const bool& FollowOutEdges, int& TreeSz, int& TreeDepth);
00067 
00068 } // namespace TSnap
00069 
00070 //#//////////////////////////////////////////////
00073 template<class PGraph>
00074 class TBreathFS {
00075 public:
00076   PGraph Graph;
00077   TSnapQueue<int> Queue;
00078   TInt StartNId;
00079   TIntH NIdDistH;
00080 public:
00081   TBreathFS(const PGraph& GraphPt, const bool& InitBigQ=true) :
00082     Graph(GraphPt), Queue(InitBigQ?Graph->GetNodes():1024), NIdDistH(InitBigQ?Graph->GetNodes():1024) { }
00084   void SetGraph(const PGraph& GraphPt);
00086   int DoBfs(const int& StartNode, const bool& FollowOut, const bool& FollowIn, const int& TargetNId=-1, const int& MxDist=TInt::Mx);
00088   int GetNVisited() const { return NIdDistH.Len(); }
00090   void GetVisitedNIdV(TIntV& NIdV) const { NIdDistH.GetKeyV(NIdV); }
00093   int GetHops(const int& SrcNId, const int& DstNId) const;
00096   int GetRndPath(const int& SrcNId, const int& DstNId, TIntV& PathNIdV) const;
00097 };
00098 
00099 template<class PGraph>
00100 void TBreathFS<PGraph>::SetGraph(const PGraph& GraphPt) {
00101   Graph=GraphPt;
00102   const int N=GraphPt->GetNodes();
00103   if (Queue.Reserved() < N) { Queue.Gen(N); }
00104   if (NIdDistH.GetReservedKeyIds() < N) { NIdDistH.Gen(N); }
00105 }
00106 
00107 template<class PGraph>
00108 int TBreathFS<PGraph>::DoBfs(const int& StartNode, const bool& FollowOut, const bool& FollowIn, const int& TargetNId, const int& MxDist) {
00109   StartNId = StartNode;
00110   IAssert(Graph->IsNode(StartNId));
00111 //  const typename PGraph::TObj::TNodeI StartNodeI = Graph->GetNI(StartNode);
00112 //  IAssertR(StartNodeI.GetOutDeg() > 0, TStr::Fmt("No neighbors from start node %d.", StartNode));
00113   NIdDistH.Clr(false);  NIdDistH.AddDat(StartNId, 0);
00114   Queue.Clr(false);  Queue.Push(StartNId);
00115   int v, MaxDist = 0;
00116   while (! Queue.Empty()) {
00117     const int NId = Queue.Top();  Queue.Pop();
00118     const int Dist = NIdDistH.GetDat(NId);
00119     if (Dist == MxDist) { break; } // max distance limit reached
00120     const typename PGraph::TObj::TNodeI NodeI = Graph->GetNI(NId);
00121     if (FollowOut) { // out-links
00122       for (v = 0; v < NodeI.GetOutDeg(); v++) {  // out-links
00123         const int DstNId = NodeI.GetOutNId(v);
00124         if (! NIdDistH.IsKey(DstNId)) {
00125           NIdDistH.AddDat(DstNId, Dist+1);
00126           MaxDist = TMath::Mx(MaxDist, Dist+1);
00127           if (DstNId == TargetNId) { return MaxDist; }
00128           Queue.Push(DstNId);
00129         }
00130       }
00131     }
00132     if (FollowIn) { // in-links
00133       for (v = 0; v < NodeI.GetInDeg(); v++) {
00134         const int DstNId = NodeI.GetInNId(v);
00135         if (! NIdDistH.IsKey(DstNId)) {
00136           NIdDistH.AddDat(DstNId, Dist+1);
00137           MaxDist = TMath::Mx(MaxDist, Dist+1);
00138           if (DstNId == TargetNId) { return MaxDist; }
00139           Queue.Push(DstNId);
00140         }
00141       }
00142     }
00143   }
00144   return MaxDist;
00145 }
00146 
00147 template<class PGraph>
00148 int TBreathFS<PGraph>::GetHops(const int& SrcNId, const int& DstNId) const {
00149   TInt Dist;
00150   if (SrcNId!=StartNId) { return -1; }
00151   if (! NIdDistH.IsKeyGetDat(DstNId, Dist)) { return -1; }
00152   return Dist.Val;
00153 }
00154 
00155 template<class PGraph>
00156 int TBreathFS<PGraph>::GetRndPath(const int& SrcNId, const int& DstNId, TIntV& PathNIdV) const {
00157   PathNIdV.Clr(false);
00158   if (SrcNId!=StartNId || ! NIdDistH.IsKey(DstNId)) { return -1; }
00159   PathNIdV.Add(DstNId);
00160   TIntV CloserNIdV;
00161   int CurNId = DstNId;
00162   TInt CurDist, NextDist;
00163   while (CurNId != SrcNId) {
00164     typename PGraph::TObj::TNodeI NI = Graph->GetNI(CurNId);
00165     IAssert(NIdDistH.IsKeyGetDat(CurNId, CurDist));
00166     CloserNIdV.Clr(false);
00167     for (int e = 0; e < NI.GetDeg(); e++) {
00168       const int Next = NI.GetNbrNId(e);
00169       IAssert(NIdDistH.IsKeyGetDat(Next, NextDist));
00170       if (NextDist == CurDist-1) { CloserNIdV.Add(Next); }
00171     }
00172     IAssert(! CloserNIdV.Empty());
00173     CurNId = CloserNIdV[TInt::Rnd.GetUniDevInt(CloserNIdV.Len())];
00174     PathNIdV.Add(CurNId);
00175   }
00176   PathNIdV.Reverse();
00177   return PathNIdV.Len()-1;
00178 }
00179 
00181 // Implementation
00182 namespace TSnap {
00183 
00184 template <class PGraph>
00185 PNGraph GetBfsTree(const PGraph& Graph, const int& StartNId, const bool& FollowOut, const bool& FollowIn) {
00186   TBreathFS<PGraph> BFS(Graph, false);
00187   BFS.DoBfs(StartNId, FollowOut, FollowIn, -1, TInt::Mx);
00188   PNGraph Tree = TNGraph::New();
00189   BFS.NIdDistH.SortByDat();
00190   for (int i = 0; i < BFS.NIdDistH.Len(); i++) {
00191     const int NId = BFS.NIdDistH.GetKey(i);
00192     const int Dist = BFS.NIdDistH[i];
00193     typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
00194     if (!Tree->IsNode(NId)) {
00195       Tree->AddNode(NId);
00196     }
00197     if (FollowOut) {
00198       for (int e = 0; e < NI.GetInDeg(); e++) {
00199         const int Prev = NI.GetInNId(e);
00200         if (Tree->IsNode(Prev) && BFS.NIdDistH.GetDat(Prev)==Dist-1) {
00201           Tree->AddEdge(Prev, NId); }
00202       }
00203     }
00204     if (FollowIn) {
00205       for (int e = 0; e < NI.GetOutDeg(); e++) {
00206         const int Prev = NI.GetOutNId(e);
00207         if (Tree->IsNode(Prev) && BFS.NIdDistH.GetDat(Prev)==Dist-1) {
00208           Tree->AddEdge(Prev, NId); }
00209       }
00210     }
00211   }
00212   return Tree;
00213 }
00214 
00215 template <class PGraph>
00216 int GetSubTreeSz(const PGraph& Graph, const int& StartNId, const bool& FollowOut, const bool& FollowIn, int& TreeSz, int& TreeDepth) {
00217   TBreathFS<PGraph> BFS(Graph);
00218   BFS.DoBfs(StartNId, FollowOut, FollowIn, -1, TInt::Mx);
00219   TreeSz = BFS.NIdDistH.Len();
00220   TreeDepth = 0;
00221   for (int i = 0; i < BFS.NIdDistH.Len(); i++) {
00222     TreeDepth = TMath::Mx(TreeDepth, BFS.NIdDistH[i].Val);
00223   }
00224   return TreeSz;
00225 }
00226 
00227 template <class PGraph>
00228 int GetNodesAtHop(const PGraph& Graph, const int& StartNId, const int& Hop, TIntV& NIdV, const bool& IsDir) {
00229   TBreathFS<PGraph> BFS(Graph);
00230   BFS.DoBfs(StartNId, true, !IsDir, -1, Hop);
00231   NIdV.Clr(false);
00232   for (int i = 0; i < BFS.NIdDistH.Len(); i++) {
00233     if (BFS.NIdDistH[i] == Hop) {
00234       NIdV.Add(BFS.NIdDistH.GetKey(i)); }
00235   }
00236   return NIdV.Len();
00237 }
00238 
00239 template <class PGraph>
00240 int GetNodesAtHops(const PGraph& Graph, const int& StartNId, TIntPrV& HopCntV, const bool& IsDir) {
00241   TBreathFS<PGraph> BFS(Graph);
00242   BFS.DoBfs(StartNId, true, !IsDir, -1, TInt::Mx);
00243   TIntH HopCntH;
00244   for (int i = 0; i < BFS.NIdDistH.Len(); i++) {
00245     HopCntH.AddDat(BFS.NIdDistH[i]) += 1;
00246   }
00247   HopCntH.GetKeyDatPrV(HopCntV);
00248   HopCntV.Sort();
00249   return HopCntV.Len();
00250 }
00251 
00252 template <class PGraph>
00253 int GetShortPath(const PGraph& Graph, const int& SrcNId, TIntH& NIdToDistH, const bool& IsDir, const int& MaxDist) {
00254   TBreathFS<PGraph> BFS(Graph);
00255   BFS.DoBfs(SrcNId, true, ! IsDir, -1, MaxDist);
00256   NIdToDistH.Clr();
00257   NIdToDistH.Swap(BFS.NIdDistH);
00258   return NIdToDistH[NIdToDistH.Len()-1];
00259 }
00260 
00261 template <class PGraph> 
00262 int GetShortPath(const PGraph& Graph, const int& SrcNId, const int& DstNId, const bool& IsDir) {
00263   TBreathFS<PGraph> BFS(Graph);
00264   BFS.DoBfs(SrcNId, true, ! IsDir, DstNId, TInt::Mx);
00265   return BFS.GetHops(SrcNId, DstNId);
00266 }
00267 
00268 template <class PGraph>
00269 int GetBfsFullDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir) {
00270   int FullDiam;
00271   double EffDiam;
00272   GetBfsEffDiam(Graph, NTestNodes, IsDir, EffDiam, FullDiam);
00273   return FullDiam;
00274 }
00275 
00276 template <class PGraph>
00277 double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir) {
00278   int FullDiam;
00279   double EffDiam;
00280   GetBfsEffDiam(Graph, NTestNodes, IsDir, EffDiam, FullDiam);
00281   return EffDiam;
00282 }
00283 
00284 template <class PGraph>
00285 double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam) {
00286   double AvgDiam;
00287   EffDiam = -1;  FullDiam = -1;
00288   return GetBfsEffDiam(Graph, NTestNodes, IsDir, EffDiam, FullDiam, AvgDiam);
00289 }
00290 
00291 template <class PGraph>
00292 double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam, double& AvgSPL) {
00293   EffDiam = -1;  FullDiam = -1;  AvgSPL = -1;
00294   TIntFltH DistToCntH;
00295   TBreathFS<PGraph> BFS(Graph);
00296   // shotest paths
00297   TIntV NodeIdV;
00298   Graph->GetNIdV(NodeIdV);  NodeIdV.Shuffle(TInt::Rnd);
00299   for (int tries = 0; tries < TMath::Mn(NTestNodes, Graph->GetNodes()); tries++) {
00300     const int NId = NodeIdV[tries];
00301     BFS.DoBfs(NId, true, ! IsDir, -1, TInt::Mx);
00302     for (int i = 0; i < BFS.NIdDistH.Len(); i++) {
00303       DistToCntH.AddDat(BFS.NIdDistH[i]) += 1; }
00304   }
00305   TIntFltKdV DistNbrsPdfV;
00306   double SumPathL=0, PathCnt=0;
00307   for (int i = 0; i < DistToCntH.Len(); i++) {
00308     DistNbrsPdfV.Add(TIntFltKd(DistToCntH.GetKey(i), DistToCntH[i]));
00309     SumPathL += DistToCntH.GetKey(i) * DistToCntH[i];
00310     PathCnt += DistToCntH[i];
00311   }
00312   DistNbrsPdfV.Sort();
00313   EffDiam = TSnap::TSnapDetail::CalcEffDiamPdf(DistNbrsPdfV, 0.9); // effective diameter (90-th percentile)
00314   FullDiam = DistNbrsPdfV.Last().Key;                // approximate full diameter (max shortest path length over the sampled nodes)
00315   AvgSPL = SumPathL/PathCnt;                        // average shortest path length
00316   return EffDiam;
00317 }
00318 
00319 template <class PGraph>
00320 double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const TIntV& SubGraphNIdV, const bool& IsDir, double& EffDiam, int& FullDiam) {
00321   EffDiam = -1;
00322   FullDiam = -1;
00323 
00324   TIntFltH DistToCntH;
00325   TBreathFS<PGraph> BFS(Graph);
00326   // shotest paths
00327   TIntV NodeIdV(SubGraphNIdV);  NodeIdV.Shuffle(TInt::Rnd);
00328   TInt Dist;
00329   for (int tries = 0; tries < TMath::Mn(NTestNodes, SubGraphNIdV.Len()); tries++) {
00330     const int NId = NodeIdV[tries];
00331     BFS.DoBfs(NId, true, ! IsDir, -1, TInt::Mx);
00332     for (int i = 0; i < SubGraphNIdV.Len(); i++) {
00333       if (BFS.NIdDistH.IsKeyGetDat(SubGraphNIdV[i], Dist)) {
00334         DistToCntH.AddDat(Dist) += 1;
00335       }
00336     }
00337   }
00338   TIntFltKdV DistNbrsPdfV;
00339   for (int i = 0; i < DistToCntH.Len(); i++) {
00340     DistNbrsPdfV.Add(TIntFltKd(DistToCntH.GetKey(i), DistToCntH[i]));
00341   }
00342   DistNbrsPdfV.Sort();
00343   EffDiam = TSnap::TSnapDetail::CalcEffDiamPdf(DistNbrsPdfV, 0.9);  // effective diameter (90-th percentile)
00344   FullDiam = DistNbrsPdfV.Last().Key;                 // approximate full diameter (max shortest path length over the sampled nodes)
00345   return EffDiam;                                     // average shortest path length
00346 }
00347 
00348 } // namespace TSnap