Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/graphs/Graph.cpp
Go to the documentation of this file.
00001 
00009 #include "stdinc.h"
00010 #include "Graph.h"
00011 
00012 namespace grafalgo {
00013 
00018 Graph::Graph(int numv, int maxe) : Adt(numv), maxEdge(maxe) {
00019         makeSpace(numv,maxe); 
00020 }
00021 
00022 Graph::~Graph() { freeSpace(); }
00023 
00028 void Graph::makeSpace(int numv, int maxe) {
00029         try {
00030                 fe = new edge[numv+1];
00031                 evec = new EdgeInfo[maxe+1];
00032                 edges = new SetPair(maxe);
00033                 adjLists = new ClistSet(2*maxe+1);
00034         } catch (std::bad_alloc e) {
00035                 stringstream ss;
00036                 ss << "Graph::makeSpace: insufficient space for "
00037                    << numv << "vertices and " << maxe << " edges";
00038                 string s = ss.str();
00039                 throw OutOfSpaceException(s);
00040         }
00041         for (vertex u = 0; u <= numv; u++) fe[u] = 0;
00042         for (edge e = 0; e <= maxe; e++) evec[e].l = 0;
00043         nn = numv; mm = 0; maxEdge = maxe;
00044 }
00045 
00047 void Graph::freeSpace() {
00048         delete [] fe; delete [] evec; delete edges; delete adjLists;
00049 }
00050 
00056 void Graph::resize(int numv, int maxe) {
00057         freeSpace();
00058         try { makeSpace(numv,maxe); } catch(OutOfSpaceException e) {
00059                 string s; s = "Graph::resize:" + e.toString(s);
00060                 throw OutOfSpaceException(s);
00061         }
00062 }
00063 
00068 void Graph::expand(int numv, int maxe) {
00069         if (numv <= n() && maxe <= maxEdge) return;
00070         Graph old(this->n(),this->maxEdge); old.copyFrom(*this);
00071         resize(numv,maxe); this->copyFrom(old);
00072 }
00073 
00075 void Graph::clear() { while (first() != 0) remove(first()); }
00076 
00078 void Graph::copyFrom(const Graph& source) {
00079         if (&source == this) return;
00080         if (source.n() > n() || source.m() > maxEdge)
00081                 resize(source.n(),source.m());
00082         else clear();
00083         for (edge e = source.first(); e != 0; e = source.next(e))
00084                 join(source.left(e),source.right(e));
00085 }
00086 
00093 edge Graph::join(vertex u, vertex v) {
00094         assert(validVertex(u) && validVertex(v));
00095 
00096         edge e = edges->firstOut();
00097         edge ee = joinWith(u,v,e);
00098         return ee;
00099 }
00100 
00108 edge Graph::joinWith(vertex u, vertex v, edge e) {
00109         if (e == 0 || !edges->isOut(e)) return 0;
00110         edges->swap(e);
00111 
00112         // initialize edge information
00113         evec[e].l = u; evec[e].r = v;
00114 
00115         // add edge to the adjacency lists
00116         // in the adjLists data structure, each edge appears twice,
00117         // as 2*e and 2*e+1
00118         if (fe[u] != 0) adjLists->join(2*e,fe[u]);
00119         if (fe[v] != 0) adjLists->join(2*e+1,fe[v]);
00120         if (fe[u] == 0) fe[u] = 2*e;
00121         if (fe[v] == 0) fe[v] = 2*e+1;
00122 
00123         mm++;
00124 
00125         return e;
00126 }
00127 
00132 bool Graph::remove(edge e) {
00133         assert(validEdge(e));
00134         edges->swap(e);
00135 
00136         vertex u = evec[e].l;
00137         if (fe[u] == 2*e)
00138                 fe[u] = (adjLists->suc(2*e) == 2*e ? 0 : adjLists->suc(2*e));
00139         u = evec[e].r;
00140         if (fe[u] == 2*e+1)
00141                 fe[u] = (adjLists->suc(2*e+1) == 2*e+1 ?
00142                                 0 : adjLists->suc(2*e+1));
00143 
00144         adjLists->remove(2*e); adjLists->remove(2*e+1);
00145 
00146         evec[e].l = 0;
00147 
00148         mm--;
00149         return true;
00150 }
00151 
00152 // Compare two edges incident to the same endpoint u.
00153 // Return -1 if u's mate in e1 is less than u's mate in e2.
00154 // Return +1 if u's mate in e1 is greater than than u's mate in e2.
00155 // Return  0 if u's mate in e1 is equal to its mate in e2.
00156 int Graph::ecmp(edge e1, edge e2, vertex u) const {
00157         if (mate(u,e1) < mate(u,e2)) return -1;
00158         else if (mate(u,e1) > mate(u,e2)) return 1;
00159         else return 0;
00160 }
00161 
00165 void Graph::sortAlist(vertex u) {
00166         edge e; int j, k, p, c;
00167 
00168         if (fe[u] == 0) return; // empty list
00169 
00170         int  *elist = new int[n()+1];
00171 
00172         // copy edges in adjacency list for u into an array
00173         k = 1; elist[k++] = fe[u];
00174         for (e = adjLists->suc(fe[u]); e != fe[u]; ) {
00175                 if (k > n())
00176                         Util::fatal("Graph::sortAlist: adjacency list "
00177                                     "too long");
00178                 elist[k++] = e;
00179                 edge f = e; e = adjLists->suc(e); adjLists->remove(f);
00180         }
00181         k--;
00182         // put edge list in heap-order using mate(u) as key
00183         for (j = k/2; j >= 1; j--) {
00184                 // do pushdown starting at position j
00185                 e = elist[j]; p = j;
00186                 while (1) {
00187                         c = 2*p;
00188                         if (c > k) break;
00189                         if (c+1 <= k && ecmp(elist[c+1]/2,elist[c]/2,u) > 0)
00190                                 c++;
00191                         if (ecmp(elist[c]/2,e/2,u) <= 0) break;
00192                         elist[p] = elist[c]; p = c;
00193                 }
00194                 elist[p] = e;
00195         }
00196         // repeatedly extract the edge with largest mate(u) from heap and
00197         // restore heap order
00198         for (j = k-1; j >= 1; j--) {
00199                 e = elist[j+1]; elist[j+1] = elist[1];
00200                 // now largest edges are in positions j+1,...,k
00201                 // elist[1,...,j] forms a heap with edge having
00202                 // largest mate(u) on top
00203                 // pushdown from 1 in this restricted heap
00204                 p = 1;
00205                 while (1) {
00206                         c = 2*p;
00207                         if (c > j) break;
00208                         if (c+1 <= j && ecmp(elist[c+1]/2,elist[c]/2,u) > 0)
00209                                 c++;
00210                         if (ecmp(elist[c]/2,e/2,u) <= 0) break;
00211                         elist[p] = elist[c]; p = c;
00212                 }
00213                 elist[p] = e;
00214         }
00215         // now elist is sorted by mate(u)
00216 
00217         // now rebuild links forming adjacency list for u
00218         for (j = k-1; j >= 1; j--) {
00219                 adjLists->join(elist[j],elist[j+1]);
00220         }
00221         fe[u] = elist[1];
00222 
00223         delete [] elist;
00224 }
00225 
00227 void Graph::sortAdjLists() {
00228         for (vertex u = 1; u <= n(); u++) sortAlist(u);
00229 }
00230 
00237 string& Graph::edge2string(edge e, string& s) const {
00238         return edge2string(e,left(e),s);
00239 }
00240 
00247 string& Graph::edge2string(edge e, vertex u, string& s) const {
00248         s = "(";
00249         string s1;
00250         vertex v = mate(u,e);
00251         s += item2string(u,s1) + ",";
00252         s += item2string(v,s1) + ")";
00253         return s;
00254 }
00255 
00261 string& Graph::elist2string(list<int>& elist, string& s) const {
00262         s = "";
00263         int i = elist.size();
00264         for (edge e : elist) {
00265                 string s1; s += edge2string(e,s1);
00266                 if (--i) s += " ";
00267         }
00268         return s;
00269 }
00270 
00276 string& Graph::adjList2string(vertex u, string& s) const {
00277         s = "";
00278         if (firstAt(u) == 0) return s;
00279         int cnt = 0;
00280         string s1;
00281         s += "[" + Adt::item2string(u,s1) + ":";
00282         for (edge e = firstAt(u); e != 0; e = nextAt(u,e)) {
00283                 vertex v = mate(u,e);
00284                 s += " " + item2string(v,s1);
00285                 if (++cnt >= 20 && nextAt(u,e) != 0) {
00286                         s += "\n"; cnt = 0;
00287                 }
00288         }
00289         s += "]\n";
00290         return s;
00291 }
00292 
00301 string& Graph::toString(string& s) const {
00302         s = "{\n";
00303         for (vertex u = 1; u <= n(); u++) {
00304                 string s1; s += adjList2string(u,s1);
00305         }
00306         s += "}\n";
00307         return s;
00308 }
00309 
00319 string& Graph::toDotString(string& s) const {
00320         s = "graph G {\n";
00321         int cnt = 0;
00322         for (edge e = first(); e != 0; e = next(e)) {
00323                 vertex u = min(left(e),right(e));
00324                 vertex v = max(left(e),right(e));
00325                 string s1;
00326                 s += Adt::item2string(u,s1) + " -- ";
00327                 s += Adt::item2string(v,s1) + " ; "; 
00328                 if (++cnt == 15) { cnt = 0; s += "\n"; }
00329         }
00330         s += "}\n";
00331         return s;
00332 }
00333 
00338 bool Graph::readAdjList(istream& in) {
00339         if (!Util::verify(in,'[')) return 0;
00340         vertex u;
00341         if (!Adt::readItem(in,u)) return 0;
00342         if (u > n()) expand(u,m());
00343         if (!Util::verify(in,':')) return 0;
00344         while (in.good() && !Util::verify(in,']')) {
00345                 vertex v;
00346                 if (!Adt::readItem(in,v)) return 0;
00347                 if (v > n()) expand(v,m());
00348                 if (m() >= maxEdge) expand(n(),max(1,2*m()));
00349                 if (u > v) join(u,v);
00350         }
00351         return in.good();
00352 }
00353 
00360 /*
00361 bool Graph::readEdge(istream& in) {
00362         vertex u, v;
00363         if (!Util::verify(in,'(') || !Adt::readItem(in,u) ||
00364             !Util::verify(in,',') || !Adt::readItem(in,v) ||
00365             !Util::verify(in,')')) {
00366                 return false;
00367         }
00368         if (u < 1 || v < 1) return false;
00369 
00370         int numv = n(); int maxe = maxEdge;
00371         if (u > n() || v > n()) numv = max(max(u,v),2*n());
00372         if (m() >= maxEdge) maxe = 2*maxEdge;
00373         if (numv > n() || maxe > maxEdge) resize(numv,maxe);
00374 
00375         if (u < v) join(u,v);
00376         return true;
00377 }
00378 */
00379 
00384 istream& operator>>(istream& in, Graph& g) {
00385         g.clear();
00386         bool ok = Util::verify(in,'{');
00387         while (ok && !Util::verify(in,'}')) ok = g.readAdjList(in);
00388         if (!ok) {
00389                 string s = "misformatted input for Graph object";
00390                 throw InputException(s);
00391         }
00392         g.sortAdjLists();
00393         return in;
00394 }
00395 
00398 void Graph::scramble() {
00399         int *vp = new int[n()+1]; int *ep = new int[maxEdge+1];
00400         Util::genPerm(n(),vp); Util::genPerm(maxEdge,ep);
00401         shuffle(vp,ep);
00402         sortAdjLists();
00403 }
00404 
00408 void Graph::shuffle(int vp[], int ep[]) {
00409         vertex u; edge e;
00410         EdgeInfo evec1[maxEdge+1];
00411 
00412         for (e = 1; e <= maxEdge; e++) evec1[e].l = evec1[e].r = 0;
00413         for (e = first(); e != 0; e = next(e)) evec1[e] = evec[e];
00414         adjLists->clear(); edges->clear();
00415         for (u = 1; u <= n(); u++) fe[u] = 0;
00416         for (e = 1; e <= maxEdge; e++) {
00417                 if (evec1[e].l != 0)
00418                         joinWith(vp[evec1[e].l],vp[evec1[e].r],ep[e]);
00419         }
00420 }
00421 
00428 void Graph::rgraph(int numv, int nume) {
00429         numv = max(0,numv); nume = max(0,nume);
00430         if (numv > n() || nume > maxEdge) resize(numv,nume); 
00431         else clear();
00432         addEdges(nume);
00433 }
00434 
00440 void Graph::addEdges(int nume) {
00441         if (nume <= m()) return;
00442         // build set containing edges already in graph
00443         HashSet edgeSet(nume);
00444         for (edge e = first(); e != 0; e = next(e)) {
00445                 vertex u = min(left(e), right(e));
00446                 vertex v = max(left(e), right(e));
00447                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00448                 edgeSet.insert(vpair);
00449         }
00450 
00451         // add edges using random sampling of vertex pairs
00452         // stop early if graph gets so dense that most samples
00453         // repeat edges already in graph
00454         while (m() < nume && m()/n() < n()/4) {
00455                 vertex u = Util::randint(1,n());
00456                 vertex v = Util::randint(1,n());
00457                 if (u == v) continue;
00458                 if (u > v) { vertex w = u; u = v; v = w; }
00459                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00460                 if (!edgeSet.member(vpair)) {
00461                         edgeSet.insert(vpair); join(u,v);
00462                 }
00463         }
00464         if (m() == nume) return;
00465 
00466         // if more edges needed, build a vector containing remaining 
00467         // "candidate" edges and then sample from this vector
00468         vector<uint64_t> vpVec;
00469         for (vertex u = 1; u < n(); u++) {
00470                 for (vertex v = u+1; v <= n(); v++) {
00471                         uint64_t vpair = u; vpair <<= 32; vpair |= v;
00472                         if (!edgeSet.member(vpair)) vpVec.push_back(vpair);
00473                 }
00474         }
00475         // sample remaining edges from vector
00476         unsigned int i = 0;
00477         while (m() < nume && i < vpVec.size()) {
00478                 int j = Util::randint(i,vpVec.size()-1);
00479                 vertex u = vpVec[j] >> 32;
00480                 vertex v = vpVec[j] & 0xffffffff;
00481                 join(u,v); vpVec[j] = vpVec[i++];
00482         }
00483         sortAdjLists();
00484 }
00485 
00493 void Graph::rbigraph(int numv, int nume) {
00494         numv = max(1,numv); nume = max(0,nume);
00495         if (n() < 2*numv || maxEdge < nume) resize(2*numv,nume); 
00496         else clear();
00497 
00498         // build set containing edges already in graph
00499         HashSet edgeSet(nume);
00500         for (edge e = first(); e != 0; e = next(e)) {
00501                 vertex u = min(left(e), right(e));
00502                 vertex v = max(left(e), right(e));
00503                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00504                 edgeSet.insert(vpair);
00505         }
00506 
00507         // add edges using random sampling of vertex pairs
00508         // stop early if graph gets so dense that most samples
00509         // repeat edges already in graph
00510         while (m() < nume && m()/numv < numv/2) {
00511                 vertex u = Util::randint(1,numv);
00512                 vertex v = Util::randint(1,numv); v += numv;
00513                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00514                 if (!edgeSet.member(vpair)) {
00515                         edgeSet.insert(vpair); join(u,v);
00516                 }
00517         }
00518         if (m() == nume) return;
00519 
00520         // if more edges needed, build a vector containing remaining 
00521         // "candidate" edges and then sample from this vector
00522         vector<uint64_t> vpVec;
00523         for (vertex u = 1; u <= numv; u++) {
00524                 for (vertex v = numv+1; v <= 2*numv; v++) {
00525                         uint64_t vpair = u; vpair <<= 32; vpair |= v;
00526                         if (!edgeSet.member(vpair)) vpVec.push_back(vpair);
00527                 }
00528         }
00529         // sample remaining edges from vector
00530         unsigned int i = 0;
00531         while (m() < nume && i < vpVec.size()) {
00532                 int j = Util::randint(i,vpVec.size()-1);
00533                 vertex u = vpVec[j] >> 32;
00534                 vertex v = vpVec[j] & 0xffffffff;
00535                 join(u,v); vpVec[j] = vpVec[i++];
00536         }
00537         sortAdjLists();
00538 }
00539 
00547 void Graph::rtree(int numv) {
00548         // build a random sequence of n-2 vertex numbers
00549         // these can be interpreted as "edge endpoints" for
00550         // the non-leaf vertices in the tree to be generated;
00551         // as we're doing this, compute the vertex degrees
00552         vertex endpoints[numv-1]; int d[numv+1];
00553         for (int i = 1; i <= numv; i++) d[i] = 1;
00554         for (int i = 1; i <= numv-2; i++) {
00555                 endpoints[i] = Util::randint(1,numv);
00556                 d[endpoints[i]]++;
00557         }
00558         // now build a heap containing all leaves in the tree
00559         // being generated
00560         Dheap degOne(numv,2);           // vertices with one more edge to go
00561         for (vertex u = 1; u <= numv; u++) {
00562                 if (d[u] == 1) degOne.insert(u,u);
00563         }
00564         // construct tree based on Cayley's theorem
00565         for (int i = 1; i <= numv-2; i++) {
00566                 vertex u = degOne.deletemin();
00567                 vertex v = endpoints[i];
00568                 join(u,v);
00569                 if (--d[v] == 1) degOne.insert(v,v);
00570         }
00571         join(degOne.deletemin(),degOne.deletemin());
00572         sortAdjLists();
00573 }
00574 
00577 void Graph::rcgraph(int numv, int nume) {
00578         // try standard random graph generation
00579         rgraph(numv,nume);
00580 
00581         if (getComponents(NULL) == 1) return;
00582         
00583         // graph too sparse for standard method to produce connected graph
00584         // so start over, adding edges to a random tree
00585         clear();
00586         rtree(numv);
00587         addEdges(nume);
00588 }
00589 
00596 edge Graph::getEdge(vertex u, vertex v) const {
00597         for (edge e = firstAt(u); e != 0; e = nextAt(u,e))
00598                 if (mate(u,e) == v) return e;
00599         return 0;
00600 }
00601 
00611 int Graph::getComponents(int *component) const {
00612         bool noComp = (component == NULL);
00613         if (noComp) component = new int[n()+1];
00614         for (vertex u = 1; u <= n(); u++) component[u] = 0;
00615         
00616         List q(n());
00617         int curComp = 0;
00618         vertex s = 1;
00619         while (s <= n()) {
00620                 // do a breadth-first search from s, labeling all vertices
00621                 // found with the current component number
00622                 component[s] = ++curComp; q.addLast(s);
00623                 while (!q.empty()) {
00624                         vertex u = q.first(); q.removeFirst();
00625                         for (edge e = firstAt(u); e != 0; e = nextAt(u,e)) {
00626                                 vertex v = mate(u,e);
00627                                 if (component[v] == 0) {
00628                                         component[v] = curComp;
00629                                         q.addLast(v);
00630                                 }
00631                         }
00632                 }
00633                 // scan ahead to next vertex that has not yet been placed in
00634                 // some component
00635                 while (s <= n() && component[s] != 0) s++;
00636         }
00637         if (noComp) delete [] component;
00638         return curComp;
00639 }
00640 
00641 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends