SNAP Library, Developer Reference
2012-10-15 15:06:59
SNAP, a general purpose network analysis and graph mining library
|
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); 00031 PUNGraph GenRndPowerLaw(const int& Nodes, const double& PowerExp, const bool& ConfModel=true, TRnd& Rnd=TInt::Rnd); 00032 PUNGraph GenDegSeq(const TIntV& DegSeqV, TRnd& Rnd=TInt::Rnd); 00033 PUNGraph GenPrefAttach(const int& Nodes, const int& NodeOutDeg, TRnd& Rnd=TInt::Rnd); 00034 PUNGraph GenGeoPrefAttach(const int& Nodes, const int& OutDeg, const double& Beta, TRnd& Rnd=TInt::Rnd); 00035 PUNGraph GenSmallWorld(const int& Nodes, const int& NodeOutDeg, const double& RewireProb, TRnd& Rnd=TInt::Rnd); 00036 00037 PUNGraph GenConfModel(const TIntV& DegSeqV, TRnd& Rnd=TInt::Rnd); 00038 PUNGraph GenRewire(const PUNGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00039 PNGraph GenRewire(const PNGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00040 PBPGraph GenRewire(const PBPGraph& Graph, const int& NSwitch=100, TRnd& Rnd=TInt::Rnd); 00041 00042 PNGraph GenForestFire(const int& Nodes, const double& FwdProb, const double& BckProb); 00043 PNGraph GenCopyModel(const int& Nodes, const double& Beta, TRnd& Rnd=TInt::Rnd); 00044 PNGraph GenRMat(const int& Nodes, const int& Edges, const double& A, const double& B, const double& C, TRnd& Rnd=TInt::Rnd); 00045 PNGraph GenRMatEpinions(); 00046 00048 // Implementation 00049 template <class PGraph> 00050 PGraph GenGrid(const int& Rows, const int& Cols, const bool& IsDir) { 00051 PGraph GraphPt = PGraph::New(); 00052 typename PGraph::TObj& Graph = *GraphPt; 00053 Graph.Reserve(Rows*Cols, 4*Rows*Cols); 00054 int node, r, c; 00055 for (node = 0; node < Rows * Cols; node++) { 00056 Graph.AddNode(node); } 00057 for (r = 0; r < Rows; r++) { 00058 for (c = 0; c < Cols; c++) { 00059 const int nodeId = Cols*r + c; 00060 if (r < Rows-1) { // bottom node 00061 Graph.AddEdge(nodeId, nodeId+Cols); 00062 if (Graph.HasFlag(gfDirected) && ! IsDir) { 00063 Graph.AddEdge(nodeId+Cols-1, nodeId); } 00064 } 00065 if (c < Cols-1) { // right node 00066 Graph.AddEdge(nodeId, nodeId+1); 00067 if (Graph.HasFlag(gfDirected) && ! IsDir) { 00068 Graph.AddEdge(nodeId+1, nodeId); } 00069 } 00070 } 00071 } 00072 return GraphPt; 00073 } 00074 00075 template <class PGraph> 00076 PGraph GenStar(const int& Nodes, const bool& IsDir) { 00077 PGraph Graph = PGraph::TObj::New(); 00078 Graph->Reserve(Nodes, Nodes); 00079 Graph->AddNode(0); 00080 for (int n = 1; n < Nodes; n++) { 00081 Graph->AddNode(n); 00082 Graph->AddEdge(0, n); 00083 if (Graph->HasFlag(gfDirected) && ! IsDir) { Graph->AddEdge(n, 0); } 00084 } 00085 return Graph; 00086 } 00087 00088 template <class PGraph> 00089 PGraph GenCircle(const int& Nodes, const int& NodeOutDeg, const bool& IsDir) { 00090 PGraph Graph = PGraph::TObj::New(); 00091 Graph->Reserve(Nodes, Nodes*NodeOutDeg); 00092 for (int n = 0; n < Nodes; n++) { 00093 Graph->AddNode(n); } 00094 for (int n = 0; n < Nodes; n++) { 00095 for (int x = 0; x < NodeOutDeg; x++) { 00096 Graph->AddEdge(n, (n+x+1) % Nodes); 00097 if (Graph->HasFlag(gfDirected) && ! IsDir) { Graph->AddEdge((n+x) % Nodes, n); } 00098 } 00099 } 00100 return Graph; 00101 } 00102 00103 template <class PGraph> 00104 PGraph GenFull(const int& Nodes) { 00105 PGraph Graph = PGraph::TObj::New(); 00106 Graph->Reserve(Nodes, Nodes*Nodes); 00107 for (int n = 0; n < Nodes; n++) { 00108 Graph->AddNode(n); } 00109 for (int n1 = 0; n1 < Nodes; n1++) { 00110 for (int n2 = 0; n2 < Nodes; n2++) { 00111 if (n1 != n2) { Graph->AddEdge(n1, n2); } 00112 } 00113 } 00114 return Graph; 00115 } 00116 00117 template <class PGraph> 00118 PGraph GenTree(const int& Fanout, const int& Levels, const bool& IsDir, const bool& ChildPointsToParent) { 00119 const int Nodes = (int) (pow(double(Fanout), double(Levels+1)) - 1) / (Fanout - 1); 00120 const int Edges = Nodes - 1; 00121 PGraph GraphPt = PGraph::New(); 00122 typename PGraph::TObj& Graph = *GraphPt; 00123 Graph.Reserve(Nodes, Edges); 00124 int node; 00125 for (node = 0; node < Nodes; node++) { 00126 Graph.AddNode(node); } 00127 // non-leaf nodes 00128 for (node = 0; node < (int) Nodes - (int) pow(double(Fanout), double(Levels)); node++) { 00129 for (int edge = 1; edge <= Fanout; edge++) { 00130 if (IsDir) { 00131 if (ChildPointsToParent) { Graph.AddEdge(Fanout*node+edge, node); } 00132 else { Graph.AddEdge(node, Fanout*node+edge); } 00133 } else { 00134 Graph.AddEdge(node, Fanout*node+edge); // link children 00135 Graph.AddEdge(Fanout*node+edge, node); 00136 } 00137 } 00138 } 00139 return GraphPt; 00140 } 00141 00147 00155 00158 template <class PGraph> 00159 PGraph GenBaraHierar(const int& Levels, const bool& IsDir) { 00160 const int Nodes = (int) TMath::Round(TMath::Power(5, Levels)); 00161 PGraph GraphPt = PGraph::New(); 00162 typename PGraph::TObj& Graph = *GraphPt; 00163 Graph.Reserve(Nodes, -1); 00164 // base graph 00165 for (int i = 0; i < 5; i++) { Graph.AddNode(i); } 00166 Graph.AddEdge(1,2); Graph.AddEdge(2,3); 00167 Graph.AddEdge(3,4); Graph.AddEdge(4,1); 00168 Graph.AddEdge(1,0); Graph.AddEdge(3,0); 00169 Graph.AddEdge(2,0); Graph.AddEdge(4,0); 00170 // expansion 00171 const int CenterId = 0; 00172 for (int lev = 1; lev < Levels+1; lev++) { 00173 const int MxNId = Graph.GetNodes(); 00174 // make 4 duplicate copies 00175 for (int d = 0; d < 4; d++) { 00176 for (int n = 0; n < MxNId; n++) { Graph.AddNode(); } 00177 for (int n = 0; n < MxNId; n++) { 00178 typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); 00179 const int SrcId = n+MxNId*(d+1); 00180 for (int e = 0; e < NI.GetOutDeg(); e++) { 00181 Graph.AddEdge(SrcId, NI.GetOutNId(e)+MxNId*(d+1)); 00182 } 00183 } 00184 } 00185 // add edges to the center 00186 //const int LevPow = (int)TMath::Round(TMath::Power(5,lev-1)); 00187 for (int n = MxNId; n < Graph.GetNodes(); n++) { 00188 typename PGraph::TObj::TNodeI NI = Graph.GetNI(n); 00189 const int SrcId = n; 00190 int Pow = 1; bool Skip = false; 00191 for (int p = 1; p <= lev; p++) { 00192 if (SrcId % (5*Pow) < Pow) { Skip=true; break; } 00193 Pow *= 5; 00194 } 00195 if (Skip) { continue; } 00196 Graph.AddEdge(SrcId, CenterId); 00197 } 00198 } 00199 return GraphPt; 00200 } 00201 00202 template <class PGraph> 00203 PGraph GenRndGnm(const int& Nodes, const int& Edges, const bool& IsDir, TRnd& Rnd) { 00204 PGraph GraphPt = PGraph::New(); 00205 typename PGraph::TObj& Graph = *GraphPt; 00206 Graph.Reserve(Nodes, Edges); 00207 for (int node = 0; node < Nodes; node++) { 00208 IAssert(Graph.AddNode(node) == node); 00209 } 00210 for (int edge = 0; edge < Edges; ) { 00211 const int SrcNId = Rnd.GetUniDevInt(Nodes); 00212 const int DstNId = Rnd.GetUniDevInt(Nodes); 00213 if (SrcNId != DstNId && Graph.AddEdge(SrcNId, DstNId) != -2) { // is new edge 00214 if (! IsDir) { Graph.AddEdge(DstNId, SrcNId); } 00215 edge++; 00216 } 00217 } 00218 return GraphPt; 00219 } 00220 00221 namespace TSnapDetail { 00223 template <class PGraph> 00224 TIntPr GetRndEdgeNonAdjNode(const PGraph& Graph, int NId1, int NId2) { 00225 typename PGraph::TObj::TNodeI NI1, NI2; 00226 int OutDeg = -1; 00227 do { 00228 NI1 = Graph->GetRndNI(); 00229 OutDeg = NI1.GetOutDeg(); 00230 } while (OutDeg == 0); 00231 NI2 = Graph->GetNI(NI1.GetOutNId(TInt::Rnd.GetUniDevInt(OutDeg))); 00232 int runs = 0; 00233 while (NI1.IsNbrNId(NId1) || NI1.IsNbrNId(NId2) || NI2.IsNbrNId(NId1) || NI2.IsNbrNId(NId2) || NI1.GetId()==NI2.GetId()) { 00234 do { 00235 NI1 = Graph->GetRndNI(); 00236 OutDeg = NI1.GetOutDeg(); 00237 } while (OutDeg == 0); 00238 NI2 = Graph->GetNI(NI1.GetOutNId(TInt::Rnd.GetUniDevInt(OutDeg))); 00239 if (runs++ == 1000) { return TIntPr(-1, -1); } 00240 } 00241 return TIntPr(NI1.GetId(), NI2.GetId()); 00242 } 00243 00244 } // namespace TSnapDetail 00245 00246 }; // namespace TSnap