SNAP Library 2.1, Developer Reference
2013-09-25 10:47:25
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 00002 // Defines 00003 #define Kilo(n) (1000*(n)) 00004 #define Mega(n) (1000*1000*(n)) 00005 #define Giga(n) (1000*1000*1000*(n)) 00006 00007 //#////////////////////////////////////////////// 00009 00011 typedef enum TGraphFlag_ { 00012 gfUndef=0, 00013 gfDirected, 00014 gfMultiGraph, 00015 gfNodeDat, 00016 gfEdgeDat, 00017 gfSources, 00018 gfBipart, 00019 gfMx 00020 } TGraphFlag; 00021 00022 namespace TSnap { 00023 00025 template <class TGraph> struct IsDirected { enum { Val = 0 }; }; 00027 template <class TGraph> struct IsMultiGraph { enum { Val = 0 }; }; 00029 template <class TGraph> struct IsNodeDat { enum { Val = 0 }; }; 00031 template <class TGraph> struct IsEdgeDat { enum { Val = 0 }; }; 00033 template <class TGraph> struct IsSources { enum { Val = 0 }; }; 00035 template <class TGraph> struct IsBipart { enum { Val = 0 }; }; 00036 00038 #define HasGraphFlag(TGraph, Flag) \ 00039 ((Flag)==gfDirected ? TSnap::IsDirected<TGraph::TNet>::Val : \ 00040 (Flag)==gfMultiGraph ? TSnap::IsMultiGraph<TGraph::TNet>::Val : \ 00041 (Flag)==gfNodeDat ? TSnap::IsNodeDat<TGraph::TNet>::Val : \ 00042 (Flag)==gfEdgeDat ? TSnap::IsEdgeDat<TGraph::TNet>::Val : \ 00043 (Flag)==gfSources ? TSnap::IsSources<TGraph::TNet>::Val : \ 00044 (Flag)==gfBipart ? TSnap::IsBipart<TGraph::TNet>::Val : 0) 00045 00046 #if 0 00047 // RS 2013/08/19, commented out IsDerivedFrom, it is not called anywhere 00048 // swig throws an error 00050 template<class TDerivClass, class TBaseClass> 00051 class IsDerivedFrom { 00052 private: 00053 struct Yes { char a[1]; }; 00054 struct No { char a[10]; }; 00055 static Yes Test(TBaseClass*); 00056 static No Test(...); // undefined 00057 public: 00058 enum { Val = sizeof(Test(static_cast<TDerivClass*>(0))) == sizeof(Yes) ? 1 : 0 }; 00059 }; 00060 #endif 00061 00063 // Graph Base 00064 00066 TStr GetFlagStr(const TGraphFlag& GraphFlag); 00068 00070 template <class PGraph> void PrintInfo(const PGraph& Graph, const TStr& Desc="", const TStr& OutFNm="", const bool& Fast=true); 00071 00073 // Implementation 00074 00075 // Forward declaration, definition in triad.h 00076 template <class PGraph> int64 GetTriads(const PGraph& Graph, int64& ClosedTriads, int64& OpenTriads, int SampleNodes=-1); 00077 template <class PGraph> double GetBfsEffDiam(const PGraph& Graph, const int& NTestNodes, const bool& IsDir, double& EffDiam, int& FullDiam); 00078 template <class PGraph> double GetMxWccSz(const PGraph& Graph); 00079 template <class PGraph> double GetMxSccSz(const PGraph& Graph); 00080 template<class PGraph> int GetKCoreNodes(const PGraph& Graph, TIntPrV& CoreIdSzV); 00081 template<class PGraph> int GetKCoreEdges(const PGraph& Graph, TIntPrV& CoreIdSzV); 00082 00083 template <class PGraph> 00084 void PrintInfo(const PGraph& Graph, const TStr& Desc, const TStr& OutFNm, const bool& Fast) { 00085 int BiDirEdges=0, ZeroNodes=0, ZeroInNodes=0, ZeroOutNodes=0, SelfEdges=0, NonZIODegNodes=0; 00086 THash<TIntPr, TInt> UniqDirE, UniqUnDirE; 00087 FILE *F = stdout; 00088 if (! OutFNm.Empty()) F = fopen(OutFNm.CStr(), "wt"); 00089 if (! Desc.Empty()) { fprintf(F, "%s:", Desc.CStr()); } 00090 else { fprintf(F, "Graph:"); } 00091 for (int f = gfUndef; f < gfMx; f++) { 00092 if (HasGraphFlag(typename PGraph::TObj, TGraphFlag(f))) { 00093 fprintf(F, " %s", TSnap::GetFlagStr(TGraphFlag(f)).CStr()); } 00094 } 00095 // calc stat 00096 for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00097 if (NI.GetDeg()==0) ZeroNodes++; 00098 if (NI.GetInDeg()==0) ZeroInNodes++; 00099 if (NI.GetOutDeg()==0) ZeroOutNodes++; 00100 if (NI.GetInDeg()!=0 && NI.GetOutDeg()!=0) NonZIODegNodes++; 00101 if (! Fast || Graph->GetNodes() < 1000) { 00102 const int NId = NI.GetId(); 00103 for (int edge = 0; edge < NI.GetOutDeg(); edge++) { 00104 const int DstNId = NI.GetOutNId(edge); 00105 if (Graph->IsEdge(DstNId, NId)) BiDirEdges++; 00106 if (NId == DstNId) SelfEdges++; 00107 UniqDirE.AddKey(TIntPr(NId, DstNId)); 00108 UniqUnDirE.AddKey(TIntPr(TInt::GetMn(NId, DstNId), TInt::GetMx(NId, DstNId))); 00109 } 00110 } 00111 } 00112 int64 Closed=0, Open=0; 00113 double WccSz=0, SccSz=0; 00114 double EffDiam=0; 00115 int FullDiam=0; 00116 if (! Fast) { 00117 TSnap::GetTriads(Graph, Closed, Open); 00118 WccSz = TSnap::GetMxWccSz(Graph); 00119 SccSz = TSnap::GetMxSccSz(Graph); 00120 TSnap::GetBfsEffDiam(Graph, 100, false, EffDiam, FullDiam); 00121 } 00122 // print info 00123 fprintf(F, "\n"); 00124 fprintf(F, " Nodes: %d\n", Graph->GetNodes()); 00125 fprintf(F, " Edges: %d\n", Graph->GetEdges()); 00126 fprintf(F, " Zero Deg Nodes: %d\n", ZeroNodes); 00127 fprintf(F, " Zero InDeg Nodes: %d\n", ZeroInNodes); 00128 fprintf(F, " Zero OutDeg Nodes: %d\n", ZeroOutNodes); 00129 fprintf(F, " NonZero In-Out Deg Nodes: %d\n", NonZIODegNodes); 00130 if (! Fast) { 00131 fprintf(F, " Unique directed edges: %d\n", UniqDirE.Len()); 00132 fprintf(F, " Unique undirected edges: %d\n", UniqUnDirE.Len()); 00133 fprintf(F, " Self Edges: %d\n", SelfEdges); 00134 fprintf(F, " BiDir Edges: %d\n", BiDirEdges); 00135 fprintf(F, " Closed triangles: %s\n", TUInt64::GetStr(Closed).CStr()); 00136 fprintf(F, " Open triangles: %s\n", TUInt64::GetStr(Open).CStr()); 00137 fprintf(F, " Frac. of closed triads: %f\n", Closed/double(Closed+Open)); 00138 fprintf(F, " Connected component size: %f\n", WccSz); 00139 fprintf(F, " Strong conn. comp. size: %f\n", SccSz); 00140 fprintf(F, " Approx. full diameter: %d\n", FullDiam); 00141 fprintf(F, " 90%% effective diameter: %f\n", EffDiam); 00142 //fprintf(F, " Core\tNodes\tEdges\n"); 00143 //for (int i = 0; i < CNodesV.Len(); i++) { 00144 // printf(" %d\t%d\t%d\n", CNodesV[i].Val1(), CNodesV[i].Val2(), CEdgesV[i].Val2()); 00145 //} 00146 } 00147 if (! OutFNm.Empty()) { fclose(F); } 00148 } 00149 00150 } // namespace TSnap 00151 00152 //#////////////////////////////////////////////// 00154 template <class TVal> 00155 class TSnapQueue { 00156 private: 00157 TInt MxFirst; // how often we move the queue to the start of the array 00158 TInt First, Last; 00159 TVec<TVal> ValV; 00160 public: 00161 TSnapQueue() : MxFirst(1024), First(0), Last(0), ValV(MxFirst, 0) { } 00163 TSnapQueue(const int& MxVals) : MxFirst(1024+MxVals/10), First(0), Last(0), ValV(TInt::GetMx(MxFirst, MxVals), 0) { } 00164 TSnapQueue(const int& MxVals, const int& MaxFirst) : MxFirst(MaxFirst), 00165 First(0), Last(0), ValV(TInt::GetMx(MxFirst, MxVals), 0) { } 00166 TSnapQueue(const TSnapQueue& Queue) : MxFirst(Queue.MxFirst), First(Queue.First), Last(Queue.Last), ValV(Queue.ValV) { } 00168 explicit TSnapQueue(TSIn& SIn): MxFirst(SIn), First(SIn), Last(SIn), ValV(SIn) { } 00170 void Save(TSOut& SOut) const { MxFirst.Save(SOut); First.Save(SOut); Last.Save(SOut); ValV.Save(SOut); } 00171 00172 TSnapQueue& operator=(const TSnapQueue& Queue) { if (this != &Queue) { MxFirst=Queue.MxFirst; 00173 First=Queue.First; Last=Queue.Last; ValV=Queue.ValV; } return *this; } 00175 const TVal& operator[](const int& ValN) const { return ValV[First+ValN]; } 00176 00178 void Clr(const bool& DoDel=true) { ValV.Clr(DoDel); First=Last=0; } 00179 void Gen(const int& MxVals, const int& MaxFirst=1024) { 00180 MxFirst=MaxFirst; First=Last=0; ValV.Gen(MxVals, 0); } 00181 00183 bool Empty() const {return First==Last;} 00185 int Len() const {return Last-First;} 00187 int GetFirst() const { return First; } 00189 int GetLast() const { return Last; } 00190 int Reserved() const { return ValV.Reserved(); } 00191 00193 const TVal& Top() const { return ValV[First]; } 00195 void Pop() { First++; 00196 if (First==Last) { ValV.Clr(false); First=Last=0; } } 00198 void Push(const TVal& Val) { 00199 if (First>0 && (First > MxFirst || ValV.Len() == ValV.Reserved()) && ! ValV.Empty()) { 00200 //printf("[move cc queue.Len:%d-->%d]", ValV.Len(),Len()); TExeTm Tm; 00201 memmove(ValV.BegI(), ValV.GetI(First), sizeof(TVal)*Len()); 00202 ValV.Del(Len(), ValV.Len()-1); Last-=First; First=0; 00203 //printf("[%s]\n", Tm.GetStr()); fflush(stdout); 00204 } 00205 //if (ValV.Len() == ValV.Reserved()){ printf("[resizeCCQ]"); fflush(stdout); } 00206 Last++; ValV.Add(Val); 00207 } 00208 }; 00209 00210 //#////////////////////////////////////////////// 00212 00214 class TUnionFind { 00215 private: 00216 THash<TInt, TIntPr> KIdSetH; // key id to (parent, rank) 00217 public: 00219 TInt& Parent(const int& Key) { return KIdSetH.GetDat(Key).Val1; } 00221 TInt& Rank(const int& Key) { return KIdSetH.GetDat(Key).Val2; } 00222 public: 00223 TUnionFind() : KIdSetH() { } 00225 TUnionFind(const int& ExpectKeys) : KIdSetH(ExpectKeys, true) { } 00226 TUnionFind(const TUnionFind& UnionFind) : KIdSetH(UnionFind.KIdSetH) { } 00227 TUnionFind& operator = (const TUnionFind& UF) { KIdSetH=UF.KIdSetH; return *this; } 00228 00230 int Len() const { return KIdSetH.Len(); } 00232 bool IsKey(const int& Key) const { return KIdSetH.IsKey(Key); } 00234 int GetKeyI(const int& KeyN) const { return KIdSetH.GetKey(KeyN); } 00236 int Find(const int& Key); 00238 int Add(const int& Key) { KIdSetH.AddDat(Key, TIntPr(-1, 0)); return Key; } 00240 void Union(const int& Key1, const int& Key2); 00242 bool IsSameSet(const int& Key1, const int& Key2) { 00243 return Find(Key1) == Find(Key2); } 00245 void Dump(); 00246 }; 00247 00248 //#////////////////////////////////////////////// 00250 00252 template <class TVal, class TCmp = TLss<TVal> > 00253 class THeap { 00254 private: 00255 TCmp Cmp; 00256 TVec<TVal> HeapV; 00257 private: 00258 void PushHeap(const int& First, int HoleIdx, const int& Top, TVal Val); 00259 void AdjustHeap(const int& First, int HoleIdx, const int& Len, TVal Val); 00260 void MakeHeap(const int& First, const int& Len); 00261 public: 00262 THeap() : HeapV() { } 00263 THeap(const int& MxVals) : Cmp(), HeapV(MxVals, 0) { } 00264 THeap(const TCmp& _Cmp) : Cmp(_Cmp), HeapV() { } 00265 THeap(const TVec<TVal>& Vec) : Cmp(), HeapV(Vec) { MakeHeap(); } 00266 THeap(const TVec<TVal>& Vec, const TCmp& _Cmp) : Cmp(_Cmp), HeapV(Vec) { MakeHeap(); } 00267 THeap(const THeap& Heap) : Cmp(Heap.Cmp), HeapV(Heap.HeapV) { } 00268 THeap& operator = (const THeap& H) { Cmp=H.Cmp; HeapV=H.HeapV; return *this; } 00269 00271 const TVal& TopHeap() const { return HeapV[0]; } 00273 void PushHeap(const TVal& Val); 00275 TVal PopHeap(); 00277 int Len() const { return HeapV.Len(); } 00279 bool Empty() const { return HeapV.Empty(); } 00281 const TVec<TVal>& operator()() const { return HeapV; } 00283 TVec<TVal>& operator()() { return HeapV; } 00285 void Add(const TVal& Val) { HeapV.Add(Val); } 00287 void MakeHeap() { MakeHeap(0, Len()); } 00288 }; 00289 00290 template <class TVal, class TCmp> 00291 void THeap<TVal, TCmp>::PushHeap(const TVal& Val) { 00292 HeapV.Add(Val); 00293 PushHeap(0, HeapV.Len()-1, 0, Val); 00294 } 00295 00296 template <class TVal, class TCmp> 00297 TVal THeap<TVal, TCmp>::PopHeap() { 00298 IAssert(! HeapV.Empty()); 00299 const TVal Top = HeapV[0]; 00300 HeapV[0] = HeapV.Last(); 00301 HeapV.DelLast(); 00302 if (! HeapV.Empty()) { 00303 AdjustHeap(0, 0, HeapV.Len(), HeapV[0]); 00304 } 00305 return Top; 00306 } 00307 00308 template <class TVal, class TCmp> 00309 void THeap<TVal, TCmp>::PushHeap(const int& First, int HoleIdx, const int& Top, TVal Val) { 00310 int Parent = (HoleIdx-1)/2; 00311 while (HoleIdx > Top && Cmp(HeapV[First+Parent], Val)) { 00312 HeapV[First+HoleIdx] = HeapV[First+Parent]; 00313 HoleIdx = Parent; Parent = (HoleIdx-1)/2; 00314 } 00315 HeapV[First+HoleIdx] = Val; 00316 } 00317 00318 template <class TVal, class TCmp> 00319 void THeap<TVal, TCmp>::AdjustHeap(const int& First, int HoleIdx, const int& Len, TVal Val) { 00320 const int Top = HoleIdx; 00321 int Right = 2*HoleIdx+2; 00322 while (Right < Len) { 00323 if (Cmp(HeapV[First+Right], HeapV[First+Right-1])) { Right--; } 00324 HeapV[First+HoleIdx] = HeapV[First+Right]; 00325 HoleIdx = Right; Right = 2*(Right+1); } 00326 if (Right == Len) { 00327 HeapV[First+HoleIdx] = HeapV[First+Right-1]; 00328 HoleIdx = Right-1; } 00329 PushHeap(First, HoleIdx, Top, Val); 00330 } 00331 00332 template <class TVal, class TCmp> 00333 void THeap<TVal, TCmp>::MakeHeap(const int& First, const int& Len) { 00334 if (Len < 2) { return; } 00335 int Parent = (Len-2)/2; 00336 while (true) { 00337 AdjustHeap(First, Parent, Len, HeapV[First+Parent]); 00338 if (Parent == 0) { return; } 00339 Parent--; 00340 } 00341 } 00342