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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines
graph.cpp
Go to the documentation of this file.
00001 
00002 // Undirected Graph
00003 bool TUNGraph::HasFlag(const TGraphFlag& Flag) const {
00004   return HasGraphFlag(TUNGraph::TNet, Flag);
00005 }
00006 
00007 // Add a node of ID NId to the graph.
00008 int TUNGraph::AddNode(int NId) {
00009   if (NId == -1) {
00010     NId = MxNId;  MxNId++;
00011   } else {
00012     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00013     MxNId = TMath::Mx(NId+1, MxNId());
00014   }
00015   NodeH.AddDat(NId, TNode(NId));
00016   return NId;
00017 }
00018 
00019 // Add a node of ID NId to the graph and create edges to all nodes in vector NbrNIdV.
00020 int TUNGraph::AddNode(const int& NId, const TIntV& NbrNIdV) {
00021   int NewNId;
00022   if (NId == -1) {
00023     NewNId = MxNId;  MxNId++;
00024   } else {
00025     IAssertR(! IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00026     NewNId = NId;
00027     MxNId = TMath::Mx(NewNId+1, MxNId());
00028   }
00029   TNode& Node = NodeH.AddDat(NewNId);
00030   Node.Id = NewNId;
00031   Node.NIdV = NbrNIdV;
00032   Node.NIdV.Sort();
00033   NEdges += Node.GetDeg();
00034   return NewNId;
00035 }
00036 
00037 // Add a node of ID NId to the graph and create edges to all nodes in the vector NIdVId in the vector pool Pool).
00038 int TUNGraph::AddNode(const int& NId, const TVecPool<TInt>& Pool, const int& NIdVId) {
00039   int NewNId;
00040   if (NId == -1) {
00041     NewNId = MxNId;  MxNId++;
00042   } else {
00043     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00044     NewNId = NId;
00045     MxNId = TMath::Mx(NewNId+1, MxNId());
00046   }
00047   TNode& Node = NodeH.AddDat(NewNId);
00048   Node.Id = NewNId;
00049   Node.NIdV.GenExt(Pool.GetValVPt(NIdVId), Pool.GetVLen(NIdVId));
00050   Node.NIdV.Sort();
00051   NEdges += Node.GetDeg();
00052   return NewNId;
00053 }
00054 
00055 // Delete node of ID NId from the graph.
00056 void TUNGraph::DelNode(const int& NId) {
00057   { AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId));
00058   TNode& Node = GetNode(NId);
00059   NEdges -= Node.GetDeg();
00060   for (int e = 0; e < Node.GetDeg(); e++) {
00061     const int nbr = Node.GetNbrNId(e);
00062     if (nbr == NId) { continue; }
00063     TNode& N = GetNode(nbr);
00064     const int n = N.NIdV.SearchBin(NId);
00065     IAssert(n != -1); // if NId points to N, then N also should point back
00066     if (n!= -1) { N.NIdV.Del(n); }
00067   } }
00068   NodeH.DelKey(NId);
00069 }
00070 
00071 int TUNGraph::GetEdges() const {
00072   //int Edges = 0;
00073   //for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00074   //  Edges += NodeH[N].GetDeg();
00075   //}
00076   //return Edges/2;
00077   return NEdges;
00078 }
00079 
00080 // Add an edge between SrcNId and DstNId to the graph.
00081 int TUNGraph::AddEdge(const int& SrcNId, const int& DstNId) {
00082   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00083   if (IsEdge(SrcNId, DstNId)) { return -2; } // edge already exists
00084   GetNode(SrcNId).NIdV.AddSorted(DstNId);
00085   if (SrcNId!=DstNId) { // not a self edge
00086     GetNode(DstNId).NIdV.AddSorted(SrcNId); }
00087   NEdges++;
00088   return -1; // edge id
00089 }
00090 
00091 // Delete an edge between node IDs SrcNId and DstNId from the graph.
00092 void TUNGraph::DelEdge(const int& SrcNId, const int& DstNId) {
00093   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00094   { TNode& N = GetNode(SrcNId);
00095   const int n = N.NIdV.SearchBin(DstNId);
00096   if (n!= -1) { N.NIdV.Del(n);  NEdges--; } }
00097   if (SrcNId != DstNId) { // not a self edge
00098     TNode& N = GetNode(DstNId);
00099     const int n = N.NIdV.SearchBin(SrcNId);
00100     if (n!= -1) { N.NIdV.Del(n); }
00101   }
00102 }
00103 
00104 // Test whether an edge between node IDs SrcNId and DstNId exists the graph.
00105 bool TUNGraph::IsEdge(const int& SrcNId, const int& DstNId) const {
00106   if (! IsNode(SrcNId) || ! IsNode(DstNId)) return false;
00107   return GetNode(SrcNId).IsNbrNId(DstNId);
00108 }
00109 
00110 // Return an iterator referring to edge (SrcNId, DstNId) in the graph.
00111 TUNGraph::TEdgeI TUNGraph::GetEI(const int& SrcNId, const int& DstNId) const {
00112   const int MnNId = TMath::Mn(SrcNId, DstNId);
00113   const int MxNId = TMath::Mx(SrcNId, DstNId);
00114   const TNodeI SrcNI = GetNI(MnNId);
00115   const int NodeN = SrcNI.NodeHI.GetDat().NIdV.SearchBin(MxNId);
00116   IAssert(NodeN != -1);
00117   return TEdgeI(SrcNI, EndNI(), NodeN);
00118 }
00119 
00120 
00121 // Get a vector IDs of all nodes in the graph.
00122 void TUNGraph::GetNIdV(TIntV& NIdV) const {
00123   NIdV.Gen(GetNodes(), 0);
00124   for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00125     NIdV.Add(NodeH.GetKey(N)); }
00126 }
00127 
00128 // Defragment the graph.
00129 void TUNGraph::Defrag(const bool& OnlyNodeLinks) {
00130   for (int n = NodeH.FFirstKeyId(); NodeH.FNextKeyId(n); ) {
00131     NodeH[n].NIdV.Pack();
00132   }
00133   if (! OnlyNodeLinks && ! NodeH.IsKeyIdEqKeyN()) {
00134     NodeH.Defrag();
00135   }
00136 }
00137 
00138 // Check the graph data structure for internal consistency.
00139 bool TUNGraph::IsOk(const bool& ThrowExcept) const {
00140   bool RetVal = true;
00141   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00142     const TNode& Node = NodeH[N];
00143     if (! Node.NIdV.IsSorted()) {
00144       const TStr Msg = TStr::Fmt("Neighbor list of node %d is not sorted.", Node.GetId());
00145       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); }
00146       RetVal=false;
00147     }
00148     int prevNId = -1;
00149     for (int e = 0; e < Node.GetDeg(); e++) {
00150       if (! IsNode(Node.GetNbrNId(e))) {
00151         const TStr Msg = TStr::Fmt("Edge %d --> %d: node %d does not exist.",
00152           Node.GetId(), Node.GetNbrNId(e), Node.GetNbrNId(e));
00153         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); }
00154         RetVal=false;
00155       }
00156       if (e > 0 && prevNId == Node.GetNbrNId(e)) {
00157         const TStr Msg = TStr::Fmt("Node %d has duplicate edge %d --> %d.",
00158           Node.GetId(), Node.GetId(), Node.GetNbrNId(e));
00159         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); }
00160         RetVal=false;
00161       }
00162       prevNId = Node.GetNbrNId(e);
00163     }
00164   }
00165   int EdgeCnt = 0;
00166   for (TEdgeI EI = BegEI(); EI < EndEI(); EI++) { EdgeCnt++; }
00167   if (EdgeCnt != GetEdges()) {
00168     const TStr Msg = TStr::Fmt("Number of edges counter is corrupted: GetEdges():%d, EdgeCount:%d.", GetEdges(), EdgeCnt);
00169     if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); }
00170     RetVal=false;
00171   }
00172   return RetVal;
00173 }
00174 
00175 // Print the graph in a human readable form to an output stream OutF.
00176 void TUNGraph::Dump(FILE *OutF) const {
00177   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00178   fprintf(OutF, "-------------------------------------------------\nUndirected Node Graph: nodes: %d, edges: %d\n", GetNodes(), GetEdges());
00179   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00180     const TNode& Node = NodeH[N];
00181     fprintf(OutF, "  %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg());
00182     for (int edge = 0; edge < Node.GetDeg(); edge++) {
00183       fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); }
00184     fprintf(OutF, "\n");
00185   }
00186   fprintf(OutF, "\n");
00187 }
00188 
00189 // Return a small graph on 5 nodes and 5 edges.
00190 PUNGraph TUNGraph::GetSmallGraph() {
00191   PUNGraph Graph = TUNGraph::New();
00192   for (int i = 0; i < 5; i++) { Graph->AddNode(i); }
00193   Graph->AddEdge(0,1);  Graph->AddEdge(0,2);
00194   Graph->AddEdge(0,3);  Graph->AddEdge(0,4);
00195   Graph->AddEdge(1,2);
00196   return Graph;
00197 }
00198 
00200 // Directed Node Graph
00201 bool TNGraph::HasFlag(const TGraphFlag& Flag) const {
00202   return HasGraphFlag(TNGraph::TNet, Flag);
00203 }
00204 
00205 int TNGraph::AddNode(int NId) {
00206   if (NId == -1) {
00207     NId = MxNId;  MxNId++;
00208   } else {
00209     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00210     MxNId = TMath::Mx(NId+1, MxNId());
00211   }
00212   NodeH.AddDat(NId, TNode(NId));
00213   return NId;
00214 }
00215 
00216 // add a node with a list of neighbors
00217 // (use TNGraph::IsOk to check whether the graph is consistent)
00218 int TNGraph::AddNode(const int& NId, const TIntV& InNIdV, const TIntV& OutNIdV) {
00219   int NewNId;
00220   if (NId == -1) {
00221     NewNId = MxNId;  MxNId++;
00222   } else {
00223     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00224     NewNId = NId;
00225     MxNId = TMath::Mx(NewNId+1, MxNId());
00226   }
00227   TNode& Node = NodeH.AddDat(NewNId);
00228   Node.Id = NewNId;
00229   Node.InNIdV = InNIdV;
00230   Node.OutNIdV = OutNIdV;
00231   Node.InNIdV.Sort();
00232   Node.OutNIdV.Sort();
00233   return NewNId;
00234 }
00235 
00236 // add a node from a vector pool
00237 // (use TNGraph::IsOk to check whether the graph is consistent)
00238 int TNGraph::AddNode(const int& NId, const TVecPool<TInt>& Pool, const int& SrcVId, const int& DstVId) {
00239   int NewNId;
00240   if (NId == -1) {
00241     NewNId = MxNId;  MxNId++;
00242   } else {
00243     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00244     NewNId = NId;
00245     MxNId = TMath::Mx(NewNId+1, MxNId());
00246   }
00247   TNode& Node = NodeH.AddDat(NewNId);
00248   Node.Id = NewNId;
00249   Node.InNIdV.GenExt(Pool.GetValVPt(SrcVId), Pool.GetVLen(SrcVId));
00250   Node.OutNIdV.GenExt(Pool.GetValVPt(DstVId), Pool.GetVLen(DstVId));
00251   Node.InNIdV.Sort();
00252   Node.OutNIdV.Sort();
00253   return NewNId;
00254 }
00255 
00256 void TNGraph::DelNode(const int& NId) {
00257   { TNode& Node = GetNode(NId);
00258   for (int e = 0; e < Node.GetOutDeg(); e++) {
00259   const int nbr = Node.GetOutNId(e);
00260   if (nbr == NId) { continue; }
00261     TNode& N = GetNode(nbr);
00262     const int n = N.InNIdV.SearchBin(NId);
00263     if (n!= -1) { N.InNIdV.Del(n); }
00264   }
00265   for (int e = 0; e < Node.GetInDeg(); e++) {
00266   const int nbr = Node.GetInNId(e);
00267   if (nbr == NId) { continue; }
00268     TNode& N = GetNode(nbr);
00269     const int n = N.OutNIdV.SearchBin(NId);
00270     if (n!= -1) { N.OutNIdV.Del(n); }
00271   } }
00272   NodeH.DelKey(NId);
00273 }
00274 
00275 int TNGraph::GetEdges() const {
00276   int edges=0;
00277   for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00278     edges+=NodeH[N].GetOutDeg();
00279   }
00280   return edges;
00281 }
00282 
00283 int TNGraph::AddEdge(const int& SrcNId, const int& DstNId) {
00284   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00285   //IAssert(! IsEdge(SrcNId, DstNId));
00286   if (IsEdge(SrcNId, DstNId)) { return -2; }
00287   GetNode(SrcNId).OutNIdV.AddSorted(DstNId);
00288   GetNode(DstNId).InNIdV.AddSorted(SrcNId);
00289   return -1; // edge id
00290 }
00291 
00292 void TNGraph::DelEdge(const int& SrcNId, const int& DstNId, const bool& IsDir) {
00293   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00294   { TNode& N = GetNode(SrcNId);
00295   const int n = N.OutNIdV.SearchBin(DstNId);
00296   if (n!= -1) { N.OutNIdV.Del(n); } }
00297   { TNode& N = GetNode(DstNId);
00298   const int n = N.InNIdV.SearchBin(SrcNId);
00299   if (n!= -1) { N.InNIdV.Del(n); } }
00300   if (! IsDir) {
00301     { TNode& N = GetNode(SrcNId);
00302     const int n = N.InNIdV.SearchBin(DstNId);
00303     if (n!= -1) { N.InNIdV.Del(n); } }
00304     { TNode& N = GetNode(DstNId);
00305     const int n = N.OutNIdV.SearchBin(SrcNId);
00306     if (n!= -1) { N.OutNIdV.Del(n); } }
00307   }
00308 }
00309 
00310 bool TNGraph::IsEdge(const int& SrcNId, const int& DstNId, const bool& IsDir) const {
00311   if (! IsNode(SrcNId) || ! IsNode(DstNId)) { return false; }
00312   if (IsDir) { return GetNode(SrcNId).IsOutNId(DstNId); }
00313   else { return GetNode(SrcNId).IsOutNId(DstNId) || GetNode(DstNId).IsOutNId(SrcNId); }
00314 }
00315 
00316 TNGraph::TEdgeI TNGraph::GetEI(const int& SrcNId, const int& DstNId) const {
00317   const TNodeI SrcNI = GetNI(SrcNId);
00318   const int NodeN = SrcNI.NodeHI.GetDat().OutNIdV.SearchBin(DstNId);
00319   IAssert(NodeN != -1);
00320   return TEdgeI(SrcNI, EndNI(), NodeN);
00321 }
00322 
00323 void TNGraph::GetNIdV(TIntV& NIdV) const {
00324   NIdV.Gen(GetNodes(), 0);
00325   for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00326     NIdV.Add(NodeH.GetKey(N)); }
00327 }
00328 
00329 void TNGraph::Defrag(const bool& OnlyNodeLinks) {
00330   for (int n = NodeH.FFirstKeyId(); NodeH.FNextKeyId(n); ) {
00331     TNode& Node = NodeH[n];
00332     Node.InNIdV.Pack();  Node.OutNIdV.Pack();
00333   }
00334   if (! OnlyNodeLinks && ! NodeH.IsKeyIdEqKeyN()) { NodeH.Defrag(); }
00335 }
00336 
00337 // for each node check that their neighbors are also nodes
00338 bool TNGraph::IsOk(const bool& ThrowExcept) const {
00339   bool RetVal = true;
00340   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00341     const TNode& Node = NodeH[N];
00342     if (! Node.OutNIdV.IsSorted()) {
00343       const TStr Msg = TStr::Fmt("Out-neighbor list of node %d is not sorted.", Node.GetId());
00344       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00345     }
00346     if (! Node.InNIdV.IsSorted()) {
00347       const TStr Msg = TStr::Fmt("In-neighbor list of node %d is not sorted.", Node.GetId());
00348       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00349     }
00350     // check out-edges
00351     int prevNId = -1;
00352     for (int e = 0; e < Node.GetOutDeg(); e++) {
00353       if (! IsNode(Node.GetOutNId(e))) {
00354         const TStr Msg = TStr::Fmt("Out-edge %d --> %d: node %d does not exist.",
00355           Node.GetId(), Node.GetOutNId(e), Node.GetOutNId(e));
00356         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00357       }
00358       if (e > 0 && prevNId == Node.GetOutNId(e)) {
00359         const TStr Msg = TStr::Fmt("Node %d has duplidate out-edge %d --> %d.",
00360           Node.GetId(), Node.GetId(), Node.GetOutNId(e));
00361         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00362       }
00363       prevNId = Node.GetOutNId(e);
00364     }
00365     // check in-edges
00366     prevNId = -1;
00367     for (int e = 0; e < Node.GetInDeg(); e++) {
00368       if (! IsNode(Node.GetInNId(e))) {
00369         const TStr Msg = TStr::Fmt("In-edge %d <-- %d: node %d does not exist.",
00370           Node.GetId(), Node.GetInNId(e), Node.GetInNId(e));
00371         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00372       }
00373       if (e > 0 && prevNId == Node.GetInNId(e)) {
00374         const TStr Msg = TStr::Fmt("Node %d has duplidate in-edge %d <-- %d.",
00375           Node.GetId(), Node.GetId(), Node.GetInNId(e));
00376         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00377       }
00378       prevNId = Node.GetInNId(e);
00379     }
00380   }
00381   return RetVal;
00382 }
00383 
00384 void TNGraph::Dump(FILE *OutF) const {
00385   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00386   fprintf(OutF, "-------------------------------------------------\nDirected Node Graph: nodes: %d, edges: %d\n", GetNodes(), GetEdges());
00387   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00388     const TNode& Node = NodeH[N];
00389     fprintf(OutF, "  %*d]\n", NodePlaces, Node.GetId());
00390     fprintf(OutF, "    in [%d]", Node.GetInDeg());
00391     for (int edge = 0; edge < Node.GetInDeg(); edge++) {
00392       fprintf(OutF, " %*d", NodePlaces, Node.GetInNId(edge)); }
00393     fprintf(OutF, "\n    out[%d]", Node.GetOutDeg());
00394     for (int edge = 0; edge < Node.GetOutDeg(); edge++) {
00395       fprintf(OutF, " %*d", NodePlaces, Node.GetOutNId(edge)); }
00396     fprintf(OutF, "\n");
00397   }
00398   fprintf(OutF, "\n");
00399 }
00400 
00401 PNGraph TNGraph::GetSmallGraph() {
00402   PNGraph G = TNGraph::New();
00403   for (int i = 0; i < 5; i++) { G->AddNode(i); }
00404   G->AddEdge(0,1); G->AddEdge(1,2); G->AddEdge(0,2);
00405   G->AddEdge(1,3); G->AddEdge(3,4); G->AddEdge(2,3);
00406   return G;
00407 }
00408 
00410 // Node Edge Graph
00411 bool TNEGraph::HasFlag(const TGraphFlag& Flag) const {
00412   return HasGraphFlag(TNEGraph::TNet, Flag);
00413 }
00414 
00415 bool TNEGraph::TNodeI::IsInNId(const int& NId) const {
00416   const TNode& Node = NodeHI.GetDat();
00417   for (int edge = 0; edge < Node.GetInDeg(); edge++) {
00418     if (NId == Graph->GetEdge(Node.GetInEId(edge)).GetSrcNId())
00419       return true;
00420   }
00421   return false;
00422 }
00423 
00424 bool TNEGraph::TNodeI::IsOutNId(const int& NId) const {
00425   const TNode& Node = NodeHI.GetDat();
00426   for (int edge = 0; edge < Node.GetOutDeg(); edge++) {
00427     if (NId == Graph->GetEdge(Node.GetOutEId(edge)).GetDstNId())
00428       return true;
00429   }
00430   return false;
00431 }
00432 
00433 int TNEGraph::AddNode(int NId) {
00434   if (NId == -1) {
00435     NId = MxNId;  MxNId++;
00436   } else {
00437     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00438     MxNId = TMath::Mx(NId+1, MxNId());
00439   }
00440   NodeH.AddDat(NId, TNode(NId));
00441   return NId;
00442 }
00443 
00444 void TNEGraph::DelNode(const int& NId) {
00445   const TNode& Node = GetNode(NId);
00446   for (int out = 0; out < Node.GetOutDeg(); out++) {
00447     const int EId = Node.GetOutEId(out);
00448     const TEdge& Edge = GetEdge(EId);
00449     IAssert(Edge.GetSrcNId() == NId);
00450     GetNode(Edge.GetDstNId()).InEIdV.DelIfIn(EId);
00451     EdgeH.DelKey(EId);
00452   }
00453   for (int in = 0; in < Node.GetInDeg(); in++) {
00454     const int EId = Node.GetInEId(in);
00455     const TEdge& Edge = GetEdge(EId);
00456     IAssert(Edge.GetDstNId() == NId);
00457     GetNode(Edge.GetSrcNId()).OutEIdV.DelIfIn(EId);
00458     EdgeH.DelKey(EId);
00459   }
00460   NodeH.DelKey(NId);
00461 }
00462 
00463 int TNEGraph::AddEdge(const int& SrcNId, const int& DstNId, int EId) {
00464   if (EId == -1) { EId = MxEId;  MxEId++; }
00465   else { MxEId = TMath::Mx(EId+1, MxEId()); }
00466   IAssertR(!IsEdge(EId), TStr::Fmt("EdgeId %d already exists", EId));
00467   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00468   EdgeH.AddDat(EId, TEdge(EId, SrcNId, DstNId));
00469   GetNode(SrcNId).OutEIdV.AddSorted(EId);
00470   GetNode(DstNId).InEIdV.AddSorted(EId);
00471   return EId;
00472 }
00473 
00474 void TNEGraph::DelEdge(const int& EId) {
00475   IAssert(IsEdge(EId));
00476   const int SrcNId = GetEdge(EId).GetSrcNId();
00477   const int DstNId = GetEdge(EId).GetDstNId();
00478   GetNode(SrcNId).OutEIdV.DelIfIn(EId);
00479   GetNode(DstNId).InEIdV.DelIfIn(EId);
00480   EdgeH.DelKey(EId);
00481 }
00482 
00483 // delete all edges between the two nodes
00484 void TNEGraph::DelEdge(const int& SrcNId, const int& DstNId, const bool& IsDir) {
00485   int EId;
00486   IAssert(IsEdge(SrcNId, DstNId, EId, IsDir)); // there is at least one edge
00487   while (IsEdge(SrcNId, DstNId, EId, IsDir)) {
00488     GetNode(SrcNId).OutEIdV.DelIfIn(EId);
00489     GetNode(DstNId).InEIdV.DelIfIn(EId);
00490   }
00491   EdgeH.DelKey(EId);
00492 }
00493 
00494 bool TNEGraph::IsEdge(const int& SrcNId, const int& DstNId, int& EId, const bool& IsDir) const {
00495   const TNode& SrcNode = GetNode(SrcNId);
00496   for (int edge = 0; edge < SrcNode.GetOutDeg(); edge++) {
00497     const TEdge& Edge = GetEdge(SrcNode.GetOutEId(edge));
00498     if (DstNId == Edge.GetDstNId()) {
00499       EId = Edge.GetId();  return true; }
00500   }
00501   if (! IsDir) {
00502     for (int edge = 0; edge < SrcNode.GetInDeg(); edge++) {
00503     const TEdge& Edge = GetEdge(SrcNode.GetInEId(edge));
00504     if (DstNId == Edge.GetSrcNId()) {
00505       EId = Edge.GetId();  return true; }
00506     }
00507   }
00508   return false;
00509 }
00510 
00511 void TNEGraph::GetNIdV(TIntV& NIdV) const {
00512   NIdV.Gen(GetNodes(), 0);
00513   for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00514     NIdV.Add(NodeH.GetKey(N)); }
00515 }
00516 
00517 void TNEGraph::GetEIdV(TIntV& EIdV) const {
00518   EIdV.Gen(GetEdges(), 0);
00519   for (int E=EdgeH.FFirstKeyId(); EdgeH.FNextKeyId(E); ) {
00520     EIdV.Add(EdgeH.GetKey(E));
00521   }
00522 }
00523 
00524 void TNEGraph::Defrag(const bool& OnlyNodeLinks) {
00525   for (int kid = NodeH.FFirstKeyId(); NodeH.FNextKeyId(kid); ) {
00526     TNode& Node = NodeH[kid];
00527     Node.InEIdV.Pack();  Node.OutEIdV.Pack();
00528   }
00529   if (! OnlyNodeLinks && ! NodeH.IsKeyIdEqKeyN()) { NodeH.Defrag(); }
00530   if (! OnlyNodeLinks && ! EdgeH.IsKeyIdEqKeyN()) { EdgeH.Defrag(); }
00531 }
00532 
00533 bool TNEGraph::IsOk(const bool& ThrowExcept) const {
00534 bool RetVal = true;
00535   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00536     const TNode& Node = NodeH[N];
00537     if (! Node.OutEIdV.IsSorted()) {
00538       const TStr Msg = TStr::Fmt("Out-edge list of node %d is not sorted.", Node.GetId());
00539       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00540     }
00541     if (! Node.InEIdV.IsSorted()) {
00542       const TStr Msg = TStr::Fmt("In-edge list of node %d is not sorted.", Node.GetId());
00543       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00544     }
00545     // check out-edge ids
00546     int prevEId = -1;
00547     for (int e = 0; e < Node.GetOutDeg(); e++) {
00548       if (! IsEdge(Node.GetOutEId(e))) {
00549         const TStr Msg = TStr::Fmt("Out-edge id %d of node %d does not exist.",  Node.GetOutEId(e), Node.GetId());
00550         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00551       }
00552       if (e > 0 && prevEId == Node.GetOutEId(e)) {
00553         const TStr Msg = TStr::Fmt("Node %d has duplidate out-edge id %d.", Node.GetId(), Node.GetOutEId(e));
00554         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00555       }
00556       prevEId = Node.GetOutEId(e);
00557     }
00558     // check in-edge ids
00559     prevEId = -1;
00560     for (int e = 0; e < Node.GetInDeg(); e++) {
00561       if (! IsEdge(Node.GetInEId(e))) {
00562         const TStr Msg = TStr::Fmt("Out-edge id %d of node %d does not exist.",  Node.GetInEId(e), Node.GetId());
00563         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00564       }
00565       if (e > 0 && prevEId == Node.GetInEId(e)) {
00566         const TStr Msg = TStr::Fmt("Node %d has duplidate out-edge id %d.", Node.GetId(), Node.GetInEId(e));
00567         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00568       }
00569       prevEId = Node.GetInEId(e);
00570     }
00571   }
00572   for (int E = EdgeH.FFirstKeyId(); EdgeH.FNextKeyId(E); ) {
00573     const TEdge& Edge = EdgeH[E];
00574     if (! IsNode(Edge.GetSrcNId())) {
00575       const TStr Msg = TStr::Fmt("Edge %d source node %d does not exist.", Edge.GetId(), Edge.GetSrcNId());
00576       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00577     }
00578     if (! IsNode(Edge.GetDstNId())) {
00579       const TStr Msg = TStr::Fmt("Edge %d destination node %d does not exist.", Edge.GetId(), Edge.GetDstNId());
00580       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00581     }
00582   }
00583   return RetVal;
00584 }
00585 
00586 void TNEGraph::Dump(FILE *OutF) const {
00587   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00588   const int EdgePlaces = (int) ceil(log10((double) GetEdges()));
00589   fprintf(OutF, "-------------------------------------------------\nDirected Node-Edge Graph: nodes: %d, edges: %d\n", GetNodes(), GetEdges());
00590   for (TNodeI NodeI = BegNI(); NodeI < EndNI(); NodeI++) {
00591     fprintf(OutF, "  %*d]\n", NodePlaces, NodeI.GetId());
00592     fprintf(OutF, "    in[%d]", NodeI.GetInDeg());
00593     for (int edge = 0; edge < NodeI.GetInDeg(); edge++) {
00594       fprintf(OutF, " %*d", EdgePlaces, NodeI.GetInEId(edge)); }
00595     fprintf(OutF, "\n    out[%d]", NodeI.GetOutDeg());
00596     for (int edge = 0; edge < NodeI.GetOutDeg(); edge++) {
00597       fprintf(OutF, " %*d", EdgePlaces, NodeI.GetOutEId(edge)); }
00598     fprintf(OutF, "\n");
00599   }
00600   for (TEdgeI EdgeI = BegEI(); EdgeI < EndEI(); EdgeI++) {
00601     fprintf(OutF, "  %*d]  %*d  ->  %*d\n", EdgePlaces, EdgeI.GetId(), NodePlaces, EdgeI.GetSrcNId(), NodePlaces, EdgeI.GetDstNId());
00602   }
00603   fprintf(OutF, "\n");
00604 }
00605 
00606 // Return a small graph on 5 nodes and 6 edges.
00607 PNEGraph TNEGraph::GetSmallGraph() {
00608   PNEGraph Graph = TNEGraph::New();
00609   for (int i = 0; i < 5; i++) { Graph->AddNode(i); }
00610   Graph->AddEdge(0,1);  Graph->AddEdge(0,2);
00611   Graph->AddEdge(0,3);  Graph->AddEdge(0,4);
00612   Graph->AddEdge(1,2);  Graph->AddEdge(1,2);
00613   return Graph;
00614 }
00615 
00617 // Bipartite graph
00618 int TBPGraph::AddNode(int NId, const bool& LeftNode) {
00619   if (NId == -1) { NId = MxNId;  MxNId++; }
00620   else if (IsLNode(NId)) { IAssertR(LeftNode, TStr::Fmt("Node with id %s already exists on the 'left'.", NId));  return NId; }
00621   else if (IsRNode(NId)) { IAssertR(! LeftNode, TStr::Fmt("Node with id %s already exists on the 'right'.", NId));  return NId; }
00622   else { MxNId = TMath::Mx(NId+1, MxNId()); }
00623   if (LeftNode) { LeftH.AddDat(NId, TNode(NId)); }
00624   else { RightH.AddDat(NId, TNode(NId)); }
00625   return NId;
00626 }
00627 
00628 // Delete node of ID NId from the bipartite graph.
00629 void TBPGraph::DelNode(const int& NId) {
00630   AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId));
00631   THash<TInt, TNode>& SrcH = IsLNode(NId) ? LeftH : RightH;
00632   THash<TInt, TNode>& DstH = IsLNode(NId) ? RightH : LeftH;
00633   { TNode& Node = SrcH.GetDat(NId);
00634   for (int e = 0; e < Node.GetOutDeg(); e++) {
00635     const int nbr = Node.GetOutNId(e);
00636     IAssertR(nbr != NId, "Bipartite graph has a loop!");
00637     TNode& N = DstH.GetDat(nbr);
00638     const int n = N.NIdV.SearchBin(NId);
00639     IAssert(n!= -1); 
00640     N.NIdV.Del(n);
00641   } }
00642   SrcH.DelKey(NId);
00643 }
00644 
00645 int TBPGraph::GetEdges() const {
00646   int Edges = 0;
00647   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00648     Edges += LeftH[N].GetDeg(); }
00649   return Edges;
00650 }
00651 
00652 int TBPGraph::AddEdge(const int& LeftNId, const int& RightNId) {
00653   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00654   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00655   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00656   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00657   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00658   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00659   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00660   if (LeftH.GetDat(LNId).IsOutNId(RNId)) { return -2; } // edge already exists
00661   LeftH.GetDat(LNId).NIdV.AddSorted(RNId);
00662   RightH.GetDat(RNId).NIdV.AddSorted(LNId);
00663   return -1; // edge id
00664 }
00665 
00666 void TBPGraph::DelEdge(const int& LeftNId, const int& RightNId) {
00667   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00668   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00669   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00670   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00671   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00672   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00673   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00674   { TIntV& NIdV = LeftH.GetDat(LNId).NIdV;
00675   const int n = NIdV.SearchBin(RNId);
00676   if (n != -1) { NIdV.Del(n); } }
00677   { TIntV& NIdV = RightH.GetDat(RNId).NIdV;
00678   const int n = NIdV.SearchBin(LNId);
00679   if (n != -1) { NIdV.Del(n); } }
00680 }
00681 
00682 bool TBPGraph::IsEdge(const int& LeftNId, const int& RightNId) const {
00683   if (! IsNode(LeftNId) || ! IsNode(RightNId)) { return false; }
00684   return IsLNode(LeftNId) ? LeftH.GetDat(LeftNId).IsOutNId(RightNId) : RightH.GetDat(LeftNId).IsOutNId(RightNId);
00685 }
00686 
00687 TBPGraph::TEdgeI TBPGraph::GetEI(const int& LeftNId, const int& RightNId) const {
00688   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00689   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00690   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00691   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00692   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00693   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00694   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00695   const TNodeI SrcNI = GetNI(LNId);
00696   const int NodeN = SrcNI.LeftHI.GetDat().NIdV.SearchBin(RNId);
00697   IAssertR(NodeN != -1, "Right edge endpoint does not exists!");
00698   return TEdgeI(SrcNI, EndNI(), NodeN);
00699 }
00700 
00701 int TBPGraph::GetRndNId(TRnd& Rnd) { 
00702   const int NNodes = GetNodes();
00703   if (Rnd.GetUniDevInt(NNodes) < GetLNodes()) {
00704     return GetRndLNId(Rnd); }
00705   else {
00706     return GetRndRNId(Rnd); }
00707 }
00708 
00709 int TBPGraph::GetRndLNId(TRnd& Rnd) { 
00710   return LeftH.GetKey(LeftH.GetRndKeyId(Rnd, 0.8)); 
00711 }
00712 
00713 int TBPGraph::GetRndRNId(TRnd& Rnd) { 
00714   return RightH.GetKey(RightH.GetRndKeyId(Rnd, 0.8)); 
00715 }
00716 
00717 void TBPGraph::GetNIdV(TIntV& NIdV) const {
00718   NIdV.Gen(GetNodes(), 0);
00719   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00720     NIdV.Add(LeftH.GetKey(N)); }
00721   for (int N=RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00722     NIdV.Add(RightH.GetKey(N)); }
00723 }
00724 
00725 void TBPGraph::GetLNIdV(TIntV& NIdV) const {
00726   NIdV.Gen(GetLNodes(), 0);
00727   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00728     NIdV.Add(LeftH.GetKey(N)); }
00729 }
00730 
00731 void TBPGraph::GetRNIdV(TIntV& NIdV) const {
00732   NIdV.Gen(GetRNodes(), 0);
00733   for (int N=RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00734     NIdV.Add(RightH.GetKey(N)); }
00735 }
00736 
00737 void TBPGraph::Reserve(const int& Nodes, const int& Edges) { 
00738   if (Nodes>0) { LeftH.Gen(Nodes/2); RightH.Gen(Nodes/2); } 
00739 }
00740 
00741 void TBPGraph::Defrag(const bool& OnlyNodeLinks) {
00742   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00743     LeftH[n].NIdV.Pack(); }
00744   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00745     RightH[n].NIdV.Pack(); }
00746   if (! OnlyNodeLinks && ! LeftH.IsKeyIdEqKeyN()) { LeftH.Defrag(); }
00747   if (! OnlyNodeLinks && ! RightH.IsKeyIdEqKeyN()) { RightH.Defrag(); }
00748 }
00749 
00750 bool TBPGraph::IsOk(const bool& ThrowExcept) const {
00751   bool RetVal = false;
00752   // edge lists are sorted
00753   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00754     if (! LeftH[n].NIdV.IsSorted()) {
00755       const TStr Msg = TStr::Fmt("Neighbor list of node %d is not sorted.", LeftH[n].GetId());
00756       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00757   }
00758   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00759     if (! RightH[n].NIdV.IsSorted()) {
00760       const TStr Msg = TStr::Fmt("Neighbor list of node %d is not sorted.", RightH[n].GetId());
00761       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00762   }
00763   // nodes only appear on one side
00764   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00765     if (RightH.IsKey(LeftH[n].GetId())) {
00766       const TStr Msg = TStr::Fmt("'Left' node %d also appears on the 'right'.", LeftH[n].GetId());
00767       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00768   } 
00769   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00770     if (LeftH.IsKey(RightH[n].GetId())) {
00771       const TStr Msg = TStr::Fmt("'Right' node %d also appears on the 'left'.", RightH[n].GetId());
00772       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00773   }
00774   // edges only point from left to right and right to left
00775   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00776     for (int e = 0; e < LeftH[n].NIdV.Len(); e++) {
00777       if (! RightH.IsKey(LeftH[n].NIdV[e]) || ! RightH.GetDat(LeftH[n].NIdV[e]).NIdV.IsIn(LeftH[n].GetId())) {
00778         const TStr Msg = TStr::Fmt("'Left' node %d does not point to the 'right' node %d.", LeftH[n].GetId(), LeftH[n].NIdV[e]());
00779         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00780     }
00781   }
00782   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00783     for (int e = 0; e < RightH[n].NIdV.Len(); e++) {
00784       if (! LeftH.IsKey(RightH[n].NIdV[e]) || ! LeftH.GetDat(RightH[n].NIdV[e]).NIdV.IsIn(RightH[n].GetId())) {
00785         const TStr Msg = TStr::Fmt("'Left' node %d does not point to the 'right' node %d.", RightH[n].GetId(), RightH[n].NIdV[e]());
00786         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00787     }
00788   }
00789   return RetVal;
00790 }
00791 
00792 void TBPGraph::Dump(FILE *OutF) const {
00793   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00794   fprintf(OutF, "-------------------------------------------------\nBipartite Graph: nodes: %d+%d=%d, edges: %d\n", GetLNodes(), GetRNodes(), GetNodes(), GetEdges());
00795   for (int N = LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00796     const TNode& Node = LeftH[N];
00797     fprintf(OutF, "  %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg());
00798     for (int edge = 0; edge < Node.GetDeg(); edge++) {
00799       fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); }
00800     fprintf(OutF, "\n");
00801   }
00802   fprintf(OutF, "\n");
00803   /*// Also dump the 'right' side
00804   fprintf(OutF, "\n");
00805   for (int N = RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00806     const TNode& Node = RightH[N];
00807     fprintf(OutF, "  %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg());
00808     for (int edge = 0; edge < Node.GetDeg(); edge++) {
00809       fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); }
00810     fprintf(OutF, "\n");
00811   }
00812   fprintf(OutF, "\n"); //*/
00813 }
00814 
00815 PBPGraph TBPGraph::GetSmallGraph() {
00816   PBPGraph BP = TBPGraph::New();
00817   BP->AddNode(0, true);
00818   BP->AddNode(1, true);
00819   BP->AddNode(2, false);
00820   BP->AddNode(3, false);
00821   BP->AddNode(4, false);
00822   BP->AddEdge(0, 2);
00823   BP->AddEdge(0, 3);
00824   BP->AddEdge(1, 2);
00825   BP->AddEdge(1, 3);
00826   BP->AddEdge(1, 4);
00827   return BP;
00828 }