SNAP Library, User Reference  2012-10-15 15:06:59
SNAP, a general purpose network analysis and graph mining library
 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);
00406   G->AddEdge(3,4);
00407   G->AddEdge(2,3);
00408   return G;
00409 }
00410 
00412 // Node Edge Graph
00413 bool TNEGraph::HasFlag(const TGraphFlag& Flag) const {
00414   return HasGraphFlag(TNEGraph::TNet, Flag);
00415 }
00416 
00417 bool TNEGraph::TNodeI::IsInNId(const int& NId) const {
00418   const TNode& Node = NodeHI.GetDat();
00419   for (int edge = 0; edge < Node.GetInDeg(); edge++) {
00420     if (NId == Graph->GetEdge(Node.GetInEId(edge)).GetSrcNId())
00421       return true;
00422   }
00423   return false;
00424 }
00425 
00426 bool TNEGraph::TNodeI::IsOutNId(const int& NId) const {
00427   const TNode& Node = NodeHI.GetDat();
00428   for (int edge = 0; edge < Node.GetOutDeg(); edge++) {
00429     if (NId == Graph->GetEdge(Node.GetOutEId(edge)).GetDstNId())
00430       return true;
00431   }
00432   return false;
00433 }
00434 
00435 int TNEGraph::AddNode(int NId) {
00436   if (NId == -1) {
00437     NId = MxNId;  MxNId++;
00438   } else {
00439     IAssertR(!IsNode(NId), TStr::Fmt("NodeId %d already exists", NId));
00440     MxNId = TMath::Mx(NId+1, MxNId());
00441   }
00442   NodeH.AddDat(NId, TNode(NId));
00443   return NId;
00444 }
00445 
00446 void TNEGraph::DelNode(const int& NId) {
00447   const TNode& Node = GetNode(NId);
00448   for (int out = 0; out < Node.GetOutDeg(); out++) {
00449     const int EId = Node.GetOutEId(out);
00450     const TEdge& Edge = GetEdge(EId);
00451     IAssert(Edge.GetSrcNId() == NId);
00452     GetNode(Edge.GetDstNId()).InEIdV.DelIfIn(EId);
00453     EdgeH.DelKey(EId);
00454   }
00455   for (int in = 0; in < Node.GetInDeg(); in++) {
00456     const int EId = Node.GetInEId(in);
00457     const TEdge& Edge = GetEdge(EId);
00458     IAssert(Edge.GetDstNId() == NId);
00459     GetNode(Edge.GetSrcNId()).OutEIdV.DelIfIn(EId);
00460     EdgeH.DelKey(EId);
00461   }
00462   NodeH.DelKey(NId);
00463 }
00464 
00465 int TNEGraph::AddEdge(const int& SrcNId, const int& DstNId, int EId) {
00466   if (EId == -1) { EId = MxEId;  MxEId++; }
00467   else { MxEId = TMath::Mx(EId+1, MxEId()); }
00468   IAssertR(!IsEdge(EId), TStr::Fmt("EdgeId %d already exists", EId));
00469   IAssertR(IsNode(SrcNId) && IsNode(DstNId), TStr::Fmt("%d or %d not a node.", SrcNId, DstNId).CStr());
00470   EdgeH.AddDat(EId, TEdge(EId, SrcNId, DstNId));
00471   GetNode(SrcNId).OutEIdV.AddSorted(EId);
00472   GetNode(DstNId).InEIdV.AddSorted(EId);
00473   return EId;
00474 }
00475 
00476 void TNEGraph::DelEdge(const int& EId) {
00477   IAssert(IsEdge(EId));
00478   const int SrcNId = GetEdge(EId).GetSrcNId();
00479   const int DstNId = GetEdge(EId).GetDstNId();
00480   GetNode(SrcNId).OutEIdV.DelIfIn(EId);
00481   GetNode(DstNId).InEIdV.DelIfIn(EId);
00482   EdgeH.DelKey(EId);
00483 }
00484 
00485 // delete all edges between the two nodes
00486 void TNEGraph::DelEdge(const int& SrcNId, const int& DstNId, const bool& IsDir) {
00487   int EId;
00488   IAssert(IsEdge(SrcNId, DstNId, EId, IsDir)); // there is at least one edge
00489   while (IsEdge(SrcNId, DstNId, EId, IsDir)) {
00490     GetNode(SrcNId).OutEIdV.DelIfIn(EId);
00491     GetNode(DstNId).InEIdV.DelIfIn(EId);
00492   }
00493   EdgeH.DelKey(EId);
00494 }
00495 
00496 bool TNEGraph::IsEdge(const int& SrcNId, const int& DstNId, int& EId, const bool& IsDir) const {
00497   const TNode& SrcNode = GetNode(SrcNId);
00498   for (int edge = 0; edge < SrcNode.GetOutDeg(); edge++) {
00499     const TEdge& Edge = GetEdge(SrcNode.GetOutEId(edge));
00500     if (DstNId == Edge.GetDstNId()) {
00501       EId = Edge.GetId();  return true; }
00502   }
00503   if (! IsDir) {
00504     for (int edge = 0; edge < SrcNode.GetInDeg(); edge++) {
00505     const TEdge& Edge = GetEdge(SrcNode.GetInEId(edge));
00506     if (DstNId == Edge.GetSrcNId()) {
00507       EId = Edge.GetId();  return true; }
00508     }
00509   }
00510   return false;
00511 }
00512 
00513 void TNEGraph::GetNIdV(TIntV& NIdV) const {
00514   NIdV.Gen(GetNodes(), 0);
00515   for (int N=NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00516     NIdV.Add(NodeH.GetKey(N)); }
00517 }
00518 
00519 void TNEGraph::GetEIdV(TIntV& EIdV) const {
00520   EIdV.Gen(GetEdges(), 0);
00521   for (int E=EdgeH.FFirstKeyId(); EdgeH.FNextKeyId(E); ) {
00522     EIdV.Add(EdgeH.GetKey(E));
00523   }
00524 }
00525 
00526 void TNEGraph::Defrag(const bool& OnlyNodeLinks) {
00527   for (int kid = NodeH.FFirstKeyId(); NodeH.FNextKeyId(kid); ) {
00528     TNode& Node = NodeH[kid];
00529     Node.InEIdV.Pack();  Node.OutEIdV.Pack();
00530   }
00531   if (! OnlyNodeLinks && ! NodeH.IsKeyIdEqKeyN()) { NodeH.Defrag(); }
00532   if (! OnlyNodeLinks && ! EdgeH.IsKeyIdEqKeyN()) { EdgeH.Defrag(); }
00533 }
00534 
00535 bool TNEGraph::IsOk(const bool& ThrowExcept) const {
00536 bool RetVal = true;
00537   for (int N = NodeH.FFirstKeyId(); NodeH.FNextKeyId(N); ) {
00538     const TNode& Node = NodeH[N];
00539     if (! Node.OutEIdV.IsSorted()) {
00540       const TStr Msg = TStr::Fmt("Out-edge list of node %d is not sorted.", Node.GetId());
00541       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00542     }
00543     if (! Node.InEIdV.IsSorted()) {
00544       const TStr Msg = TStr::Fmt("In-edge list of node %d is not sorted.", Node.GetId());
00545       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00546     }
00547     // check out-edge ids
00548     int prevEId = -1;
00549     for (int e = 0; e < Node.GetOutDeg(); e++) {
00550       if (! IsEdge(Node.GetOutEId(e))) {
00551         const TStr Msg = TStr::Fmt("Out-edge id %d of node %d does not exist.",  Node.GetOutEId(e), Node.GetId());
00552         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00553       }
00554       if (e > 0 && prevEId == Node.GetOutEId(e)) {
00555         const TStr Msg = TStr::Fmt("Node %d has duplidate out-edge id %d.", Node.GetId(), Node.GetOutEId(e));
00556         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00557       }
00558       prevEId = Node.GetOutEId(e);
00559     }
00560     // check in-edge ids
00561     prevEId = -1;
00562     for (int e = 0; e < Node.GetInDeg(); e++) {
00563       if (! IsEdge(Node.GetInEId(e))) {
00564         const TStr Msg = TStr::Fmt("Out-edge id %d of node %d does not exist.",  Node.GetInEId(e), Node.GetId());
00565         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00566       }
00567       if (e > 0 && prevEId == Node.GetInEId(e)) {
00568         const TStr Msg = TStr::Fmt("Node %d has duplidate out-edge id %d.", Node.GetId(), Node.GetInEId(e));
00569         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00570       }
00571       prevEId = Node.GetInEId(e);
00572     }
00573   }
00574   for (int E = EdgeH.FFirstKeyId(); EdgeH.FNextKeyId(E); ) {
00575     const TEdge& Edge = EdgeH[E];
00576     if (! IsNode(Edge.GetSrcNId())) {
00577       const TStr Msg = TStr::Fmt("Edge %d source node %d does not exist.", Edge.GetId(), Edge.GetSrcNId());
00578       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00579     }
00580     if (! IsNode(Edge.GetDstNId())) {
00581       const TStr Msg = TStr::Fmt("Edge %d destination node %d does not exist.", Edge.GetId(), Edge.GetDstNId());
00582       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false;
00583     }
00584   }
00585   return RetVal;
00586 }
00587 
00588 void TNEGraph::Dump(FILE *OutF) const {
00589   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00590   const int EdgePlaces = (int) ceil(log10((double) GetEdges()));
00591   fprintf(OutF, "-------------------------------------------------\nDirected Node-Edge Graph: nodes: %d, edges: %d\n", GetNodes(), GetEdges());
00592   for (TNodeI NodeI = BegNI(); NodeI < EndNI(); NodeI++) {
00593     fprintf(OutF, "  %*d]\n", NodePlaces, NodeI.GetId());
00594     fprintf(OutF, "    in[%d]", NodeI.GetInDeg());
00595     for (int edge = 0; edge < NodeI.GetInDeg(); edge++) {
00596       fprintf(OutF, " %*d", EdgePlaces, NodeI.GetInEId(edge)); }
00597     fprintf(OutF, "\n    out[%d]", NodeI.GetOutDeg());
00598     for (int edge = 0; edge < NodeI.GetOutDeg(); edge++) {
00599       fprintf(OutF, " %*d", EdgePlaces, NodeI.GetOutEId(edge)); }
00600     fprintf(OutF, "\n");
00601   }
00602   for (TEdgeI EdgeI = BegEI(); EdgeI < EndEI(); EdgeI++) {
00603     fprintf(OutF, "  %*d]  %*d  ->  %*d\n", EdgePlaces, EdgeI.GetId(), NodePlaces, EdgeI.GetSrcNId(), NodePlaces, EdgeI.GetDstNId());
00604   }
00605   fprintf(OutF, "\n");
00606 }
00607 
00609 // Bipartite graph
00610 int TBPGraph::AddNode(int NId, const bool& LeftNode) {
00611   if (NId == -1) { NId = MxNId;  MxNId++; }
00612   else if (IsLNode(NId)) { IAssertR(LeftNode, TStr::Fmt("Node with id %s already exists on the 'left'.", NId));  return NId; }
00613   else if (IsRNode(NId)) { IAssertR(! LeftNode, TStr::Fmt("Node with id %s already exists on the 'right'.", NId));  return NId; }
00614   else { MxNId = TMath::Mx(NId+1, MxNId()); }
00615   if (LeftNode) { LeftH.AddDat(NId, TNode(NId)); }
00616   else { RightH.AddDat(NId, TNode(NId)); }
00617   return NId;
00618 }
00619 
00620 // Delete node of ID NId from the bipartite graph.
00621 void TBPGraph::DelNode(const int& NId) {
00622   AssertR(IsNode(NId), TStr::Fmt("NodeId %d does not exist", NId));
00623   THash<TInt, TNode>& SrcH = IsLNode(NId) ? LeftH : RightH;
00624   THash<TInt, TNode>& DstH = IsLNode(NId) ? RightH : LeftH;
00625   { TNode& Node = SrcH.GetDat(NId);
00626   for (int e = 0; e < Node.GetOutDeg(); e++) {
00627     const int nbr = Node.GetOutNId(e);
00628     IAssertR(nbr != NId, "Bipartite graph has a loop!");
00629     TNode& N = DstH.GetDat(nbr);
00630     const int n = N.NIdV.SearchBin(NId);
00631     IAssert(n!= -1); 
00632     N.NIdV.Del(n);
00633   } }
00634   SrcH.DelKey(NId);
00635 }
00636 
00637 int TBPGraph::GetEdges() const {
00638   int Edges = 0;
00639   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00640     Edges += LeftH[N].GetDeg(); }
00641   return Edges;
00642 }
00643 
00644 int TBPGraph::AddEdge(const int& LeftNId, const int& RightNId) {
00645   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00646   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00647   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00648   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00649   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00650   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00651   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00652   if (LeftH.GetDat(LNId).IsOutNId(RNId)) { return -2; } // edge already exists
00653   LeftH.GetDat(LNId).NIdV.AddSorted(RNId);
00654   RightH.GetDat(RNId).NIdV.AddSorted(LNId);
00655   return -1; // edge id
00656 }
00657 
00658 void TBPGraph::DelEdge(const int& LeftNId, const int& RightNId) {
00659   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00660   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00661   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00662   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00663   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00664   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00665   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00666   { TIntV& NIdV = LeftH.GetDat(LNId).NIdV;
00667   const int n = NIdV.SearchBin(RNId);
00668   if (n != -1) { NIdV.Del(n); } }
00669   { TIntV& NIdV = RightH.GetDat(RNId).NIdV;
00670   const int n = NIdV.SearchBin(LNId);
00671   if (n != -1) { NIdV.Del(n); } }
00672 }
00673 
00674 bool TBPGraph::IsEdge(const int& LeftNId, const int& RightNId) const {
00675   if (! IsNode(LeftNId) || ! IsNode(RightNId)) { return false; }
00676   return IsLNode(LeftNId) ? LeftH.GetDat(LeftNId).IsOutNId(RightNId) : RightH.GetDat(LeftNId).IsOutNId(RightNId);
00677 }
00678 
00679 TBPGraph::TEdgeI TBPGraph::GetEI(const int& LeftNId, const int& RightNId) const {
00680   const bool IsLL = IsLNode(LeftNId), IsLR = IsRNode(LeftNId);
00681   const bool IsRL = IsLNode(RightNId), IsRR = IsRNode(RightNId);
00682   IAssertR((IsLL||IsLR)&&(IsRL||IsRR), TStr::Fmt("%d or %d is not a node.", LeftNId, RightNId).CStr());
00683   IAssertR(LeftNId!=RightNId, "No self-edges are allowed."); 
00684   IAssertR((IsLL&&!IsLR&&!IsRL&&IsRR)||(!IsLL&&IsLR&&IsRL&&!IsRR), "One node should be on the 'left' and the other on the 'right'.");
00685   const int LNId = IsLL ? LeftNId : RightNId; // the real left node
00686   const int RNId = IsLL ? RightNId : LeftNId; // the real right node
00687   const TNodeI SrcNI = GetNI(LNId);
00688   const int NodeN = SrcNI.LeftHI.GetDat().NIdV.SearchBin(RNId);
00689   IAssertR(NodeN != -1, "Right edge endpoint does not exists!");
00690   return TEdgeI(SrcNI, EndNI(), NodeN);
00691 }
00692 
00693 int TBPGraph::GetRndNId(TRnd& Rnd) { 
00694   const int NNodes = GetNodes();
00695   if (Rnd.GetUniDevInt(NNodes) < GetLNodes()) {
00696     return GetRndLNId(Rnd); }
00697   else {
00698     return GetRndRNId(Rnd); }
00699 }
00700 
00701 int TBPGraph::GetRndLNId(TRnd& Rnd) { 
00702   return LeftH.GetKey(LeftH.GetRndKeyId(Rnd, 0.8)); 
00703 }
00704 
00705 int TBPGraph::GetRndRNId(TRnd& Rnd) { 
00706   return RightH.GetKey(RightH.GetRndKeyId(Rnd, 0.8)); 
00707 }
00708 
00709 void TBPGraph::GetNIdV(TIntV& NIdV) const {
00710   NIdV.Gen(GetNodes(), 0);
00711   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00712     NIdV.Add(LeftH.GetKey(N)); }
00713   for (int N=RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00714     NIdV.Add(RightH.GetKey(N)); }
00715 }
00716 
00717 void TBPGraph::GetLNIdV(TIntV& NIdV) const {
00718   NIdV.Gen(GetLNodes(), 0);
00719   for (int N=LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00720     NIdV.Add(LeftH.GetKey(N)); }
00721 }
00722 
00723 void TBPGraph::GetRNIdV(TIntV& NIdV) const {
00724   NIdV.Gen(GetRNodes(), 0);
00725   for (int N=RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00726     NIdV.Add(RightH.GetKey(N)); }
00727 }
00728 
00729 void TBPGraph::Reserve(const int& Nodes, const int& Edges) { 
00730   if (Nodes>0) { LeftH.Gen(Nodes/2); RightH.Gen(Nodes/2); } 
00731 }
00732 
00733 void TBPGraph::Defrag(const bool& OnlyNodeLinks) {
00734   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00735     LeftH[n].NIdV.Pack(); }
00736   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00737     RightH[n].NIdV.Pack(); }
00738   if (! OnlyNodeLinks && ! LeftH.IsKeyIdEqKeyN()) { LeftH.Defrag(); }
00739   if (! OnlyNodeLinks && ! RightH.IsKeyIdEqKeyN()) { RightH.Defrag(); }
00740 }
00741 
00742 bool TBPGraph::IsOk(const bool& ThrowExcept) const {
00743   bool RetVal = false;
00744   // edge lists are sorted
00745   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00746     if (! LeftH[n].NIdV.IsSorted()) {
00747       const TStr Msg = TStr::Fmt("Neighbor list of node %d is not sorted.", LeftH[n].GetId());
00748       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00749   }
00750   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00751     if (! RightH[n].NIdV.IsSorted()) {
00752       const TStr Msg = TStr::Fmt("Neighbor list of node %d is not sorted.", RightH[n].GetId());
00753       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00754   }
00755   // nodes only appear on one side
00756   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00757     if (RightH.IsKey(LeftH[n].GetId())) {
00758       const TStr Msg = TStr::Fmt("'Left' node %d also appears on the 'right'.", LeftH[n].GetId());
00759       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00760   } 
00761   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00762     if (LeftH.IsKey(RightH[n].GetId())) {
00763       const TStr Msg = TStr::Fmt("'Right' node %d also appears on the 'left'.", RightH[n].GetId());
00764       if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00765   }
00766   // edges only point from left to right and right to left
00767   for (int n = LeftH.FFirstKeyId(); LeftH.FNextKeyId(n); ) {
00768     for (int e = 0; e < LeftH[n].NIdV.Len(); e++) {
00769       if (! RightH.IsKey(LeftH[n].NIdV[e]) || ! RightH.GetDat(LeftH[n].NIdV[e]).NIdV.IsIn(LeftH[n].GetId())) {
00770         const TStr Msg = TStr::Fmt("'Left' node %d does not point to the 'right' node %d.", LeftH[n].GetId(), LeftH[n].NIdV[e]());
00771         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00772     }
00773   }
00774   for (int n = RightH.FFirstKeyId(); RightH.FNextKeyId(n); ) {
00775     for (int e = 0; e < RightH[n].NIdV.Len(); e++) {
00776       if (! LeftH.IsKey(RightH[n].NIdV[e]) || ! LeftH.GetDat(RightH[n].NIdV[e]).NIdV.IsIn(RightH[n].GetId())) {
00777         const TStr Msg = TStr::Fmt("'Left' node %d does not point to the 'right' node %d.", RightH[n].GetId(), RightH[n].NIdV[e]());
00778         if (ThrowExcept) { EAssertR(false, Msg); } else { ErrNotify(Msg.CStr()); } RetVal=false; }
00779     }
00780   }
00781   return RetVal;
00782 }
00783 
00784 void TBPGraph::Dump(FILE *OutF) const {
00785   const int NodePlaces = (int) ceil(log10((double) GetNodes()));
00786   fprintf(OutF, "-------------------------------------------------\nBipartite Graph: nodes: %d+%d=%d, edges: %d\n", GetLNodes(), GetRNodes(), GetNodes(), GetEdges());
00787   for (int N = LeftH.FFirstKeyId(); LeftH.FNextKeyId(N); ) {
00788     const TNode& Node = LeftH[N];
00789     fprintf(OutF, "  %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg());
00790     for (int edge = 0; edge < Node.GetDeg(); edge++) {
00791       fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); }
00792     fprintf(OutF, "\n");
00793   }
00794   fprintf(OutF, "\n");
00795   /*// Also dump the 'right' side
00796   fprintf(OutF, "\n");
00797   for (int N = RightH.FFirstKeyId(); RightH.FNextKeyId(N); ) {
00798     const TNode& Node = RightH[N];
00799     fprintf(OutF, "  %*d [%d] ", NodePlaces, Node.GetId(), Node.GetDeg());
00800     for (int edge = 0; edge < Node.GetDeg(); edge++) {
00801       fprintf(OutF, " %*d", NodePlaces, Node.GetNbrNId(edge)); }
00802     fprintf(OutF, "\n");
00803   }
00804   fprintf(OutF, "\n"); //*/
00805 }
00806 
00807 PBPGraph TBPGraph::GetSmallGraph() {
00808   PBPGraph BP = TBPGraph::New();
00809   BP->AddNode(0, true);
00810   BP->AddNode(1, true);
00811   BP->AddNode(2, false);
00812   BP->AddNode(3, false);
00813   BP->AddNode(4, false);
00814   BP->AddEdge(0, 2);
00815   BP->AddEdge(0, 3);
00816   BP->AddEdge(1, 2);
00817   BP->AddEdge(1, 3);
00818   BP->AddEdge(1, 4);
00819   return BP;
00820 }