Example #1
0
void
checkTNEANetCorrect(PNEANet G, PNEANet G2) {
  EXPECT_EQ(G->GetNodes(), G2->GetNodes());
  EXPECT_EQ(G->GetEdges(), G2->GetEdges());
  TStr attr2 = "int";
  TStr attr3 = "float";
  TStr attr1 = "str";
  EXPECT_EQ(G->GetNAIntI(attr2, 3).GetDat(), G2->GetNAIntI(attr2, 3).GetDat());
  EXPECT_EQ(G->GetNAIntI(attr2, 50).GetDat(), G2->GetNAIntI(attr2, 50).GetDat());
  EXPECT_EQ(G->GetNAFltI(attr3, 5).GetDat(), G2->GetNAFltI(attr3, 5).GetDat());
  EXPECT_EQ(G->GetNAFltI(attr3, 50).GetDat(), G2->GetNAFltI(attr3, 50).GetDat());
  EXPECT_EQ(G->GetNAStrI(attr1, 10).GetDat().LastCh(), G2->GetNAStrI(attr1, 10).GetDat().LastCh());
  EXPECT_EQ(G->GetNAStrI(attr1, 20).GetDat().LastCh(), G2->GetNAStrI(attr1, 20).GetDat().LastCh());
}
Example #2
0
 TPRManager(PNEANet &Net) : Net(Net), CapIndex(0), FlowV(Net->GetMxEId()), ExcessV(Net->GetMxNId()), EdgeNumsV(Net->GetMxNId()), LabelsV(Net->GetMxNId()), LabelCounts(Net->GetNodes() + 1), LabelLimit(0), MaxLabel(Net->GetNodes()), ActiveNodeSet(Net->GetMxNId()), ActiveCount(0) {
   CapIndex = Net->GetIntAttrIndE(CapAttrName);
   for (int i = 0; i <= Net->GetNodes(); i++) { LabelCounts[i] = 0; }
   for (TNEANet::TEdgeI EI = Net->BegEI(); EI != Net->EndEI(); EI++) {
     int EId = EI.GetId();
     IAssert(Capacity(EId) >= 0);
     FlowV[EId] = 0;
   }
   for (TNEANet::TNodeI NI = Net->BegNI(); NI != Net->EndNI(); NI++) {
     int NId = NI.GetId();
     ExcessV[NId] = 0;
     EdgeNumsV[NId] = 0;
     ActiveNodeSet[NId] = 0;
   }
   LabelCounts[0] = Net->GetNodes();
 }
Example #3
0
int GetWeightedPageRankMP1(const PNEANet Graph, TIntFltH& PRankH, const TStr& Attr, const double& C, const double& Eps, const int& MaxIter) {
  if (!Graph->IsFltAttrE(Attr)) return -1;

  TFltV Weights = Graph->GetFltAttrVecE(Attr);

  int mxid = Graph->GetMxNId();
  TFltV OutWeights(mxid);
  Graph->GetWeightOutEdgesV(OutWeights, Weights);
  /*for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    OutWeights[NI.GetId()] = Graph->GetWeightOutEdges(NI, Attr);
  }*/


  /*TIntFltH Weights;
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    Weights.AddDat(NI.GetId(), Graph->GetWeightOutEdges(NI, Attr));
  }*/

  const int NNodes = Graph->GetNodes();
  TVec<TNEANet::TNodeI> NV;
  //const double OneOver = 1.0/double(NNodes);
  PRankH.Gen(NNodes);
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    NV.Add(NI);
    PRankH.AddDat(NI.GetId(), 1.0/NNodes);
    //IAssert(NI.GetId() == PRankH.GetKey(PRankH.Len()-1));
  }
  TFltV TmpV(NNodes);
  for (int iter = 0; iter < MaxIter; iter++) {
    #pragma omp parallel for schedule(dynamic,10000)
    for (int j = 0; j < NNodes; j++) {
      TNEANet::TNodeI NI = NV[j];
      TmpV[j] = 0;
      for (int e = 0; e < NI.GetInDeg(); e++) {
        const int InNId = NI.GetInNId(e);
        const TFlt OutWeight = OutWeights[InNId];
        int EId = Graph->GetEId(InNId, NI.GetId());
        const TFlt Weight = Weights[Graph->GetFltKeyIdE(EId)];
        if (OutWeight > 0) {
          TmpV[j] += PRankH.GetDat(InNId) * Weight / OutWeight; }
      }
      TmpV[j] =  C*TmpV[j]; // Berkhin (the correct way of doing it)
      //TmpV[j] =  C*TmpV[j] + (1.0-C)*OneOver; // iGraph
    }
    double diff=0, sum=0, NewVal;
    #pragma omp parallel for reduction(+:sum) schedule(dynamic,10000)
    for (int i = 0; i < TmpV.Len(); i++) { sum += TmpV[i]; }
    const double Leaked = (1.0-sum) / double(NNodes);
    #pragma omp parallel for reduction(+:diff) schedule(dynamic,10000)
    for (int i = 0; i < PRankH.Len(); i++) { // re-instert leaked PageRank
      NewVal = TmpV[i] + Leaked; // Berkhin
      //NewVal = TmpV[i] / sum;  // iGraph
      diff += fabs(NewVal-PRankH[i]);
      PRankH[i] = NewVal;
    }
    if (diff < Eps) { break; }
  }
  return 0;
}
Example #4
0
// Test the default constructor
TEST(TNEANet, DefaultConstructor) {
  PNEANet Graph;

  Graph = TNEANet::New();

  EXPECT_EQ(0,Graph->GetNodes());
  EXPECT_EQ(0,Graph->GetEdges());

  EXPECT_EQ(1,Graph->IsOk());
  EXPECT_EQ(1,Graph->Empty());
  EXPECT_EQ(1,Graph->HasFlag(gfDirected));
}
Example #5
0
// Test small graph
TEST(TNEANet, GetSmallGraph) {
  PNEANet Graph;

  return;

  // not implemented
  //Graph = TNEANet::GetSmallGraph();

  EXPECT_EQ(5,Graph->GetNodes());
  EXPECT_EQ(6,Graph->GetEdges());

  EXPECT_EQ(1,Graph->IsOk());
  EXPECT_EQ(0,Graph->Empty());
  EXPECT_EQ(1,Graph->HasFlag(gfDirected));
}
Example #6
0
int GetMaxFlowIntPR (PNEANet &Net, const int& SrcNId, const int& SnkNId) {
  IAssert(Net->IsNode(SrcNId));
  IAssert(Net->IsNode(SnkNId));
  if (SrcNId == SnkNId) { return 0; }

  TPRManager PRM(Net);
  int MaxLabel = PRM.GetMaxLabel();

  TNEANet::TNodeI SrcNI = Net->GetNI(SrcNId);
  for (int EdgeN = 0; EdgeN < SrcNI.GetOutDeg(); EdgeN++) {
    int EId = SrcNI.GetOutEId(EdgeN);
    int OutNId = SrcNI.GetOutNId(EdgeN);
    if (OutNId != SrcNId) {
      int Capacity = PRM.Capacity(EId);
      PRM.Flow(EId) = Capacity;
      PRM.Excess(OutNId) = Capacity;
    }
  }
  GlobalRelabel(Net, PRM, SrcNId, SnkNId);
  PRM.SetLabel(SrcNId, MaxLabel);
  int RelabelCount = 1;
  int GRRate = Net->GetNodes();
  while (PRM.HasActive()) {
    int NId = PRM.PopActive();
    const TNEANet::TNodeI &NI = Net->GetNI(NId);
    int PrevLabel = MaxLabel;
    while (PRM.Excess(NId) > 0 && PRM.Label(NId) <= PrevLabel) {
      PrevLabel = PRM.Label(NId);
      int NbrNId = PushRelabel(PRM, NId, NI);
      if (NbrNId != -1 && NbrNId != SnkNId && PRM.Excess(NbrNId) > 0 && !PRM.IsActive(NbrNId)) {
        PRM.PushActive(NbrNId);
      }
    }
    if (PRM.Excess(NId) > 0 && PRM.Label(NId) < MaxLabel) {
      PRM.PushActive(NId);
    }
    if (RelabelCount % GRRate == 0) { GlobalRelabel(Net, PRM, SrcNId, SnkNId); }
  }
  return PRM.Excess(SnkNId);
}
Example #7
0
// Print graph statistics
void PrintGStats(const char s[], PNEANet Graph) {
  printf("graph %s, nodes %d, edges %d, empty %s\n",
      s, Graph->GetNodes(), Graph->GetEdges(),
      Graph->Empty() ? "yes" : "no");
}
Example #8
0
// Test node, edge creation
void ManipulateNodesEdges() {
  int NNodes = 1000;
  int NEdges = 100000;
  const char *FName = "demo.graph.dat";

  PNEANet Graph;
  PNEANet Graph1;
  PNEANet Graph2;
  int i;
  int n;
  int NCount;
  int ECount1;
  int ECount2;
  int x,y;
  bool t;

  Graph = TNEANet::New();
  t = Graph->Empty();

  // create the nodes
  for (i = 0; i < NNodes; i++) {
    Graph->AddNode(i);
  }
  n = Graph->GetNodes();
  t = Graph->Empty();

  // create random edges
  NCount = NEdges;
  while (NCount > 0) {
    x = rand() % NNodes;
    y = rand() % NNodes;
    n = Graph->AddEdge(x, y);
    NCount--;
  }
  PrintGStats("ManipulateNodesEdges:Graph",Graph);

  // get all the nodes
  NCount = 0;
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    NCount++;
  }

  // get all the edges for all the nodes
  ECount1 = 0;
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    for (int e = 0; e < NI.GetOutDeg(); e++) {
      ECount1++;
    }
  }

  // get all the edges directly
  ECount2 = 0;
  for (TNEANet::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
    ECount2++;
  }
  printf("graph ManipulateNodesEdges:Graph, nodes %d, edges1 %d, edges2 %d\n",
      NCount, ECount1, ECount2);

  // assignment
  Graph1 = TNEANet::New();
  *Graph1 = *Graph;
  PrintGStats("ManipulateNodesEdges:Graph1",Graph1);

  // save the graph
  {
    TFOut FOut(FName);
    Graph->Save(FOut);
    FOut.Flush();
  }

  // load the graph
  {
    TFIn FIn(FName);
    Graph2 = TNEANet::Load(FIn);
  }
  PrintGStats("ManipulateNodesEdges:Graph2",Graph2);

  // remove all the nodes and edges
  for (i = 0; i < NNodes; i++) {
    n = Graph->GetRndNId();
    Graph->DelNode(n);
  }

  PrintGStats("ManipulateNodesEdges:Graph",Graph);

  Graph1->Clr();
  PrintGStats("ManipulateNodesEdges:Graph1",Graph1);
}
Example #9
0
int main(int argc, char* argv[]) {
  Env = TEnv(argc, argv, TNotify::StdNotify);
  Env.PrepArgs(TStr::Fmt("Flow. build: %s, %s. Time: %s", __TIME__, __DATE__, TExeTm::GetCurTm()));
  double NetPRTimeSum = 0;
  double NetEKTimeSum = 0;
  int NumWins = 0;
  Try
  const TStr InFNm = Env.GetIfArgPrefixStr("-i:", "", "Input file");
  const int Iters = Env.GetIfArgPrefixInt("-n:", 10, "Number of runs per thread");
  const int Threads = Env.GetIfArgPrefixInt("-t:", 4, "Number of threads");
  printf("Integer Flow Test\n");
  printf("Filename: %s\n", InFNm.CStr());
  printf("Building Network...\n");
  TFIn InFile(InFNm);
  // If the input file is a binary, use the following line to load the network
  PNEANet Net = TNEANet::Load(InFile);
  // If the input file is a text file, use the following to load the network and save as binary
  // PNEANet Net;
  // int MaxEdgeCap = BuildCapacityNetwork(InFNm, Net);
  // const TStr OutFNm = Env.GetIfArgPrefixStr("-o:", "", "Output file");
  // TFOut OutFile(OutFNm);
  // Net->Save(OutFile);
  printf("PNEANet Nodes: %d, Edges: %d\n\n", Net->GetNodes(), Net->GetEdges());
  #pragma omp parallel for reduction(+:NetEKTimeSum,NetPRTimeSum,NumWins) schedule(static, 1)
  for (int t = 0; t < Threads; t++) {
    TRnd Random(t);
    for (int i = 0; i < Iters; i++) {
      int SrcNId = Net->GetRndNId(Random);
      int SnkNId = Net->GetRndNId(Random);

      double PRBeginTime = getcputime();
      int NetMaxFlowPR = TSnap::GetMaxFlowIntPR(Net, SrcNId, SnkNId);
      double PREndTime = getcputime();
      double NetPRFlowRunTime = PREndTime - PRBeginTime;

      double EKBeginTime = getcputime();
      int NetMaxFlowEK = TSnap::GetMaxFlowIntEK(Net, SrcNId, SnkNId);
      double EKEndTime = getcputime();
      double NetEKFlowRunTime = EKEndTime - EKBeginTime;
      
      IAssert(NetMaxFlowPR == NetMaxFlowEK);

      if (NetPRFlowRunTime < NetEKFlowRunTime) { NumWins++; }

      NetPRTimeSum += NetPRFlowRunTime;
      NetEKTimeSum += NetEKFlowRunTime;
      
      #pragma omp critical
      {
#ifndef NOMP
        printf("Thread: %d\n", omp_get_thread_num());
#endif
        printf("Source: %d, Sink %d\n", SrcNId, SnkNId);
        printf("Max Flow: %d\n", NetMaxFlowEK);
        printf("PR CPU Time: %f\n", NetPRFlowRunTime);
        printf("EK CPU Time: %f\n", NetEKFlowRunTime);
        printf("\n");
      }
    }
  }
  int TotalRuns = Iters*Threads;
  printf ("Avg PR PNEANet Time: %f\n", NetPRTimeSum/TotalRuns);
  printf ("Avg EK PNEANet Time: %f\n", NetEKTimeSum/TotalRuns);
  printf ("%d out of %d PR was faster\n", NumWins, TotalRuns);
  Catch
  return 0;
}
Example #10
0
int GetWeightedPageRankMP2(const PNEANet Graph, TIntFltH& PRankH, const TStr& Attr, const double& C, const double& Eps, const int& MaxIter) {
  if (!Graph->IsFltAttrE(Attr)) return -1;
  const int NNodes = Graph->GetNodes();
  TVec<TNEANet::TNodeI> NV;

  //const double OneOver = 1.0/double(NNodes);
  PRankH.Gen(NNodes);
  int MxId;

  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    NV.Add(NI);
    PRankH.AddDat(NI.GetId(), 1.0/NNodes);
    int Id = NI.GetId();
    if (Id > MxId) {
      MxId = Id;
    }
  }

  TFltV PRankV(MxId+1);
  TFltV OutWeights(MxId+1);

  TFltV Weights = Graph->GetFltAttrVecE(Attr);

  #pragma omp parallel for schedule(dynamic,10000)
  for (int j = 0; j < NNodes; j++) {
    TNEANet::TNodeI NI = NV[j];
    int Id = NI.GetId();
    OutWeights[Id] = Graph->GetWeightOutEdges(NI, Attr);
    PRankV[Id] = 1/NNodes;
  }

  TFltV TmpV(NNodes);
  for (int iter = 0; iter < MaxIter; iter++) {

    #pragma omp parallel for schedule(dynamic,10000)
    for (int j = 0; j < NNodes; j++) {
      TNEANet::TNodeI NI = NV[j];
      TFlt Tmp = 0;
      for (int e = 0; e < NI.GetInDeg(); e++) {
        const int InNId = NI.GetInNId(e);

        const TFlt OutWeight = OutWeights[InNId];

        int EId = Graph->GetEId(InNId, NI.GetId());
        const TFlt Weight = Weights[Graph->GetFltKeyIdE(EId)];

        if (OutWeight > 0) {
          Tmp += PRankH.GetDat(InNId) * Weight / OutWeight; 
        }
      }
      TmpV[j] =  C*Tmp; // Berkhin (the correct way of doing it)
      //TmpV[j] =  C*TmpV[j] + (1.0-C)*OneOver; // iGraph
    }

    double sum = 0;
    #pragma omp parallel for reduction(+:sum) schedule(dynamic,10000)
    for (int i = 0; i < TmpV.Len(); i++) { sum += TmpV[i]; }
    const double Leaked = (1.0-sum) / double(NNodes);

    double diff = 0;
    #pragma omp parallel for reduction(+:diff) schedule(dynamic,10000)
    for (int i = 0; i < NNodes; i++) {
      TNEANet::TNodeI NI = NV[i];
      double NewVal = TmpV[i] + Leaked; // Berkhin
      //NewVal = TmpV[i] / sum;  // iGraph
      int Id = NI.GetId();
      diff += fabs(NewVal-PRankV[Id]);
      PRankV[Id] = NewVal;
    }
    if (diff < Eps) { break; }
  }

  #pragma omp parallel for schedule(dynamic,10000)
  for (int i = 0; i < NNodes; i++) {
    TNEANet::TNodeI NI = NV[i];
    PRankH[i] = PRankV[NI.GetId()];
  }

  return 0;
}
Example #11
0
// Test node, edge creation
TEST(TNEANet, ManipulateNodesEdges) {
  int NNodes = 1000;
  int NEdges = 100000;
  const char *FName = "test.graph.dat";

  PNEANet Graph;
  PNEANet Graph1;
  PNEANet Graph2;
  int i;
  int n;
  int NCount;
  int x,y;
  int Deg, InDeg, OutDeg;

  Graph = TNEANet::New();
  EXPECT_EQ(1,Graph->Empty());

  // create the nodes
  for (i = 0; i < NNodes; i++) {
    Graph->AddNode(i);
  }
  EXPECT_EQ(0,Graph->Empty());
  EXPECT_EQ(NNodes,Graph->GetNodes());

  // create random edges
  NCount = NEdges;
  while (NCount > 0) {
    x = (long) (drand48() * NNodes);
    y = (long) (drand48() * NNodes);
    n = Graph->AddEdge(x, y);
    NCount--;
  }

  EXPECT_EQ(NEdges,Graph->GetEdges());

  EXPECT_EQ(0,Graph->Empty());
  EXPECT_EQ(1,Graph->IsOk());

  for (i = 0; i < NNodes; i++) {
    EXPECT_EQ(1,Graph->IsNode(i));
  }

  EXPECT_EQ(0,Graph->IsNode(NNodes));
  EXPECT_EQ(0,Graph->IsNode(NNodes+1));
  EXPECT_EQ(0,Graph->IsNode(2*NNodes));

  // nodes iterator
  NCount = 0;
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    NCount++;
  }
  EXPECT_EQ(NNodes,NCount);

  // edges per node iterator
  NCount = 0;
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    for (int e = 0; e < NI.GetOutDeg(); e++) {
      NCount++;
    }
  }
  EXPECT_EQ(NEdges,NCount);

  // edges iterator
  NCount = 0;
  for (TNEANet::TEdgeI EI = Graph->BegEI(); EI < Graph->EndEI(); EI++) {
    NCount++;
  }
  EXPECT_EQ(NEdges,NCount);

  // node degree
  for (TNEANet::TNodeI NI = Graph->BegNI(); NI < Graph->EndNI(); NI++) {
    Deg = NI.GetDeg();
    InDeg = NI.GetInDeg();
    OutDeg = NI.GetOutDeg();

    EXPECT_EQ(Deg,InDeg+OutDeg);
  }

  // assignment
  Graph1 = TNEANet::New();
  *Graph1 = *Graph;

  EXPECT_EQ(NNodes,Graph1->GetNodes());
  EXPECT_EQ(NEdges,Graph1->GetEdges());
  EXPECT_EQ(0,Graph1->Empty());
  EXPECT_EQ(1,Graph1->IsOk());

  // saving and loading
  {
    TFOut FOut(FName);
    Graph->Save(FOut);
    FOut.Flush();
  }

  {
    TFIn FIn(FName);
    Graph2 = TNEANet::Load(FIn);
  }

  EXPECT_EQ(NNodes,Graph2->GetNodes());
  EXPECT_EQ(NEdges,Graph2->GetEdges());
  EXPECT_EQ(0,Graph2->Empty());
  EXPECT_EQ(1,Graph2->IsOk());

  // remove all the nodes and edges
  for (i = 0; i < NNodes; i++) {
    n = Graph->GetRndNId();
    Graph->DelNode(n);
  }

  EXPECT_EQ(0,Graph->GetNodes());
  EXPECT_EQ(0,Graph->GetEdges());

  EXPECT_EQ(1,Graph->IsOk());
  EXPECT_EQ(1,Graph->Empty());

  Graph1->Clr();

  EXPECT_EQ(0,Graph1->GetNodes());
  EXPECT_EQ(0,Graph1->GetEdges());

  EXPECT_EQ(1,Graph1->IsOk());
  EXPECT_EQ(1,Graph1->Empty());
}
Example #12
0
// 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();
}