• Main Page
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

graphs.h

Go to the documentation of this file.
00001 /// @addtogroup unifexp
00002 /// @{
00003 
00004 /////////////////////////////////////////////////////////////////////////////
00005 ///
00006 /// @file graphs.h
00007 ///
00008 /// This file contains the definition of the main procedures for the
00009 /// computations which use graph algorithms.
00010 ///
00011 /// @author Pawel Pilarczyk
00012 ///
00013 /////////////////////////////////////////////////////////////////////////////
00014 
00015 // Copyright (C) 2007 by Pawel Pilarczyk.
00016 //
00017 // This file is part of my research program package.  This is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This software is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started on March 8, 2007. Last revision: August 22, 2007.
00033 
00034 #ifndef _graphs_h_
00035 #define _graphs_h_
00036 
00037 #include "rounding.h" // (this header must be included first - BOOST)
00038 
00039 #include "chomp/system/config.h"
00040 #include "chomp/system/textfile.h"
00041 #include "chomp/struct/digraph.h"
00042 
00043 #include "maptype.h"
00044 #include "parttype.h"
00045 
00046 
00047 namespace unifexp {
00048 
00049 // --------------------------------------------------
00050 // ------------------ create graph ------------------
00051 // --------------------------------------------------
00052 
00053 /// Computes the images of intervals in the partition
00054 /// and fills in the corresponding weighted graph.
00055 /// Fills out the table of images of critical neighborhoods.
00056 template <class wType, class numType>
00057 inline void createGraph (chomp::homology::diGraph<wType> &g,
00058         const mapType<numType> &theMap, const partType<numType> &thePart,
00059         int partCount, std::vector<int> &critImages)
00060 {
00061         using namespace chomp::homology;
00062 
00063         // compute the images of the intervals
00064         for (int i = 0; i < partCount; ++ i)
00065         {
00066                 // compute the image of the interval [i,i+1]
00067                 const numType &x1 = thePart [i];
00068                 const numType &x2 = thePart [i + 1];
00069                 if (false && sbug. show)
00070                 {
00071                         sbug << "Img of [" << x1 << "," << x2 << "]... ";
00072                 }
00073                 numType y1, y2;
00074                 theMap. image (x1, x2, y1, y2);
00075 
00076                 // cover this image with a series of intervals
00077                 int i1 = thePart. find (y1);
00078                 if (i1 < 0)
00079                         i1 = 0;
00080                 if ((i1 > 0) && (thePart [i1] == y1))
00081                         -- i1;
00082                 int i2 = thePart. find (y2);
00083                 if (i2 < partCount)
00084                         ++ i2;
00085                 if (false && sbug. show)
00086                 {
00087                         sbug << "(" << y1 << "," << y2 << "): " <<
00088                                 i1 << "-" << i2 << " (";
00089                         sbug << thePart [i1] << "," <<
00090                                 thePart [i2] << ").\n";
00091                 }
00092 
00093                 // add the vertex that corresponds to this interval
00094                 g. addVertex ();
00095 
00096                 // if this is part of a critical neighborhood,
00097                 // then add the image intervals to the sources list
00098                 if (thePart. isCritical (i))
00099                 {
00100                         for (int j = i1; j < i2; ++ j)
00101                                 critImages. push_back (j);
00102                         continue;
00103                 }
00104 
00105                 // add the edges to the graph
00106                 for (int j = i1; j < i2; ++ j)
00107                 {
00108                         g. addEdge (j, theMap. minLogDerivative
00109                                 (x1, x2, thePart [j], thePart [j + 1]));
00110                 }
00111         }
00112 
00113         return;
00114 } /* createGraph */
00115 
00116 
00117 // --------------------------------------------------
00118 // ------------ find lambda(s) and log C ------------
00119 // --------------------------------------------------
00120 
00121 /// Computes lambda, C, and lambda0 with the given partition
00122 /// and for the given map.
00123 /// Does not compute those values whose pointers are set to 0.
00124 template <class numType>
00125 inline void findLambdaC (const numType &delta,
00126         const mapType<numType> &theMap, partType<numType> &thePart,
00127         int partCount, numType *lambda, numType *logC, numType *lambda0,
00128         int rigorous, int sparseGraph)
00129 {
00130         using namespace chomp::homology;
00131 
00132         // create a partition
00133         thePart. create (theMap, partCount, delta);
00134         if (false && sbug. show)
00135         {
00136                 const partType<numType> &thePartConst = thePart;
00137                 numType minWidth = -1, maxWidth = 0;
00138                 bool firstTime = true;
00139                 for (int i = 0; i <= partCount; ++ i)
00140                 {
00141                         sbug << (i ? "\t" : "Partition:\n\t") <<
00142                                 thePartConst [i] << "\n";
00143                         if (!i || thePartConst. isCritical (i - 1))
00144                                 continue;
00145                         const numType width = thePartConst [i] -
00146                                 thePartConst [i - 1];
00147                         if (firstTime)
00148                         {
00149                                 minWidth = maxWidth = width;
00150                                 firstTime = false;
00151                         }
00152                         else if (width < minWidth)
00153                                 minWidth = width;
00154                         else if (maxWidth < width)
00155                                 maxWidth = width;
00156                 }
00157                 sbug << "Partition interval widths: from " << minWidth <<
00158                         " to " << maxWidth << ".\n";
00159         }
00160 
00161         // create a graph that represents the map on this partition
00162         sbug << "Creating the graph...\n";
00163         diGraph<numType> g;
00164         std::vector<int> critImages;
00165         createGraph (g, theMap, thePart, partCount, critImages);
00166 
00167         // show the information about the graph that has been created
00168         sbug << "The graph has " << g. countVertices () << " vertices, " <<
00169                 g. countEdges () << " edges.\n";
00170         if (false && sbug. show)
00171         {
00172                 sbug << "The graph:\n";
00173                 g. show (sbug, true);
00174                 sbug << "\n";
00175         }
00176 
00177         // create a substitute lambda if necessary
00178         numType lambdaTemp;
00179         if (!lambda && (lambda0 || logC))
00180                 lambda = &lambdaTemp;
00181 
00182         // prepare a transposed graph if necessary
00183         diGraph<numType> gT;
00184 
00185         // create an object for rounding in graph algorithms
00186         tRounding<numType> rounding;
00187 
00188         // compute lambda if necessary
00189         if (lambda)
00190         {
00191                 sbug << "Computing the exponent lambda... ";
00192                 if (rigorous)
00193                 {
00194                         *lambda = g. minMeanCycleWeight (rounding,
00195                                 lambda0 ? &gT : 0);
00196                 }
00197                 else
00198                         *lambda = g. minMeanCycleWeight (lambda0 ? &gT : 0);
00199                 sbug << *lambda << ".\n";
00200         }
00201 
00202         // compute lambda0 if requested to
00203         if (lambda0)
00204         {
00205                 // find the minimum mean path weight starting at the image
00206                 // of the critical neighborhood
00207                 sbug << "Computing path weights... ";
00208                 numType minStart = 0;
00209                 if (rigorous)
00210                 {
00211                         minStart = g. minMeanPathWeight (rounding,
00212                                 critImages, critImages. size ());
00213                 }
00214                 else
00215                 {
00216                         minStart = g. minMeanPathWeight (critImages,
00217                                 critImages. size ());
00218                 }
00219                 sbug << minStart << " and... ";
00220 
00221                 // find the minimum mean path weight ending at the critical
00222                 // neighborhood
00223                 std::vector<int> critIntervals;
00224                 int countCrit = theMap. countCritical ();
00225                 for (int i = 0; i < countCrit; ++ i)
00226                         critIntervals. push_back (thePart. getCritical (i));
00227                 numType minEnd = 0;
00228                 if (rigorous)
00229                 {
00230                         minEnd = gT. minMeanPathWeight (rounding,
00231                                 critIntervals, critIntervals. size ());
00232                 }
00233                 else
00234                 {
00235                         minEnd = gT. minMeanPathWeight (critIntervals,
00236                                 critIntervals. size ());
00237                 }
00238                 sbug << minEnd << ".\n";
00239                 numType minPath = (minStart < minEnd) ? minStart : minEnd;
00240                 *lambda0 = (minPath < *lambda) ? minPath : *lambda;
00241         }
00242 
00243         // compute C if requested to
00244         if (logC)
00245         {
00246                 // decrease the weights of the edges by lambda if necessary
00247                 numType zero (0);
00248                 if (!(*lambda == zero))
00249                 {
00250                         // decrease lambda a tiny bit to compensate for
00251                         // rounding errors which otherwise cause the creation
00252                         // of negative loops in the graph
00253                         if (*lambda < 0)
00254                                 *lambda *= 1.00000000001;
00255                         else
00256                                 *lambda *= 0.99999999999;
00257                         sout << "Decreasing lambda to " << *lambda <<
00258                                 " to avoid spurious negative loops.\n";
00259 
00260                         // decrease the weights by the value of lambda
00261                         int nEdges = g. countEdges ();
00262                         for (int edge = 0; edge < nEdges; ++ edge)
00263                         {
00264                                 g. setWeight (edge, rounding. sub_down
00265                                         (g. getWeight (edge), *lambda));
00266                         }
00267                 }
00268 
00269                 // use Floyd-Warshall or Johnson's algorithm
00270                 // to compute the minimal path weight in the graph
00271                 sbug << "Computing log C... ";
00272                 if (rigorous)
00273                 {
00274                         *logC = g. minPathWeight (rounding,
00275                                 false, sparseGraph);
00276                 }
00277                 else
00278                 {
00279                         *logC = g. minPathWeight (false, sparseGraph);
00280                 }
00281                 sbug << *logC << "\n";
00282         }
00283 
00284         return;
00285 } /* findLambdaC */
00286 
00287 
00288 // --------------------------------------------------
00289 // ------------------- find delta -------------------
00290 // --------------------------------------------------
00291 
00292 /// Finds a possibly small value of delta using the bisection method.
00293 /// The initial values of the arguments of this function are ignored.
00294 /// The actual computations are done for log(1/delta), and the accuracy
00295 /// is  applied to these rescaled numbers.
00296 /// The bisection method is used until the requested accuracy has been
00297 /// reached, and the two returned values contain delta that is too small,
00298 /// and delta that is still good.
00299 template <class numType>
00300 inline void findDeltaBisection (numType lambdaMin, numType resolution,
00301         const mapType<numType> &theMap, partType<numType> &thePart,
00302         int partCount, numType &deltaBad, numType &deltaGood,
00303         bool considerPaths, int rigorous, int sparseGraph)
00304 {
00305         using namespace chomp::homology;
00306 
00307         sout << "Finding min delta for which " <<
00308                 (considerPaths ? "lambda0" : "lambda") << " > " <<
00309                 lambdaMin << "...\n";
00310 
00311         // compute a reasonable guess for the initial delta
00312         double width = theMap. rightBound () - theMap. leftBound ();
00313         int nCrit = theMap. countCritical ();
00314         for (int i = 0; i <= nCrit; ++ i)
00315         {
00316                 double left = (i == 0) ? theMap. leftBound () :
00317                         theMap. criticalPoint (i - 1);
00318                 double right = (i == nCrit) ? theMap. rightBound () :
00319                         theMap. criticalPoint (i);
00320                 if (right - left < width)
00321                         width = right - left;
00322         }
00323 
00324         // WARNING: delta stands for log (1/delta)
00325         double deltaMin = log (1 / (width / 8));
00326         double deltaMax = log (1 / (width / 16));
00327         sbug << "Initial guess for delta: [" << exp (-deltaMax) << ", " <<
00328                 exp (-deltaMin) << "].\n";
00329         sbug << "Initial guess for log(1/delta): [" << deltaMin << ", " <<
00330                 deltaMax << "].\n";
00331 
00332         // decrease the lower limit for delta until it is good,
00333         // then increase the upper limit for delta until it is good,
00334         // and finally use bisection to narrow down the delta scope
00335         // until the given accuracy is accomplished
00336         bool deltaMinOK = false;
00337         bool deltaMaxOK = false;
00338         numType accuracy = 0;
00339         numType delta = deltaMin;
00340         while (1)
00341         {
00342                 // if the two bounds for delta are already known...
00343                 if (deltaMinOK && deltaMaxOK)
00344                 {
00345                         // determine the accuracy for computing delta
00346                         if (!accuracy)
00347                         {
00348                                 accuracy = deltaMin * resolution;
00349                                 sbug << "Computing log(1/delta) "
00350                                         "with the accuracy of " <<
00351                                         accuracy << "...\n";
00352                         }
00353                         if (deltaMax - deltaMin < accuracy)
00354                                 break;
00355                 }
00356 
00357                 // indicate the current value of delta under consideration
00358                 scon << "[" << deltaMin << "," << deltaMax << "]       \r";
00359                 sbug << "(Current estimate for log(1/delta): " << deltaMin <<
00360                         " - " << deltaMax << ".)\n";
00361                 sbug << "Checking log(1/delta) = " << delta <<
00362                         " (delta = " << exp (-delta) << ")...\n";
00363 
00364                 // compute the appropriate lambda for this delta
00365                 numType lambda = 0;
00366                 numType *none = 0;
00367                 findLambdaC (exp (-delta), theMap, thePart, partCount,
00368                         considerPaths ? none : &lambda, none,
00369                         considerPaths ? &lambda : none,
00370                         rigorous, sparseGraph);
00371 
00372                 // prepare a new delta to verify
00373                 if (!deltaMinOK)
00374                 {
00375                         if (lambdaMin < lambda)
00376                         {
00377                                 sbug << "Good min delta. :)\n";
00378                                 deltaMinOK = true;
00379                                 if (deltaMaxOK)
00380                                         delta = (deltaMin + deltaMax) / 2;
00381                                 else
00382                                         delta = deltaMax;
00383                         }
00384                         else
00385                         {
00386                                 sbug << "Bad min delta. %(\n";
00387                                 deltaMaxOK = true;
00388                                 // increase the lower limit by twice the
00389                                 // current difference between min and max
00390                                 deltaMin = deltaMin * 3 - deltaMax * 2;
00391                                 deltaMax = delta;
00392                                 delta = deltaMin;
00393                         }
00394                 }
00395                 else if (!deltaMaxOK)
00396                 {
00397                         if (lambdaMin < lambda)
00398                         {
00399                                 sbug << "Good max delta. %)\n";
00400                                 // increase the upper limit by twice the
00401                                 // current difference between min and max
00402                                 deltaMax = deltaMax * 3 - deltaMin * 2;
00403                                 deltaMin = delta;
00404                                 delta = deltaMax;
00405                         }
00406                         else
00407                         {
00408                                 sbug << "Bad max delta. :(\n";
00409                                 deltaMaxOK = true;
00410                                 deltaMax = delta;
00411                                 delta = (deltaMin + deltaMax) / 2;
00412                         }
00413                 }
00414                 else // if (deltaMinOK && deltaMaxOK)
00415                 {
00416                         if (lambdaMin < lambda)
00417                         {
00418                                 sbug << "Good delta. :)\n";
00419                                 deltaMin = delta;
00420                                 delta = (deltaMin + deltaMax) / 2;
00421                         }
00422                         else
00423                         {
00424                                 sbug << "Bad delta. :(\n";
00425                                 deltaMax = delta;
00426                                 delta = (deltaMin + deltaMax) / 2;
00427                         }
00428                 }
00429         }
00430 
00431         // show the answer for the log
00432         sout << "Log(1/delta) is between " << deltaMin << " and " <<
00433                 deltaMax << ".\n";
00434 
00435         // make the right numbers
00436         deltaBad = exp (-deltaMax);
00437         deltaGood = exp (-deltaMin);
00438 
00439         // show the actual answer
00440         sout << "Delta is between " << deltaBad << " and " << deltaGood <<
00441                 ".\n";
00442 
00443         return;
00444 } /* findDeltaBisection */
00445 
00446 
00447 } // namespace unifexp
00448 
00449 #endif // _graphs_h_
00450 
00451 /// @}
00452 

Generated on Sun Feb 3 2013 12:40:31 for The Uniform Expansion Software by  doxygen 1.7.2