SNAP Library, Developer Reference  2012-10-15 15:06:59
SNAP, a general purpose network analysis and graph mining library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
kronecker.cpp
Go to the documentation of this file.
00001 #include "stdafx.h"
00002 #include "kronecker.h"
00003 
00005 // Kronecker Graphs
00006 const double TKronMtx::NInf = -DBL_MAX;
00007 TRnd TKronMtx::Rnd = TRnd(0);
00008 
00009 TKronMtx::TKronMtx(const TFltV& SeedMatrix) : SeedMtx(SeedMatrix) {
00010   MtxDim = (int) sqrt((double)SeedMatrix.Len());
00011   IAssert(MtxDim*MtxDim == SeedMtx.Len());
00012 }
00013 
00014 void TKronMtx::SaveTxt(const TStr& OutFNm) const {
00015   FILE *F = fopen(OutFNm.CStr(), "wt");
00016   for (int i = 0; i < GetDim(); i++) {
00017     for (int j = 0; j < GetDim(); j++) {
00018       if (j > 0) fprintf(F, "\t");
00019       fprintf(F, "%f", At(i,j)); }
00020     fprintf(F, "\n");
00021   }
00022   fclose(F);
00023 }
00024 
00025 TKronMtx& TKronMtx::operator = (const TKronMtx& Kronecker) {
00026   if (this != &Kronecker){
00027     MtxDim=Kronecker.MtxDim;
00028     SeedMtx=Kronecker.SeedMtx;
00029   }
00030   return *this;
00031 }
00032 
00033 bool TKronMtx::IsProbMtx() const {
00034   for (int i = 0; i < Len(); i++) {
00035     if (At(i) < 0.0 || At(i) > 1.0) return false;
00036   }
00037   return true;
00038 }
00039 
00040 void TKronMtx::SetRndMtx(const int& PrmMtxDim, const double& MinProb) {
00041   MtxDim = PrmMtxDim;
00042   SeedMtx.Gen(MtxDim*MtxDim);
00043   for (int p = 0; p < SeedMtx.Len(); p++) {
00044     do {
00045       SeedMtx[p] = TKronMtx::Rnd.GetUniDev();
00046     } while (SeedMtx[p] < MinProb);
00047   }
00048 }
00049 
00050 void TKronMtx::SetEpsMtx(const double& Eps1, const double& Eps0, const int& Eps1Val, const int& Eps0Val) {
00051   for (int i = 0; i < Len(); i++) {
00052     double& Val = At(i);
00053     if (Val == Eps1Val) Val = double(Eps1);
00054     else if (Val == Eps0Val) Val = double(Eps0);
00055   }
00056 }
00057 
00058 // scales parameter values to allow Edges
00059 void TKronMtx::SetForEdges(const int& Nodes, const int& Edges) {
00060   const int KronIter = GetKronIter(Nodes);
00061   const double EZero = pow((double) Edges, 1.0/double(KronIter));
00062   const double Factor = EZero / GetMtxSum();
00063   for (int i = 0; i < Len(); i++) {
00064     At(i) *= Factor;
00065     if (At(i) > 1) { At(i) = 1; }
00066   }
00067 }
00068 
00069 void TKronMtx::AddRndNoise(const double& SDev) {
00070   Dump("before");
00071   double NewVal;
00072   int c =0;
00073   for (int i = 0; i < Len(); i++) {
00074     for(c = 0; ((NewVal = At(i)*Rnd.GetNrmDev(1, SDev, 0.8, 1.2)) < 0.01 || NewVal>0.99) && c <1000; c++) { }
00075     if (c < 999) { At(i) = NewVal; } else { printf("XXXXX\n"); }
00076   }
00077   Dump("after");
00078 }
00079 
00080 TStr TKronMtx::GetMtxStr() const {
00081   TChA ChA("[");
00082   for (int i = 0; i < Len(); i++) {
00083     ChA += TStr::Fmt("%g", At(i));
00084     if ((i+1)%GetDim()==0 && (i+1<Len())) { ChA += "; "; }
00085     else if (i+1<Len()) { ChA += ", "; }
00086   }
00087   ChA += "]";
00088   return TStr(ChA);
00089 }
00090 
00091 void TKronMtx::ToOneMinusMtx() {
00092   for (int i = 0; i < Len(); i++) {
00093     IAssert(At(i) >= 0.0 && At(i) <= 1.0);
00094     At(i) = 1.0 - At(i);
00095   }
00096 }
00097 
00098 void TKronMtx::GetLLMtx(TKronMtx& LLMtx) {
00099   LLMtx.GenMtx(MtxDim);
00100   for (int i = 0; i < Len(); i++) {
00101     if (At(i) != 0.0) { LLMtx.At(i) = log(At(i)); }
00102     else { LLMtx.At(i) = NInf; }
00103   }
00104 }
00105 
00106 void TKronMtx::GetProbMtx(TKronMtx& ProbMtx) {
00107   ProbMtx.GenMtx(MtxDim);
00108   for (int i = 0; i < Len(); i++) {
00109     if (At(i) != NInf) { ProbMtx.At(i) = exp(At(i)); }
00110     else { ProbMtx.At(i) = 0.0; }
00111   }
00112 }
00113 
00114 void TKronMtx::Swap(TKronMtx& KronMtx) {
00115   ::Swap(MtxDim, KronMtx.MtxDim);
00116   SeedMtx.Swap(KronMtx.SeedMtx);
00117 }
00118 
00119 int TKronMtx::GetNodes(const int& NIter) const {
00120   return (int) pow(double(GetDim()), double(NIter));
00121 }
00122 
00123 int TKronMtx::GetEdges(const int& NIter) const {
00124   return (int) pow(double(GetMtxSum()), double(NIter));
00125 }
00126 
00127 int TKronMtx::GetKronIter(const int& Nodes) const {
00128   return (int) ceil(log(double(Nodes)) / log(double(GetDim()))); // upper bound
00129   //return (int) TMath::Round(log(double(Nodes)) / log(double(GetDim()))); // round to nearest power
00130 }
00131 
00132 int TKronMtx::GetNZeroK(const PNGraph& Graph) const {
00133  return GetNodes(GetKronIter(Graph->GetNodes()));
00134 }
00135 
00136 double TKronMtx::GetEZero(const int& Edges, const int& KronIters) const {
00137   return pow((double) Edges, 1.0/double(KronIters));
00138 }
00139 
00140 double TKronMtx::GetMtxSum() const {
00141   double Sum = 0;
00142   for (int i = 0; i < Len(); i++) {
00143     Sum += At(i); }
00144   return Sum;
00145 }
00146 
00147 double TKronMtx::GetRowSum(const int& RowId) const {
00148   double Sum = 0;
00149   for (int c = 0; c < GetDim(); c++) {
00150     Sum += At(RowId, c); }
00151   return Sum;
00152 }
00153 
00154 double TKronMtx::GetColSum(const int& ColId) const {
00155   double Sum = 0;
00156   for (int r = 0; r < GetDim(); r++) {
00157     Sum += At(r, ColId); }
00158   return Sum;
00159 }
00160 
00161 double TKronMtx::GetEdgeProb(int NId1, int NId2, const int& NKronIters) const {
00162   double Prob = 1.0;
00163   for (int level = 0; level < NKronIters; level++) {
00164     Prob *= At(NId1 % MtxDim, NId2 % MtxDim);
00165     if (Prob == 0.0) { return 0.0; }
00166     NId1 /= MtxDim;  NId2 /= MtxDim;
00167   }
00168   return Prob;
00169 }
00170 
00171 double TKronMtx::GetNoEdgeProb(int NId1, int NId2, const int& NKronIters) const {
00172   return 1.0 - GetEdgeProb(NId1, NId2, NKronIters);
00173 }
00174 
00175 double TKronMtx::GetEdgeLL(int NId1, int NId2, const int& NKronIters) const {
00176   double LL = 0.0;
00177   for (int level = 0; level < NKronIters; level++) {
00178     const double& LLVal = At(NId1 % MtxDim, NId2 % MtxDim);
00179     if (LLVal == NInf) return NInf;
00180     LL += LLVal;
00181     NId1 /= MtxDim;  NId2 /= MtxDim;
00182   }
00183   return LL;
00184 }
00185 
00186 double TKronMtx::GetNoEdgeLL(int NId1, int NId2, const int& NKronIters) const {
00187   return log(1.0 - exp(GetEdgeLL(NId1, NId2, NKronIters)));
00188 }
00189 
00190 // 2nd order Taylor approximation log(1-x) ~ -x - 0.5x^2
00191 double TKronMtx::GetApxNoEdgeLL(int NId1, int NId2, const int& NKronIters) const {
00192   const double EdgeLL = GetEdgeLL(NId1, NId2, NKronIters);
00193   return -exp(EdgeLL) - 0.5*exp(2*EdgeLL);
00194 }
00195 
00196 bool TKronMtx::IsEdgePlace(int NId1, int NId2, const int& NKronIters, const double& ProbTresh) const {
00197   double Prob = 1.0;
00198   for (int level = 0; level < NKronIters; level++) {
00199     Prob *= At(NId1 % MtxDim, NId2 % MtxDim);
00200     if (ProbTresh > Prob) { return false; }
00201     NId1 /= MtxDim;  NId2 /= MtxDim;
00202   }
00203   return true;
00204 }
00205 
00206 // deriv a*log(x) = a/x
00207 double TKronMtx::GetEdgeDLL(const int& ParamId, int NId1, int NId2, const int& NKronIters) const {
00208   const int ThetaX = ParamId % GetDim();
00209   const int ThetaY = ParamId / GetDim();
00210   int ThetaCnt = 0;
00211   for (int level = 0; level < NKronIters; level++) {
00212     if ((NId1 % MtxDim) == ThetaX && (NId2 % MtxDim) == ThetaY) {
00213       ThetaCnt++; }
00214     NId1 /= MtxDim;  NId2 /= MtxDim;
00215   }
00216   return double(ThetaCnt) / exp(At(ParamId));
00217 }
00218 
00219 // deriv log(1-x^a*y^b..) = -x'/(1-x) = (-a*x^(a-1)*y^b..) / (1-x^a*y^b..)
00220 double TKronMtx::GetNoEdgeDLL(const int& ParamId, int NId1, int NId2, const int& NKronIters) const {
00221   const int& ThetaX = ParamId % GetDim();
00222   const int& ThetaY = ParamId / GetDim();
00223   int ThetaCnt = 0;
00224   double DLL = 0, LL = 0;
00225   for (int level = 0; level < NKronIters; level++) {
00226     const int X = NId1 % MtxDim;
00227     const int Y = NId2 % MtxDim;
00228     const double LVal = At(X, Y);
00229     if (X == ThetaX && Y == ThetaY) {
00230       if (ThetaCnt != 0) { DLL += LVal; }
00231       ThetaCnt++;
00232     } else { DLL += LVal; }
00233     LL += LVal;
00234     NId1 /= MtxDim;  NId2 /= MtxDim;
00235   }
00236   return -ThetaCnt*exp(DLL) / (1.0 - exp(LL));
00237 }
00238 
00239 // 2nd order Taylor approximation log(1-x) ~ -x - 0.5x^2
00240 double TKronMtx::GetApxNoEdgeDLL(const int& ParamId, int NId1, int NId2, const int& NKronIters) const {
00241   const int& ThetaX = ParamId % GetDim();
00242   const int& ThetaY = ParamId / GetDim();
00243   int ThetaCnt = 0;
00244   double DLL = 0;//, LL = 0;
00245   for (int level = 0; level < NKronIters; level++) {
00246     const int X = NId1 % MtxDim;
00247     const int Y = NId2 % MtxDim;
00248     const double LVal = At(X, Y); IAssert(LVal > NInf);
00249     if (X == ThetaX && Y == ThetaY) {
00250       if (ThetaCnt != 0) { DLL += LVal; }
00251       ThetaCnt++;
00252     } else { DLL += LVal; }
00253     //LL += LVal;
00254     NId1 /= MtxDim;  NId2 /= MtxDim;
00255   }
00256   //return -ThetaCnt*exp(DLL)*(1.0 + exp(LL)); // -x'/(1+x) WRONG!
00257   // deriv = -(ax^(a-1)*y^b..) - a*x^(2a-1)*y^2b..
00258   //       = - (ax^(a-1)*y^b..) - a*x*(x^(a-1)*y^b..)^2
00259   return -ThetaCnt*exp(DLL) - ThetaCnt*exp(At(ThetaX, ThetaY)+2*DLL);
00260 }
00261 
00262 uint TKronMtx::GetNodeSig(const double& OneProb) {
00263   uint Sig = 0;
00264   for (int i = 0; i < (int)(8*sizeof(uint)); i++) {
00265     if (TKronMtx::Rnd.GetUniDev() < OneProb) {
00266       Sig |= (1u<<i); }
00267   }
00268   return Sig;
00269 }
00270 
00271 double TKronMtx::GetEdgeProb(const uint& NId1Sig, const uint& NId2Sig, const int& NIter) const {
00272   Assert(GetDim() == 2);
00273   double Prob = 1.0;
00274   for (int i = 0; i < NIter; i++) {
00275     const uint Mask = (1u<<i);
00276     const uint Bit1 = NId1Sig & Mask;
00277     const uint Bit2 = NId2Sig & Mask;
00278     Prob *= At(int(Bit1!=0), int(Bit2!=0));
00279   }
00280   return Prob;
00281 }
00282 
00283 PNGraph TKronMtx::GenThreshGraph(const double& Thresh) const {
00284   PNGraph Graph = TNGraph::New();
00285   for (int i = 0; i < GetDim(); i++) {
00286     Graph->AddNode(i); }
00287   for (int r = 0; r < GetDim(); r++) {
00288     for (int c = 0; c < GetDim(); c++) {
00289       if (At(r, c) >= Thresh) { Graph->AddEdge(r, c); }
00290     }
00291   }
00292   return Graph;
00293 }
00294 
00295 PNGraph TKronMtx::GenRndGraph(const double& RndFact) const {
00296   PNGraph Graph = TNGraph::New();
00297   for (int i = 0; i < GetDim(); i++) {
00298     Graph->AddNode(i); }
00299   for (int r = 0; r < GetDim(); r++) {
00300     for (int c = 0; c < GetDim(); c++) {
00301       if (RndFact * At(r, c) >= TKronMtx::Rnd.GetUniDev()) { Graph->AddEdge(r, c); }
00302     }
00303   }
00304   return Graph;
00305 }
00306 
00307 int TKronMtx::GetKronIter(const int& GNodes, const int& SeedMtxSz) {
00308   return (int) ceil(log(double(GNodes)) / log(double(SeedMtxSz)));
00309 }
00310 
00311 // slow but exaxt procedure (we flip all O(N^2) edges)
00312 PNGraph TKronMtx::GenKronecker(const TKronMtx& SeedMtx, const int& NIter, const bool& IsDir, const int& Seed) {
00313   const TKronMtx& SeedGraph = SeedMtx;
00314   const int NNodes = SeedGraph.GetNodes(NIter);
00315   printf("  Kronecker: %d nodes, %s...\n", NNodes, IsDir ? "Directed":"UnDirected");
00316   PNGraph Graph = TNGraph::New(NNodes, -1);
00317   TExeTm ExeTm;
00318   TRnd Rnd(Seed);
00319   int edges = 0;
00320   for (int node1 = 0; node1 < NNodes; node1++) {
00321     Graph->AddNode(node1); }
00322   if (IsDir) {
00323     for (int node1 = 0; node1 < NNodes; node1++) {
00324       for (int node2 = 0; node2 < NNodes; node2++) {
00325         if (SeedGraph.IsEdgePlace(node1, node2, NIter, Rnd.GetUniDev())) {
00326           Graph->AddEdge(node1, node2);
00327           edges++;
00328         }
00329       }
00330       if (node1 % 1000 == 0) printf("\r...%dk, %dk", node1/1000, edges/1000);
00331     }
00332   } else {
00333     for (int node1 = 0; node1 < NNodes; node1++) {
00334       for (int node2 = node1; node2 < NNodes; node2++) {
00335         if (SeedGraph.IsEdgePlace(node1, node2, NIter, Rnd.GetUniDev())) {
00336           Graph->AddEdge(node1, node2);
00337           Graph->AddEdge(node2, node1);
00338           edges++;
00339         }
00340       }
00341       if (node1 % 1000 == 0) printf("\r...%dk, %dk", node1/1000, edges/1000);
00342     }
00343   }
00344   printf("\r             %d edges [%s]\n", Graph->GetEdges(), ExeTm.GetTmStr());
00345   return Graph;
00346 }
00347 
00348 // use RMat like recursive descent to quickly generate a Kronecker graph
00349 PNGraph TKronMtx::GenFastKronecker(const TKronMtx& SeedMtx, const int& NIter, const bool& IsDir, const int& Seed) {
00350   const TKronMtx& SeedGraph = SeedMtx;
00351   const int MtxDim = SeedGraph.GetDim();
00352   const double MtxSum = SeedGraph.GetMtxSum();
00353   const int NNodes = SeedGraph.GetNodes(NIter);
00354   const int NEdges = SeedGraph.GetEdges(NIter);
00355   //const double DiagEdges = NNodes * pow(SeedGraph.At(0,0), double(NIter));
00356   //const int NEdges = (int) TMath::Round(((pow(double(SeedGraph.GetMtxSum()), double(NIter)) - DiagEdges) /2.0));
00357   printf("  FastKronecker: %d nodes, %d edges, %s...\n", NNodes, NEdges, IsDir ? "Directed":"UnDirected");
00358   PNGraph Graph = TNGraph::New(NNodes, -1);
00359   TRnd Rnd(Seed);
00360   TExeTm ExeTm;
00361   // prepare cell probability vector
00362   TVec<TFltIntIntTr> ProbToRCPosV; // row, col position
00363   double CumProb = 0.0;
00364   for (int r = 0; r < MtxDim; r++) {
00365     for (int c = 0; c < MtxDim; c++) {
00366       const double Prob = SeedGraph.At(r, c);
00367       if (Prob > 0.0) {
00368         CumProb += Prob;
00369         ProbToRCPosV.Add(TFltIntIntTr(CumProb/MtxSum, r, c));
00370       }
00371     }
00372   }
00373   // add nodes
00374   for (int i = 0; i < NNodes; i++) {
00375     Graph->AddNode(i); }
00376   // add edges
00377   int Rng, Row, Col, Collision=0, n = 0;
00378   for (int edges = 0; edges < NEdges; ) {
00379     Rng=NNodes;  Row=0;  Col=0;
00380     for (int iter = 0; iter < NIter; iter++) {
00381       const double& Prob = Rnd.GetUniDev();
00382       n = 0; while(Prob > ProbToRCPosV[n].Val1) { n++; }
00383       const int MtxRow = ProbToRCPosV[n].Val2;
00384       const int MtxCol = ProbToRCPosV[n].Val3;
00385       Rng /= MtxDim;
00386       Row += MtxRow * Rng;
00387       Col += MtxCol * Rng;
00388     }
00389     if (! Graph->IsEdge(Row, Col)) { // allow self-loops
00390       Graph->AddEdge(Row, Col);  edges++;
00391       if (! IsDir) {
00392         if (Row != Col) Graph->AddEdge(Col, Row);
00393         edges++;
00394       }
00395     } else { Collision++; }
00396     //if (edges % 1000 == 0) printf("\r...%dk", edges/1000);
00397   }
00398   //printf("             %d edges [%s]\n", Graph->GetEdges(), ExeTm.GetTmStr());
00399   printf("             collisions: %d (%.4f)\n", Collision, Collision/(double)Graph->GetEdges());
00400   return Graph;
00401 }
00402 
00403 // use RMat like recursive descent to quickly generate a Kronecker graph
00404 PNGraph TKronMtx::GenFastKronecker(const TKronMtx& SeedMtx, const int& NIter, const int& Edges, const bool& IsDir, const int& Seed) {
00405   const TKronMtx& SeedGraph = SeedMtx;
00406   const int MtxDim = SeedGraph.GetDim();
00407   const double MtxSum = SeedGraph.GetMtxSum();
00408   const int NNodes = SeedGraph.GetNodes(NIter);
00409   const int NEdges = Edges;
00410   //const double DiagEdges = NNodes * pow(SeedGraph.At(0,0), double(NIter));
00411   //const int NEdges = (int) TMath::Round(((pow(double(SeedGraph.GetMtxSum()), double(NIter)) - DiagEdges) /2.0));
00412   printf("  RMat Kronecker: %d nodes, %d edges, %s...\n", NNodes, NEdges, IsDir ? "Directed":"UnDirected");
00413   PNGraph Graph = TNGraph::New(NNodes, -1);
00414   TRnd Rnd(Seed);
00415   TExeTm ExeTm;
00416   // prepare cell probability vector
00417   TVec<TFltIntIntTr> ProbToRCPosV; // row, col position
00418   double CumProb = 0.0;
00419   for (int r = 0; r < MtxDim; r++) {
00420     for (int c = 0; c < MtxDim; c++) {
00421       const double Prob = SeedGraph.At(r, c);
00422       if (Prob > 0.0) {
00423         CumProb += Prob;
00424         ProbToRCPosV.Add(TFltIntIntTr(CumProb/MtxSum, r, c));
00425       }
00426     }
00427   }
00428   // add nodes
00429   for (int i = 0; i < NNodes; i++) {
00430     Graph->AddNode(i); }
00431   // add edges
00432   int Rng, Row, Col, Collision=0, n = 0;
00433   for (int edges = 0; edges < NEdges; ) {
00434     Rng=NNodes;  Row=0;  Col=0;
00435     for (int iter = 0; iter < NIter; iter++) {
00436       const double& Prob = Rnd.GetUniDev();
00437       n = 0; while(Prob > ProbToRCPosV[n].Val1) { n++; }
00438       const int MtxRow = ProbToRCPosV[n].Val2;
00439       const int MtxCol = ProbToRCPosV[n].Val3;
00440       Rng /= MtxDim;
00441       Row += MtxRow * Rng;
00442       Col += MtxCol * Rng;
00443     }
00444     if (! Graph->IsEdge(Row, Col)) { // allow self-loops
00445       Graph->AddEdge(Row, Col);  edges++;
00446       if (! IsDir) {
00447         if (Row != Col) Graph->AddEdge(Col, Row);
00448         edges++;
00449       }
00450     } else { Collision++; }
00451     //if (edges % 1000 == 0) printf("\r...%dk", edges/1000);
00452   }
00453   //printf("             %d edges [%s]\n", Graph->GetEdges(), ExeTm.GetTmStr());
00454   printf("             collisions: %d (%.4f)\n", Collision, Collision/(double)Graph->GetEdges());
00455   return Graph;
00456 }
00457 
00458 PNGraph TKronMtx::GenDetKronecker(const TKronMtx& SeedMtx, const int& NIter, const bool& IsDir) {
00459   const TKronMtx& SeedGraph = SeedMtx;
00460   const int NNodes = SeedGraph.GetNodes(NIter);
00461   printf("  Deterministic Kronecker: %d nodes, %s...\n", NNodes, IsDir ? "Directed":"UnDirected");
00462   PNGraph Graph = TNGraph::New(NNodes, -1);
00463   TExeTm ExeTm;
00464   int edges = 0;
00465   for (int node1 = 0; node1 < NNodes; node1++) { Graph->AddNode(node1); }
00466 
00467   for (int node1 = 0; node1 < NNodes; node1++) {
00468     for (int node2 = 0; node2 < NNodes; node2++) {
00469       if (SeedGraph.IsEdgePlace(node1, node2, NIter, Rnd.GetUniDev())) {
00470         Graph->AddEdge(node1, node2);
00471         edges++;
00472       }
00473     }
00474     if (node1 % 1000 == 0) printf("\r...%dk, %dk", node1/1000, edges/1000);
00475   }
00476   return Graph;
00477 }
00478 
00479 void TKronMtx::PlotCmpGraphs(const TKronMtx& SeedMtx, const PNGraph& Graph, const TStr& FNmPref, const TStr& Desc) {
00480   const int KronIters = SeedMtx.GetKronIter(Graph->GetNodes());
00481   PNGraph KronG, WccG;
00482   const bool FastGen = true;
00483   if (FastGen) { KronG = TKronMtx::GenFastKronecker(SeedMtx, KronIters, true, 0); }
00484   else { KronG = TKronMtx::GenKronecker(SeedMtx, KronIters, true, 0); }
00485   TSnap::DelZeroDegNodes(KronG);
00486   WccG = TSnap::GetMxWcc(KronG);
00487   const TStr Desc1 = TStr::Fmt("%s", Desc.CStr());
00488   TGStatVec GS(tmuNodes, TFSet() | gsdInDeg | gsdOutDeg | gsdWcc | gsdHops | gsdScc | gsdClustCf | gsdSngVec | gsdSngVal);
00489   //gsdHops
00490   //gsWccHops, gsdSngVal, gsdSngVec, gsdClustCf
00491   GS.Add(Graph, TSecTm(1), TStr::Fmt("GRAPH  G(%d, %d)", Graph->GetNodes(), Graph->GetEdges()));
00492   GS.Add(KronG, TSecTm(2), TStr::Fmt("KRONECKER  K(%d, %d)", KronG->GetNodes(), KronG->GetEdges()));
00493   GS.Add(WccG, TSecTm(3),  TStr::Fmt("KRONECKER  wccK(%d, %d)", WccG->GetNodes(), WccG->GetEdges()));
00494   const TStr Style = "linewidth 1 pointtype 6 pointsize 1";
00495   GS.ImposeDistr(gsdInDeg, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00496   GS.ImposeDistr(gsdInDeg, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00497   GS.ImposeDistr(gsdOutDeg, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00498   GS.ImposeDistr(gsdOutDeg, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00499   GS.ImposeDistr(gsdHops, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00500   GS.ImposeDistr(gsdClustCf, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00501   GS.ImposeDistr(gsdClustCf, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00502   GS.ImposeDistr(gsdSngVal, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00503   GS.ImposeDistr(gsdSngVal, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00504   GS.ImposeDistr(gsdSngVec, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00505   GS.ImposeDistr(gsdSngVec, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00506   GS.ImposeDistr(gsdWcc, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00507   GS.ImposeDistr(gsdWcc, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00508   GS.ImposeDistr(gsdScc, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00509   GS.ImposeDistr(gsdScc, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00510 //    typedef enum { distrUndef, distrInDeg, distrOutDeg, distrWcc, distrScc,
00511 //  distrHops, distrWccHops, distrSngVal, distrSngVec, distrClustCf, distrMx } TGraphDistr;*/
00512 }
00513 
00514 void TKronMtx::PlotCmpGraphs(const TKronMtx& SeedMtx1, const TKronMtx& SeedMtx2, const PNGraph& Graph, const TStr& FNmPref, const TStr& Desc) {
00515   const int KronIters1 = SeedMtx1.GetKronIter(Graph->GetNodes());
00516   const int KronIters2 = SeedMtx2.GetKronIter(Graph->GetNodes());
00517   PNGraph KronG1, KronG2;
00518   const bool FastGen = true;
00519   if (FastGen) {
00520     KronG1 = TKronMtx::GenFastKronecker(SeedMtx1, KronIters1, true, 0);
00521     KronG2 = TKronMtx::GenFastKronecker(SeedMtx2, KronIters2, false, 0); } 
00522   else {
00523     KronG1 = TKronMtx::GenKronecker(SeedMtx1, KronIters1, true, 0);
00524     KronG2 = TKronMtx::GenKronecker(SeedMtx2, KronIters2, true, 0);  }
00525   TSnap::DelZeroDegNodes(KronG1);
00526   TSnap::DelZeroDegNodes(KronG2);
00527   const TStr Desc1 = TStr::Fmt("%s", Desc.CStr());
00528   TGStatVec GS(tmuNodes, TFSet() | gsdInDeg | gsdOutDeg | gsdWcc | gsdScc | gsdHops | gsdClustCf | gsdSngVec | gsdSngVal | gsdTriadPart);
00529   //gsdHops
00530   //gsWccHops, gsdSngVal, gsdSngVec, gsdClustCf
00531   GS.Add(Graph, TSecTm(1), TStr::Fmt("GRAPH  G(%d, %d)", Graph->GetNodes(), Graph->GetEdges()));
00532   GS.Add(KronG1, TSecTm(2), TStr::Fmt("KRONECKER1  K(%d, %d) %s", KronG1->GetNodes(), KronG1->GetEdges(), SeedMtx1.GetMtxStr().CStr()));
00533   GS.Add(KronG2, TSecTm(3),  TStr::Fmt("KRONECKER2  K(%d, %d) %s", KronG2->GetNodes(), KronG2->GetEdges(), SeedMtx2.GetMtxStr().CStr()));
00534   const TStr Style = "linewidth 1 pointtype 6 pointsize 1";
00535   // raw data
00536   GS.ImposeDistr(gsdInDeg, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00537   GS.ImposeDistr(gsdOutDeg, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00538   GS.ImposeDistr(gsdHops, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00539   GS.ImposeDistr(gsdClustCf, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00540   GS.ImposeDistr(gsdSngVal, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00541   GS.ImposeDistr(gsdSngVec, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00542   GS.ImposeDistr(gsdWcc, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00543   GS.ImposeDistr(gsdScc, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00544   GS.ImposeDistr(gsdTriadPart, FNmPref, Desc1, false, false, gpwLinesPoints, Style);
00545   // smooth
00546   GS.ImposeDistr(gsdInDeg, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00547   GS.ImposeDistr(gsdOutDeg, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00548   GS.ImposeDistr(gsdClustCf, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00549   GS.ImposeDistr(gsdScc, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00550   GS.ImposeDistr(gsdWcc, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00551   GS.ImposeDistr(gsdSngVec, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00552   GS.ImposeDistr(gsdSngVal, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00553   GS.ImposeDistr(gsdTriadPart, FNmPref+"-B", Desc1, true, false, gpwLinesPoints, Style);
00554 }
00555 
00556 void TKronMtx::PlotCmpGraphs(const TVec<TKronMtx>& SeedMtxV, const PNGraph& Graph, const TStr& FNmPref, const TStr& Desc) {
00557   const TStr Desc1 = TStr::Fmt("%s", Desc.CStr());
00558   TGStatVec GS(tmuNodes, TFSet() | gsdInDeg | gsdOutDeg | gsdWcc | gsdScc | gsdHops | gsdClustCf | gsdSngVec | gsdSngVal);
00559   GS.Add(Graph, TSecTm(1), TStr::Fmt("GRAPH  G(%d, %d)", Graph->GetNodes(), Graph->GetEdges()));
00560   //gsdHops
00561   //gsWccHops, gsdSngVal, gsdSngVec, gsdClustCf
00562   for (int m = 0; m < SeedMtxV.Len(); m++) {
00563     const int KronIters = SeedMtxV[m].GetKronIter(Graph->GetNodes());
00564     PNGraph KronG1 = TKronMtx::GenFastKronecker(SeedMtxV[m], KronIters, true, 0);
00565     printf("*** K(%d, %d) n0=%d\n", KronG1->GetNodes(), KronG1->GetEdges(), SeedMtxV[m].GetDim());
00566     TSnap::DelZeroDegNodes(KronG1);
00567     printf(" del zero deg K(%d, %d) n0=%d\n", KronG1->GetNodes(), KronG1->GetEdges(), m);
00568     GS.Add(KronG1, TSecTm(m+2), TStr::Fmt("K(%d, %d) n0^k=%d n0=%d", KronG1->GetNodes(), KronG1->GetEdges(), SeedMtxV[m].GetNZeroK(Graph), SeedMtxV[m].GetDim()));
00569     // plot after each Kronecker is done
00570     const TStr Style = "linewidth 1 pointtype 6 pointsize 1";
00571     GS.ImposeDistr(gsdInDeg, FNmPref, Desc1, false, false, gpwLines, Style);
00572     GS.ImposeDistr(gsdInDeg, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00573     GS.ImposeDistr(gsdOutDeg, FNmPref, Desc1, false, false, gpwLines, Style);
00574     GS.ImposeDistr(gsdOutDeg, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00575     GS.ImposeDistr(gsdHops, FNmPref, Desc1, false, false, gpwLines, Style);
00576     GS.ImposeDistr(gsdClustCf, FNmPref, Desc1, false, false, gpwLines, Style);
00577     GS.ImposeDistr(gsdClustCf, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00578     GS.ImposeDistr(gsdSngVal, FNmPref, Desc1, false, false, gpwLines, Style);
00579     GS.ImposeDistr(gsdSngVal, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00580     GS.ImposeDistr(gsdSngVec, FNmPref, Desc1, false, false, gpwLines, Style);
00581     GS.ImposeDistr(gsdSngVec, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00582     GS.ImposeDistr(gsdWcc, FNmPref, Desc1, false, false, gpwLines, Style);
00583     GS.ImposeDistr(gsdWcc, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00584     GS.ImposeDistr(gsdScc, FNmPref, Desc1, false, false, gpwLines, Style);
00585     GS.ImposeDistr(gsdScc, FNmPref+"-B", Desc1, true, false, gpwLines, Style);
00586   }
00587   //    typedef enum { distrUndef, distrInDeg, distrOutDeg, distrWcc, distrScc,
00588   //  distrHops, distrWccHops, distrSngVal, distrSngVec, distrClustCf, distrMx } TGraphDistr;*/
00589 }
00590 
00591 void TKronMtx::KronMul(const TKronMtx& Left, const TKronMtx& Right, TKronMtx& Result) {
00592   const int LDim = Left.GetDim();
00593   const int RDim = Right.GetDim();
00594   Result.GenMtx(LDim * RDim);
00595   for (int r1 = 0; r1 < LDim; r1++) {
00596     for (int c1 = 0; c1 < LDim; c1++) {
00597       const double& Val = Left.At(r1, c1);
00598       for (int r2 = 0; r2 < RDim; r2++) {
00599         for (int c2 = 0; c2 < RDim; c2++) {
00600           Result.At(r1*RDim+r2, c1*RDim+c2) = Val * Right.At(r2, c2);
00601         }
00602       }
00603     }
00604   }
00605 }
00606 
00607 void TKronMtx::KronSum(const TKronMtx& Left, const TKronMtx& Right, TKronMtx& Result) {
00608   const int LDim = Left.GetDim();
00609   const int RDim = Right.GetDim();
00610   Result.GenMtx(LDim * RDim);
00611   for (int r1 = 0; r1 < LDim; r1++) {
00612     for (int c1 = 0; c1 < LDim; c1++) {
00613       const double& Val = Left.At(r1, c1);
00614       for (int r2 = 0; r2 < RDim; r2++) {
00615         for (int c2 = 0; c2 < RDim; c2++) {
00616           if (Val == NInf || Right.At(r2, c2) == NInf) {
00617             Result.At(r1*RDim+r2, c1*RDim+c2) = NInf; }
00618           else {
00619             Result.At(r1*RDim+r2, c1*RDim+c2) = Val + Right.At(r2, c2); }
00620         }
00621       }
00622     }
00623   }
00624 }
00625 
00626 void TKronMtx::KronPwr(const TKronMtx& KronMtx, const int& NIter, TKronMtx& OutMtx) {
00627   OutMtx = KronMtx;
00628   TKronMtx NewOutMtx;
00629   for (int iter = 0; iter < NIter; iter++) {
00630     KronMul(OutMtx, KronMtx, NewOutMtx);
00631     NewOutMtx.Swap(OutMtx);
00632   }
00633 
00634 }
00635 
00636 void TKronMtx::Dump(const TStr& MtxNm, const bool& Sort) const {
00637   /*printf("%s: %d x %d\n", MtxNm.Empty()?"Mtx":MtxNm.CStr(), GetDim(), GetDim());
00638   for (int r = 0; r < GetDim(); r++) {
00639     for (int c = 0; c < GetDim(); c++) { printf("  %8.2g", At(r, c)); }
00640     printf("\n");
00641   }*/
00642   if (! MtxNm.Empty()) printf("%s\n", MtxNm.CStr());
00643   double Sum=0.0;
00644   TFltV ValV = SeedMtx;
00645   if (Sort) { ValV.Sort(false); }
00646   for (int i = 0; i < ValV.Len(); i++) {
00647     printf("  %10.4g", ValV[i]());
00648     Sum += ValV[i];
00649     if ((i+1) % GetDim() == 0) { printf("\n"); }
00650   }
00651   printf(" (sum:%.4f)\n", Sum);
00652 }
00653 
00654 // average difference in the parameters
00655 double TKronMtx::GetAvgAbsErr(const TKronMtx& Kron1, const TKronMtx& Kron2) {
00656   TFltV P1 = Kron1.GetMtx();
00657   TFltV P2 = Kron2.GetMtx();
00658   IAssert(P1.Len() == P2.Len());
00659   P1.Sort();  P2.Sort();
00660   double delta = 0.0;
00661   for (int i = 0; i < P1.Len(); i++) {
00662     delta += fabs(P1[i] - P2[i]);
00663   }
00664   return delta/P1.Len();
00665 }
00666 
00667 // average L2 difference in the parameters
00668 double TKronMtx::GetAvgFroErr(const TKronMtx& Kron1, const TKronMtx& Kron2) {
00669   TFltV P1 = Kron1.GetMtx();
00670   TFltV P2 = Kron2.GetMtx();
00671   IAssert(P1.Len() == P2.Len());
00672   P1.Sort();  P2.Sort();
00673   double delta = 0.0;
00674   for (int i = 0; i < P1.Len(); i++) {
00675     delta += pow(P1[i] - P2[i], 2);
00676   }
00677   return sqrt(delta/P1.Len());
00678 }
00679 
00680 // get matrix from matlab matrix notation
00681 TKronMtx TKronMtx::GetMtx(TStr MatlabMtxStr) {
00682   TStrV RowStrV, ColStrV;
00683   MatlabMtxStr.ChangeChAll(',', ' ');
00684   MatlabMtxStr.SplitOnAllCh(';', RowStrV);  IAssert(! RowStrV.Empty());
00685   RowStrV[0].SplitOnWs(ColStrV);    IAssert(! ColStrV.Empty());
00686   const int Rows = RowStrV.Len();
00687   const int Cols = ColStrV.Len();
00688   IAssert(Rows == Cols);
00689   TKronMtx Mtx(Rows);
00690   for (int r = 0; r < Rows; r++) {
00691     RowStrV[r].SplitOnWs(ColStrV);
00692     IAssert(ColStrV.Len() == Cols);
00693     for (int c = 0; c < Cols; c++) {
00694       Mtx.At(r, c) = (double) ColStrV[c].GetFlt(); }
00695   }
00696   return Mtx;
00697 }
00698 
00699 TKronMtx TKronMtx::GetRndMtx(const int& Dim, const double& MinProb) {
00700   TKronMtx Mtx;
00701   Mtx.SetRndMtx(Dim, MinProb);
00702   return Mtx;
00703 }
00704 
00705 TKronMtx TKronMtx::GetInitMtx(const int& Dim, const int& Nodes, const int& Edges) {
00706   const double MxParam = 0.8+TKronMtx::Rnd.GetUniDev()/5.0;
00707   const double MnParam = 0.2-TKronMtx::Rnd.GetUniDev()/5.0;
00708   const double Step = (MxParam-MnParam) / (Dim*Dim-1);
00709   TFltV ParamV(Dim*Dim);
00710   if (Dim == 1) { ParamV.PutAll(0.5); } // random graph
00711   else {
00712     for (int p = 0; p < ParamV.Len(); p++) {
00713       ParamV[p] = MxParam - p*Step; }
00714   }
00715   //IAssert(ParamV[0]==MxParam && ParamV.Last()==MnParam);
00716   TKronMtx Mtx(ParamV);
00717   Mtx.SetForEdges(Nodes, Edges);
00718   return Mtx;
00719 }
00720 
00721 TKronMtx TKronMtx::GetInitMtx(const TStr& MtxStr, const int& Dim, const int& Nodes, const int& Edges) {
00722   TKronMtx Mtx(Dim);
00723   if (TCh::IsNum(MtxStr[0])) { Mtx = TKronMtx::GetMtx(MtxStr); }
00724   else if (MtxStr[0] == 'r') { Mtx = TKronMtx::GetRndMtx(Dim, 0.1); }
00725   else if (MtxStr[0] == 'a') {
00726     const double Prob = TKronMtx::Rnd.GetUniDev();
00727     if (Prob < 0.4) {
00728       Mtx = TKronMtx::GetInitMtx(Dim, Nodes, Edges); }
00729     else { // interpolate so that there are in the corners 0.9, 0.5, 0.1, 0.5
00730       const double Max = 0.9+TKronMtx::Rnd.GetUniDev()/10.0;
00731       const double Min = 0.1-TKronMtx::Rnd.GetUniDev()/10.0;
00732       const double Med = (Max-Min)/2.0;
00733       Mtx.At(0,0)      = Max;       Mtx.At(0,Dim-1) = Med;
00734       Mtx.At(Dim-1, 0) = Med;  Mtx.At(Dim-1, Dim-1) = Min;
00735       for (int i = 1; i < Dim-1; i++) {
00736         Mtx.At(i,i) = Max - double(i)*(Max-Min)/double(Dim-1);
00737         Mtx.At(i, 0) = Mtx.At(0, i) = Max - double(i)*(Max-Med)/double(Dim-1);
00738         Mtx.At(i, Dim-1) = Mtx.At(Dim-1, i) = Med - double(i)*(Med-Min)/double(Dim-1);
00739       }
00740       for (int i = 1; i < Dim-1; i++) {
00741         for (int j = 1; j < Dim-1; j++) {
00742           if (i >= j) { continue; }
00743           Mtx.At(i,j) = Mtx.At(j,i) = Mtx.At(i,i) - (j-i)*(Mtx.At(i,i)-Mtx.At(i,Dim-1))/(Dim-i-1);
00744         }
00745       }
00746       Mtx.AddRndNoise(0.1);
00747     }
00748   } else { FailR("Wrong mtx: matlab str, or random (r), or all (a)"); }
00749   Mtx.SetForEdges(Nodes, Edges);
00750   return Mtx;
00751 }
00752 
00753 TKronMtx TKronMtx::GetMtxFromNm(const TStr& MtxNm) {
00754   if (MtxNm == "3chain") return TKronMtx::GetMtx("1 1 0; 1 1 1; 0 1 1");
00755   else if (MtxNm == "4star") return TKronMtx::GetMtx("1 1 1 1; 1 1 0 0 ; 1 0 1 0; 1 0 0 1");
00756   else if (MtxNm == "4chain") return TKronMtx::GetMtx("1 1 0 0; 1 1 1 0 ; 0 1 1 1; 0 0 1 1");
00757   else if (MtxNm == "4square") return TKronMtx::GetMtx("1 1 0 1; 1 1 1 0 ; 0 1 1 1; 1 0 1 1");
00758   else if (MtxNm == "5star") return TKronMtx::GetMtx("1 1 1 1 1; 1 1 0 0 0; 1 0 1 0 0; 1 0 0 1 0; 1 0 0 0 1");
00759   else if (MtxNm == "6star") return TKronMtx::GetMtx("1 1 1 1 1 1; 1 1 0 0 0 0; 1 0 1 0 0 0; 1 0 0 1 0 0; 1 0 0 0 1 0; 1 0 0 0 0 1");
00760   else if (MtxNm == "7star") return TKronMtx::GetMtx("1 1 1 1 1 1 1; 1 1 0 0 0 0 0; 1 0 1 0 0 0 0; 1 0 0 1 0 0 0; 1 0 0 0 1 0 0; 1 0 0 0 0 1 0; 1 0 0 0 0 0 1");
00761   else if (MtxNm == "5burst") return TKronMtx::GetMtx("1 1 1 1 0; 1 1 0 0 0; 1 0 1 0 0; 1 0 0 1 1; 0 0 0 1 1");
00762   else if (MtxNm == "7burst") return TKronMtx::GetMtx("1 0 0 1 0 0 0; 0 1 0 1 0 0 0; 0 0 1 1 0 0 0; 1 1 1 1 1 0 0; 0 0 0 1 1 1 1; 0 0 0 0 1 1 0; 0 0 0 0 1 0 1");
00763   else if (MtxNm == "7cross") return TKronMtx::GetMtx("1 0 0 1 0 0 0; 0 1 0 1 0 0 0; 0 0 1 1 0 0 0; 1 1 1 1 1 0 0; 0 0 0 1 1 1 0; 0 0 0 0 1 1 1; 0 0 0 0 0 1 1");
00764   FailR(TStr::Fmt("Unknow matrix: '%s'", MtxNm.CStr()).CStr());
00765   return TKronMtx();
00766 }
00767 
00768 TKronMtx TKronMtx::LoadTxt(const TStr& MtxFNm) {
00769   PSs Ss = TSs::LoadTxt(ssfTabSep, MtxFNm);
00770   IAssertR(Ss->GetXLen() == Ss->GetYLen(), "Not a square matrix");
00771   IAssert(Ss->GetYLen() == Ss->GetXLen());
00772   TKronMtx Mtx(Ss->GetYLen());
00773   for (int r = 0; r < Ss->GetYLen(); r++) {
00774     for (int c = 0; c < Ss->GetXLen(); c++) {
00775       Mtx.At(r, c) = (double) Ss->At(c, r).GetFlt(); }
00776   }
00777   return Mtx;
00778 }
00779 
00780 
00782 // Kronecker Log Likelihood
00783 TKroneckerLL::TKroneckerLL(const PNGraph& GraphPt, const TFltV& ParamV, const double& PermPSwapNd): PermSwapNodeProb(PermPSwapNd) {
00784   InitLL(GraphPt, TKronMtx(ParamV));
00785 }
00786 
00787 TKroneckerLL::TKroneckerLL(const PNGraph& GraphPt, const TKronMtx& ParamMtx, const double& PermPSwapNd) : PermSwapNodeProb(PermPSwapNd) {
00788   InitLL(GraphPt, ParamMtx);
00789 }
00790 
00791 TKroneckerLL::TKroneckerLL(const PNGraph& GraphPt, const TKronMtx& ParamMtx, const TIntV& NodeIdPermV, const double& PermPSwapNd) : PermSwapNodeProb(PermPSwapNd) {
00792   InitLL(GraphPt, ParamMtx);
00793   NodePerm = NodeIdPermV;
00794   SetIPerm(NodePerm);
00795 }
00796 
00797 PKroneckerLL TKroneckerLL::New(const PNGraph& GraphPt, const TKronMtx& ParamMtx, const double& PermPSwapNd) {
00798   return new TKroneckerLL(GraphPt, ParamMtx, PermPSwapNd);
00799 }
00800 
00801 PKroneckerLL TKroneckerLL::New(const PNGraph& GraphPt, const TKronMtx& ParamMtx, const TIntV& NodeIdPermV, const double& PermPSwapNd) {
00802   return new TKroneckerLL(GraphPt, ParamMtx, NodeIdPermV, PermPSwapNd);
00803 }
00804 
00805 void TKroneckerLL::SetPerm(const char& PermId) {
00806   if (PermId == 'o') { SetOrderPerm(); }
00807   else if (PermId == 'd') { SetDegPerm(); }
00808   else if (PermId == 'r') { SetRndPerm(); }
00809   else if (PermId == 'b') { SetBestDegPerm(); }
00810   else FailR("Unknown permutation type (o,d,r)");
00811 }
00812 
00813 void TKroneckerLL::SetOrderPerm() {
00814   NodePerm.Gen(Nodes, 0);
00815   for (int i = 0; i < Graph->GetNodes(); i++) {
00816     NodePerm.Add(i); }
00817   SetIPerm(NodePerm);
00818 }
00819 
00820 void TKroneckerLL::SetRndPerm() {
00821   NodePerm.Gen(Nodes, 0);
00822   for (int i = 0; i < Graph->GetNodes(); i++) {
00823     NodePerm.Add(i); }
00824   NodePerm.Shuffle(TKronMtx::Rnd);
00825   SetIPerm(NodePerm);
00826 }
00827 
00828 void TKroneckerLL::SetDegPerm() {
00829   TIntPrV DegNIdV;
00830   for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
00831     DegNIdV.Add(TIntPr(NI.GetDeg(), NI.GetId()));
00832   }
00833   DegNIdV.Sort(false);
00834   NodePerm.Gen(DegNIdV.Len(), 0);
00835   for (int i = 0; i < DegNIdV.Len(); i++) {
00836     NodePerm.Add(DegNIdV[i].Val2);
00837   }
00838   SetIPerm(NodePerm);
00839 }
00840 
00842 void TKroneckerLL::SetBestDegPerm() {
00843   NodePerm.Gen(Nodes);
00844   const int NZero = ProbMtx.GetDim();
00845   TFltIntPrV DegV(Nodes), CDegV(Nodes);
00846   TFltV Row(NZero);
00847   TFltV Col(NZero);
00848   for(int i = 0; i < NZero; i++) {
00849           for(int j = 0; j < NZero; j++) {
00850                   Row[i] += ProbMtx.At(i, j);
00851                   Col[i] += ProbMtx.At(j, i);
00852           }
00853   }
00854 
00855   for(int i = 0; i < Nodes; i++) {
00856           TNGraph::TNodeI NodeI = Graph->GetNI(i);
00857           int NId = i;
00858           double RowP = 1.0, ColP = 1.0;
00859           for(int j = 0; j < KronIters; j++) {
00860                   int Bit = NId % NZero;
00861                   RowP *= Row[Bit];             ColP *= Col[Bit];
00862                   NId /= NZero;
00863           }
00864           CDegV[i] = TFltIntPr(RowP + ColP, i);
00865           DegV[i] = TFltIntPr(NodeI.GetDeg(), i);
00866   }
00867   DegV.Sort(false);             CDegV.Sort(false);
00868   for(int i = 0; i < Nodes; i++) {
00869           NodePerm[DegV[i].Val2] = CDegV[i].Val2;
00870   }
00871   SetIPerm(NodePerm);
00872 }
00873 
00875 void TKroneckerLL::SetIPerm(const TIntV& Perm) {
00876         InvertPerm.Gen(Perm.Len());
00877         for (int i = 0; i < Perm.Len(); i++) {
00878                 InvertPerm[Perm[i]] = i;
00879         }
00880 }
00881 
00882 void TKroneckerLL::SetGraph(const PNGraph& GraphPt) {
00883   Graph = GraphPt;
00884   bool NodesOk = true;
00885   // check that nodes IDs are {0,1,..,Nodes-1}
00886   for (int nid = 0; nid < Graph->GetNodes(); nid++) {
00887     if (! Graph->IsNode(nid)) { NodesOk=false; break; } }
00888   if (! NodesOk) {
00889     TIntV NIdV;  GraphPt->GetNIdV(NIdV);
00890     Graph = TSnap::GetSubGraph(GraphPt, NIdV, true);
00891     for (int nid = 0; nid < Graph->GetNodes(); nid++) {
00892       IAssert(Graph->IsNode(nid)); }
00893   }
00894   Nodes = Graph->GetNodes();
00895   IAssert(LLMtx.GetDim() > 1 && LLMtx.Len() == ProbMtx.Len());
00896   KronIters = (int) ceil(log(double(Nodes)) / log(double(ProbMtx.GetDim())));
00897   // edge vector (for swap-edge permutation proposal)
00898 //  if (PermSwapNodeProb < 1.0) { /// !!!!! MYUNGHWAN, CHECK! WHY IS THIS COMMENTED OUT
00899     GEdgeV.Gen(Graph->GetEdges(), 0);
00900     for (TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
00901       if (EI.GetSrcNId() != EI.GetDstNId()) {
00902         GEdgeV.Add(TIntTr(EI.GetSrcNId(), EI.GetDstNId(), -1));
00903       }
00904     }
00905 //  }
00906 
00907   RealNodes = Nodes;
00908   RealEdges = Graph->GetEdges();
00909   LEdgeV = TIntTrV();
00910   LSelfEdge = 0;
00911 }
00912 
00913 
00914 void TKroneckerLL::AppendIsoNodes() {
00915   Nodes = (int) pow((double)ProbMtx.GetDim(), KronIters);
00916   // add nodes until filling the Kronecker graph model
00917   for (int nid = Graph->GetNodes(); nid < Nodes; nid++) {
00918           Graph->AddNode(nid);
00919   }
00920 }
00921 
00923 void TKroneckerLL::RestoreGraph(const bool RestoreNodes) {
00924         //      remove from Graph
00925         int NId1, NId2;
00926         for (int e = 0; e < LEdgeV.Len(); e++) {
00927         NId1 = LEdgeV[e].Val1;  NId2 = LEdgeV[e].Val2;
00928                 Graph->DelEdge(NId1, NId2);
00929 //              GEdgeV.DelIfIn(LEdgeV[e]);
00930         }
00931         if(LEdgeV.Len() - LSelfEdge)
00932                 GEdgeV.Del(GEdgeV.Len() - LEdgeV.Len() + LSelfEdge, GEdgeV.Len() - 1);
00933         LEdgeV.Clr();
00934         LSelfEdge = 0;
00935 
00936         if(RestoreNodes) {
00937                 for(int i = Graph->GetNodes()-1; i >= RealNodes; i--) {
00938                         Graph->DelNode(i);
00939                 }
00940         }
00941 }
00942 
00943 double TKroneckerLL::GetFullGraphLL() const {
00944   // the number of times a seed matrix element appears in
00945   // the full kronecker adjacency matrix after KronIter
00946   // kronecker multiplications
00947   double ElemCnt = 1;
00948   const double dim = LLMtx.GetDim();
00949   // count number of times x appears in the full kronecker matrix
00950   for (int i = 1; i < KronIters; i++) {
00951     ElemCnt = dim*dim*ElemCnt + TMath::Power(dim, 2*i);
00952   }
00953   return ElemCnt * LLMtx.GetMtxSum();
00954 }
00955 
00956 double TKroneckerLL::GetFullRowLL(int RowId) const {
00957   double RowLL = 0.0;
00958   const int MtxDim = LLMtx.GetDim();
00959   for (int level = 0; level < KronIters; level++) {
00960     RowLL += LLMtx.GetRowSum(RowId % MtxDim);
00961     RowId /= MtxDim;
00962   }
00963   return RowLL;
00964 }
00965 
00966 double TKroneckerLL::GetFullColLL(int ColId) const {
00967   double ColLL = 0.0;
00968   const int MtxDim = LLMtx.GetDim();
00969   for (int level = 0; level < KronIters; level++) {
00970     ColLL += LLMtx.GetColSum(ColId % MtxDim);
00971     ColId /= MtxDim;
00972   }
00973   return ColLL;
00974 }
00975 
00976 double TKroneckerLL::GetEmptyGraphLL() const {
00977   double LL = 0;
00978   for (int NId1 = 0; NId1 < LLMtx.GetNodes(KronIters); NId1++) {
00979     for (int NId2 = 0; NId2 < LLMtx.GetNodes(KronIters); NId2++) {
00980       LL = LL + LLMtx.GetNoEdgeLL(NId1, NId2, KronIters);
00981     }
00982   }
00983   return LL;
00984 }
00985 
00986 // 2nd prder Taylor approximation, log(1-x) ~ -x - 0.5x^2
00987 double TKroneckerLL::GetApxEmptyGraphLL() const {
00988   double Sum=0.0, SumSq=0.0;
00989   for (int i = 0; i < ProbMtx.Len(); i++) {
00990     Sum += ProbMtx.At(i);
00991     SumSq += TMath::Sqr(ProbMtx.At(i));
00992   }
00993   return -pow(Sum, KronIters) - 0.5*pow(SumSq, KronIters);
00994 }
00995 
00996 void TKroneckerLL::InitLL(const TFltV& ParamV) {
00997   InitLL(TKronMtx(ParamV));
00998 }
00999 
01000 void TKroneckerLL::InitLL(const TKronMtx& ParamMtx) {
01001   IAssert(ParamMtx.IsProbMtx());
01002   ProbMtx = ParamMtx;
01003   ProbMtx.GetLLMtx(LLMtx);
01004   LogLike = TKronMtx::NInf;
01005   if (GradV.Len() != ProbMtx.Len()) {
01006     GradV.Gen(ProbMtx.Len()); }
01007   GradV.PutAll(0.0);
01008 }
01009 
01010 void TKroneckerLL::InitLL(const PNGraph& GraphPt, const TKronMtx& ParamMtx) {
01011   IAssert(ParamMtx.IsProbMtx());
01012   ProbMtx = ParamMtx;
01013   ProbMtx.GetLLMtx(LLMtx);
01014   SetGraph(GraphPt);
01015   LogLike = TKronMtx::NInf;
01016   if (GradV.Len() != ProbMtx.Len()) {
01017     GradV.Gen(ProbMtx.Len()); }
01018   GradV.PutAll(0.0);
01019 }
01020 
01021 // exact graph log-likelihood, takes O(N^2 + E)
01022 double TKroneckerLL::CalcGraphLL() {
01023   LogLike = GetEmptyGraphLL(); // takes O(N^2)
01024   for (int nid = 0; nid < Nodes; nid++) {
01025     const TNGraph::TNodeI Node = Graph->GetNI(nid);
01026     const int SrcNId = NodePerm[nid];
01027     for (int e = 0; e < Node.GetOutDeg(); e++) {
01028       const int DstNId = NodePerm[Node.GetOutNId(e)];
01029       LogLike = LogLike - LLMtx.GetNoEdgeLL(SrcNId, DstNId, KronIters)
01030         + LLMtx.GetEdgeLL(SrcNId, DstNId, KronIters);
01031     }
01032   }
01033   return LogLike;
01034 }
01035 
01036 // approximate graph log-likelihood, takes O(E + N_0)
01037 double TKroneckerLL::CalcApxGraphLL() {
01038   LogLike = GetApxEmptyGraphLL(); // O(N_0)
01039   for (int nid = 0; nid < Nodes; nid++) {
01040     const TNGraph::TNodeI Node = Graph->GetNI(nid);
01041     const int SrcNId = NodePerm[nid];
01042     for (int e = 0; e < Node.GetOutDeg(); e++) {
01043       const int DstNId = NodePerm[Node.GetOutNId(e)];
01044       LogLike = LogLike - LLMtx.GetApxNoEdgeLL(SrcNId, DstNId, KronIters)
01045         + LLMtx.GetEdgeLL(SrcNId, DstNId, KronIters);
01046     }
01047   }
01048   return LogLike;
01049 }
01050 
01051 // Used in TKroneckerLL::SwapNodesLL: DeltaLL if we
01052 // add the node to the matrix (node gets/creates all
01053 // of its in- and out-edges).
01054 // Zero is for the empty row/column (isolated node)
01055 double TKroneckerLL::NodeLLDelta(const int& NId) const {
01056   if (! Graph->IsNode(NId)) { return 0.0; } // zero degree node
01057   double Delta = 0.0;
01058   const TNGraph::TNodeI Node = Graph->GetNI(NId);
01059   // out-edges
01060   const int SrcRow = NodePerm[NId];
01061   for (int e = 0; e < Node.GetOutDeg(); e++) {
01062     const int DstCol = NodePerm[Node.GetOutNId(e)];
01063     Delta += - LLMtx.GetApxNoEdgeLL(SrcRow, DstCol, KronIters)
01064       + LLMtx.GetEdgeLL(SrcRow, DstCol, KronIters);
01065   }
01066   //in-edges
01067   const int SrcCol = NodePerm[NId];
01068   for (int e = 0; e < Node.GetInDeg(); e++) {
01069     const int DstRow = NodePerm[Node.GetInNId(e)];
01070     Delta += - LLMtx.GetApxNoEdgeLL(DstRow, SrcCol, KronIters)
01071       + LLMtx.GetEdgeLL(DstRow, SrcCol, KronIters);
01072   }
01073   // double counted self-edge
01074   if (Graph->IsEdge(NId, NId)) {
01075     Delta += + LLMtx.GetApxNoEdgeLL(SrcRow, SrcCol, KronIters)
01076       - LLMtx.GetEdgeLL(SrcRow, SrcCol, KronIters);
01077     IAssert(SrcRow == SrcCol);
01078   }
01079   return Delta;
01080 }
01081 
01082 // swapping two nodes, only need to go over two rows and columns
01083 double TKroneckerLL::SwapNodesLL(const int& NId1, const int& NId2) {
01084   // subtract old LL (remove nodes)
01085   LogLike = LogLike - NodeLLDelta(NId1) - NodeLLDelta(NId2);
01086   const int PrevId1 = NodePerm[NId1], PrevId2 = NodePerm[NId2];
01087   // double-counted edges
01088   if (Graph->IsEdge(NId1, NId2)) {
01089     LogLike += - LLMtx.GetApxNoEdgeLL(PrevId1, PrevId2, KronIters)
01090       + LLMtx.GetEdgeLL(PrevId1, PrevId2, KronIters); }
01091   if (Graph->IsEdge(NId2, NId1)) {
01092     LogLike += - LLMtx.GetApxNoEdgeLL(PrevId2, PrevId1, KronIters)
01093       + LLMtx.GetEdgeLL(PrevId2, PrevId1, KronIters); }
01094   // swap
01095   NodePerm.Swap(NId1, NId2);
01096   InvertPerm.Swap(NodePerm[NId1], NodePerm[NId2]);
01097   // add new LL (add nodes)
01098   LogLike = LogLike + NodeLLDelta(NId1) + NodeLLDelta(NId2);
01099   const int NewId1 = NodePerm[NId1], NewId2 = NodePerm[NId2];
01100   // correct for double-counted edges
01101   if (Graph->IsEdge(NId1, NId2)) {
01102     LogLike += + LLMtx.GetApxNoEdgeLL(NewId1, NewId2, KronIters)
01103       - LLMtx.GetEdgeLL(NewId1, NewId2, KronIters); }
01104   if (Graph->IsEdge(NId2, NId1)) {
01105     LogLike += + LLMtx.GetApxNoEdgeLL(NewId2, NewId1, KronIters)
01106       - LLMtx.GetEdgeLL(NewId2, NewId1, KronIters); }
01107   return LogLike;
01108 }
01109 
01110 // metropolis sampling from P(permutation|graph)
01111 bool TKroneckerLL::SampleNextPerm(int& NId1, int& NId2) {
01112   // pick 2 uniform nodes and swap
01113   if (TKronMtx::Rnd.GetUniDev() < PermSwapNodeProb) {
01114     NId1 = TKronMtx::Rnd.GetUniDevInt(Nodes);
01115     NId2 = TKronMtx::Rnd.GetUniDevInt(Nodes);
01116     while (NId2 == NId1) { NId2 = TKronMtx::Rnd.GetUniDevInt(Nodes); }
01117   } else {
01118     // pick uniform edge and swap endpoints (slow as it moves around high degree nodes)
01119     const int e = TKronMtx::Rnd.GetUniDevInt(GEdgeV.Len());
01120     NId1 = GEdgeV[e].Val1;  NId2 = GEdgeV[e].Val2;
01121   }
01122   const double U = TKronMtx::Rnd.GetUniDev();
01123   const double OldLL = LogLike;
01124   const double NewLL = SwapNodesLL(NId1, NId2);
01125   const double LogU = log(U);
01126   if (LogU > NewLL - OldLL) { // reject
01127     LogLike = OldLL;
01128     NodePerm.Swap(NId2, NId1); //swap back
01129         InvertPerm.Swap(NodePerm[NId2], NodePerm[NId1]); // swap back
01130     return false;
01131   }
01132   return true; // accept new sample
01133 }
01134 
01135 // exact gradient of an empty graph, O(N^2)
01136 double TKroneckerLL::GetEmptyGraphDLL(const int& ParamId) const {
01137   double DLL = 0.0;
01138   for (int NId1 = 0; NId1 < Nodes; NId1++) {
01139     for (int NId2 = 0; NId2 < Nodes; NId2++) {
01140       DLL += LLMtx.GetNoEdgeDLL(ParamId, NodePerm[NId1], NodePerm[NId2], KronIters);
01141     }
01142   }
01143   return DLL;
01144 }
01145 
01146 // approx gradient, using 2nd order Taylor approximation, O(N_0^2)
01147 double TKroneckerLL::GetApxEmptyGraphDLL(const int& ParamId) const {
01148   double Sum=0.0, SumSq=0.0;
01149   for (int i = 0; i < ProbMtx.Len(); i++) {
01150     Sum += ProbMtx.At(i);
01151     SumSq += TMath::Sqr(ProbMtx.At(i));
01152   }
01153   // d/dx -sum(x_i) - 0.5sum(x_i^2) = d/dx sum(theta)^k - 0.5 sum(theta^2)^k
01154   return -KronIters*pow(Sum, KronIters-1) - KronIters*pow(SumSq, KronIters-1)*ProbMtx.At(ParamId);
01155 }
01156 
01157 // exact graph gradient, runs O(N^2)
01158 const TFltV& TKroneckerLL::CalcGraphDLL() {
01159   for (int ParamId = 0; ParamId < LLMtx.Len(); ParamId++) {
01160     double DLL = 0.0;
01161     for (int NId1 = 0; NId1 < Nodes; NId1++) {
01162       for (int NId2 = 0; NId2 < Nodes; NId2++) {
01163         if (Graph->IsEdge(NId1, NId2)) {
01164           DLL += LLMtx.GetEdgeDLL(ParamId, NodePerm[NId1], NodePerm[NId2], KronIters);
01165         } else {
01166           DLL += LLMtx.GetNoEdgeDLL(ParamId, NodePerm[NId1], NodePerm[NId2], KronIters);
01167         }
01168       }
01169     }
01170     GradV[ParamId] = DLL;
01171   }
01172   return GradV;
01173 }
01174 
01175 // slow (but correct) approximate gradient, runs O(N^2)
01176 const TFltV& TKroneckerLL::CalcFullApxGraphDLL() {
01177   for (int ParamId = 0; ParamId < LLMtx.Len(); ParamId++) {
01178     double DLL = 0.0;
01179     for (int NId1 = 0; NId1 < Nodes; NId1++) {
01180       for (int NId2 = 0; NId2 < Nodes; NId2++) {
01181         if (Graph->IsEdge(NId1, NId2)) {
01182           DLL += LLMtx.GetEdgeDLL(ParamId, NodePerm[NId1], NodePerm[NId2], KronIters);
01183         } else {
01184           DLL += LLMtx.GetApxNoEdgeDLL(ParamId, NodePerm[NId1], NodePerm[NId2], KronIters);
01185         }
01186       }
01187     }
01188     GradV[ParamId] = DLL;
01189   }
01190   return GradV;
01191 }
01192 
01193 // fast approximate gradient, runs O(E)
01194 const TFltV& TKroneckerLL::CalcApxGraphDLL() {
01195   for (int ParamId = 0; ParamId < LLMtx.Len(); ParamId++) {
01196     double DLL = GetApxEmptyGraphDLL(ParamId);
01197     for (int nid = 0; nid < Nodes; nid++) {
01198       const TNGraph::TNodeI Node = Graph->GetNI(nid);
01199       const int SrcNId = NodePerm[nid];
01200       for (int e = 0; e < Node.GetOutDeg(); e++) {
01201         const int DstNId = NodePerm[Node.GetOutNId(e)];
01202         DLL = DLL - LLMtx.GetApxNoEdgeDLL(ParamId, SrcNId, DstNId, KronIters)
01203           + LLMtx.GetEdgeDLL(ParamId, SrcNId, DstNId, KronIters);
01204       }
01205     }
01206     GradV[ParamId] = DLL;
01207   }
01208   return GradV;
01209 }
01210 
01211 // Used in TKroneckerLL::UpdateGraphDLL: DeltaDLL if we
01212 // add the node to the empty matrix/graph (node
01213 // gets/creates all of its in- and out-edges).
01214 double TKroneckerLL::NodeDLLDelta(const int ParamId, const int& NId) const {
01215   if (! Graph->IsNode(NId)) { return 0.0; } // zero degree node
01216   double Delta = 0.0;
01217   const TNGraph::TNodeI Node = Graph->GetNI(NId);
01218   const int SrcRow = NodePerm[NId];
01219   for (int e = 0; e < Node.GetOutDeg(); e++) {
01220     const int DstCol = NodePerm[Node.GetOutNId(e)];
01221     Delta += - LLMtx.GetApxNoEdgeDLL(ParamId, SrcRow, DstCol, KronIters)
01222       + LLMtx.GetEdgeDLL(ParamId, SrcRow, DstCol, KronIters);
01223   }
01224   const int SrcCol = NodePerm[NId];
01225   for (int e = 0; e < Node.GetInDeg(); e++) {
01226     const int DstRow = NodePerm[Node.GetInNId(e)];
01227     Delta += - LLMtx.GetApxNoEdgeDLL(ParamId, DstRow, SrcCol, KronIters)
01228       + LLMtx.GetEdgeDLL(ParamId, DstRow, SrcCol, KronIters);
01229   }
01230   // double counter self-edge
01231   if (Graph->IsEdge(NId, NId)) {
01232     Delta += + LLMtx.GetApxNoEdgeDLL(ParamId, SrcRow, SrcCol, KronIters)
01233       - LLMtx.GetEdgeDLL(ParamId, SrcRow, SrcCol, KronIters);
01234     IAssert(SrcRow == SrcCol);
01235   }
01236   return Delta;
01237 }
01238 
01239 // given old DLL and new permutation, efficiently updates the DLL
01240 // permutation is new, but DLL is old
01241 void TKroneckerLL::UpdateGraphDLL(const int& SwapNId1, const int& SwapNId2) {
01242   for (int ParamId = 0; ParamId < LLMtx.Len(); ParamId++) {
01243     // permutation before the swap (swap back to previous position)
01244     NodePerm.Swap(SwapNId1, SwapNId2);
01245     // subtract old DLL
01246     TFlt& DLL = GradV[ParamId];
01247     DLL = DLL - NodeDLLDelta(ParamId, SwapNId1) - NodeDLLDelta(ParamId, SwapNId2);
01248     // double-counted edges
01249     const int PrevId1 = NodePerm[SwapNId1], PrevId2 = NodePerm[SwapNId2];
01250     if (Graph->IsEdge(SwapNId1, SwapNId2)) {
01251       DLL += - LLMtx.GetApxNoEdgeDLL(ParamId, PrevId1, PrevId2, KronIters)
01252         + LLMtx.GetEdgeDLL(ParamId, PrevId1, PrevId2, KronIters); }
01253     if (Graph->IsEdge(SwapNId2, SwapNId1)) {
01254       DLL += - LLMtx.GetApxNoEdgeDLL(ParamId, PrevId2, PrevId1, KronIters)
01255         + LLMtx.GetEdgeDLL(ParamId, PrevId2, PrevId1, KronIters); }
01256     // permutation after the swap (restore the swap)
01257     NodePerm.Swap(SwapNId1, SwapNId2);
01258     // add new DLL
01259     DLL = DLL + NodeDLLDelta(ParamId, SwapNId1) + NodeDLLDelta(ParamId, SwapNId2);
01260     const int NewId1 = NodePerm[SwapNId1], NewId2 = NodePerm[SwapNId2];
01261     // double-counted edges
01262     if (Graph->IsEdge(SwapNId1, SwapNId2)) {
01263       DLL += + LLMtx.GetApxNoEdgeDLL(ParamId, NewId1, NewId2, KronIters)
01264         - LLMtx.GetEdgeDLL(ParamId, NewId1, NewId2, KronIters); }
01265     if (Graph->IsEdge(SwapNId2, SwapNId1)) {
01266       DLL += + LLMtx.GetApxNoEdgeDLL(ParamId, NewId2, NewId1, KronIters)
01267         - LLMtx.GetEdgeDLL(ParamId, NewId2, NewId1, KronIters); }
01268   }
01269 }
01270 
01271 void TKroneckerLL::SampleGradient(const int& WarmUp, const int& NSamples, double& AvgLL, TFltV& AvgGradV) {
01272   printf("SampleGradient: %s (%s warm-up):", TInt::GetMegaStr(NSamples).CStr(), TInt::GetMegaStr(WarmUp).CStr());
01273   int NId1=0, NId2=0, NAccept=0;
01274   TExeTm ExeTm1;
01275   if (WarmUp > 0) {
01276     CalcApxGraphLL();
01277     for (int s = 0; s < WarmUp; s++) { SampleNextPerm(NId1, NId2); }
01278     printf("  warm-up:%s,", ExeTm1.GetTmStr());  ExeTm1.Tick();
01279   }
01280   CalcApxGraphLL(); // re-calculate LL (due to numerical errors)
01281   CalcApxGraphDLL();
01282   AvgLL = 0;
01283   AvgGradV.Gen(LLMtx.Len());  AvgGradV.PutAll(0.0);
01284   printf("  sampl");
01285   for (int s = 0; s < NSamples; s++) {
01286     if (SampleNextPerm(NId1, NId2)) { // new permutation
01287       UpdateGraphDLL(NId1, NId2);  NAccept++; }
01288     for (int m = 0; m < LLMtx.Len(); m++) { AvgGradV[m] += GradV[m]; }
01289     AvgLL += GetLL();
01290   }
01291   printf("ing");
01292   AvgLL = AvgLL / double(NSamples);
01293   for (int m = 0; m < LLMtx.Len(); m++) {
01294     AvgGradV[m] = AvgGradV[m] / double(NSamples); }
01295   printf(":%s (%.0f/s), accept %.1f%%\n", ExeTm1.GetTmStr(), double(NSamples)/ExeTm1.GetSecs(),
01296     double(100*NAccept)/double(NSamples));
01297 }
01298 
01299 double TKroneckerLL::GradDescent(const int& NIter, const double& LrnRate, double MnStep, double MxStep, const int& WarmUp, const int& NSamples) {
01300   printf("\n----------------------------------------------------------------------\n");
01301   printf("Fitting graph on %d nodes, %d edges\n", Graph->GetNodes(), Graph->GetEdges());
01302   printf("Kron iters:  %d (== %d nodes)\n\n", KronIters(), ProbMtx.GetNodes(KronIters()));
01303   TExeTm IterTm, TotalTm;
01304   double OldLL=-1e10, CurLL=0;
01305   const double EZero = pow((double) Graph->GetEdges(), 1.0/double(KronIters));
01306   TFltV CurGradV, LearnRateV(GetParams()), LastStep(GetParams());
01307   LearnRateV.PutAll(LrnRate);
01308   TKronMtx NewProbMtx = ProbMtx;
01309 
01310   if(DebugMode) {  
01311           LLV.Gen(NIter, 0);
01312           MtxV.Gen(NIter, 0);
01313   }
01314 
01315   for (int Iter = 0; Iter < NIter; Iter++) {
01316     printf("%03d] ", Iter);
01317     SampleGradient(WarmUp, NSamples, CurLL, CurGradV);
01318     for (int p = 0; p < GetParams(); p++) {
01319       LearnRateV[p] *= 0.95;
01320       if (Iter < 1) {
01321         while (fabs(LearnRateV[p]*CurGradV[p]) > MxStep) { LearnRateV[p] *= 0.95; }
01322         while (fabs(LearnRateV[p]*CurGradV[p]) < 0.02) { LearnRateV[p] *= (1.0/0.95); } // move more
01323       } else {
01324         // set learn rate so that move for each parameter is inside the [MnStep, MxStep]
01325         while (fabs(LearnRateV[p]*CurGradV[p]) > MxStep) { LearnRateV[p] *= 0.95; printf(".");}
01326         while (fabs(LearnRateV[p]*CurGradV[p]) < MnStep) { LearnRateV[p] *= (1.0/0.95); printf("*");}
01327         if (MxStep > 3*MnStep) { MxStep *= 0.95; }
01328       }
01329       NewProbMtx.At(p) = ProbMtx.At(p) + LearnRateV[p]*CurGradV[p];
01330       if (NewProbMtx.At(p) > 0.9999) { NewProbMtx.At(p)=0.9999; }
01331       if (NewProbMtx.At(p) < 0.0001) { NewProbMtx.At(p)=0.0001; }
01332     }
01333     printf("  trueE0: %.2f (%d),  estE0: %.2f (%d),  ERR: %f\n", EZero, Graph->GetEdges(),
01334       ProbMtx.GetMtxSum(), ProbMtx.GetEdges(KronIters), fabs(EZero-ProbMtx.GetMtxSum()));
01335     printf("  currLL: %.4f, deltaLL: %.4f\n", CurLL, CurLL-OldLL); // positive is good
01336     for (int p = 0; p < GetParams(); p++) {
01337       printf("    %d]  %f  <--  %f + %9f   Grad: %9.1f   Rate: %g\n", p, NewProbMtx.At(p),
01338         ProbMtx.At(p), (double)(LearnRateV[p]*CurGradV[p]), CurGradV[p](), LearnRateV[p]());
01339     }
01340     if (Iter+1 < NIter) { // skip last update
01341       ProbMtx = NewProbMtx;  ProbMtx.GetLLMtx(LLMtx); }
01342     OldLL=CurLL;
01343     printf("\n");  fflush(stdout);
01344 
01345         if(DebugMode) {  
01346                 LLV.Add(CurLL);
01347                 MtxV.Add(NewProbMtx);
01348         }
01349   }
01350   printf("TotalExeTm: %s %g\n", TotalTm.GetStr(), TotalTm.GetSecs());
01351   ProbMtx.Dump("FITTED PARAMS", false);
01352   return CurLL;
01353 }
01354 
01355 double TKroneckerLL::GradDescent2(const int& NIter, const double& LrnRate, double MnStep, double MxStep, const int& WarmUp, const int& NSamples) {
01356   printf("\n----------------------------------------------------------------------\n");
01357   printf("GradDescent2\n");
01358   printf("Fitting graph on %d nodes, %d edges\n", Graph->GetNodes(), Graph->GetEdges());
01359   printf("Skip moves that make likelihood smaller\n");
01360   printf("Kron iters:  %d (== %d nodes)\n\n", KronIters(), ProbMtx.GetNodes(KronIters()));
01361   TExeTm IterTm, TotalTm;
01362   double CurLL=0, NewLL=0;
01363   const double EZero = pow((double) Graph->GetEdges(), 1.0/double(KronIters));
01364   TFltV CurGradV, NewGradV, LearnRateV(GetParams()), LastStep(GetParams());
01365   LearnRateV.PutAll(LrnRate);
01366   TKronMtx NewProbMtx=ProbMtx, CurProbMtx=ProbMtx;
01367   bool GoodMove = false;
01368   // Start
01369   for (int Iter = 0; Iter < NIter; Iter++) {
01370     printf("%03d] ", Iter);
01371     if (! GoodMove) { SampleGradient(WarmUp, NSamples, CurLL, CurGradV); }
01372     CurProbMtx = ProbMtx;
01373     // update parameters
01374     for (int p = 0; p < GetParams(); p++) {
01375       while (fabs(LearnRateV[p]*CurGradV[p]) > MxStep) { LearnRateV[p] *= 0.95; printf(".");}
01376       while (fabs(LearnRateV[p]*CurGradV[p]) < MnStep) { LearnRateV[p] *= (1.0/0.95); printf("*");}
01377       NewProbMtx.At(p) = CurProbMtx.At(p) + LearnRateV[p]*CurGradV[p];
01378       if (NewProbMtx.At(p) > 0.9999) { NewProbMtx.At(p)=0.9999; }
01379       if (NewProbMtx.At(p) < 0.0001) { NewProbMtx.At(p)=0.0001; }
01380       LearnRateV[p] *= 0.95;
01381     }
01382     printf("  ");
01383     ProbMtx=NewProbMtx;  ProbMtx.GetLLMtx(LLMtx);
01384     SampleGradient(WarmUp, NSamples, NewLL, NewGradV);
01385     if (NewLL > CurLL) { // accept the move
01386       printf("== Good move:\n");
01387       printf("  trueE0: %.2f (%d),  estE0: %.2f (%d),  ERR: %f\n", EZero, Graph->GetEdges(),
01388         ProbMtx.GetMtxSum(), ProbMtx.GetEdges(KronIters), fabs(EZero-ProbMtx.GetMtxSum()));
01389       printf("  currLL: %.4f  deltaLL: %.4f\n", CurLL, NewLL-CurLL); // positive is good
01390       for (int p = 0; p < GetParams(); p++) {
01391         printf("    %d]  %f  <--  %f + %9f   Grad: %9.1f   Rate: %g\n", p, NewProbMtx.At(p),
01392           CurProbMtx.At(p), (double)(LearnRateV[p]*CurGradV[p]), CurGradV[p](), LearnRateV[p]()); }
01393       CurLL = NewLL;
01394       CurGradV = NewGradV;
01395       GoodMove = true;
01396     } else {
01397       printf("** BAD move:\n");
01398       printf("  *trueE0: %.2f (%d),  estE0: %.2f (%d),  ERR: %f\n", EZero, Graph->GetEdges(),
01399         ProbMtx.GetMtxSum(), ProbMtx.GetEdges(KronIters), fabs(EZero-ProbMtx.GetMtxSum()));
01400       printf("  *curLL:  %.4f  deltaLL: %.4f\n", CurLL, NewLL-CurLL); // positive is good
01401       for (int p = 0; p < GetParams(); p++) {
01402         printf("   b%d]  %f  <--  %f + %9f   Grad: %9.1f   Rate: %g\n", p, NewProbMtx.At(p),
01403           CurProbMtx.At(p), (double)(LearnRateV[p]*CurGradV[p]), CurGradV[p](), LearnRateV[p]()); }
01404       // move to old position
01405       ProbMtx = CurProbMtx;  ProbMtx.GetLLMtx(LLMtx);
01406       GoodMove = false;
01407     }
01408     printf("\n");  fflush(stdout);
01409   }
01410   printf("TotalExeTm: %s %g\n", TotalTm.GetStr(), TotalTm.GetSecs());
01411   ProbMtx.Dump("FITTED PARAMS\n", false);
01412   return CurLL;
01413 }
01414 
01416 // filling in random edges for KronEM
01417 void TKroneckerLL::SetRandomEdges(const int& NEdges, const bool isDir) {
01418         int count = 0, added = 0, collision = 0;
01419         const int MtxDim = ProbMtx.GetDim();
01420         const double MtxSum = ProbMtx.GetMtxSum();
01421         TVec<TFltIntIntTr> ProbToRCPosV; // row, col position
01422         double CumProb = 0.0;
01423 
01424         for(int r = 0; r < MtxDim; r++) {
01425                 for(int c = 0; c < MtxDim; c++) {
01426                         const double Prob = ProbMtx.At(r, c);
01427                         if (Prob > 0.0) {
01428                                 CumProb += Prob;
01429                                 ProbToRCPosV.Add(TFltIntIntTr(CumProb/MtxSum, r, c));
01430                         }
01431                 }
01432         }
01433 
01434         int Rng, Row, Col, n, NId1, NId2;
01435         while(added < NEdges) {
01436                 Rng = Nodes;    Row = 0;        Col = 0;
01437                 for (int iter = 0; iter < KronIters; iter++) {
01438                         const double& Prob = TKronMtx::Rnd.GetUniDev();
01439                         n = 0; while(Prob > ProbToRCPosV[n].Val1) { n++; }
01440                         const int MtxRow = ProbToRCPosV[n].Val2;
01441                         const int MtxCol = ProbToRCPosV[n].Val3;
01442                         Rng /= MtxDim;
01443                         Row += MtxRow * Rng;
01444                         Col += MtxCol * Rng;
01445                 }
01446 
01447                 count++;
01448 
01449                 NId1 = InvertPerm[Row]; NId2 = InvertPerm[Col];
01450 
01451                 //      Check conflicts
01452                 if(EMType != kronEdgeMiss && IsObsEdge(NId1, NId2)) {
01453                         continue;
01454                 }
01455 
01456                 if (! Graph->IsEdge(NId1, NId2)) {
01457                         Graph->AddEdge(NId1, NId2);
01458                         if(NId1 != NId2)        { GEdgeV.Add(TIntTr(NId1, NId2, LEdgeV.Len())); }
01459                         else { LSelfEdge++; }
01460                         LEdgeV.Add(TIntTr(NId1, NId2, GEdgeV.Len()-1));
01461                         added++;
01462                         if (! isDir) {
01463                                 if (NId1 != NId2) {
01464                                    Graph->AddEdge(NId2, NId1);
01465                                    GEdgeV.Add(TIntTr(NId2, NId1, LEdgeV.Len()));
01466                                    LEdgeV.Add(TIntTr(NId2, NId1, GEdgeV.Len()-1));
01467                                    added++;
01468                                 }
01469                         }
01470                 } else { collision ++; }
01471         }
01472 //      printf("total = %d / added = %d / collision = %d\n", count, added, collision);
01473 }
01474 
01475 // sampling setup for KronEM
01476 void TKroneckerLL::MetroGibbsSampleSetup(const int& WarmUp) {
01477         double alpha = log(ProbMtx.GetMtxSum()) / log(double(ProbMtx.GetDim()));
01478         int NId1 = 0, NId2 = 0;
01479         int NMissing;
01480 
01481         RestoreGraph(false);
01482         if(EMType == kronEdgeMiss) {
01483                 CalcApxGraphLL();
01484                 for (int s = 0; s < WarmUp; s++)        SampleNextPerm(NId1, NId2);
01485         }
01486 
01487         if(EMType == kronFutureLink) {
01488                 NMissing = (int) (pow(ProbMtx.GetMtxSum(), KronIters) - pow(double(RealNodes), alpha));
01489         } else if(EMType == kronEdgeMiss) {
01490                 NMissing = MissEdges;
01491         } else {
01492                 NMissing = (int) (pow(ProbMtx.GetMtxSum(), KronIters) * (1.0 - pow(double(RealNodes) / double(Nodes), 2)));
01493         }
01494         NMissing = (NMissing < 1) ? 1 : NMissing;
01495 
01496         SetRandomEdges(NMissing, true);
01497 
01498         CalcApxGraphLL();
01499         for (int s = 0; s < WarmUp; s++)        SampleNextPerm(NId1, NId2);
01500 }
01501 
01502 // Metropolis-Hastings steps for KronEM
01503 void TKroneckerLL::MetroGibbsSampleNext(const int& WarmUp, const bool DLLUpdate) {
01504         int NId1 = 0, NId2 = 0, hit = 0, GId = 0;
01505         TIntTr EdgeToRemove, NewEdge;
01506         double RndAccept;
01507 
01508         if(LEdgeV.Len()) {
01509                 for(int i = 0; i < WarmUp; i++) {
01510                         hit = TKronMtx::Rnd.GetUniDevInt(LEdgeV.Len());
01511 
01512                         NId1 = LEdgeV[hit].Val1;        NId2 = LEdgeV[hit].Val2;
01513                         GId = LEdgeV[hit].Val3;
01514                         SetRandomEdges(1, true);
01515                         NewEdge = LEdgeV.Last();
01516 
01517                         RndAccept = (1.0 - exp(LLMtx.GetEdgeLL(NewEdge.Val1, NewEdge.Val2, KronIters))) / (1.0 - exp(LLMtx.GetEdgeLL(NId1, NId2, KronIters)));
01518                         RndAccept = (RndAccept > 1.0) ? 1.0 : RndAccept;
01519 
01520                         if(TKronMtx::Rnd.GetUniDev() > RndAccept) { //  reject
01521                                 Graph->DelEdge(NewEdge.Val1, NewEdge.Val2);
01522                                 if(NewEdge.Val1 != NewEdge.Val2) {      GEdgeV.DelLast();       }
01523                                 else {  LSelfEdge--;    }
01524                                 LEdgeV.DelLast();
01525                         } else {        //      accept
01526                                 Graph->DelEdge(NId1, NId2);
01527                                 LEdgeV[hit] = LEdgeV.Last();
01528                                 LEdgeV.DelLast();
01529                                 if(NId1 == NId2) {
01530                                         LSelfEdge--;
01531                                         if(NewEdge.Val1 != NewEdge.Val2) {
01532                                                 GEdgeV[GEdgeV.Len()-1].Val3 = hit;
01533                                         }
01534                                 } else {
01535                                         IAssertR(GEdgeV.Last().Val3 >= 0, "Invalid indexing");
01536 
01537                                         GEdgeV[GId] = GEdgeV.Last();
01538                                         if(NewEdge.Val1 != NewEdge.Val2) {
01539                                                 GEdgeV[GId].Val3 = hit;
01540                                         }
01541                                         LEdgeV[GEdgeV[GId].Val3].Val3 = GId;
01542                                         GEdgeV.DelLast();
01543                                 }
01544 
01545                         LogLike += LLMtx.GetApxNoEdgeLL(EdgeToRemove.Val1, EdgeToRemove.Val2, KronIters) - LLMtx.GetEdgeLL(EdgeToRemove.Val1, EdgeToRemove.Val2, KronIters);
01546                         LogLike += -LLMtx.GetApxNoEdgeLL(NewEdge.Val1, NewEdge.Val2, KronIters) + LLMtx.GetEdgeLL(NewEdge.Val1, NewEdge.Val2, KronIters);
01547 
01548                                 if(DLLUpdate) {
01549                                         for (int p = 0; p < LLMtx.Len(); p++) {
01550                                                 GradV[p] += LLMtx.GetApxNoEdgeDLL(p, EdgeToRemove.Val1, EdgeToRemove.Val2, KronIters) - LLMtx.GetEdgeDLL(p, EdgeToRemove.Val1, EdgeToRemove.Val2, KronIters);
01551                                                 GradV[p] += -LLMtx.GetApxNoEdgeDLL(p, NewEdge.Val1, NewEdge.Val2, KronIters) + LLMtx.GetEdgeDLL(p, NewEdge.Val1, NewEdge.Val2, KronIters);
01552                                         }
01553                                 }
01554                         }
01555                 }
01556         }
01557 
01558 //      CalcApxGraphLL();
01559         for (int s = 0; s < WarmUp; s++) {
01560                 if(SampleNextPerm(NId1, NId2)) {
01561                         if(DLLUpdate)   UpdateGraphDLL(NId1, NId2);
01562                 }
01563         }
01564 }
01565 
01566 // E-step in KronEM
01567 void TKroneckerLL::RunEStep(const int& GibbsWarmUp, const int& WarmUp, const int& NSamples, TFltV& LLV, TVec<TFltV>& DLLV) {
01568         TExeTm ExeTm, TotalTm;
01569         LLV.Gen(NSamples, 0);
01570         DLLV.Gen(NSamples, 0);
01571 
01572         ExeTm.Tick();
01573         for(int i = 0; i < 2; i++)      MetroGibbsSampleSetup(WarmUp);
01574         printf("  Warm-Up [%u] : %s\n", WarmUp, ExeTm.GetTmStr());
01575         CalcApxGraphLL();
01576         for(int i = 0; i < GibbsWarmUp; i++)    MetroGibbsSampleNext(10, false);
01577         printf("  Gibbs Warm-Up [%u] : %s\n", GibbsWarmUp, ExeTm.GetTmStr());
01578 
01579         ExeTm.Tick();
01580         CalcApxGraphLL();
01581         CalcApxGraphDLL();
01582         for(int i = 0; i < NSamples; i++) {
01583                 MetroGibbsSampleNext(50, false);
01584 
01585                 LLV.Add(LogLike);
01586                 DLLV.Add(GradV);
01587 
01588                 int OnePercent = (i+1) % (NSamples / 10);
01589                 if(OnePercent == 0) {
01590                         int TenPercent = ((i+1) / (NSamples / 10)) * 10;
01591                         printf("  %3u%% done : %s\n", TenPercent, ExeTm.GetTmStr());
01592                 }
01593         }
01594 }
01595 
01596 // M-step in KronEM
01597 double TKroneckerLL::RunMStep(const TFltV& LLV, const TVec<TFltV>& DLLV, const int& GradIter, const double& LrnRate, double MnStep, double MxStep) {
01598         TExeTm IterTm, TotalTm;
01599         double OldLL=LogLike, CurLL=0;
01600         const double alpha = log(double(RealEdges)) / log(double(RealNodes));
01601         const double EZero = pow(double(ProbMtx.GetDim()), alpha);
01602 
01603         TFltV CurGradV(GetParams()), LearnRateV(GetParams()), LastStep(GetParams());
01604         LearnRateV.PutAll(LrnRate);
01605 
01606         TKronMtx NewProbMtx = ProbMtx;
01607         const int NSamples = LLV.Len();
01608         const int ReCalcLen = NSamples / 10;
01609 
01610         for (int s = 0; s < LLV.Len(); s++) {
01611                 CurLL += LLV[s];
01612                 for(int p = 0; p < GetParams(); p++) { CurGradV[p] += DLLV[s][p]; }
01613         }
01614         CurLL /= NSamples;
01615         for(int p = 0; p < GetParams(); p++) { CurGradV[p] /= NSamples; }
01616 
01617         double MaxLL = CurLL;
01618         TKronMtx MaxProbMtx = ProbMtx;
01619         TKronMtx OldProbMtx = ProbMtx;
01620 
01621         for (int Iter = 0; Iter < GradIter; Iter++) {
01622                 printf("    %03d] ", Iter+1);
01623                 IterTm.Tick();
01624 
01625                 for (int p = 0; p < GetParams(); p++) {
01626                         if (Iter < 1) {
01627                                 while (fabs(LearnRateV[p]*CurGradV[p]) > MxStep) { LearnRateV[p] *= 0.95; }
01628                                 while (fabs(LearnRateV[p]*CurGradV[p]) < 5 * MnStep) { LearnRateV[p] *= (1.0/0.95); } // move more
01629                         } else {
01630                         // set learn rate so that move for each parameter is inside the [MnStep, MxStep]
01631                                 while (fabs(LearnRateV[p]*CurGradV[p]) > MxStep) { LearnRateV[p] *= 0.95; printf(".");}
01632                                 while (fabs(LearnRateV[p]*CurGradV[p]) < MnStep) { LearnRateV[p] *= (1.0/0.95); printf("*");}
01633                                 if (MxStep > 3*MnStep) { MxStep *= 0.95; }
01634                         }
01635                         NewProbMtx.At(p) = ProbMtx.At(p) + LearnRateV[p]*CurGradV[p];
01636                         if (NewProbMtx.At(p) > 0.9999) { NewProbMtx.At(p)=0.9999; }
01637                         if (NewProbMtx.At(p) < 0.0001) { NewProbMtx.At(p)=0.0001; }
01638                         LearnRateV[p] *= 0.95;
01639                 }
01640                 printf("  trueE0: %.2f (%u from %u),  estE0: %.2f (%u from %u),  ERR: %f\n", EZero, RealEdges(), RealNodes(), ProbMtx.GetMtxSum(), Graph->GetEdges(), Graph->GetNodes(), fabs(EZero-ProbMtx.GetMtxSum()));
01641                 printf("      currLL: %.4f, deltaLL: %.4f\n", CurLL, CurLL-OldLL); // positive is good
01642                 for (int p = 0; p < GetParams(); p++) {
01643                         printf("      %d]  %f  <--  %f + %9f   Grad: %9.1f   Rate: %g\n", p, NewProbMtx.At(p),
01644                         ProbMtx.At(p), (double)(LearnRateV[p]*CurGradV[p]), CurGradV[p](), LearnRateV[p]());
01645                 }
01646 
01647                 OldLL=CurLL;
01648                 if(Iter == GradIter - 1) {
01649                         break;
01650                 }
01651 
01652                 CurLL = 0;
01653                 CurGradV.PutAll(0.0);
01654                 TFltV OneDLL;
01655 
01656                 CalcApxGraphLL();
01657                 CalcApxGraphDLL();
01658 
01659                 for(int s = 0; s < NSamples; s++) {
01660                         ProbMtx = OldProbMtx;  ProbMtx.GetLLMtx(LLMtx);
01661                         MetroGibbsSampleNext(10, true);
01662                         ProbMtx = NewProbMtx;  ProbMtx.GetLLMtx(LLMtx);
01663                         if(s % ReCalcLen == ReCalcLen/2) {
01664                                 CurLL += CalcApxGraphLL();
01665                                 OneDLL = CalcApxGraphDLL();
01666                         } else {
01667                                 CurLL += LogLike;
01668                                 OneDLL = GradV;
01669                         }
01670                         for(int p = 0; p < GetParams(); p++) {
01671                                 CurGradV[p] += OneDLL[p];
01672                         }
01673                 }
01674                 CurLL /= NSamples;
01675 
01676                 if(MaxLL < CurLL) {
01677                         MaxLL = CurLL;  MaxProbMtx = ProbMtx;
01678                 }
01679 
01680                 printf("    Time: %s\n", IterTm.GetTmStr());
01681                 printf("\n");  fflush(stdout);
01682         }
01683         ProbMtx = MaxProbMtx;   ProbMtx.GetLLMtx(LLMtx);
01684 
01685         printf("    FinalLL : %f,   TotalExeTm: %s\n", MaxLL, TotalTm.GetTmStr());
01686         ProbMtx.Dump("    FITTED PARAMS", false);
01687 
01688         return MaxLL;
01689 }
01690 
01691 // KronEM
01692 void TKroneckerLL::RunKronEM(const int& EMIter, const int& GradIter, double LrnRate, double MnStep, double MxStep, const int& GibbsWarmUp, const int& WarmUp, const int& NSamples, const TKronEMType& Type, const int& NMissing) {
01693         printf("\n----------------------------------------------------------------------\n");
01694         printf("Fitting graph on %d nodes, %d edges\n", int(RealNodes), int(RealEdges));
01695         printf("Kron iters:  %d (== %d nodes)\n\n", KronIters(), ProbMtx.GetNodes(KronIters()));
01696 
01697         TFltV LLV(NSamples);
01698         TVec<TFltV> DLLV(NSamples);
01699         //int count = 0;
01700 
01701         EMType = Type;
01702         MissEdges = NMissing;
01703         AppendIsoNodes();
01704         SetRndPerm();
01705 
01706         if(DebugMode) {
01707                 LLV.Gen(EMIter, 0);
01708                 MtxV.Gen(EMIter, 0);
01709         }
01710 
01711         for(int i = 0; i < EMIter; i++) {
01712                 printf("\n----------------------------------------------------------------------\n");
01713                 printf("%03d EM-iter] E-Step\n", i+1);
01714                 RunEStep(GibbsWarmUp, WarmUp, NSamples, LLV, DLLV);
01715                 printf("\n\n");
01716 
01717                 printf("%03d EM-iter] M-Step\n", i+1);
01718                 double CurLL = RunMStep(LLV, DLLV, GradIter, LrnRate, MnStep, MxStep);
01719                 printf("\n\n");
01720 
01721                 if(DebugMode) {
01722                         LLV.Add(CurLL);
01723                         MtxV.Add(ProbMtx);
01724                 }
01725         }
01726 
01727         RestoreGraph();
01728 }
01729 
01730 
01731 
01732 void GetMinMax(const TFltPrV& XYValV, double& Min, double& Max, const bool& ResetMinMax) {
01733   if (ResetMinMax) { Min = TFlt::Mx;  Max = TFlt::Mn; }
01734   for (int i = 0; i < XYValV.Len(); i++) {
01735     Min = TMath::Mn(Min, XYValV[i].Val2.Val);
01736     Max = TMath::Mx(Max, XYValV[i].Val2.Val);
01737   }
01738 }
01739 
01740 void PlotGrad(const TFltPrV& EstLLV, const TFltPrV& TrueLLV, const TVec<TFltPrV>& GradVV, const TFltPrV& AcceptV, const TStr& OutFNm, const TStr& Desc) {
01741   double Min, Max, Min1, Max1;
01742   // plot log-likelihood
01743   { TGnuPlot GP("sLL-"+OutFNm, TStr::Fmt("Log-likelihood (avg 1k samples). %s", Desc.CStr()), true);
01744   GP.AddPlot(EstLLV, gpwLines, "Esimated LL", "linewidth 1");
01745   if (! TrueLLV.Empty()) { GP.AddPlot(TrueLLV, gpwLines, "TRUE LL", "linewidth 1"); }
01746   //GetMinMax(EstLLV, Min, Max, true);  GetMinMax(TrueLLV, Min, Max, false);
01747   //GP.SetYRange((int)floor(Min-1), (int)ceil(Max+1));
01748   GP.SetXYLabel("Sample Index (time)", "Log-likelihood");
01749   GP.SavePng(); }
01750   // plot accept
01751   { TGnuPlot GP("sAcc-"+OutFNm, TStr::Fmt("Pct. accepted rnd moves (over 1k samples). %s", Desc.CStr()), true);
01752   GP.AddPlot(AcceptV, gpwLines, "Pct accepted swaps", "linewidth 1");
01753   GP.SetXYLabel("Sample Index (time)", "Pct accept permutation swaps");
01754   GP.SavePng(); }
01755   // plot grads
01756   TGnuPlot GPAll("sGradAll-"+OutFNm, TStr::Fmt("Gradient (avg 1k samples). %s", Desc.CStr()), true);
01757   GetMinMax(GradVV[0], Min1, Max1, true);
01758   for (int g = 0; g < GradVV.Len(); g++) {
01759     GPAll.AddPlot(GradVV[g], gpwLines, TStr::Fmt("param %d", g+1), "linewidth 1");
01760     GetMinMax(GradVV[g], Min1, Max1, false);
01761     TGnuPlot GP(TStr::Fmt("sGrad%02d-", g+1)+OutFNm, TStr::Fmt("Gradient (avg 1k samples). %s", Desc.CStr()), true);
01762     GP.AddPlot(GradVV[g], gpwLines, TStr::Fmt("param id %d", g+1), "linewidth 1");
01763     GetMinMax(GradVV[g], Min, Max, true);
01764     GP.SetYRange((int)floor(Min-1), (int)ceil(Max+1));
01765     GP.SetXYLabel("Sample Index (time)", "Gradient");
01766     GP.SavePng();
01767   }
01768   GPAll.SetYRange((int)floor(Min1-1), (int)ceil(Max1+1));
01769   GPAll.SetXYLabel("Sample Index (time)", "Gradient");
01770   GPAll.SavePng();
01771 }
01772 
01773 void PlotAutoCorrelation(const TFltV& ValV, const int& MaxK, const TStr& OutFNm, const TStr& Desc) {
01774   double Avg=0.0, Var=0.0;
01775   for (int i = 0; i < ValV.Len(); i++) { Avg += ValV[i]; }
01776   Avg /= (double) ValV.Len();
01777   for (int i = 0; i < ValV.Len(); i++) { Var += TMath::Sqr(ValV[i]-Avg); }
01778   TFltPrV ACorrV;
01779   for (int k = 0; k < TMath::Mn(ValV.Len(), MaxK); k++) {
01780     double corr = 0.0;
01781     for (int i = 0; i < ValV.Len() - k; i++) {
01782       corr += (ValV[i]-Avg)*(ValV[i+k]-Avg);
01783     }
01784     ACorrV.Add(TFltPr(k, corr/Var));
01785   }
01786   // plot grads
01787   TGnuPlot GP("sAutoCorr-"+OutFNm, TStr::Fmt("AutoCorrelation (%d samples). %s", ValV.Len(), Desc.CStr()), true);
01788   GP.AddPlot(ACorrV, gpwLines, "", "linewidth 1");
01789   GP.SetXYLabel("Lag, k", "Autocorrelation, r_k");
01790   GP.SavePng();
01791 }
01792 
01793 // sample permutations and plot the current gradient and log-likelihood as the function
01794 // of the number of samples
01795 TFltV TKroneckerLL::TestSamplePerm(const TStr& OutFNm, const int& WarmUp, const int& NSamples, const TKronMtx& TrueMtx, const bool& DoPlot) {
01796   printf("Sample permutations: %s (warm-up: %s)\n", TInt::GetMegaStr(NSamples).CStr(), TInt::GetMegaStr(WarmUp).CStr());
01797   int NId1=0, NId2=0, NAccept=0;
01798   TExeTm ExeTm;
01799   const int PlotLen = NSamples/1000+1;
01800   double TrueLL=-1, AvgLL=0.0;
01801   TFltV AvgGradV(GetParams());
01802   TFltPrV TrueLLV(PlotLen, 0); // true log-likelihood (under the correct permutation)
01803   TFltPrV EstLLV(PlotLen, 0);  // estiamted log-likelihood (averaged over last 1k permutation)
01804   TFltPrV AcceptV;             // sample acceptance ratio
01805   TFltV SampleLLV(NSamples, 0);
01806   TVec<TFltPrV> GradVV(GetParams());
01807   for (int g = 0; g < GetParams(); g++) {
01808     GradVV[g].Gen(PlotLen, 0); }
01809   if (! TrueMtx.Empty()) {
01810     TIntV PermV=NodePerm;  TKronMtx CurMtx=ProbMtx;  ProbMtx.Dump();
01811     InitLL(TrueMtx);  SetOrderPerm();  CalcApxGraphLL();  printf("TrueLL: %f\n", LogLike());
01812     TrueLL=LogLike;  InitLL(CurMtx); NodePerm=PermV;
01813   }
01814   CalcApxGraphLL();
01815   printf("LogLike at start:       %f\n", LogLike());
01816   if (WarmUp > 0) {
01817     EstLLV.Add(TFltPr(0, LogLike));
01818     if (TrueLL != -1) { TrueLLV.Add(TFltPr(0, TrueLL)); }
01819     for (int s = 0; s < WarmUp; s++) { SampleNextPerm(NId1, NId2); }
01820     printf("  warm-up:%s,", ExeTm.GetTmStr());  ExeTm.Tick();
01821   }
01822   printf("LogLike afterm warm-up: %f\n", LogLike());
01823   CalcApxGraphLL(); // re-calculate LL (due to numerical errors)
01824   CalcApxGraphDLL();
01825   EstLLV.Add(TFltPr(WarmUp, LogLike));
01826   if (TrueLL != -1) { TrueLLV.Add(TFltPr(WarmUp, TrueLL)); }
01827   printf("  recalculated:         %f\n", LogLike());
01828   // start sampling
01829   printf("  sampling (average per 1000 samples)\n");
01830   TVec<TFltV> SamplVV(5);
01831   for (int s = 0; s < NSamples; s++) {
01832     if (SampleNextPerm(NId1, NId2)) { // new permutation
01833       UpdateGraphDLL(NId1, NId2);  NAccept++; }
01834     for (int m = 0; m < AvgGradV.Len(); m++) { AvgGradV[m] += GradV[m]; }
01835     AvgLL += GetLL();
01836     SampleLLV.Add(GetLL());
01837     /*SamplVV[0].Add(GetLL()); // gives worse autocoreelation than the avg below
01838     SamplVV[1].Add(GradV[0]);
01839     SamplVV[2].Add(GradV[1]);
01840     SamplVV[3].Add(GradV[2]);
01841     SamplVV[4].Add(GradV[3]);*/
01842     if (s > 0 && s % 1000 == 0) {
01843       printf(".");
01844       for (int g = 0; g < AvgGradV.Len(); g++) {
01845         GradVV[g].Add(TFltPr(WarmUp+s, AvgGradV[g] / 1000.0)); }
01846       EstLLV.Add(TFltPr(WarmUp+s, AvgLL / 1000.0));
01847       if (TrueLL != -1) { TrueLLV.Add(TFltPr(WarmUp+s, TrueLL)); }
01848       AcceptV.Add(TFltPr(WarmUp+s, NAccept/1000.0));
01849       // better (faster decaying) autocorrelation when one takes avg. of 1000 consecutive samples
01850       /*SamplVV[0].Add(AvgLL);
01851       SamplVV[1].Add(AvgGradV[0]);
01852       SamplVV[2].Add(AvgGradV[1]);
01853       SamplVV[3].Add(AvgGradV[2]);
01854       SamplVV[4].Add(AvgGradV[3]); //*/
01855       if (s % 100000 == 0 && DoPlot) {
01856         const TStr Desc = TStr::Fmt("P(NodeSwap)=%g. Nodes: %d, Edges: %d, Params: %d, WarmUp: %s, Samples: %s", PermSwapNodeProb(),
01857           Graph->GetNodes(), Graph->GetEdges(), GetParams(), TInt::GetMegaStr(WarmUp).CStr(), TInt::GetMegaStr(NSamples).CStr());
01858         PlotGrad(EstLLV, TrueLLV, GradVV, AcceptV, OutFNm, Desc);
01859         for (int n = 0; n < SamplVV.Len(); n++) {
01860           PlotAutoCorrelation(SamplVV[n], 1000, TStr::Fmt("%s-n%d", OutFNm.CStr(), n), Desc); }
01861         printf("  samples: %d, time: %s, samples/s: %.1f\n", s, ExeTm.GetTmStr(), double(s+1)/ExeTm.GetSecs());
01862       }
01863       AvgLL = 0;  AvgGradV.PutAll(0);  NAccept=0;
01864     }
01865   }
01866   if (DoPlot) {
01867     const TStr Desc = TStr::Fmt("P(NodeSwap)=%g. Nodes: %d, Edges: %d, Params: %d, WarmUp: %s, Samples: %s", PermSwapNodeProb(),
01868       Graph->GetNodes(), Graph->GetEdges(), GetParams(), TInt::GetMegaStr(WarmUp).CStr(), TInt::GetMegaStr(NSamples).CStr());
01869     PlotGrad(EstLLV, TrueLLV, GradVV, AcceptV, OutFNm, Desc);
01870     for (int n = 0; n < SamplVV.Len(); n++) {
01871       PlotAutoCorrelation(SamplVV[n], 1000, TStr::Fmt("%s-n%d", OutFNm.CStr(), n), Desc); }
01872   }
01873   return SampleLLV; // seems to work better for potential scale reduction plot
01874 }
01875 
01876 void McMcGetAvgAvg(const TFltV& AvgJV, double& AvgAvg) {
01877   AvgAvg = 0.0;
01878   for (int j = 0; j < AvgJV.Len(); j++) {
01879     AvgAvg += AvgJV[j]; }
01880   AvgAvg /= AvgJV.Len();
01881 }
01882 
01883 void McMcGetAvgJ(const TVec<TFltV>& ChainLLV, TFltV& AvgJV) {
01884   for (int j = 0; j < ChainLLV.Len(); j++) {
01885     const TFltV& ChainV = ChainLLV[j];
01886     double Avg = 0;
01887     for (int i = 0; i < ChainV.Len(); i++) {
01888       Avg += ChainV[i];
01889     }
01890     AvgJV.Add(Avg/ChainV.Len());
01891   }
01892 }
01893 
01894 // calculates the chain potential scale reduction (see Gelman Bayesian Statistics book)
01895 double TKroneckerLL::CalcChainR2(const TVec<TFltV>& ChainLLV) {
01896   const double J = ChainLLV.Len();
01897   const double K = ChainLLV[0].Len();
01898   TFltV AvgJV;    McMcGetAvgJ(ChainLLV, AvgJV);
01899   double AvgAvg;  McMcGetAvgAvg(AvgJV, AvgAvg);
01900   IAssert(AvgJV.Len() == ChainLLV.Len());
01901   double InChainVar=0, OutChainVar=0;
01902   // between chain var
01903   for (int j = 0; j < AvgJV.Len(); j++) {
01904     OutChainVar += TMath::Sqr(AvgJV[j] - AvgAvg); }
01905   OutChainVar = OutChainVar * (K/double(J-1));
01906   printf("*** %g chains of len %g\n", J, K);
01907   printf("  ** between chain var: %f\n", OutChainVar);
01908   //within chain variance
01909   for (int j = 0; j < AvgJV.Len(); j++) {
01910     const TFltV& ChainV = ChainLLV[j];
01911     for (int k = 0; k < ChainV.Len(); k++) {
01912       InChainVar += TMath::Sqr(ChainV[k] - AvgJV[j]); }
01913   }
01914   InChainVar = InChainVar * 1.0/double(J*(K-1));
01915   printf("  ** within chain var: %f\n", InChainVar);
01916   const double PostVar = (K-1)/K * InChainVar + 1.0/K * OutChainVar;
01917   printf("  ** posterior var: %f\n", PostVar);
01918   const double ScaleRed = sqrt(PostVar/InChainVar);
01919   printf("  ** scale reduction (< 1.2): %f\n\n", ScaleRed);
01920   return ScaleRed;
01921 }
01922 
01923 // Gelman-Rubin-Brooks plot: how does potential scale reduction chainge with chain length
01924 void TKroneckerLL::ChainGelmapRubinPlot(const TVec<TFltV>& ChainLLV, const TStr& OutFNm, const TStr& Desc) {
01925   TFltPrV LenR2V; // how does potential scale reduction chainge with chain length
01926   TVec<TFltV> SmallLLV(ChainLLV.Len());
01927   const int K = ChainLLV[0].Len();
01928   const int Buckets=1000;
01929   const int BucketSz = K/Buckets;
01930   for (int b = 1; b < Buckets; b++) {
01931     const int End = TMath::Mn(BucketSz*b, K-1);
01932     for (int c = 0; c < ChainLLV.Len(); c++) {
01933       ChainLLV[c].GetSubValV(0, End, SmallLLV[c]); }
01934     LenR2V.Add(TFltPr(End, TKroneckerLL::CalcChainR2(SmallLLV)));
01935   }
01936   LenR2V.Add(TFltPr(K, TKroneckerLL::CalcChainR2(ChainLLV)));
01937   TGnuPlot::PlotValV(LenR2V, TStr::Fmt("gelman-%s", OutFNm.CStr()), TStr::Fmt("%s. %d chains of len %d. BucketSz: %d.",
01938     Desc.CStr(), ChainLLV.Len(), ChainLLV[0].Len(), BucketSz), "Chain length", "Potential scale reduction");
01939 }
01940 
01941 // given a Kronecker graph generate from TrueParam, try to recover the parameters
01942 TFltQu TKroneckerLL::TestKronDescent(const bool& DoExact, const bool& TruePerm, double LearnRate, const int& WarmUp, const int& NSamples, const TKronMtx& TrueParam) {
01943   printf("Test gradient descent on a synthetic kronecker graphs:\n");
01944   if (DoExact) { printf("  -- Exact gradient calculations\n"); }
01945   else { printf("  -- Approximate gradient calculations\n"); }
01946   if (TruePerm) { printf("  -- No permutation sampling (use true permutation)\n"); }
01947   else { printf("  -- Sample permutations (start with degree permutation)\n"); }
01948   TExeTm IterTm;
01949   int Iter;
01950   double OldLL=0, MyLL=0, AvgAbsErr, AbsSumErr;
01951   TFltV MyGradV, SDevV;
01952   TFltV LearnRateV(GetParams());  LearnRateV.PutAll(LearnRate);
01953   if (TruePerm) {
01954     SetOrderPerm();
01955   }
01956   else {
01957     /*printf("SET EIGEN VECTOR PERMUTATIONS\n");
01958     TFltV LeftSV, RightSV;
01959     TGSvd::GetSngVec(Graph, LeftSV, RightSV);
01960     TFltIntPrV V;
01961     for (int v=0; v<LeftSV.Len();v++) { V.Add(TFltIntPr(LeftSV[v], v)); }
01962     V.Sort(false);
01963     NodePerm.Gen(Nodes, 0);
01964     for (int v=0; v < V.Len();v++) { NodePerm.Add(V[v].Val2); } //*/
01965     //printf("RANDOM PERMUTATION\n");   SetRndPerm();
01966     printf("DEGREE  PERMUTATION\n");  SetDegPerm();
01967   }
01968   for (Iter = 0; Iter < 100; Iter++) {
01969     if (TruePerm) {
01970       // don't sample over permutations
01971       if (DoExact) { CalcGraphDLL();  CalcGraphLL(); } // slow, O(N^2)
01972       else { CalcApxGraphDLL();  CalcApxGraphLL(); }   // fast
01973       MyLL = LogLike;  MyGradV = GradV;
01974     } else {
01975       printf(".");
01976       // sample over permutations (approximate calculations)
01977       SampleGradient(WarmUp, NSamples, MyLL, MyGradV);
01978     }
01979     printf("%d] LL: %g, ", Iter, MyLL);
01980     AvgAbsErr = TKronMtx::GetAvgAbsErr(ProbMtx, TrueParam);
01981     AbsSumErr = fabs(ProbMtx.GetMtxSum() - TrueParam.GetMtxSum());
01982     printf("  avgAbsErr: %.4f, absSumErr: %.4f, newLL: %.2f, deltaLL: %.2f\n", AvgAbsErr, AbsSumErr, MyLL, OldLL-MyLL);
01983     for (int p = 0; p < GetParams(); p++) {
01984       // set learn rate so that move for each parameter is inside the [0.01, 0.1]
01985       LearnRateV[p] *= 0.9;
01986       //printf("%d: rate: %f   delta:%f\n", p, LearnRateV[p], fabs(LearnRateV[p]*MyGradV[p]));
01987       while (fabs(LearnRateV[p]*MyGradV[p]) > 0.1) { LearnRateV[p] *= 0.9; }
01988       //printf("   rate: %f   delta:%f\n", LearnRateV[p], fabs(LearnRateV[p]*MyGradV[p]));
01989       while (fabs(LearnRateV[p]*MyGradV[p]) < 0.001) { LearnRateV[p] *= (1.0/0.9); }
01990       //printf("   rate: %f   delta:%f\n", LearnRateV[p], fabs(LearnRateV[p]*MyGradV[p]));
01991       printf("    %d]  %f  <--  %f + %f    lrnRate:%g\n", p, ProbMtx.At(p) + LearnRateV[p]*MyGradV[p],
01992         ProbMtx.At(p), (double)(LearnRateV[p]*MyGradV[p]), LearnRateV[p]());
01993       ProbMtx.At(p) = ProbMtx.At(p) + LearnRateV[p]*MyGradV[p];
01994       // box constraints
01995       if (ProbMtx.At(p) > 0.99) { ProbMtx.At(p)=0.99; }
01996       if (ProbMtx.At(p) < 0.01) { ProbMtx.At(p)=0.01; }
01997     }
01998     ProbMtx.GetLLMtx(LLMtx);  OldLL = MyLL;
01999     if (AvgAbsErr < 0.01) { printf("***CONVERGED!\n");  break; }
02000     printf("\n");  fflush(stdout);
02001   }
02002   TrueParam.Dump("True  Thetas", true);
02003   ProbMtx.Dump("Final Thetas", true);
02004   printf("  AvgAbsErr: %f\n  AbsSumErr: %f\n  Iterations: %d\n", AvgAbsErr, AbsSumErr, Iter);
02005   printf("Iteration run time: %s, sec: %g\n\n", IterTm.GetTmStr(), IterTm.GetSecs());
02006   return TFltQu(AvgAbsErr, AbsSumErr, Iter, IterTm.GetSecs());
02007 }
02008 
02009 void PlotTrueAndEst(const TStr& OutFNm, const TStr& Desc, const TStr& YLabel, const TFltPrV& EstV, const TFltPrV& TrueV) {
02010   TGnuPlot GP(OutFNm, Desc.CStr(), true);
02011   GP.AddPlot(EstV, gpwLinesPoints, YLabel, "linewidth 1 pointtype 6 pointsize 1");
02012   if (! TrueV.Empty()) { GP.AddPlot(TrueV, gpwLines, "TRUE"); }
02013   GP.SetXYLabel("Gradient descent iterations", YLabel);
02014   GP.SavePng();
02015 }
02016 
02017 void TKroneckerLL::GradDescentConvergence(const TStr& OutFNm, const TStr& Desc1, const bool& SamplePerm, const int& NIters,
02018  double LearnRate, const int& WarmUp, const int& NSamples, const int& AvgKGraphs, const TKronMtx& TrueParam) {
02019   TExeTm IterTm;
02020   int Iter;
02021   double OldLL=0, MyLL=0, AvgAbsErr=0, AbsSumErr=0;
02022   TFltV MyGradV, SDevV;
02023   TFltV LearnRateV(GetParams());  LearnRateV.PutAll(LearnRate);
02024   TFltPrV EZeroV, DiamV, Lambda1V, Lambda2V, AvgAbsErrV, AvgLLV;
02025   TFltPrV TrueEZeroV, TrueDiamV, TrueLambda1V, TrueLambda2V, TrueLLV;
02026   TFltV SngValV;  TSnap::GetSngVals(Graph, 2, SngValV);  SngValV.Sort(false);
02027   const double TrueEZero = pow((double) Graph->GetEdges(), 1.0/double(KronIters));
02028   const double TrueEffDiam = TSnap::GetAnfEffDiam(Graph, false, 10);
02029   const double TrueLambda1 = SngValV[0];
02030   const double TrueLambda2 = SngValV[1];
02031   if (! TrueParam.Empty()) {
02032     const TKronMtx CurParam = ProbMtx;  ProbMtx.Dump();
02033     InitLL(TrueParam);  SetOrderPerm();  CalcApxGraphLL(); printf("TrueLL: %f\n", LogLike());
02034     OldLL = LogLike;  InitLL(CurParam);
02035   }
02036   const double TrueLL = OldLL;
02037   if (! SamplePerm) { SetOrderPerm(); } else { SetDegPerm(); }
02038   for (Iter = 0; Iter < NIters; Iter++) {
02039     if (! SamplePerm) {
02040       // don't sample over permutations
02041       CalcApxGraphDLL();  CalcApxGraphLL();   // fast
02042       MyLL = LogLike;  MyGradV = GradV;
02043     } else {
02044       // sample over permutations (approximate calculations)
02045       SampleGradient(WarmUp, NSamples, MyLL, MyGradV);
02046     }
02047     double SumDiam=0, SumSngVal1=0, SumSngVal2=0;
02048     for (int trial = 0; trial < AvgKGraphs; trial++) {
02049       // generate kronecker graph
02050       PNGraph KronGraph = TKronMtx::GenFastKronecker(ProbMtx, KronIters, true, 0); // approx
02051       //PNGraph KronGraph = TKronMtx::GenKronecker(ProbMtx, KronIters, true, 0); // true
02052       SngValV.Clr(true);  TSnap::GetSngVals(KronGraph, 2, SngValV);  SngValV.Sort(false);
02053       SumDiam += TSnap::GetAnfEffDiam(KronGraph, false, 10);
02054       SumSngVal1 += SngValV[0];  SumSngVal2 += SngValV[1];
02055     }
02056     // how good is the current fit
02057     AvgLLV.Add(TFltPr(Iter, MyLL));
02058     EZeroV.Add(TFltPr(Iter, ProbMtx.GetMtxSum()));
02059     DiamV.Add(TFltPr(Iter, SumDiam/double(AvgKGraphs)));
02060     Lambda1V.Add(TFltPr(Iter, SumSngVal1/double(AvgKGraphs)));
02061     Lambda2V.Add(TFltPr(Iter, SumSngVal2/double(AvgKGraphs)));
02062     TrueLLV.Add(TFltPr(Iter, TrueLL));
02063     TrueEZeroV.Add(TFltPr(Iter, TrueEZero));
02064     TrueDiamV.Add(TFltPr(Iter, TrueEffDiam));
02065     TrueLambda1V.Add(TFltPr(Iter, TrueLambda1));
02066     TrueLambda2V.Add(TFltPr(Iter, TrueLambda2));
02067     if (Iter % 10 == 0) {
02068       const TStr Desc = TStr::Fmt("%s. Iter: %d, G(%d, %d)  K(%d, %d)", Desc1.Empty()?OutFNm.CStr():Desc1.CStr(),
02069         Iter, Graph->GetNodes(), Graph->GetEdges(), ProbMtx.GetNodes(KronIters), ProbMtx.GetEdges(KronIters));
02070       PlotTrueAndEst("LL."+OutFNm, Desc, "Average LL", AvgLLV, TrueLLV);
02071       PlotTrueAndEst("E0."+OutFNm, Desc, "E0 (expected number of edges)", EZeroV, TrueEZeroV);
02072       PlotTrueAndEst("Diam."+OutFNm+"-Diam", Desc, "Effective diameter", DiamV, TrueDiamV);
02073       PlotTrueAndEst("Lambda1."+OutFNm, Desc, "Lambda 1", Lambda1V, TrueLambda1V);
02074       PlotTrueAndEst("Lambda2."+OutFNm, Desc, "Lambda 2", Lambda2V, TrueLambda2V);
02075       if (! TrueParam.Empty()) {
02076         PlotTrueAndEst("AbsErr."+OutFNm, Desc, "Average Absolute Error", AvgAbsErrV, TFltPrV()); }
02077     }
02078     if (! TrueParam.Empty()) {
02079       AvgAbsErr = TKronMtx::GetAvgAbsErr(ProbMtx, TrueParam);
02080       AvgAbsErrV.Add(TFltPr(Iter, AvgAbsErr));
02081     } else { AvgAbsErr = 1.0; }
02082     // update parameters
02083     AbsSumErr = fabs(ProbMtx.GetMtxSum() - TrueEZero);
02084     // update parameters
02085     for (int p = 0; p < GetParams(); p++) {
02086       LearnRateV[p] *= 0.99;
02087       while (fabs(LearnRateV[p]*MyGradV[p]) > 0.1) { LearnRateV[p] *= 0.99; printf(".");}
02088       while (fabs(LearnRateV[p]*MyGradV[p]) < 0.002) { LearnRateV[p] *= (1.0/0.95); printf("*");}
02089       printf("    %d]  %f  <--  %f + %9f   Grad: %9.1f,  Rate:%g\n", p, ProbMtx.At(p) + LearnRateV[p]*MyGradV[p],
02090         ProbMtx.At(p), (double)(LearnRateV[p]*MyGradV[p]), MyGradV[p](), LearnRateV[p]());
02091       ProbMtx.At(p) = ProbMtx.At(p) + LearnRateV[p]*MyGradV[p];
02092       // box constraints
02093       if (ProbMtx.At(p) > 1.0) { ProbMtx.At(p)=1.0; }
02094       if (ProbMtx.At(p) < 0.001) { ProbMtx.At(p)=0.001; }
02095     }
02096     printf("%d] LL: %g, ", Iter, MyLL);
02097     printf("  avgAbsErr: %.4f, absSumErr: %.4f, newLL: %.2f, deltaLL: %.2f\n", AvgAbsErr, AbsSumErr, MyLL, OldLL-MyLL);
02098     if (AvgAbsErr < 0.001) { printf("***CONVERGED!\n");  break; }
02099     printf("\n");  fflush(stdout);
02100     ProbMtx.GetLLMtx(LLMtx);  OldLL = MyLL;
02101   }
02102   TrueParam.Dump("True  Thetas", true);
02103   ProbMtx.Dump("Final Thetas", true);
02104   printf("  AvgAbsErr: %f\n  AbsSumErr: %f\n  Iterations: %d\n", AvgAbsErr, AbsSumErr, Iter);
02105   printf("Iteration run time: %s, sec: %g\n\n", IterTm.GetTmStr(), IterTm.GetSecs());
02106 }
02107 
02108 // given true N0, fit the parameters, get likelihood and calculate BIC (MDL), plot n0 vs. BIC
02109 void TKroneckerLL::TestBicCriterion(const TStr& OutFNm, const TStr& Desc1, const PNGraph& G, const int& GradIters,
02110  double LearnRate, const int& WarmUp, const int& NSamples, const int& TrueN0) {
02111   TFltPrV BicV, MdlV, LLV;
02112   const double rndGP = G->GetEdges()/TMath::Sqr(double(G->GetNodes()));
02113   const double RndGLL = G->GetEdges()*log(rndGP )+ (TMath::Sqr(double(G->GetNodes()))-G->GetEdges())*log(1-rndGP);
02114   LLV.Add(TFltPr(1, RndGLL));
02115   BicV.Add(TFltPr(1, -RndGLL + 0.5*TMath::Sqr(1)*log(TMath::Sqr(G->GetNodes()))));
02116   MdlV.Add(TFltPr(1, -RndGLL + 32*TMath::Sqr(1)+2*(log((double)1)+log((double)G->GetNodes()))));
02117   for (int NZero = 2; NZero < 10; NZero++) {
02118     const TKronMtx InitKronMtx = TKronMtx::GetInitMtx(NZero, G->GetNodes(), G->GetEdges());
02119     InitKronMtx.Dump("INIT PARAM", true);
02120     TKroneckerLL KronLL(G, InitKronMtx);
02121     KronLL.SetPerm('d'); // degree perm
02122     const double LastLL = KronLL.GradDescent(GradIters, LearnRate, 0.001, 0.01, WarmUp, NSamples);
02123     LLV.Add(TFltPr(NZero, LastLL));
02124     BicV.Add(TFltPr(NZero, -LastLL + 0.5*TMath::Sqr(NZero)*log(TMath::Sqr(G->GetNodes()))));
02125     MdlV.Add(TFltPr(NZero, -LastLL + 32*TMath::Sqr(NZero)+2*(log((double)NZero)+log((double)KronLL.GetKronIters()))));
02126     { TGnuPlot GP("LL-"+OutFNm, Desc1);
02127     GP.AddPlot(LLV, gpwLinesPoints, "Log-likelihood", "linewidth 1 pointtype 6 pointsize 2");
02128     GP.SetXYLabel("NZero", "Log-Likelihood");  GP.SavePng(); }
02129     { TGnuPlot GP("BIC-"+OutFNm, Desc1);
02130     GP.AddPlot(BicV, gpwLinesPoints, "BIC", "linewidth 1 pointtype 6 pointsize 2");
02131     GP.SetXYLabel("NZero", "BIC");  GP.SavePng(); }
02132     { TGnuPlot GP("MDL-"+OutFNm, Desc1);
02133     GP.AddPlot(MdlV, gpwLinesPoints, "MDL", "linewidth 1 pointtype 6 pointsize 2");
02134     GP.SetXYLabel("NZero", "MDL");  GP.SavePng(); }
02135   }
02136 }
02137 
02138 void TKroneckerLL::TestGradDescent(const int& KronIters, const int& KiloSamples, const TStr& Permutation) {
02139   const TStr OutFNm = TStr::Fmt("grad-%s%d-%dk", Permutation.CStr(), KronIters, KiloSamples);
02140   TKronMtx KronParam = TKronMtx::GetMtx("0.8 0.6; 0.6 0.4");
02141   PNGraph Graph  = TKronMtx::GenFastKronecker(KronParam, KronIters, true, 0);
02142   TKroneckerLL KronLL(Graph, KronParam);
02143   TVec<TFltV> GradVV(4), SDevVV(4);  TFltV XValV;
02144   int NId1 = 0, NId2 = 0, NAccept = 0;
02145   TVec<TMom> GradMomV(4);
02146   TExeTm ExeTm;
02147   if (Permutation == "r") KronLL.SetRndPerm();
02148   else if (Permutation == "d") KronLL.SetDegPerm();
02149   else if (Permutation == "o") KronLL.SetOrderPerm();
02150   else FailR("Unknown permutation (r,d,o)");
02151   KronLL.CalcApxGraphLL();
02152   KronLL.CalcApxGraphDLL();
02153   for (int s = 0; s < 1000*KiloSamples; s++) {
02154     if (KronLL.SampleNextPerm(NId1, NId2)) { // new permutation
02155       KronLL.UpdateGraphDLL(NId1, NId2);  NAccept++; }
02156     if (s > 50000) { //warm up period
02157       for (int m = 0; m < 4; m++) { GradVV[m].Add(KronLL.GradV[m]); }
02158       if ((s+1) % 1000 == 0) {
02159         printf(".");
02160         for (int m = 0; m < 4; m++) { GradVV[m].Add(KronLL.GradV[m]); }
02161         XValV.Add((s+1));
02162         if ((s+1) % 100000 == 0) {
02163           TGnuPlot GP(OutFNm, TStr::Fmt("Gradient vs. samples. %d nodes, %d edges", Graph->GetNodes(), Graph->GetEdges()), true);
02164           for (int g = 0; g < GradVV.Len(); g++) {
02165             GP.AddPlot(XValV, GradVV[g], gpwLines, TStr::Fmt("grad %d", g)); }
02166           GP.SetXYLabel("sample index","log Gradient");
02167           GP.SavePng();
02168         }
02169       }
02170     }
02171   }
02172   printf("\n");
02173   for (int m = 0; m < 4; m++) {
02174     GradMomV[m].Def();
02175     printf("grad %d: mean: %12f  sDev: %12f  median: %12f\n", m,
02176       GradMomV[m].GetMean(), GradMomV[m].GetSDev(), GradMomV[m].GetMedian());
02177   }
02178 }
02179 /*
02180 // sample over permutations
02181 void TKroneckerLL::GradDescent(const double& LearnRate, const int& WarmUp, const int& NSamples, const int& NIter) {
02182   TFltV GradV, SDevV;
02183   double AvgLL;
02184   for (int Iter = 0; Iter < 100; Iter++) {
02185     //SampleGradient(WarmUp, NSamples, AvgLL, GradV, SDevV, true);
02186     SampleGradient(WarmUp, NSamples, AvgLL, GradV);
02187     for (int theta = 0; theta < GetParams(); theta++) {
02188       printf("%d]  %f  <--  %f + %f\n", theta, ProbMtx.At(theta) + LearnRate*GradV[theta], ProbMtx.At(theta), LearnRate*GradV[theta]);
02189       ProbMtx.At(theta) = ProbMtx.At(theta) + LearnRate*GradV[theta];
02190       // box constraints
02191       if (ProbMtx.At(theta) > 0.99) ProbMtx.At(theta)=0.99;
02192       if (ProbMtx.At(theta) < 0.01) ProbMtx.At(theta)=0.01;
02193     }
02194     ProbMtx.GetLLMtx(LLMtx);
02195   }
02196   ProbMtx.Dump("Final Thetas");
02197 }
02198 */
02199 
02200 
02202 // Add Noise to Graph
02204 int TKronNoise::RemoveNodeNoise(PNGraph& Graph, const int& NNodes, const bool Random) {
02205         IAssert(NNodes > 0 && NNodes < (Graph->GetNodes() / 2));
02206 
02207         int i = 0;
02208         TIntV ShufflePerm;
02209         Graph->GetNIdV(ShufflePerm);
02210         if(Random) {
02211                 ShufflePerm.Shuffle(TKronMtx::Rnd);
02212                 for(i = 0; i < NNodes; i++) {
02213                         Graph->DelNode(int(ShufflePerm[i]));
02214                 }
02215         } else {
02216                 for(i = 0; i < NNodes; i++) {
02217                         Graph->DelNode(int(ShufflePerm[ShufflePerm.Len() - 1 - i]));
02218                 }
02219         }
02220 
02221         return Graph->GetNodes();
02222 }
02223 
02224 int TKronNoise::RemoveNodeNoise(PNGraph& Graph, const double& Rate, const bool Random) {
02225         IAssert(Rate > 0 && Rate < 0.5);
02226         return TKronNoise::RemoveNodeNoise(Graph, (int) floor(Rate * double(Graph->GetNodes())), Random);
02227 }
02228 
02229 int TKronNoise::FlipEdgeNoise(PNGraph& Graph, const int& NEdges, const bool Random) {
02230         IAssert(NEdges > 0 && NEdges < Graph->GetEdges());
02231 
02232         const int Nodes = Graph->GetNodes();
02233         const int Edges = Graph->GetEdges();
02234         int Src, Dst;
02235 
02236         TIntV NIdV, TempV;
02237         TIntPrV ToAdd, ToDel;
02238         Graph->GetNIdV(NIdV);
02239 
02240         ToAdd.Gen(NEdges / 2, 0);
02241         for(int i = 0; i < NEdges / 2; i++) {
02242                 Src = NIdV[TKronMtx::Rnd.GetUniDevInt(Nodes)];
02243                 Dst = NIdV[TKronMtx::Rnd.GetUniDevInt(Nodes)];
02244                 if(Graph->IsEdge(Src, Dst)) {   i--;    continue;       }
02245 
02246                 ToAdd.Add(TIntPr(Src, Dst));
02247         }
02248 
02249         ToDel.Gen(Edges, 0);
02250         for(TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
02251                 ToDel.Add(TIntPr(EI.GetSrcNId(), EI.GetDstNId()));
02252         }
02253         ToDel.Shuffle(TKronMtx::Rnd);
02254 
02255         for(int i = 0; i < NEdges / 2; i++) {
02256                 Graph->DelEdge(ToDel[i].Val1, ToDel[i].Val2);
02257                 Graph->AddEdge(ToAdd[i].Val1, ToAdd[i].Val2);
02258         }
02259 
02260         return Graph->GetEdges();
02261 }
02262 
02263 int TKronNoise::FlipEdgeNoise(PNGraph& Graph, const double& Rate, const bool Random) {
02264         IAssert(Rate > 0 && Rate < 0.5);
02265         return TKronNoise::FlipEdgeNoise(Graph, (int) floor(Rate * double(Graph->GetEdges())), Random);
02266 }
02267 
02268 int TKronNoise::RemoveEdgeNoise(PNGraph& Graph, const int& NEdges) {
02269         IAssert(NEdges > 0 && NEdges < Graph->GetEdges());
02270 
02271         TIntPrV ToDel;
02272 
02273         ToDel.Gen(Graph->GetEdges(), 0);
02274         for(TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
02275                 if(EI.GetSrcNId() != EI.GetDstNId()) {
02276                         ToDel.Add(TIntPr(EI.GetSrcNId(), EI.GetDstNId()));
02277                 }
02278         }
02279         ToDel.Shuffle(TKronMtx::Rnd);
02280 
02281         for(int i = 0; i < NEdges; i++) {
02282                 Graph->DelEdge(ToDel[i].Val1, ToDel[i].Val2);
02283         }
02284 
02285         return Graph->GetEdges();
02286 }
02287 
02288 int TKronNoise::RemoveEdgeNoise(PNGraph& Graph, const double& Rate) {
02289         IAssert(Rate > 0 && Rate < 0.5);
02290         return TKronNoise::RemoveEdgeNoise(Graph, (int) floor(Rate * double(Graph->GetEdges())));
02291 }
02292 
02293 
02294 
02296 // Kronecker Log Likelihood Maximization
02297 void TKronMaxLL::SetPerm(const char& PermId) {
02298   if (PermId == 'o') KronLL.SetOrderPerm();
02299   else if (PermId == 'd') KronLL.SetDegPerm();
02300   else if (PermId == 'r') KronLL.SetRndPerm();
02301   else FailR("Unknown permutation type (o,d,r)");
02302 }
02303 
02304 /* void TKronMaxLL::EvalNewEdgeP(const TKronMtx& ProbMtx) {
02305   ProbMtx.Dump("\n***EVAL:");
02306   for (int i = 0; i < ProbMtx.Len(); i++) {
02307     // parameters are out of bounds
02308     if (ProbMtx.At(i) < 0.05 || ProbMtx.At(i) > 0.95) {
02309       TFltV MxDerivV(ProbMtx.Len()); MxDerivV.PutAll(1e5);
02310       FEvalH.AddDat(ProbMtx, TFEval(-1e10, MxDerivV));
02311       return;
02312     }
02313   }
02314   double AvgLL;
02315   TFltV GradV, SDevV;
02316   KronLL.InitLL(ProbMtx); // set current point
02317   //KronLL.SampleGradient(WarmUp, NSamples, AvgLL, GradV, SDevV, true); //sample the gradient
02318   KronLL.SampleGradient(WarmUp, NSamples, AvgLL, GradV);
02319   FEvalH.AddDat(ProbMtx, TFEval(AvgLL, GradV));
02320 }
02321 
02322 double TKronMaxLL::GetLL(const TFltV& ThetaV) {
02323   TKronMtx ProbMtx;  RoundTheta(ThetaV, ProbMtx);
02324   if (! FEvalH.IsKey(ProbMtx)) {
02325     EvalNewEdgeP(ProbMtx);
02326   }
02327   return FEvalH.GetDat(ProbMtx).LogLike;
02328 }
02329 
02330 void TKronMaxLL::GetDLL(const TFltV& ThetaV, TFltV& GradV) {
02331   TKronMtx ProbMtx;  RoundTheta(ThetaV, ProbMtx);
02332   if (! FEvalH.IsKey(ProbMtx)) {
02333     EvalNewEdgeP(ProbMtx);
02334   }
02335   GradV = FEvalH.GetDat(ProbMtx).GradV;
02336 }
02337 
02338 double TKronMaxLL::GetDLL(const TFltV& ThetaV, const int& ParamId) {
02339   TKronMtx ProbMtx;  RoundTheta(ThetaV, ProbMtx);
02340   if (! FEvalH.IsKey(ProbMtx)) {
02341     EvalNewEdgeP(ProbMtx);
02342   }
02343   return FEvalH.GetDat(ProbMtx).GradV[ParamId];
02344 }
02345 void TKronMaxLL::MaximizeLL(const int& NWarmUp, const int& Samples) {
02346   WarmUp = NWarmUp;
02347   NSamples = Samples;
02348   TConjGrad<TFunc> ConjGrad(KronLL.GetProbMtx().GetMtx(), TFunc(this));
02349   //TConjGrad<TLogBarFunc> ConjGrad(KronLL.GetEdgeP().GetV(), TLogBarFunc(this, 0.1));
02350   ConjGrad.ConjGradMin(0.1);
02351 }*/
02352 
02353 // round to 3 decimal places
02354 void TKronMaxLL::RoundTheta(const TFltV& ThetaV, TFltV& NewThetaV) {
02355   NewThetaV.Gen(ThetaV.Len());
02356   for (int i = 0; i < ThetaV.Len(); i++) {
02357     NewThetaV[i] = TMath::Round(ThetaV[i], 3); }
02358 }
02359 
02360 // round to 3 decimal places
02361 void TKronMaxLL::RoundTheta(const TFltV& ThetaV, TKronMtx& Kronecker) {
02362   Kronecker.GenMtx((int)sqrt((double)ThetaV.Len()));
02363   for (int i = 0; i < ThetaV.Len(); i++) {
02364     Kronecker.At(i) = TMath::Round(ThetaV[i], 3); }
02365 }
02366 
02367 void TKronMaxLL::Test() {
02368   TKronMtx::PutRndSeed(1);
02369   TKronMtx KronParam = TKronMtx::GetMtx("0.8 0.7; 0.6 0.5");
02370   PNGraph Graph  = TKronMtx::GenFastKronecker(KronParam, 8, true, 1);
02371 
02372   TKronMaxLL KronMaxLL(Graph, TFltV::GetV(0.9, 0.7, 0.5, 0.3));
02373   KronMaxLL.SetPerm('d');
02374   //KronMaxLL.MaximizeLL(10000, 50000);
02375   /*TKroneckerLL KronLL(Graph, *TKronMtx::GetMtx("0.9 0.7; 0.5 0.3"));
02376   KronLL.SetDegPerm();
02377   KronLL.GradDescent(0.005/double(Graph->GetNodes()));*/
02378 }
02379 
02381 // Kronecker Phase Plot
02382 /*
02383 void TKronPhasePlot::SaveMatlab(const TStr& OutFNm) const {
02384   FILE *F = fopen(OutFNm.CStr(), "wt");
02385   fprintf(F, "#Take last graph stats\n");
02386   fprintf(F, "#i\tAlpha\tBeta\tNodes\tNonZNodes\tEdges\tWccNodes\tWccEdges\tDiam\tEffDiam\tWccDiam\tWccEffDiam\t1StEigVal\tMxEigVal\n");
02387   for (int i = 0 ; i < PhaseV.Len(); i++) {
02388     const TPhasePoint& Point = PhaseV[i];
02389     const TGrowthStat& GrowthStat = Point.GrowthStat;
02390     const PGraphStat& FirstGrowth = GrowthStat[0];
02391     const PGraphStat& LastGrowth = GrowthStat.Last();
02392     fprintf(F, "%d\t%g\t%g\t", i, Point.Alpha, Point.Beta);
02393     fprintf(F, "%d\t%d\t%d\t", LastGrowth->Nodes, LastGrowth->Edges, LastGrowth->NonZNodes);
02394     fprintf(F, "%d\t%d\t", LastGrowth->WccNodes, LastGrowth->WccEdges);
02395     fprintf(F, "%f\t%f\t%f\t%f\t", LastGrowth->FullDiam, LastGrowth->EffDiam, LastGrowth->FullWccDiam, LastGrowth->EffWccDiam);
02396     //fprintf(F, "%f\t%f", FirstGrowth.MxEigVal, LastGrowth.MxEigVal);
02397     fprintf(F, "\n");
02398   }
02399   fclose(F);
02400 }
02401 
02402 void TKronPhasePlot::KroneckerPhase(const TStr& MtxId, const int& MxIter,
02403  const double& MnAlpha, const double& MxAlpha, const double& AlphaStep,
02404  const double& MnBeta, const double& MxBeta, const double& BetaStep,
02405  const TStr& FNmPref) {
02406   TKronPhasePlot PhasePlot;
02407   TExeTm KronTm;
02408   int AlphaCnt=0, BetaCnt=0;
02409   for (double Alpha = MnAlpha; (Alpha-1e-6) <= MxAlpha; Alpha += AlphaStep) {
02410     AlphaCnt++;  BetaCnt = 0;
02411     printf("\n\n****A:%g***********************************************************************", Alpha);
02412     for (double Beta = MnBeta; (Beta-1e-6) <= MxBeta; Beta += BetaStep) {
02413       printf("\n\n==A[%d]:%g====B[%d]:%g=====================================================\n", AlphaCnt, Alpha, BetaCnt, Beta);
02414       BetaCnt++;
02415       TGrowthStat GrowthStat;
02416       PNGraph Graph;
02417       // run Kronecker
02418       TFullRectMtx SeedMtx = TFullRectMtx::GetMtxFromNm(MtxId);
02419       SeedMtx.Epsilonize(Alpha, Beta);
02420       for (int iter = 1; iter < MxIter + 1; iter++) {
02421         printf("%2d] at %s\n", iter, TExeTm::GetCurTm().CStr());
02422         Graph = PNGraph();  KronTm.Tick();
02423         Graph = SeedMtx.GenRMatKronecker(iter, false, 0);
02424         GrowthStat.Add(Graph, TNodeTm(iter));
02425         if (KronTm.GetSecs() > 30 * 60) {
02426           printf("*** TIME LIMIT [%s]\n", KronTm.GetTmStr().CStr());  break; }
02427       }
02428       const TStr Desc = TStr::Fmt("%s. Alpha:%g. Beta:%g", MtxId.CStr(), Alpha, Beta);
02429       const TStr FNmPref1 = TStr::Fmt("%s.a%02d.b%02d", FNmPref.CStr(), AlphaCnt, BetaCnt);
02430       TGPlot::PlotDegDist(Graph, FNmPref1, Desc, false, true, true);
02431       TGPlot::PlotWccDist(Graph, FNmPref1, Desc);
02432       TGPlot::PlotSccDist(Graph, FNmPref1, Desc);
02433       GrowthStat.PlotAll(FNmPref1, Desc);
02434       GrowthStat.SaveTxt(FNmPref1, Desc);
02435       PhasePlot.PhaseV.Add(TPhasePoint(Alpha, Beta, GrowthStat));
02436     }
02437     {TFOut FOut(TStr::Fmt("phase.%s.bin", FNmPref.CStr()));
02438     PhasePlot.Save(FOut); }
02439   }
02440 }
02441 */
02442 /*void TKroneckerLL::SetRndThetas() {
02443   ProbMtx.Dump("TRUE parameters");
02444   TFltV RndV;
02445   double SumRnd = 0.0;
02446   for (int i = 0; i < ProbMtx.Len(); i++) {
02447     RndV.Add(0.1+TKronMtx::Rnd.GetUniDev());
02448     SumRnd += RndV.Last();
02449   }
02450   RndV.Sort(false);
02451   for (int i = 0; i < ProbMtx.Len(); i++) { ProbMtx.At(i) = RndV[i]; }
02452   ProbMtx.Dump("Random parameters");
02453   const double EdgePSum = pow(Graph->GetEdges(), 1.0/KronIters);
02454   bool Repeat = true;
02455   while (Repeat) {
02456     const double Scale = EdgePSum / SumRnd;
02457     Repeat=false;  SumRnd = 0.0;
02458     for (int i = 0; i < ProbMtx.Len(); i++) {
02459       ProbMtx.At(i) = ProbMtx.At(i)*Scale;
02460       if (ProbMtx.At(i) > 0.95) { ProbMtx.At(i)=0.95; Repeat=true; }
02461       SumRnd += ProbMtx.At(i);
02462     }
02463   }
02464   ProbMtx.Dump("INIT parameters");
02465   ProbMtx.GetLLMtx(LLMtx);
02466 }*/
02467 
02468 /*
02469 void TKroneckerLL::TestLL() {
02470   TExeTm ExeTm;
02471   // approximation to empty graph log-likelihood
02472   */
02473   /*{ PNGraph Graph = TNGraph::New();
02474   for (uint i = 0; i < TMath::Pow2(4); i++) { Graph->AddNode(i); } //8k nodes
02475   PKronecker KronParam = TKronMtx::GetMtx("0.8 0.6; 0.7 0.3");
02476   TKroneckerLL KronLL(Graph, KronParam);
02477   printf("\nNodes: %d\n", KronLL.GetNodes());
02478   printf("Full Graph LL:               %f\n", KronLL.GetFullGraphLL());
02479   printf("Empty Graph Exact LL:        %f\n", KronLL.GetEmptyGraphLL());
02480   printf("Empty Approx x=log(1-x) LL:  %f\n", KronLL.GetApxEmptyGraphLL());
02481   printf("Empty Sample LL (100/node):  %f\n", KronLL.GetSampleEmptyGraphLL(Graph->GetNodes() * 100));
02482   KronLL.SetOrderPerm();
02483   printf("\nEdge    prob: %f, LL: %f\n", KronParam->GetEdgeProb(0,0,8), log(KronParam->GetEdgeProb(0,0,8)));
02484   printf("No Edge prob: %f, LL: %f\n", KronParam->GetNoEdgeProb(0,0,8), log(KronParam->GetNoEdgeProb(0,0,8)));
02485   printf("Empty Graph  LL:     %f\n", KronLL.CalcGraphLL());
02486   printf("Apx Empty Graph  LL: %f\n", KronLL.CalcApxGraphLL());
02487   Graph->AddEdge(0, 0);
02488   printf("add 1 edge.  LL:     %f\n", KronLL.CalcGraphLL());
02489   printf("Apx add 1 edge.  LL: %f\n", KronLL.CalcApxGraphLL()); }
02490   */
02491 
02492   // log-likelihood versus different Kronecker parameters
02493   /*{ PKronecker KronParam = TKronMtx::GetMtx("0.9 0.6; 0.6 0.2");
02494   PNGraph Graph = TKronMtx::GenKronecker(KronParam, 10, true, 10);
02495   TVec<PKronecker> ParamV;
02496   ParamV.Add(KronParam);
02497   ParamV.Add(TKronMtx::GetMtx("0.6 0.6; 0.6 0.5")); // sum = 2.3
02498   //ParamV.Add(TKronMtx::GetMtx("0.9 0.9; 0.4 0.1")); // sum = 2.3
02499   //ParamV.Add(TKronMtx::GetMtx("0.8 0.7; 0.6 0.2")); // sum = 2.3
02500   ParamV.Add(TKronMtx::GetMtx("0.9 0.9; 0.6 0.2")); // sum = 2.6
02501   for (int i = 0; i < ParamV.Len(); i++) {
02502     ParamV[i]->Dump();
02503     TKroneckerLL KronLL(Graph, ParamV[i]);
02504     for (int k = 0; k < 3; k++) {
02505       if (k==0) { KronLL.SetOrderPerm();  printf("Order permutation:\n"); }
02506       if (k==1) { KronLL.SetDegPerm();  printf("Degree permutation:\n"); }
02507       if (k==2) { KronLL.SetRndPerm();  printf("Random permutation:\n"); }
02508       const double LL = KronLL.CalcGraphLL(), aLL = KronLL.CalcApxGraphLL();
02509       printf("  Exact  Graph LL:  %f\n", LL);
02510       printf("  Approx Graph LL:  %f\n", aLL);
02511       printf("  error          :  %.12f\n", -fabs(LL-aLL)/LL);
02512     }
02513   } }
02514   */
02515   // exact vs. approximate log-likelihood
02516   /*{ PKronecker KronParam = TKronMtx::GetMtx("0.9 0.6; 0.6 0.2");
02517   PNGraph Graph = TKronMtx::GenFastKronecker(KronParam, 16, true, 0);
02518   TKroneckerLL KronLL(Graph, KronParam);
02519   TMom ExactLL, ApxLL;
02520   printf("Random permutation:\n");
02521   for (int i = 0; i < 100; i++) {
02522     KronLL.SetRndPerm();
02523     //ExactLL.Add(KronLL.CalcGraphLL());
02524     ApxLL.Add(KronLL.CalcApxGraphLL());
02525     //printf("  Exact  Graph LL:  %f\n", ExactLL.GetVal(ExactLL.GetVals()-1));
02526     printf("  Approx Graph LL:  %f\n", ApxLL.GetVal(ApxLL.GetVals()-1));
02527   }
02528   ExactLL.Def();  ApxLL.Def();
02529   //printf("EXACT:   %f  (%f)\n", ExactLL.GetMean(), ExactLL.GetSDev());
02530   printf("APPROX:  %f  (%f)\n", ApxLL.GetMean(), ApxLL.GetSDev());
02531   KronLL.SetOrderPerm();
02532   printf("Order permutation:\n");
02533   printf("  Exact  Graph LL:  %f\n", KronLL.CalcGraphLL());
02534   printf("  Approx Graph LL:  %f\n", KronLL.CalcApxGraphLL());
02535   }
02536   */
02537 
02538   // start from random permultation and sort it using bubble sort
02539   // compare the end result with ordered permutation
02540   //PKronecker KronParam = TKronMtx::GetMtx("0.9 0.6; 0.6 0.2");
02541   //PNGraph Graph = TKronMtx::GenFastKronecker(KronParam, 10, true, 1);
02542   /*PKronecker KronParam = TKronMtx::GetMtx("0.9 0.7; 0.9 0.5");
02543   PNGraph Graph = TKronMtx::GenFastKronecker(KronParam, 6, true, 2);
02544   TGAlg::SaveFullMtx(Graph, "kron32.tab");
02545 
02546   TKroneckerLL KronLL(Graph, KronParam);
02547   KronLL.SetOrderPerm();
02548   KronLL.LogLike = KronLL.CalcApxGraphLL();
02549   printf("  Approx Graph LL:   %f\n", KronLL.CalcApxGraphLL());
02550   printf("  swap 1-20:         %f\n", KronLL.SwapNodesLL(1, 20));
02551   printf("  swap 20-30:        %f\n", KronLL.SwapNodesLL(20, 30));
02552   printf("  swap 30-1:         %f\n", KronLL.SwapNodesLL(1, 30));
02553   printf("  swap 20-30:        %f\n", KronLL.SwapNodesLL(30, 20));
02554   IAssert(KronLL.GetPerm().IsSorted());
02555   KronLL.SetRndPerm();
02556   KronLL.LogLike = KronLL.CalcApxGraphLL();
02557   for (int i = 0; i < 1000000; i++) {
02558     const int nid1 = TInt::Rnd.GetUniDevInt(KronLL.Nodes);
02559     const int nid2 = TInt::Rnd.GetUniDevInt(KronLL.Nodes);
02560     printf("%3d]  swap LL:     %f\n", i, KronLL.SwapNodesLL(nid1, nid2));
02561   }
02562   printf("***   approx LL:   %f\n", KronLL.CalcApxGraphLL());
02563   printf("***    exact LL:   %f\n", KronLL.CalcGraphLL());
02564   */
02565   /*ExeTm.Tick();
02566   // bubble sort
02567   for (int i = 0; i < Graph->GetNodes()-1; i++) {
02568     for (int j = 1; j < Graph->GetNodes(); j++) {
02569       if (KronLL.GetPerm()[j-1] > KronLL.GetPerm()[j]) {
02570         const double oldLL = KronLL.GetLL();
02571         const double newLL = KronLL.SwapNodesLL(j-1, j);
02572         //const double trueLL = KronLL.CalcApxGraphLL();
02573         //printf("swap %3d - %3d:   old: %f   new: %f  true:%f\n",
02574         //    KronLL.GetPerm()[j-1], KronLL.GetPerm()[j], oldLL, newLL, trueLL);
02575       }
02576     }
02577   }
02578   //for (int i = 0; i < 100000; i++) {
02579   //  KronLL.SwapNodesLL(TInt::Rnd.GetUniDevInt(TMath::Pow2(16)), TInt::Rnd.GetUniDevInt(TMath::Pow2(16))); }
02580   printf("\nPermutation is %s\n", KronLL.GetPerm().IsSorted()? "SORTED" : "NOT SORTED");
02581   printf("  Swap   Graph LL:   %f\n", KronLL.GetLL());
02582   printf("  Approx Graph LL:   %f\n", KronLL.CalcApxGraphLL());
02583   KronLL.SetOrderPerm();
02584   printf("  Order  Graph LL:   %f\n\n", KronLL.CalcApxGraphLL());
02585   printf("Permutation is %s\n", KronLL.GetPerm().IsSorted()? "SORTED" : "NOT SORTED");
02586   printf("time: %f\n", ExeTm.GetSecs());
02587   */
02588   // evaluate the derivatives
02589   /*{ PNGraph Graph = TNGraph::New();
02590   TKronMtx KronParam = TKronMtx::GetMtx("0.8 0.4; 0.4 0.2");
02591   //for (uint i = 0; i < TMath::Pow2(4); i++) { Graph->AddNode(i); } //8k nodes
02592   Graph = TKronMtx::GenFastKronecker(KronParam, 8, true, 2); //TGAlg::SaveFullMtx(Graph, "kron16.txt");
02593   TKroneckerLL KronLL(Graph, KronParam);
02594   KronLL.SetOrderPerm();
02595   printf("\nNodes: %d\n", KronLL.GetNodes());
02596   printf("Full  Graph Exact LL:        %f\n", KronLL.GetFullGraphLL());
02597   printf("Empty Graph Exact LL:        %f\n", KronLL.GetEmptyGraphLL());
02598   printf("Empty Approx LL:             %f\n", KronLL.GetApxEmptyGraphLL());
02599   printf("Exact Graph LL:   %f\n", KronLL.CalcGraphLL());
02600   printf("Apx   Graph LL:   %f\n\n", KronLL.CalcApxGraphLL());
02601   // derivatives
02602   printf("Empty graph Exact DLL:           %f\n", KronLL.GetEmptyGraphDLL(0));
02603   printf("Empty graph Apx   DLL:           %f\n", KronLL.GetApxEmptyGraphDLL(0));
02604   printf("Theta0    edge(0,1) DLL:      %f\n", KronLL.LLMtx.GetEdgeDLL(0, 0, 1, 4));
02605   printf("Theta0 NO edge(0,1) DLL:      %f\n", KronLL.LLMtx.GetNoEdgeDLL(0, 0, 1, 4));
02606   printf("Theta0 NO edge(0,1) DLL:      %f\n", KronLL.LLMtx.GetApxNoEdgeDLL(0, 0, 1, 4));
02607   KronLL.CalcGraphDLL();  printf("Exact Theta0 DLL:");  KronLL.GetDLL(0);
02608   KronLL.CalcApxGraphDLL();  printf("Apx   Theta0 DLL:");  KronLL.GetDLL(0);
02609   KronLL.CalcFullApxGraphDLL();  printf("Apx   Theta0 DLL:");  KronLL.GetDLL(0);
02610   // swap
02611   */
02612   /*for (int i = 0; i < 100; i++) {
02613     const int A = TInt::Rnd.GetUniDevInt(KronLL.Nodes);
02614     KronLL.NodePerm.Swap(i, A);
02615     //KronLL.UpdateGraphDLL(i, A); printf("Fast  Theta0 DLL:");  KronLL.GetDLL(0);
02616     KronLL.CalcApxGraphDLL();  printf("Apx   Theta0 DLL:");  KronLL.GetDLL(0);
02617     //KronLL.CalcFullApxGraphDLL();  printf("Apx   Theta0 DLL:");  KronLL.GetDLL(0);
02618     //KronLL.CalcGraphDLL();  printf("Exact Theta0 DLL:");  KronLL.GetDLL(0);
02619     printf("\n");
02620   } */
02621   //}
02622 //}
02623 
02624 /*void TKroneckerLL::SampleGradient(const int& WarmUp, const int& NSamples, double& AvgLL, TFltV& AvgGradV, TFltV& SDevV, const bool& Plot) {
02625   printf("Samples: %s (warm-up: %s)\n", TInt::GetMegaStr(NSamples).CStr(), TInt::GetMegaStr(WarmUp).CStr());
02626   int NId1 = 0, NId2 = 0;
02627   TExeTm ExeTm;
02628   CalcApxGraphLL();
02629   for (int s = 0; s < WarmUp; s++) {
02630     SampleNextPerm(NId1, NId2); }
02631   printf("  warm-up:%s", ExeTm.GetTmStr());  ExeTm.Tick();
02632   CalcApxGraphLL();
02633   CalcApxGraphDLL();
02634   AvgLL = 0;
02635   TVec<TMom> DLLMomV(LLMtx.Len());
02636   for (int s = 0; s < NSamples; s++) {
02637     if (SampleNextPerm(NId1, NId2)) { // new permutation
02638       UpdateGraphDLL(NId1, NId2);
02639     }
02640     AvgLL += GetLL();
02641     for (int m = 0; m < LLMtx.Len(); m++) { DLLMomV[m].Add(GradV[m]); }
02642   }
02643   AvgLL = AvgLL / (NSamples*Nodes);
02644   // plot gradients over sampling time
02645   if (Plot) {
02646     TVec<TFltV> FltVV(LLMtx.Len()+1);
02647     for (int s = 0; s < DLLMomV[0].GetVals(); s += 1000) {
02648       for (int m = 0; m < LLMtx.Len(); m++) { FltVV[m].Add(DLLMomV[m].GetVal(s)); }
02649       FltVV.Last().Add(s); }
02650     const TStr FNm = TFile::GetUniqueFNm(TStr::Fmt("grad%dW%sS%s-#.png", KronIters, TInt::GetMegaStr(WarmUp).CStr(), TInt::GetMegaStr(NSamples).CStr()));
02651     TGnuPlot GP(FNm.GetFMid(), TStr::Fmt("Gradient vs. Sample Index. Nodes: %d, WarmUp: %s, Samples: %s, Avg LL: %f", Nodes,
02652       TInt::GetMegaStr(WarmUp).CStr(), TInt::GetMegaStr(NSamples).CStr(), AvgLL), true);
02653     for (int m = 0; m < LLMtx.Len(); m++) {
02654       GP.AddPlot(FltVV.Last(), FltVV[m], gpwLines, TStr::Fmt("Grad %d", m+1), "linewidth 5"); }
02655     GP.SetXYLabel("Sample Index (time)", "Log-likelihood gradient");
02656     GP.SavePng();
02657   }
02658   // average gradients
02659   printf("  sampling:%s\n", ExeTm.GetTmStr());
02660   printf("  AverageLL: %f\n", AvgLL);
02661   printf("Gradients:\n");
02662   AvgGradV.Gen(LLMtx.Len());
02663   SDevV.Gen(LLMtx.Len());
02664   for (int m = 0; m < LLMtx.Len(); m++) {
02665     DLLMomV[m].Def();
02666     AvgGradV[m] = DLLMomV[m].GetMean() / (Nodes*Nodes);
02667     SDevV[m] = DLLMomV[m].GetSDev() / (Nodes*Nodes);
02668     printf("  %d]  mean: %16f    sDev: %16f\n", m, AvgGradV[m], SDevV[m]);
02669   }
02670 }
02671 
02672 void TKronMaxLL::TFunc::FDeriv(const TFltV& Point, TFltV& GradV) {
02673   CallBack->GetDLL(Point, GradV);
02674   for (int i = 0; i < GradV.Len(); i++) { GradV[i] = -GradV[i]; }
02675 }
02676 
02677 double TKronMaxLL::TLogBarFunc::FVal(const TFltV& Point) {
02678   // log-likelihood
02679   const double LogLL = CallBack->GetLL(Point);
02680   // log-barrier
02681   const double MinBarrier = 0.05;
02682   const double MaxBarrier = 0.95;
02683   const double T1 = 1.0/T;
02684   double Barrier = 0.0;
02685   for (int i = 0; i < Point.Len(); i++) {
02686     if(Point[i].Val > MinBarrier && Point[i].Val < MaxBarrier) {
02687       Barrier += - T1 * (log(Point[i]-MinBarrier) + log(MaxBarrier-Point[i])); //log-barrier
02688     } else { Barrier = 1e5; }
02689   }
02690   IAssert(Barrier > 0.0);
02691   printf("barrrier: %f\n", Barrier);
02692   return -LogLL + Barrier; // minus LL since we want to maximize it
02693 }
02694 
02695 void TKronMaxLL::TLogBarFunc::FDeriv(const TFltV& Point, TFltV& DerivV) {
02696   // derivative of log-likelihood
02697   CallBack->GetDLL(Point, DerivV);
02698   // derivative of log barrier
02699   const double MinBarrier = 0.05;
02700   const double MaxBarrier = 0.95;
02701   const double T1 = 1.0/T;
02702   for (int i = 0; i < Point.Len(); i++) {
02703     DerivV[i] = - DerivV[i] + (- T1*(1.0/(Point[i]-MinBarrier) - 1.0/(MaxBarrier-Point[i])));
02704   }
02705 }
02706 */