void GetEigenVectorCentr(const PUNGraph& Graph, TIntFltH& EigenH, const double& Eps, const int& MaxIter) { const int NNodes = Graph->GetNodes(); EigenH.Gen(NNodes); for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { EigenH.AddDat(NI.GetId(), 1.0/NNodes); IAssert(NI.GetId() == EigenH.GetKey(EigenH.Len()-1)); } TFltV TmpV(NNodes); double diff = TFlt::Mx; for (int iter = 0; iter < MaxIter; iter++) { int j = 0; for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++, j++) { TmpV[j] = 0; for (int e = 0; e < NI.GetOutDeg(); e++) { TmpV[j] += EigenH.GetDat(NI.GetOutNId(e)); } } double sum = 0; for (int i = 0; i < TmpV.Len(); i++) { EigenH[i] = TmpV[i]; sum += EigenH[i]; } for (int i = 0; i < EigenH.Len(); i++) { EigenH[i] /= sum; } if (fabs(diff-sum) < Eps) { break; } //printf("\tdiff:%f\tsum:%f\n", fabs(diff-sum), sum); diff = sum; } }
int ComputeKCore(const PUNGraph& G) { int cnt = 0; for(TUNGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) cnt = max(cnt, NI.GetOutDeg()); THashSet <TInt> D[cnt+1]; THash <TInt, TInt> deg; for(TUNGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { TInt tmp = NI.GetOutDeg() - G->IsEdge(NI.GetId(), NI.GetId() ); D[tmp.Val].AddKey(NI.GetId()); deg.AddDat(NI.GetId()) = tmp; } int max_k = 0; for(int num_iters = 0;num_iters < G->GetNodes(); num_iters++) for(int i = 0; i < cnt; i++) if(D[i].Empty() == 0) { max_k = max(max_k, i); TInt a = *(D[i].BegI()); D[i].DelKey(a); deg.AddDat(a.Val) = -1; // Hope overwriting works TUNGraph::TNodeI NI = G->GetNI(a.Val); for(int e = 0; e < NI.GetOutDeg(); e++) { TInt b = NI.GetOutNId(e); if(deg.GetDat(b) >= 0) { int Id = deg.GetKeyId(b); D[deg[Id].Val].DelKey(b); deg[Id] = deg[Id] - 1; //Hope the overwriting works D[deg[Id]].AddKey(b); } } break; } return max_k; }
double TAGMUtil::GetConductance(const PUNGraph& Graph, const TIntSet& CmtyS, const int Edges) { const int Edges2 = Edges >= 0 ? 2*Edges : Graph->GetEdges(); int Vol = 0, Cut = 0; double Phi = 0.0; for (int i = 0; i < CmtyS.Len(); i++) { if (! Graph->IsNode(CmtyS[i])) { continue; } TUNGraph::TNodeI NI = Graph->GetNI(CmtyS[i]); for (int e = 0; e < NI.GetOutDeg(); e++) { if (! CmtyS.IsKey(NI.GetOutNId(e))) { Cut += 1; } } Vol += NI.GetOutDeg(); } // get conductance if (Vol != Edges2) { if (2 * Vol > Edges2) { Phi = Cut / double (Edges2 - Vol); } else if (Vol == 0) { Phi = 0.0; } else { Phi = Cut / double(Vol); } } else { if (Vol == Edges2) { Phi = 1.0; } } return Phi; }
/// Rewire the network. Keeps node degrees as is but randomly rewires the edges. /// Use this function to generate a random graph with the same degree sequence /// as the OrigGraph. /// See: On the uniform generation of random graphs with prescribed degree /// sequences by R. Milo, N. Kashtan, S. Itzkovitz, M. E. J. Newman, U. Alon /// URL: http://arxiv.org/abs/cond-mat/0312028 PUNGraph GenRewire(const PUNGraph& OrigGraph, const int& NSwitch, TRnd& Rnd) { const int Nodes = OrigGraph->GetNodes(); const int Edges = OrigGraph->GetEdges(); PUNGraph GraphPt = TUNGraph::New(); TUNGraph& Graph = *GraphPt; Graph.Reserve(Nodes, -1); TExeTm ExeTm; // generate a graph that satisfies the constraints printf("Randomizing edges (%d, %d)...\n", Nodes, Edges); TIntPrSet EdgeSet(Edges); for (TUNGraph::TNodeI NI = OrigGraph->BegNI(); NI < OrigGraph->EndNI(); NI++) { const int NId = NI.GetId(); for (int e = 0; e < NI.GetOutDeg(); e++) { if (NId <= NI.GetOutNId(e)) { continue; } EdgeSet.AddKey(TIntPr(NId, NI.GetOutNId(e))); } Graph.AddNode(NI.GetId()); } // edge switching uint skip=0; for (uint swps = 0; swps < 2*uint(Edges)*uint(NSwitch); swps++) { const int keyId1 = EdgeSet.GetRndKeyId(Rnd); const int keyId2 = EdgeSet.GetRndKeyId(Rnd); if (keyId1 == keyId2) { skip++; continue; } const TIntPr& E1 = EdgeSet[keyId1]; const TIntPr& E2 = EdgeSet[keyId2]; TIntPr NewE1(E1.Val1, E2.Val1), NewE2(E1.Val2, E2.Val2); if (NewE1.Val1 > NewE1.Val2) { Swap(NewE1.Val1, NewE1.Val2); } if (NewE2.Val1 > NewE2.Val2) { Swap(NewE2.Val1, NewE2.Val2); } if (NewE1!=NewE2 && NewE1.Val1!=NewE1.Val2 && NewE2.Val1!=NewE2.Val2 && ! EdgeSet.IsKey(NewE1) && ! EdgeSet.IsKey(NewE2)) { EdgeSet.DelKeyId(keyId1); EdgeSet.DelKeyId(keyId2); EdgeSet.AddKey(TIntPr(NewE1)); EdgeSet.AddKey(TIntPr(NewE2)); } else { skip++; } if (swps % Edges == 0) { printf("\r %uk/%uk: %uk skip [%s]", swps/1000u, 2*uint(Edges)*uint(NSwitch)/1000u, skip/1000u, ExeTm.GetStr()); if (ExeTm.GetSecs() > 2*3600) { printf(" *** Time limit!\n"); break; } // time limit 2 hours } } printf("\r total %uk switchings attempted, %uk skiped [%s]\n", 2*uint(Edges)*uint(NSwitch)/1000u, skip/1000u, ExeTm.GetStr()); for (int e = 0; e < EdgeSet.Len(); e++) { Graph.AddEdge(EdgeSet[e].Val1, EdgeSet[e].Val2); } return GraphPt; }
// RenumberNodes ... Renumber node ids in the subgraph to 0...N-1 PUNGraph GetSubGraph(const PUNGraph& Graph, const TIntV& NIdV, const bool& RenumberNodes) { //if (! RenumberNodes) { return TSnap::GetSubGraph(Graph, NIdV); } PUNGraph NewGraphPt = TUNGraph::New(); TUNGraph& NewGraph = *NewGraphPt; NewGraph.Reserve(NIdV.Len(), -1); TIntSet NIdSet(NIdV.Len()); for (int n = 0; n < NIdV.Len(); n++) { if (Graph->IsNode(NIdV[n])) { NIdSet.AddKey(NIdV[n]); if (! RenumberNodes) { NewGraph.AddNode(NIdV[n]); } else { NewGraph.AddNode(NIdSet.GetKeyId(NIdV[n])); } } } if (! RenumberNodes) { for (int n = 0; n < NIdSet.Len(); n++) { const int SrcNId = NIdSet[n]; const TUNGraph::TNodeI NI = Graph->GetNI(SrcNId); for (int edge = 0; edge < NI.GetOutDeg(); edge++) { const int OutNId = NI.GetOutNId(edge); if (NIdSet.IsKey(OutNId)) { NewGraph.AddEdge(SrcNId, OutNId); } } } } else { for (int n = 0; n < NIdSet.Len(); n++) { const int SrcNId = NIdSet[n]; const TUNGraph::TNodeI NI = Graph->GetNI(SrcNId); for (int edge = 0; edge < NI.GetOutDeg(); edge++) { const int OutNId = NI.GetOutNId(edge); if (NIdSet.IsKey(OutNId)) { NewGraph.AddEdge(NIdSet.GetKeyId(SrcNId), NIdSet.GetKeyId(OutNId)); } } } } return NewGraphPt; }
// simulate SI model cascade using infection probability Beta until the cascade stops or reaches size MxCascSz PNGraph RunSICascade2(PUNGraph G, const double& Beta, const int& MxCascSz, TIntH& NIdInfTmH) { PNGraph Casc = TNGraph::New(); const int StartNId = G->GetRndNId(); Casc->AddNode(StartNId); NIdInfTmH.AddDat(StartNId, NIdInfTmH.Len()); TIntQ Q; Q.Push(StartNId); while (! Q.Empty()) { const TUNGraph::TNodeI NI = G->GetNI(Q.Top()); Q.Pop(); for (int i = 0; i < NI.GetOutDeg(); i++) { if (TInt::Rnd.GetUniDev() < Beta && ! NIdInfTmH.IsKey(NI.GetOutNId(i))) { Casc->AddNode(NI.GetOutNId(i)); NIdInfTmH.AddDat(NI.GetOutNId(i), NIdInfTmH.Len()); Casc->AddEdge(NI.GetId(), NI.GetOutNId(i)); if (Casc->GetNodes() == MxCascSz) { return Casc; } Q.Push(NI.GetOutNId(i)); } } } return Casc; }
// simulate SI model cascade using infection probability Beta until the cascade reaches size CascSz PNGraph RunSICascade(PUNGraph G, const double& Beta, const int& CascSz, TIntH& NIdInfTmH) { PNGraph Casc = TNGraph::New(); const int StartId = G->GetRndNId(); Casc->AddNode(StartId); NIdInfTmH.AddDat(StartId, NIdInfTmH.Len()); for (int X = 0; X < 10*CascSz; X++) { TIntV CascNIdV; Casc->GetNIdV(CascNIdV); for (int n = 0; n < CascNIdV.Len(); n++) { const TUNGraph::TNodeI NI = G->GetNI(CascNIdV[n]); for (int i = 0; i < NI.GetOutDeg(); i++) { if (Casc->IsNode(NI.GetOutNId(i))) { continue; } if (TInt::Rnd.GetUniDev() < Beta) { Casc->AddNode(NI.GetOutNId(i)); NIdInfTmH.AddDat(NI.GetOutNId(i), NIdInfTmH.Len()); Casc->AddEdge(NI.GetId(), NI.GetOutNId(i)); if (Casc->GetNodes() == CascSz) { return Casc; } } } } } return Casc; }
// Loads a (directed, undirected or multi) graph from a text file InFNm with 1 node and all its edges in a single line. void IOConnListStr() { const int NNodes = 500; const int NEdges = 2000; const char *FName = "demo.graph.dat"; PUNGraph GOut, GIn; GOut = GenRndGnm<PUNGraph>(NNodes, NEdges); // Output nodes as random strings TIntStrH OutNIdStrH; TStrHash<TInt> OutStrNIdH; // Generate unique random strings for graph for (TUNGraph::TNodeI NI = GOut->BegNI(); NI < GOut->EndNI(); NI++) { TStr RandStr = ""; do { TInt RandLen = TInt::Rnd.GetUniDevInt(5, 10); for (int i = 0; i < RandLen; i++) { // TStr RandChar(TInt::Rnd.GetUniDevInt(33, 126)); TStr RandChar(TInt::Rnd.GetUniDevInt(97, 122)); RandStr += RandChar; } } while (OutStrNIdH.IsKey(RandStr) || RandStr[0] == '#'); OutNIdStrH.AddDat(NI.GetId(), RandStr); OutStrNIdH.AddDat(RandStr, NI.GetId()); } // Create graph file FILE *F = fopen(FName, "w"); for (TUNGraph::TNodeI NI = GOut->BegNI(); NI < GOut->EndNI(); NI++) { fprintf(F, "%s", OutNIdStrH[NI.GetId()].CStr()); for (int e = 0; e < NI.GetOutDeg(); e++) { fprintf(F, " %s", OutNIdStrH[NI.GetOutNId(e)].CStr()); } fprintf(F, "\n"); } fclose(F); TStrHash<TInt> InStrToNIdH; GIn = LoadConnListStr<PUNGraph>(FName, InStrToNIdH); PrintGStats("ConnListStr - Out", GOut); PrintGStats("ConnListStr - In", GIn); }
void GetEigenVectorCentr(const PUNGraph& Graph, TIntFltH& NIdEigenH, const double& Eps, const int& MaxIter) { const int NNodes = Graph->GetNodes(); NIdEigenH.Gen(NNodes); // initialize vector values for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { NIdEigenH.AddDat(NI.GetId(), 1.0 / NNodes); IAssert(NI.GetId() == NIdEigenH.GetKey(NIdEigenH.Len() - 1)); } TFltV TmpV(NNodes); for (int iter = 0; iter < MaxIter; iter++) { int j = 0; // add neighbor values for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++, j++) { TmpV[j] = 0; for (int e = 0; e < NI.GetOutDeg(); e++) { TmpV[j] += NIdEigenH.GetDat(NI.GetOutNId(e)); } } // normalize double sum = 0; for (int i = 0; i < TmpV.Len(); i++) { sum += (TmpV[i] * TmpV[i]); } sum = sqrt(sum); for (int i = 0; i < TmpV.Len(); i++) { TmpV[i] /= sum; } // compute difference double diff = 0.0; j = 0; for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++, j++) { diff += fabs(NIdEigenH.GetDat(NI.GetId()) - TmpV[j]); } // set new values j = 0; for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++, j++) { NIdEigenH.AddDat(NI.GetId(), TmpV[j]); } if (diff < Eps) { break; } } }
// network cascade: add spurious edges // for more details see "Correcting for Missing Data in Information Cascades" by E. Sadikov, M. Medina, J. Leskovec, H. Garcia-Molina. WSDM, 2011 PNGraph AddSpuriousEdges(const PUNGraph& Graph, const PNGraph& Casc, TIntH NIdTmH) { TIntPrV EdgeV; for (TNGraph::TNodeI NI = Casc->BegNI(); NI < Casc->EndNI(); NI++) { TUNGraph::TNodeI GNI = Graph->GetNI(NI.GetId()); const int Tm = NIdTmH.GetDat(NI.GetId()); for (int i=0,j=0; i < GNI.GetOutDeg(); i++) { const int Dst = GNI.GetOutNId(i); if (NIdTmH.IsKey(Dst) && Tm<NIdTmH.GetDat(Dst) && ! NI.IsNbhNId(Dst)) { EdgeV.Add(TIntPr(GNI.GetId(), Dst)); } } } PNGraph NetCasc = TNGraph::New(); *NetCasc = *Casc; for (int e = 0; e < EdgeV.Len(); e++) { NetCasc->AddEdge(EdgeV[e].Val1, EdgeV[e].Val2); } return NetCasc; }
void Init(const PUNGraph& Graph) { const double M = 0.5/Graph->GetEdges(); // 1/2m Q = 0.0; for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { CmtyIdUF.Add(NI.GetId()); const int OutDeg = NI.GetOutDeg(); if (OutDeg == 0) { continue; } TCmtyDat& Dat = CmtyQH.AddDat(NI.GetId(), TCmtyDat(M * OutDeg, OutDeg)); for (int e = 0; e < NI.GetOutDeg(); e++) { const int DstNId = NI.GetOutNId(e); const double DstMod = 2 * M * (1.0 - OutDeg * Graph->GetNI(DstNId).GetOutDeg() * M); Dat.AddQ(DstNId, DstMod); } Q += -1.0*TMath::Sqr(OutDeg*M); if (NI.GetId() < Dat.GetMxQNId()) { MxQHeap.Add(TFltIntIntTr(Dat.GetMxQ(), NI.GetId(), Dat.GetMxQNId())); } } MxQHeap.MakeHeap(); }
void GetBetweennessCentr(const PUNGraph& Graph, const TIntV& BtwNIdV, TIntFltH& NodeBtwH, const bool& DoNodeCent, TIntPrFltH& EdgeBtwH, const bool& DoEdgeCent) { if (DoNodeCent) { NodeBtwH.Clr(); } if (DoEdgeCent) { EdgeBtwH.Clr(); } const int nodes = Graph->GetNodes(); TIntS S(nodes); TIntQ Q(nodes); TIntIntVH P(nodes); // one vector for every node TIntFltH delta(nodes); TIntH sigma(nodes), d(nodes); // init for (TUNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { if (DoNodeCent) { NodeBtwH.AddDat(NI.GetId(), 0); } if (DoEdgeCent) { for (int e = 0; e < NI.GetOutDeg(); e++) { if (NI.GetId() < NI.GetOutNId(e)) { EdgeBtwH.AddDat(TIntPr(NI.GetId(), NI.GetOutNId(e)), 0); } } } sigma.AddDat(NI.GetId(), 0); d.AddDat(NI.GetId(), -1); P.AddDat(NI.GetId(), TIntV()); delta.AddDat(NI.GetId(), 0); } // calc betweeness for (int k = 0; k < BtwNIdV.Len(); k++) { const TUNGraph::TNodeI NI = Graph->GetNI(BtwNIdV[k]); // reset for (int i = 0; i < sigma.Len(); i++) { sigma[i] = 0; d[i] = -1; delta[i] = 0; P[i].Clr(false); } S.Clr(false); Q.Clr(false); sigma.AddDat(NI.GetId(), 1); d.AddDat(NI.GetId(), 0); Q.Push(NI.GetId()); while (!Q.Empty()) { const int v = Q.Top(); Q.Pop(); const TUNGraph::TNodeI NI2 = Graph->GetNI(v); S.Push(v); const int VDat = d.GetDat(v); for (int e = 0; e < NI2.GetOutDeg(); e++) { const int w = NI2.GetOutNId(e); if (d.GetDat(w) < 0) { // find w for the first time Q.Push(w); d.AddDat(w, VDat + 1); } //shortest path to w via v ? if (d.GetDat(w) == VDat + 1) { sigma.AddDat(w) += sigma.GetDat(v); P.GetDat(w).Add(v); } } } while (!S.Empty()) { const int w = S.Top(); const double SigmaW = sigma.GetDat(w); const double DeltaW = delta.GetDat(w); const TIntV NIdV = P.GetDat(w); S.Pop(); for (int i = 0; i < NIdV.Len(); i++) { const int nid = NIdV[i]; const double c = (sigma.GetDat(nid)*1.0 / SigmaW) * (1 + DeltaW); delta.AddDat(nid) += c; if (DoEdgeCent) { EdgeBtwH.AddDat(TIntPr(TMath::Mn(nid, w), TMath::Mx(nid, w))) += c; } } if (DoNodeCent && w != NI.GetId()) { NodeBtwH.AddDat(w) += delta.GetDat(w) / 2.0; } } } }
void GetMotifCount(const PUNGraph& G, const int MotifSize, TVec <int64> & MotifV, const int num) { if (MotifSize == 3) { MotifV = TVec <int64> (2); MotifV.PutAll(0); TSnap::GetTriads(G,MotifV[mtThreeClosed],MotifV[mtThreeOpen],num); } else { MotifV = TVec <int64> (6); MotifV.PutAll(0); TIntPrV V(G->GetEdges(), 0); for (TUNGraph::TEdgeI EI = G->BegEI(); EI < G->EndEI(); EI++) { V.Add(TIntPr(EI.GetSrcNId(), EI.GetDstNId())); } TRnd blargh; V.Shuffle(blargh); for (int z = 0; z < num; z++) { int SrcNId = V[z].Val1.Val, DstNId = V[z].Val2.Val; TUNGraph::TNodeI SrcNI = G->GetNI(SrcNId), DstNI = G->GetNI(DstNId); TIntV SrcV(SrcNI.GetOutDeg(),0), DstV(DstNI.GetOutDeg(),0), BothV(min(SrcNI.GetOutDeg(), DstNI.GetOutDeg()),0); SrcV.Clr(0,-1); DstV.Clr(0,-1); BothV.Clr(0,-1); //Grouping the vertices into sets for (int e = 0; e < SrcNI.GetOutDeg(); e++) { if (SrcNI.GetOutNId(e) == DstNId) continue; if (G->IsEdge(DstNId, SrcNI.GetOutNId(e)) ) { BothV.Add(SrcNI.GetOutNId(e)); } else { SrcV.Add(SrcNI.GetOutNId(e)); } } for (int e = 0; e < DstNI.GetOutDeg(); e++) { if (DstNI.GetOutNId(e) == SrcNId) continue; if (G->IsEdge(SrcNId, DstNI.GetOutNId(e)) == 0) { DstV.Add(DstNI.GetOutNId(e)); } } //Compute Motif 0 and 1 for (int i = 0; i < SrcV.Len(); i++) { for (int j = 0; j < DstV.Len(); j++) { if (G->IsEdge(SrcV[i], DstV[j]) ) { MotifV[mfFourSquare]++; } else MotifV[mfFourLine]++; } } //Compute Motif 2 and 3 for (int i = 0; i < SrcV.Len(); i++) { for (int j = i + 1; j < SrcV.Len(); j++) { if (G->IsEdge(SrcV[i], SrcV[j]) ) { MotifV[mfFourTriangleEdge]++; } else MotifV[mfFourStar]++; } } for (int i = 0; i < DstV.Len(); i++) { for (int j = i + 1; j < DstV.Len(); j++) { if (G->IsEdge(DstV[i], DstV[j]) ) { MotifV[mfFourTriangleEdge]++; } else MotifV[mfFourStar]++; } } //Compute Motif 4 and 5 for (int i = 0; i < BothV.Len(); i++) { for (int j = i + 1; j < BothV.Len(); j++) { if (G->IsEdge(BothV[i], BothV[j]) ) { MotifV[mfFourComplete]++; } else MotifV[mfFourSquareDiag]++; } } } MotifV[mfFourSquare] /= 4ll; MotifV[mfFourStar] /= 3ll; MotifV[mfFourComplete] /= 6ll; } }
/// save graph into a gexf file which Gephi can read void TAGMUtil::SaveGephi(const TStr& OutFNm, const PUNGraph& G, const TVec<TIntV>& CmtyVVAtr, const double MaxSz, const double MinSz, const TIntStrH& NIDNameH, const THash<TInt, TIntTr>& NIDColorH ) { THash<TInt,TIntV> NIDComVHAtr; TAGMUtil::GetNodeMembership(NIDComVHAtr, CmtyVVAtr); FILE* F = fopen(OutFNm.CStr(), "wt"); fprintf(F, "<?xml version='1.0' encoding='UTF-8'?>\n"); fprintf(F, "<gexf xmlns='http://www.gexf.net/1.2draft' xmlns:viz='http://www.gexf.net/1.1draft/viz' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd' version='1.2'>\n"); fprintf(F, "\t<graph mode='static' defaultedgetype='undirected'>\n"); if (CmtyVVAtr.Len() > 0) { fprintf(F, "\t<attributes class='node'>\n"); for (int c = 0; c < CmtyVVAtr.Len(); c++) { fprintf(F, "\t\t<attribute id='%d' title='c%d' type='boolean'>", c, c); fprintf(F, "\t\t<default>false</default>\n"); fprintf(F, "\t\t</attribute>\n"); } fprintf(F, "\t</attributes>\n"); } fprintf(F, "\t\t<nodes>\n"); for (TUNGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { int NID = NI.GetId(); TStr Label = NIDNameH.IsKey(NID)? NIDNameH.GetDat(NID): ""; Label.ChangeChAll('<', ' '); Label.ChangeChAll('>', ' '); Label.ChangeChAll('&', ' '); Label.ChangeChAll('\'', ' '); TIntTr Color = NIDColorH.IsKey(NID)? NIDColorH.GetDat(NID) : TIntTr(120, 120, 120); double Size = MinSz; double SizeStep = (MaxSz - MinSz) / (double) CmtyVVAtr.Len(); if (NIDComVHAtr.IsKey(NID)) { Size = MinSz + SizeStep * (double) NIDComVHAtr.GetDat(NID).Len(); } double Alpha = 1.0; fprintf(F, "\t\t\t<node id='%d' label='%s'>\n", NID, Label.CStr()); fprintf(F, "\t\t\t\t<viz:color r='%d' g='%d' b='%d' a='%.1f'/>\n", Color.Val1.Val, Color.Val2.Val, Color.Val3.Val, Alpha); fprintf(F, "\t\t\t\t<viz:size value='%.3f'/>\n", Size); //specify attributes if (NIDComVHAtr.IsKey(NID)) { fprintf(F, "\t\t\t\t<attvalues>\n"); for (int c = 0; c < NIDComVHAtr.GetDat(NID).Len(); c++) { int CID = NIDComVHAtr.GetDat(NID)[c]; fprintf(F, "\t\t\t\t\t<attvalue for='%d' value='true'/>\n", CID); } fprintf(F, "\t\t\t\t</attvalues>\n"); } fprintf(F, "\t\t\t</node>\n"); } fprintf(F, "\t\t</nodes>\n"); //plot edges int EID = 0; fprintf(F, "\t\t<edges>\n"); for (TUNGraph::TNodeI NI = G->BegNI(); NI < G->EndNI(); NI++) { for (int e = 0; e < NI.GetOutDeg(); e++) { if (NI.GetId() > NI.GetOutNId(e)) { continue; } fprintf(F, "\t\t\t<edge id='%d' source='%d' target='%d'/>\n", EID++, NI.GetId(), NI.GetOutNId(e)); } } fprintf(F, "\t\t</edges>\n"); fprintf(F, "\t</graph>\n"); fprintf(F, "</gexf>\n"); fclose(F); }