7 for (
int i = 0; i < LeftNodes; i++) { G->AddNode(i,
true); }
8 for (
int i = 0; i < RightNodes; i++) { G->AddNode(LeftNodes+i,
false); }
9 IAssertR(Edges <= LeftNodes*RightNodes,
"Too many edges in the bipartite graph!");
10 for (
int edges = 0; edges < Edges; ) {
12 const int RNId = LeftNodes + Rnd.
GetUniDevInt(RightNodes);
13 if (G->AddEdge(LNId, RNId) != -2) { edges++; }
22 for (
int i = 0; i < Nodes; i++) {
37 for (
int n = 0; n < Nodes; n++) {
39 if (! (Val >= 1 && Val < Nodes/2)) { n--;
continue; }
43 printf(
"%d nodes, %u edges\n", Nodes, DegSum);
44 if (DegSum % 2 == 1) { DegSeqV[0] += 1; }
62 const int Nodes = DegSeqV.
Len();
68 IAssertR(DegSeqV.
IsSorted(
false),
"DegSeqV must be sorted in descending order.");
70 for (
int node = 0; node < Nodes; node++) {
72 DegH.AddDat(node, DegSeqV[node]);
73 DegSum += DegSeqV[node];
76 while (! DegH.Empty()) {
78 const int NId1 = DegH.GetKey(DegH.GetRndKeyId(Rnd, 0.5));
79 const int NId2 = DegH.GetKey(DegH.GetRndKeyId(Rnd, 0.5));
80 IAssert(DegH.IsKey(NId1) && DegH.IsKey(NId2));
82 if (DegH.GetDat(NId1) == 1) {
continue; }
85 if (Edge.
Val1==-1) {
continue; }
89 if (DegH.GetDat(NId1) == 2) { DegH.DelKey(NId1); }
90 else { DegH.GetDat(NId1) -= 2; }
92 if (! Graph.
IsEdge(NId1, NId2)) {
97 if (Edge.
Val1==-1) {
continue; }
102 if (DegH.GetDat(NId1)==1) { DegH.DelKey(NId1); }
103 else { DegH.GetDat(NId1) -= 1; }
104 if (DegH.GetDat(NId2)==1) { DegH.DelKey(NId2); }
105 else { DegH.GetDat(NId2) -= 1; }
107 if (++
edge % 1000 == 0) {
108 printf(
"\r %dk / %dk",
edge/1000, DegSum/2000); }
123 const int Nodes = DegSeqV.
Len();
128 int DegSum=0, edges=0;
129 for (
int node = 0; node < Nodes; node++) {
131 for (
int d = 0; d < DegSeqV[node]; d++) { NIdDegV.Add(node); }
132 DegSum += DegSeqV[node];
134 NIdDegV.Shuffle(Rnd);
136 if (DegSum % 2 != 0) {
137 printf(
"Seg seq is odd [%d]: ", DegSeqV.
Len());
138 for (
int d = 0; d <
TMath::Mn(100, DegSeqV.
Len()); d++) { printf(
" %d", (
int)DegSeqV[d]); }
142 for (
int c = 0; NIdDegV.Len() > 1; c++) {
145 if (u > v) {
Swap(u, v); }
146 const int E1 = NIdDegV[u];
147 const int E2 = NIdDegV[v];
148 if (v == NIdDegV.Len()-1) { NIdDegV.DelLast(); }
149 else { NIdDegV[v] = NIdDegV.Last(); NIdDegV.DelLast(); }
150 if (u == NIdDegV.Len()-1) { NIdDegV.DelLast(); }
151 else { NIdDegV[u] = NIdDegV.Last(); NIdDegV.DelLast(); }
152 if (E1 == E2 || EdgeH.
IsKey(
TIntPr(E1, E2))) {
continue; }
156 if (c % (DegSum/100+1) == 0) { printf(
"\r configuration model: iter %d: edges: %d, left: %d", c, edges, NIdDegV.Len()/2); }
169 const int Nodes = OrigGraph->
GetNodes();
170 const int Edges = OrigGraph->
GetEdges();
176 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
179 const int NId = NI.GetId();
180 for (
int e = 0; e < NI.GetOutDeg(); e++) {
181 if (NId <= NI.GetOutNId(e)) {
continue; }
188 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
191 if (keyId1 == keyId2) { skip++;
continue; }
192 const TIntPr& E1 = EdgeSet[keyId1];
193 const TIntPr& E2 = EdgeSet[keyId2];
195 if (NewE1.Val1 > NewE1.Val2) {
Swap(NewE1.Val1, NewE1.Val2); }
197 if (NewE1!=NewE2 && NewE1.
Val1!=NewE1.Val2 && NewE2.
Val1!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
202 if (swps % Edges == 0) {
203 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
204 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
207 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
208 for (
int e = 0; e < EdgeSet.
Len(); e++) {
209 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
220 const int Nodes = OrigGraph->GetNodes();
221 const int Edges = OrigGraph->GetEdges();
227 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
229 for (
TNGraph::TNodeI NI = OrigGraph->BegNI(); NI < OrigGraph->EndNI(); NI++) {
230 const int NId = NI.GetId();
231 for (
int e = 0; e < NI.GetOutDeg(); e++) {
237 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
240 if (keyId1 == keyId2) { skip++;
continue; }
241 const TIntPr& E1 = EdgeSet[keyId1];
242 const TIntPr& E2 = EdgeSet[keyId2];
244 if (NewE1.Val1!=NewE1.Val2 && NewE2.
Val1!=NewE2.
Val2 && NewE1.Val1!=NewE2.
Val1 && NewE1.Val2!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
249 if (swps % Edges == 0) {
250 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
251 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
254 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
255 for (
int e = 0; e < EdgeSet.
Len(); e++) {
256 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
267 const int Nodes = OrigGraph->GetNodes();
268 const int Edges = OrigGraph->GetEdges();
274 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
276 for (
TBPGraph::TNodeI NI = OrigGraph->BegLNI(); NI < OrigGraph->EndLNI(); NI++) {
277 const int NId = NI.GetId();
278 for (
int e = 0; e < NI.GetOutDeg(); e++) {
280 Graph.
AddNode(NI.GetId(),
true); }
281 for (
TBPGraph::TNodeI NI = OrigGraph->BegRNI(); NI < OrigGraph->EndRNI(); NI++) {
282 Graph.
AddNode(NI.GetId(),
false); }
286 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
289 if (keyId1 == keyId2) { skip++;
continue; }
290 const TIntPr& E1 = EdgeSet[keyId1];
291 const TIntPr& E2 = EdgeSet[keyId2];
293 if (NewE1!=NewE2 && NewE1.
Val1!=NewE1.Val2 && NewE2.
Val1!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
298 if (swps % Edges == 0) {
299 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
300 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
303 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
304 for (
int e = 0; e < EdgeSet.
Len(); e++) {
305 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
316 Graph.
Reserve(Nodes, NodeOutDeg*Nodes);
317 TIntV NIdV(NodeOutDeg*Nodes, 0);
323 for (
int node = 2; node < Nodes; node++) {
325 while (NodeSet.
Len() < NodeOutDeg && NodeSet.
Len() < node) {
329 for (
int i = 0; i < NodeSet.
Len(); i++) {
332 NIdV.
Add(NodeSet[i]);
344 namespace TSnapDetail {
347 if (ValV.
Len() != Dim) { ValV.
Gen(Dim); }
349 for (
int i = 0; i < Dim; i++) {
352 Length = 1.0 / sqrt(Length);
353 for (
int i = 0; i < Dim; i++) {
370 for (
int i = 0; i < Nodes; i++) {
372 PointV.
Add(
TFltTr(Rad*ValV[0], Rad*ValV[1], Rad*ValV[2]));
374 const double R2 =
TMath::Sqr(log((
double) Nodes) / (pow((
double) Nodes, 0.5-Beta)));
377 for (
int t = 0; t < Nodes; t++) {
379 const TFltTr& P1 = PointV[pid];
383 DegV.
Clr(
false); NIdV.
Clr(
false); SumDeg=0;
384 for (
int p = 0; p < t; p++) {
385 const TFltTr& P2 = PointV[p];
389 SumDeg += DegV.
Last();
393 for (
int m = 0; m < OutDeg; m++) {
395 int sum = 0, dst = -1;
396 for (
int s = 0; s < DegV.
Len(); s++) {
398 if (rnd < sum) { dst=s;
break; }
403 NIdV.
Del(dst); DegV.
Del(dst);
418 IAssertR(Nodes > NodeOutDeg,
TStr::Fmt(
"Insufficient nodes for out degree, %d!", NodeOutDeg));
419 for (
int node = 0; node < Nodes; node++) {
420 const int src = node;
422 int dst = (node+
edge) % Nodes;
425 while (dst == src || EdgeSet.
IsKey(
TIntPr(src, dst))) {
435 for (node = 0; node < Nodes; node++) {
460 const int startNId = Graph.
AddNode();
461 Graph.
AddEdge(startNId, startNId);
462 for (
int n = 1; n < Nodes; n++) {
464 const int NId = Graph.
AddNode();
481 PNGraph GenRMat(
const int& Nodes,
const int& Edges,
const double& A,
const double& B,
const double& C,
TRnd& Rnd) {
486 int rngX, rngY, offX, offY;
487 int Depth=0, Collisions=0, Cnt=0, PctDone=0;
488 const int EdgeGap = Edges / 100 + 1;
490 TVec<double> sumA(128, 0), sumAB(128, 0), sumAC(128, 0), sumABC(128, 0);
491 for (
int i = 0; i < 128; i++) {
492 const double a = A * (Rnd.
GetUniDev() + 0.5);
493 const double b = B * (Rnd.
GetUniDev() + 0.5);
494 const double c = C * (Rnd.
GetUniDev() + 0.5);
495 const double d = (1.0 - (A+B+C)) * (Rnd.
GetUniDev() + 0.5);
496 const double abcd = a+b+c+d;
498 sumAB.Add((a+b) / abcd);
499 sumAC.Add((a+c) / abcd);
500 sumABC.
Add((a+b+c) / abcd);
503 for (
int node = 0; node < Nodes; node++) {
507 for (
int edge = 0;
edge < Edges; ) {
508 rngX = Nodes; rngY = Nodes; offX = 0; offY = 0;
511 while (rngX > 1 || rngY > 1) {
513 if (rngX>1 && rngY>1) {
514 if (RndProb < sumA[Depth]) { rngX/=2; rngY/=2; }
515 else if (RndProb < sumAB[Depth]) { offX+=rngX/2; rngX-=rngX/2; rngY/=2; }
516 else if (RndProb < sumABC[Depth]) { offY+=rngY/2; rngX/=2; rngY-=rngY/2; }
517 else { offX+=rngX/2; offY+=rngY/2; rngX-=rngX/2; rngY-=rngY/2; }
520 if (RndProb < sumAC[Depth]) { rngX/=2; rngY/=2; }
521 else { offX+=rngX/2; rngX-=rngX/2; rngY/=2; }
524 if (RndProb < sumAB[Depth]) { rngX/=2; rngY/=2; }
525 else { offY+=rngY/2; rngX/=2; rngY-=rngY/2; }
530 const int NId1 = offX;
531 const int NId2 = offY;
532 if (NId1 != NId2 && ! Graph.
IsEdge(NId1, NId2)) {
534 if (++Cnt > EdgeGap) {
535 Cnt=0; printf(
"\r %d%% edges", ++PctDone); }
540 printf(
"\r RMat: nodes:%d, edges:%d, Iterations:%d, Collisions:%d (%.1f%%).\n", Nodes, Edges,
541 Edges+Collisions, Collisions, 100*Collisions/
double(Edges+Collisions));
551 return GenRMat(75888, 508837, 0.550, 0.228, 0.212);
void Clr(const bool &DoDel=true, const int &NoDelLim=-1)
static const T & Mn(const T &LVal, const T &RVal)
TPair< TInt, TInt > TIntPr
Main namespace for all the Snap global entities.
void Reserve(const int &Nodes, const int &Edges)
Reserves memory for a biparite graph of Nodes nodes and Edges edges.
#define IAssertR(Cond, Reason)
PNGraph GenRMatEpinions()
Generates a R-Mat graph, with a synthetic copy of the Epinions social network.
void DelKeyId(const int &KeyId)
void Del(const TSizeTy &ValN)
Removes the element at position ValN.
PUNGraph GenRewire(const PUNGraph &OrigGraph, const int &NSwitch, TRnd &Rnd)
Rewire a random undirected graph. Keeps node degrees the same, but randomly rewires the edges...
PNGraph GenRMat(const int &Nodes, const int &Edges, const double &A, const double &B, const double &C, TRnd &Rnd)
Generates a R-MAT graph using recursive descent into a 2x2 matrix [A,B; C, 1-(A+B+C)].
static PNGraph New()
Static constructor that returns a pointer to the graph. Call: PNGraph Graph = TNGraph::New().
TNodeI GetNI(const int &NId) const
Returns an iterator referring to the node of ID NId in the graph.
Node iterator. Only forward iteration (operator++) is supported.
int AddNode(int NId=-1)
Adds a node of ID NId to the graph.
int GetEdges() const
Returns the number of edges in the graph.
TSizeTy Len() const
Returns the number of elements in the vector.
Node iterator. Only forward iteration (operator++) is supported.
int AddNode(int NId=-1, const bool &LeftNode=true)
Adds a node of ID NId to the graph.
int AddNode(int NId=-1)
Adds a node of ID NId to the graph.
PNGraph GenCopyModel(const int &Nodes, const double &Beta, TRnd &Rnd)
Generates a random scale-free network using the Copying Model.
static double Sqr(const double &x)
PBPGraph GenRndBipart(const int &LeftNodes, const int &RightNodes, const int &Edges, TRnd &Rnd)
Generates a random bipartite graph.
bool IsKey(const TKey &Key) const
int GetNodes() const
Returns the number of nodes in the graph.
int GetDeg() const
Returns degree of the current node.
void GetSphereDev(const int &Dim, TRnd &Rnd, TFltV &ValV)
Sample random point from the surface of a Dim-dimensional unit sphere.
PUNGraph GenDegSeq(const TIntV &DegSeqV, TRnd &Rnd)
Generates a random graph with exact degree sequence.
TIntPr GetRndEdgeNonAdjNode(const PGraph &Graph, int NId1, int NId2)
Returns a random edge in a graph Graph where the edge does not touch nodes NId1 and NId2...
void Clr(const bool &DoDel=true, const TSizeTy &NoDelLim=-1)
Clears the contents of the vector.
void GetDegSeqV(const PGraph &Graph, TIntV &DegV)
Returns a degree sequence vector.
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 SrcNId to node DstNId to the graph.
PUNGraph GenRndDegK(const int &Nodes, const int &NodeDeg, const int &NSwitch, TRnd &Rnd)
Generates a random graph where each node has degree exactly NodeDeg.
bool IsEdge(const int &SrcNId, const int &DstNId, const bool &IsDir=true) const
Tests whether an edge from node IDs SrcNId to DstNId exists in the graph.
void Reserve(const int &Nodes, const int &Edges)
Reserves memory for a graph of Nodes nodes and Edges edges.
int GetRndNId(TRnd &Rnd=TInt::Rnd)
Returns an ID of a random node in the graph.
static double Round(const double &Val)
TNodeI GetNI(const int &NId) const
Returns an iterator referring to the node of ID NId in the graph.
static PUNGraph New()
Static constructor that returns a pointer to the graph. Call: PUNGraph Graph = TUNGraph::New().
int AddKey(const TKey &Key)
const TVal & Last() const
Returns a reference to the last element of the vector.
PNGraph GenForestFire(const int &Nodes, const double &FwdProb, const double &BckProb)
Generates a random Forest Fire, directed graph with given probabilities.
void DelEdge(const int &SrcNId, const int &DstNId)
Deletes an edge between node IDs SrcNId and DstNId from the graph.
TTriple< TFlt, TFlt, TFlt > TFltTr
PUNGraph GenConfModel(const TIntV &DegSeqV, TRnd &Rnd)
Generates a random undirect graph with a given degree sequence.
PUNGraph GenPrefAttach(const int &Nodes, const int &NodeOutDeg, TRnd &Rnd)
Generates a power-law degree distribution using Barabasi-Albert model of scale-free graphs...
void Defrag(const bool &OnlyNodeLinks=false)
Defragments the graph.
int AddEdge(const int &SrcNId, const int &DstNId)
Adds an edge between node IDs SrcNId and DstNId to the graph.
int GetRndKeyId(TRnd &Rnd) const
int AddEdge(const int &LeftNId, const int &RightNId)
Adds an edge between a node LeftNId on the left and a node RightNId on the right side of the bipartit...
int GetOutDeg() const
Returns out-degree of the current node.
PUNGraph GenSmallWorld(const int &Nodes, const int &NodeOutDeg, const double &RewireProb, TRnd &Rnd)
Generates a randomly small-world graph using the Watts-Strogatz model.
static TStr Fmt(const char *FmtStr,...)
bool IsSorted(const bool &Asc=true) const
Checks whether the vector is sorted in ascending (if Asc=true) or descending (if Asc=false) order...
Node iterator. Only forward iteration (operator++) is supported.
void Defrag(const bool &OnlyNodeLinks=false)
Defragments the graph.
TNodeI EndNI() const
Returns an iterator referring to the past-the-end node in the graph.
PUNGraph GenGeoPrefAttach(const int &Nodes, const int &OutDeg, const double &Beta, TRnd &Rnd)
Generates a random scale-free graph using the Geometric Preferential model.
void Reserve(const int &Nodes, const int &Edges)
Reserves memory for a graph of Nodes nodes and Edges edges.
static PBPGraph New()
Static constructor that returns a pointer to the graph. Call: PBPGraph BPGraph = TBPGraph::New();.
bool IsNode(const int &NId) const
Tests whether ID NId is a node.
void Reverse()
Reverses the order of the elements in the vector.
void Gen(const TSizeTy &_Vals)
Constructs a vector (an array) of _Vals elements.
int GetUniDevInt(const int &Range=0)
PUNGraph GenRndPowerLaw(const int &Nodes, const double &PowerExp, const bool &ConfModel, TRnd &Rnd)
Generates a random scale-free graph with power-law degree distribution.
const char * GetStr() const
bool IsEdge(const int &SrcNId, const int &DstNId) const
Tests whether an edge between node IDs SrcNId and DstNId exists in the graph.
TSizeTy Add()
Adds a new element at the end of the vector, after its current last element.
static PNGraph GenGraph(const int &Nodes, const double &FwdProb, const double &BckProb)
TNodeI BegNI() const
Returns an iterator referring to the first node in the graph.
int GetOutNId(const int &NodeN) const
Returns ID of NodeN-th out-node (the node the current node points to).
double GetPowerDev(const double &AlphaSlope)
void Swap(TRec &Rec1, TRec &Rec2)
Vector is a sequence TVal objects representing an array that can change in size.