digraph.h

Go to the documentation of this file.
00001 
00002 
00003 
00015 
00016 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00017 //
00018 // This file is part of the Homology Library.  This library is free software;
00019 // you can redistribute it and/or modify it under the terms of the GNU
00020 // General Public License as published by the Free Software Foundation;
00021 // either version 2 of the License, or (at your option) any later version.
00022 //
00023 // This library is distributed in the hope that it will be useful,
00024 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00026 // GNU General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License along
00029 // with this software; see the file "license.txt".  If not, write to the
00030 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00031 // MA 02111-1307, USA.
00032 
00033 // Started in January 2006. Last revision: May 29, 2010.
00034 
00035 
00036 #ifndef _CHOMP_STRUCT_DIGRAPH_H_
00037 #define _CHOMP_STRUCT_DIGRAPH_H_
00038 
00039 #include <iostream>
00040 #include <new>
00041 #include <stack>
00042 #include <queue>
00043 #include <set>
00044 #include <memory>
00045 #include <vector>
00046 #include <algorithm>
00047 
00048 #include "chomp/struct/multitab.h"
00049 #include "chomp/struct/hashsets.h"
00050 #include "chomp/struct/flatmatr.h"
00051 #include "chomp/struct/bitfield.h"
00052 #include "chomp/struct/bitsets.h"
00053 #include "chomp/struct/fibheap.h"
00054 #include "chomp/system/textfile.h"
00055 #include "chomp/system/timeused.h"
00056 
00057 namespace chomp {
00058 namespace homology {
00059 
00060 
00061 // --------------------------------------------------
00062 // ----------------- DUMMY ROUNDING -----------------
00063 // --------------------------------------------------
00064 
00067 template <class numType>
00068 class dummyRounding
00069 {
00070 public:
00072         static inline numType add_down (const numType &x, const numType &y)
00073         { return x + y; }
00074 
00076         static inline numType add_up (const numType &x, const numType &y)
00077         { return x + y; }
00078 
00080         static inline numType sub_down (const numType &x, const numType &y)
00081         { return x - y; }
00082 
00084         static inline numType sub_up (const numType &x, const numType &y)
00085         { return x - y; }
00086 
00088         static inline numType mul_down (const numType &x, const numType &y)
00089         { return x * y; }
00090 
00092         static inline numType mul_up (const numType &x, const numType &y)
00093         { return x * y; }
00094 
00096         static inline numType div_down (const numType &x, const numType &y)
00097         { return x / y; }
00098 
00100         static inline numType div_down (const numType &x, int_t y)
00101         { return x / y; }
00102 
00104         static inline numType div_up (const numType &x, const numType &y)
00105         { return x / y; }
00106 
00107 private:
00108 }; /* class dummyRounding */
00109 
00110 
00111 // --------------------------------------------------
00112 // ------------------ DUMMY ARRAY -------------------
00113 // --------------------------------------------------
00114 
00116 class dummyArray
00117 {
00118 public:
00120         dummyArray () {n = 0;}
00121 
00123         int_t &operator [] (int_t) {return n;}
00124 
00125 private:
00127         int_t n;
00128 
00129 }; /* class dummyArray */
00130 
00131 
00132 // --------------------------------------------------
00133 // ----------------- DIRECTED GRAPH -----------------
00134 // --------------------------------------------------
00135 
00136 // #define DIGRAPH_DEBUG
00137 
00141 template <class wType = int>
00142 class diGraph
00143 {
00144 public:
00146         typedef wType weight_type;
00147         
00151         diGraph ();
00152 
00154         ~diGraph ();
00155 
00157         void swap (diGraph<wType> &g);
00158 
00160         void addVertex (void);
00161 
00164         void addEdge (int_t target);
00165 
00168         void addEdge (int_t target, const wType &weight);
00169 
00171         void setWeight (int_t vertex, int_t i, const wType &weight);
00172 
00174         void setWeight (int_t edge, const wType &weight);
00175         
00178         template <class Table>
00179         void setWeights (const Table &tab);
00180 
00183         void removeVertex (void);
00184 
00189         void removeVertex (int_t vertex, bool updateweights = false);
00190 
00192         int_t countVertices (void) const;
00193 
00195         int_t countEdges (void) const;
00196 
00198         int_t countEdges (int_t vertex) const;
00199         
00201         int_t getEdge (int_t vertex, int_t i) const;
00202 
00204         const wType &getWeight (int_t vertex, int_t i) const;
00205 
00207         const wType &getWeight (int_t edge) const;
00208 
00211         template <class Table>
00212         void getWeights (Table &tab) const;
00213 
00217         template <class Table>
00218         void writeEdges (Table &tab) const;
00219 
00221         template <class wType1>
00222         void transpose (diGraph<wType1> &result,
00223                 bool copyweights = false) const;
00224 
00228         template <class Table, class wType1>
00229         void subgraph (diGraph<wType1> &result, const Table &tab,
00230                 bool copyweights = false) const;
00231 
00235         template <class Table, class Color>
00236         void DFScolor (Table &tab, const Color &color,
00237                 int_t vertex = 0) const;
00238 
00240         template <class Table, class Color>
00241         void DFScolorRecurrent (Table &tab, const Color &color,
00242                 int_t vertex = 0) const;
00243 
00245         template <class Table, class Color>
00246         void DFScolorStack (Table &tab, const Color &color,
00247                 int_t vertex = 0) const;
00248 
00251         template <class Table>
00252         void DFSfinishTime (Table &tab) const;
00253 
00263         template <class Table1, class Table2, class Table3>
00264         int_t DFSforest (const Table1 &ordered, Table2 &compVertices,
00265                 Table3 &compEnds, bool nontrivial = false,
00266                 diGraph<wType> *sccGraph = 0) const;
00267 
00273         int_t shortestPath (int_t source, int_t destination) const;
00274 
00279         int_t shortestLoop (int_t origin) const;
00280 
00288         template <class lenTable, class weightsType, class roundType>
00289         void Dijkstra (const roundType &rounding, int_t source,
00290                 lenTable &len, weightsType &edgeWeights) const;
00291 
00293         template <class lenTable, class roundType>
00294         void Dijkstra (const roundType &rounding, int_t source,
00295                 lenTable &len) const;
00296 
00298         template <class lenTable>
00299         void Dijkstra (int_t source, lenTable &len) const;
00300 
00311         template <class lenTable, class predTable, class roundType>
00312         bool BellmanFord (const roundType &rounding, int_t source,
00313                 lenTable &len, wType *infinity, predTable pred) const;
00314 
00316         template <class lenTable, class predTable>
00317         bool BellmanFord (int_t source, lenTable &len, wType *infinity,
00318                 predTable pred) const;
00319 
00323         template <class roundType>
00324         bool BellmanFord (const roundType &rounding, int_t source) const;
00325 
00327         bool BellmanFord (int_t source) const;
00328 
00335         wType Edmonds () const;
00336 
00338         wType EdmondsOld () const;
00339 
00354         template <class arrayType, class roundType>
00355         wType FloydWarshall (const roundType &rounding, arrayType &arr,
00356                 bool setInfinity = true, bool ignoreNegLoop = false) const;
00357 
00359         template <class arrayType>
00360         wType FloydWarshall (arrayType &arr, bool setInfinity = true,
00361                 bool ignoreNegLoop = false) const;
00362 
00371         template <class arrayType, class roundType>
00372         wType Johnson (const roundType &rounding, arrayType &arr,
00373                 bool setInfinity = true, bool ignoreNegLoop = false) const;
00374 
00376         template <class arrayType>
00377         wType Johnson (arrayType &arr, bool setInfinity = true,
00378                 bool ignoreNegLoop = false) const;
00379 
00389         template <class roundType>
00390         wType minPathWeight (const roundType &rounding,
00391                 bool ignoreNegLoop = false, int sparseGraph = -1) const;
00392 
00394         wType minPathWeight (bool ignoreNegLoop = false,
00395                 int sparseGraph = -1) const;
00396 
00401         wType minMeanCycleWeight (diGraph<wType> *transposed = 0) const;
00402 
00411         template <class roundType>
00412         wType minMeanCycleWeight (const roundType &rounding,
00413                 diGraph<wType> *transposed) const;
00414 
00420         template <class arrayType, class roundType>
00421         wType minMeanPathWeight (const roundType &rounding,
00422                 const arrayType &starting, int_t n) const;
00423 
00425         template <class arrayType>
00426         wType minMeanPathWeight (const arrayType &starting, int_t n) const;
00427 
00430         template <class wType1, class wType2>
00431         friend bool operator == (const diGraph<wType1> &g1,
00432                 const diGraph<wType2> &g2);
00433 
00435         template <class outType>
00436         outType &show (outType &out, bool showWeights = false) const;
00437 
00438 protected:
00440         int_t nVertices;
00441 
00444         multitable<int_t> edgeEnds;
00445 
00447         multitable<int_t> edges;
00448 
00450         multitable<wType> weights;
00451 
00452 private:
00454         template <class Table>
00455         void DFSfinishTimeRecurrent (Table &tab, int_t vertex,
00456                 int_t &counter) const;
00457 
00459         template <class Table>
00460         void DFSfinishTimeStack (Table &tab, int_t vertex,
00461                 int_t &counter) const;
00462 
00465         template <class Table1, class Table2>
00466         bool DFSforestRecurrent (Table1 &tab, Table1 &ntab, int_t vertex,
00467                 int_t treeNumber, int_t countTrees, Table2 &compVertices,
00468                 int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded)
00469                 const;
00470 
00472         template <class Table1, class Table2>
00473         bool DFSforestStack (Table1 &tab, Table1 &ntab, int_t vertex,
00474                 int_t treeNumber, int_t countTrees, Table2 &compVertices,
00475                 int_t &curVertex, diGraph *sccGraph, int_t *sccEdgeAdded)
00476                 const;
00477 
00479         struct edgeTriple
00480         {
00482                 int_t vert1;
00483                 int_t vert2;
00484                 
00486                 wType weight;
00487 
00489                 friend bool operator < (const edgeTriple &x,
00490                         const edgeTriple &y)
00491                 {
00492                         return (x. weight < y. weight);
00493                 }
00494         };
00495 
00498         class posWeight
00499         {
00500         public:
00502                 posWeight ()
00503                 {
00504                         value = 0;
00505                         return;
00506                 }
00507 
00509                 explicit posWeight (const wType &_value)
00510                 {
00511                         if (_value < 0)
00512                                 value = 0;
00513                         else
00514                                 value = _value;
00515                         return;
00516                 }
00517 
00519                 void setInfinity ()
00520                 {
00521                         value = -1;
00522                         return;
00523                 }
00524 
00526                 bool isInfinity () const
00527                 {
00528                         return (value < 0);
00529                 }
00530 
00532                 const wType &getValue () const
00533                 {
00534                         return value;
00535                 }
00536 
00538                 friend bool operator < (const posWeight &x,
00539                         const posWeight &y)
00540                 {
00541                         if (y. isInfinity ())
00542                                 return !(x. isInfinity ());
00543                         else if (x. isInfinity ())
00544                                 return false;
00545                         return (x. value < y. value);
00546                 }
00547 
00549                 friend std::ostream &operator << (std::ostream &out,
00550                         const posWeight &x)
00551                 {
00552                         if (x. isInfinity ())
00553                                 out << "+oo";
00554                         else
00555                                 out << x. getValue ();
00556                         return out;
00557                 }
00558 
00559         private:
00561                 wType value;
00562         };
00563 
00564 }; /* class diGraph */
00565 
00566 // --------------------------------------------------
00567 
00568 template <class wType>
00569 inline diGraph<wType>::diGraph (): nVertices (0),
00570         edgeEnds (1024), edges (4096), weights (4096)
00571 {
00572         return;
00573 } /* diGraph::diGraph */
00574 
00575 template <class wType>
00576 inline diGraph<wType>::~diGraph ()
00577 {
00578         return;
00579 } /* diGraph::~diGraph */
00580 
00581 // --------------------------------------------------
00582 
00583 template <class wType1, class wType2>
00584 inline bool operator == (const diGraph<wType1> &g1,
00585         const diGraph<wType2> &g2)
00586 {
00587         if (g1. nVertices != g2. nVertices)
00588                 return false;
00589         if (!g1. nVertices)
00590                 return true;
00591         for (int_t i = 0; i < g1. nVertices; ++ i)
00592         {
00593                 if (g1. edgeEnds [i] != g2. edgeEnds [i])
00594                         return false;
00595         }
00596         int_t nEdges = g1. edgeEnds [g1. nVertices - 1];
00597         for (int_t i = 0; i < nEdges; ++ i)
00598         {
00599                 if (g1. edges [i] != g2. edges [i])
00600                         return false;
00601         }
00602         return true;
00603 } /* operator == */
00604 
00605 template <class wType1, class wType2>
00606 inline bool operator != (const diGraph<wType1> &g1,
00607         const diGraph<wType2> &g2)
00608 {
00609         return !(g1 == g2);
00610 } /* operator != */
00611 
00612 // --------------------------------------------------
00613 
00614 template <class wType>
00615 inline void diGraph<wType>::swap (diGraph<wType> &g)
00616 {
00617         my_swap (nVertices, g. nVertices);
00618         edgeEnds. swap (g. edgeEnds);
00619         edges. swap (g. edges);
00620         weights. swap (g. weights);
00621         return;
00622 } /* diGraph::swap */
00623 
00624 template <class wType>
00625 inline void diGraph<wType>::addVertex (void)
00626 {
00627         edgeEnds [nVertices] = nVertices ? edgeEnds [nVertices - 1] :
00628                 static_cast<int_t> (0);
00629         ++ nVertices;
00630         return;
00631 } /* diGraph::addVertex */
00632 
00633 template <class wType>
00634 inline void diGraph<wType>::addEdge (int_t target)
00635 {
00636         if (!nVertices)
00637                 throw "Trying to add an edge to an empty graph.";
00638 //      if (target >= nVertices)
00639 //              throw "Trying to add an edge to a nonexistent vertex.";
00640         if (target < 0)
00641                 throw "Trying to add an edge to a negative vertex.";
00642         int_t &offset = edgeEnds [nVertices - 1];
00643         if (offset + 1 <= 0)
00644                 throw "Too many edges in a diGraph (limit = 2,147,483,647).";
00645         edges [offset] = target;
00646         ++ offset;
00647         return;
00648 } /* diGraph::addEdge */
00649 
00650 template <class wType>
00651 inline void diGraph<wType>::addEdge (int_t target, const wType &weight)
00652 {
00653         if (!nVertices)
00654                 throw "Trying to add an edge to an empty graph.";
00655 //      if (target >= nVertices)
00656 //              throw "Trying to add an edge to a nonexistent vertex.";
00657         if (target < 0)
00658                 throw "Trying to add an edge to a negative vertex.";
00659         int_t &offset = edgeEnds [nVertices - 1];
00660         if (offset + 1 <= 0)
00661                 throw "Too many edges in a diGraph (limit = 2,147,483,647).";
00662         edges [offset] = target;
00663         weights [offset] = weight;
00664         ++ offset;
00665         return;
00666 } /* diGraph::addEdge */
00667 
00668 template <class wType>
00669 inline void diGraph<wType>::setWeight (int_t vertex, int_t i,
00670         const wType &weight)
00671 {
00672         if (!vertex)
00673                 weights [i] = weight;
00674         else
00675                 weights [edgeEnds [vertex - 1] + i] = weight;
00676         return;
00677 } /* diGraph::setWeight */
00678 
00679 template <class wType>
00680 inline void diGraph<wType>::setWeight (int_t edge, const wType &weight)
00681 {
00682         weights [edge] = weight;
00683         return;
00684 } /* diGraph::setWeight */
00685 
00686 template <class wType> template <class Table>
00687 inline void diGraph<wType>::setWeights (const Table &tab)
00688 {
00689         if (!nVertices)
00690                 return;
00691         int_t nEdges = edgeEnds [nVertices - 1];
00692         for (int_t i = 0; i < nEdges; ++ i)
00693                 weights [i] = tab [i];
00694         return;
00695 } /* diGraph::setWeights */
00696 
00697 template <class wType>
00698 inline void diGraph<wType>::removeVertex (void)
00699 {
00700         if (!nVertices)
00701                 throw "Trying to remove a vertex from the empty graph.";
00702         -- nVertices;
00703         return;
00704 } /* diGraph::removeVertex */
00705 
00706 template <class wType>
00707 inline void diGraph<wType>::removeVertex (int_t vertex, bool updateweights)
00708 {
00709         // make sure that the vertex number is within the scope
00710         if ((vertex < 0) || (vertex >= nVertices))
00711                 throw "Trying to remove a vertex that is not in the graph.";
00712 
00713         // remove edges that begin or end at the given vertex
00714         int_t curEdge = 0;
00715         int_t newEdge = 0;
00716         int_t skipped = 0;
00717         for (int_t v = 0; v < nVertices; ++ v)
00718         {
00719                 // skip the edges that begin at the given vertex
00720                 if (!skipped && (v == vertex))
00721                 {
00722                         curEdge = edgeEnds [v];
00723                         ++ skipped;
00724                         continue;
00725                 }
00726 
00727                 // skip the edges that point to the given vertex
00728                 int_t maxEdge = edgeEnds [v];
00729                 for (; curEdge < maxEdge; ++ curEdge)
00730                 {
00731                         if (edges [curEdge] == vertex)
00732                                 continue;
00733                         int_t target = edges [curEdge];
00734                         edges [newEdge] = (target < vertex) ? target :
00735                                 (target - 1);
00736                         if (updateweights)
00737                                 weights [newEdge] = weights [curEdge];
00738                         ++ newEdge;
00739                 }
00740                 edgeEnds [v - skipped] = newEdge;
00741         }
00742 
00743         // decrease the number of vertices
00744         nVertices -= skipped;
00745 
00746         return;
00747 } /* diGraph::removeVertex */
00748 
00749 template <class wType>
00750 inline int_t diGraph<wType>::countVertices (void) const
00751 {
00752         return nVertices;
00753 } /* diGraph::countVertices */
00754 
00755 template <class wType>
00756 inline int_t diGraph<wType>::countEdges (void) const
00757 {
00758         if (!nVertices)
00759                 return 0;
00760         else
00761                 return edgeEnds [nVertices - 1];
00762 } /* diGraph::countEdges */
00763 
00764 template <class wType>
00765 inline int_t diGraph<wType>::countEdges (int_t vertex) const
00766 {
00767         if (!vertex)
00768                 return edgeEnds [0];
00769         else
00770                 return edgeEnds [vertex] - edgeEnds [vertex - 1];
00771 } /* diGraph::countEdges */
00772 
00773 template <class wType>
00774 inline int_t diGraph<wType>::getEdge (int_t vertex, int_t i) const
00775 {
00776         if (!vertex)
00777                 return edges [i];
00778         else
00779                 return edges [edgeEnds [vertex - 1] + i];
00780 } /* diGraph::getEdge */
00781 
00782 template <class wType>
00783 inline const wType &diGraph<wType>::getWeight (int_t vertex, int_t i) const
00784 {
00785         if (!vertex)
00786                 return weights [i];
00787         else
00788                 return weights [edgeEnds [vertex - 1] + i];
00789 } /* diGraph::getWeight */
00790 
00791 template <class wType>
00792 inline const wType &diGraph<wType>::getWeight (int_t edge) const
00793 {
00794         return weights [edge];
00795 } /* diGraph::getWeight */
00796 
00797 template <class wType> template <class Table>
00798 inline void diGraph<wType>::getWeights (Table &tab) const
00799 {
00800         if (!nVertices)
00801                 return;
00802         int_t nEdges = edgeEnds [nVertices - 1];
00803         for (int_t i = 0; i < nEdges; ++ i)
00804                 tab [i] = weights [i];
00805         return;
00806 } /* diGraph::getWeights */
00807 
00808 template <class wType> template <class Table>
00809 inline void diGraph<wType>::writeEdges (Table &tab) const
00810 {
00811         int_t curEdge = 0;
00812         for (int_t curVertex = 0; curVertex < nVertices; ++ curVertex)
00813         {
00814                 int_t maxEdge = edgeEnds [curVertex];
00815                 while (curEdge < maxEdge)
00816                 {
00817                         tab [curEdge] [0] = curVertex;
00818                         tab [curEdge] [1] = edges [curEdge];
00819                         ++ curEdge;
00820                 }
00821         }
00822         return;
00823 } /* diGraph::writeEdges */
00824 
00825 template <class wType> template <class wType1>
00826 inline void diGraph<wType>::transpose (diGraph<wType1> &result,
00827         bool copyweights) const
00828 {
00829         // prepare the resulting graph
00830         result. nVertices = nVertices;
00831         if (!nVertices)
00832                 return;
00833 
00834         // compute the initial offsets for the edge numbers
00835         for (int_t i = 0; i < nVertices; ++ i)
00836                 result. edgeEnds [i] = 0;
00837         int_t nEdges = edgeEnds [nVertices - 1];
00838         for (int_t i = 0; i < nEdges; ++ i)
00839         {
00840                 if (edges [i] < nVertices - 1)
00841                         ++ result. edgeEnds [edges [i] + 1];
00842         }
00843         for (int_t i = 2; i < nVertices; ++ i)
00844                 result. edgeEnds [i] += result. edgeEnds [i - 1];
00845 
00846         // compute the reversed edges
00847         int_t curEdge = 0;
00848         for (int_t i = 0; i < nVertices; ++ i)
00849         {
00850                 for (; curEdge < edgeEnds [i]; ++ curEdge)
00851                 {
00852                         int_t j = edges [curEdge];
00853                         int_t &offset = result. edgeEnds [j];
00854                         result. edges [offset] = i;
00855                         if (copyweights)
00856                                 result. weights [offset] = weights [curEdge];
00857                         ++ offset;
00858                 }
00859         }
00860         return;
00861 } /* diGraph::transpose */
00862 
00863 template <class wType> template <class Table, class wType1>
00864 inline void diGraph<wType>::subgraph (diGraph<wType1> &g,
00865         const Table &tab, bool copyweights) const
00866 {
00867         // compute the new numbers of vertices that remain in the graph
00868         int_t *numbers = new int_t [nVertices];
00869         int_t curNumber = 0;
00870         for (int_t i = 0; i < nVertices; ++ i)
00871         {
00872                 if (tab [i])
00873                         numbers [i] = curNumber ++;
00874                 else
00875                         numbers [i] = -1;
00876         }
00877 
00878         // copy the edges from the old graph to the new one
00879         for (int_t i = 0; i < nVertices; ++ i)
00880         {
00881                 if (numbers [i] < 0)
00882                         continue;
00883                 g. addVertex ();
00884                 int_t firstEdge = i ? edgeEnds [i - 1] :
00885                         static_cast<int_t> (0);
00886                 int_t endEdge = edgeEnds [i];
00887                 for (int_t j = firstEdge; j < endEdge; ++ j)
00888                 {
00889                         int_t edgeEnd = edges [j];
00890                         if (numbers [edgeEnd] >= 0)
00891                         {
00892                                 if (copyweights)
00893                                         g. addEdge (numbers [edgeEnd],
00894                                                 weights [j]);
00895                                 else
00896                                         g. addEdge (numbers [edgeEnd]);
00897                         }
00898                 }
00899         }
00900 
00901         // clean up memory and exit
00902         delete [] numbers;
00903         return;
00904 } /* diGraph::subgraph */
00905 
00906 // --------------------------------------------------
00907 
00908 template <class wType> template <class Table, class Color>
00909 inline void diGraph<wType>::DFScolorRecurrent (Table &tab,
00910         const Color &color, int_t vertex) const
00911 {
00912         tab [vertex] = color;
00913         int_t maxEdge = edgeEnds [vertex];
00914         for (int_t i = vertex ? edgeEnds [vertex - 1] :
00915                 static_cast<int_t> (0); i < maxEdge; ++ i)
00916         {
00917                 int_t next = edges [i];
00918                 if (tab [next] != color)
00919                         DFScolorRecurrent (tab, color, next);
00920         }
00921         return;
00922 } /* diGraph::DFScolorRecurrent */
00923 
00924 template <class wType> template <class Table, class Color>
00925 inline void diGraph<wType>::DFScolorStack (Table &tab, const Color &color,
00926         int_t vertex) const
00927 {
00928         // prepare stacks for the recursion
00929         std::stack<int_t> s_vertex;
00930         std::stack<int_t> s_edge;
00931         std::stack<int_t> s_maxedge;
00932 
00933         // mark the current vertex as visited
00934         tab [vertex] = color;
00935 
00936         // determine the edges to be visited
00937         int_t edge = vertex ? edgeEnds [vertex - 1] :
00938                 static_cast<int_t> (0);
00939         int_t maxedge = edgeEnds [vertex];
00940 
00941         while (1)
00942         {
00943                 // return to the previous recursion level
00944                 // if all the edges have been followed
00945                 if (edge >= maxedge)
00946                 {
00947                         // return if this is the initial recursion level
00948                         if (s_vertex. empty ())
00949                                 return;
00950 
00951                         // restore the variables from the previous level
00952                         vertex = s_vertex. top ();
00953                         s_vertex. pop ();
00954                         edge = s_edge. top ();
00955                         s_edge. pop ();
00956                         maxedge = s_maxedge. top ();
00957                         s_maxedge. pop ();
00958                         continue;
00959                 }
00960 
00961                 // go to the deeper recursion level if possible
00962                 int_t next = edges [edge ++];
00963                 if (tab [next] != color)
00964                 {
00965                         // store the previous variables at the stacks
00966                         s_vertex. push (vertex);
00967                         s_edge. push (edge);
00968                         s_maxedge. push (maxedge);
00969 
00970                         // set the new vertex
00971                         vertex = next;
00972                         
00973                         // mark the new vertex as visited
00974                         tab [vertex] = color;
00975                         
00976                         // determine the edges to be visited
00977                         edge = vertex ? edgeEnds [vertex - 1] :
00978                                 static_cast<int_t> (0);
00979                         maxedge = edgeEnds [vertex];
00980                 }
00981         }
00982 } /* diGraph::DFScolorStack */
00983 
00984 template <class wType> template <class Table, class Color>
00985 inline void diGraph<wType>::DFScolor (Table &tab, const Color &color,
00986         int_t vertex) const
00987 {
00988         DFScolorStack (tab, color, vertex);
00989         return;
00990 } /* diGraph::DFScolor */
00991 
00992 // --------------------------------------------------
00993 
00994 template <class wType> template <class Table>
00995 inline void diGraph<wType>::DFSfinishTimeRecurrent (Table &tab,
00996         int_t vertex, int_t &counter) const
00997 {
00998         // mark the current vertex as visited
00999         tab [vertex] = -1;
01000 
01001         // call DFS for the other vertices
01002         for (int_t edge = vertex ? edgeEnds [vertex - 1] :
01003                 static_cast<int_t> (0);
01004                 edge < edgeEnds [vertex]; ++ edge)
01005         {
01006                 int_t next = edges [edge];
01007                 if (!tab [next])
01008                         DFSfinishTimeRecurrent (tab, next, counter);
01009         }
01010 
01011         // record the finishing time for the current vertex and return
01012         tab [vertex] = ++ counter;
01013         return;
01014 } /* diGraph::DFSfinishTimeRecurrent */
01015 
01016 template <class wType> template <class Table>
01017 inline void diGraph<wType>::DFSfinishTimeStack (Table &tab, int_t vertex,
01018         int_t &counter) const
01019 {
01020         // prepare stacks for the recursion
01021         std::stack<int_t> s_vertex;
01022         std::stack<int_t> s_edge;
01023         std::stack<int_t> s_maxedge;
01024 
01025         // mark the current vertex as visited
01026         tab [vertex] = -1;
01027 
01028         // determine the edges to be visited
01029         int_t edge = vertex ? edgeEnds [vertex - 1] :
01030                 static_cast<int_t> (0);
01031         int_t maxedge = edgeEnds [vertex];
01032 
01033         while (1)
01034         {
01035                 // return to the previous recursion level
01036                 // if all the edges have been followed
01037                 if (edge >= maxedge)
01038                 {
01039                         // record the finishing time
01040                         // for the current vertex
01041                         tab [vertex] = ++ counter;
01042 
01043                         // return if this is the initial recursion level
01044                         if (s_vertex. empty ())
01045                                 return;
01046 
01047                         // restore the variables from the previous level
01048                         vertex = s_vertex. top ();
01049                         s_vertex. pop ();
01050                         edge = s_edge. top ();
01051                         s_edge. pop ();
01052                         maxedge = s_maxedge. top ();
01053                         s_maxedge. pop ();
01054                         continue;
01055                 }
01056 
01057                 // go to the deeper recursion level if possible
01058                 int_t next = edges [edge ++];
01059                 if (!tab [next])
01060                 {
01061                         // store the previous variables at the stacks
01062                         s_vertex. push (vertex);
01063                         s_edge. push (edge);
01064                         s_maxedge. push (maxedge);
01065 
01066                         // set the new vertex
01067                         vertex = next;
01068                         
01069                         // mark the new vertex as visited
01070                         tab [vertex] = -1;
01071                         
01072                         // determine the edges to be visited
01073                         edge = vertex ? edgeEnds [vertex - 1] :
01074                                 static_cast<int_t> (0);
01075                         maxedge = edgeEnds [vertex];
01076                 }
01077         }
01078 
01079         return;
01080 } /* diGraph::DFSfinishTimeStack */
01081 
01082 template <class wType> template <class Table>
01083 inline void diGraph<wType>::DFSfinishTime (Table &tab) const
01084 {
01085         // initialize the table and the counter
01086         for (int_t i = 0; i < nVertices; ++ i)
01087                 tab [i] = 0;
01088         int_t counter = 0;
01089 
01090         // compute the finishing time for each tree in the DFS forest
01091         for (int_t i = 0; i < nVertices; ++ i)
01092         {
01093                 if (!tab [i])
01094                         DFSfinishTimeStack (tab, i, counter);
01095         }
01096 
01097         #ifdef DIGRAPH_DEBUG
01098         int_t *tabdebug = new int_t [nVertices];
01099         for (int_t i = 0; i < nVertices; ++ i)
01100                 tabdebug [i] = 0;
01101         int_t counterdebug = 0;
01102         for (int_t i = 0; i < nVertices; ++ i)
01103                 if (!tabdebug [i])
01104                         DFSfinishTimeRecurrent (tabdebug, i, counterdebug);
01105         if (counter != counterdebug)
01106                 throw "DFSfinishTime: Wrong counter.";
01107         for (int_t i = 0; i < nVertices; ++ i)
01108         {
01109                 if (tab [i] != tabdebug [i])
01110                 {
01111                         sbug << "\nDFSfinishTime error: tabRec [" << i <<
01112                                 "] = " << tab [i] << ", tabStack [" << i <<
01113                                 "] = " << tabdebug [i] << ".\n";
01114                         throw "DFSfinishTime: Wrong numbers.";
01115                 }
01116         }
01117         sbug << "DEBUG: DFSfinishTime OK. ";
01118         #endif // DIGRAPH_DEBUG
01119         return;
01120 } /* diGraph::DFSfinishTime */
01121 
01122 // --------------------------------------------------
01123 
01124 template <class wType> template <class Table1, class Table2>
01125 inline bool diGraph<wType>::DFSforestRecurrent (Table1 &tab, Table1 &ntab,
01126         int_t vertex, int_t treeNumber, int_t countTrees,
01127         Table2 &compVertices, int_t &curVertex,
01128         diGraph<wType> *sccGraph, int_t *sccEdgeAdded) const
01129 {
01130         // add the vertex to the tree
01131         compVertices [curVertex ++] = vertex;
01132 
01133         // mark the vertex as belonging to the current tree
01134         tab [vertex] = treeNumber;
01135 //      if (sccGraph)
01136 //              ntab [treeNumber - 1] = countTrees;
01137 
01138         // build the tree recursively or record connections
01139         bool loop = false;
01140         for (int_t edge = vertex ? edgeEnds [vertex - 1] :
01141                 static_cast<int_t> (0);
01142                 edge < edgeEnds [vertex]; ++ edge)
01143         {
01144                 int_t next = edges [edge];
01145                 if (!tab [next])
01146                         loop |= DFSforestRecurrent (tab, ntab, next,
01147                                 treeNumber, countTrees, compVertices,
01148                                 curVertex, sccGraph, sccEdgeAdded);
01149                 else if (tab [next] == treeNumber)
01150                 {
01151                         if (sccGraph)
01152                         {
01153                                 int_t target = ntab [treeNumber - 1];
01154                                 if (sccEdgeAdded [target] != treeNumber)
01155                                 {
01156                                         sccGraph -> addEdge (target);
01157                                         sccEdgeAdded [target] = treeNumber;
01158                                 }
01159                         }
01160                         loop = true;
01161                 }
01162                 else if (sccGraph)
01163                 {
01164                         int_t target = ntab [tab [next] - 1];
01165                         if ((target >= 0) &&
01166                                 (sccEdgeAdded [target] != treeNumber))
01167                         {
01168                                 sccGraph -> addEdge (target);
01169                                 sccEdgeAdded [target] = treeNumber;
01170                         }
01171                 }
01172         }
01173 
01174         return loop;
01175 } /* diGraph::DFSforestRecurrent */
01176 
01177 template <class wType> template <class Table1, class Table2>
01178 inline bool diGraph<wType>::DFSforestStack (Table1 &tab, Table1 &ntab,
01179         int_t vertex, int_t treeNumber, int_t countTrees,
01180         Table2 &compVertices, int_t &curVertex,
01181         diGraph<wType> *sccGraph, int_t *sccEdgeAdded) const
01182 {
01183         // prepare stacks for the recursion
01184         std::stack<int_t> s_vertex;
01185         std::stack<int_t> s_edge;
01186         std::stack<int_t> s_maxedge;
01187         std::stack<bool> s_loop;
01188 
01189         // add the vertex to the tree
01190         compVertices [curVertex ++] = vertex;
01191 
01192         // mark the vertex as belonging to the current tree
01193         tab [vertex] = treeNumber;
01194 //      if (sccGraph)
01195 //              ntab [vertex] = countTrees;
01196 
01197         // build the tree recursively or record connections
01198         bool loop = false;
01199         int_t edge = vertex ? edgeEnds [vertex - 1] :
01200                 static_cast<int_t> (0);
01201         int_t maxedge = edgeEnds [vertex];
01202         while (1)
01203         {
01204                 // return to the previous recursion level
01205                 // if all the edges have been followed
01206                 if (edge >= maxedge)
01207                 {
01208                         // return if this is the initial recursion level
01209                         if (s_vertex. empty ())
01210                                 return loop;
01211 
01212                         // restore the variables from the previous level
01213                         vertex = s_vertex. top ();
01214                         s_vertex. pop ();
01215                         edge = s_edge. top ();
01216                         s_edge. pop ();
01217                         maxedge = s_maxedge. top ();
01218                         s_maxedge. pop ();
01219                         loop |= s_loop. top ();
01220                         s_loop. pop ();
01221                         continue;
01222                 }
01223 
01224                 // go to the deeper recursion level if possible
01225                 int_t next = edges [edge ++];
01226                 if (!tab [next])
01227                 {
01228                         // store the previous variables at the stacks
01229                         s_vertex. push (vertex);
01230                         s_edge. push (edge);
01231                         s_maxedge. push (maxedge);
01232                         s_loop. push (loop);
01233 
01234                         // set the new vertex
01235                         vertex = next;
01236                         
01237                         // add the vertex to the tree
01238                         compVertices [curVertex ++] = vertex;
01239 
01240                         // mark the vertex as belonging to the current tree
01241                         tab [vertex] = treeNumber;
01242 
01243                         // determine the edges to be visited
01244                         loop = false;
01245                         edge = vertex ? edgeEnds [vertex - 1] :
01246                                 static_cast<int_t> (0);
01247                         maxedge = edgeEnds [vertex];
01248                 }
01249                 else if (tab [next] == treeNumber)
01250                 {
01251                         if (sccGraph)
01252                         {
01253                                 int_t target = ntab [treeNumber - 1];
01254                                 if (sccEdgeAdded [target] != treeNumber)
01255                                 {
01256                                         sccGraph -> addEdge (target);
01257                                         sccEdgeAdded [target] = treeNumber;
01258                                 }
01259                         }
01260                         loop = true;
01261                 }
01262                 else if (sccGraph)
01263                 {
01264                         int_t target = ntab [tab [next] - 1];
01265                         if ((target >= 0) &&
01266                                 (sccEdgeAdded [target] != treeNumber))
01267                         {
01268                                 sccGraph -> addEdge (target);
01269                                 sccEdgeAdded [target] = treeNumber;
01270                         }
01271                 }
01272         }
01273 
01274         return loop;
01275 } /* diGraph::DFSforestStack */
01276 
01277 template <class wType> template <class Table1, class Table2, class Table3>
01278 inline int_t diGraph<wType>::DFSforest (const Table1 &ordered,
01279         Table2 &compVertices, Table3 &compEnds, bool nontrivial,
01280         diGraph<wType> *sccGraph) const
01281 {
01282         // prepare a table to record the numbers of DFS trees
01283         // to which the vertices belong (the tree numbers begin with 1)
01284         int_t *tab = new int_t [nVertices];
01285         for (int_t i = 0; i < nVertices; ++ i)
01286                 tab [i] = 0;
01287 
01288         // prepare a table to record the numbers of nontrivial trees
01289         // that correspond to the trees in 'tab' (these numbers begin with 0)
01290         int_t *ntab = new int_t [nVertices];
01291 
01292         // prepare a table to record the numbers of edges already in the
01293         // scc graph; "sccEdgeAdded [n] = m" indicates that the edge
01294         // m -> n has been added to the scc graph
01295         int_t *sccEdgeAdded = sccGraph ? new int_t [nVertices] :
01296                 static_cast<int_t *> (0);
01297         if (sccGraph)
01298         {
01299                 for (int_t n = 0; n < nVertices; ++ n)
01300                         sccEdgeAdded [n] = -1;
01301         }
01302 
01303         // prepare the official DFS tree number
01304         int_t treeNumber = 0;
01305 
01306         // prepare the data for keeping the nontrivial trees information
01307         int_t countTrees = 0;
01308         int_t curVertex = 0;
01309 
01310         // compute the DFS trees and connections between them
01311         for (int_t i = 0; i < nVertices; ++ i)
01312         {
01313                 // take the next vertex
01314                 int_t vertex = ordered [i];
01315 
01316                 // if the vertex already belongs to some tree, skip it
01317                 if (tab [vertex])
01318                         continue;
01319 
01320                 // add a vertex corresponding to the component
01321                 if (sccGraph)
01322                         sccGraph -> addVertex ();
01323 
01324                 // remember the previous vertex number
01325                 int_t prevVertex = curVertex;
01326 
01327                 // mark the entire component and record connections graph
01328                 if (sccGraph)
01329                         ntab [treeNumber] = countTrees;
01330                 ++ treeNumber;
01331                 bool loop = DFSforestStack (tab, ntab, vertex,
01332                         treeNumber, countTrees, compVertices,
01333                         curVertex, sccGraph, sccEdgeAdded);
01334 
01335                 // update the index bound for the vertex list
01336                 compEnds [countTrees ++] = curVertex;
01337 
01338                 // remove the component if it is trivial
01339                 if (nontrivial && !loop)
01340                 {
01341                         -- countTrees;
01342                         curVertex = prevVertex;
01343                         if (sccGraph)
01344                         {
01345                                 ntab [treeNumber - 1] = -1;
01346                                 sccGraph -> removeVertex ();
01347                         }
01348                 }
01349         }
01350 
01351         #ifdef DIGRAPH_DEBUG
01352         diGraph<wType> *sccGraphdebug = 0;
01353         if (sccGraph)
01354                 sccGraphdebug = new diGraph<wType>;
01355         // prepare a table to record the numbers of DFS trees
01356         // to which the vertices belong (the tree numbers begin with 1)
01357         int_t *tabdebug = new int_t [nVertices];
01358         for (int_t i = 0; i < nVertices; ++ i)
01359                 tabdebug [i] = 0;
01360 
01361         // prepare a table to record the numbers of nontrivial trees
01362         // to which the vertices belong (the tree numbers begin with 0)
01363         int_t *ntabdebug = new int_t [nVertices];
01364 
01365         // prepare a table to record the numbers of vertices from which
01366         // edges were added to the scc graph
01367         int_t *sccEdgeAddeddebug = sccGraph ? new int_t [nVertices] :
01368                 static_cast<int_t> (0);
01369         if (sccGraph)
01370         {
01371                 for (int_t n = 0; n < nVertices; ++ n)
01372                         sccEdgeAddeddebug [n] = -1;
01373         }
01374         // prepare the official DFS tree number
01375         int_t treeNumberdebug = 0;
01376 
01377         // prepare the data for keeping the nontrivial trees information
01378         int_t countTreesdebug = 0;
01379         int_t curVertexdebug = 0;
01380 
01381         int_t *compVerticesdebug = new int_t [nVertices];
01382         int_t *compEndsdebug = new int_t [nVertices];
01383         
01384         // compute the DFS trees and connections between them
01385         for (int_t i = 0; i < nVertices; ++ i)
01386         {
01387                 // take the next vertex
01388                 int_t vertex = ordered [i];
01389 
01390                 // if the vertex already belongs to some tree, skip it
01391                 if (tabdebug [vertex])
01392                         continue;
01393 
01394                 // add a vertex corresponding to the component
01395                 if (sccGraphdebug)
01396                         sccGraphdebug -> addVertex ();
01397 
01398                 // remember the previous vertex number
01399                 int_t prevVertex = curVertexdebug;
01400 
01401                 // mark the entire component and record connections graph
01402                 if (sccGraphdebug)
01403                         ntabdebug [treeNumberdebug] = countTreesdebug;
01404                 ++ treeNumberdebug;
01405                 bool loop = DFSforestRecurrent (tabdebug, ntabdebug, vertex,
01406                         treeNumberdebug, countTreesdebug, compVerticesdebug,
01407                         curVertexdebug, sccGraphdebug, sccEdgeAddeddebug);
01408 
01409                 // update the index bound for the vertex list
01410                 compEndsdebug [countTreesdebug ++] = curVertexdebug;
01411 
01412                 // remove the component if it is trivial
01413                 if (nontrivial && !loop)
01414                 {
01415                         -- countTreesdebug;
01416                         curVertexdebug = prevVertex;
01417                         if (sccGraphdebug)
01418                         {
01419                                 ntabdebug [treeNumberdebug - 1] = -1;
01420                                 sccGraphdebug -> removeVertex ();
01421                         }
01422                 }
01423         }
01424         if (countTrees != countTreesdebug)
01425                 throw "DFSforest: Wrong countTrees.";
01426         for (int_t i = 0; i < countTrees; ++ i)
01427                 if (compEnds [i] != compEndsdebug [i])
01428                         throw "DFSforest: Wrong compEnds.";
01429         for (int_t i = 0; i < compEndsdebug [countTrees - 1]; ++ i)
01430                 if (compVertices [i] != compVerticesdebug [i])
01431                         throw "DFSforest: Wrong vertices.";
01432         if (curVertex != curVertexdebug)
01433                 throw "DFSforest: Wrong curVertex.";
01434         for (int_t i = 0; i < nVertices; ++ i)
01435                 if (tab [i] != tabdebug [i])
01436                         throw "DFSforest: Wrong tab.";
01437         if (sccGraph)
01438         {
01439                 for (int_t i = 0; i < nVertices; ++ i)
01440                         if (ntab [i] != ntabdebug [i])
01441                                 throw "DFSforest: Wrong ntab.";
01442                 if (*sccGraph != *sccGraphdebug)
01443                         throw "DFSforest: Wrong graph.";
01444         }
01445         if (sccEdgeAdded)
01446         {
01447                 for (int_t i = 0; i < nVertices; ++ i)
01448                         if (sccEdgeAdded [i] != sccEdgeAddeddebug [i])
01449                                 throw "DFSforest: Wrong sccEdgeAdded.";
01450         }
01451         if (treeNumber != treeNumberdebug)
01452                 throw "DFSforest: Wrong treeNumber.";
01453         sbug << "DEBUG: DFSforest OK. ";
01454         if (!sccGraph)
01455                 sbug << "(Graphs not compared.) ";
01456         delete [] compVerticesdebug;
01457         delete [] compEndsdebug;
01458         if (sccGraphdebug)
01459                 delete sccGraphdebug;
01460         delete [] ntabdebug;
01461         delete [] tabdebug;
01462         if (sccEdgeAddeddebug)
01463                 delete [] sccEdgeAddeddebug;
01464         #endif // DIGRAPH_DEBUG
01465 
01466         if (sccEdgeAdded)
01467                 delete [] sccEdgeAdded;
01468         delete [] ntab;
01469         delete [] tab;
01470         return countTrees;
01471 } /* diGraph::DFSforest */
01472 
01473 template <class wType>
01474 inline int_t diGraph<wType>::shortestPath (int_t source, int_t destination)
01475         const
01476 {
01477         // make sure that the given vertex is present in the graph
01478         if ((source < 0) || (source >= nVertices) ||
01479                 (destination < 0) || (destination >= nVertices))
01480         {
01481                 throw "diGraph - shortest path: Wrong vertex number.";
01482         }
01483 
01484         // prepare an array of bits to store the information
01485         // on whether the given vertices have been visited or not
01486         BitField visited;
01487         visited. allocate (nVertices);
01488         visited. clearall (nVertices);
01489 
01490         // prepare queues for the BFS algorithm
01491         std::queue<int_t> q_vertex;
01492         std::queue<int_t> q_depth;
01493 
01494         // set the initial vertex
01495         int_t vertex = source;
01496         int_t depth = 0;
01497 
01498         while (1)
01499         {
01500                 // mark the current vertex as visited
01501                 visited. set (vertex);
01502 
01503                 // determine the depth of the vertices that will be analyzed
01504                 ++ depth;
01505 
01506                 // determine the edges to be checked
01507                 int_t firstedge = vertex ? edgeEnds [vertex - 1] :
01508                         static_cast<int_t> (0);
01509                 int_t maxedge = edgeEnds [vertex];
01510 
01511                 // put all the unvisited destination vertices on the stack
01512                 for (int_t edge = firstedge; edge < maxedge; ++ edge)
01513                 {
01514                         // determine the vertex pointed to by this edge
01515                         int_t next = edges [edge];
01516 
01517                         // if this is the destination vertex then return
01518                         // the shortest path length; note: this vertex
01519                         // might be visited if checking a loop, so it is
01520                         // important to check the destination first
01521                         if (next == destination)
01522                         {
01523                                 visited. free ();
01524                                 return depth;
01525                         }
01526 
01527                         // if the vertex was already visited then skip it
01528                         if (visited. test (next))
01529                                 continue;
01530 
01531                         // add the vertex to the queue
01532                         q_vertex. push (next);
01533                         q_depth. push (depth);
01534                 }
01535 
01536                 // if there are no vertices whose neighbors are to be
01537                 // analyzed and the destination vertex was not found
01538                 // then there is no path to that vertex
01539                 if (q_vertex. empty ())
01540                 {
01541                         visited. free ();
01542                         return 0;
01543                 }
01544 
01545                 // pick up a vertex stored in the queue
01546                 vertex = q_vertex. front ();
01547                 q_vertex. pop ();
01548                 depth = q_depth. front ();
01549                 q_depth. pop ();
01550         }
01551 } /* diGraph::shortestPath */
01552 
01553 template <class wType>
01554 inline int_t diGraph<wType>::shortestLoop (int_t origin) const
01555 {
01556         return shortestPath (origin, origin);
01557 } /* diGraph::shortestLoop */
01558 
01559 template <class wType>
01560 template <class lenTable, class weightsType, class roundType>
01561 inline void diGraph<wType>::Dijkstra (const roundType &rounding,
01562         int_t source, lenTable &len, weightsType &edgeWeights) const
01563 {
01564         // use the Fibonacci heap as a priority queue
01565         FibonacciHeap<posWeight> Q (nVertices);
01566 
01567         // add the vertices to the heap with the initial shortest path
01568         // lengths: 0 to the source, plus infinity to all the others
01569         for (int_t v = 0; v < nVertices; ++ v)
01570         {
01571                 posWeight w (0);
01572                 if (v != source)
01573                         w. setInfinity ();
01574                 int_t number = Q. Insert (w);
01575                 if (number != v)
01576                 {
01577                         throw "Wrong implementation of Fibonacci heap "
01578                                 "for this version of Dijkstra.";
01579                 }
01580         }
01581 
01582         // pick up vertices from the priority queue, record the length
01583         // of the shortest path to them, and modify the remaining paths
01584         for (int_t i = 0; i < nVertices; ++ i)
01585         {
01586                 // extract the minimal vertex from the queue
01587                 int_t minVertex = Q. Minimum ();
01588                 posWeight minWeight = Q. ExtractMinimum ();
01589 
01590                 if (minWeight. isInfinity ())
01591                 {
01592                         len [minVertex] = -1;
01593                         continue;
01594                 }
01595                 wType minValue = minWeight. getValue ();
01596                 len [minVertex] = minValue;
01597 
01598                 // go through all the edges emanating from this vertex
01599                 // and update the path lengths for the target vertices
01600                 int_t edge = minVertex ? edgeEnds [minVertex - 1] :
01601                         static_cast<int_t> (0);
01602                 int_t maxEdge = edgeEnds [minVertex];
01603                 for (; edge < maxEdge; ++ edge)
01604                 {
01605                         // determine the vertex at the other end of the edge
01606                         int_t nextVertex = edges [edge];
01607 
01608                         // if the path that runs through the extracted
01609                         // vertex is shorter, then make a correction
01610                         const posWeight &nextWeight = Q. Value (nextVertex);
01611                         wType newWeight = rounding. add_down (minValue,
01612                                 edgeWeights [edge]);
01613                         if (newWeight < 0)
01614                                 newWeight = 0;
01615                         if (nextWeight. isInfinity () ||
01616                                 (newWeight < nextWeight. getValue ()))
01617                         {
01618                                 Q. DecreaseKey (nextVertex,
01619                                         posWeight (newWeight));
01620                         }
01621                 }
01622         }
01623         return;
01624 } /* diGraph::Dijkstra */
01625 
01626 template <class wType>
01627 template <class lenTable, class roundType>
01628 inline void diGraph<wType>::Dijkstra (const roundType &rounding,
01629         int_t source, lenTable &len) const
01630 {
01631         this -> Dijkstra (rounding, source, len, this -> weights);
01632         return;
01633 } /* diGraph::Dijkstra */
01634 
01635 template <class wType>
01636 template <class lenTable>
01637 inline void diGraph<wType>::Dijkstra (int_t source, lenTable &len) const
01638 {
01639         const dummyRounding<wType> rounding = dummyRounding<wType> ();
01640         this -> Dijkstra (rounding, source, len);
01641         return;
01642 } /* diGraph::Dijkstra */
01643 
01644 template <class wType> template <class lenTable, class predTable,
01645         class roundType>
01646 inline bool diGraph<wType>::BellmanFord (const roundType &rounding,
01647         int_t source, lenTable &len, wType *infinity, predTable pred) const
01648 {
01649         // make sure the source vertex number is correct
01650         if ((source < 0) || (source >= nVertices))
01651                 throw "Bellman-Ford: Wrong source vertex number.";
01652 
01653         // prepare marks to indicate finite values (not "infinity")
01654         BitField finite;
01655         finite. allocate (nVertices);
01656         finite. clearall (nVertices);
01657         finite. set (source);
01658         len [source] = 0;
01659 
01660         // count the negative vertices
01661         int_t countNegative = 0;
01662 
01663         // set the initial predecessors
01664         for (int_t i = 0; i < nVertices; ++ i)
01665                 pred [i] = -1;
01666 
01667         // update the lenghts of the paths repeatedly (max nVertices times)
01668         bool noNegativeLoop = false;
01669         int_t counter = 0;
01670         for (; counter <= nVertices; ++ counter)
01671         {
01672                 bool modified = false;
01673                 int_t curEdge = 0;
01674                 for (int_t vertex = 0; vertex < nVertices; ++ vertex)
01675                 {
01676                         int_t maxEdge = edgeEnds [vertex];
01677                         if (!finite. test (vertex))
01678                         {
01679                                 curEdge = maxEdge;
01680                                 continue;
01681                         }
01682                         for (; curEdge < maxEdge; ++ curEdge)
01683                         {
01684                                 int_t next = edges [curEdge];
01685                                 wType newlen = rounding. add_down
01686                                         (len [vertex], weights [curEdge]);
01687                                 if (!finite. test (next))
01688                                 {
01689                                         finite. set (next);
01690                                         modified = true;
01691                                         len [next] = newlen;
01692                                         pred [next] = vertex;
01693                                         if (newlen < 0)
01694                                                 ++ countNegative;
01695                                 }
01696                                 else if (newlen < len [next])
01697                                 {
01698                                         modified = true;
01699                                         if (!(len [next] < 0) &&
01700                                                 (newlen < 0))
01701                                         {
01702                                                 ++ countNegative;
01703                                         }
01704                                         len [next] = newlen;
01705                                         pred [next] = vertex;
01706                                 }
01707                         }
01708                 }
01709                 if (countNegative == nVertices)
01710                 {
01711                         noNegativeLoop = false;
01712                         ++ counter;
01713                         break;
01714                 }
01715                 if (!modified)
01716                 {
01717                         noNegativeLoop = true;
01718                         ++ counter;
01719                         break;
01720                 }
01721         }
01722 
01723         // show a message on how many loops have been done
01724         if (false && chomp::homology::sbug. show)
01725         {
01726                 chomp::homology::sbug << "Bellman-Ford: " <<
01727                         counter << ((counter > 1) ? " loops (" : " loop (") <<
01728                         nVertices << " vertices, " << countNegative <<
01729                         " negative). " <<
01730                         (noNegativeLoop ? "No negative loops.\n" :
01731                         "A negative loop found.\n");
01732         }
01733 
01734         // compute the value for the infinity and set the undefined distances
01735         if (infinity && noNegativeLoop)
01736         {
01737                 wType infty (0);
01738                 bool first = true;
01739                 for (int_t i = 0; i < nVertices; ++ i)
01740                 {
01741                         if (!finite. test (i))
01742                                 continue;
01743                         if (first)
01744                         {
01745                                 infty = len [i];
01746                                 first = false;
01747                         }
01748                         else if (infty < len [i])
01749                         {
01750                                 infty = len [i];
01751                         }
01752                 }
01753                 infty = infty + 1;
01754                 for (int_t i = 0; i < nVertices; ++ i)
01755                 {
01756                         if (!finite. test (i))
01757                                 len [i] = infty;
01758                 }
01759                 *infinity = infty;
01760         }
01761 
01762         finite. free ();
01763         return noNegativeLoop;
01764 } /* diGraph::BellmanFord */
01765 
01766 template <class wType> template <class lenTable, class predTable>
01767 inline bool diGraph<wType>::BellmanFord (int_t source, lenTable &len,
01768         wType *infinity, predTable pred) const
01769 {
01770         const dummyRounding<wType> rounding = dummyRounding<wType> ();
01771         return this -> BellmanFord (rounding, source, len, infinity, pred);
01772 } /* diGraph::BellmanFord */
01773 
01774 template <class wType> template <class roundType>
01775 inline bool diGraph<wType>::BellmanFord (const roundType &rounding,
01776         int_t source) const
01777 {
01778         std::auto_ptr<wType> len_ptr (new wType [nVertices]);
01779         wType *len = len_ptr. get ();
01780         wType *infinity = 0;
01781         dummyArray tab;
01782         return BellmanFord (rounding, source, len, infinity, tab);
01783 } /* diGraph::BellmanFord */
01784 
01785 template <class wType>
01786 inline bool diGraph<wType>::BellmanFord (int_t source) const
01787 {
01788         const dummyRounding<wType> rounding = dummyRounding<wType> ();
01789         return BellmanFord (rounding, source);
01790 } /* diGraph::BellmanFord */
01791 
01792 template <class wType>
01793 inline wType diGraph<wType>::Edmonds () const
01794 {
01795         // create a list of edges with weights and sort this list
01796         std::vector<edgeTriple> edgeTriples (countEdges ());
01797         int_t prevEdge = 0;
01798         int_t curEdge = 0;
01799         for (int_t vert = 0; vert < nVertices; ++ vert)
01800         {
01801                 while (curEdge < edgeEnds [vert])
01802                 {
01803                         edgeTriple &e = edgeTriples [curEdge];
01804                         e. vert1 = vert;
01805                         e. vert2 = edges [curEdge];
01806                         e. weight = weights [curEdge];
01807                         ++ curEdge;
01808                 }
01809                 prevEdge = curEdge;
01810         }
01811         std::sort (edgeTriples. begin (), edgeTriples. end ());
01812 
01813         // create a forest which initially contains single vertices
01814         std::auto_ptr<int_t> root_ptr (new int_t [nVertices]);
01815         int_t *root = root_ptr. get ();
01816         for (int_t vert = 0; vert < nVertices; ++ vert)
01817         {
01818                 root [vert] = -1;
01819         }
01820 
01821         // go through the edges and join the trees, but avoid loops
01822         wType totalWeight = 0;
01823         int_t nEdges = countEdges ();
01824         for (int_t curEdge = 0; curEdge < nEdges; ++ curEdge)
01825         {
01826                 // determine the roots of both vertices of the edge
01827                 // and compress the paths
01828                 edgeTriple &e = edgeTriples [curEdge];
01829                 int_t root1 = e. vert1;
01830                 while (root [root1] >= 0)
01831                 {
01832                         root1 = root [root1];
01833                 }
01834                 int_t vert1 = e. vert1;
01835                 while (root [vert1] >= 0)
01836                 {
01837                         int_t next = root [vert1];
01838                         root [vert1] = root1;
01839                         vert1 = next;
01840                 }
01841                 int_t root2 = e. vert2;
01842                 while (root [root2] >= 0)
01843                 {
01844                         root2 = root [root2];
01845                 }
01846                 int_t vert2 = e. vert2;
01847                 while (root [vert2] >= 0)
01848                 {
01849                         int_t next = root [vert2];
01850                         root [vert2] = root2;
01851                         vert2 = next;
01852                 }
01853 
01854                 // skip the edge if it closes a loop
01855                 if (root1 == root2)
01856                         continue;
01857 
01858                 // add the weight
01859                 totalWeight += e. weight;
01860 
01861                 // join the trees
01862                 root [root1] = root2;
01863         }
01864         return totalWeight;
01865 } /* diGraph::Edmonds */
01866 
01867 template <class wType>
01868 inline wType diGraph<wType>::EdmondsOld () const
01869 {
01870         // create a list of edges with weights and sort this list
01871         std::vector<edgeTriple> edgeTriples (countEdges ());
01872         int_t prevEdge = 0;
01873         int_t curEdge = 0;
01874         for (int_t vert = 0; vert < nVertices; ++ vert)
01875         {
01876                 while (curEdge < edgeEnds [vert])
01877                 {
01878                         edgeTriple &e = edgeTriples [curEdge];
01879                         e. vert1 = vert;
01880                         e. vert2 = edges [curEdge];
01881                         e. weight = weights [curEdge];
01882                         ++ curEdge;
01883                 }
01884                 prevEdge = curEdge;
01885         }
01886         std::sort (edgeTriples. begin (), edgeTriples. end ());
01887 
01888         // create a forest which initially contains single vertices
01889         std::auto_ptr<int_t> forest_ptr (new int_t [nVertices]);
01890         int_t *forest = forest_ptr. get ();
01891         std::auto_ptr<int_t> next_ptr (new int_t [nVertices]);
01892         int_t *next = next_ptr. get ();
01893         std::auto_ptr<int_t> prev_ptr (new int_t [nVertices]);
01894         int_t *prev = prev_ptr. get ();
01895         for (int_t vert = 0; vert < nVertices; ++ vert)
01896         {
01897                 forest [vert] = vert;
01898                 next [vert] = -1;
01899                 prev [vert] = -1;
01900         }
01901 
01902         // go through the edges and join the trees, but avoid loops
01903         wType totalWeight = 0;
01904         int_t nEdges = countEdges ();
01905         for (int_t curEdge = 0; curEdge < nEdges; ++ curEdge)
01906         {
01907                 // check the edge and skip it if it closes a loop
01908                 edgeTriple &e = edgeTriples [curEdge];
01909                 if (forest [e. vert1] == forest [e. vert2])
01910                         continue;
01911 
01912                 // add the weight
01913                 totalWeight += e. weight;
01914 
01915                 // go to the end of the first tree
01916                 int_t vert1 = e. vert1;
01917                 while (next [vert1] >= 0)
01918                 {
01919                         vert1 = next [vert1];
01920                 }
01921                 
01922                 // go to the beginning of the second tree
01923                 int_t vert2 = e. vert2;
01924                 while (prev [vert2] >= 0)
01925                 {
01926                         vert2 = prev [vert2];
01927                 }
01928 
01929                 // join the trees and modify the numbers
01930                 next [vert1] = vert2;
01931                 prev [vert2] = vert1;
01932                 int_t treeNumber = forest [vert1];
01933                 while (vert2 >= 0)
01934                 {
01935                         forest [vert2] = treeNumber;
01936                         vert2 = next [vert2];
01937                 }
01938         }
01939         return totalWeight;
01940 } /* diGraph::EdmondsOld */
01941 
01942 template <class wType>
01943 template <class arrayType, class roundType>
01944 inline wType diGraph<wType>::FloydWarshall (const roundType &rounding,
01945         arrayType &arr, bool setInfinity, bool ignoreNegLoop) const
01946 {
01947         // do nothing if the graph is empty
01948         if (!nVertices)
01949                 return 0;
01950 
01951         // prepare marks to indicate finite values (not "infinity")
01952         BitField *finite = new BitField [nVertices];
01953         for (int_t i = 0; i < nVertices; ++ i)
01954         {
01955                 finite [i]. allocate (nVertices);
01956                 finite [i]. clearall (nVertices);
01957         }
01958 
01959         // create the initial values of the array based on the edge weights
01960         int_t curEdge = 0;
01961         for (int_t source = 0; source < nVertices; ++ source)
01962         {
01963                 bool diagset = false;
01964                 while (curEdge < edgeEnds [source])
01965                 {
01966                         int_t target = edges [curEdge];
01967                         const wType &weight = weights [curEdge];
01968                         if (source == target)
01969                         {
01970                                 if (weight < 0)
01971                                 {
01972                                         arr [source] [target] = weight;
01973                                         diagset = true;
01974                                 }
01975                         }
01976                         else
01977                         {
01978                                 arr [source] [target] = weight;
01979                                 finite [source]. set (target);
01980                         }
01981                         ++ curEdge;
01982                 }
01983                 if (!diagset)
01984                         arr [source] [source] = 0;
01985                 finite [source]. set (source);
01986         }
01987 
01988         // find the shortest paths between the vertices (dynamic programming)
01989         for (int_t k = 0; k < nVertices; ++ k)
01990         {
01991                 for (int_t i = 0; i < nVertices; ++ i)
01992                 {
01993                         if (!finite [i]. test (k))
01994                                 continue;
01995                         for (int_t j = 0; j < nVertices; ++ j)
01996                         {
01997                                 if (!finite [k]. test (j))
01998                                         continue;
01999                                 const wType sum = rounding. add_down
02000                                         (arr [i] [k], arr [k] [j]);
02001                                 if (finite [i]. test (j))
02002                                 {
02003                                         if (sum < arr [i] [j])
02004                                                 arr [i] [j] = sum;
02005                                 }
02006                                 else
02007                                 {
02008                                         arr [i] [j] = sum;
02009                                         finite [i]. set (j);
02010                                 }
02011                         }
02012                 }
02013         }
02014 
02015         // verify if a negative loop exists by checking for a negative
02016         // result in the diagonal
02017         if (!ignoreNegLoop)
02018         {
02019                 for (int_t i = 0; i < nVertices; ++ i)
02020                 {
02021                         if (arr [i] [i] < 0)
02022                                 throw "Negative loop in Floyd-Warshall.";
02023                 }
02024         }
02025 
02026         // prepare a variable to store the returned result
02027         wType result = 0;
02028 
02029         // compute the value for the infinity and fill in the array
02030         // if requested to do so
02031         if (setInfinity)
02032         {
02033                 wType &infinity = result;
02034                 for (int_t i = 0; i < nVertices; ++ i)
02035                 {
02036                         for (int_t j = 0; j < nVertices; ++ j)
02037                         {
02038                                 if (finite [i]. test (j) &&
02039                                         (infinity <= arr [i] [j]))
02040                                 {
02041                                         infinity = rounding. add_up
02042                                                 (arr [i] [j], 1);
02043                                 }
02044                         }
02045                 }
02046                 for (int_t i = 0; i < nVertices; ++ i)
02047                 {
02048                         for (int_t j = 0; j < nVertices; ++ j)
02049                         {
02050                                 if (!finite [i]. test (j))
02051                                         arr [i] [j] = infinity;
02052                         }
02053                 }
02054         }
02055 
02056         // otherwise, only compute the minimum path weight
02057         else
02058         {
02059                 wType &minWeight = result;
02060                 bool firstTime = true;
02061                 for (int_t i = 0; i < nVertices; ++ i)
02062                 {
02063                         for (int_t j = 0; j < nVertices; ++ j)
02064                         {
02065                                 if (finite [i]. test (j))
02066                                 {
02067                                         if (firstTime)
02068                                         {
02069                                                 minWeight = arr [i] [j];
02070                                                 firstTime = false;
02071                                         }
02072                                         else if (arr [i] [j] < minWeight)
02073                                         {
02074                                                 minWeight = arr [i] [j];
02075                                         }
02076                                 }
02077                         }
02078                 }
02079         }
02080 
02081         // release the 'finite' bitfields
02082         for (int_t i = 0; i < nVertices; ++ i)
02083                 finite [i]. free ();
02084         delete [] finite;
02085 
02086         return result;
02087 } /* diGraph::FloydWarshall */
02088 
02089 template <class wType>
02090 template <class arrayType>
02091 inline wType diGraph<wType>::FloydWarshall (arrayType &arr,
02092         bool setInfinity, bool ignoreNegLoop) const
02093 {
02094         const dummyRounding<wType> rounding = dummyRounding<wType> ();
02095         return FloydWarshall (rounding, arr, setInfinity, ignoreNegLoop);
02096 } /* diGraph::FloydWarshall */
02097 
02098 template <class wType>
02099 template <class arrayType, class roundType>
02100 inline wType diGraph<wType>::Johnson (const roundType &rounding,
02101         arrayType &arr, bool setInfinity, bool ignoreNegLoop) const
02102 {
02103         // DEBUG VERIFICATION
02104         if (false && sbug. show)
02105         {
02106                 timeused stopWatch;
02107                 wType res = FloydWarshall (rounding,
02108                         arr, setInfinity, ignoreNegLoop);
02109                 chomp::homology::sbug << "\n[Floyd-Warshall: " << res <<
02110                         ", " << (double) stopWatch << " sec]\n";
02111         }
02112         // debug time measurement (see below)
02113 //      timeused stopWatch;
02114 
02115         // do nothing if the graph is empty
02116         if (!nVertices)
02117                 return 0;
02118 
02119         // STEP 1: Compute the shortest paths to any vertex from an
02120         // artificial extra vertex connected to every other vertex in the
02121         // graph by an edge of weight zero. Use Bellman-Ford for this.
02122         wType *len = new wType [nVertices];
02123         for (int_t i = 0; i < nVertices; ++ i)
02124                 len [i] = 0;
02125 
02126         // update the lenghts of the paths repeatedly (max nVertices times)
02127         bool noNegativeLoop = false;
02128         int_t counter = 0;
02129         for (; counter <= nVertices; ++ counter)
02130         {
02131                 bool modified = false;
02132                 int_t curEdge = 0;
02133                 for (int_t vertex = 0; vertex < nVertices; ++ vertex)
02134                 {
02135                         int_t maxEdge = edgeEnds [vertex];
02136                         for (; curEdge < maxEdge; ++ curEdge)
02137                         {
02138                                 int_t next = edges [curEdge];
02139                                 wType newlen = rounding. add_down
02140                                         (len [vertex], weights [curEdge]);
02141                                 if (newlen < len [next])
02142                                 {
02143                                         // this "if" statement is necessary
02144                                         // because of a bug in GCC 3.4.2...
02145                                         if (counter > nVertices)
02146                                         {
02147                                                 std::cout << vertex;
02148                                         }
02149                                         modified = true;
02150                                         len [next] = newlen;
02151                                 }
02152                         }
02153                 }
02154                 if (!modified)
02155                 {
02156                         noNegativeLoop = true;
02157                         ++ counter;
02158                         break;
02159                 }
02160         }
02161         if (!ignoreNegLoop && !noNegativeLoop)
02162                 throw "Negative loop found in Johnson's algorithm.";
02163 
02164         // STEP 2: Re-weigh the edges using the computed path lengths.
02165         wType *newWeights = new wType [edgeEnds [nVertices - 1]];
02166         int_t edge = 0;
02167         for (int_t vertex = 0; vertex < nVertices; ++ vertex)
02168         {
02169                 int_t maxEdge = edgeEnds [vertex];
02170                 for (; edge < maxEdge; ++ edge)
02171                 {
02172                         wType w = weights [edge];
02173                         w = rounding. add_down (w, len [vertex]);
02174                         w = rounding. sub_down (w, len [edges [edge]]);
02175                         newWeights [edge] = (w < 0) ?
02176                                 static_cast<wType> (0) : w;
02177                 }
02178         }
02179 
02180         // STEP 3: Run the Dijkstra algorithm for every vertex to compute
02181         // the shortest paths to all the other vertices.
02182         // Negative entries indicate no path existence.
02183         for (int_t u = 0; u < nVertices; ++ u)
02184         {
02185                 this -> Dijkstra (rounding, u, arr [u], newWeights);
02186         }
02187         delete [] newWeights;
02188 
02189         // STEP 4: Make a correction to the computed path lengths.
02190         // Compute the value for infinity if requested to.
02191         // Otherwise compute the minimum of path lengths.
02192         wType result = 0;
02193         if (setInfinity)
02194         {
02195                 wType &infinity = result;
02196                 for (int_t u = 0; u < nVertices; ++ u)
02197                 {
02198                         for (int_t v = 0; v < nVertices; ++ v)
02199                         {
02200                                 wType w = arr [u] [v];
02201                                 if (w < 0)
02202                                         continue;
02203                                 w = rounding. add_down (w, len [v]);
02204                                 w = rounding. sub_down (w, len [u]);
02205                                 if (w < infinity)
02206                                         continue;
02207                                 infinity = rounding. add_up (w, 1);
02208                         }
02209                 }
02210                 for (int_t u = 0; u < nVertices; ++ u)
02211                 {
02212                         for (int_t v = 0; v < nVertices; ++ v)
02213                         {
02214                                 wType w = arr [u] [v];
02215                                 if (w < 0)
02216                                 {
02217                                         arr [u] [v] = infinity;
02218                                         continue;
02219                                 }
02220                                 w = rounding. add_down (w, len [v]);
02221                                 arr [u] [v] =
02222                                         rounding. sub_down (w, len [u]);
02223                         }
02224                 }
02225         }
02226         else
02227         {
02228                 wType &minWeight = result;
02229                 bool firstTime = true;
02230                 for (int_t u = 0; u < nVertices; ++ u)
02231                 {
02232                         for (int_t v = 0; v < nVertices; ++ v)
02233                         {
02234                                 wType w = arr [u] [v];
02235                                 if (w < 0)
02236                                         continue;
02237                                 w = rounding. add_down (w, len [v]);
02238                                 w = rounding. sub_down (w, len [u]);
02239                                 if (firstTime)
02240                                 {
02241                                         minWeight = w;
02242                                         firstTime = false;
02243                                 }
02244                                 else if (w < minWeight)
02245                                         minWeight = w;
02246                         }
02247                 }
02248         }
02249         delete [] len;
02250 
02251         // DEBUG VERIFICATION
02252         if (false && sbug. show)
02253         {
02254 //              chomp::homology::sbug << "[Johnson: " << result <<
02255 //                      ", " << (double) stopWatch << " sec]\n";
02256         }
02257 
02258         return result;
02259 } /* diGraph::Johnson */
02260 
02261 template <class wType>
02262 template <class arrayType>
02263 inline wType diGraph<wType>::Johnson (arrayType &arr,
02264         bool setInfinity, bool ignoreNegLoop) const
02265 {
02266         const dummyRounding<wType> rounding = dummyRounding<wType> ();
02267         return Johnson (rounding, arr, setInfinity, ignoreNegLoop);
02268 } /* diGraph::Johnson */
02269 
02270 template <class wType>
02271 template <class roundType>
02272 wType diGraph<wType>::minPathWeight (const roundType &rounding,
02273         bool ignoreNegLoop, int sparseGraph) const
02274 {
02275         // if the graph is empty, return 0 as the minimum path weight
02276         if (nVertices <= 0)
02277                 return 0;
02278 
02279         // allocate memory for an array of arrays to store min path weights
02280         wType **arr = new wType * [nVertices];
02281         for (int_t i = 0; i < nVertices; ++ i)
02282                 arr [i] = new wType [nVertices];
02283 
02284         // determine whether to run the Floyd-Warshall algorithm
02285         // or Johnson's algorithm
02286         bool sparse = false;
02287         if (sparseGraph == 1)
02288                 sparse = true;
02289         else if (sparseGraph != 0)
02290         {
02291                 double nEdgesD = this -> countEdges ();
02292                 double nVerticesD = this -> countVertices ();
02293                 if ((nVerticesD > 3000) && (nEdgesD < nVerticesD * 1000) &&
02294                         (nEdgesD < nVerticesD * nVerticesD / 50))
02295                 {
02296                         sparse = true;
02297                 }
02298         }
02299 
02300         // run the Johnson's or Floyd-Warshall algorithm
02301         wType minWeight = sparse ?
02302                 this -> Johnson (rounding, arr, false, ignoreNegLoop) :
02303                 this -> FloydWarshall (rounding, arr, false, ignoreNegLoop);
02304 
02305 /*      // compute the minimum of all the paths
02306         wType minWeight = arr [0] [0];
02307         for (int_t i = 0; i < nVertices; ++ i)
02308         {
02309                 for (int_t j = 0; j < nVertices; ++ j)
02310                 {
02311                         const wType &weight = arr [i] [j];
02312                         if (weight < minWeight)
02313                                 minWeight = weight;
02314                 }
02315         }
02316 */
02317         // release the memory
02318         for (int_t i = 0; i < nVertices; ++ i)
02319                 delete [] (arr [i]);
02320         delete [] arr;
02321 
02322         return minWeight;
02323 } /* diGraph::minPathWeight */
02324 
02325 template <class wType>
02326 wType diGraph<wType>::minPathWeight (bool ignoreNegLoop, int sparseGraph)
02327         const
02328 {
02329         const dummyRounding<wType> rounding = dummyRounding<wType> ();
02330         return this -> minPathWeight (rounding, ignoreNegLoop, sparseGraph);
02331 } /* diGraph::minPathWeight */
02332 
02333 template <class wType> template <class outType>
02334 inline outType &diGraph<wType>::show (outType &out, bool showWeights) const
02335 {
02336         out << "; Directed graph: " << nVertices << " vertices.\n";
02337         int_t curEdge = 0;
02338         for (int_t i = 0; i < nVertices; ++ i)
02339         {
02340                 for (; curEdge < edgeEnds [i]; ++ curEdge)
02341                 {
02342                         out << i << " -> " << edges [curEdge];
02343                         if (showWeights)
02344                                 out << " [" << weights [curEdge] << "]\n";
02345                         else
02346                                 out << "\n";
02347                 }
02348         }
02349         out << "; This is the end of the graph.\n";
02350         return out;
02351 } /* diGraph::show */
02352 
02353         
02354 // --------------------------------------------------
02355 
02357 template <class wType>
02358 inline std::ostream &operator << (std::ostream &out, const diGraph<wType> &g)
02359 {
02360         return g. show (out, false);
02361 } /* operator << */
02362 
02363 // --------------------------------------------------
02364 
02372 template <class wType, class Table1, class Table2>
02373 inline int_t SCC (const diGraph<wType> &g, Table1 &compVertices,
02374         Table2 &compEnds, diGraph<wType> *scc = 0,
02375         diGraph<wType> *transposed = 0, bool copyweights = false)
02376 {
02377         // prepare two tables
02378         int_t nVert = g. countVertices ();
02379         int_t *ordered = new int_t [nVert];
02380         int_t *tab = new int_t [nVert];
02381 
02382         // compute the list of vertices in the descending finishing time
02383         g. DFSfinishTime (tab);
02384         for (int_t i = 0; i < nVert; ++ i)
02385                 ordered [nVert - tab [i]] = i;
02386         delete [] tab;
02387 
02388         // create the transposed graph
02389         diGraph<wType> gT;
02390         if (!transposed)
02391                 transposed = &gT;
02392         g. transpose (*transposed, copyweights);
02393 
02394         // extract the DFS forest of gT in the given order of vertices
02395         int_t n = transposed -> DFSforest (ordered, compVertices, compEnds,
02396                 true, scc);
02397 
02398         // cleanup memory and return the number of components
02399         delete [] ordered;
02400         return n;
02401 } /* SCC */
02402 
02403 // --------------------------------------------------
02404 
02414 template <class wType, class Table1, class Table2>
02415 inline int_t SCC_Tarjan (const diGraph<wType> &g, Table1 &compVertices,
02416         Table2 &compEnds)
02417 {
02418         // return the obvious result if the graph is empty
02419         int_t nVertices = g. countVertices ();
02420         if (!nVertices)
02421                 return 0;
02422 
02423         // prepare an array of discovery times for all the vertices
02424         // (zero == not yet discovered)
02425         std::vector<int_t> dfsIndex (nVertices, 0);
02426 
02427         // prepare an array of the minimal index of a node reachable
02428         // from each of the vertices
02429         std::vector<int_t> lowLink (nVertices, 0);
02430 
02431         // prepare an empty stack of nodes
02432         std::stack<int_t> s_nodes;
02433 
02434         // prepare an array of bits indicating whether the vertices are
02435         // in the stack of nodes or not
02436         BitField inTheStack;
02437         inTheStack. allocate (nVertices);
02438         inTheStack. clearall (nVertices);
02439 
02440         // prepare the number of strongly connected components
02441         int_t nComponents = 0;
02442 
02443         // prepare the current position in the array 'compVertices'
02444         int_t posVertices = 0;
02445 
02446         // remember the next vertex number in the graph to scan
02447         // whether this vertex has already been visited or not
02448         int_t vertexToScan = 0;
02449 
02450         // prepare a variable for storing the discovery time in the DFS
02451         int_t discoveryTime = 0;
02452 
02453         // prepare stacks for the DFS recursion
02454         std::stack<int_t> s_vertex;
02455         std::stack<int_t> s_edge;
02456         std::stack<int_t> s_maxedge;
02457 
02458         // initialize the number of the currently processed vertex
02459         int_t vertex = -1;
02460 
02461         // initialize the range of edges to be visited
02462         int_t edge = 0;
02463         int_t maxedge = 0;
02464 
02465         while (1)
02466         {
02467                 // return to the previous recursion level
02468                 // if all the edges have been checked
02469                 if (edge >= maxedge)
02470                 {
02471                         // extract a strongly connected component
02472                         if ((vertex >= 0) && (lowLink [vertex] ==
02473                                 dfsIndex [vertex]))
02474                         {
02475                                 int_t v = 0;
02476                                 do
02477                                 {
02478                                         v = s_nodes. top ();
02479                                         s_nodes. pop ();
02480                                         inTheStack. clear (v);
02481                                         compVertices [posVertices ++] = v;
02482                                 } while (v != vertex);
02483                                 compEnds [nComponents ++] = posVertices;
02484                         }
02485 
02486                         // if this is the top level of the recursion
02487                         // then find another unvisited vertex or return
02488                         if (s_vertex. empty ())
02489                         {
02490                                 // find an unvisited vertex in the graph
02491                                 while ((vertexToScan < nVertices) &&
02492                                         (dfsIndex [vertexToScan] != 0))
02493                                 {
02494                                         ++ vertexToScan;
02495                                 }
02496 
02497                                 // return the result if all visited
02498                                 if (vertexToScan == nVertices)
02499                                 {
02500                                         inTheStack. free ();
02501                                         return nComponents;
02502                                 }
02503 
02504                                 // set the new vertex
02505                                 vertex = vertexToScan ++;
02506 
02507                                 // mark the current vertex as visited
02508                                 // and initialize its low link
02509                                 dfsIndex [vertex] = ++ discoveryTime;
02510                                 lowLink [vertex] = discoveryTime;
02511 
02512                                 // push this vertex on the stack
02513                                 s_nodes. push (vertex);
02514                                 inTheStack. set (vertex);
02515 
02516                                 // determine the edges to be visited
02517                                 edge = 0;
02518                                 maxedge = g. countEdges (vertex);
02519                         }
02520 
02521                         // otherwise trace back to the previous level
02522                         else
02523                         {
02524                                 // remember the current low link index
02525                                 int_t lowLink2 = lowLink [vertex];
02526 
02527                                 // restore the variables
02528                                 vertex = s_vertex. top ();
02529                                 s_vertex. pop ();
02530                                 edge = s_edge. top ();
02531                                 s_edge. pop ();
02532                                 maxedge = s_maxedge. top ();
02533                                 s_maxedge. pop ();
02534 
02535                                 // update the current low link index
02536                                 if (lowLink [vertex] > lowLink2)
02537                                         lowLink [vertex] = lowLink2;
02538                         }
02539                 }
02540 
02541                 // analyse the next edge coming out from the current vertex
02542                 else
02543                 {
02544                         // determine the next vertex
02545                         int_t next = g. getEdge (vertex, edge ++);
02546 
02547                         // go to a deeper recursion level if unvisited
02548                         if (dfsIndex [next] == 0)
02549                         {
02550                                 // store the variables at the stacks
02551                                 s_vertex. push (vertex);
02552                                 s_edge. push (edge);
02553                                 s_maxedge. push (maxedge);
02554 
02555                                 // set the new vertex
02556                                 vertex = next;
02557                         
02558                                 // mark the new vertex as visited
02559                                 dfsIndex [vertex] = ++ discoveryTime;
02560                                 lowLink [vertex] = discoveryTime;
02561                         
02562                                 // push this vertex on the stack
02563                                 s_nodes. push (vertex);
02564                                 inTheStack. set (vertex);
02565 
02566                                 // determine the edges to be visited
02567                                 edge = 0;
02568                                 maxedge = g. countEdges (vertex);
02569                         }
02570 
02571                         // update the low link index if the vertex has been
02572                         // visited and is currently in the stack of nodes
02573                         else if (inTheStack. test (next))
02574                         {
02575                                 if (lowLink [vertex] > dfsIndex [next])
02576                                         lowLink [vertex] = dfsIndex [next];
02577                         }
02578                 }
02579         }
02580 
02581         // finalize and return the number of strongly connected components
02582         inTheStack. free ();
02583         return nComponents;
02584 } /* SCC_Tarjan */
02585 
02586 // --------------------------------------------------
02587 
02588 template <class wType>
02589 wType diGraph<wType>::minMeanCycleWeight (diGraph<wType> *transposed) const
02590 {
02591         // find the strongly connected components of the graph
02592         multitable<int_t> compVertices, compEnds;
02593         bool copyweights = !!transposed;
02594         int_t countSCC = SCC (*this, compVertices, compEnds,
02595                 static_cast<diGraph<wType> *> (0), transposed, copyweights);
02596         if (countSCC <= 0)
02597                 return 0;
02598 
02599         // compute the maximum size of each strongly connected component
02600         int_t maxCompSize = compEnds [0];
02601         for (int_t comp = 1; comp < countSCC; ++ comp)
02602         {
02603                 int_t compSize = compEnds [comp] - compEnds [comp - 1];
02604                 if (maxCompSize < compSize)
02605                         maxCompSize = compSize;
02606         }
02607 
02608         // allocate arrays for weights and bit fields
02609         wType **F = new wType * [maxCompSize + 1];
02610         BitField *finite = new BitField [maxCompSize + 1];
02611         for (int_t i = 0; i <= maxCompSize; ++ i)
02612         {
02613                 F [i] = new wType [maxCompSize];
02614                 finite [i]. allocate (maxCompSize);
02615         }
02616 
02617         // compute the numbers of vertices in each component
02618         int_t *numbers = new int_t [nVertices];
02619         int_t *components = new int_t [nVertices];
02620         for (int_t i = 0; i < nVertices; ++ i)
02621                 components [i] = -1;
02622         int_t offset = 0;
02623         for (int_t comp = 0; comp < countSCC; ++ comp)
02624         {
02625                 int_t maxOffset = compEnds [comp];
02626                 int_t pos = offset;
02627                 for (; pos < maxOffset; ++ pos)
02628                 {
02629                         numbers [compVertices [pos]] = pos - offset;
02630                         components [compVertices [pos]] = comp;
02631                 }
02632                 offset = pos;
02633         }
02634 
02635         // compute the minimum mean cycle weight for each component
02636         wType minWeight (0);
02637         for (int_t comp = 0; comp < countSCC; ++ comp)
02638         {
02639                 int_t offset = comp ? compEnds [comp - 1] :
02640                         static_cast<int_t> (0);
02641                 int_t compSize = compEnds [comp] - offset;
02642                 for (int_t i = 0; i <= compSize; ++ i)
02643                         finite [i]. clearall (compSize);
02644                 F [0] [0] = 0;
02645                 finite [0]. set (0);
02646                 // compute path progressions of given length
02647                 for (int_t len = 1; len <= compSize; ++ len)
02648                 {
02649                         // process source vertices
02650                         for (int_t i = 0; i < compSize; ++ i)
02651                         {
02652                                 if (!finite [len - 1]. test (i))
02653                                         continue;
02654                                 wType prevWeight = F [len - 1] [i];
02655                                 int_t source = compVertices [offset + i];
02656 
02657                                 // process target vertices (and edges)
02658                                 int_t edgeOffset = source ?
02659                                         edgeEnds [source - 1] :
02660                                         static_cast<int_t> (0);
02661                                 int_t edgeEnd = edgeEnds [source];
02662                                 for (; edgeOffset < edgeEnd; ++ edgeOffset)
02663                                 {
02664                                         int_t target = edges [edgeOffset];
02665                                         if (components [target] != comp)
02666                                                 continue;
02667                                         int_t j = numbers [target];
02668                                         wType newWeight = prevWeight +
02669                                                 weights [edgeOffset];
02670                                         if (!finite [len]. test (j))
02671                                         {
02672                                                 finite [len]. set (j);
02673                                                 F [len] [j] = newWeight;
02674                                         }
02675                                         else if (newWeight < F [len] [j])
02676                                                 F [len] [j] = newWeight;
02677                                 }
02678                         }
02679                 }
02680 
02681                 // compute the minimum mean cycle weight for this component
02682                 wType minCompWeight (0);
02683                 bool firstMin = true;
02684                 for (int_t vert = 0; vert < compSize; ++ vert)
02685                 {
02686                         if (!finite [compSize]. test (vert))
02687                                 continue;
02688                         bool firstAverage = true;
02689                         wType maxAverage = 0;
02690                         for (int_t first = 0; first < compSize; ++ first)
02691                         {
02692                                 if (!finite [first]. test (vert))
02693                                         continue;
02694                                 wType average = (F [compSize] [vert] -
02695                                         F [first] [vert]) /
02696                                         (compSize - first);
02697                                 if (firstAverage)
02698                                 {
02699                                         maxAverage = average;
02700                                         firstAverage = false;
02701                                 }
02702                                 else if (maxAverage < average)
02703                                         maxAverage = average;
02704                         }
02705                         if (firstMin || (maxAverage < minCompWeight))
02706                         {
02707                                 if (firstAverage)
02708                                         throw "Bug in Karp's algorithm";
02709                                 minCompWeight = maxAverage;
02710                                 firstMin = false;
02711                         }
02712                 }
02713 
02714                 // make a correction to the total minimum if necessary
02715                 if (!comp || (minCompWeight < minWeight))
02716                         minWeight = minCompWeight;
02717         }
02718 
02719         // release allocated memory
02720         delete [] components;
02721         delete [] numbers;
02722         for (int_t i = 0; i < maxCompSize; ++ i)
02723         {
02724                 finite [i]. free ();
02725                 delete [] (F [i]);
02726         }
02727         delete [] finite;
02728         delete [] F;
02729 
02730         // return the computed minimum
02731         return minWeight;
02732 } /* diGraph::minMeanCycleWeight */
02733 
02734 template <class wType>
02735 template <class roundType>
02736 wType diGraph<wType>::minMeanCycleWeight (const roundType &rounding,
02737         diGraph<wType> *transposed) const
02738 {
02739         // find the strongly connected components of the graph
02740         multitable<int_t> compVertices, compEnds;
02741         bool copyweights = !!transposed;
02742         int_t countSCC = SCC (*this, compVertices, compEnds,
02743                 static_cast<diGraph<wType> *> (0), transposed, copyweights);
02744         if (countSCC <= 0)
02745                 return 0;
02746 
02747         // compute the maximum size of each strongly connected component
02748         int_t maxCompSize = compEnds [0];
02749         for (int_t comp = 1; comp < countSCC; ++ comp)
02750         {
02751                 int_t compSize = compEnds [comp] - compEnds [comp - 1];
02752                 if (maxCompSize < compSize)
02753                         maxCompSize = compSize;
02754         }
02755 
02756         // allocate arrays for weights and bit fields
02757         wType **FUpper = new wType * [maxCompSize + 1];
02758         wType **FLower = new wType * [maxCompSize + 1];
02759         BitField *finite = new BitField [maxCompSize + 1];
02760         for (int_t i = 0; i <= maxCompSize; ++ i)
02761         {
02762                 FUpper [i] = new wType [maxCompSize];
02763                 FLower [i] = new wType [maxCompSize];
02764                 finite [i]. allocate (maxCompSize);
02765         }
02766 
02767         // compute the numbers of vertices in each component
02768         int_t *numbers = new int_t [nVertices];
02769         int_t *components = new int_t [nVertices];
02770         for (int_t i = 0; i < nVertices; ++ i)
02771                 components [i] = -1;
02772         int_t offset = 0;
02773         for (int_t comp = 0; comp < countSCC; ++ comp)
02774         {
02775                 int_t maxOffset = compEnds [comp];
02776                 int_t pos = offset;
02777                 for (; pos < maxOffset; ++ pos)
02778                 {
02779                         numbers [compVertices [pos]] = pos - offset;
02780                         components [compVertices [pos]] = comp;
02781                 }
02782                 offset = pos;
02783         }
02784 
02785         // compute the minimum mean cycle weight for each component
02786         wType minWeight (0);
02787         for (int_t comp = 0; comp < countSCC; ++ comp)
02788         {
02789                 int_t offset = comp ? compEnds [comp - 1] :
02790                         static_cast<int_t> (0);
02791                 int_t compSize = compEnds [comp] - offset;
02792                 for (int_t i = 0; i <= compSize; ++ i)
02793                         finite [i]. clearall (compSize);
02794                 FUpper [0] [0] = 0;
02795                 FLower [0] [0] = 0;
02796                 finite [0]. set (0);
02797                 // compute path progressions of given length
02798                 for (int_t len = 1; len <= compSize; ++ len)
02799                 {
02800                         // process source vertices
02801                         for (int_t i = 0; i < compSize; ++ i)
02802                         {
02803                                 if (!finite [len - 1]. test (i))
02804                                         continue;
02805                                 wType prevUpper = FUpper [len - 1] [i];
02806                                 wType prevLower = FLower [len - 1] [i];
02807                                 int_t source = compVertices [offset + i];
02808 
02809                                 // process target vertices (and edges)
02810                                 int_t edgeOffset = source ?
02811                                         edgeEnds [source - 1] :
02812                                         static_cast<int_t> (0);
02813                                 int_t edgeEnd = edgeEnds [source];
02814                                 for (; edgeOffset < edgeEnd; ++ edgeOffset)
02815                                 {
02816                                         int_t target = edges [edgeOffset];
02817                                         if (components [target] != comp)
02818                                                 continue;
02819                                         int_t j = numbers [target];
02820                                         wType newUpper = rounding. add_up
02821                                                 (prevUpper,
02822                                                 weights [edgeOffset]);
02823                                         wType newLower = rounding. add_down
02824                                                 (prevLower,
02825                                                 weights [edgeOffset]);
02826                                         if (!finite [len]. test (j))
02827                                         {
02828                                                 finite [len]. set (j);
02829                                                 FUpper [len] [j] = newUpper;
02830                                                 FLower [len] [j] = newLower;
02831                                         }
02832                                         else
02833                                         {
02834                                                 wType &curUpper =
02835                                                         FUpper [len] [j];
02836                                                 if (newUpper < curUpper)
02837                                                         curUpper = newUpper;
02838                                                 wType &curLower =
02839                                                         FLower [len] [j];
02840                                                 if (newLower < curLower)
02841                                                         curLower = newLower;
02842                                         }
02843                                 }
02844                         }
02845                 }
02846 
02847                 // compute the minimum mean cycle weight for this component
02848                 wType minCompWeight (0);
02849                 bool firstMin = true;
02850                 for (int_t vert = 0; vert < compSize; ++ vert)
02851                 {
02852                         if (!finite [compSize]. test (vert))
02853                                 continue;
02854                         bool firstAverage = true;
02855                         wType maxAverage = 0;
02856                         for (int_t first = 0; first < compSize; ++ first)
02857                         {
02858                                 if (!finite [first]. test (vert))
02859                                         continue;
02860                                 const wType diff = rounding. sub_down
02861                                         (FLower [compSize] [vert],
02862                                         FUpper [first] [vert]);
02863                                 wType average = rounding. div_down
02864                                         (diff, compSize - first);
02865                                 if (firstAverage)
02866                                 {
02867                                         maxAverage = average;
02868                                         firstAverage = false;
02869                                 }
02870                                 else if (maxAverage < average)
02871                                         maxAverage = average;
02872                         }
02873                         if (firstMin || (maxAverage < minCompWeight))
02874                         {
02875                                 if (firstAverage)
02876                                         throw "Bug in Karp's algorithm";
02877                                 minCompWeight = maxAverage;
02878                                 firstMin = false;
02879                         }
02880                 }
02881 
02882                 // make a correction to the total minimum if necessary
02883                 if (!comp || (minCompWeight < minWeight))
02884                         minWeight = minCompWeight;
02885         }
02886 
02887         // release allocated memory
02888         delete [] components;
02889         delete [] numbers;
02890         for (int_t i = 0; i < maxCompSize; ++ i)
02891         {
02892                 finite [i]. free ();
02893                 delete [] (FUpper [i]);
02894                 delete [] (FLower [i]);
02895         }
02896         delete [] finite;
02897         delete [] FUpper;
02898         delete [] FLower;
02899 
02900         // return the computed minimum
02901         return minWeight;
02902 } /* diGraph::minMeanCycleWeight_intv */
02903 
02904 template <class wType>
02905 template <class arrayType, class roundType>
02906 wType diGraph<wType>::minMeanPathWeight (const roundType &rounding,
02907         const arrayType &starting, int_t n) const
02908 {
02909         // allocate arrays for weights and bit fields
02910         const int nIndices = 2;
02911         wType **F = new wType * [nIndices];
02912         BitField *finite = new BitField [nIndices];
02913         for (int i = 0; i < nIndices; ++ i)
02914         {
02915                 F [i] = new wType [nVertices];
02916                 finite [i]. allocate (nVertices);
02917         }
02918 
02919         // set the zero path lengths from the initial vertices
02920         for (int_t i = 0; i < n; ++ i)
02921         {
02922                 int_t v = starting [i];
02923                 if ((v < 0) || (v >= nVertices))
02924                         throw "Starting vertex out of range.";
02925                 F [0] [v] = 0;
02926                 finite [0]. set (v);
02927         }
02928 
02929         // compute path progressions of given length and average weights
02930         wType minWeight (0);
02931         bool firstWeight = true;
02932         for (int_t len = 1; len <= nVertices; ++ len)
02933         {
02934                 // determine the indices for previous and current paths
02935                 int_t prevIndex = (len - 1) & 1;
02936                 int_t curIndex = len & 1;
02937                 finite [curIndex]. clearall (nVertices);
02938 
02939                 // process source vertices
02940                 for (int_t source = 0; source < nVertices; ++ source)
02941                 {
02942                         if (!finite [prevIndex]. test (source))
02943                                 continue;
02944                         wType prevWeight = F [prevIndex] [source];
02945 
02946                         // process target vertices (and edges)
02947                         int_t edgeOffset = source ?
02948                                 edgeEnds [source - 1] :
02949                                 static_cast<int_t> (0);
02950                         int_t edgeEnd = edgeEnds [source];
02951                         for (; edgeOffset < edgeEnd; ++ edgeOffset)
02952                         {
02953                                 int_t target = edges [edgeOffset];
02954                                 wType newWeight = rounding. add_down
02955                                         (prevWeight, weights [edgeOffset]);
02956                                 if (!finite [curIndex]. test (target))
02957                                 {
02958                                         finite [curIndex]. set (target);
02959                                         F [curIndex] [target] = newWeight;
02960                                 }
02961                                 else if (newWeight < F [curIndex] [target])
02962                                         F [curIndex] [target] = newWeight;
02963                         }
02964                 }
02965 
02966                 // update the minimum mean path weight
02967                 for (int_t vert = 0; vert < nVertices; ++ vert)
02968                 {
02969                         if (!finite [curIndex]. test (vert))
02970                                 continue;
02971                         wType average = rounding. div_down
02972                                 (F [curIndex] [vert], len);
02973                         if (firstWeight)
02974                         {
02975                                 minWeight = average;
02976                                 firstWeight = false;
02977                         }
02978                         else if (average < minWeight)
02979                                 minWeight = average;
02980                 }
02981         }
02982 
02983         // release allocated memory
02984         for (int i = 0; i < nIndices; ++ i)
02985         {
02986                 finite [i]. free ();
02987                 delete [] (F [i]);
02988         }
02989         delete [] finite;
02990         delete [] F;
02991 
02992         // return the computed minimum
02993         return minWeight;
02994 } /* diGraph::minMeanPathWeight */
02995 
02996 template <class wType>
02997 template <class arrayType>
02998 wType diGraph<wType>::minMeanPathWeight (const arrayType &starting, int_t n)
02999         const
03000 {
03001         const dummyRounding<wType> rounding = dummyRounding<wType> ();
03002         return minMeanPathWeight (rounding, starting, n);
03003 } /* diGraph::minMeanPathWeight */
03004 
03005 
03006 // --------------------------------------------------
03007 // ------------- OTHER GRAPH ALGORITHMS -------------
03008 // --------------------------------------------------
03009 
03011 template <class wType>
03012 inline int_t addRenumEdges (const diGraph<wType> &g, int_t vertex,
03013         const int_t *newNum, int_t cur, int_t *srcVert,
03014         diGraph<wType> &result)
03015 {
03016         int_t nEdges = g. countEdges (vertex);
03017         // add all the edges that start at the component
03018         for (int_t edge = 0; edge < nEdges; ++ edge)
03019         {
03020                 // determine the dest. vertex of the edge
03021                 int_t dest = newNum [g. getEdge (vertex, edge)];
03022                 // if this is an edge to self, then ignore it
03023                 if (dest == cur)
03024                         continue;
03025                 // if the edge has already been added,
03026                 // then skip it
03027                 if (srcVert [dest] == cur)
03028                         continue;
03029                 // remember that the dest. vertex has an edge
03030                 // pointing out from the current vertex
03031                 srcVert [dest] = cur;
03032                 // add the edge to the result graph
03033                 result. addEdge (dest);
03034         }
03035         return 0;
03036 } /* addRenumEdges */
03037 
03043 template <class wType, class Table1, class Table2>
03044 inline int_t collapseVertices (const diGraph<wType> &g,
03045         int_t compNum, Table1 &compVertices, Table2 &compEnds,
03046         diGraph<wType> &result, int_t *newNumbers = 0)
03047 {
03048         // do nothing if the input graph is empty
03049         int_t nVert = g. countVertices ();
03050         if (!nVert)
03051                 return 0;
03052 
03053         // compute the new numbers of vertices: newNum [i] is the
03054         // number of vertex 'i' from 'g' in the resulting graph
03055         int_t *newNum = newNumbers ? newNumbers : new int_t [nVert];
03056         for (int_t i = 0; i < nVert; ++ i)
03057                 newNum [i] = -1;
03058         int_t cur = 0; // current vertex number in the new graph
03059         int_t pos = 0; // position in compVertices
03060         while (cur < compNum)
03061         {
03062                 int_t posEnd = compEnds [cur];
03063                 while (pos < posEnd)
03064                         newNum [compVertices [pos ++]] = cur;
03065                 ++ cur;
03066         }
03067         for (int_t i = 0; i < nVert; ++ i)
03068         {
03069                 if (newNum [i] < 0)
03070                         newNum [i] = cur ++;
03071         }
03072 
03073         // prepare a table to mark the most recent source vertex for edges:
03074         // srcVert [j] contains i if the edge i -> j has just been added
03075         int_t newVert = nVert - (compNum ? compEnds [compNum - 1] :
03076                 static_cast<int_t> (0)) + compNum;
03077         // debug:
03078         if (cur != newVert)
03079                 throw "DEBUG: Wrong numbers.";
03080         int_t *srcVert = new int_t [newVert];
03081         for (int_t i = 0; i < newVert; ++ i)
03082                 srcVert [i] = -1;
03083 
03084         // scan the input graph and create the resulting graph: begin with
03085         // the vertices in the collapsed groups
03086         cur = 0, pos = 0;
03087         while (cur < compNum)
03088         {
03089                 // add a new vertex to the result graph
03090                 result. addVertex ();
03091                 // for all the vertices in this component...
03092                 int_t posEnd = compEnds [cur];
03093                 while (pos < posEnd)
03094                 {
03095                         // take the next vertex from the component
03096                         int_t vertex = compVertices [pos ++];
03097                         // add the appropriate edges to the result graph
03098                         addRenumEdges (g, vertex, newNum, cur,
03099                                 srcVert, result);
03100                 }
03101                 ++ cur;
03102         }
03103         // process the remaining vertices of the graph
03104         for (int_t vertex = 0; vertex < nVert; ++ vertex)
03105         {
03106                 // debug
03107                 if (newNum [vertex] > cur)
03108                         throw "DEBUG: Wrong order.";
03109                 // if the vertex has already been processed, skip it
03110                 if (newNum [vertex] != cur)
03111                         continue;
03112                 // add the appropriate edges to the result graph
03113                 result. addVertex ();
03114                 addRenumEdges (g, vertex, newNum, cur, srcVert, result);
03115                 ++ cur;
03116         }
03117 
03118         // free memory and exit
03119         delete [] srcVert;
03120         if (!newNumbers)
03121                 delete [] newNum;
03122         return 0;
03123 } /* collapseVertices */
03124 
03126 template <class wType, class TabSets>
03127 inline int_t addRenumEdges2 (const diGraph<wType> &g, int_t vertex,
03128         const int_t *newNum, TabSets &numSets,
03129         int_t cur, int_t *srcVert, diGraph<wType> &result)
03130 {
03131         int_t nEdges = g. countEdges (vertex);
03132 
03133         // add all the edges that start at this vertex
03134         for (int_t edge = 0; edge < nEdges; ++ edge)
03135         {
03136                 // determine the dest. vertex of the edge
03137                 int_t destNumber = newNum [g. getEdge (vertex, edge)];
03138 
03139                 // consider all the destination vertices
03140                 int_t destSize = (destNumber < 0) ?
03141                         numSets [-destNumber]. size () :
03142                         static_cast<int_t> (1);
03143                 for (int_t i = 0; i < destSize; ++ i)
03144                 {
03145                         // determine the consecutive destination vertex
03146                         int_t dest = (destNumber < 0) ?
03147                                 numSets [-destNumber] [i] : destNumber;
03148 
03149                         // if this is an edge to self, then ignore it
03150                         if (dest == cur)
03151                                 continue;
03152 
03153                         // if the edge has already been added,
03154                         // then skip it
03155                         if (srcVert [dest] == cur)
03156                                 continue;
03157 
03158                         // add the edge to the result graph
03159                         result. addEdge (dest);
03160                 }
03161         }
03162         return 0;
03163 } /* addRenumEdges2 */
03164 
03169 template <class wType, class Table1, class Table2>
03170 inline int_t collapseVertices2 (const diGraph<wType> &g,
03171         int_t compNum, Table1 &compVertices, Table2 &compEnds,
03172         diGraph<wType> &result)
03173 {
03174         // do nothing if the input graph is empty
03175         int_t nVert = g. countVertices ();
03176         if (!nVert)
03177                 return 0;
03178 
03179         // compute the new numbers of vertices: newNum [i] is the
03180         // number of vertex 'i' from 'g' in the resulting graph,
03181         // unless negative; then it points to a set of numbers,
03182         // with -1 meaning "not defined, yet"
03183         int_t *newNum = new int_t [nVert];
03184         for (int_t i = 0; i < nVert; ++ i)
03185                 newNum [i] = -1;
03186 
03187         // sets of numbers of vertices; the numbers refering to the sets
03188         // begin with 2, thus the first two sets are skipped
03189         multitable<hashedset<int_t> > numSets;
03190         // the number of the set waiting to be used next
03191         int_t numSetCur = 2;
03192 
03193         int_t cur = 0; // current vertex number in the new graph
03194         int_t pos = 0; // position in compVertices
03195         while (cur < compNum)
03196         {
03197                 int_t posEnd = compEnds [cur];
03198                 while (pos < posEnd)
03199                 {
03200                         int_t number = compVertices [pos ++];
03201                         if (newNum [number] == -1)
03202                                 newNum [number] = cur;
03203                         else if (newNum [number] < 0)
03204                                 numSets [-newNum [number]]. add (cur);
03205                         else
03206                         {
03207                                 numSets [numSetCur]. add (newNum [number]);
03208                                 numSets [numSetCur]. add (cur);
03209                                 newNum [number] = -(numSetCur ++);
03210                         }
03211                 }
03212                 ++ cur;
03213         }
03214         for (int_t i = 0; i < nVert; ++ i)
03215         {
03216                 if (newNum [i] == -1)
03217                         newNum [i] = cur ++;
03218         }
03219 
03220         // prepare a table to mark the most recent source vertex for edges:
03221         // srcVert [j] contains i if the edge i -> j has just been added
03222         int_t newVert = cur;
03223         int_t *srcVert = new int_t [newVert];
03224         for (int_t i = 0; i < newVert; ++ i)
03225                 srcVert [i] = -1;
03226 
03227         // scan the input graph and create the resulting graph: begin with
03228         // the vertices in the collapsed groups
03229         cur = 0;
03230         pos = 0;
03231         while (cur < compNum)
03232         {
03233                 // add a new vertex to the result graph
03234                 result. addVertex ();
03235 
03236                 // for all the vertices in this component...
03237                 int_t posEnd = compEnds [cur];
03238                 while (pos < posEnd)
03239                 {
03240                         // take the next vertex from the component
03241                         int_t vertex = compVertices [pos ++];
03242 
03243                         // add the appropriate edges to the result graph
03244                         addRenumEdges2 (g, vertex, newNum, numSets, cur,
03245                                 srcVert, result);
03246                 }
03247                 ++ cur;
03248         }
03249 
03250         // process the remaining vertices of the graph
03251         for (int_t vertex = 0; vertex < nVert; ++ vertex)
03252         {
03253                 // debug
03254                 if (newNum [vertex] > cur)
03255                         throw "DEBUG: Wrong order 2.";
03256 
03257                 // if the vertex has already been processed, skip it
03258                 if (newNum [vertex] != cur)
03259                         continue;
03260 
03261                 // add the appropriate edges to the result graph
03262                 result. addVertex ();
03263                 addRenumEdges2 (g, vertex, newNum, numSets, cur,
03264                         srcVert, result);
03265                 ++ cur;
03266         }
03267 
03268         // free memory and exit
03269         delete [] srcVert;
03270         delete [] newNum;
03271         return 0;
03272 } /* collapseVertices2 */
03273 
03282 template <class wType>
03283 inline int_t connectionGraph (const diGraph<wType> &g, int_t nVert,
03284         diGraph<wType> &result)
03285 {
03286         // remember the number of vertices in the input graph
03287         int_t nVertG = g. countVertices ();
03288         if (!nVertG)
03289                 return 0;
03290 
03291         // prepare a bitfield in which visited vertices will be marked
03292         BitField visited;
03293         visited. allocate (nVertG);
03294         visited. clearall (nVertG);
03295 
03296         // run DFS for each of the starting vertices
03297         for (int_t startVertex = 0; startVertex < nVert; ++ startVertex)
03298         {
03299                 // add this vertex to the resulting graph
03300                 result. addVertex ();
03301 
03302                 // prepare a counter and a stack of visited vertices
03303                 int_t nVisited = 0;
03304                 std::stack<int_t> s_visited;
03305 
03306                 // prepare stacks for the DFS algorithm
03307                 std::stack<int_t> s_vertex;
03308                 std::stack<int_t> s_edge;
03309 
03310                 // mark the starting vertex as visited
03311                 visited. set (startVertex);
03312                 s_visited. push (startVertex);
03313                 ++ nVisited;
03314 
03315                 // use DFS to visit vertices reachable from that vertex
03316                 int_t vertex = startVertex;
03317                 int_t edge = 0;
03318                 while (1)
03319                 {
03320                         // go back with the recursion
03321                         // if all the edges have been processed
03322                         if (edge >= g. countEdges (vertex))
03323                         {
03324                                 // if this was the top recursion level
03325                                 // then quit
03326                                 if (s_vertex. empty ())
03327                                         break;
03328 
03329                                 // return from the recursion
03330                                 vertex = s_vertex. top ();
03331                                 s_vertex. pop ();
03332                                 edge = s_edge. top ();
03333                                 s_edge. pop ();
03334                                 continue;
03335                         }
03336 
03337                         // take the next vertex
03338                         int_t next = g. getEdge (vertex, edge ++);
03339 
03340                         // go to the deeper recursion level if not visited
03341                         if (!visited. test (next))
03342                         {
03343                                 // add an edge to the result if necessary
03344                                 if (next < nVert)
03345                                         result. addEdge (next);
03346 
03347                                 // store the previous variables at the stacks
03348                                 s_vertex. push (vertex);
03349                                 s_edge. push (edge);
03350 
03351                                 // take the new vertex
03352                                 vertex = next;
03353                                 edge = 0;
03354 
03355                                 // mark the new vertex as visited
03356                                 visited. set (vertex);
03357                                 s_visited. push (vertex);
03358                                 ++ nVisited;
03359                         }
03360                 }
03361 
03362                 // if this was the last vertex then skip the rest
03363                 if (startVertex == nVert - 1)
03364                         break;
03365 
03366                 // mark each vertex as non-visited
03367                 if (nVisited > (nVertG >> 6))
03368                 {
03369                         visited. clearall (nVertG);
03370                 }
03371                 else
03372                 {
03373                         while (!s_visited. empty ())
03374                         {
03375                                 int_t vertex = s_visited. top ();
03376                                 s_visited. pop ();
03377                                 visited. clear (vertex);
03378                         }
03379                 }
03380         }
03381 
03382         // free memory and exit
03383         visited. free ();
03384         return 0;
03385 } /* connectionGraph */
03386 
03392 template <class GraphType>
03393 inline int_t computePeriod (const GraphType &g)
03394 {
03395         // remember the number of vertices in the input graph
03396         int_t nVertG = g. countVertices ();
03397         if (!nVertG)
03398                 return 0;
03399 
03400         // prepare an array to record the depth of each visited vertex
03401         std::vector<int_t> visited (nVertG, 0);
03402 
03403         // run DFS starting at the first vertex
03404         // prepare stacks for the DFS algorithm
03405         std::stack<int_t> s_vertex;
03406         std::stack<int_t> s_edge;
03407 
03408         // mark the starting vertex as visited
03409         visited [0] = 1;
03410 
03411         // use DFS to visit vertices reachable from that vertex
03412         int_t vertex = 0;
03413         int_t edge = 0;
03414         int_t level = 1;
03415         int_t period = 0;
03416         while (1)
03417         {
03418                 // go back with the recursion
03419                 // if all the edges have been processed
03420                 if (edge >= g. countEdges (vertex))
03421                 {
03422                         // if this was the top recursion level then quit
03423                         if (s_vertex. empty ())
03424                                 break;
03425 
03426                         // return from the recursion
03427                         vertex = s_vertex. top ();
03428                         s_vertex. pop ();
03429                         edge = s_edge. top ();
03430                         s_edge. pop ();
03431                         -- level;
03432                         continue;
03433                 }
03434 
03435                 // take the next vertex
03436                 int_t next = g. getEdge (vertex, edge ++);
03437 
03438                 // update the GCD of the cycle lengths
03439                 if (visited [next])
03440                 {
03441                         // determine the period provided by the cycle
03442                         int_t newPeriod = visited [next] - level - 1;
03443                         if (newPeriod < 0)
03444                                 newPeriod = -newPeriod;
03445 
03446                         // compute the GCD of the old and new periods
03447                         int_t a = newPeriod;
03448                         int_t b = period;
03449                         while (b)
03450                         {
03451                                 int_t t = b;
03452                                 b = a % b;
03453                                 a = t;
03454                         }
03455                         period = a;
03456 
03457                         // if the graph turns out to be aperiodic
03458                         // then immediately return the result
03459                         if (period == 1)
03460                                 return period;
03461                 }
03462 
03463                 // go to the deeper recursion level if not visited
03464                 else
03465                 {
03466                         // store the previous variables at the stacks
03467                         s_vertex. push (vertex);
03468                         s_edge. push (edge);
03469 
03470                         // take the new vertex
03471                         vertex = next;
03472                         edge = 0;
03473                         ++ level;
03474 
03475                         // mark the new vertex as visited
03476                         visited [vertex] = level;
03477                 }
03478         }
03479 
03480         // return the computed peirod and exit
03481         return period;
03482 } /* computePeriod */
03483 
03489 template <class wType>
03490 inline int_t inclusionGraph (const diGraph<wType> &g, int_t nVert,
03491         diGraph<wType> &result)
03492 {
03493         // remember the number of vertices in the input graph
03494         int_t nVertG = g. countVertices ();
03495         if (!nVertG)
03496                 return 0;
03497 
03498         // mark each vertex as non-visited
03499         BitField visited;
03500         visited. allocate (nVertG);
03501         visited. clearall (nVertG);
03502 
03503         // create the sets of vertices reachable from each vertex
03504         BitSets lists (nVertG, nVert);
03505 
03506         // prepare stacks for the DFS algorithm
03507         std::stack<int_t> s_vertex;
03508         std::stack<int_t> s_edge;
03509 
03510         // use DFS to propagate the reachable sets
03511         int_t startVertex = 0;
03512         int_t vertex = 0;
03513         int_t edge = 0;
03514         visited. set (vertex);
03515         while (1)
03516         {
03517                 // go back with the recursion
03518                 // if all the edges have been processed
03519                 if (edge >= g. countEdges (vertex))
03520                 {
03521                         // if this was the top recursion level,
03522                         // then find another starting point or quit
03523                         if (s_vertex. empty ())
03524                         {
03525                                 while ((startVertex < nVertG) &&
03526                                         (visited. test (startVertex)))
03527                                         ++ startVertex;
03528                                 if (startVertex >= nVertG)
03529                                         break;
03530                                 vertex = startVertex;
03531                                 edge = 0;
03532                                 visited. set (vertex);
03533                                 continue;
03534                         }
03535 
03536                         // determine the previous vertex (to trace back to)
03537                         int_t prev = s_vertex. top ();
03538 
03539                         // add the list of the current vertex
03540                         // to the list of the previous vertex
03541                         // unless that was one of the first 'nVert' vertices
03542                         if (vertex >= nVert)
03543                                 lists. addset (prev, vertex);
03544 
03545                         // return from the recursion
03546                         vertex = prev;
03547                         s_vertex. pop ();
03548                         edge = s_edge. top ();
03549                         s_edge. pop ();
03550                         continue;
03551                 }
03552 
03553                 // take the next vertex
03554                 int_t next = g. getEdge (vertex, edge ++);
03555 
03556                 // add the number to the list if appropriate
03557                 if (next < nVert)
03558                         lists. add (vertex, next);
03559 
03560                 // go to the deeper recursion level if vertex not visited
03561                 if (!visited. test (next))
03562                 {
03563                         // store the previous variables at the stacks
03564                         s_vertex. push (vertex);
03565                         s_edge. push (edge);
03566 
03567                         // take the new vertex and mark as visited
03568                         vertex = next;
03569                         edge = 0;
03570                         visited. set (vertex);
03571                 }
03572 
03573                 // add the list of the next vertex to the current one
03574                 // if the vertex has already been visited before
03575                 // and the vertex is not one of the first 'nVert' ones
03576                 else if (next >= nVert)
03577                 {
03578                         lists. addset (vertex, next);
03579                 }
03580         }
03581 
03582         // create the result graph based on the lists of edges
03583         for (int_t vertex = 0; vertex < nVert; ++ vertex)
03584         {
03585                 result. addVertex ();
03586                 int_t edge = lists. get (vertex);
03587                 while (edge >= 0)
03588                 {
03589                         result. addEdge (edge);
03590                         edge = lists. get (vertex, edge + 1);
03591                 }
03592         }
03593 
03594         // free memory and exit
03595         visited. free ();
03596         return 0;
03597 } /* inclusionGraph */
03598 
03599 // --------------------------------------------------
03600 
03609 template<class wType, class TConn>
03610 inline int_t inclusionGraph (const diGraph<wType> &g, int_t nVert,
03611         diGraph<wType> &result, TConn &connections)
03612 {
03613         // remember the number of vertices in the input graph
03614         int_t nVertG = g. countVertices ();
03615         if (!nVertG)
03616                 return 0;
03617 
03618         // mark each vertex as non-visited
03619         BitField visited;
03620         visited. allocate (nVertG);
03621         visited. clearall (nVertG);
03622 
03623         // create the sets of vertices reachable from each vertex
03624         BitSets forwardlists (nVertG, nVert);
03625 
03626         // prepare stacks for the DFS algorithm
03627         std::stack<int_t> s_vertex;
03628         std::stack<int_t> s_edge;
03629 
03630         // use DFS to propagate the reachable sets
03631         int_t startVertex = 0;
03632         int_t vertex = 0;
03633         int_t edge = 0;
03634         visited. set (vertex);
03635         while (1)
03636         {
03637                 // go back with the recursion
03638                 // if all the edges have been processed
03639                 if (edge >= g. countEdges (vertex))
03640                 {
03641                         // if this was the top recursion level,
03642                         // then find another starting point or quit
03643                         if (s_vertex. empty ())
03644                         {
03645                                 while ((startVertex < nVertG) &&
03646                                         (visited. test (startVertex)))
03647                                         ++ startVertex;
03648                                 if (startVertex >= nVertG)
03649                                         break;
03650                                 vertex = startVertex;
03651                                 edge = 0;
03652                                 visited. set (vertex);
03653                                 continue;
03654                         }
03655 
03656                         // determine the previous vertex (to trace back to)
03657                         int_t prev = s_vertex. top ();
03658 
03659                         // add the list of the current vertex
03660                         // to the list of the previous vertex
03661                         // unless that was one of the first 'nVert' vertices
03662                         if (vertex >= nVert)
03663                                 forwardlists. addset (prev, vertex);
03664 
03665                         // return from the recursion
03666                         vertex = prev;
03667                         s_vertex. pop ();
03668                         edge = s_edge. top ();
03669                         s_edge. pop ();
03670                         continue;
03671                 }
03672 
03673                 // take the next vertex
03674                 int_t next = g. getEdge (vertex, edge ++);
03675 
03676                 // add the number to the list if appropriate
03677                 if (next < nVert)
03678                         forwardlists. add (vertex, next);
03679 
03680                 // go to the deeper recursion level if vertex not visited
03681                 if (!visited. test (next))
03682                 {
03683                         // store the previous variables at the stacks
03684                         s_vertex. push (vertex);
03685                         s_edge. push (edge);
03686 
03687                         // take the new vertex and mark as visited
03688                         vertex = next;
03689                         edge = 0;
03690                         visited. set (vertex);
03691                 }
03692 
03693                 // add the list of the next vertex to the current one
03694                 // if the vertex has already been visited before
03695                 // and the vertex is not one of the first 'nVert' ones
03696                 else if (next >= nVert)
03697                 {
03698                         forwardlists. addset (vertex, next);
03699                 }
03700         }
03701 
03702         // ------------------------------------------
03703 
03704         // create the sets of vertices that can reach each vertex
03705         BitSets backlists (nVertG, nVert);
03706 
03707         diGraph<wType> gT;
03708         g. transpose (gT);
03709 
03710         // do a simple test for debugging purposes
03711         if (!s_vertex. empty () || !s_edge. empty ())
03712                 throw "DEBUG: Nonempty stacks in 'inclusionGraph'.";
03713 
03714         // mark all the vertices as unvisited for the backward run
03715         visited. clearall (nVertG);
03716 
03717         // use DFS to propagate the reachable sets
03718         startVertex = 0;
03719         vertex = 0;
03720         edge = 0;
03721         visited. set (vertex);
03722         while (1)
03723         {
03724                 // go back with the recursion
03725                 // if all the edges have been processed
03726                 if (edge >= gT. countEdges (vertex))
03727                 {
03728                         // if this was the top recursion level,
03729                         // then find another starting point or quit
03730                         if (s_vertex. empty ())
03731                         {
03732                                 while ((startVertex < nVertG) &&
03733                                         (visited. test (startVertex)))
03734                                         ++ startVertex;
03735                                 if (startVertex >= nVertG)
03736                                         break;
03737                                 vertex = startVertex;
03738                                 edge = 0;
03739                                 visited. set (vertex);
03740                                 continue;
03741                         }
03742 
03743                         // determine the previous vertex (to trace back to)
03744                         int_t prev = s_vertex. top ();
03745 
03746                         // add the list of the current vertex
03747                         // to the list of the previous vertex
03748                         // unless that was one of the first 'nVert' vertices
03749                         if (vertex >= nVert)
03750                                 backlists. addset (prev, vertex);
03751 
03752                         // return from the recursion
03753                         vertex = prev;
03754                         s_vertex. pop ();
03755                         edge = s_edge. top ();
03756                         s_edge. pop ();
03757                         continue;
03758                 }
03759 
03760                 // take the next vertex
03761                 int_t next = gT. getEdge (vertex, edge ++);
03762 
03763                 // add the number to the list if appropriate
03764                 if (next < nVert)
03765                         backlists. add (vertex, next);
03766 
03767                 // go to the deeper recursion level if vertex not visited
03768                 if (!visited. test (next))
03769                 {
03770                         // store the previous variables at the stacks
03771                         s_vertex. push (vertex);
03772                         s_edge. push (edge);
03773 
03774                         // take the new vertex and mark as visited
03775                         vertex = next;
03776                         edge = 0;
03777                         visited. set (vertex);
03778                 }
03779 
03780                 // add the list of the next vertex to the current one
03781                 // if the vertex has already been visited before
03782                 // and the vertex is not one of the first 'nVert' ones
03783                 else if (next >= nVert)
03784                 {
03785                         backlists. addset (vertex, next);
03786                 }
03787         }
03788 
03789         // ------------------------------------------
03790 
03791         // record the connections to the obtained data structure
03792         for (int_t v = nVert; v < nVertG; ++ v)
03793         {
03794                 int_t bvertex = backlists. get (v);
03795                 while (bvertex >= 0)
03796                 {
03797                         int_t fvertex = forwardlists. get (v);
03798                         while (fvertex >= 0)
03799                         {
03800                                 connections (bvertex, fvertex, v);
03801                                 fvertex = forwardlists. get (v, fvertex + 1);
03802                         }
03803                         bvertex = backlists. get (v, bvertex + 1);
03804                 }
03805         }
03806 
03807         // ------------------------------------------
03808         
03809         // create the result graph based on the lists of edges
03810         for (int_t vertex = 0; vertex < nVert; ++ vertex)
03811         {
03812                 result. addVertex ();
03813                 int_t edge = forwardlists. get (vertex);
03814                 while (edge >= 0)
03815                 {
03816                         result. addEdge (edge);
03817                         edge = forwardlists. get (vertex, edge + 1);
03818                 }
03819         }
03820 
03821         // free memory and exit
03822         visited. free ();
03823         return 0;
03824 } /* inclusionGraph */
03825 
03826 // --------------------------------------------------
03827 
03831 template <class wType, class matrix>
03832 inline void graph2matrix (const diGraph<wType> &g, matrix &m)
03833 {
03834         int_t nVert = g. countVertices ();
03835         for (int_t v = 0; v < nVert; ++ v)
03836         {
03837                 int_t nEdges = g. countEdges (v);
03838                 for (int_t e = 0; e < nEdges; ++ e)
03839                 {
03840                         int_t w = g. getEdge (v, e);
03841                         m [v] [w] = 1;
03842                 }
03843         }
03844         return;
03845 } /* graph2matrix */
03846 
03851 template <class wType, class matrix>
03852 inline void matrix2graph (const matrix &m, int_t n, diGraph<wType> &g)
03853 {
03854         for (int_t v = 0; v < n; ++ v)
03855         {
03856                 g. addVertex ();
03857                 for (int_t w = 0; w < n; ++ w)
03858                         if (m [v] [w])
03859                                 g. addEdge (w);
03860         }
03861         return;
03862 } /* matrix2graph */
03863 
03864 // --------------------------------------------------
03865 
03869 template <class matrix>
03870 inline void transitiveClosure (matrix &m, int_t n)
03871 {
03872         for (int_t k = 0; k < n; ++ k)
03873         {
03874                 for (int_t i = 0; i < n; ++ i)
03875                 {
03876                         for (int_t j = 0; j < n; ++ j)
03877                         {
03878                                 if (m [i] [k] && m [k] [j])
03879                                         m [i] [j] = 1;
03880                         }
03881                 }
03882         }
03883         return;
03884 } /* transitiveClosure */
03885 
03893 template <class matrix>
03894 inline void transitiveReduction (matrix &m, int_t n)
03895 {
03896         for (int_t k = n - 1; k >= 0; -- k)
03897         {
03898                 for (int_t i = 0; i < n; ++ i)
03899                 {
03900                         for (int_t j = 0; j < n; ++ j)
03901                         {
03902                                 if (m [i] [k] && m [k] [j])
03903                                         m [i] [j] = 0;
03904                         }
03905                 }
03906         }
03907         return;
03908 } /* transitiveReduction */
03909 
03912 template <class wType>
03913 inline void transitiveReduction (const diGraph<wType> &g,
03914         diGraph<wType> &gRed)
03915 {
03916         int_t nVert = g. countVertices ();
03917         if (nVert <= 0)
03918                 return;
03919         flatMatrix<char> m (nVert);
03920         m. clear (0);
03921         graph2matrix (g, m);
03922         transitiveClosure (m, nVert);
03923         transitiveReduction (m, nVert);
03924         matrix2graph (m, nVert, gRed);
03925         return;
03926 } /* transitiveReduction */
03927 
03928 
03929 } // namespace homology
03930 } // namespace chomp
03931 
03932 #endif // _CHOMP_STRUCT_DIGRAPH_H_
03933 
03935