Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/graphs/Digraph.cpp
Go to the documentation of this file.
00001 
00009 #include "stdinc.h"
00010 #include "Digraph.h"
00011 
00012 namespace grafalgo {
00013 
00018 Digraph::Digraph(int numv, int maxe) : Graph(numv,maxe) {
00019         makeSpace(numv,maxe);
00020 }
00021 
00022 Digraph::~Digraph() { freeSpace(); }
00023 
00028 void Digraph::makeSpace(int numv, int maxe) {
00029         try {
00030                 fi = new edge[numv+1];
00031         } catch (std::bad_alloc e) {
00032                 stringstream ss;
00033                 ss << "Digraph::makeSpace: insufficient space for "
00034                    << numv << "vertices and " << maxe << " edges";
00035                 string s = ss.str();
00036                 throw OutOfSpaceException(s);
00037         }
00038         for (vertex u = 0; u <= numv; u++) fi[u] = 0;
00039         nn = numv;
00040 }
00041 
00043 void Digraph::freeSpace() { delete [] fi; }
00044 
00050 void Digraph::resize(int numv, int maxe) {
00051         freeSpace();
00052         Graph::resize(numv,maxe);
00053         try { makeSpace(numv,maxe); } catch(OutOfSpaceException e) {
00054                 string s; s = "Digraph::resize:" + e.toString(s);
00055                 throw OutOfSpaceException(s);
00056         }
00057 }
00058 
00063 void Digraph::expand(int numv, int maxe) {
00064         if (numv <= n() && maxe <= maxEdge) return;
00065         Digraph old(this->n(),this->maxEdge); old.copyFrom(*this);
00066         resize(numv,maxe); this->copyFrom(old);
00067 }
00068 
00075 edge Digraph::joinWith(vertex u, vertex v, edge e) {
00076         assert(validVertex(u) && validVertex(v));
00077 
00078         if (e == 0 || !edges->isOut(e)) return 0;
00079         edges->swap(e);
00080 
00081         // initialize edge information
00082         evec[e].l = u; evec[e].r = v;
00083 
00084         // add edge to the adjacency lists
00085         // in the adjLists data structure, each edge appears twice,
00086         // as 2*e and 2*e+1
00087         if (fe[u] == 0) fe[u] = 2*e;
00088         else adjLists->join(2*e,fe[u]);
00089         if (fi[v] == 0) fi[v] = 2*e+1;
00090         else adjLists->join(2*e+1,fi[v]);
00091 
00092         mm++;
00093 
00094         return e;
00095 }
00096 
00101 bool Digraph::remove(edge e) {
00102         assert(validEdge(e));
00103         edges->swap(e);
00104 
00105         vertex u = evec[e].l;
00106         if (fe[u] == 2*e)
00107                 fe[u] = (adjLists->suc(2*e) == 2*e ? 0 : adjLists->suc(2*e));
00108         u = evec[e].r;
00109         if (fi[u] == 2*e+1)
00110                 fi[u] = (adjLists->suc(2*e+1) == 2*e+1 ?
00111                                 0 : adjLists->suc(2*e+1));
00112 
00113         adjLists->remove(2*e); adjLists->remove(2*e+1);
00114 
00115         evec[e].l = 0;
00116 
00117         mm--;
00118         return true;
00119 }
00120 
00126 string& Digraph::adjList2string(vertex u, string& s) const {
00127         s = "";
00128         if (firstOut(u) == 0) return s;
00129         int cnt = 0;
00130         string s1;
00131         s += "[" + Adt::item2string(u,s1) + ":";
00132         for (edge e = firstOut(u); e != 0; e = nextOut(u,e)) {
00133                 vertex v = head(e);
00134                 s += " " + Adt::item2string(v,s1);
00135                 if (++cnt >= 20 && nextOut(u,e) != 0) {
00136                         s += "\n"; cnt = 0;
00137                 }
00138         }
00139         s += "]\n";
00140         return s;
00141 }
00142 
00152 string& Digraph::toDotString(string& s) const {
00153         s = "digraph G {\n";
00154         int cnt = 0;
00155         for (edge e = first(); e != 0; e = next(e)) {
00156                 vertex u = tail(e); vertex v = head(e);
00157                 string s1;
00158                 s += Adt::item2string(u,s1) + " -> ";
00159                 s += Adt::item2string(v,s1) + " ; "; 
00160                 if (++cnt == 15) { cnt = 0; s += "\n"; }
00161         }
00162         s += "}\n";
00163         return s;
00164 }
00165 
00170 /*
00171 bool Digraph::readEdge(istream& in) {
00172         vertex u, v;
00173         if (!Util::verify(in,'(') || !Adt::readItem(in,u) ||
00174             !Util::verify(in,',') || !Adt::readItem(in,v) ||
00175             !Util::verify(in,')')) {
00176                 return false;
00177         }
00178         if (u < 1 || v < 1) return false;
00179 
00180         int numv = n(); int maxe = maxEdge;
00181         if (u > n() || v > n()) numv = max(max(u,v),2*n());
00182         if (m() >= maxEdge) maxe = 2*maxEdge;
00183         if (numv > n() || maxe > maxEdge) resize(numv,maxe);
00184 
00185         join(u,v);
00186         return true;
00187 }
00188 */
00189 
00194 bool Digraph::readAdjList(istream& in) {
00195         if (!Util::verify(in,'[')) return 0;
00196         vertex u;
00197         if (!Adt::readItem(in,u)) return 0;
00198         if (u > n()) expand(u,m());
00199         if (!Util::verify(in,':')) return 0;
00200         while (in.good() && !Util::verify(in,']')) {
00201                 vertex v;
00202                 if (!Adt::readItem(in,v)) return 0;
00203                 if (v > n()) expand(v,m());
00204                 if (m() >= maxEdge) expand(n(),max(1,2*m()));
00205                 join(u,v);
00206         }
00207         return in.good();
00208 }
00209 
00214 /*
00215 istream& operator>>(istream& in, Digraph& dg) {
00216         bool ok = Util::verify(in,'{');
00217         while (ok && !Util::verify(in,'}')) ok = dg.readEdge(in);
00218         if (!ok) {
00219                 string s = "misformatted input for Graph object";
00220                 throw InputException(s);
00221         }
00222         dg.sortAdjLists();
00223         return in;
00224 }
00225 */
00226 
00233 void Digraph::rgraph(int numv, int nume) {
00234         numv = max(0,numv); nume = max(0,nume);
00235         if (numv > n() || nume > maxEdge) resize(numv,nume); 
00236         else clear();
00237 
00238         // build set containing edges already in graph
00239         HashSet edgeSet(nume);
00240         for (edge e = first(); e != 0; e = next(e)) {
00241                 vertex u = min(tail(e), head(e));
00242                 vertex v = max(tail(e), head(e));
00243                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00244                 edgeSet.insert(vpair);
00245         }
00246 
00247         // add edges using random sampling of vertex pairs
00248         // stop early if graph gets so dense that most samples
00249         // repeat edges already in graph
00250         while (m() < nume && m()/numv < numv/2) {
00251                 vertex u = Util::randint(1,numv);
00252                 vertex v = Util::randint(1,numv);
00253                 if (u == v) continue;
00254                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00255                 if (!edgeSet.member(vpair)) {
00256                         edgeSet.insert(vpair); join(u,v);
00257                 }
00258         }
00259         if (m() == nume) return;
00260 
00261         // if more edges needed, build a vector containing remaining 
00262         // "candidate" edges and then sample from this vector
00263         vector<uint64_t> vpVec;
00264         unsigned int i = 0;
00265         for (vertex u = 1; u < numv; u++) {
00266                 for (vertex v = 1; v <= numv; v++) {
00267                         if (v == u) continue;
00268                         uint64_t vpair = u; vpair <<= 32; vpair |= v;
00269                         if (!edgeSet.member(vpair)) vpVec[i++] = vpair;
00270                 }
00271         }
00272         // sample remaining edges from vector
00273         i = 0;
00274         while (m() < nume && i < vpVec.size()) {
00275                 int j = Util::randint(i,vpVec.size()-1);
00276                 vertex u = vpVec[j] >> 32;
00277                 vertex v = vpVec[j] & 0xffffffff;
00278                 join(u,v); vpVec[j] = vpVec[i++];
00279         }
00280         sortAdjLists();
00281 }
00282 
00289 void Digraph::rdag(int numv, int nume) {
00290         numv = max(0,numv); nume = max(0,nume);
00291         if (n() < numv || maxEdge < nume) resize(numv,nume); 
00292         else clear();
00293 
00294         // build set containing edges already in graph
00295         HashSet edgeSet(nume);
00296         for (edge e = first(); e != 0; e = next(e)) {
00297                 vertex u = min(tail(e), head(e));
00298                 vertex v = max(tail(e), head(e));
00299                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00300                 edgeSet.insert(vpair);
00301         }
00302 
00303         // add edges using random sampling of vertex pairs
00304         // stop early if graph gets so dense that most samples
00305         // repeat edges already in graph
00306         while (m() < nume && m()/numv < numv/4) {
00307                 vertex u = Util::randint(1,numv-1);
00308                 vertex v = Util::randint(u+1,numv);
00309                 if (u == v) continue;
00310                 uint64_t vpair = u; vpair <<= 32; vpair |= v;
00311                 if (!edgeSet.member(vpair)) {
00312                         edgeSet.insert(vpair); join(u,v);
00313                 }
00314         }
00315         if (m() == nume) return;
00316 
00317         // if more edges needed, build a vector containing remaining 
00318         // "candidate" edges and then sample from this vector
00319         vector<uint64_t> vpVec;
00320         for (vertex u = 1; u < numv; u++) {
00321                 for (vertex v = u+1; v <= numv; v++) {
00322                         if (v == u) continue;
00323                         uint64_t vpair = u; vpair <<= 32; vpair |= v;
00324                         if (!edgeSet.member(vpair)) vpVec.push_back(vpair);
00325                 }
00326         }
00327         // sample remaining edges from vector
00328         int i = 0;
00329         while (m() < nume && i < vpVec.size()) {
00330                 int j = Util::randint(i,vpVec.size()-1);
00331                 vertex u = vpVec[j] >> 32;
00332                 vertex v = vpVec[j] & 0xffffffff;
00333                 join(u,v); vpVec[j] = vpVec[i++];
00334         }
00335         sortAdjLists();
00336 }
00337 
00338 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends