SNAP Library 2.2, Developer Reference
2014-03-11 19:15:55
SNAP, a general purpose, high performance system for analysis and manipulation of large networks
|
00001 #include "stdafx.h" 00002 #include "cascnetinf.h" 00003 00004 double TCascade::TransProb(const int& NId1, const int& NId2) const { 00005 if (!IsNode(NId1) || !IsNode(NId2)) { return Eps.Val; } 00006 if (GetTm(NId1) >= GetTm(NId2)) { return Eps.Val; } 00007 if (Model==0) 00008 return Alpha*exp(-Alpha*(GetTm(NId2)-GetTm(NId1))); // exponential 00009 else if (Model==1) 00010 return (Alpha-1)*pow((GetTm(NId2)-GetTm(NId1)), -Alpha); // power-law 00011 else 00012 return Alpha*(GetTm(NId2)-GetTm(NId1))*exp(-0.5*Alpha*pow(GetTm(NId2)-GetTm(NId1), 2)); // rayleigh 00013 00014 return (-1); 00015 } 00016 00017 double TCascade::GetProb(const PNGraph& G) { 00018 double P = 0; 00019 for (int n = 0; n < Len(); n++) { 00020 const int DstNId = GetNode(n); 00021 const double DstTm = GetTm(DstNId); 00022 TNGraph::TNodeI NI = G->GetNI(DstNId); 00023 double MxProb = log(Eps); 00024 int BestParent = -1; 00025 for (int e = 0; e < NI.GetInDeg(); e++) { 00026 const int SrcNId = NI.GetInNId(e); 00027 if (IsNode(SrcNId) && GetTm(SrcNId) < DstTm) { 00028 const double Prob = log(TransProb(SrcNId, DstNId)); 00029 if (MxProb < Prob) { MxProb = Prob; BestParent = SrcNId; } 00030 } 00031 } 00032 NIdHitH.GetDat(DstNId).Parent = BestParent; 00033 P += MxProb; 00034 } 00035 00036 return P; 00037 } 00038 00039 // init prob of a cascade in an empty graph 00040 void TCascade::InitProb() { 00041 CurProb = log(Eps) * Len(); 00042 for (int i = 0; i < Len(); i++) { 00043 NIdHitH[i].Parent = -1; } 00044 } 00045 00046 // update the cascade probability given a new edge (N1, N2) in the graph 00047 double TCascade::UpdateProb(const int& N1, const int& N2, const bool& UpdateProb) { 00048 if (!IsNode(N1) || !IsNode(N2)) { return CurProb; } 00049 if (GetTm(N1) >= GetTm(N2)) { return CurProb; } 00050 const double P1 = log(TransProb(GetParent(N2), N2)); 00051 const double P2 = log(TransProb(N1, N2)); // N1 influences N2 00052 if (P1 < P2) { 00053 if (UpdateProb) { // the edge is there, update the CurProb and best Parent 00054 CurProb = CurProb - P1 + P2; 00055 NIdHitH.GetDat(N2).Parent = N1; 00056 } else { 00057 return CurProb - P1 + P2; } 00058 } 00059 return CurProb; 00060 } 00061 00062 void TNetInfBs::LoadCascadesTxt(TSIn& SIn, const int& Model, const double& alpha) { 00063 TStr Line; 00064 while (!SIn.Eof()) { 00065 SIn.GetNextLn(Line); 00066 if (Line=="") { break; } 00067 TStrV NIdV; Line.SplitOnAllCh(',', NIdV); 00068 AddNodeNm(NIdV[0].GetInt(), TNodeInfo(NIdV[1], 0)); 00069 } 00070 printf("All nodes read!\n"); 00071 while (!SIn.Eof()) { SIn.GetNextLn(Line); AddCasc(Line, Model, alpha); } 00072 printf("All cascades read!\n"); 00073 } 00074 00075 void TNetInfBs::LoadGroundTruthTxt(TSIn& SIn) { 00076 GroundTruth = TNGraph::New(); TStr Line; 00077 00078 // add nodes 00079 while (!SIn.Eof()) { 00080 SIn.GetNextLn(Line); 00081 if (Line=="") { break; } 00082 TStrV NIdV; Line.SplitOnAllCh(',', NIdV); 00083 GroundTruth->AddNode(NIdV[0].GetInt()); 00084 } 00085 00086 // add edges 00087 while (!SIn.Eof()) { 00088 SIn.GetNextLn(Line); 00089 TStrV NIdV; Line.SplitOnAllCh(',', NIdV); 00090 GroundTruth->AddEdge(NIdV[0].GetInt(), NIdV[1].GetInt()); 00091 if (NIdV.Len()>2) { Alphas.AddDat(TIntPr(NIdV[0].GetInt(), NIdV[1].GetInt())) = NIdV[2].GetFlt(); } 00092 else { Alphas.AddDat(TIntPr(NIdV[0].GetInt(), NIdV[1].GetInt())) = 1.0; } 00093 } 00094 00095 printf("groundtruth nodes:%d edges:%d\n", GroundTruth->GetNodes(), GroundTruth->GetEdges()); 00096 } 00097 00098 void TNetInfBs::AddCasc(const TStr& CascStr, const int& Model, const double& alpha) { 00099 TStrV NIdV; CascStr.SplitOnAllCh(',', NIdV); 00100 TCascade C(alpha, Model); 00101 for (int i = 0; i < NIdV.Len(); i+=2) { 00102 int NId; 00103 double Tm; 00104 NId = NIdV[i].GetInt(); 00105 Tm = NIdV[i+1].GetFlt(); 00106 GetNodeInfo(NId).Vol = GetNodeInfo(NId).Vol + 1; 00107 C.Add(NId, Tm); 00108 } 00109 C.Sort(); 00110 CascV.Add(C); 00111 } 00112 00113 void TNetInfBs::GenCascade(TCascade& C, const int& TModel, const double &window, TIntPrIntH& EdgesUsed, const double& delta, 00114 const double& std_waiting_time, const double& std_beta) { 00115 TIntFltH InfectedNIdH; TIntH InfectedBy; 00116 double GlobalTime; int StartNId; 00117 double alpha, beta; 00118 00119 if (GroundTruth->GetNodes() == 0) 00120 return; 00121 00122 while (C.Len() < 2) { 00123 C.Clr(); 00124 InfectedNIdH.Clr(); 00125 InfectedBy.Clr(); 00126 GlobalTime = 0; 00127 00128 StartNId = GroundTruth->GetRndNId(); 00129 InfectedNIdH.AddDat(StartNId) = GlobalTime; 00130 00131 while (true) { 00132 // sort by time & get the oldest node that did not run infection 00133 InfectedNIdH.SortByDat(true); 00134 const int& NId = InfectedNIdH.BegI().GetKey(); 00135 GlobalTime = InfectedNIdH.BegI().GetDat(); 00136 00137 // all the nodes has run infection 00138 if (GlobalTime >= window) 00139 break; 00140 00141 // add current oldest node to the network and set its time 00142 C.Add(NId, GlobalTime); 00143 00144 // run infection from the current oldest node 00145 const TNGraph::TNodeI NI = GroundTruth->GetNI(NId); 00146 for (int e = 0; e < NI.GetOutDeg(); e++) { 00147 const int DstNId = NI.GetOutNId(e); 00148 00149 beta = Betas.GetDat(TIntPr(NId, DstNId)); 00150 00151 // flip biased coin (set by beta) 00152 if (TInt::Rnd.GetUniDev() > beta+std_beta*TFlt::Rnd.GetNrmDev()) 00153 continue; 00154 00155 alpha = Alphas.GetDat(TIntPr(NId, DstNId)); 00156 00157 // not infecting the parent 00158 if (InfectedBy.IsKey(NId) && InfectedBy.GetDat(NId).Val == DstNId) 00159 continue; 00160 00161 double sigmaT; 00162 switch (TModel) { 00163 case 0: 00164 // exponential with alpha parameter 00165 sigmaT = TInt::Rnd.GetExpDev(alpha); 00166 break; 00167 case 1: 00168 // power-law with alpha parameter 00169 sigmaT = TInt::Rnd.GetPowerDev(alpha); 00170 while (sigmaT < delta) { sigmaT = TInt::Rnd.GetPowerDev(alpha); } 00171 break; 00172 case 2: 00173 // rayleigh with alpha parameter 00174 sigmaT = TInt::Rnd.GetRayleigh(1/sqrt(alpha)); 00175 break; 00176 default: 00177 sigmaT = 1; 00178 break; 00179 } 00180 00181 // avoid negative time diffs in case of noise 00182 if (std_waiting_time > 0) 00183 sigmaT = TFlt::GetMx(0.0, sigmaT + std_waiting_time*TFlt::Rnd.GetNrmDev()); 00184 00185 double t1 = GlobalTime + sigmaT; 00186 00187 if (InfectedNIdH.IsKey(DstNId)) { 00188 double t2 = InfectedNIdH.GetDat(DstNId); 00189 if (t2 > t1 && t2 != window) { 00190 InfectedNIdH.GetDat(DstNId) = t1; 00191 InfectedBy.GetDat(DstNId) = NId; 00192 } 00193 } else { 00194 InfectedNIdH.AddDat(DstNId) = t1; 00195 InfectedBy.AddDat(DstNId) = NId; 00196 } 00197 } 00198 00199 // we cannot delete key (otherwise, we cannot sort), so we assign a big time (window cut-off) 00200 InfectedNIdH.GetDat(NId) = window; 00201 } 00202 00203 } 00204 00205 C.Sort(); 00206 00207 for (TIntH::TIter EI = InfectedBy.BegI(); EI < InfectedBy.EndI(); EI++) { 00208 TIntPr Edge(EI.GetDat().Val, EI.GetKey().Val); 00209 00210 if (!EdgesUsed.IsKey(Edge)) EdgesUsed.AddDat(Edge) = 0; 00211 00212 EdgesUsed.GetDat(Edge) += 1; 00213 } 00214 } 00215 00216 void TNetInfBs::Init() { 00217 THash<TInt, TIntV> CascPN; 00218 Graph = TNGraph::New(); 00219 00220 // reset vectors 00221 EdgeGainV.Clr(); 00222 CascPerEdge.Clr(); 00223 PrecisionRecall.Clr(); 00224 00225 for (int c = 0; c < CascV.Len(); c++) { 00226 for (int i = 0; i < CascV[c].Len(); i++) { 00227 if (!Graph->IsNode(CascV[c].GetNode(i))) Graph->AddNode(CascV[c].GetNode(i)); 00228 if (!CascPN.IsKey(CascV[c].GetNode(i))) CascPN.AddDat(CascV[c].GetNode(i)) = TIntV(); 00229 CascPN.GetDat(CascV[c].GetNode(i)).Add(c); 00230 } 00231 CascV[c].InitProb(); 00232 } 00233 00234 // only add edges that make sense (i.e., at least once coherent in time) 00235 for (TNGraph::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) { 00236 TIntV &Cascs = CascPN.GetDat(NI.GetId()); 00237 for (int c = 0; c < Cascs.Len(); c++) { 00238 for (int i=0; i < CascV[Cascs[c]].Len(); i++) { 00239 if (CascV[Cascs[c]].GetNode(i)==NI.GetId()) 00240 continue; 00241 00242 if (CascV[Cascs[c]].GetTm(CascV[Cascs[c]].GetNode(i)) < CascV[Cascs[c]].GetTm(NI.GetId()) ) { 00243 if (!CascPerEdge.IsKey(TIntPr(CascV[Cascs[c]].GetNode(i), NI.GetId()))) { 00244 EdgeGainV.Add(TPair<TFlt, TIntPr>(TFlt::Mx, TIntPr(CascV[Cascs[c]].GetNode(i), NI.GetId()))); 00245 CascPerEdge.AddDat(TIntPr(CascV[Cascs[c]].GetNode(i), NI.GetId())) = TIntV(); 00246 } 00247 // Add cascade to hash of cascades per edge (to implement localized update) 00248 CascPerEdge.GetDat(TIntPr(CascV[Cascs[c]].GetNode(i), NI.GetId())).Add(Cascs[c]); 00249 } 00250 } 00251 } 00252 } 00253 } 00254 00255 double TNetInfBs::GetAllCascProb(const int& EdgeN1, const int& EdgeN2) { 00256 double P = 0.0; 00257 00258 if (EdgeN1==-1 && EdgeN2==-1) { 00259 for (int c = 0; c < CascV.Len(); c++) { 00260 P += CascV[c].UpdateProb(EdgeN1, EdgeN2, false); } // initial log-likelihood 00261 return P; 00262 } 00263 00264 TIntV &CascsEdge = CascPerEdge.GetDat(TIntPr(EdgeN1, EdgeN2)); // only check cascades that contain the edge 00265 00266 for (int c = 0; c < CascsEdge.Len(); c++) { 00267 P += (CascV[CascsEdge[c]].UpdateProb(EdgeN1, EdgeN2, false) - CascV[CascsEdge[c]].CurProb); } // marginal gain 00268 return P; 00269 } 00270 00271 TIntPr TNetInfBs::GetBestEdge(double& CurProb, double& LastGain, bool& msort, int &attempts) { 00272 TIntPr BestE; 00273 TVec<TInt> KeysV; 00274 TVec<TPair<TFlt, TIntPr> > EdgeGainCopyToSortV; 00275 TIntV EdgeZero; 00276 double BestGain = TFlt::Mn; 00277 int BestGainIndex = -1; 00278 00279 if (msort) { 00280 for (int i=0; i<TMath::Mn(attempts-1, EdgeGainV.Len()); i++) 00281 EdgeGainCopyToSortV.Add(EdgeGainV[i]); 00282 00283 // printf("Sorting sublist of size %d of marginal gains!\n", EdgeGainCopyToSortV.Len()); 00284 00285 // sort this list 00286 EdgeGainCopyToSortV.Sort(false); 00287 00288 // printf("Sublist sorted!\n"); 00289 00290 // clever way of resorting without need to copy (google interview question! :-)) 00291 for (int i=0, ii=0, j=0; ii < EdgeGainCopyToSortV.Len(); j++) { 00292 if ( (i+EdgeGainCopyToSortV.Len() < EdgeGainV.Len()) && (EdgeGainCopyToSortV[ii].Val1 < EdgeGainV[i+EdgeGainCopyToSortV.Len()].Val1) ) { 00293 EdgeGainV[j] = EdgeGainV[i+EdgeGainCopyToSortV.Len()]; 00294 i++; 00295 } else { 00296 EdgeGainV[j] = EdgeGainCopyToSortV[ii]; 00297 ii++; 00298 } 00299 } 00300 } 00301 00302 attempts = 0; 00303 00304 for (int e = 0; e < EdgeGainV.Len(); e++) { 00305 const TIntPr& Edge = EdgeGainV[e].Val2; 00306 if (Graph->IsEdge(Edge.Val1, Edge.Val2)) { continue; } // if edge was already included in the graph 00307 00308 const double EProb = GetAllCascProb(Edge.Val1, Edge.Val2); 00309 EdgeGainV[e].Val1 = EProb; // update marginal gain 00310 if (BestGain < EProb) { 00311 BestGain = EProb; 00312 BestGainIndex = e; 00313 BestE = Edge; 00314 } 00315 00316 // if we only update one weight, we don't need to sort the list 00317 attempts++; 00318 00319 // keep track of zero edges after sorting once the full list 00320 if (!Graph->IsEdge(Edge.Val1, Edge.Val2) && Graph->GetEdges() > 1) { 00321 if (EProb == 0) 00322 EdgeZero.Add(e); 00323 } 00324 00325 // lazy evaluation 00326 if (e+1 == EdgeGainV.Len() || BestGain >= EdgeGainV[e+1].Val1) { 00327 CurProb += BestGain; 00328 00329 if (BestGain == 0) 00330 return TIntPr(-1, -1); 00331 00332 EdgeGainV.Del(BestGainIndex); 00333 00334 // we know the edges in 0 will be in sorted order, so we start from the biggest 00335 for (int i=EdgeZero.Len()-1; i>=0; i--) { 00336 if (EdgeZero[i] > BestGainIndex) 00337 EdgeGainV.Del(EdgeZero[i]-1); 00338 else 00339 EdgeGainV.Del(EdgeZero[i]); 00340 } 00341 00342 if (EdgeZero.Len() > 2) { attempts -= (EdgeZero.Len()-1); } 00343 00344 msort = (attempts > 1); 00345 00346 LastGain = BestGain; 00347 00348 return BestE; 00349 } 00350 } 00351 00352 printf("Edges exhausted!\n"); 00353 return TIntPr(-1, -1); 00354 } 00355 00356 double TNetInfBs::GetBound(const TIntPr& Edge, double& CurProb) { 00357 double Bound = 0; 00358 TFltV Bounds; 00359 00360 // bound could be computed faster (using lazy evaluation, as in the optimization procedure) 00361 for (int e=0; e < EdgeGainV.Len(); e++) { 00362 const TIntPr& EE = EdgeGainV[e].Val2; 00363 if (EE != Edge && !Graph->IsEdge(EE.Val1, EE.Val2)) { 00364 const double EProb = GetAllCascProb(EE.Val1, EE.Val2); 00365 if (EProb > CurProb) Bounds.Add(EProb - CurProb); } 00366 } 00367 00368 Bounds.Sort(false); 00369 for (int i=0; i<Graph->GetEdges() && i<Bounds.Len(); i++) Bound += Bounds[i]; 00370 00371 return Bound; 00372 } 00373 00374 void TNetInfBs::GreedyOpt(const int& MxEdges) { 00375 double CurProb = GetAllCascProb(-1, -1); 00376 double LastGain = TFlt::Mx; 00377 int attempts = 0; 00378 bool msort = false; 00379 00380 for (int k = 0; k < MxEdges && EdgeGainV.Len() > 0; k++) { 00381 const TIntPr BestE = GetBestEdge(CurProb, LastGain, msort, attempts); 00382 if (BestE == TIntPr(-1, -1)) // if we cannot add more edges, we stop 00383 break; 00384 00385 if (CompareGroundTruth) { 00386 double precision = 0, recall = 0; 00387 if (PrecisionRecall.Len() > 1) { 00388 precision = PrecisionRecall[PrecisionRecall.Len()-1].Val2.Val; 00389 recall = PrecisionRecall[PrecisionRecall.Len()-1].Val1.Val; 00390 } 00391 if (GroundTruth->IsEdge(BestE.Val1, BestE.Val2)) { 00392 recall++; 00393 } else { 00394 precision++; 00395 } 00396 00397 PrecisionRecall.Add(TPair<TFlt, TFlt>(recall, precision)); 00398 } 00399 00400 Graph->AddEdge(BestE.Val1, BestE.Val2); // add edge to network 00401 00402 00403 // localized update! 00404 TIntV &CascsEdge = CascPerEdge.GetDat(BestE); // only check cascades that contain the edge 00405 for (int c = 0; c < CascsEdge.Len(); c++) { 00406 CascV[CascsEdge[c]].UpdateProb(BestE.Val1, BestE.Val2, true); // update probabilities 00407 } 00408 00409 // some extra info for the added edge 00410 TInt Vol; TFlt AverageTimeDiff; TFltV TimeDiffs; 00411 Vol = 0; AverageTimeDiff = 0; 00412 for (int i=0; i< CascV.Len(); i++) { 00413 if (CascV[i].IsNode(BestE.Val2) && CascV[i].GetParent(BestE.Val2) == BestE.Val1) { 00414 Vol += 1; TimeDiffs.Add(CascV[i].GetTm(BestE.Val2)-CascV[i].GetTm(BestE.Val1)); 00415 AverageTimeDiff += TimeDiffs[TimeDiffs.Len()-1]; } 00416 } 00417 AverageTimeDiff /= Vol; 00418 if (TimeDiffs.Len() > 0) 00419 TimeDiffs.Sort(); 00420 else 00421 TimeDiffs.Add(0); 00422 00423 // compute bound only if explicitly required 00424 EdgeInfoH.AddDat(BestE) = TEdgeInfo(Vol, 00425 LastGain, 00426 0.0, 00427 TimeDiffs[(int)(TimeDiffs.Len()/2)], 00428 AverageTimeDiff); 00429 } 00430 00431 if (CompareGroundTruth) { 00432 for (int i=0; i<PrecisionRecall.Len(); i++) { 00433 PrecisionRecall[i].Val2 = 1.0 - PrecisionRecall[i].Val2/(PrecisionRecall[i].Val2+PrecisionRecall[i].Val1); 00434 PrecisionRecall[i].Val1 /= (double)GroundTruth->GetEdges(); 00435 } 00436 } 00437 } 00438 00439 void TNetInfBs::SavePajek(const TStr& OutFNm) { 00440 TIntSet NIdSet; 00441 FILE *F = fopen(OutFNm.CStr(), "wt"); 00442 fprintf(F, "*Vertices %d\r\n", NIdSet.Len()); 00443 for (THash<TInt, TNodeInfo>::TIter NI = NodeNmH.BegI(); NI < NodeNmH.EndI(); NI++) { 00444 const TNodeInfo& I = NI.GetDat(); 00445 fprintf(F, "%d \"%s\" ic Blue x_fact %f y_fact %f\r\n", NI.GetKey().Val, 00446 I.Name.CStr(), TMath::Mx<double>(log((double)I.Vol)-5,1), TMath::Mx<double>(log((double)I.Vol)-5,1)); 00447 } 00448 fprintf(F, "*Arcs\r\n"); 00449 for (TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { 00450 fprintf(F, "%d %d 1\r\n", EI.GetSrcNId(), EI.GetDstNId()); 00451 } 00452 fclose(F); 00453 } 00454 00455 void TNetInfBs::SavePlaneTextNet(const TStr& OutFNm) { 00456 TIntSet NIdSet; 00457 FILE *F = fopen(OutFNm.CStr(), "wt"); 00458 for (THash<TInt, TNodeInfo>::TIter NI = NodeNmH.BegI(); NI < NodeNmH.EndI(); NI++) { 00459 fprintf(F, "%d,%d\r\n", NI.GetKey().Val, NI.GetKey().Val); 00460 } 00461 00462 fprintf(F, "\r\n"); 00463 00464 for (TNGraph::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) { 00465 fprintf(F, "%d,%d\r\n", EI.GetSrcNId(), EI.GetDstNId()); 00466 } 00467 fclose(F); 00468 } 00469 00470 void TNetInfBs::SaveEdgeInfo(const TStr& OutFNm) { 00471 FILE *F = fopen(OutFNm.CStr(), "wt"); 00472 00473 fprintf(F, "src dst vol marginal_gain median_timediff average_timediff\n"); 00474 for (THash<TIntPr, TEdgeInfo>::TIter EI = EdgeInfoH.BegI(); EI < EdgeInfoH.EndI(); EI++) { 00475 TEdgeInfo &EdgeInfo = EI.GetDat(); 00476 fprintf(F, "%s/%s/%d/%f/%f/%f\n", 00477 NodeNmH.GetDat(EI.GetKey().Val1.Val).Name.CStr(), NodeNmH.GetDat(EI.GetKey().Val2.Val).Name.CStr(), 00478 EdgeInfo.Vol.Val, EdgeInfo.MarginalGain.Val, 00479 EdgeInfo.MedianTimeDiff.Val, 00480 EdgeInfo.AverageTimeDiff.Val); 00481 } 00482 fclose(F); 00483 } 00484 00485 void TNetInfBs::SaveObjInfo(const TStr& OutFNm) { 00486 TGnuPlot GnuPlot(OutFNm); 00487 00488 TFltV Objective; 00489 00490 for (THash<TIntPr, TEdgeInfo>::TIter EI = EdgeInfoH.BegI(); EI < EdgeInfoH.EndI(); EI++) { 00491 if (Objective.Len()==0) { Objective.Add(EI.GetDat().MarginalGain); 00492 } else { 00493 Objective.Add(Objective[Objective.Len()-1]+EI.GetDat().MarginalGain); 00494 } 00495 } 00496 00497 GnuPlot.AddPlot(Objective, gpwLinesPoints); 00498 00499 GnuPlot.SavePng(); 00500 } 00501 00502 void TNetInfBs::SaveGroundTruth(const TStr& OutFNm) { 00503 TFOut FOut(OutFNm); 00504 00505 // write nodes to file 00506 for (TNGraph::TNodeI NI = GroundTruth->BegNI(); NI < GroundTruth->EndNI(); NI++) { 00507 FOut.PutStr(TStr::Fmt("%d,%d\r\n", NI.GetId(), NI.GetId())); // nodes 00508 } 00509 00510 FOut.PutStr("\r\n"); 00511 00512 // write edges to file (not allowing self loops in the network) 00513 for (TNGraph::TEdgeI EI = GroundTruth->BegEI(); EI < GroundTruth->EndEI(); EI++) { 00514 // not allowing self loops in the Kronecker network 00515 if (EI.GetSrcNId() != EI.GetDstNId()) { 00516 if (Alphas.IsKey(TIntPr(EI.GetSrcNId(), EI.GetDstNId()))) 00517 FOut.PutStr(TStr::Fmt("%d,%d,%f\r\n", EI.GetSrcNId(), EI.GetDstNId(), Alphas.GetDat(TIntPr(EI.GetSrcNId(), EI.GetDstNId())).Val)); 00518 else 00519 FOut.PutStr(TStr::Fmt("%d,%d,1\r\n", EI.GetSrcNId(), EI.GetDstNId())); 00520 } 00521 } 00522 } 00523 00524 void TNetInfBs::SaveCascades(const TStr& OutFNm) { 00525 TFOut FOut(OutFNm); 00526 00527 // write nodes to file 00528 for (TNGraph::TNodeI NI = GroundTruth->BegNI(); NI < GroundTruth->EndNI(); NI++) { 00529 FOut.PutStr(TStr::Fmt("%d,%d\r\n", NI.GetId(), NI.GetId())); // nodes 00530 } 00531 00532 FOut.PutStr("\r\n"); 00533 00534 // write cascades to file 00535 for (int i=0; i<CascV.Len(); i++) { 00536 TCascade &C = CascV[i]; 00537 int j = 0; 00538 for (THash<TInt, THitInfo>::TIter NI = C.NIdHitH.BegI(); NI < C.NIdHitH.EndI(); NI++, j++) { 00539 if (j > 0) 00540 FOut.PutStr(TStr::Fmt(",%d,%f", NI.GetDat().NId.Val, NI.GetDat().Tm.Val)); 00541 else 00542 FOut.PutStr(TStr::Fmt("%d,%f", NI.GetDat().NId.Val, NI.GetDat().Tm.Val)); 00543 } 00544 00545 if (C.Len() >= 1) 00546 FOut.PutStr(TStr::Fmt("\r\n")); 00547 } 00548 }