SNAP Library 2.2, Developer Reference
2014-03-11 19:15:55
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 // TODO ROK, Jure included basic documentation, finalize reference doc 00002 00004 // Graph Generators 00005 namespace TSnap { 00006 00008 // Deterministic graphs 00010 template <class PGraph> PGraph GenGrid(const int& Rows, const int& Cols, const bool& IsDir=true); 00012 template <class PGraph> PGraph GenStar(const int& Nodes, const bool& IsDir=true); 00014 template <class PGraph> PGraph GenCircle(const int& Nodes, const int& NodeOutDeg=1, const bool& IsDir=true); 00016 template <class PGraph> PGraph GenFull(const int& Nodes); 00018 template <class PGraph> PGraph GenTree(const int& Fanout, const int& Levels, const bool& IsDir=true, const bool& ChildPointsToParent=true); 00020 template <class PGraph> PGraph GenBaraHierar(const int& Levels, const bool& IsDir=true); 00021 00023 // Random graphs 00024 00026 template <class PGraph> PGraph GenRndGnm(const int& Nodes, const int& Edges, const bool& IsDir=true, TRnd& Rnd=TInt::Rnd); 00028 PBPGraph GenRndBipart(const int& LeftNodes, const int& RightNodes, const int& Edges, TRnd& Rnd=TInt::Rnd); 00030 PUNGraph GenRndDegK(const int& Nodes, const int& NodeDeg, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00032 PUNGraph GenRndPowerLaw(const int& Nodes, const double& PowerExp, const bool& ConfModel=true, TRnd& Rnd=TInt::Rnd); 00034 PUNGraph GenDegSeq(const TIntV& DegSeqV, TRnd& Rnd=TInt::Rnd); 00036 PUNGraph GenPrefAttach(const int& Nodes, const int& NodeOutDeg, TRnd& Rnd=TInt::Rnd); 00038 PUNGraph GenGeoPrefAttach(const int& Nodes, const int& OutDeg, const double& Beta, TRnd& Rnd=TInt::Rnd); 00040 PUNGraph GenSmallWorld(const int& Nodes, const int& NodeOutDeg, const double& RewireProb, TRnd& Rnd=TInt::Rnd); 00042 PUNGraph GenConfModel(const TIntV& DegSeqV, TRnd& Rnd=TInt::Rnd); 00044 PNGraph GenForestFire(const int& Nodes, const double& FwdProb, const double& BckProb); 00046 PNGraph GenCopyModel(const int& Nodes, const double& Beta, TRnd& Rnd=TInt::Rnd); 00048 PNGraph GenRMat(const int& Nodes, const int& Edges, const double& A, const double& B, const double& C, TRnd& Rnd=TInt::Rnd); 00050 PNGraph GenRMatEpinions(); 00051 00052 00054 PUNGraph GenRewire(const PUNGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00056 PNGraph GenRewire(const PNGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00058 PBPGraph GenRewire(const PBPGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00060 PUNGraph GenConfModel(const PUNGraph& G); 00061 00063 // Implementation 00064 template <class PGraph> 00065 PGraph GenGrid(const int& Rows, const int& Cols, const bool& IsDir) { 00066 PGraph GraphPt = PGraph::New(); 00067 typename PGraph::TObj& Graph = *GraphPt; 00068 Graph.Reserve(Rows*Cols, 4*Rows*Cols); 00069 int node, r, c; 00070 for (node = 0; node < Rows * Cols; node++) { 00071 Graph.AddNode(node); } 00072 for (r = 0; r < Rows; r++) { 00073 for (c = 0; c < Cols; c++) { 00074 const int nodeId = Cols*r + c; 00075 if (r < Rows-1) { // bottom node 00076 Graph.AddEdge(nodeId, nodeId+Cols); 00077 if (Graph.HasFlag(gfDirected) && ! IsDir) { 00078 Graph.AddEdge(nodeId+Cols-1, nodeId); } 00079 } 00080 if (c < Cols-1) { // right node 00081 Graph.AddEdge(nodeId, nodeId+1); 00082 if (Graph.HasFlag(gfDirected) && ! IsDir) { 00083 Graph.AddEdge(nodeId+1, nodeId); } 00084 } 00085 } 00086 } 00087 return GraphPt; 00088 } 00089 00090 template <class PGraph> 00091 PGraph GenStar(const int& Nodes, const bool& IsDir) { 00092 PGraph Graph = PGraph::TObj::New(); 00093 Graph->Reserve(Nodes, Nodes); 00094 Graph->AddNode(0); 00095 for (int n = 1; n < Nodes; n++) { 00096 Graph->AddNode(n); 00097 Graph->AddEdge(0, n); 00098 if (Graph->HasFlag(gfDirected) && ! IsDir) { Graph->AddEdge(n, 0); } 00099 } 00100 return Graph; 00101 } 00102 00103 template <class PGraph> 00104 PGraph GenCircle(const int& Nodes, const int& NodeOutDeg, const bool& IsDir) { 00105 PGraph Graph = PGraph::TObj::New(); 00106 Graph->Reserve(Nodes, Nodes*NodeOutDeg); 00107 for (int n = 0; n < Nodes; n++) { 00108 Graph->AddNode(n); } 00109 for (int n = 0; n < Nodes; n++) { 00110 for (int x = 0; x < NodeOutDeg; x++) { 00111 Graph->AddEdge(n, (n+x+1) % Nodes); 00112 if (Graph->HasFlag(gfDirected) && ! IsDir) { Graph->AddEdge((n+x) % Nodes, n); } 00113 } 00114 } 00115 return Graph; 00116 } 00117 00118 template <class PGraph> 00119 PGraph GenFull(const int& Nodes) { 00120 PGraph Graph = PGraph::TObj::New(); 00121 Graph->Reserve(Nodes, Nodes*Nodes); 00122 for (int n = 0; n < Nodes; n++) { 00123 Graph->AddNode(n); } 00124 for (int n1 = 0; n1 < Nodes; n1++) { 00125 for (int n2 = 0; n2 < Nodes; n2++) { 00126 if (n1 != n2) { Graph->AddEdge(n1, n2); } 00127 } 00128 } 00129 return Graph; 00130 } 00131 00132 template <class PGraph> 00133 PGraph GenTree(const int& Fanout, const int& Levels, const bool& IsDir, const bool& ChildPointsToParent) { 00134 const int Nodes = (int) (pow(double(Fanout), double(Levels+1)) - 1) / (Fanout - 1); 00135 const int Edges = Nodes - 1; 00136 PGraph GraphPt = PGraph::New(); 00137 typename PGraph::TObj& Graph = *GraphPt; 00138 Graph.Reserve(Nodes, Edges); 00139 int node; 00140 for (node = 0; node < Nodes; node++) { 00141 Graph.AddNode(node); } 00142 // non-leaf nodes 00143 for (node = 0; node < (int) Nodes - (int) pow(double(Fanout), double(Levels)); node++) { 00144 for (int edge = 1; edge <= Fanout; edge++) { 00145 if (IsDir) { 00146 if (ChildPointsToParent) { Graph.AddEdge(Fanout*node+edge, node); } 00147 else { Graph.AddEdge(node, Fanout*node+edge); } 00148 } else { 00149 Graph.AddEdge(node, Fanout*node+edge); // link children 00150 Graph.AddEdge(Fanout*node+edge, node); 00151 } 00152 } 00153 } 00154 return GraphPt; 00155 } 00156 00162 00170 00173 template <class PGraph> 00174 PGraph GenBaraHierar(const int& Levels, const bool& IsDir) { 00175 const int Nodes = (int) TMath::Round(TMath::Power(5, Levels)); 00176 PGraph GraphPt = PGraph::New(); 00177 typename PGraph::TObj& Graph = *GraphPt; 00178 Graph.Reserve(Nodes, -1); 00179 // base graph 00180 for (int i = 0; i < 5; i++) { Graph.AddNode(i); } 00181 Graph.AddEdge(1,2); Graph.AddEdge(2,3); 00182 Graph.AddEdge(3,4); Graph.AddEdge(4,1); 00183 Graph.AddEdge(1,0); Graph.AddEdge(3,0); 00184 Graph.AddEdge(2,0); Graph.AddEdge(4,0); 00185 // expansion 00186 const int CenterId = 0; 00187 for (int lev = 1; lev < Levels+1; lev++) { 00188 const int MxNId = Graph.GetNodes(); 00189 // make 4 duplicate copies 00190 for (int d = 0; d < 4; d++) { 00191 for (int n = 0; n < MxNId; n++) { Graph.AddNode(); } 00192 for (int n = 0; n < MxNId; n++) { 00193 typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); 00194 const int SrcId = n+MxNId*(d+1); 00195 for (int e = 0; e < NI.GetOutDeg(); e++) { 00196 Graph.AddEdge(SrcId, NI.GetOutNId(e)+MxNId*(d+1)); 00197 } 00198 } 00199 } 00200 // add edges to the center 00201 //const int LevPow = (int)TMath::Round(TMath::Power(5,lev-1)); 00202 for (int n = MxNId; n < Graph.GetNodes(); n++) { 00203 typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); 00204 const int SrcId = n; 00205 int Pow = 1; bool Skip = false; 00206 for (int p = 1; p <= lev; p++) { 00207 if (SrcId % (5*Pow) < Pow) { Skip=true; break; } 00208 Pow *= 5; 00209 } 00210 if (Skip) { continue; } 00211 Graph.AddEdge(SrcId, CenterId); 00212 } 00213 } 00214 return GraphPt; 00215 } 00216 00217 template <class PGraph> 00218 PGraph GenRndGnm(const int& Nodes, const int& Edges, const bool& IsDir, TRnd& Rnd) { 00219 PGraph GraphPt = PGraph::New(); 00220 typename PGraph::TObj& Graph = *GraphPt; 00221 Graph.Reserve(Nodes, Edges); 00222 IAssertR((1.0 * (Nodes-1) / 2 * (IsDir ? 2 : 1)) >= (1.0 * Edges / Nodes), TStr::Fmt("Not enough nodes (%d), for edges (%d).", Nodes, Edges)); 00223 for (int node = 0; node < Nodes; node++) { 00224 IAssert(Graph.AddNode(node) == node); 00225 } 00226 for (int edge = 0; edge < Edges; ) { 00227 const int SrcNId = Rnd.GetUniDevInt(Nodes); 00228 const int DstNId = Rnd.GetUniDevInt(Nodes); 00229 if (SrcNId != DstNId && Graph.AddEdge(SrcNId, DstNId) != -2) { // is new edge 00230 if (! IsDir) { Graph.AddEdge(DstNId, SrcNId); } 00231 edge++; 00232 } 00233 } 00234 return GraphPt; 00235 } 00236 00237 namespace TSnapDetail { 00239 template <class PGraph> 00240 TIntPr GetRndEdgeNonAdjNode(const PGraph& Graph, int NId1, int NId2) { 00241 typename PGraph::TObj::TNodeI NI1, NI2; 00242 int OutDeg = -1; 00243 do { 00244 NI1 = Graph->GetRndNI(); 00245 OutDeg = NI1.GetOutDeg(); 00246 } while (OutDeg == 0); 00247 NI2 = Graph->GetNI(NI1.GetOutNId(TInt::Rnd.GetUniDevInt(OutDeg))); 00248 int runs = 0; 00249 while (NI1.IsNbrNId(NId1) || NI1.IsNbrNId(NId2) || NI2.IsNbrNId(NId1) || NI2.IsNbrNId(NId2) || NI1.GetId()==NI2.GetId()) { 00250 do { 00251 NI1 = Graph->GetRndNI(); 00252 OutDeg = NI1.GetOutDeg(); 00253 } while (OutDeg == 0); 00254 NI2 = Graph->GetNI(NI1.GetOutNId(TInt::Rnd.GetUniDevInt(OutDeg))); 00255 if (runs++ == 1000) { return TIntPr(-1, -1); } 00256 } 00257 return TIntPr(NI1.GetId(), NI2.GetId()); 00258 } 00259 00260 } // namespace TSnapDetail 00261 00262 }; // namespace TSnap