SNAP Library 2.2, User Reference  2014-03-11 19:15:55
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
agmdirected.h
Go to the documentation of this file.
00001 #ifndef yanglib_agmdirected_h
00002 #define yanglib_agmdirected_h
00003 #include "Snap.h"
00004 #include "agm.h"
00005 #include "agmfast.h"
00006 
00007 class TCoda { //sparse AGM-fast with coordinate ascent for directed affiliation
00008 private:
00009   PNGraph G; //graph to fit
00010   TVec<TIntFltH> F; // outdegree membership for each user (Size: Nodes * Coms)
00011   TVec<TIntFltH> H; // in-degree membership for each user (Size: Nodes * Coms) A ~ F * H'
00012   TRnd Rnd; // random number generator
00013   TIntV NIDV; // original node ID vector
00014   TFlt RegCoef; //Regularization coefficient when we fit for P_c +: L1, -: L2
00015   TFltV SumFV; // sum_u F_uc for each community c. Needed for efficient calculation
00016   TFltV SumHV; // sum_u H_uc for each community c. Needed for efficient calculation
00017   TBool NodesOk; // Node ID is from 0 ~ N-1
00018   TInt NumComs; // number of communities
00019   TVec<TIntSet> HOVIDSV; //NID pairs to hold out for cross validation
00020 public:
00021   TFlt MinVal; // minimum value of F (0)
00022   TFlt MaxVal; // maximum value of F (for numerical reason)
00023   TFlt NegWgt; // weight of negative example (a pair of nodes without an edge)
00024   TFlt PNoCom; // base probability \varepsilon (edge probability between a pair of nodes sharing no community
00025   TBool DoParallel; // whether to use parallelism for computation
00026 
00027   TCoda(const PNGraph& GraphPt, const int& InitComs, const int RndSeed = 0): Rnd(RndSeed), RegCoef(0), 
00028     NodesOk(true), MinVal(0.0), MaxVal(1000.0), NegWgt(1.0) { SetGraph(GraphPt); RandomInit(InitComs); }
00029   TCoda() { G = TNGraph::New(); }
00030   void SetGraph(const PNGraph& GraphPt);
00031   PNGraph GetGraph() { return G; }
00032   PNGraph GetGraphRawNID();
00033   void SetRegCoef(const double _RegCoef) { RegCoef = _RegCoef; }
00034   double GetRegCoef() { return RegCoef; }
00035   void RandomInit(const int InitComs);
00036   int GetNumComs() { return NumComs.Val; }
00037   void NeighborComInit(const int InitComs);
00038   void NeighborComInit(TFltIntPrV& NIdPhiV, const int InitComs);
00039   void SetCmtyVV(const TVec<TIntV>& CmtyVVOut, const TVec<TIntV>& CmtyVVIn);
00040   double Likelihood(const bool DoParallel = false);
00041   double LikelihoodForNode(const bool IsRow, const int UID);
00042   double LikelihoodForNode(const bool IsRow, const int UID, const TIntFltH& FU);
00043   void GetNonEdgePairScores(TFltIntIntTrV& ScoreV);
00044   void GetNIDValH(TIntFltH& NIdValInOutH, TIntFltH& NIdValOutH, TIntFltH& NIdValInH, const int CID, const double Thres);
00045   void DumpMemberships(const TStr& OutFNm, const TStrHash<TInt>& NodeNameH) { DumpMemberships(OutFNm, NodeNameH, sqrt(PNoCom)); }
00046   void DumpMemberships(const TStr& OutFNm, const TStrHash<TInt>& NodeNameH, const double Thres);
00047   void GetCmtyS(TIntSet& CmtySOut, TIntSet& CmtySIn, const int CID, const double Thres);
00048   void DumpMemberships(const TStr& OutFNm, const double Thres);
00049   void DumpMemberships(const TStr& OutFNm) { DumpMemberships(OutFNm, sqrt(PNoCom)); }
00050   void GetCommunity(TIntV& CmtyVIn, TIntV& CmtyVOut, const int CID) { GetCommunity(CmtyVIn, CmtyVOut, CID, sqrt(PNoCom)); }
00051   void GetCommunity(TIntV& CmtyVIn, TIntV& CmtyVOut, const int CID, const double Thres);
00052   void GetTopCIDs(TIntV& CIdV, const int TopK, const int IsAverage = 1, const int MinSz = 1);
00053   void GradientForNode(const bool IsRow, const int UID, TIntFltH& GradU, const TIntSet& CIDSet);
00054   void SetHoldOut(const double HOFrac) { TVec<TIntSet> HoldOut; TAGMFastUtil::GenHoldOutPairs(G, HoldOut, HOFrac, Rnd); HOVIDSV = HoldOut; }
00055   //double LikelihoodForRow(const int UID);
00056   //double LikelihoodForRow(const int UID, const TIntFltH& FU);
00057   //double LikelihoodForCol(const int VID);
00058   //double LikelihoodForCol(const int VID, const TIntFltH& HV);
00059   //void GradientForRow(const int UID, TIntFltH& GradU, const TIntSet& CIDSet);
00060   void GetCmtyVV(TVec<TIntV>& CmtyVVOut, TVec<TIntV>& CmtyVVIn, const int MinSz = 3);
00061   void GetCmtyVV(TVec<TIntV>& CmtyVVOut, TVec<TIntV>& CmtyVVIn, const double ThresOut, const double ThresIn, const int MinSz = 3);
00062   void GetCmtyVV(const bool IsOut, TVec<TIntV>& CmtyVV);
00063   void GetCmtyVV(const bool IsOut, TVec<TIntV>& CmtyVV, const double Thres, const int MinSz = 3);
00064   void GetCmtyVVUnSorted(const bool IsOut, TVec<TIntV>& CmtyVV, const double Thres, const int MinSz = 3);
00065   void GetCmtyVVUnSorted(TVec<TIntV>& CmtyVVOut, TVec<TIntV>& CmtyVVIn);
00066   //void GetCmtyVVIn(TVec<TIntV>& CmtyVV);
00067   //void GetCmtyVVIn(TVec<TIntV>& CmtyVV, const double Thres, const int MinSz = 3);
00068   int FindComsByCV(TIntV& ComsV, const double HOFrac = 0.2, const int NumThreads = 20, const TStr PlotLFNm = TStr(), const int EdgesForCV = 100, const double StepAlpha = 0.3, const double StepBeta = 0.1);
00069   int FindComsByCV(const int NumThreads, const int MaxComs, const int MinComs, const int DivComs, const TStr OutFNm, const int EdgesForCV = 100, const double StepAlpha = 0.3, const double StepBeta = 0.3);
00070   double LikelihoodHoldOut(const bool DoParallel = false);
00071   double GetStepSizeByLineSearch(const bool IsRow, const int UID, const TIntFltH& DeltaV, const TIntFltH& GradV, const double& Alpha, const double& Beta, const int MaxIter = 10);
00072   int MLEGradAscent(const double& Thres, const int& MaxIter, const TStr PlotNm, const double StepAlpha = 0.3, const double StepBeta = 0.1);
00073   int MLEGradAscentParallel(const double& Thres, const int& MaxIter, const int ChunkNum, const int ChunkSize, const TStr PlotNm, const double StepAlpha = 0.3, const double StepBeta = 0.1);
00074   int MLEGradAscentParallel(const double& Thres, const int& MaxIter, const int ChunkNum, const TStr PlotNm = TStr(), const double StepAlpha = 0.3, const double StepBeta = 0.1) {
00075     int ChunkSize = G->GetNodes() / 10 / ChunkNum;
00076     if (ChunkSize == 0) { ChunkSize = 1; }
00077     return MLEGradAscentParallel(Thres, MaxIter, ChunkNum, ChunkSize, PlotNm, StepAlpha, StepBeta);
00078   }
00079   //int MLENewton(const double& Thres, const int& MaxIter, const TStr PlotNm = TStr());
00080   //double GradientForOneVar(const TFltV& AlphaKV, const int UID, const int CID, const double& Val);
00081   //double HessianForOneVar(const TFltV& AlphaKV, const int UID, const int CID, const double& Val);
00082   //double LikelihoodForOneVar(const TFltV& AlphaKV, const int UID, const int CID, const double& Val);
00083   //double FindOptimalThres(const TVec<TIntV>& TrueCmtyVV, TVec<TIntV>& CmtyVV);
00084   void Save(TSOut& SOut);
00085   void Load(TSIn& SIn, const int& RndSeed = 0);
00086   TFlt& GetSumVal(const bool IsOut, const int CID) { 
00087     if (IsOut) {
00088       return SumFV[CID];
00089     } else {
00090       return SumHV[CID];
00091     }
00092   }
00093   double inline GetCom(const bool IsOut, const int& NID, const int& CID) {
00094     if (IsOut) {
00095       return GetComOut(NID, CID);
00096     } else {
00097       return GetComIn(NID, CID);
00098     }
00099   }
00100   double inline GetComOut(const int& NID, const int& CID) {
00101     if (F[NID].IsKey(CID)) {
00102       return F[NID].GetDat(CID);
00103     } else {
00104       return 0.0;
00105     }
00106   }
00107   double inline GetComIn(const int& NID, const int& CID) {
00108     if (H[NID].IsKey(CID)) {
00109       return H[NID].GetDat(CID);
00110     } else {
00111       return 0.0;
00112     }
00113   }
00114   void inline AddCom(const bool IsOut, const int& NID, const int& CID, const double& Val) {
00115     if (IsOut) {
00116       AddComOut(NID, CID, Val);
00117     } else {
00118       AddComIn(NID, CID, Val);
00119     }
00120   }
00121   void inline AddComOut(const int& NID, const int& CID, const double& Val) {
00122     if (F[NID].IsKey(CID)) {
00123       SumFV[CID] -= F[NID].GetDat(CID);
00124     }
00125     F[NID].AddDat(CID) = Val;
00126     SumFV[CID] += Val;
00127   }
00128   void inline AddComIn(const int& NID, const int& CID, const double& Val) {
00129     if (H[NID].IsKey(CID)) {
00130       SumHV[CID] -= H[NID].GetDat(CID);
00131     }
00132     H[NID].AddDat(CID) = Val;
00133     SumHV[CID] += Val;
00134   }
00135   void inline DelCom(const bool IsOut, const int& NID, const int& CID) {
00136     if (IsOut) {
00137       return DelComOut(NID, CID);
00138     } else {
00139       return DelComIn(NID, CID);
00140     }
00141   }
00142   void inline DelComOut(const int& NID, const int& CID) {
00143     if (F[NID].IsKey(CID)) {
00144       SumFV[CID] -= F[NID].GetDat(CID);
00145       F[NID].DelKey(CID);
00146     }
00147   }
00148   void inline DelComIn(const int& NID, const int& CID) {
00149     if (H[NID].IsKey(CID)) {
00150       SumHV[CID] -= H[NID].GetDat(CID);
00151       H[NID].DelKey(CID);
00152     }
00153   }
00154   double inline DotProduct(const TIntFltH& UV, const TIntFltH& VV) {
00155     double DP = 0;
00156     if (UV.Len() > VV.Len()) {
00157       for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) {
00158         if (VV.IsKey(HI.GetKey())) { 
00159           DP += VV.GetDat(HI.GetKey()) * HI.GetDat(); 
00160         }
00161       }
00162     } else {
00163       for (TIntFltH::TIter HI = VV.BegI(); HI < VV.EndI(); HI++) {
00164         if (UV.IsKey(HI.GetKey())) { 
00165           DP += UV.GetDat(HI.GetKey()) * HI.GetDat(); 
00166         }
00167       }
00168     }
00169     return DP;
00170   }
00171   double inline DotProductUtoV(const int& UID, const int& VID) {
00172     return DotProduct(F[UID], H[VID]);
00173   }
00174   double inline Prediction(const TIntFltH& FU, const TIntFltH& HV) {
00175     double DP = log (1.0 / (1.0 - PNoCom)) + DotProduct(FU, HV);
00176     IAssertR(DP > 0.0, TStr::Fmt("DP: %f", DP));
00177     return exp(- DP);
00178   }
00179   double inline Prediction(const int& UID, const int& VID) {
00180     return Prediction(F[UID], H[VID]);
00181   }
00182   double inline Sum(const TIntFltH& UV) {
00183     double N = 0.0;
00184     for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) {
00185       N += HI.GetDat();
00186     }
00187     return N;
00188   }
00189   double inline Norm2(const TIntFltH& UV) {
00190     double N = 0.0;
00191     for (TIntFltH::TIter HI = UV.BegI(); HI < UV.EndI(); HI++) {
00192       N += HI.GetDat() * HI.GetDat();
00193     }
00194     return N;
00195   }
00196 };
00197 
00198 class TCodaAnalyzer {
00199 public:
00200   PNGraph G;
00201   TVec<TIntFltH> InCmtyValHV;
00202   TVec<TIntFltH> OutCmtyValHV;
00203   TVec<TIntFltH> InOutCmtyValHV;
00204   TCodaAnalyzer() { G = TNGraph::New(); }
00205   TCodaAnalyzer(TCoda& Coda, const double MemThres = -1.0) {
00206     G = Coda.GetGraphRawNID();
00207     printf("graph copied (%d nodes %d edges)\n", G->GetNodes(), G->GetEdges());
00208     TIntV CIdV;
00209     Coda.GetTopCIDs(CIdV, Coda.GetNumComs());
00210     double Delta = MemThres == -1.0 ? sqrt(Coda.PNoCom): MemThres;
00211     for (int c = 0; c < CIdV.Len(); c++) {
00212       int CID = CIdV[c];
00213       TIntFltH InMemH, OutMemH, InOutMemH;
00214       Coda.GetNIDValH(InOutMemH, OutMemH, InMemH, CID, Delta);
00215       InCmtyValHV.Add(InMemH);
00216       OutCmtyValHV.Add(OutMemH);
00217       InOutCmtyValHV.Add(InOutMemH);
00218     }
00219     printf("Communities copied (%d communities)\n", InCmtyValHV.Len());
00220   }
00221   void GetAllCmtyVV(TVec<TIntV>& CmtyVV, const int MinSz) {
00222     for (int c = 0; c < InCmtyValHV.Len(); c++) {
00223       TIntV CmtyVIn, CmtyVOut, CmtyVInOut;
00224       if (InCmtyValHV[c].Len() < MinSz || OutCmtyValHV[c].Len() < MinSz) { continue; }
00225       InOutCmtyValHV[c].GetKeyV(CmtyVInOut);
00226       InCmtyValHV[c].GetKeyV(CmtyVIn);
00227       OutCmtyValHV[c].GetKeyV(CmtyVOut);
00228       CmtyVV.Add(CmtyVInOut);
00229       CmtyVV.Add(CmtyVOut);
00230       CmtyVV.Add(CmtyVIn);
00231     }
00232   }
00233 
00234   double GetFrac2Mode(const double Thres2Mode = 0.2, const int MinSzEach = 2) {
00235     int Cnt2Mode = 0;
00236     int CntAll = 0;
00237     for (int c = 0; c < InCmtyValHV.Len(); c++) {
00238       double Jacc = (double) InOutCmtyValHV[c].Len() / (double) (InCmtyValHV[c].Len() + OutCmtyValHV[c].Len() - InOutCmtyValHV[c].Len());
00239       if (InCmtyValHV[c].Len() < MinSzEach || OutCmtyValHV[c].Len() < MinSzEach) { continue; }
00240       if (Jacc <= Thres2Mode) { Cnt2Mode++; }
00241       CntAll++;
00242     }
00243     return (double) Cnt2Mode / (double) CntAll;
00244   }
00245 
00246   void Summary(const int TopK = 10, const double Thres2Mode = 0.2) {
00247     int Cnt2Mode = 0;
00248     double SumJacc = 0.0;
00249     for (int c = 0; c < InCmtyValHV.Len(); c++) {
00250       double Jacc = (double) InOutCmtyValHV[c].Len() / (double) (InCmtyValHV[c].Len() + OutCmtyValHV[c].Len() - InOutCmtyValHV[c].Len());
00251       if (Jacc <= Thres2Mode) { Cnt2Mode++; }
00252       SumJacc += Jacc;
00253       if (c < TopK) {
00254         printf("Cmty %d: InOut: %d, In:%d, Out:%d, Jacc;%.3f\n", c, InCmtyValHV[c].Len(), InCmtyValHV[c].Len(), OutCmtyValHV[c].Len(), Jacc);
00255       }
00256     }
00257     double AvgJacc = SumJacc / (double) InCmtyValHV.Len();
00258     printf("Average jaccard similarity = %.3f. (%d / %d communities are 2-mode)\n", AvgJacc, Cnt2Mode, InCmtyValHV.Len());
00259   }
00260   int GetNumComs() { return InCmtyValHV.Len(); }
00262 
00263   void GetCmtyVAll(TIntV& CmtyVAll, const int CID) {
00264     TIntV CmtyVIn, CmtyVOut;
00265     InCmtyValHV[CID].GetKeyV(CmtyVIn);
00266     OutCmtyValHV[CID].GetKeyV(CmtyVOut);
00267     CmtyVIn.Sort();
00268     CmtyVOut.Sort();
00269     CmtyVAll.Gen(CmtyVIn.Len() + CmtyVOut.Len(), 0);
00270     CmtyVIn.Union(CmtyVOut, CmtyVAll);
00271   }
00272 
00273   PNGraph Net2ModeCommunities(const double MaxJac, const double JacEdge, const bool GetWcc = true) {
00274     //if In(A) is similar to Out(B), create an edge A->B between 2 communities A, B
00275     int Coms = InCmtyValHV.Len();
00276     PNGraph ComG = TNGraph::New(Coms, -1);
00277     for (int c = 0; c < InCmtyValHV.Len(); c++) {
00278       double Jacc = (double) InOutCmtyValHV[c].Len() / (double) (InCmtyValHV[c].Len() + OutCmtyValHV[c].Len() - InOutCmtyValHV[c].Len());
00279       if (Jacc > MaxJac) { continue; }
00280       ComG->AddNode(c);
00281     }
00282     TVec<TIntSet> CmtySVIn, CmtySVOut;
00283     for (int c = 0; c < Coms; c++) {
00284       TIntV CmtyVIn, CmtyVOut;
00285       InCmtyValHV[c].GetKeyV(CmtyVIn);
00286       OutCmtyValHV[c].GetKeyV(CmtyVOut);
00287       TIntSet CmtySIn(CmtyVIn), CmtySOut(CmtyVOut);
00288       CmtySVIn.Add(CmtySIn);
00289       CmtySVOut.Add(CmtySOut);
00290     }
00291     for (int c1 = 0; c1 < Coms; c1++) {
00292       if (! ComG->IsNode(c1)) { continue; }
00293       for (int c2 = 0; c2 < Coms; c2++) {
00294         if (! ComG->IsNode(c2)) { continue; }
00295         int IntC1C2 = TAGMUtil::Intersection(CmtySVIn[c1], CmtySVOut[c2]);
00296         double Jac = (double) IntC1C2 / (CmtySVIn[c1].Len() + CmtySVOut[c2].Len() - IntC1C2);
00297         if (Jac >= JacEdge) {
00298           ComG->AddEdge(c1, c2);
00299         }
00300       }
00301     }
00302     //PNGraph Wcc = TSnap::GetMxWcc(ComG);
00303     TIntV NIDV;
00304     ComG->GetNIdV(NIDV);
00305     for (int u = 0; u < NIDV.Len(); u++) {
00306       int NID = NIDV[u];
00307       TNGraph::TNodeI NI = ComG->GetNI(NID);
00308       if (NI.GetDeg() == 0) { ComG->DelNode(NID); }
00309       if (NI.GetInDeg() == 1 && NI.GetOutDeg() == 1 && NI.GetOutNId(0) == NID) { ComG->DelNode(NID); }
00310     }
00311     printf("Community graph made (Jaccard similarity for edges: %f, %d nodes, %d edges)\n", JacEdge, ComG->GetNodes(), ComG->GetEdges());
00312     return ComG;
00313   }
00314 
00315   // RS:2014/03/11 default parameter values do not compile on OS X with g++-4.2
00316   //void Dump2ModeCommunities(const TStr& OutFNm, const double MaxJac, const TIntStrH& NIDNameH =  THash<TInt, TStr>()) {
00317   void Dump2ModeCommunities(const TStr& OutFNm, const double MaxJac, const TIntStrH& NIDNameH) {
00318     FILE* F = fopen(OutFNm.CStr(), "wt");
00319     for (int c = 0; c < InCmtyValHV.Len(); c++) {
00320       double Jacc = (double) InOutCmtyValHV[c].Len() / (double) (InCmtyValHV[c].Len() + OutCmtyValHV[c].Len() - InOutCmtyValHV[c].Len());
00321       if (Jacc > MaxJac) { continue; }
00322       TIntV CmtyVIn, CmtyVOut, CmtyVAll;
00323       InCmtyValHV[c].GetKeyV(CmtyVIn);
00324       OutCmtyValHV[c].GetKeyV(CmtyVOut);
00325       GetCmtyVAll(CmtyVAll, c);
00326       //adjust for the nodes who belong to both cmtyvin and cmtyvout
00327       for (int u = 0; u < InOutCmtyValHV[c].Len(); u++) {
00328         int UID = InOutCmtyValHV[c].GetKey(u);
00329         if (CmtyVIn.Len() >= CmtyVOut.Len()) {
00330           CmtyVIn.DelIfIn(UID); 
00331         } else {
00332           CmtyVOut.DelIfIn(UID); 
00333         }
00334       }
00335       if (CmtyVAll.Len() == 0) { continue; }
00336       fprintf(F, "Com %d\n", c);
00337       for (int u = 0; u < CmtyVOut.Len(); u++) {
00338         int NID = CmtyVOut[u];
00339         TStr Label = NIDNameH.IsKey(NID)? NIDNameH.GetDat(NID): TStr::Fmt("Concept %d", NID);
00340         fprintf(F, "%s:%f\n", Label.CStr(), OutCmtyValHV[c].GetDat(NID).Val);
00341       }
00342       fprintf(F, "||==>||\n");
00343       for (int u = 0; u < CmtyVIn.Len(); u++) {
00344         int NID = CmtyVIn[u];
00345         TStr Label = NIDNameH.IsKey(NID)? NIDNameH.GetDat(NID): TStr::Fmt("Concept %d", NID);
00346         fprintf(F, "%s:%f\n", Label.CStr(), InCmtyValHV[c].GetDat(NID).Val);
00347       }
00348       fprintf(F, "\n");
00349     }
00350     fclose(F);
00351   }
00352 
00353   // RS:2014/03/11 default parameter values do not compile on OS X with g++-4.2
00354   //void Draw2ModeCommunity(const int CID, const TStr& OutFNm, const TIntStrH& NIDNameH =  THash<TInt, TStr>(), const THash<TInt, TIntTr>& NIDColorH = THash<TInt, TIntTr>() ) {
00355   void Draw2ModeCommunity(const int CID, const TStr& OutFNm, const TIntStrH& NIDNameH, const THash<TInt, TIntTr>& NIDColorH) {
00356     TIntV CmtyVIn, CmtyVOut, CmtyVAll;
00357     InCmtyValHV[CID].GetKeyV(CmtyVIn);
00358     OutCmtyValHV[CID].GetKeyV(CmtyVOut);
00359     GetCmtyVAll(CmtyVAll, CID);
00360 
00361     //adjust for the nodes who belong to both cmtyvin and cmtyvout
00362     for (int u = 0; u < InOutCmtyValHV[CID].Len(); u++) {
00363       int UID = InOutCmtyValHV[CID].GetKey(u);
00364       if (CmtyVIn.Len() >= CmtyVOut.Len()) {
00365         CmtyVIn.DelIfIn(UID); 
00366       } else {
00367         CmtyVOut.DelIfIn(UID); 
00368       }
00369     }
00370 
00371     PNGraph SG = TSnap::GetSubGraph(G, CmtyVAll);
00373     if (CmtyVAll.Len() == 0) { return; }
00374     double OXMin = 0.1, YMin = 0.1, OXMax = 2500.00, YMax = 1000.0, IXMin = 0.1, IXMax = 2500.00;
00375     double OStep = (OXMax - OXMin) / (double) CmtyVOut.Len(), IStep = (IXMax - IXMin) / (double) CmtyVIn.Len();
00376 
00377     FILE* F = fopen(OutFNm.CStr(), "wt");
00378     fprintf(F, "<?xml version='1.0' encoding='UTF-8'?>\n");
00379     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");
00380     fprintf(F, "\t<graph mode='static' defaultedgetype='directed'>\n");
00381     fprintf(F, "\t\t<nodes>\n");
00382     for (int c = 0; c < CmtyVOut.Len(); c++) {
00383       int NID = CmtyVOut[c];
00384       double XPos = c * OStep + OXMin;
00385       TStr Label = NIDNameH.IsKey(NID)? NIDNameH.GetDat(NID): "";
00386       Label.ChangeChAll('<', ' ');
00387       Label.ChangeChAll('>', ' ');
00388       Label.ChangeChAll('&', ' ');
00389       Label.ChangeChAll('\'', ' ');
00390       TIntTr Color = NIDColorH.IsKey(NID)? NIDColorH.GetDat(NID) : TIntTr(120, 120, 120);
00391       fprintf(F, "\t\t\t<node id='%d' label='%s'>\n", NID, Label.CStr());
00392       fprintf(F, "\t\t\t\t<viz:color r='%d' g='%d' b='%d'/>\n", Color.Val1.Val, Color.Val2.Val, Color.Val3.Val);
00393       fprintf(F, "\t\t\t\t<viz:size value='4.0'/>\n");
00394       fprintf(F, "\t\t\t\t<viz:shape value='square'/>\n");
00395       fprintf(F, "\t\t\t\t<viz:position x='%f' y='%f' z='0.0'/>\n", XPos, YMax); 
00396       fprintf(F, "\t\t\t</node>\n");
00397     }
00398 
00399     for (int u = 0; u < CmtyVIn.Len(); u++) {
00400       int NID = CmtyVIn[u];
00401       TStr Label = NIDNameH.IsKey(NID)? NIDNameH.GetDat(NID): "";
00402       Label.ChangeChAll('<', ' ');
00403       Label.ChangeChAll('>', ' ');
00404       Label.ChangeChAll('&', ' ');
00405       Label.ChangeChAll('\'', ' ');
00406       double XPos = IXMin + u * IStep;
00407       TIntTr Color = NIDColorH.IsKey(NID)? NIDColorH.GetDat(NID) : TIntTr(120, 120, 120);
00408       double Alpha = 1.0;
00409       fprintf(F, "\t\t\t<node id='%d' label='%s'>\n", NID, Label.CStr());
00410       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);
00411       fprintf(F, "\t\t\t\t<viz:size value='4.0'/>\n");
00412       fprintf(F, "\t\t\t\t<viz:shape value='square'/>\n");
00413       fprintf(F, "\t\t\t\t<viz:position x='%f' y='%f' z='0.0'/>\n", XPos, YMin); 
00414       fprintf(F, "\t\t\t</node>\n");
00415     }
00416     fprintf(F, "\t\t</nodes>\n");
00417     //plot edges
00418     int EID = 0;
00419     fprintf(F, "\t\t<edges>\n");
00420     for (TNGraph::TNodeI NI = SG->BegNI(); NI < SG->EndNI(); NI++) {
00421       if (NI.GetOutDeg() == 0 && NI.GetInDeg() == 0  ) { continue; }
00422       for (int e = 0; e < NI.GetOutDeg(); e++) {
00423         fprintf(F, "\t\t\t<edge id='%d' source='%d' target='%d'/>\n", EID++, NI.GetId(), NI.GetOutNId(e));
00424       }
00425     }
00426     fprintf(F, "\t\t</edges>\n");
00427     fprintf(F, "\t</graph>\n");
00428     fprintf(F, "</gexf>\n");
00429     fclose(F);
00430   }
00431 
00432 };
00433 
00434 #endif