9 template <
class PGraph>
PNGraph GetBfsTree(
const PGraph& Graph,
const int& StartNId,
const bool& FollowOut,
const bool& FollowIn);
11 template <
class PGraph>
int GetSubTreeSz(
const PGraph& Graph,
const int& StartNId,
const bool& FollowOut,
const bool& FollowIn,
int& TreeSzX,
int& TreeDepthX);
15 template <
class PGraph>
int GetNodesAtHop(
const PGraph& Graph,
const int& StartNId,
const int& Hop,
TIntV& NIdV,
const bool& IsDir=
false);
19 template <
class PGraph>
int GetNodesAtHops(
const PGraph& Graph,
const int& StartNId,
TIntPrV& HopCntV,
const bool& IsDir=
false);
26 template <
class PGraph>
int GetShortPath(
const PGraph& Graph,
const int& SrcNId,
const int& DstNId,
const bool& IsDir=
false);
32 template <
class PGraph>
int GetShortPath(
const PGraph& Graph,
const int& SrcNId,
TIntH& NIdToDistH,
const bool& IsDir=
false,
const int& MaxDist=
TInt::Mx);
40 template <
class PGraph>
int GetBfsFullDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir=
false);
44 template <
class PGraph>
double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir=
false);
48 template <
class PGraph>
double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir,
double& EffDiamX,
int& FullDiamX);
50 template <
class PGraph>
double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir,
double& EffDiamX,
int& FullDiamX,
double& AvgSPLX);
52 template <
class PGraph>
double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const TIntV& SubGraphNIdV,
const bool& IsDir,
double& EffDiamX,
int& FullDiamX);
73 template<
class PGraph>
81 TBreathFS(
const PGraph& GraphPt,
const bool& InitBigQ=
true) :
84 void SetGraph(
const PGraph& GraphPt);
86 int DoBfs(
const int& StartNode,
const bool& FollowOut,
const bool& FollowIn,
const int& TargetNId=-1,
const int& MxDist=
TInt::Mx);
88 int DoBfsHybrid(
const int& StartNode,
const bool& FollowOut,
const bool& FollowIn,
const int& TargetNId=-1,
const int& MxDist=
TInt::Mx);
95 int GetHops(
const int& SrcNId,
const int& DstNId)
const;
98 int GetRndPath(
const int& SrcNId,
const int& DstNId,
TIntV& PathNIdV)
const;
103 static const unsigned int alpha = 100;
104 static const unsigned int beta = 20;
106 bool TopDownStep(
TIntV &NIdDistV,
TIntV *Frontier,
TIntV *NextFrontier,
int& MaxDist,
const int& TargetNId,
const bool& FollowOut,
const bool& FollowIn);
107 bool BottomUpStep(
TIntV &NIdDistV,
TIntV *Frontier,
TIntV *NextFrontier,
int& MaxDist,
const int& TargetNId,
const bool& FollowOut,
const bool& FollowIn);
110 template<
class PGraph>
113 const int N=GraphPt->GetNodes();
114 if (Queue.Reserved() < N) { Queue.Gen(N); }
115 if (NIdDistH.GetReservedKeyIds() < N) { NIdDistH.Gen(N); }
118 template<
class PGraph>
119 int TBreathFS<PGraph>::DoBfs(
const int& StartNode,
const bool& FollowOut,
const bool& FollowIn,
const int& TargetNId,
const int& MxDist) {
120 StartNId = StartNode;
121 IAssert(Graph->IsNode(StartNId));
124 NIdDistH.Clr(
false); NIdDistH.AddDat(StartNId, 0);
125 Queue.Clr(
false); Queue.Push(StartNId);
127 while (! Queue.Empty()) {
128 const int NId = Queue.Top(); Queue.Pop();
129 const int Dist = NIdDistH.GetDat(NId);
130 if (Dist == MxDist) {
break; }
131 const typename PGraph::TObj::TNodeI NodeI = Graph->GetNI(NId);
133 for (v = 0; v < NodeI.GetOutDeg(); v++) {
134 const int DstNId = NodeI.GetOutNId(v);
135 if (! NIdDistH.IsKey(DstNId)) {
136 NIdDistH.AddDat(DstNId, Dist+1);
138 if (DstNId == TargetNId) {
return MaxDist; }
144 for (v = 0; v < NodeI.GetInDeg(); v++) {
145 const int DstNId = NodeI.GetInNId(v);
146 if (! NIdDistH.IsKey(DstNId)) {
147 NIdDistH.AddDat(DstNId, Dist+1);
149 if (DstNId == TargetNId) {
return MaxDist; }
158 template<
class PGraph>
160 StartNId = StartNode;
161 IAssert(Graph->IsNode(StartNId));
162 if (TargetNId == StartNode)
return 0;
163 const typename PGraph::TObj::TNodeI StartNodeI = Graph->GetNI(StartNode);
166 TIntV NIdDistV(Graph->GetMxNId() + 1);
167 for (
int i = 0; i < NIdDistV.Len(); i++) {
170 TIntV *Frontier =
new TIntV(Graph->GetNodes(), 0);
171 TIntV *NextFrontier =
new TIntV(Graph->GetNodes(), 0);
173 NIdDistV.
SetVal(StartNId, 0);
174 Frontier->
Add(StartNId);
177 const unsigned int TotalNodes = Graph->GetNodes();
178 unsigned int UnvisitedNodes = Graph->GetNodes();
179 while (! Frontier->
Empty()) {
181 NextFrontier->Clr(
false);
182 if (MaxDist == MxDist) {
break; }
184 UnvisitedNodes -= Frontier->
Len();
185 if (Stage == 0 && UnvisitedNodes / Frontier->
Len() < alpha) {
187 }
else if (Stage == 1 && TotalNodes / Frontier->
Len() > beta) {
192 bool targetFound =
false;
193 if (Stage == 0 || Stage == 2) {
194 targetFound = TopDownStep(NIdDistV, Frontier, NextFrontier, MaxDist, TargetNId, FollowOut, FollowIn);
196 targetFound = BottomUpStep(NIdDistV, Frontier, NextFrontier, MaxDist, TargetNId, FollowOut, FollowIn);
199 MaxDist = NIdDistV[TargetNId];
204 TIntV *temp = Frontier;
205 Frontier = NextFrontier;
213 for (
int NId = 0; NId < NIdDistV.Len(); NId++) {
214 if (NIdDistV[NId] != -1) {
215 NIdDistH.AddDat(NId, NIdDistV[NId]);
221 template<
class PGraph>
225 const int Dist = NIdDistV[NId];
227 const typename PGraph::TObj::TNodeI NodeI = Graph->GetNI(NId);
229 for (
int v = 0; v < NodeI.GetOutDeg(); v++) {
230 const int NeighborNId = NodeI.GetOutNId(v);
231 if (NIdDistV[NeighborNId] == -1) {
232 NIdDistV.
SetVal(NeighborNId, Dist+1);
233 if (NeighborNId == TargetNId)
return true;
234 NextFrontier->
Add(NeighborNId);
239 for (
int v = 0; v < NodeI.GetInDeg(); v++) {
240 const int NeighborNId = NodeI.GetInNId(v);
241 if (NIdDistV[NeighborNId] == -1) {
242 NIdDistV.
SetVal(NeighborNId, Dist+1);
243 if (NeighborNId == TargetNId)
return true;
244 NextFrontier->
Add(NeighborNId);
252 template<
class PGraph>
254 for (
typename PGraph::TObj::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) {
255 const int NId = NodeI.GetId();
256 if (NIdDistV[NId] == -1) {
258 for (
int v = 0; v < NodeI.GetInDeg(); v++) {
259 const int ParentNId = NodeI.GetInNId(v);
260 if (NIdDistV[ParentNId] == MaxDist) {
261 NIdDistV[NId] = MaxDist + 1;
262 if (NId == TargetNId)
return true;
263 NextFrontier->
Add(NId);
268 if (FollowIn && NIdDistV[NId] == -1) {
269 for (
int v = 0; v < NodeI.GetOutDeg(); v++) {
270 const int ParentNId = NodeI.GetOutNId(v);
271 if (NIdDistV[ParentNId] == MaxDist) {
272 NIdDistV[NId] = MaxDist + 1;
273 if (NId == TargetNId)
return true;
274 NextFrontier->
Add(NId);
284 template<
class PGraph>
287 if (SrcNId!=StartNId) {
return -1; }
288 if (! NIdDistH.IsKeyGetDat(DstNId, Dist)) {
return -1; }
292 template<
class PGraph>
295 if (SrcNId!=StartNId || ! NIdDistH.IsKey(DstNId)) {
return -1; }
296 PathNIdV.
Add(DstNId);
299 TInt CurDist, NextDist;
300 while (CurNId != SrcNId) {
301 typename PGraph::TObj::TNodeI NI = Graph->GetNI(CurNId);
302 IAssert(NIdDistH.IsKeyGetDat(CurNId, CurDist));
303 CloserNIdV.
Clr(
false);
304 for (
int e = 0; e < NI.GetDeg(); e++) {
305 const int Next = NI.GetNbrNId(e);
306 if (NIdDistH.IsKeyGetDat(Next, NextDist)) {
307 if (NextDist == CurDist-1) { CloserNIdV.
Add(Next); }
312 PathNIdV.
Add(CurNId);
315 return PathNIdV.
Len()-1;
322 template <
class PGraph>
323 PNGraph GetBfsTree(
const PGraph& Graph,
const int& StartNId,
const bool& FollowOut,
const bool& FollowIn) {
331 typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
336 for (
int e = 0; e < NI.GetInDeg(); e++) {
337 const int Prev = NI.GetInNId(e);
343 for (
int e = 0; e < NI.GetOutDeg(); e++) {
344 const int Prev = NI.GetOutNId(e);
353 template <
class PGraph>
354 int GetSubTreeSz(
const PGraph& Graph,
const int& StartNId,
const bool& FollowOut,
const bool& FollowIn,
int& TreeSz,
int& TreeDepth) {
365 template <
class PGraph>
366 int GetNodesAtHop(
const PGraph& Graph,
const int& StartNId,
const int& Hop,
TIntV& NIdV,
const bool& IsDir) {
368 BFS.
DoBfs(StartNId,
true, !IsDir, -1, Hop);
377 template <
class PGraph>
387 return HopCntV.
Len();
390 template <
class PGraph>
391 int GetShortPath(
const PGraph& Graph,
const int& SrcNId,
TIntH& NIdToDistH,
const bool& IsDir,
const int& MaxDist) {
393 BFS.
DoBfs(SrcNId,
true, ! IsDir, -1, MaxDist);
396 return NIdToDistH[NIdToDistH.
Len()-1];
399 template <
class PGraph>
400 int GetShortPath(
const PGraph& Graph,
const int& SrcNId,
const int& DstNId,
const bool& IsDir) {
403 return BFS.
GetHops(SrcNId, DstNId);
406 template <
class PGraph>
407 int GetBfsFullDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir) {
414 template <
class PGraph>
415 double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir) {
422 template <
class PGraph>
423 double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir,
double& EffDiam,
int& FullDiam) {
425 EffDiam = -1; FullDiam = -1;
426 return GetBfsEffDiam(Graph, NTestNodes, IsDir, EffDiam, FullDiam, AvgDiam);
429 template <
class PGraph>
430 double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const bool& IsDir,
double& EffDiam,
int& FullDiam,
double& AvgSPL) {
431 EffDiam = -1; FullDiam = -1; AvgSPL = -1;
437 for (
int tries = 0; tries <
TMath::Mn(NTestNodes, Graph->GetNodes()); tries++) {
438 const int NId = NodeIdV[tries];
444 double SumPathL=0, PathCnt=0;
445 for (
int i = 0; i < DistToCntH.
Len(); i++) {
447 SumPathL += DistToCntH.
GetKey(i) * DistToCntH[i];
448 PathCnt += DistToCntH[i];
452 FullDiam = DistNbrsPdfV.
Last().Key;
453 AvgSPL = SumPathL/PathCnt;
457 template <
class PGraph>
458 double GetBfsEffDiam(
const PGraph& Graph,
const int& NTestNodes,
const TIntV& SubGraphNIdV,
const bool& IsDir,
double& EffDiam,
int& FullDiam) {
467 for (
int tries = 0; tries <
TMath::Mn(NTestNodes, SubGraphNIdV.
Len()); tries++) {
468 const int NId = NodeIdV[tries];
470 for (
int i = 0; i < SubGraphNIdV.
Len(); i++) {
472 DistToCntH.
AddDat(Dist) += 1;
477 for (
int i = 0; i < DistToCntH.
Len(); i++) {
482 FullDiam = DistNbrsPdfV.
Last().Key;
486 template <
class PGraph>
489 int MxNId = Graph->GetMxNId();
490 int NonNodeDepth = 2147483647;
491 int InfDepth = 2147483646;
492 ShortestDists.
Gen(MxNId);
493 for (
int NId = 0; NId < MxNId; NId++) {
494 if (Graph->IsNode(NId)) { ShortestDists[NId] = InfDepth; }
495 else { ShortestDists[NId] = NonNodeDepth; }
498 TIntV Vec1(MxNId, 0);
499 TIntV Vec2(MxNId, 0);
501 ShortestDists[StartNId] = 0;
502 TIntV* PCurV = &Vec1;
503 PCurV->
Add(StartNId);
504 TIntV* PNextV = &Vec2;
506 while (!PCurV->
Empty()) {
508 for (
int i = 0; i < PCurV->
Len(); i++) {
509 int NId = PCurV->
GetVal(i);
510 typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
511 for (
int e = 0; e < NI.GetOutDeg(); e++) {
512 const int OutNId = NI.GetOutNId(e);
513 if (ShortestDists[OutNId].Val == InfDepth) {
514 ShortestDists[OutNId] = Depth;
530 template <
class PGraph>
532 int MxNId = Graph->GetMxNId();
533 int NonNodeDepth = 2147483647;
534 int InfDepth = 2147483646;
535 ShortestDists.
Gen(MxNId);
536 #pragma omp parallel for schedule(dynamic,10000)
537 for (
int NId = 0; NId < MxNId; NId++) {
538 if (Graph->IsNode(NId)) { ShortestDists[NId] = InfDepth; }
539 else { ShortestDists[NId] = NonNodeDepth; }
542 TIntV Vec1(MxNId, 0);
543 TIntV Vec2(MxNId, 0);
545 ShortestDists[StartNId] = 0;
546 TIntV* PCurV = &Vec1;
547 PCurV->
Add(StartNId);
548 TIntV* PNextV = &Vec2;
551 while (!PCurV->
Empty()) {
553 #pragma omp parallel for schedule(dynamic,10000)
554 for (
int i = 0; i < PCurV->
Len(); i++) {
555 int NId = PCurV->
GetVal(i);
556 typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
557 for (
int e = 0; e < NI.GetOutDeg(); e++) {
558 const int OutNId = NI.GetOutNId(e);
559 if (__sync_bool_compare_and_swap(&(ShortestDists[OutNId].Val), InfDepth, Depth)) {
560 PNextV->
AddMP(OutNId);
static const T & Mn(const T &LVal, const T &RVal)
bool BottomUpStep(TIntV &NIdDistV, TIntV *Frontier, TIntV *NextFrontier, int &MaxDist, const int &TargetNId, const bool &FollowOut, const bool &FollowIn)
TIter EndI() const
Returns an iterator referring to the past-the-end element in the vector.
int GetHops(const int &SrcNId, const int &DstNId) const
static const unsigned int beta
int GetShortestDistances(const PGraph &Graph, const int &StartNId, const bool &FollowOut, const bool &FollowIn, TIntV &ShortestDists)
int GetBfsFullDiam(const PGraph &Graph, const int &NTestNodes, const bool &IsDir=false)
Returns the (approximation of the) Diameter (maximum shortest path length) of a graph (by performing ...
bool TopDownStep(TIntV &NIdDistV, TIntV *Frontier, TIntV *NextFrontier, int &MaxDist, const int &TargetNId, const bool &FollowOut, const bool &FollowIn)
double GetBfsEffDiam(const PGraph &Graph, const int &NTestNodes, const bool &IsDir=false)
Returns the (approximation of the) Effective Diameter (90-th percentile of the distribution of shorte...
static const T & Mx(const T &LVal, const T &RVal)
static PNGraph New()
Static constructor that returns a pointer to the graph. Call: PNGraph Graph = TNGraph::New().
int DoBfs(const int &StartNode, const bool &FollowOut, const bool &FollowIn, const int &TargetNId=-1, const int &MxDist=TInt::Mx)
Performs BFS from node id StartNode for at maps MxDist steps by only following in-links (parameter Fo...
TSizeTy Len() const
Returns the number of elements in the vector.
TKeyDat< TInt, TFlt > TIntFltKd
static const unsigned int alpha
TBreathFS(const PGraph &GraphPt, const bool &InitBigQ=true)
int GetNodesAtHops(const PGraph &Graph, const int &StartNId, TIntPrV &HopCntV, const bool &IsDir=false)
Returns the number of nodes at each hop distance from the starting node StartNId. ...
static TPt< TSOut > New()
TSizeTy AddMP(const TVal &Val)
Adds element Val at the end of the vector in a thread safe manner, returns the element index in the v...
int AddNode(int NId=-1)
Adds a node of ID NId to the graph.
const TDat & GetDat(const TKey &Key) const
void Reduce(const TSizeTy &_Vals=-1)
Reduces the vector's length to _Vals elements, which must be less than the current length...
void SetGraph(const PGraph &GraphPt)
Sets the graph to be used by the BFS to GraphPt and resets the data structures.
PNGraph GetBfsTree(const PGraph &Graph, const int &StartNId, const bool &FollowOut, const bool &FollowIn)
Returns a directed Breadth-First-Search tree rooted at StartNId.
bool Empty() const
Tests whether the vector is empty.
int GetRndPath(const int &SrcNId, const int &DstNId, TIntV &PathNIdV) const
const TVal & GetVal(const TSizeTy &ValN) const
Returns a reference to the element at position ValN in the vector.
void Clr(const bool &DoDel=true, const TSizeTy &NoDelLim=-1)
Clears the contents of the vector.
int GetNodesAtHop(const PGraph &Graph, const int &StartNId, const int &Hop, TIntV &NIdV, const bool &IsDir=false)
Finds IDs of all nodes that are at distance Hop from node StartNId.
void Sort(const bool &Asc=true)
Sorts the elements of the vector.
int AddEdge(const int &SrcNId, const int &DstNId)
Adds an edge from node IDs SrcNId to node DstNId to the graph.
double CalcEffDiamPdf(const TIntFltKdV &DistNbrsPdfV, const double &Percentile)
Helper function for computing a given Percentile of a (unnormalized) probability distribution functio...
bool IsNode(const int &NId) const
Tests whether ID NId is a node.
bool IsKeyGetDat(const TKey &Key, TDat &Dat) const
const TVal & Last() const
Returns a reference to the last element of the vector.
int GetSubTreeSz(const PGraph &Graph, const int &StartNId, const bool &FollowOut, const bool &FollowIn, int &TreeSzX, int &TreeDepthX)
Returns the BFS tree size (number of nodes) and depth (number of levels) by following in-links (param...
void SetVal(const TSizeTy &ValN, const TVal &Val)
Sets the value of element at position ValN to Val.
int GetShortestDistancesMP2(const PGraph &Graph, const int &StartNId, const bool &FollowOut, const bool &FollowIn, TIntV &ShortestDists)
void GetKeyV(TVec< TKey > &KeyV) const
TIter BegI() const
Returns an iterator pointing to the first element in the vector.
void Shuffle(TRnd &Rnd)
Randomly shuffles the elements of the vector.
int GetNVisited() const
Returns the number of nodes visited/reached by the BFS.
void GetKeyDatPrV(TVec< TPair< TKey, TDat > > &KeyDatPrV) const
void GetVisitedNIdV(TIntV &NIdV) const
Returns the IDs of the nodes visited/reached by the BFS.
void Clr(const bool &DoDel=true, const int &NoDelLim=-1, const bool &ResetDat=true)
void Reverse()
Reverses the order of the elements in the vector.
int DoBfsHybrid(const int &StartNode, const bool &FollowOut, const bool &FollowIn, const int &TargetNId=-1, const int &MxDist=TInt::Mx)
Same functionality as DoBfs with better performance.
void Gen(const TSizeTy &_Vals)
Constructs a vector (an array) of _Vals elements.
int GetUniDevInt(const int &Range=0)
TSizeTy Add()
Adds a new element at the end of the vector, after its current last element.
int GetShortPath(const PGraph &Graph, const int &SrcNId, const int &DstNId, const bool &IsDir=false)
Returns the length of the shortest path from node SrcNId to node DstNId.
TDat & AddDat(const TKey &Key)
const TKey & GetKey(const int &KeyId) const
void SortByDat(const bool &Asc=true)