Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/dataStructures/graphs/Flograph.cpp
Go to the documentation of this file.
00001 
00008 #include "Flograph.h"
00009 
00010 #define flo(x) floInfo[x].flo
00011 #define cpy(x) floInfo[x].cpy
00012 
00013 namespace grafalgo {
00014 
00021 Flograph::Flograph(int numv, int maxe, int s1, int t1) 
00022         : Digraph(numv, maxe), s(s1), t(t1) {
00023         assert(n() >= 2 && maxEdge >= 0 && 1 <= s && s <= n() 
00024                 && 1 <= t && t <= n() && s != t);
00025         makeSpace(numv,maxe);
00026 }
00027 
00028 Flograph::~Flograph() { freeSpace(); }
00029 
00034 void Flograph::makeSpace(int numv, int maxe) {
00035         try {
00036                 floInfo = new FloInfo[maxe+1];
00037         } catch (std::bad_alloc e) {
00038                 stringstream ss;
00039                 ss << "Flograph::makeSpace: insufficient space for "
00040                    << maxe << " edge weights";
00041                 string s = ss.str();
00042                 throw OutOfSpaceException(s);
00043         }
00044 }
00045 
00047 void Flograph::freeSpace() { delete [] floInfo; }
00048 
00054 void Flograph::resize(int numv, int maxe) {
00055         freeSpace();
00056         Digraph::resize(numv,maxe);
00057         try { makeSpace(numv,maxe); } catch(OutOfSpaceException e) {
00058                 string s; s = "Flograph::resize:" + e.toString(s);
00059                 throw OutOfSpaceException(s);
00060         }
00061 }
00062 
00067 void Flograph::expand(int numv, int maxe) {
00068         if (numv <= n() && maxe <= maxEdge) return;
00069         Flograph old(this->n(),this->maxEdge); old.copyFrom(*this);
00070         resize(numv,maxe); this->copyFrom(old);
00071 }
00072 
00074 void Flograph::copyFrom(const Flograph& source) {
00075         if (&source == this) return;
00076         if (source.n() > n() || source.m() > maxEdge)
00077                 resize(source.n(),source.m());
00078         else clear();
00079         for (edge e = source.first(); e != 0; e = source.next(e)) {
00080                 edge ee = join(source.tail(e),source.head(e));
00081                 setCapacity(ee,source.cap(source.tail(e),e));
00082                 setFlow(ee,source.f(source.tail(e),e));
00083         }
00084         sortAdjLists();
00085 }
00086 
00091 bool Flograph::readAdjList(istream& in) {
00092         if (!Util::verify(in,'[')) return 0;
00093         bool isSrc = false; bool isSnk = false;
00094         if (Util::verify(in,'-')) {
00095                 if (!Util::verify(in,'>',true)) return 0;
00096                 isSnk = true;
00097         }
00098         vertex u;
00099         if (!Adt::readItem(in,u)) return 0;
00100         if (Util::verify(in,'-')) {
00101                 if (!Util::verify(in,'>',true)) return 0;
00102                 isSrc = true;
00103         }
00104         if (!Util::verify(in,':')) return 0;
00105         if (u > n()) expand(u,m());
00106         if (isSrc) setSrc(u);
00107         if (isSnk) setSnk(u);
00108         while (in.good() && !Util::verify(in,']')) {
00109                 vertex v;
00110                 if (!Adt::readItem(in,v)) return 0;
00111                 if (v > n()) expand(v,m());
00112                 if (m() >= maxEdge) expand(n(),max(1,2*m()));
00113                 int capacity, flow;
00114                 if (!Util::verify(in,'(') || !Util::readInt(in,capacity) ||
00115                     !Util::verify(in,',') || !Util::readInt(in,flow) ||
00116                     !Util::verify(in,')'))
00117                         return 0;
00118                 edge e = join(u,v);
00119                 setCapacity(e,capacity); setFlow(e,flow);
00120         }
00121         return in.good();
00122 }
00123 
00129 edge Flograph::join(vertex u, vertex v) {
00130         assert(1 <= u && u <= n() && 1 <= v && v <= n() && m() < maxEdge);
00131         edge e = Digraph::join(u,v); setFlow(e,0);
00132         return e;
00133 }
00134 
00137 void Flograph::clearFlow() {
00138         for (edge e = first(); e != 0; e = next(e)) setFlow(e,0);
00139 }
00140 
00147 void Flograph::addFlow(vertex v, edge e, flow ff) {
00148         if (tail(e) == v) {
00149                 if (ff + flo(e) > cpy(e) || ff + flo(e) < 0) {
00150                         Util::fatal("addflow: requested flow outside allowed "
00151                                     "range");
00152                 }
00153                 flo(e) += ff;
00154         } else {
00155                 if (flo(e) - ff < 0 || flo(e) - ff > cpy(e)) {
00156                         Util::fatal("addflow: requested flow outside allowed "
00157                                     "range");
00158                 }
00159                 flo(e) -= ff;
00160         }
00161 }
00162 
00168 string& Flograph::edge2string(edge e, string& s) const {
00169         stringstream ss;
00170         vertex u = tail(e); vertex v = head(e);
00171         if (e == 0) {
00172                ss << "-"; 
00173         } else {
00174                 ss << "(" << item2string(u,s);
00175                 ss << "," << item2string(v,s)
00176                    << "," << cap(u,e) << "," <<  f(u,e) << ")";
00177         }
00178         s = ss.str();
00179         return s;
00180 }
00181 
00187 string& Flograph::adjList2string(vertex u, string& s) const {
00188         s = "";
00189         if (firstOut(u) == 0) return s;
00190         stringstream ss;
00191         ss << "[";
00192         if (u == snk()) ss << "->";
00193         ss << Adt::item2string(u,s);
00194         if (u == src()) ss << "->";
00195         ss << ":";
00196         int cnt = 0;
00197         for (edge e = firstOut(u); e != 0; e = nextOut(u,e)) {
00198                 vertex v = head(e);
00199                 ss << " " << Adt::item2string(v,s) << "(" << cap(u,e) << ","
00200                    << f(u,e) << ")";
00201                 if (++cnt >= 15 && nextOut(u,e) != 0) {
00202                         ss <<  "\n"; cnt = 0;
00203                 }
00204         }
00205         ss <<  "]\n";
00206         s = ss.str();
00207         return s;
00208 }
00209 
00214 string& Flograph::toDotString(string& s) const {
00215         stringstream ss;
00216         ss << "digraph G { " << endl;
00217         ss << Adt::item2string(src(),s) 
00218            << " [ style = bold, peripheries = 2, color = red]; "
00219            << endl;
00220         ss << Adt::item2string(snk(),s) 
00221            << " [ style = bold, peripheries = 2, color = blue]; "
00222            << endl;
00223         int cnt = 0;
00224         for (edge e = first(); e != 0; e = next(e)) {
00225                 vertex u = min(left(e),right(e));
00226                 vertex v = max(left(e),right(e));
00227                 ss << Adt::item2string(u,s) << " -> ";
00228                 ss << Adt::item2string(v,s);
00229                 ss << " [label = \"(" << cap(u,e) << "," << f(u,e) << ")\"]; ";
00230                 if (++cnt == 10) { s += "\n"; cnt = 0; }
00231         }
00232         ss << "}\n" << endl;
00233         s = ss.str();
00234         return s;
00235 }
00236 
00242 void Flograph::shuffle(int vp[], int ep[]) {
00243         edge e;
00244         FloInfo *floInfo1 = new FloInfo[m()+1];
00245 
00246         Digraph::shuffle(vp,ep);
00247         for (e = 1; e <= m(); e++) floInfo1[ep[e]] = floInfo[e];
00248         for (e = 1; e <= m(); e++) floInfo[e] = floInfo1[e];
00249         s = vp[s]; t = vp[t];
00250 
00251         delete [] floInfo1;
00252 }
00253 
00264 void Flograph::rgraph(int numv, int nume, int mss) {
00265         mss = max(1,mss); mss = min(mss,(numv-2)/4); 
00266         numv = max(numv,3); nume = max(2*mss,nume);
00267 
00268         if (n() != numv || maxEdge < nume) resize(numv,nume); 
00269         else clear();
00270         Digraph::rgraph(numv-2,nume-2*mss);
00271         setSrc(numv-1); setSnk(numv);
00272 
00273         vertex *neighbors = new vertex[2*mss+1];
00274         Util::genPerm(2*mss,neighbors);
00275         for (int i = 1; i <= mss; i++) {
00276                 join(src(),neighbors[i]);
00277         }
00278         Util::genPerm(2*mss,neighbors);
00279         for (int i = 1; i <= mss; i++) {
00280                 join((numv-2)-neighbors[i],snk());
00281         }
00282         sortAdjLists();
00283 
00284         delete [] neighbors;
00285 }
00286 
00292 void Flograph::randCapacity(flow ec1, flow ec2) {
00293         for (edge e = first(); e != 0; e = next(e)) {
00294                 if (tail(e) == s || head(e) == t)
00295                         setCapacity(e,Util::randint(1,ec1));
00296                 else
00297                         setCapacity(e,Util::randint(1,ec2));
00298         }
00299 }
00300 
00301 } // ends namespace
 All Classes Files Functions Variables Typedefs Friends