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