SNAP Library 3.0, User Reference  2016-07-20 17:56:49
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
triad.h
Go to the documentation of this file.
1 #ifndef TRIAD_H
2 #define TRIAD_H
3 
4 namespace TSnap {
5 
7 // Triads and clustering coefficient
8 
10 
12 template <class PGraph> double GetClustCf(const PGraph& Graph, int SampleNodes=-1);
14 
18 template <class PGraph> double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int SampleNodes=-1);
20 
24 template <class PGraph> double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes=-1);
26 
28 template <class PGraph> double GetNodeClustCf(const PGraph& Graph, const int& NId);
30 
34 template <class PGraph> void GetNodeClustCf(const PGraph& Graph, TIntFltH& NIdCCfH);
35 
37 
41 template <class PGraph> int64 GetTriads(const PGraph& Graph, int SampleNodes=-1);
43 
46 template <class PGraph> int64 GetTriads(const PGraph& Graph, int64& ClosedTriadsX, int64& OpenTriadsX, int SampleNodes);
48 
52 template <class PGraph> void GetTriads(const PGraph& Graph, TIntTrV& NIdCOTriadV, int SampleNodes=-1);
54 
57 template <class PGraph> int GetTriadEdges(const PGraph& Graph, int SampleEdges=-1);
58 
60 
64 template <class PGraph> int GetNodeTriads(const PGraph& Graph, const int& NId);
66 
72 template <class PGraph> int GetNodeTriads(const PGraph& Graph, const int& NId, int& ClosedNTriadsX, int& OpenNTriadsX);
74 
82 template <class PGraph>
83 int GetNodeTriads(const PGraph& Graph, const int& NId, const TIntSet& GroupSet, int& InGroupEdgesX, int& InOutGroupEdgesX, int& OutGroupEdgesX);
85 
87 template <class PGraph> void GetTriadParticip(const PGraph& Graph, TIntPrV& TriadCntV);
88 
90 template<class PGraph> int GetCmnNbrs(const PGraph& Graph, const int& NId1, const int& NId2);
92 template<class PGraph> int GetCmnNbrs(const PGraph& Graph, const int& NId1, const int& NId2, TIntV& NbrV);
94 template<class PGraph> int GetLen2Paths(const PGraph& Graph, const int& NId1, const int& NId2);
96 
98 template<class PGraph> int GetLen2Paths(const PGraph& Graph, const int& NId1, const int& NId2, TIntV& NbrV);
100 template<class PGraph> int64 CountTriangles(const PGraph& Graph);
102 template<class PGraph> int64 GetTriangleCnt(const PGraph& Graph);
104 template<class PGraph> void MergeNbrs(TIntV& NeighbourV, const typename PGraph::TObj::TNodeI& NI);
105 
106 void GetMergeSortedV(TIntV& NeighbourV, TNGraph::TNodeI NI);
107 
109 template <class PGraph> void GetUniqueNbrV(const PGraph& Graph, const int& NId, TIntV& NbrV);
110 
112 int GetCommon(TIntV& A, TIntV& B);
113 
115 // Implementation
116 
117 template <class PGraph> double GetClustCf(const PGraph& Graph, int SampleNodes) {
118  TIntTrV NIdCOTriadV;
119  GetTriads(Graph, NIdCOTriadV, SampleNodes);
120  if (NIdCOTriadV.Empty()) { return 0.0; }
121  double SumCcf = 0.0;
122  for (int i = 0; i < NIdCOTriadV.Len(); i++) {
123  const double OpenCnt = NIdCOTriadV[i].Val2()+NIdCOTriadV[i].Val3();
124  if (OpenCnt > 0) {
125  SumCcf += NIdCOTriadV[i].Val2() / OpenCnt; }
126  }
127  IAssert(SumCcf>=0);
128  return SumCcf / double(NIdCOTriadV.Len());
129 }
130 
131 template <class PGraph> double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int SampleNodes) {
132  TIntTrV NIdCOTriadV;
133  GetTriads(Graph, NIdCOTriadV, SampleNodes);
134  THash<TInt, TFltPr> DegSumCnt;
135  double SumCcf = 0.0;
136  for (int i = 0; i < NIdCOTriadV.Len(); i++) {
137  const int D = NIdCOTriadV[i].Val2()+NIdCOTriadV[i].Val3();
138  const double Ccf = D!=0 ? NIdCOTriadV[i].Val2() / double(D) : 0.0;
139  TFltPr& SumCnt = DegSumCnt.AddDat(Graph->GetNI(NIdCOTriadV[i].Val1).GetDeg());
140  SumCnt.Val1 += Ccf;
141  SumCnt.Val2 += 1;
142  SumCcf += Ccf;
143  }
144  // get average clustering coefficient for each degree
145  DegToCCfV.Gen(DegSumCnt.Len(), 0);
146  for (int d = 0; d < DegSumCnt.Len(); d++) {
147  DegToCCfV.Add(TFltPr(DegSumCnt.GetKey(d).Val, double(DegSumCnt[d].Val1()/DegSumCnt[d].Val2())));
148  }
149  DegToCCfV.Sort();
150  return SumCcf / double(NIdCOTriadV.Len());
151 }
152 
153 template <class PGraph>
154 double GetClustCf(const PGraph& Graph, TFltPrV& DegToCCfV, int64& ClosedTriads, int64& OpenTriads, int SampleNodes) {
155  TIntTrV NIdCOTriadV;
156  GetTriads(Graph, NIdCOTriadV, SampleNodes);
157  THash<TInt, TFltPr> DegSumCnt;
158  double SumCcf = 0.0;
159  int64 closedTriads = 0;
160  int64 openTriads = 0;
161  for (int i = 0; i < NIdCOTriadV.Len(); i++) {
162  const int D = NIdCOTriadV[i].Val2()+NIdCOTriadV[i].Val3();
163  const double Ccf = D!=0 ? NIdCOTriadV[i].Val2() / double(D) : 0.0;
164  closedTriads += NIdCOTriadV[i].Val2;
165  openTriads += NIdCOTriadV[i].Val3;
166  TFltPr& SumCnt = DegSumCnt.AddDat(Graph->GetNI(NIdCOTriadV[i].Val1).GetDeg());
167  SumCnt.Val1 += Ccf;
168  SumCnt.Val2 += 1;
169  SumCcf += Ccf;
170  }
171  // get average clustering coefficient for each degree
172  DegToCCfV.Gen(DegSumCnt.Len(), 0);
173  for (int d = 0; d < DegSumCnt.Len(); d++) {
174  DegToCCfV.Add(TFltPr(DegSumCnt.GetKey(d).Val, DegSumCnt[d].Val1()/DegSumCnt[d].Val2()));
175  }
176  //if(closedTriads/3 > (uint64) TInt::Mx) { WarnNotify(TStr::Fmt("[%s line %d] %g closed triads.\n", __FILE__, __LINE__, float(closedTriads/3)).CStr()); }
177  //if(openTriads > (uint64) TInt::Mx) { WarnNotify(TStr::Fmt("[%s line %d] %g open triads.\n", __FILE__, __LINE__, float(openTriads/3)).CStr()); }
178  ClosedTriads = closedTriads/int64(3); // each triad is counted 3 times
179  OpenTriads = openTriads;
180  DegToCCfV.Sort();
181  return SumCcf / double(NIdCOTriadV.Len());
182 }
183 
184 template <class PGraph>
185 double GetNodeClustCf(const PGraph& Graph, const int& NId) {
186  int Open, Closed;
187  GetNodeTriads(Graph, NId, Open, Closed);
188  //const double Deg = Graph->GetNI(NId).GetDeg();
189  return (Open+Closed)==0 ? 0 : double(Open)/double(Open+Closed);
190 }
191 
192 template <class PGraph>
193 void GetNodeClustCf(const PGraph& Graph, TIntFltH& NIdCCfH) {
194  TIntTrV NIdCOTriadV;
195  GetTriads(Graph, NIdCOTriadV);
196  NIdCCfH.Clr(false);
197  for (int i = 0; i < NIdCOTriadV.Len(); i++) {
198  const int D = NIdCOTriadV[i].Val2()+NIdCOTriadV[i].Val3();
199  const double CCf = D!=0 ? NIdCOTriadV[i].Val2() / double(D) : 0.0;
200  NIdCCfH.AddDat(NIdCOTriadV[i].Val1, CCf);
201  }
202 }
203 
204 template <class PGraph>
205 int64 GetTriads(const PGraph& Graph, int SampleNodes) {
206  int64 OpenTriads, ClosedTriads;
207  return GetTriads(Graph, ClosedTriads, OpenTriads, SampleNodes);
208 }
209 
210 template <class PGraph>
211 int64 GetTriads(const PGraph& Graph, int64& ClosedTriads, int64& OpenTriads, int SampleNodes) {
212  TIntTrV NIdCOTriadV;
213  GetTriads(Graph, NIdCOTriadV, SampleNodes);
214  uint64 closedTriads = 0;
215  uint64 openTriads = 0;
216  for (int i = 0; i < NIdCOTriadV.Len(); i++) {
217  closedTriads += NIdCOTriadV[i].Val2;
218  openTriads += NIdCOTriadV[i].Val3;
219  }
220  //IAssert(closedTriads/3 < (uint64) TInt::Mx);
221  //IAssert(openTriads < (uint64) TInt::Mx);
222  ClosedTriads = int64(closedTriads/3); // each triad is counted 3 times
223  OpenTriads = int64(openTriads);
224  return ClosedTriads;
225 }
226 
227 // Function pretends that the graph is undirected (count unique connected triples of nodes)
228 // This implementation is slower, it uses hash tables directly
229 template <class PGraph>
230 void GetTriads_v0(const PGraph& Graph, TIntTrV& NIdCOTriadV, int SampleNodes) {
231  const bool IsDir = Graph->HasFlag(gfDirected);
232  TIntSet NbrH;
233  TIntV NIdV;
234  TRnd Rnd(0);
235 
236  Graph->GetNIdV(NIdV);
237  NIdV.Shuffle(Rnd);
238  if (SampleNodes == -1) {
239  SampleNodes = Graph->GetNodes(); }
240  NIdCOTriadV.Clr(false);
241  NIdCOTriadV.Reserve(SampleNodes);
242  for (int node = 0; node < SampleNodes; node++) {
243  typename PGraph::TObj::TNodeI NI = Graph->GetNI(NIdV[node]);
244  if (NI.GetDeg() < 2) {
245  NIdCOTriadV.Add(TIntTr(NI.GetId(), 0, 0)); // zero triangles
246  continue;
247  }
248  // find neighborhood
249  NbrH.Clr(false);
250  for (int e = 0; e < NI.GetOutDeg(); e++) {
251  if (NI.GetOutNId(e) != NI.GetId()) {
252  NbrH.AddKey(NI.GetOutNId(e)); }
253  }
254  if (IsDir) {
255  for (int e = 0; e < NI.GetInDeg(); e++) {
256  if (NI.GetInNId(e) != NI.GetId()) {
257  NbrH.AddKey(NI.GetInNId(e)); }
258  }
259  }
260  // count connected neighbors
261  int OpenCnt=0, CloseCnt=0;
262  for (int srcNbr = 0; srcNbr < NbrH.Len(); srcNbr++) {
263  const typename PGraph::TObj::TNodeI SrcNode = Graph->GetNI(NbrH.GetKey(srcNbr));
264  for (int dstNbr = srcNbr+1; dstNbr < NbrH.Len(); dstNbr++) {
265  const int dstNId = NbrH.GetKey(dstNbr);
266  if (SrcNode.IsNbrNId(dstNId)) { CloseCnt++; } // is edge
267  else { OpenCnt++; }
268  }
269  }
270  IAssert(2*(OpenCnt+CloseCnt) == NbrH.Len()*(NbrH.Len()-1));
271  NIdCOTriadV.Add(TIntTr(NI.GetId(), CloseCnt, OpenCnt));
272  }
273 }
274 
275 // Function pretends that the graph is undirected (count unique connected triples of nodes)
276 // This implementation is faster, it converts hash tables to vectors
277 template <class PGraph>
278 void GetTriads(const PGraph& Graph, TIntTrV& NIdCOTriadV, int SampleNodes) {
279  const bool IsDir = Graph->HasFlag(gfDirected);
280  TIntSet NbrH;
281  TIntV NIdV;
282  //TRnd Rnd(0);
283  TRnd Rnd(1);
284  int NNodes;
285  TIntV Nbrs;
286  int NId;
287 
288  int64 hcount;
289 
290  hcount = 0;
291 
292  NNodes = Graph->GetNodes();
293  Graph->GetNIdV(NIdV);
294  NIdV.Shuffle(Rnd);
295  if (SampleNodes == -1) {
296  SampleNodes = NNodes;
297  }
298 
299  int MxId = -1;
300  for (int i = 0; i < NNodes; i++) {
301  if (NIdV[i] > MxId) {
302  MxId = NIdV[i];
303  }
304  }
305 
306  TVec<TIntV> NbrV(MxId + 1);
307 
308  if (IsDir) {
309  // get in and out neighbors
310  for (int node = 0; node < NNodes; node++) {
311  int NId = NIdV[node];
312  NbrV[NId] = TIntV();
313  GetUniqueNbrV(Graph, NId, NbrV[NId]);
314  }
315  } else {
316  // get only out neighbors
317  for (int node = 0; node < NNodes; node++) {
318  int NId = NIdV[node];
319  typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
320  NbrV[NId] = TIntV();
321  NbrV[NId].Reserve(NI.GetOutDeg());
322  NbrV[NId].Reduce(0);
323  for (int i = 0; i < NI.GetOutDeg(); i++) {
324  NbrV[NId].Add(NI.GetOutNId(i));
325  }
326  }
327  }
328 
329  NIdCOTriadV.Clr(false);
330  NIdCOTriadV.Reserve(SampleNodes);
331  for (int node = 0; node < SampleNodes; node++) {
332  typename PGraph::TObj::TNodeI NI = Graph->GetNI(NIdV[node]);
333  int NLen;
334 
335  NId = NI.GetId();
336  hcount++;
337  if (NI.GetDeg() < 2) {
338  NIdCOTriadV.Add(TIntTr(NId, 0, 0)); // zero triangles
339  continue;
340  }
341 
342  Nbrs = NbrV[NId];
343  NLen = Nbrs.Len();
344 
345  // count connected neighbors
346  int OpenCnt1 = 0, CloseCnt1 = 0;
347  for (int srcNbr = 0; srcNbr < NLen; srcNbr++) {
348  int Count = GetCommon(NbrV[NbrV[NId][srcNbr]],Nbrs);
349  CloseCnt1 += Count;
350  }
351  CloseCnt1 /= 2;
352  OpenCnt1 = (NLen*(NLen-1))/2 - CloseCnt1;
353  NIdCOTriadV.Add(TIntTr(NId, CloseCnt1, OpenCnt1));
354  }
355 }
356 
357 template<class PGraph>
358 int64 CountTriangles(const PGraph& Graph) {
360  TIntV MapV;
361 
362  int ind = 0;
363  for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
364  H.AddDat(NI.GetId(), ind);
365  MapV.Add(NI.GetId());
366  ind += 1;
367  }
368 
369  TVec<TIntV> HigherDegNbrV(ind);
370 
371 #ifdef USE_OPENMP
372 #pragma omp parallel for schedule(dynamic)
373 #endif
374  for (int i = 0; i < ind; i++) {
375  TNGraph::TNodeI NI = Graph->GetNI(MapV[i]);
376  TIntV NbrV;
377 
378  GetMergeSortedV(NbrV, NI);
379 
380  TIntV V;
381  for (int j = 0; j < NbrV.Len(); j++) {
382  TInt Vert = NbrV[j];
383  TInt Deg = Graph->GetNI(Vert).GetDeg();
384  if (Deg > NI.GetDeg() ||
385  (Deg == NI.GetDeg() && Vert > NI.GetId())) {
386  V.Add(Vert);
387  }
388  }
389 
390  HigherDegNbrV[i] = V;
391 
392  }
393 
394  int64 cnt = 0;
395 #ifdef USE_OPENMP
396 #pragma omp parallel for schedule(dynamic) reduction(+:cnt)
397 #endif
398  for (int i = 0; i < HigherDegNbrV.Len(); i++) {
399  for (int j = 0; j < HigherDegNbrV[i].Len(); j++) {
400  TInt NbrInd = H.GetDat(HigherDegNbrV[i][j]);
401 
402  int64 num = GetCommon(HigherDegNbrV[i], HigherDegNbrV[NbrInd]);
403  cnt += num;
404  }
405  }
406 
407  return cnt;
408 }
409 
410 template<class PGraph>
411 int64 GetTriangleCnt(const PGraph& Graph) {
412  struct timeval start, end;
413  struct timeval startall, endall;
414  float delta;
415  TTmProfiler Profiler;
416  int TimerId = Profiler.AddTimer("Profiler");
417  int TimerAll = Profiler.AddTimer("ProfilerAll");
418  const int NNodes = Graph->GetNodes();
419 
420  TIntV MapV(NNodes);
422  NV.Reduce(0);
423 
424  Profiler.ResetTimer(TimerAll);
425  Profiler.StartTimer(TimerAll);
426  gettimeofday(&startall, NULL);
427 
428  Profiler.ResetTimer(TimerId);
429  Profiler.StartTimer(TimerId);
430  gettimeofday(&start, NULL);
431 
432  int MxId = -1;
433  int ind = 0;
434  for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
435  NV.Add(NI);
436  int Id = NI.GetId();
437  if (Id > MxId) {
438  MxId = Id;
439  }
440  MapV[ind] = Id;
441  ind++;
442  }
443 
444  TIntV IndV(MxId+1);
445 
446  for (int j = 0; j < NNodes; j++) {
447  IndV[MapV[j]] = j;
448  }
449 
450  gettimeofday(&end, NULL);
451  Profiler.StopTimer(TimerId);
452  delta = ((end.tv_sec - start.tv_sec) * 1000000u +
453  end.tv_usec - start.tv_usec) / 1.e6;
454  printf("__nodemap__\ttime %7.3f\tcpu %8.3f\n", delta, Profiler.GetTimerSec(TimerId));
455 
456  Profiler.ResetTimer(TimerId);
457  Profiler.StartTimer(TimerId);
458  gettimeofday(&start, NULL);
459 
460  ind = MapV.Len();
461 
462  Profiler.ResetTimer(TimerId);
463  Profiler.StartTimer(TimerId);
464  gettimeofday(&start, NULL);
465 
466  TVec<TIntV> HigherDegNbrV(ind);
467 
468  for (int i = 0; i < ind; i++) {
469  HigherDegNbrV[i] = TVec<TInt>();
470  HigherDegNbrV[i].Reserve(NV[i].GetDeg());
471  HigherDegNbrV[i].Reduce(0);
472  }
473 
474  gettimeofday(&end, NULL);
475  Profiler.StopTimer(TimerId);
476  delta = ((end.tv_sec - start.tv_sec) * 1000000u +
477  end.tv_usec - start.tv_usec) / 1.e6;
478  printf("__valloc__\ttime %7.3f\tcpu %8.3f\n", delta, Profiler.GetTimerSec(TimerId));
479 
480  Profiler.ResetTimer(TimerId);
481  Profiler.StartTimer(TimerId);
482  gettimeofday(&start, NULL);
483 
484 #ifdef USE_OPENMP
485 #pragma omp parallel for schedule(dynamic)
486 #endif
487  for (int i = 0; i < ind; i++) {
488  typename PGraph::TObj::TNodeI NI = NV[i];
489  //HigherDegNbrV[i] = TVec<TInt>();
490  //HigherDegNbrV[i].Reserve(NI.GetDeg());
491  //HigherDegNbrV[i].Reduce(0);
492 
493  MergeNbrs<PGraph>(HigherDegNbrV[i], NI);
494 
495  int k = 0;
496  for (int j = 0; j < HigherDegNbrV[i].Len(); j++) {
497  TInt Vert = HigherDegNbrV[i][j];
498  TInt Deg = NV[IndV[Vert]].GetDeg();
499  if (Deg > NI.GetDeg() ||
500  (Deg == NI.GetDeg() && Vert > NI.GetId())) {
501  HigherDegNbrV[i][k] = Vert;
502  k++;
503  }
504  }
505  HigherDegNbrV[i].Reduce(k);
506  }
507 
508  gettimeofday(&end, NULL);
509  Profiler.StopTimer(TimerId);
510  delta = ((end.tv_sec - start.tv_sec) * 1000000u +
511  end.tv_usec - start.tv_usec) / 1.e6;
512  printf("__sort__\ttime %7.3f\tcpu %8.3f\n", delta, Profiler.GetTimerSec(TimerId));
513 
514  Profiler.ResetTimer(TimerId);
515  Profiler.StartTimer(TimerId);
516  gettimeofday(&start, NULL);
517 
518  int64 cnt = 0;
519 #ifdef USE_OPENMP
520 #pragma omp parallel for schedule(dynamic) reduction(+:cnt)
521 #endif
522  for (int i = 0; i < HigherDegNbrV.Len(); i++) {
523  for (int j = 0; j < HigherDegNbrV[i].Len(); j++) {
524  //TInt NbrInd = H.GetDat(HigherDegNbrV[i][j]);
525  TInt NbrInd = IndV[HigherDegNbrV[i][j]];
526 
527  int64 num = GetCommon(HigherDegNbrV[i], HigherDegNbrV[NbrInd]);
528  cnt += num;
529  }
530  }
531 
532  gettimeofday(&end, NULL);
533  Profiler.StopTimer(TimerId);
534  delta = ((end.tv_sec - start.tv_sec) * 1000000u +
535  end.tv_usec - start.tv_usec) / 1.e6;
536  printf("__count__\ttime %7.3f\tcpu %8.3f\n", delta, Profiler.GetTimerSec(TimerId));
537 
538  gettimeofday(&endall, NULL);
539  Profiler.StopTimer(TimerAll);
540  delta = ((endall.tv_sec - startall.tv_sec) * 1000000u +
541  endall.tv_usec - startall.tv_usec) / 1.e6;
542  printf("__all__ \ttime %7.3f\tcpu %8.3f\n", delta, Profiler.GetTimerSec(TimerAll));
543 
544  return cnt;
545 }
546 template<class PGraph>
547 void MergeNbrs(TIntV& NeighbourV, const typename PGraph::TObj::TNodeI& NI) {
548  int j = 0;
549  int k = 0;
550  int prev = -1;
551  int indeg = NI.GetInDeg();
552  int outdeg = NI.GetOutDeg();
553  //while (j < NI.GetInDeg() && k < NI.GetOutDeg()) {
554  if (indeg > 0 && outdeg > 0) {
555  int v1 = NI.GetInNId(j);
556  int v2 = NI.GetOutNId(k);
557  while (1) {
558  if (v1 <= v2) {
559  if (prev != v1) {
560  NeighbourV.Add(v1);
561  prev = v1;
562  }
563  j += 1;
564  if (j >= indeg) {
565  break;
566  }
567  v1 = NI.GetInNId(j);
568  } else {
569  if (prev != v2) {
570  NeighbourV.Add(v2);
571  prev = v2;
572  }
573  k += 1;
574  if (k >= outdeg) {
575  break;
576  }
577  v2 = NI.GetOutNId(k);
578  }
579  }
580  }
581  while (j < indeg) {
582  int v = NI.GetInNId(j);
583  if (prev != v) {
584  NeighbourV.Add(v);
585  prev = v;
586  }
587  j += 1;
588  }
589  while (k < outdeg) {
590  int v = NI.GetOutNId(k);
591  if (prev != v) {
592  NeighbourV.Add(v);
593  prev = v;
594  }
595  k += 1;
596  }
597 }
598 
599 // Count the number of edges that participate in at least one triad
600 template <class PGraph>
601 int GetTriadEdges(const PGraph& Graph, int SampleEdges) {
602  const bool IsDir = Graph->HasFlag(gfDirected);
603  TIntSet NbrH;
604  int TriadEdges = 0;
605  for(typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
606  NbrH.Clr(false);
607  for (int e = 0; e < NI.GetOutDeg(); e++) {
608  if (NI.GetOutNId(e) != NI.GetId()) {
609  NbrH.AddKey(NI.GetOutNId(e)); }
610  }
611  if (IsDir) {
612  for (int e = 0; e < NI.GetInDeg(); e++) {
613  if (NI.GetInNId(e) != NI.GetId()) {
614  NbrH.AddKey(NI.GetInNId(e)); }
615  }
616  }
617  for (int e = 0; e < NI.GetOutDeg(); e++) {
618  if (!IsDir && NI.GetId()<NI.GetOutNId(e)) { continue; } // for undirected graphs count each edge only once
619  const typename PGraph::TObj::TNodeI SrcNode = Graph->GetNI(NI.GetOutNId(e));
620  bool Triad=false;
621  for (int e1 = 0; e1 < SrcNode.GetOutDeg(); e1++) {
622  if (NbrH.IsKey(SrcNode.GetOutNId(e1))) { Triad=true; break; }
623  }
624  if (IsDir && ! Triad) {
625  for (int e1 = 0; e1 < SrcNode.GetInDeg(); e1++) {
626  if (NbrH.IsKey(SrcNode.GetInNId(e1))) { Triad=true; break; }
627  }
628  }
629  if (Triad) { TriadEdges++; }
630  }
631  }
632  return TriadEdges;
633 }
634 
635 // Returns number of undirected triads a node participates in
636 template <class PGraph>
637 int GetNodeTriads(const PGraph& Graph, const int& NId) {
638  int ClosedTriads=0, OpenTriads=0;
639  return GetNodeTriads(Graph, NId, ClosedTriads, OpenTriads);
640 }
641 
642 // Return number of undirected triads a node participates in
643 template <class PGraph>
644 int GetNodeTriads(const PGraph& Graph, const int& NId, int& ClosedTriads, int& OpenTriads) {
645  const typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
646  ClosedTriads=0; OpenTriads=0;
647  if (NI.GetDeg() < 2) { return 0; }
648  // find neighborhood
649  TIntSet NbrSet(NI.GetDeg());
650  for (int e = 0; e < NI.GetOutDeg(); e++) {
651  if (NI.GetOutNId(e) != NI.GetId()) { // exclude self edges
652  NbrSet.AddKey(NI.GetOutNId(e)); }
653  }
654  if (Graph->HasFlag(gfDirected)) {
655  for (int e = 0; e < NI.GetInDeg(); e++) {
656  if (NI.GetInNId(e) != NI.GetId()) { // exclude self edges
657  NbrSet.AddKey(NI.GetInNId(e)); }
658  }
659  }
660  // count connected neighbors
661  for (int srcNbr = 0; srcNbr < NbrSet.Len(); srcNbr++) {
662  const typename PGraph::TObj::TNodeI SrcNode = Graph->GetNI(NbrSet.GetKey(srcNbr));
663  for (int dstNbr = srcNbr+1; dstNbr < NbrSet.Len(); dstNbr++) {
664  const int dstNId = NbrSet.GetKey(dstNbr);
665  if (SrcNode.IsNbrNId(dstNId)) { ClosedTriads++; }
666  else { OpenTriads++; }
667  }
668  }
669  return ClosedTriads;
670 }
671 
672 // Node NId and a subset of its neighbors GroupSet
673 // InGroupEdges ... triads (NId, g1, g2), where g1 and g2 are in GroupSet
674 // InOutGroupEdges ... triads (NId, g1, o1), where g1 in GroupSet and o1 not in GroupSet
675 // OutGroupEdges ... triads (NId, o1, o2), where o1 and o2 are not in GroupSet
676 template <class PGraph>
677 int GetNodeTriads(const PGraph& Graph, const int& NId, const TIntSet& GroupSet, int& InGroupEdges, int& InOutGroupEdges, int& OutGroupEdges) {
678  const typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
679  const bool IsDir = Graph->HasFlag(gfDirected);
680  InGroupEdges=0; InOutGroupEdges=0; OutGroupEdges=0;
681  if (NI.GetDeg() < 2) { return 0; }
682  // find neighborhood
683  TIntSet NbrSet(NI.GetDeg());
684  for (int e = 0; e < NI.GetOutDeg(); e++) {
685  if (NI.GetOutNId(e) != NI.GetId()) { // exclude self edges
686  NbrSet.AddKey(NI.GetOutNId(e)); }
687  }
688  if (IsDir) {
689  for (int e = 0; e < NI.GetInDeg(); e++) {
690  if (NI.GetInNId(e) != NI.GetId()) {
691  NbrSet.AddKey(NI.GetInNId(e)); }
692  }
693  }
694  // count connected neighbors
695  for (int srcNbr = 0; srcNbr < NbrSet.Len(); srcNbr++) {
696  const int NbrId = NbrSet.GetKey(srcNbr);
697  const bool NbrIn = GroupSet.IsKey(NbrId);
698  const typename PGraph::TObj::TNodeI SrcNode = Graph->GetNI(NbrId);
699  for (int dstNbr = srcNbr+1; dstNbr < NbrSet.Len(); dstNbr++) {
700  const int DstNId = NbrSet.GetKey(dstNbr);
701  if (SrcNode.IsNbrNId(DstNId)) { // triad (NId, NbrId, DstNid)
702  bool DstIn = GroupSet.IsKey(DstNId);
703  if (NbrIn && DstIn) { InGroupEdges++; }
704  else if (NbrIn || DstIn) { InOutGroupEdges++; }
705  else { OutGroupEdges++; }
706  }
707  }
708  }
709  return InGroupEdges;
710 }
711 
712 // For each node count how many triangles it participates in
713 template <class PGraph>
714 void GetTriadParticip(const PGraph& Graph, TIntPrV& TriadCntV) {
715  TIntH TriadCntH;
716  for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
717  const int Triads = GetNodeTriads(Graph, NI.GetId());
718  TriadCntH.AddDat(Triads) += 1;
719  }
720  TriadCntH.GetKeyDatPrV(TriadCntV);
721  TriadCntV.Sort();
722 }
723 
724 template<class PGraph>
725 int GetCmnNbrs(const PGraph& Graph, const int& NId1, const int& NId2) {
726  TIntV NbrV;
727  return GetCmnNbrs(Graph, NId1, NId2, NbrV);
728 }
729 
730 // Get common neighbors between a pair of nodes (undirected)
731 template<class PGraph>
732 int GetCmnNbrs(const PGraph& Graph, const int& NId1, const int& NId2, TIntV& NbrV) {
733  if (! Graph->IsNode(NId1) || ! Graph->IsNode(NId2)) { NbrV.Clr(false); return 0; }
734  typename PGraph::TObj::TNodeI NI1 = Graph->GetNI(NId1);
735  typename PGraph::TObj::TNodeI NI2 = Graph->GetNI(NId2);
736  NbrV.Clr(false);
737  NbrV.Reserve(TMath::Mn(NI1.GetDeg(), NI2.GetDeg()));
738  TIntSet NSet1(NI1.GetDeg()), NSet2(NI2.GetDeg());
739  for (int i = 0; i < NI1.GetDeg(); i++) {
740  const int nid = NI1.GetNbrNId(i);
741  if (nid!=NId1 && nid!=NId2) {
742  NSet1.AddKey(nid); }
743  }
744  for (int i = 0; i < NI2.GetDeg(); i++) {
745  const int nid = NI2.GetNbrNId(i);
746  if (NSet1.IsKey(nid)) {
747  NSet2.AddKey(nid);
748  }
749  }
750  NSet2.GetKeyV(NbrV);
751  return NbrV.Len();
752 }
753 
754 template<>
755 inline int GetCmnNbrs<PUNGraph>(const PUNGraph& Graph, const int& NId1, const int& NId2, TIntV& NbrV) {
756  if (! Graph->IsNode(NId1) || ! Graph->IsNode(NId2)) { NbrV.Clr(false); return 0; }
757  const TUNGraph::TNodeI NI1 = Graph->GetNI(NId1);
758  const TUNGraph::TNodeI NI2 = Graph->GetNI(NId2);
759  int i=0, j=0;
760  NbrV.Clr(false);
761  NbrV.Reserve(TMath::Mn(NI1.GetDeg(), NI2.GetDeg()));
762  while (i < NI1.GetDeg() && j < NI2.GetDeg()) {
763  const int nid = NI1.GetNbrNId(i);
764  while (j < NI2.GetDeg() && NI2.GetNbrNId(j) < nid) { j++; }
765  if (j < NI2.GetDeg() && nid==NI2.GetNbrNId(j) && nid!=NId1 && nid!=NId2) {
766  IAssert(NbrV.Empty() || NbrV.Last() < nid);
767  NbrV.Add(nid);
768  j++;
769  }
770  i++;
771  }
772  return NbrV.Len();
773 }
774 
775 // get number of length 2 directed paths between a pair of nodes
776 // for a pair of nodes (i,j): |{u: (i,u) and (u,j) }|
777 template<class PGraph>
778 int GetLen2Paths(const PGraph& Graph, const int& NId1, const int& NId2) {
779  TIntV NbrV;
780  return GetLen2Paths(Graph, NId1, NId2, NbrV);
781 }
782 
783 // get number of length 2 directed paths between a pair of nodes
784 // for a pair of nodes (i,j): {u: (i,u) and (u,j) }
785 template<class PGraph>
786 int GetLen2Paths(const PGraph& Graph, const int& NId1, const int& NId2, TIntV& NbrV) {
787  const typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId1);
788  NbrV.Clr(false);
789  NbrV.Reserve(NI.GetOutDeg());
790  for (int e = 0; e < NI.GetOutDeg(); e++) {
791  const typename PGraph::TObj::TNodeI MidNI = Graph->GetNI(NI.GetOutNId(e));
792  if (MidNI.IsOutNId(NId2)) {
793  NbrV.Add(MidNI.GetId());
794  }
795  }
796  return NbrV.Len();
797 }
798 
799 template <class PGraph>
800 void GetUniqueNbrV(const PGraph& Graph, const int& NId, TIntV& NbrV) {
801  typename PGraph::TObj::TNodeI NI = Graph->GetNI(NId);
802  NbrV.Reserve(NI.GetDeg());
803  NbrV.Reduce(0);
804 
805  int j = 0;
806  int k = 0;
807  int Prev = -1;
808  int InDeg = NI.GetInDeg();
809  int OutDeg = NI.GetOutDeg();
810  if (InDeg > 0 && OutDeg > 0) {
811  int v1 = NI.GetInNId(j);
812  int v2 = NI.GetOutNId(k);
813  while (1) {
814  if (v1 <= v2) {
815  if (Prev != v1) {
816  if (v1 != NId) {
817  NbrV.Add(v1);
818  Prev = v1;
819  }
820  }
821  j += 1;
822  if (j >= InDeg) {
823  break;
824  }
825  v1 = NI.GetInNId(j);
826  } else {
827  if (Prev != v2) {
828  if (v2 != NId) {
829  NbrV.Add(v2);
830  }
831  Prev = v2;
832  }
833  k += 1;
834  if (k >= OutDeg) {
835  break;
836  }
837  v2 = NI.GetOutNId(k);
838  }
839  }
840  }
841  while (j < InDeg) {
842  int v = NI.GetInNId(j);
843  if (Prev != v) {
844  if (v != NId) {
845  NbrV.Add(v);
846  }
847  Prev = v;
848  }
849  j += 1;
850  }
851  while (k < OutDeg) {
852  int v = NI.GetOutNId(k);
853  if (Prev != v) {
854  if (v != NId) {
855  NbrV.Add(v);
856  }
857  Prev = v;
858  }
859  k += 1;
860  }
861 }
862 
863 }; // mamespace TSnap
864 
866 // Node and Edge Network Constraint (by Ron Burt)
867 // works for directed and undirected graphs (but not for multigraphs)
868 template <class PGraph>
870 public:
871  PGraph Graph;
872  THash<TIntPr, TFlt> NodePrCH; // pairs of nodes that have non-zero network constraint
873 public:
874  TNetConstraint(const PGraph& GraphPt, const bool& CalcaAll=true);
875  int Len() const { return NodePrCH.Len(); }
876  double GetC(const int& ConstraintN) const { return NodePrCH[ConstraintN]; }
877  TIntPr GetNodePr(const int& ConstraintN) const { return NodePrCH.GetKey(ConstraintN); }
878  double GetEdgeC(const int& NId1, const int& NId2) const;
879  double GetNodeC(const int& NId) const;
880  void AddConstraint(const int& NId1, const int& NId2);
881  void CalcConstraints();
882  void CalcConstraints(const int& NId);
883  void Dump() const;
884  static void Test();
885 };
886 
887 template <class PGraph>
888 TNetConstraint<PGraph>::TNetConstraint(const PGraph& GraphPt, const bool& CalcaAll) : Graph(GraphPt) {
889  CAssert(! HasGraphFlag(typename PGraph::TObj, gfMultiGraph)); // must not be multigraph
890  if (CalcaAll) {
891  CalcConstraints();
892  }
893 }
894 
895 template <class PGraph>
896 double TNetConstraint<PGraph>::GetEdgeC(const int& NId1, const int& NId2) const {
897  if (NodePrCH.IsKey(TIntPr(NId1, NId2))) {
898  return NodePrCH.GetDat(TIntPr(NId1, NId2)); }
899  else {
900  return 0.0; }
901 }
902 
903 template <class PGraph>
904 double TNetConstraint<PGraph>::GetNodeC(const int& NId) const {
905  typename PGraph::TObj::TNodeI NI1 = Graph->GetNI(NId);
906  if (NI1.GetOutDeg() == 0) { return 0.0; }
907  int KeyId = -1;
908  for (int k = 0; k<NI1.GetOutDeg(); k++) {
909  KeyId = NodePrCH.GetKeyId(TIntPr(NI1.GetId(), NI1.GetOutNId(k)));
910  if (KeyId > -1) { break; }
911  }
912  if (KeyId < 0) { return 0.0; }
913  double Constraint = NodePrCH[KeyId];
914  for (int i = KeyId-1; i >-1 && NodePrCH.GetKey(i).Val1()==NId; i--) {
915  Constraint += NodePrCH[i];
916  }
917  for (int i = KeyId+1; i < NodePrCH.Len() && NodePrCH.GetKey(i).Val1()==NId; i++) {
918  Constraint += NodePrCH[i];
919  }
920  return Constraint;
921 }
922 
923 template <class PGraph>
924 void TNetConstraint<PGraph>::AddConstraint(const int& NId1, const int& NId2) {
925  if (NId1==NId2 || NodePrCH.IsKey(TIntPr(NId1, NId2))) {
926  return;
927  }
928  typename PGraph::TObj::TNodeI NI1 = Graph->GetNI(NId1);
929  double Constraint = 0.0;
930  if (NI1.IsOutNId(NId2)) { // is direct edge
931  Constraint += 1.0/(double) NI1.GetOutDeg();
932  }
933  const double SrcC = 1.0/(double) NI1.GetOutDeg();
934  for (int e = 0; e < NI1.GetOutDeg(); e++) {
935  const int MidNId = NI1.GetOutNId(e);
936  if (MidNId == NId1 || MidNId == NId2) { continue; }
937  const typename PGraph::TObj::TNodeI MidNI = Graph->GetNI(MidNId);
938  if (MidNI.IsOutNId(NId2)) {
939  Constraint += SrcC * (1.0/(double)MidNI.GetOutDeg());
940  }
941  }
942  if (Constraint==0) { return; }
943  Constraint = TMath::Sqr(Constraint);
944  NodePrCH.AddDat(TIntPr(NId1, NId2), Constraint);
945 }
946 
947 template <class PGraph>
949  // add edges
950  for (typename PGraph::TObj::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
951  AddConstraint(EI.GetSrcNId(), EI.GetDstNId());
952  AddConstraint(EI.GetDstNId(), EI.GetSrcNId());
953  }
954  // add open triads
955  for (typename PGraph::TObj::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
956  for (int i = 0; i < NI.GetDeg(); i++) {
957  const int NId1 = NI.GetNbrNId(i);
958  for (int j = 0; j < NI.GetDeg(); j++) {
959  const int NId2 = NI.GetNbrNId(j);
960  AddConstraint(NId1, NId2);
961  }
962  }
963  }
964  NodePrCH.SortByKey();
965 }
966 
967 // calculate constraints around a node id
968 template <class PGraph>
970  typename PGraph::TObj::TNodeI StartNI = Graph->GetNI(NId);
971  TIntSet SeenSet;
972  for (int e = 0; e < StartNI.GetOutDeg(); e++) {
973  typename PGraph::TObj::TNodeI MidNI = Graph->GetNI(StartNI.GetOutNId(e));
974  AddConstraint(NId, MidNI.GetId());
975  for (int i = 0; i < MidNI.GetOutDeg(); i++) {
976  const int EndNId = MidNI.GetOutNId(i);
977  if (! SeenSet.IsKey(EndNId)) {
978  AddConstraint(NId, EndNId);
979  SeenSet.AddKey(EndNId);
980  }
981  }
982  }
983 }
984 
985 template <class PGraph>
987  printf("Edge network constraint: (%d, %d)\n", Graph->GetNodes(), Graph->GetEdges());
988  for (int e = 0; e < NodePrCH.Len(); e++) {
989  printf(" %4d %4d : %f\n", NodePrCH.GetKey(e).Val1(), NodePrCH.GetKey(e).Val2(), NodePrCH[e].Val);
990  }
991  printf("\n");
992 }
993 
994 // example from page 56 of Structural Holes by Ronald S. Burt
995 // (http://www.amazon.com/Structural-Holes-Social-Structure-Competition/dp/0674843711)
996 template <class PGraph>
998  PUNGraph G = TUNGraph::New();
999  G->AddNode(0); G->AddNode(1); G->AddNode(2); G->AddNode(3);
1000  G->AddNode(4); G->AddNode(5); G->AddNode(6);
1001  G->AddEdge(0,1); G->AddEdge(0,2); G->AddEdge(0,3); G->AddEdge(0,4); G->AddEdge(0,5); G->AddEdge(0,6);
1002  G->AddEdge(1,2); G->AddEdge(1,5); G->AddEdge(1,6);
1003  G->AddEdge(2,4);
1004  TNetConstraint<PUNGraph> NetConstraint(G, true);
1005  // NetConstraint.CalcConstraints(0);
1006  NetConstraint.Dump();
1007  printf("middle node network constraint: %f\n", NetConstraint.GetNodeC(0));
1008 }
1009 
1010 #endif // TRIAD_H
1011 
void Clr(const bool &DoDel=true, const int &NoDelLim=-1)
Definition: shash.h:1243
#define IAssert(Cond)
Definition: bd.h:262
double GetTimerSec(const int &TimerId) const
Definition: tm.cpp:1293
static const T & Mn(const T &LVal, const T &RVal)
Definition: xmath.h:36
void GetUniqueNbrV(const PGraph &Graph, const int &NId, TIntV &NbrV)
Returns sorted vector NbrV containing unique in or out neighbors of node NId in graph Graph...
Definition: triad.h:800
TPair< TInt, TInt > TIntPr
Definition: ds.h:83
int64 GetTriads(const PGraph &Graph, int64 &ClosedTriads, int64 &OpenTriads, int SampleNodes=-1)
Computes the number of Closed and Open triads.
Definition: triad.h:211
void CalcConstraints()
Definition: triad.h:948
Definition: dt.h:11
int64 GetTriangleCnt(const PGraph &Graph)
Returns the number of triangles in graph Graph, newer version.
Definition: triad.h:411
int64 CountTriangles(const PGraph &Graph)
Returns the number of triangles in graph Graph, original version.
Definition: triad.h:358
int Val
Definition: dt.h:1046
double GetNodeClustCf(const PGraph &Graph, const int &NId)
Returns clustering coefficient of a particular node.
Definition: triad.h:185
static void Test()
Definition: triad.h:997
int GetLen2Paths(const PGraph &Graph, const int &NId1, const int &NId2)
Returns the number of length 2 directed paths between a pair of nodes NId1, NId2 (NId1 –> U –> NId2...
Definition: triad.h:778
int AddNode(int NId=-1)
Adds a node of ID NId to the graph.
Definition: graph.cpp:8
TSizeTy Len() const
Returns the number of elements in the vector.
Definition: ds.h:547
Node iterator. Only forward iteration (operator++) is supported.
Definition: graph.h:64
PGraph Graph
Definition: triad.h:871
int GetCmnNbrs< PUNGraph >(const PUNGraph &Graph, const int &NId1, const int &NId2, TIntV &NbrV)
Definition: triad.h:755
void MergeNbrs(TIntV &NeighbourV, const typename PGraph::TObj::TNodeI &NI)
Merges neighbors.
Definition: triad.h:547
const TDat & GetDat(const TKey &Key) const
Definition: hash.h:220
static double Sqr(const double &x)
Definition: xmath.h:12
TNetConstraint(const PGraph &GraphPt, const bool &CalcaAll=true)
Definition: triad.h:888
void Reduce(const TSizeTy &_Vals=-1)
Reduces the vector's length to _Vals elements, which must be less than the current length...
Definition: ds.h:528
bool IsKey(const TKey &Key) const
Definition: shash.h:1148
const TKey & GetKey(const int &KeyId) const
Definition: shash.h:1141
bool Empty() const
Tests whether the vector is empty.
Definition: ds.h:542
have explicit edges (multigraph): TNEGraph, TNodeEdgeNet
Definition: gbase.h:14
int GetDeg() const
Returns degree of the current node.
Definition: graph.h:86
int AddTimer(const TStr &TimerNm)
Definition: tm.cpp:1272
void Clr(const bool &DoDel=true, const TSizeTy &NoDelLim=-1)
Clears the contents of the vector.
Definition: ds.h:971
void Sort(const bool &Asc=true)
Sorts the elements of the vector.
Definition: ds.h:1254
#define HasGraphFlag(TGraph, Flag)
For quick testing of the properties of the graph/network object (see TGraphFlag). ...
Definition: gbase.h:41
unsigned long long uint64
Definition: bd.h:38
void GetTriads_v0(const PGraph &Graph, TIntTrV &NIdCOTriadV, int SampleNodes)
Definition: triad.h:230
void AddConstraint(const int &NId1, const int &NId2)
Definition: triad.h:924
void GetMergeSortedV(TIntV &NeighbourV, TNGraph::TNodeI NI)
Definition: triad.cpp:3
double GetNodeC(const int &NId) const
Definition: triad.h:904
static PUNGraph New()
Static constructor that returns a pointer to the graph. Call: PUNGraph Graph = TUNGraph::New().
Definition: graph.h:155
int AddKey(const TKey &Key)
Definition: shash.h:1254
int GetNodeTriads(const PGraph &Graph, const int &NId)
Returns the number of undirected triads a node NId participates in.
Definition: triad.h:637
double GetC(const int &ConstraintN) const
Definition: triad.h:876
TPair< TFlt, TFlt > TFltPr
Definition: ds.h:99
int GetDeg() const
Returns degree of the current node, the sum of in-degree and out-degree.
Definition: graph.h:358
int AddEdge(const int &SrcNId, const int &DstNId)
Adds an edge between node IDs SrcNId and DstNId to the graph.
Definition: graph.cpp:92
void StopTimer(const TStr &TimerNm)
Definition: tm.h:419
void Dump() const
Definition: triad.h:986
void StartTimer(const TStr &TimerNm)
Definition: tm.h:416
Definition: dt.h:1044
directed graph (TNGraph, TNEGraph), else graph is undirected TUNGraph
Definition: gbase.h:13
double GetEdgeC(const int &NId1, const int &NId2) const
Definition: triad.h:896
#define CAssert(Cond)
Definition: bd.h:302
int Len() const
Definition: shash.h:1121
int GetId() const
Returns ID of the current node.
Definition: graph.h:356
long long int64
Definition: bd.h:27
int GetTriadEdges(const PGraph &Graph, int SampleEdges=-1)
Counts the number of edges that participate in at least one triad.
Definition: triad.h:601
int GetCommon(TIntV &A, TIntV &B)
Returns the number of common elements in two sorted TInt vectors.
Definition: triad.cpp:54
void Shuffle(TRnd &Rnd)
Randomly shuffles the elements of the vector.
Definition: ds.h:1271
Node iterator. Only forward iteration (operator++) is supported.
Definition: graph.h:339
void GetTriadParticip(const PGraph &Graph, TIntPrV &TriadCntV)
Triangle Participation Ratio: For each node counts how many triangles it participates in and then ret...
Definition: triad.h:714
void GetKeyDatPrV(TVec< TPair< TKey, TDat > > &KeyDatPrV) const
Definition: hash.h:458
void ResetTimer(const TStr &TimerNm)
Definition: tm.h:423
double GetClustCf(const PGraph &Graph, int SampleNodes=-1)
Computes the average clustering coefficient as defined in Watts and Strogatz, Collective dynamics of ...
Definition: triad.h:117
TVal1 Val1
Definition: ds.h:34
int GetNbrNId(const int &NodeN) const
Returns ID of NodeN-th neighboring node.
Definition: graph.h:107
TVec< TInt > TIntV
Definition: ds.h:1529
TVal2 Val2
Definition: ds.h:35
void Clr(const bool &DoDel=true, const int &NoDelLim=-1, const bool &ResetDat=true)
Definition: hash.h:319
Definition: bd.h:196
TIntPr GetNodePr(const int &ConstraintN) const
Definition: triad.h:877
TTriple< TInt, TInt, TInt > TIntTr
Definition: ds.h:170
void Gen(const TSizeTy &_Vals)
Constructs a vector (an array) of _Vals elements.
Definition: ds.h:495
void Reserve(const TSizeTy &_MxVals)
Reserves enough memory for the vector to store _MxVals elements.
Definition: ds.h:515
THash< TIntPr, TFlt > NodePrCH
Definition: triad.h:872
TSizeTy Add()
Adds a new element at the end of the vector, after its current last element.
Definition: ds.h:574
int Len() const
Definition: hash.h:186
TDat & AddDat(const TKey &Key)
Definition: hash.h:196
int GetCmnNbrs(const PGraph &Graph, const int &NId1, const int &NId2)
Returns a number of shared neighbors between a pair of nodes NId1 and NId2.
Definition: triad.h:725
const TKey & GetKey(const int &KeyId) const
Definition: hash.h:210
int Len() const
Definition: triad.h:875
Vector is a sequence TVal objects representing an array that can change in size.
Definition: ds.h:429