void TSkyGridEnt::GetEntClustV(const TSkyGridBs* SkyGridBs, const uint64& MnTm, const int& MnDocs, const int& MxDocs, const int& Clusts, TVec<TStrFltPrV>& EntNmWgtPrVV) const { EntNmWgtPrVV.Clr(); // create bow PBowDocBs BowDocBs=TBowDocBs::New(); // collect documents TIntV DocIdV; GetDocIdV(SkyGridBs, MnTm, 0, DocIdV); DocIdV.Reverse(); DocIdV.Shuffle(TRnd(1)); DocIdV.Trunc(MxDocs); if (DocIdV.Len()<MnDocs){return;} for (int DocN=0; DocN<DocIdV.Len(); DocN++){ int DocId=DocIdV[DocN]; PSkyGridDoc Doc=SkyGridBs->GetDoc(DocId); // create vector of entity-weights TIntFltPrV WIdWgtPrV; for (int EntN=0; EntN<Doc->GetEnts(); EntN++){ int EntId; int EntFq; Doc->GetEntNmFq(EntN, EntId, EntFq); TStr EntNm=SkyGridBs->GetEntNm(EntId); int EntWId=BowDocBs->AddWordStr(EntNm); WIdWgtPrV.Add(TIntFltPr(EntWId, EntFq)); } // create bow-document int DId=BowDocBs->AddDoc(TInt::GetStr(DocId), TStrV(), WIdWgtPrV); TStr DocDescStr=Doc->GetTitleStr(); BowDocBs->PutDocDescStr(DId, DocDescStr); } // k-means clustering PBowSim BowSim=TBowSim::New(bstCos); // similarity object TBowWordWgtType WordWgtType=bwwtNrmTFIDF; // define weighting PBowDocPart BowDocPart=TBowClust::GetKMeansPart( TNotify::StdNotify, // log output BowDocBs, // document data BowSim, // similarity function TRnd(1), // random generator Clusts, // number of clusters 1, // trials per k-means 1, // convergence epsilon for k-means 1, // min. documents per cluster WordWgtType, // word weighting 0, // cut-word-weights percentage 0); // minimal word frequency EntNmWgtPrVV.Clr(); for (int ClustN=0; ClustN<BowDocPart->GetClusts(); ClustN++){ PBowDocPartClust Clust=BowDocPart->GetClust(ClustN); TStrFltPrV WordStrWgtPrV; Clust->GetTopWordStrWgtPrV(BowDocBs, 25, 0.5, WordStrWgtPrV); EntNmWgtPrVV.Add(WordStrWgtPrV); } //BowDocPart->SaveTxt("Clusts.Txt", BowDocBs, true, 25, 0.5, false); }
/// Clique Percolation method communities void TCliqueOverlap::GetCPMCommunities(const PUNGraph& G, int MinMaxCliqueSize, TVec<TIntV>& NIdCmtyVV) { printf("Clique Percolation Method\n"); TExeTm ExeTm; TVec<TIntV> MaxCliques; TCliqueOverlap::GetMaxCliques(G, MinMaxCliqueSize, MaxCliques); // op RS 2012/05/15, commented out next line, a parameter is missing, // creating a warning on OS X // printf("...%d cliques found\n"); // get clique overlap matrix (graph) PUNGraph OverlapGraph = TCliqueOverlap::CalculateOverlapMtx(MaxCliques, MinMaxCliqueSize-1); printf("...overlap matrix (%d, %d)\n", G->GetNodes(), G->GetEdges()); // connected components are communities TCnComV CnComV; TSnap::GetWccs(OverlapGraph, CnComV); NIdCmtyVV.Clr(false); TIntSet CmtySet; for (int c = 0; c < CnComV.Len(); c++) { CmtySet.Clr(false); for (int i = 0; i <CnComV[c].Len(); i++) { const TIntV& CliqueNIdV = MaxCliques[CnComV[c][i]]; CmtySet.AddKeyV(CliqueNIdV); } NIdCmtyVV.Add(); CmtySet.GetKeyV(NIdCmtyVV.Last()); NIdCmtyVV.Last().Sort(); } printf("done [%s].\n", ExeTm.GetStr()); }
void GetSngVec(const PNGraph& Graph, const int& SngVecs, TFltV& SngValV, TVec<TFltV>& LeftSV, TVec<TFltV>& RightSV) { const int Nodes = Graph->GetNodes(); SngValV.Clr(); LeftSV.Clr(); RightSV.Clr(); TFltVV LSingV, RSingV; if (Nodes < 100) { // perform full SVD TFltVV AdjMtx(Nodes+1, Nodes+1); TIntH NodeIdH; // create adjecency matrix (1-based) for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { NodeIdH.AddKey(NodeI.GetId()); } for (TNGraph::TNodeI NodeI = Graph->BegNI(); NodeI < Graph->EndNI(); NodeI++) { const int NodeId = NodeIdH.GetKeyId(NodeI.GetId())+1; for (int e = 0; e < NodeI.GetOutDeg(); e++) { const int DstNId = NodeIdH.GetKeyId(NodeI.GetOutNId(e))+1; // no self edges if (NodeId != DstNId) AdjMtx.At(NodeId, DstNId) = 1; } } try { // can fail to converge but results seem to be good TSvd::Svd1Based(AdjMtx, LSingV, SngValV, RSingV); } catch(...) { printf("\n***No SVD convergence: G(%d, %d)\n", Nodes, Graph->GetEdges()); } } else { // Lanczos TNGraphMtx GraphMtx(Graph); TSparseSVD::LanczosSVD(GraphMtx, SngVecs, 2*SngVecs, ssotFull, SngValV, LSingV, RSingV); //TGAlg::SaveFullMtx(Graph, "adj_mtx.txt"); //TLAMisc::DumpTFltVVMjrSubMtrx(LSingV, LSingV.GetRows(), LSingV.GetCols(), "LSingV2.txt"); // save MTX } TFltIntPrV SngValIdV; for (int i = 0; i < SngValV.Len(); i++) { SngValIdV.Add(TFltIntPr(SngValV[i], i)); } SngValIdV.Sort(false); SngValV.Sort(false); for (int v = 0; v < SngValIdV.Len(); v++) { LeftSV.Add(); LSingV.GetCol(SngValIdV[v].Val2, LeftSV.Last()); RightSV.Add(); RSingV.GetCol(SngValIdV[v].Val2, RightSV.Last()); } IsAllValVNeg(LeftSV[0], true); IsAllValVNeg(RightSV[0], true); }
///Generate bipartite community affiliation from given power law coefficients for membership distribution and community size distribution. void TAGMUtil::GenCmtyVVFromPL(TVec<TIntV>& CmtyVV, const PUNGraph& Graph, const int& Nodes, const int& Coms, const double& ComSzAlpha, const double& MemAlpha, const int& MinSz, const int& MaxSz, const int& MinK, const int& MaxK, TRnd& Rnd) { if (Coms == 0 || Nodes == 0) { CmtyVV.Clr(); return; } TIntV NIDV; Graph->GetNIdV(NIDV); GenCmtyVVFromPL(CmtyVV, NIDV, Nodes, Coms, ComSzAlpha, MemAlpha, MinSz, MaxSz, MinK, MaxK, Rnd); }
int TStrUtil::SplitWords(TChA& ChA, TVec<char *>& WrdV, const bool& SplitOnWs) { WrdV.Clr(false); WrdV.Add(ChA.CStr()); for (char *c = (char *) ChA.CStr(); *c; c++) { if ((SplitOnWs && *c == ' ') || (! SplitOnWs && ! TCh::IsAlNum(*c))) { *c = 0; if (! WrdV.Empty() && strlen(WrdV.Last()) == 0) { WrdV.DelLast(); } WrdV.Add(c+1); } } return WrdV.Len(); }
int TStrUtil::SplitOnCh(TChA& ChA, TVec<char *>& WrdV, const char& Ch, const bool& SkipEmpty) { WrdV.Clr(false); WrdV.Add(ChA.CStr()); for (char *c = (char *) ChA.CStr(); *c; c++) { if (*c == Ch) { *c = 0; if (SkipEmpty && ! WrdV.Empty() && strlen(WrdV.Last()) == 0) { WrdV.DelLast(); } WrdV.Add(c+1); } } if (SkipEmpty && ! WrdV.Empty() && strlen(WrdV.Last()) == 0) { WrdV.DelLast(); } return WrdV.Len(); }
///Generate bipartite community affiliation from given power law coefficients for membership distribution and community size distribution. void TAGMUtil::GenCmtyVVFromPL(TVec<TIntV>& CmtyVV, const TIntV& NIDV, const int& Nodes, const int& Coms, const double& ComSzAlpha, const double& MemAlpha, const int& MinSz, const int& MaxSz, const int& MinK, const int& MaxK, TRnd& Rnd) { if (Coms == 0 || Nodes == 0) { CmtyVV.Clr(); return; } TIntV ComSzSeq, MemSeq; TAGMUtil::GenPLSeq(ComSzSeq,Coms,ComSzAlpha,Rnd,MinSz,MaxSz); TAGMUtil::GenPLSeq(MemSeq,Nodes,MemAlpha,Rnd,MinK,MaxK); TIntPrV CIDSzPrV, NIDMemPrV; for (int i = 0; i < ComSzSeq.Len(); i++) { CIDSzPrV.Add(TIntPr(i, ComSzSeq[i])); } for (int i = 0; i < MemSeq.Len(); i++) { NIDMemPrV.Add(TIntPr(NIDV[i], MemSeq[i])); } TAGMUtil::ConnectCmtyVV(CmtyVV, CIDSzPrV, NIDMemPrV, Rnd); }
int TStrUtil::SplitLines(TChA& ChA, TVec<char *>& LineV, const bool& SkipEmpty) { LineV.Clr(false); LineV.Add(ChA.CStr()); bool IsChs=false; for (char *c = (char *) ChA.CStr(); *c; c++) { if (*c == '\n') { if (c > ChA.CStr() && *(c-1)=='\r') { *(c-1)=0; } // \r\n *c=0; if (SkipEmpty) { if (IsChs) { LineV.Add(c+1); } } else { LineV.Add(c+1); } IsChs=false; } else { IsChs=true; } } return LineV.Len(); }
int TStrUtil::SplitSentences(TChA& ChA, TVec<char *>& SentenceV) { SentenceV.Clr(); const char *B = ChA.CStr(); const char *E = B+ChA.Len(); char *c = (char *) B; while (*c && TCh::IsWs(*c)) { c++; } if (*c) { SentenceV.Add(c); } else { return 0; } for (; c < E; c++) { if (c<E && (*c == '.' || *c == '!' || *c == '?') && ! TCh::IsAlNum(*(c+1))) { // end of sentence if (c<E && *(c+1)=='"') { *c='"'; c++; } // blah." --> blah" if (c>=E) { continue; } *c=0; c++; char *e = c-1; while (e>B && *e!='"' && ! TCh::IsAlNum(*e)) { *e=0; e--; } // skip trailing non-alpha-num chars while (c<E && ! (TCh::IsAlNum(*c) || (*c=='"' && TCh::IsAlNum(*(c+1))))) { c++; } // sentence starts with AlNum or "AlNum if (c<E) { SentenceV.Add(c); } } } return SentenceV.Len(); }
///////////////////////////////////////////////// // Epidemiological modeling and model fitting void TEpidemModel::RunModel(const TFltV& StartValV, const double& StartT, const double& StopT, const int& NSteps, TVec<TFltV>& OutValV) { TFltV ValV(StartValV), dydx(StartValV.Len()), ValV2(StartValV.Len()); OutValV.Clr(false); for (int v = 0; v < StartValV.Len(); v++) { OutValV.Add(); OutValV[v].Clr(false); OutValV[v].Add(StartValV[v]); } const double h = (StopT-StartT) / NSteps; double x = StartT; for (int k = 0; k < NSteps; k++) { GetDerivs(x, ValV, dydx); RungeKutta(ValV, dydx, x, h, ValV2); for (int v = 0; v < ValV2.Len(); v++) { double X = ValV2[v]; if (X < 0 || _isnan(X) || !_finite(X)) { X = 0; } OutValV[v].Add(X); } ValV = ValV2; x += h; } }
// run the model internally with 10 times greater resolution void TEpidemModel::RunModel10(const TFltV& StartValV, const double& StartT, const double& StopT, const int& NSteps, TVec<TFltV>& OutValV) { TFltV ValV(StartValV), dydx(StartValV.Len()), ValV2(StartValV.Len()); OutValV.Clr(false); for (int v = 0; v < StartValV.Len(); v++) { OutValV.Add(); OutValV[v].Clr(false); OutValV[v].Add(StartValV[v]); } const double h = (StopT-StartT) / (10*NSteps); double x = StartT; for (int k = 0; k < 10*NSteps; k++) { GetDerivs(x, ValV, dydx); RungeKutta(ValV, dydx, x, h, ValV2); // take values at only every 10th step if (k % 10 == 0) { for (int v = 0; v < ValV2.Len(); v++) { OutValV[v].Add(ValV2[v]); } } ValV = ValV2; x += h; } }
// Essesntially the same as TssParser::Next // For parallel load, FldV cannot be shared across many threads void TSsParserMP::NextFromIndex(uint64 Index, TVec<char*>& FieldsV) { // split on SplitCh FieldsV.Clr(); char* cur = FInPt->GetLine(Index); if (SkipLeadBlanks) { // skip leading blanks while (*cur && TCh::IsWs(*cur)) { cur++; } } char *last = cur; while (*cur != 0 && *cur != '\n') { if (SsFmt == ssfWhiteSep) { while (*cur && (*cur != '\n') && ! TCh::IsWs(*cur)) { cur++; } } else { while (*cur && *cur!=SplitCh && (*cur != '\n')) { cur++; } } if (*cur == 0) { break; } if (*cur == '\n') { break; } //*cur = 0; cur++; FieldsV.Add(last); last = cur; if (SkipEmptyFld && strlen(FieldsV.Last())==0) { FieldsV.DelLast(); } // skip empty fields } FieldsV.Add(last); // add last field }
void TCliqueOverlap::CalculateOverlapMtx(const TVec<TIntV>& MaxCliques, int MinNodeOverlap, TVec<TIntV>& OverlapMtx) { OverlapMtx.Clr(); // int n = MaxCliques.Len(); //Convert max cliques to HashSets TVec<THashSet<TInt> > cliques; for (int i=0; i<n; i++) { const int len = MaxCliques[i].Len(); cliques.Add(); if (len < MinNodeOverlap) { continue; } THashSet<TInt>& set = cliques.Last(); set.Gen(len); for (int j=0; j<len; j++) { set.AddKey(MaxCliques[i][j]); } } //Init clique clique overlap matrix n = cliques.Len(); OverlapMtx.Gen(n); for (int i=0; i<n; i++) OverlapMtx[i].Gen(n); //Calculate clique clique overlap matrix for (int i=0; i<n; i++) { OverlapMtx[i][i] = cliques[i].Len(); for (int j=i+1; j<n; j++) { OverlapMtx[i][j] = Intersection(cliques[i], cliques[j]); } } }
/// Enumerate maximal cliques of the network on more than MinMaxCliqueSize nodes void TCliqueOverlap::GetMaxCliques(const PUNGraph& G, int MinMaxCliqueSize, TVec<TIntV>& MaxCliques) { TCliqueOverlap CO; MaxCliques.Clr(false); CO.GetMaximalCliques(G, MinMaxCliqueSize, MaxCliques); }
// Test node, edge attribute functionality TEST(TNEANet, ManipulateNodesEdgeAttributes) { int NNodes = 1000; int NEdges = 1000; const char *FName = "demo.graph.dat"; PNEANet Graph; PNEANet Graph1; int i; int x, y; bool t; Graph = TNEANet::New(); t = Graph->Empty(); // create the nodes for (i = NNodes - 1; i >= 0; i--) { Graph->AddNode(i); } EXPECT_EQ(NNodes, Graph->GetNodes()); // create the edges for (i = NEdges - 1; i >= 0; i--) { x = (long) (drand48() * NNodes); y = (long) (drand48() * NNodes); Graph->AddEdge(x, y, i); } // create attributes and fill all nodes TStr attr1 = "str"; TStr attr2 = "int"; TStr attr3 = "float"; TStr attr4 = "default"; // Test vertical int iterator for node 3, 50, 700, 900 // Check if we can set defaults to 0 for Int data. Graph->AddIntAttrN(attr2, 0); Graph->AddIntAttrDatN(3, 3*2, attr2); Graph->AddIntAttrDatN(50, 50*2, attr2); Graph->AddIntAttrDatN(700, 700*2, attr2); Graph->AddIntAttrDatN(900, 900*2, attr2); EXPECT_EQ(3*2, Graph->GetNAIntI(attr2, 3).GetDat()); EXPECT_EQ(50*2, Graph->GetNAIntI(attr2, 50).GetDat()); int NodeId = 0; int DefNodes = 0; TVec<TInt> TAIntIV = TVec<TInt>(); for (TNEANet::TAIntI NI = Graph->BegNAIntI(attr2); NI < Graph->EndNAIntI(attr2); NI++) { if (NI.GetDat()() != 0) { TAIntIV.Add(NI.GetDat()); NodeId++; } else { DefNodes++; } } EXPECT_EQ(4, NodeId); EXPECT_EQ(NNodes - 4, DefNodes); TAIntIV.Sort(); EXPECT_EQ(3*2, TAIntIV[0]); EXPECT_EQ(50*2, TAIntIV[1]); EXPECT_EQ(700*2, TAIntIV[2]); EXPECT_EQ(900*2, TAIntIV[3]); // Test vertical flt iterator for node 3, 50, 700, 900 Graph->AddFltAttrDatN(5, 3.41, attr3); Graph->AddFltAttrDatN(50, 2.718, attr3); Graph->AddFltAttrDatN(300, 150.0, attr3); Graph->AddFltAttrDatN(653, 563, attr3); EXPECT_EQ(3.41, Graph->GetNAFltI(attr3, 5).GetDat()); EXPECT_EQ(2.718, Graph->GetNAFltI(attr3, 50).GetDat()); NodeId = 0; DefNodes = 0; TVec<TFlt> TAFltIV = TVec<TFlt>(); for (TNEANet::TAFltI NI = Graph->BegNAFltI(attr3); NI < Graph->EndNAFltI(attr3); NI++) { if (NI.GetDat() != TFlt::Mn) { NodeId++; TAFltIV.Add(NI.GetDat()); } else { DefNodes++; } } EXPECT_EQ(4, NodeId); EXPECT_EQ(NNodes - 4, DefNodes); TAFltIV.Sort(); EXPECT_EQ(2.718, TAFltIV[0]); EXPECT_EQ(3.41, TAFltIV[1]); EXPECT_EQ(150.0, TAFltIV[2]); EXPECT_EQ(563.0, TAFltIV[3]); // Test vertical str iterator for node 3, 50, 700, 900 Graph->AddStrAttrDatN(10, "abc", attr1); Graph->AddStrAttrDatN(20, "def", attr1); Graph->AddStrAttrDatN(400, "ghi", attr1); // this does not show since ""=null Graph->AddStrAttrDatN(455, "", attr1); EXPECT_EQ('c', Graph->GetNAStrI(attr1, 10).GetDat().LastCh()); EXPECT_EQ('f', Graph->GetNAStrI(attr1, 20).GetDat().LastCh()); NodeId = 0; DefNodes = 0; TVec<TStr> TAStrIV = TVec<TStr>(); for (TNEANet::TAStrI NI = Graph->BegNAStrI(attr1); NI < Graph->EndNAStrI(attr1); NI++) { if (NI.GetDat() != TStr::GetNullStr()) { NodeId++; TAStrIV.Add(NI.GetDat()); } else { DefNodes++; } } EXPECT_EQ(3, NodeId); EXPECT_EQ(NNodes - 3, DefNodes); TAStrIV.Sort(); // TODO(nkhadke): Fix hack to compare strings properly. This works for now. EXPECT_EQ('c', TAStrIV[0].LastCh()); EXPECT_EQ('f', TAStrIV[1].LastCh()); EXPECT_EQ('i', TAStrIV[2].LastCh()); // Test vertical iterator over many types (must skip default/deleted attr) int NId = 55; Graph->AddStrAttrDatN(NId, "aaa", attr1); Graph->AddIntAttrDatN(NId, 3*2, attr2); Graph->AddFltAttrDatN(NId, 3.41, attr3); Graph->AddStrAttrDatN(80, "dont appear", attr4); // should not show up TStrV NIdAttrName; Graph->AttrNameNI(NId, NIdAttrName); int AttrLen = NIdAttrName.Len(); NodeId = 0; DefNodes = 0; EXPECT_EQ(3, AttrLen); Graph->DelAttrDatN(NId, attr2); Graph->AttrNameNI(NId, NIdAttrName); AttrLen = NIdAttrName.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("int") == NIdAttrName[i]()) { // FAIL EXPECT_EQ(1,2); } } EXPECT_EQ(2, AttrLen); Graph->AddIntAttrDatN(NId, 3*2, attr2); Graph->DelAttrN(attr1); Graph->AttrNameNI(NId, NIdAttrName); AttrLen = NIdAttrName.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("str") == NIdAttrName[i]()) { // FAIL EXPECT_EQ(1,2); } } EXPECT_EQ(2, AttrLen); TStrV NIdAttrValue; Graph->AttrValueNI(NId, NIdAttrValue); AttrLen = NIdAttrValue.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("str") == NIdAttrValue[i]()) { // FAIL EXPECT_EQ(1,2); } } int expectedTotal = 0; for (i = 0; i <NNodes; i++) { Graph->AddIntAttrDatN(i, NNodes+i, attr2); EXPECT_EQ(NNodes+i, Graph->GetIntAttrDatN(i, attr2)); expectedTotal += NNodes+i; } { TFOut FOut(FName); Graph->Save(FOut); FOut.Flush(); } { TFIn FIn(FName); Graph1 = TNEANet::Load(FIn); } int total = 0; for (TNEANet::TAIntI NI = Graph1->BegNAIntI(attr2); NI < Graph1->EndNAIntI(attr2); NI++) { total += NI.GetDat(); } ASSERT_EQ(expectedTotal, total); Graph1->Clr(); // Test vertical int iterator for edge Graph->AddIntAttrDatE(3, 3*2, attr2); Graph->AddIntAttrDatE(55, 55*2, attr2); Graph->AddIntAttrDatE(705, 705*2, attr2); Graph->AddIntAttrDatE(905, 905*2, attr2); EXPECT_EQ(3*2, Graph->GetEAIntI(attr2, 3).GetDat()); EXPECT_EQ(55*2, Graph->GetEAIntI(attr2, 55).GetDat()); int EdgeId = 0; int DefEdges = 0; TAIntIV.Clr(); for (TNEANet::TAIntI EI = Graph->BegEAIntI(attr2); EI < Graph->EndEAIntI(attr2); EI++) { if (EI.GetDat() != TInt::Mn) { TAIntIV.Add(EI.GetDat()); EdgeId++; } else { DefEdges++; } } EXPECT_EQ(4, EdgeId); EXPECT_EQ(NEdges - 4, DefEdges); TAIntIV.Sort(); EXPECT_EQ(3*2, TAIntIV[0]); EXPECT_EQ(55*2, TAIntIV[1]); EXPECT_EQ(705*2, TAIntIV[2]); EXPECT_EQ(905*2, TAIntIV[3]); // Test vertical flt iterator for edge Graph->AddFltAttrE(attr3, 0.00); Graph->AddFltAttrDatE(5, 4.41, attr3); Graph->AddFltAttrDatE(50, 3.718, attr3); Graph->AddFltAttrDatE(300, 151.0, attr3); Graph->AddFltAttrDatE(653, 654, attr3); EXPECT_EQ(4.41, Graph->GetEAFltI(attr3, 5).GetDat()); EXPECT_EQ(3.718, Graph->GetEAFltI(attr3, 50).GetDat()); EdgeId = 0; DefEdges = 0; TAFltIV.Clr(); for (TNEANet::TAFltI EI = Graph->BegEAFltI(attr3); EI < Graph->EndEAFltI(attr3); EI++) { // Check if defaults are set to 0. if (EI.GetDat() != 0.00) { TAFltIV.Add(EI.GetDat()); EdgeId++; } else { DefEdges++; } } EXPECT_EQ(4, EdgeId); EXPECT_EQ(NEdges - 4, DefEdges); TAFltIV.Sort(); EXPECT_EQ(3.718, TAFltIV[0]); EXPECT_EQ(4.41, TAFltIV[1]); EXPECT_EQ(151.0, TAFltIV[2]); EXPECT_EQ(654.0, TAFltIV[3]); // Test vertical str iterator for edge Graph->AddStrAttrDatE(10, "abc", attr1); Graph->AddStrAttrDatE(20, "def", attr1); Graph->AddStrAttrDatE(400, "ghi", attr1); // this does not show since ""=null Graph->AddStrAttrDatE(455, "", attr1); EXPECT_EQ('c', Graph->GetEAStrI(attr1, 10).GetDat().LastCh()); EXPECT_EQ('f', Graph->GetEAStrI(attr1, 20).GetDat().LastCh()); EdgeId = 0; DefEdges = 0; TAStrIV.Clr(); for (TNEANet::TAStrI EI = Graph->BegEAStrI(attr1); EI < Graph->EndEAStrI(attr1); EI++) { if (EI.GetDat() != TStr::GetNullStr()) { TAStrIV.Add(EI.GetDat()); EdgeId++; } else { DefEdges++; } } EXPECT_EQ(3, EdgeId); EXPECT_EQ(NEdges - 3, DefEdges); TAStrIV.Sort(); // TODO(nkhadke): Fix hack to compare strings properly. This works for now. EXPECT_EQ('c', TAStrIV[0].LastCh()); EXPECT_EQ('f', TAStrIV[1].LastCh()); EXPECT_EQ('i', TAStrIV[2].LastCh()); // Test vertical iterator over many types (must skip default/deleted attr) int EId = 55; Graph->AddStrAttrDatE(EId, "aaa", attr1); Graph->AddIntAttrDatE(EId, 3*2, attr2); Graph->AddFltAttrDatE(EId, 3.41, attr3); Graph->AddStrAttrDatE(80, "dont appear", attr4); // should not show up TStrV EIdAttrName; Graph->AttrNameEI(EId, EIdAttrName); AttrLen = EIdAttrName.Len(); EXPECT_EQ(3, AttrLen); Graph->DelAttrDatE(EId, attr2); Graph->AttrNameEI(EId, EIdAttrName); AttrLen = EIdAttrName.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("int") == EIdAttrName[i]()) { // FAIL EXPECT_EQ(2,3); } } Graph->AddIntAttrDatE(EId, 3*2, attr2); Graph->DelAttrE(attr1); Graph->AttrNameEI(EId, EIdAttrName); AttrLen = EIdAttrName.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("aaa") == EIdAttrName[i]()) { // FAIL EXPECT_EQ(2,3); } } TStrV EIdAttrValue; Graph->AttrValueEI(EId, EIdAttrValue); AttrLen = EIdAttrValue.Len(); for (i = 0; i < AttrLen; i++) { if (TStr("str") == EIdAttrValue[i]()) { // FAIL EXPECT_EQ(2,3); } } expectedTotal = 0; for (i = 0; i <NEdges; i++) { Graph->AddIntAttrDatE(i, NEdges+i, attr2); EXPECT_EQ(NEdges+i, Graph->GetIntAttrDatE(i, attr2)); expectedTotal += NEdges+i; } { TFOut FOut(FName); Graph->Save(FOut); FOut.Flush(); Graph->Clr(); } { TFIn FIn(FName); Graph1 = TNEANet::Load(FIn); } total = 0; for (TNEANet::TAIntI EI = Graph1->BegNAIntI(attr2); EI < Graph1->EndNAIntI(attr2); EI++) { total += EI.GetDat(); } EXPECT_EQ(expectedTotal, total); //Graph1->Dump(); Graph1->Clr(); }