00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034 #ifndef _graphs_h_
00035 #define _graphs_h_
00036
00037 #include "rounding.h"
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
00051
00052
00053
00054
00055
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
00064 for (int i = 0; i < partCount; ++ i)
00065 {
00066
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
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
00094 g. addVertex ();
00095
00096
00097
00098 if (thePart. isCritical (i))
00099 {
00100 for (int j = i1; j < i2; ++ j)
00101 critImages. push_back (j);
00102 continue;
00103 }
00104
00105
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 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
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
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
00162 sbug << "Creating the graph...\n";
00163 diGraph<numType> g;
00164 std::vector<int> critImages;
00165 createGraph (g, theMap, thePart, partCount, critImages);
00166
00167
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
00178 numType lambdaTemp;
00179 if (!lambda && (lambda0 || logC))
00180 lambda = &lambdaTemp;
00181
00182
00183 diGraph<numType> gT;
00184
00185
00186 tRounding<numType> rounding;
00187
00188
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
00203 if (lambda0)
00204 {
00205
00206
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
00222
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
00244 if (logC)
00245 {
00246
00247 numType zero (0);
00248 if (!(*lambda == zero))
00249 {
00250
00251
00252
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
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
00270
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 }
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
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
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
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
00333
00334
00335
00336 bool deltaMinOK = false;
00337 bool deltaMaxOK = false;
00338 numType accuracy = 0;
00339 numType delta = deltaMin;
00340 while (1)
00341 {
00342
00343 if (deltaMinOK && deltaMaxOK)
00344 {
00345
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
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
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
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
00389
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
00401
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
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
00432 sout << "Log(1/delta) is between " << deltaMin << " and " <<
00433 deltaMax << ".\n";
00434
00435
00436 deltaBad = exp (-deltaMax);
00437 deltaGood = exp (-deltaMin);
00438
00439
00440 sout << "Delta is between " << deltaBad << " and " << deltaGood <<
00441 ".\n";
00442
00443 return;
00444 }
00445
00446
00447 }
00448
00449 #endif // _graphs_h_
00450
00451
00452