Go to the documentation of this file.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
00035 #ifndef _partcrit_h_
00036 #define _partcrit_h_
00037
00038 #include <vector>
00039 #include <string>
00040 #include "chomp/system/textfile.h"
00041 #include "parttype.h"
00042
00043
00044 namespace unifexp {
00045
00046
00047
00048
00049
00050
00051
00052
00053 template <class numType>
00054 class partCritical: public partType<numType>
00055 {
00056 public:
00057
00058 std::string name () const;
00059
00060
00061
00062
00063 void create (const mapType<numType> &theMap, int partCount,
00064 const numType &delta);
00065
00066 private:
00067
00068
00069 static numType dist (const numType &x, const numType &y);
00070
00071
00072
00073 template <class vectType>
00074 static void fillUniform (vectType &tab, int first, int last);
00075
00076 };
00077
00078
00079
00080 template <class numType>
00081 std::string partCritical<numType>::name () const
00082 {
00083 return std::string ("critical");
00084 }
00085
00086 template <class numType>
00087 inline numType partCritical<numType>::dist (const numType &x,
00088 const numType &y)
00089 {
00090 numType diff = x - y;
00091 return (diff < 0) ? -diff : diff;
00092 }
00093
00094 template <class numType>
00095 template <class vectType>
00096 void partCritical<numType>::fillUniform (vectType &tab, int first, int last)
00097 {
00098 const numType &numFirst = tab [first];
00099 const numType &numLast = tab [last];
00100 const numType numDiff = (numLast - numFirst) / (last - first);
00101 for (int i = first + 1; i < last; ++ i)
00102 tab [i] = numFirst + (i - first) * numDiff;
00103 return;
00104 }
00105
00106 template <class numType>
00107 void partCritical<numType>::create (const mapType<numType> &theMap,
00108 int partCount, const numType &delta)
00109 {
00110 using chomp::homology::sbug;
00111
00112
00113 const int coarseFraction = 10;
00114 const int nImages = 30;
00115 const int widthFraction = 100;
00116 const int iterCoef = 3;
00117
00118
00119
00120 int nCrit = theMap. countCritical ();
00121 if (partCount < 2 * coarseFraction * (nCrit + 1))
00122 throw "Too small critical partition requested.";
00123
00124
00125 const int coarseCount = partCount / coarseFraction;
00126 std::vector<numType> coarse (coarseCount + 1);
00127 coarse [0] = theMap. leftBound ();
00128 coarse [coarseCount] = theMap. rightBound ();
00129
00130
00131
00132
00133 numType width = coarse [coarseCount] - coarse [0] -
00134 2 * delta * nCrit;
00135 if (width <= 0)
00136 throw "Too wide critical neighborhood requested.";
00137
00138
00139 std::vector<numType> images (nImages);
00140 std::vector<int> iterates (nImages);
00141 int maxIndex = 0;
00142 int curIndex = -nCrit;
00143 int iterate = 0;
00144 int iterateIndex = 0;
00145 while ((curIndex < maxIndex) && (maxIndex < nImages))
00146 {
00147
00148 if (curIndex == iterateIndex)
00149 {
00150 ++ iterate;
00151 iterateIndex = maxIndex;
00152 }
00153
00154
00155 numType prevPoint = (curIndex < 0) ?
00156 theMap. criticalPoint (-curIndex - 1) :
00157 images [curIndex];
00158 ++ curIndex;
00159
00160
00161 numType image1, image2;
00162 theMap. image (prevPoint, prevPoint, image1, image2);
00163 numType image = (image1 == image2) ? image1 :
00164 ((image1 + image2) / 2);
00165
00166
00167 if ((image < theMap. leftBound ()) ||
00168 (theMap. rightBound () < image))
00169 {
00170 continue;
00171 }
00172
00173
00174 bool wrong = false;
00175 for (int j = 0; j < nCrit; ++ j)
00176 {
00177 if (dist (image, theMap. criticalPoint (j)) < delta)
00178 {
00179 wrong = true;
00180 break;
00181 }
00182 }
00183 if (wrong)
00184 continue;
00185
00186
00187 images [maxIndex] = image;
00188 iterates [maxIndex] = iterate;
00189 ++ maxIndex;
00190 }
00191
00192
00193 if (false && sbug. show)
00194 {
00195 sbug << "Critical points and their iterates:\n";
00196 for (int i = 0; i < maxIndex; ++ i)
00197 sbug << std::setw (8) << iterates [i] << ": " <<
00198 images [i] << "\n";
00199 }
00200
00201
00202 std::vector<int> leftPoints;
00203 std::vector<int> rightPoints;
00204 int prev = 0;
00205 for (int i = 0; i < nCrit; ++ i)
00206 {
00207 const numType crit = theMap. criticalPoint (i);
00208 const numType left = crit - delta;
00209 const numType right = crit + delta;
00210 if ((left <= coarse [prev]) ||
00211 (coarse [coarseCount] <= right))
00212 {
00213 throw "Too large critical neighborhood requested.";
00214 }
00215 int n = prev + static_cast<int> (coarseCount / width *
00216 (left - coarse [prev]));
00217 if (n <= prev)
00218 n = prev + 1;
00219 if (coarseCount <= n + 1)
00220 throw "Too few partition intervals requested.";
00221 coarse [n] = left;
00222 fillUniform (coarse, prev, n);
00223 leftPoints. push_back (prev);
00224 rightPoints. push_back (n);
00225 coarse [n + 1] = right;
00226 prev = n + 1;
00227 }
00228 fillUniform (coarse, prev, coarseCount);
00229 leftPoints. push_back (prev);
00230 rightPoints. push_back (coarseCount);
00231
00232
00233 if (false && sbug. show)
00234 {
00235 sbug << "Coarse partition (" << (coarseCount + 1) <<
00236 " points):\n";
00237 for (int i = 0; i <= coarseCount; ++ i)
00238 sbug << "\t" << coarse [i] << "\n";
00239 }
00240
00241
00242 std::vector<numType> weights (coarseCount);
00243 int nPoints = leftPoints. size ();
00244 int cur = 0;
00245 numType sumWeights = 0;
00246 const numType widthScale = width / widthFraction;
00247 for (int n = 0; n < nPoints; ++ n)
00248 {
00249 int left = leftPoints [n];
00250 int right = rightPoints [n];
00251 for (int i = left; i < right; ++ i)
00252 {
00253 numType midPoint = (coarse [i] + coarse [i + 1]) / 2;
00254 numType weight = 0;
00255 for (int curInd = 0; curInd < maxIndex; ++ curInd)
00256 {
00257 numType influence = exp (-dist (midPoint,
00258 images [curInd]) / widthScale);
00259 if (iterates [curInd])
00260 {
00261 influence /= iterCoef *
00262 iterates [curInd];
00263 }
00264 weight += influence;
00265 }
00266 sumWeights += weight;
00267 weights [cur] = weight;
00268 ++ cur;
00269
00270
00271 if (false && sbug. show)
00272 {
00273 sbug << "Weight of " << midPoint << " = " <<
00274 weight << "\n";
00275 }
00276 }
00277 }
00278
00279
00280 this -> allocate (partCount);
00281
00282
00283
00284
00285 int coarseCur = 0;
00286 int partCur = 0;
00287 int nRemaining = partCount - coarseCount;
00288 for (int n = 0; n < nPoints; ++ n)
00289 {
00290 int left = leftPoints [n];
00291 int right = rightPoints [n];
00292 for (int i = left; i < right; ++ i)
00293 {
00294
00295 bool theLastInterval = (i == right - 1) &&
00296 (n == nPoints - 1);
00297
00298 int nInsert = static_cast<int>
00299 ((partCount - coarseCount) *
00300 weights [coarseCur] / sumWeights + 0.5);
00301 if ((nRemaining < nInsert) || theLastInterval)
00302 nInsert = nRemaining;
00303 nRemaining -= nInsert;
00304
00305
00306 if (false && sbug. show)
00307 {
00308 sbug << "Inserting " << nInsert <<
00309 " points into " <<
00310 i << " of [" << left << ", " <<
00311 right << "], " << nRemaining <<
00312 " remaining.\n";
00313 }
00314
00315
00316 (*this) [partCur] = coarse [i];
00317 (*this) [partCur + nInsert + 1] = coarse [i + 1];
00318 fillUniform (*this, partCur, partCur + nInsert + 1);
00319 partCur += nInsert + 1;
00320 ++ coarseCur;
00321 }
00322
00323
00324 if (n != nPoints - 1)
00325 {
00326 if (false && sbug. show)
00327 {
00328 sbug << "*Critical: " <<
00329 (*this) [partCur] << "\n";
00330 }
00331
00332 this -> addCritical (partCur);
00333 ++ partCur;
00334 }
00335 }
00336
00337 return;
00338 }
00339
00340
00341 }
00342
00343 #endif // _partcrit_h_
00344
00345
00346