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; }
59 const int Nodes = DegSeqV.
Len();
65 IAssertR(DegSeqV.
IsSorted(
false),
"DegSeqV must be sorted in descending order.");
67 for (
int node = 0; node < Nodes; node++) {
69 DegH.AddDat(node, DegSeqV[node]);
70 DegSum += DegSeqV[node];
73 while (! DegH.Empty()) {
75 const int NId1 = DegH.GetKey(DegH.GetRndKeyId(
TInt::Rnd, 0.5));
76 const int NId2 = DegH.GetKey(DegH.GetRndKeyId(
TInt::Rnd, 0.5));
77 IAssert(DegH.IsKey(NId1) && DegH.IsKey(NId2));
79 if (DegH.GetDat(NId1) == 1) {
continue; }
82 if (Edge.
Val1==-1) {
continue; }
86 if (DegH.GetDat(NId1) == 2) { DegH.DelKey(NId1); }
87 else { DegH.GetDat(NId1) -= 2; }
89 if (! Graph.
IsEdge(NId1, NId2)) {
94 if (Edge.
Val1==-1) {
continue; }
99 if (DegH.GetDat(NId1)==1) { DegH.DelKey(NId1); }
100 else { DegH.GetDat(NId1) -= 1; }
101 if (DegH.GetDat(NId2)==1) { DegH.DelKey(NId2); }
102 else { DegH.GetDat(NId2) -= 1; }
104 if (++
edge % 1000 == 0) {
105 printf(
"\r %dk / %dk",
edge/1000, DegSum/2000); }
120 const int Nodes = DegSeqV.
Len();
125 int DegSum=0, edges=0;
126 for (
int node = 0; node < Nodes; node++) {
128 for (
int d = 0; d < DegSeqV[node]; d++) { NIdDegV.Add(node); }
129 DegSum += DegSeqV[node];
131 NIdDegV.Shuffle(Rnd);
133 if (DegSum % 2 != 0) {
134 printf(
"Seg seq is odd [%d]: ", DegSeqV.
Len());
135 for (
int d = 0; d <
TMath::Mn(100, DegSeqV.
Len()); d++) { printf(
" %d", (
int)DegSeqV[d]); }
139 for (
int c = 0; NIdDegV.Len() > 1; c++) {
142 if (u > v) {
Swap(u, v); }
143 const int E1 = NIdDegV[u];
144 const int E2 = NIdDegV[v];
145 if (v == NIdDegV.Len()-1) { NIdDegV.DelLast(); }
146 else { NIdDegV[v] = NIdDegV.Last(); NIdDegV.DelLast(); }
147 if (u == NIdDegV.Len()-1) { NIdDegV.DelLast(); }
148 else { NIdDegV[u] = NIdDegV.Last(); NIdDegV.DelLast(); }
149 if (E1 == E2 || EdgeH.
IsKey(
TIntPr(E1, E2))) {
continue; }
153 if (c % (DegSum/100+1) == 0) { printf(
"\r configuration model: iter %d: edges: %d, left: %d", c, edges, NIdDegV.Len()/2); }
166 const int Nodes = OrigGraph->GetNodes();
167 const int Edges = OrigGraph->GetEdges();
173 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
175 for (
TUNGraph::TNodeI NI = OrigGraph->BegNI(); NI < OrigGraph->EndNI(); NI++) {
176 const int NId = NI.GetId();
177 for (
int e = 0; e < NI.GetOutDeg(); e++) {
178 if (NId <= NI.GetOutNId(e)) {
continue; }
185 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
188 if (keyId1 == keyId2) { skip++;
continue; }
189 const TIntPr& E1 = EdgeSet[keyId1];
190 const TIntPr& E2 = EdgeSet[keyId2];
192 if (NewE1.Val1 > NewE1.Val2) {
Swap(NewE1.Val1, NewE1.Val2); }
194 if (NewE1!=NewE2 && NewE1.
Val1!=NewE1.Val2 && NewE2.
Val1!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
199 if (swps % Edges == 0) {
200 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
201 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
204 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
205 for (
int e = 0; e < EdgeSet.
Len(); e++) {
206 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
217 const int Nodes = OrigGraph->
GetNodes();
218 const int Edges = OrigGraph->
GetEdges();
224 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
227 const int NId = NI.GetId();
228 for (
int e = 0; e < NI.GetOutDeg(); e++) {
234 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
237 if (keyId1 == keyId2) { skip++;
continue; }
238 const TIntPr& E1 = EdgeSet[keyId1];
239 const TIntPr& E2 = EdgeSet[keyId2];
241 if (NewE1.Val1!=NewE2.
Val1 && NewE1.Val2!=NewE2.
Val1 && NewE1.Val2!=NewE2.
Val1 && NewE1.Val2!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
246 if (swps % Edges == 0) {
247 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
248 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
251 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
252 for (
int e = 0; e < EdgeSet.
Len(); e++) {
253 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
264 const int Nodes = OrigGraph->GetNodes();
265 const int Edges = OrigGraph->GetEdges();
271 printf(
"Randomizing edges (%d, %d)...\n", Nodes, Edges);
273 for (
TBPGraph::TNodeI NI = OrigGraph->BegLNI(); NI < OrigGraph->EndLNI(); NI++) {
274 const int NId = NI.GetId();
275 for (
int e = 0; e < NI.GetOutDeg(); e++) {
277 Graph.
AddNode(NI.GetId(),
true); }
278 for (
TBPGraph::TNodeI NI = OrigGraph->BegRNI(); NI < OrigGraph->EndRNI(); NI++) {
279 Graph.
AddNode(NI.GetId(),
false); }
283 for (
uint swps = 0; swps < 2*
uint(Edges)*
uint(NSwitch); swps++) {
286 if (keyId1 == keyId2) { skip++;
continue; }
287 const TIntPr& E1 = EdgeSet[keyId1];
288 const TIntPr& E2 = EdgeSet[keyId2];
290 if (NewE1!=NewE2 && NewE1.
Val1!=NewE1.Val2 && NewE2.
Val1!=NewE2.
Val2 && ! EdgeSet.
IsKey(NewE1) && ! EdgeSet.
IsKey(NewE2)) {
295 if (swps % Edges == 0) {
296 printf(
"\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
297 if (ExeTm.
GetSecs() > 2*3600) { printf(
" *** Time limit!\n");
break; }
300 printf(
"\r total %uk switchings attempted, %uk skiped [%s]\n", 2*
uint(Edges)*
uint(NSwitch)/1000u, skip/1000u, ExeTm.
GetStr());
301 for (
int e = 0; e < EdgeSet.
Len(); e++) {
302 Graph.
AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); }
313 Graph.
Reserve(Nodes, NodeOutDeg*Nodes);
314 TIntV NIdV(NodeOutDeg*Nodes, 0);
320 for (
int node = 2; node < Nodes; node++) {
322 while (NodeSet.
Len() < NodeOutDeg && NodeSet.
Len() < node) {
326 for (
int i = 0; i < NodeSet.
Len(); i++) {
329 NIdV.
Add(NodeSet[i]);
336 TIntV DegSeqV(G->GetNodes(), 0);
341 namespace TSnapDetail {
344 if (ValV.
Len() != Dim) { ValV.
Gen(Dim); }
346 for (
int i = 0; i < Dim; i++) {
349 Length = 1.0 / sqrt(Length);
350 for (
int i = 0; i < Dim; i++) {
367 for (
int i = 0; i < Nodes; i++) {
369 PointV.
Add(
TFltTr(Rad*ValV[0], Rad*ValV[1], Rad*ValV[2]));
371 const double R2 =
TMath::Sqr(log((
double) Nodes) / (pow((
double) Nodes, 0.5-Beta)));
374 for (
int t = 0; t < Nodes; t++) {
376 const TFltTr& P1 = PointV[pid];
378 if (! G->IsNode(pid)) { G->AddNode(pid); }
380 DegV.
Clr(
false); NIdV.
Clr(
false); SumDeg=0;
381 for (
int p = 0; p < t; p++) {
382 const TFltTr& P2 = PointV[p];
385 DegV.
Add(G->GetNI(p).GetDeg()+1);
386 SumDeg += DegV.
Last();
390 for (
int m = 0; m < OutDeg; m++) {
392 int sum = 0, dst = -1;
393 for (
int s = 0; s < DegV.
Len(); s++) {
395 if (rnd < sum) { dst=s;
break; }
398 G->AddEdge(pid, NIdV[dst]);
400 NIdV.
Del(dst); DegV.
Del(dst);
415 IAssertR(Nodes > NodeOutDeg,
TStr::Fmt(
"Insufficient nodes for out degree, %d!", NodeOutDeg));
416 for (
int node = 0; node < Nodes; node++) {
417 const int src = node;
419 int dst = (node+
edge) % Nodes;
422 while (dst == src || EdgeSet.
IsKey(
TIntPr(src, dst))) {
432 for (node = 0; node < Nodes; node++) {
457 const int startNId = Graph.
AddNode();
458 Graph.
AddEdge(startNId, startNId);
459 for (
int n = 1; n < Nodes; n++) {
461 const int NId = Graph.
AddNode();
478 PNGraph GenRMat(
const int& Nodes,
const int& Edges,
const double& A,
const double& B,
const double& C,
TRnd& Rnd) {
483 int rngX, rngY, offX, offY;
484 int Depth=0, Collisions=0, Cnt=0, PctDone=0;
485 const int EdgeGap = Edges / 100 + 1;
487 TVec<double> sumA(128, 0), sumAB(128, 0), sumAC(128, 0), sumABC(128, 0);
488 for (
int i = 0; i < 128; i++) {
489 const double a = A * (Rnd.
GetUniDev() + 0.5);
490 const double b = B * (Rnd.
GetUniDev() + 0.5);
491 const double c = C * (Rnd.
GetUniDev() + 0.5);
492 const double d = (1.0 - (A+B+C)) * (Rnd.
GetUniDev() + 0.5);
493 const double abcd = a+b+c+d;
495 sumAB.Add((a+b) / abcd);
496 sumAC.Add((a+c) / abcd);
497 sumABC.
Add((a+b+c) / abcd);
500 for (
int node = 0; node < Nodes; node++) {
504 for (
int edge = 0;
edge < Edges; ) {
505 rngX = Nodes; rngY = Nodes; offX = 0; offY = 0;
508 while (rngX > 1 || rngY > 1) {
510 if (rngX>1 && rngY>1) {
511 if (RndProb < sumA[Depth]) { rngX/=2; rngY/=2; }
512 else if (RndProb < sumAB[Depth]) { offX+=rngX/2; rngX-=rngX/2; rngY/=2; }
513 else if (RndProb < sumABC[Depth]) { offY+=rngY/2; rngX/=2; rngY-=rngY/2; }
514 else { offX+=rngX/2; offY+=rngY/2; rngX-=rngX/2; rngY-=rngY/2; }
517 if (RndProb < sumAC[Depth]) { rngX/=2; rngY/=2; }
518 else { offX+=rngX/2; rngX-=rngX/2; rngY/=2; }
521 if (RndProb < sumAB[Depth]) { rngX/=2; rngY/=2; }
522 else { offY+=rngY/2; rngX/=2; rngY-=rngY/2; }
527 const int NId1 = offX;
528 const int NId2 = offY;
529 if (NId1 != NId2 && ! Graph.
IsEdge(NId1, NId2)) {
531 if (++Cnt > EdgeGap) {
532 Cnt=0; printf(
"\r %d%% edges", ++PctDone); }
537 printf(
"\r RMat: nodes:%d, edges:%d, Iterations:%d, Collisions:%d (%.1f%%).\n", Nodes, Edges,
538 Edges+Collisions, Collisions, 100*Collisions/
double(Edges+Collisions));
548 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
void Reserve(const int &Nodes, const int &Edges)
Reserves memory for a biparite graph of Nodes nodes and Edges edges.
#define IAssertR(Cond, Reason)
TNodeI BegNI() const
Returns an iterator referring to the first node in the graph.
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.
int GetEdges() const
Returns the number of edges 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.
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 GetNodes() const
Returns the number of nodes in 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
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.
int AddEdge(const int &SrcNId, const int &DstNId)
Adds an edge from node IDs 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)
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...
TNodeI EndNI() const
Returns an iterator referring to the past-the-end node in the graph.
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.
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();.
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)
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)