SNAP Library, Developer Reference
2012-10-02 12:56:23
SNAP, a general purpose network analysis and graph mining library
|
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 }