text: ////////////////////////////////////////////////
  // Forward declarations
  class TGrowthStat;
  typedef TPt<TGrowthStat> PGrowthStat;
  class TGStatVec;
  typedef TPt<TGStatVec> PGStatVec;
  
  class TTimeNet;
  typedef TPt<TTimeNet> PTimeNet;
  
  class TTimeNENet;
  typedef TPt<TTimeNENet> PTimeNENet;
  
  /////////////////////////////////////////////////
  // Time Network
  class TTimeNet : public TNodeNet<TSecTm> {
  public:
    typedef TNodeNet<TSecTm> TNet;
    typedef TPt<TNodeNet<TSecTm> > PNet;
  public:
    class TTmBucket {
    public:
      TSecTm BegTm; // start time of the bucket, end time is determined by GroupBy
      TIntV NIdV;
    public:
      TTmBucket() { }
      TTmBucket(const TSecTm& BucketTm) : BegTm(BucketTm) { }
      TTmBucket(const TTmBucket& TmBucket) : BegTm(TmBucket.BegTm), NIdV(TmBucket.NIdV) { }
      TTmBucket& operator = (const TTmBucket& TmBucket) { if (this!=&TmBucket) {
        BegTm=TmBucket.BegTm; NIdV=TmBucket.NIdV; } return *this; }
    };
    typedef TVec<TTmBucket> TTmBucketV;
  public:
    TTimeNet() { }
    TTimeNet(const int& Nodes, const int& Edges) : TNet(Nodes, Edges) { }
    TTimeNet(const TTimeNet& TimeNet) : TNet(TimeNet) { }
    TTimeNet(TSIn& SIn) : TNet(SIn) { }
    void Save(TSOut& SOut) const { TNet::Save(SOut); }
    static PTimeNet New() { return new TTimeNet(); }
    static PTimeNet New(const int& Nodes, const int& Edges) { return new TTimeNet(Nodes, Edges); }
    static PTimeNet Load(TSIn& SIn) { return new TTimeNet(SIn); }
    TTimeNet& operator = (const TTimeNet& TimeNet);
  
    PTimeNet GetSubGraph(const TIntV& NIdV) const;
    PTimeNENet GetTimeNENet() const;
  
    void GetNIdByTm(TIntV& NIdV) const;
    void GetTmBuckets(const TTmUnit& GroupBy, TTmBucketV& TmBucketV) const;
    void GetNodeBuckets(const int NodesPerBucket, TTimeNet::TTmBucketV& TmBucketV) const;
  
    PGStatVec TimeGrowth(const TTmUnit& TmUnit, const TFSet& TakeStat, const TSecTm& StartTm) const;
    void PlotEffDiam(const TStr& FNmPref, const TStr& Desc, const TTmUnit& GroupBy, const TSecTm& StartTm,
      const int& NDiamRuns=10, const bool& OnlyWcc=false, const bool& AlsoRewire=false) const;
    void PlotMissingPast(const TStr& FNmPref, const TStr& Desc, const TTmUnit& GroupBy,
      const TSecTm& DelPreTmEdges, const TSecTm& PostTmDiam) const;
    void PlotCCfOverTm(const TStr& FNmPref, TStr Desc, const TTmUnit& TmUnit, const int& NodesBucket=-1) const;
    void PlotMedianDegOverTm(const TStr& FNmPref, const TTmUnit& TmUnit, const int& NodesPerBucket=-1) const;
  
    // networks
    static PTimeNet LoadBipartite(const TStr& InFNm);
    static PTimeNet LoadArxiv(const TStr& PaperFNm, const TStr& CiteFNm);
    static PTimeNet LoadPatents(const TStr& PatentFNm, const TStr& CiteFNm);
    static PTimeNet LoadAmazon(const TStr& StlFNm);
  
    friend class TPt<TTimeNet>;
  };
  
  // set flags
  namespace TSnap {
  template <> struct IsDirected<TTimeNet> { enum { Val = 1 }; };
  template <> struct IsNodeDat<TTimeNet> { enum { Val = 1 }; };
  }
  
  /////////////////////////////////////////////////
  // Time Node-Edge Network
  class TTimeNENet : public TNodeEdgeNet<TSecTm, TSecTm> {
  public:
    typedef TNodeEdgeNet<TSecTm, TSecTm> TNet;
    typedef TPt<TNodeEdgeNet<TSecTm, TSecTm> > PNet;
  public:
    TTimeNENet() { }
    TTimeNENet(const int& Nodes, const int& Edges) : TNet(Nodes, Edges) { }
    TTimeNENet(TSIn& SIn) : TNet(SIn) { }
    TTimeNENet(const TTimeNENet& TimeNet) : TNet(TimeNet) { }
    void Save(TSOut& SOut) const { TNet::Save(SOut); }
    static PTimeNENet New() { return new TTimeNENet(); }
    static PTimeNENet New(const int& Nodes, const int& Edges) { return new TTimeNENet(Nodes, Edges); }
    static PTimeNENet Load(TSIn& SIn) { return new TTimeNENet(SIn); }
    TTimeNENet& operator = (const TTimeNENet& TimeNet);
  
    PTimeNet GetTimeNet() const;
    PTimeNENet Get1stEdgeNet() const;
    PTimeNENet GetSubGraph(const TIntV& NIdV) const;
    PTimeNENet GetESubGraph(const TIntV& EIdV) const;
    PTimeNENet GetGraphUpToTm(const TSecTm& MaxEdgeTm) const;
  
    void SortNodeEdgeTimes();
    void UpdateNodeTimes();
    void SetNodeTmToFirstEdgeTm();
    void SetRndEdgeTimes(const int& MinTmEdge=0);
    void DumpTimeStat() const;
  
    void GetNIdByTm(TIntV& NIdV) const;
    void GetEIdByTm(TIntV& EIdV) const;
    void GetTmBuckets(const TTmUnit& GroupBy, TTimeNet::TTmBucketV& TmBucketV) const;
    void GetEdgeTmBuckets(const TTmUnit& GroupBy, TTimeNet::TTmBucketV& TmBucketV) const;
    void GetNodeBuckets(const int NodesPerBucket, TTimeNet::TTmBucketV& TmBucketV) const;
    void GetEdgeBuckets(const int EdgesPerBucket, TTimeNet::TTmBucketV& TmBucketV) const;
    int GetTriadEdges(TIntV& TriadEIdV) const;
  
    PGStatVec TimeGrowth(const TTmUnit& TimeStep, const TFSet& TakeStat, const TSecTm& StartTm=TSecTm(1)) const;
    PGStatVec TimeGrowth(const TStr& FNmPref, const TStr& Desc, const TFSet& TakeStat, const int& NDiamRuns,
      const TTmUnit& TmUnit, const int& TakeNTmUnits, const bool& LinkBWays) const;
    void PlotEffDiam(const TStr& FNmPref, const TStr& Desc, const TTmUnit& GroupBy, const TSecTm& StartTm,
      const int& NDiamRuns=10, const bool& OnlyWcc=false) const;
    void PlotMissingPast(const TStr& FNmPref, const TStr& Desc, const TTmUnit& TmUnit,
      const TSecTm& DelPreTmEdges, const TSecTm& PostTmDiam, const bool& LinkBWays);
  
    void SaveEdgeTm(const TStr& EdgeFNm, const bool& RenumberNId=false, const bool& RelativeTm=false) const;
    static PTimeNENet GetSmallNet();
    static PTimeNENet GetGnmRndNet(const int& Nodes, const int& Edges);
    static PTimeNENet GetPrefAttach(const int& Nodes, const int& Edges, const double& GammaIn, const double& GammaOut);
    static PTimeNENet GetPrefAttach(const int& Nodes, const int& OutDeg);
    static PTimeNENet LoadFlickr(const TStr& NodeFNm, const TStr& EdgeFNm);
    static PTimeNENet LoadEdgeTm(const TStr& EdgeFNm, const int& SrcFld=0, const int& DstFld=1, const int& TimeFld=2, const TSsFmt& Separator=ssfTabSep);
  
    friend class TPt<TTimeNENet>;
  };
  
  // set flags
  namespace TSnap {
  template <> struct IsMultiGraph<TTimeNENet> { enum { Val = 1 }; };
  template <> struct IsDirected<TTimeNENet> { enum { Val = 1 }; };
  template <> struct IsNodeDat<TTimeNENet> { enum { Val = 1 }; };
  template <> struct IsEdgeDat<TTimeNENet> { enum { Val = 1 }; };
  }
  