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 _partderiv_h_
00036 #define _partderiv_h_
00037
00038 #include <vector>
00039 #include <string>
00040 #include <cmath>
00041 #include "chomp/system/textfile.h"
00042 #include "parttype.h"
00043
00044
00045 namespace unifexp {
00046
00047
00048
00049
00050
00051
00052
00053
00054 template <class numType>
00055 class partDerivative: public partType<numType>
00056 {
00057 public:
00058
00059 std::string name () const;
00060
00061
00062
00063
00064 void create (const mapType<numType> &theMap, int partCount,
00065 const numType &delta);
00066
00067 private:
00068
00069
00070 template <class vectType>
00071 static void fillUniform (vectType &tab, int first, int last);
00072
00073 };
00074
00075
00076
00077 template <class numType>
00078 std::string partDerivative<numType>::name () const
00079 {
00080 return std::string ("derivative");
00081 }
00082
00083 template <class numType>
00084 template <class vectType>
00085 void partDerivative<numType>::fillUniform (vectType &tab, int first, int last)
00086 {
00087 const numType &numFirst = tab [first];
00088 const numType &numLast = tab [last];
00089 const numType numDiff = (numLast - numFirst) / (last - first);
00090 for (int i = first + 1; i < last; ++ i)
00091 tab [i] = numFirst + (i - first) * numDiff;
00092 return;
00093 }
00094
00095 template <class numType>
00096 void partDerivative<numType>::create (const mapType<numType> &theMap,
00097 int partCount, const numType &delta)
00098 {
00099 using chomp::homology::sbug;
00100
00101
00102 const int coarseFraction = 10;
00103
00104
00105
00106 int nCrit = theMap. countCritical ();
00107 if (partCount < 2 * coarseFraction * (nCrit + 1))
00108 throw "Too small derivative-based partition requested.";
00109
00110
00111 const int coarseCount = partCount / coarseFraction;
00112 std::vector<numType> coarse (coarseCount + 1);
00113 coarse [0] = theMap. leftBound ();
00114 coarse [coarseCount] = theMap. rightBound ();
00115
00116
00117
00118
00119 numType width = coarse [coarseCount] - coarse [0] -
00120 2 * delta * nCrit;
00121 if (width <= 0)
00122 throw "Too wide critical neighborhood requested.";
00123
00124
00125 std::vector<int> leftPoints;
00126 std::vector<int> rightPoints;
00127 int prev = 0;
00128 for (int i = 0; i < nCrit; ++ i)
00129 {
00130 const numType crit = theMap. criticalPoint (i);
00131 const numType left = crit - delta;
00132 const numType right = crit + delta;
00133 if ((left <= coarse [prev]) ||
00134 (coarse [coarseCount] <= right))
00135 {
00136 throw "Too large critical neighborhood requested.";
00137 }
00138 int n = prev + static_cast<int> (coarseCount / width *
00139 (left - coarse [prev]));
00140 if (n <= prev)
00141 n = prev + 1;
00142 if (coarseCount <= n + 1)
00143 throw "Too few partition intervals requested.";
00144 coarse [n] = left;
00145 fillUniform (coarse, prev, n);
00146 leftPoints. push_back (prev);
00147 rightPoints. push_back (n);
00148 coarse [n + 1] = right;
00149 prev = n + 1;
00150 }
00151 fillUniform (coarse, prev, coarseCount);
00152 leftPoints. push_back (prev);
00153 rightPoints. push_back (coarseCount);
00154
00155
00156 if (false && sbug. show)
00157 {
00158 sbug << "Coarse partition (" << (coarseCount + 1) <<
00159 " points):\n";
00160 for (int i = 0; i <= coarseCount; ++ i)
00161 sbug << "\t" << coarse [i] << "\n";
00162 }
00163
00164
00165 std::vector<numType> weights (coarseCount);
00166 int nPoints = leftPoints. size ();
00167 int cur = 0;
00168 numType sumWeights = 0;
00169 for (int n = 0; n < nPoints; ++ n)
00170 {
00171 int left = leftPoints [n];
00172 int right = rightPoints [n];
00173 for (int i = left; i < right; ++ i)
00174 {
00175 numType midPoint = (coarse [i] + coarse [i + 1]) / 2;
00176 numType y1 = 0, y2 = 0;
00177 theMap. image (midPoint, midPoint, y1, y2);
00178 numType deriv = std::exp (theMap. minLogDerivative
00179 (midPoint, midPoint, y1, y2));
00180 numType weight = std::exp (deriv);
00181 sumWeights += weight;
00182 weights [cur] = weight;
00183 ++ cur;
00184
00185
00186 if (false && sbug. show)
00187 {
00188 sbug << "Weight of " << midPoint << " = " <<
00189 weight << "\n";
00190 }
00191 }
00192 }
00193
00194
00195 this -> allocate (partCount);
00196
00197
00198
00199
00200 int coarseCur = 0;
00201 int partCur = 0;
00202 int nRemaining = partCount - coarseCount;
00203 for (int n = 0; n < nPoints; ++ n)
00204 {
00205 int left = leftPoints [n];
00206 int right = rightPoints [n];
00207 for (int i = left; i < right; ++ i)
00208 {
00209
00210 bool theLastInterval = (i == right - 1) &&
00211 (n == nPoints - 1);
00212
00213 int nInsert = static_cast<int>
00214 ((partCount - coarseCount) *
00215 weights [coarseCur] / sumWeights + 0.5);
00216 if ((nRemaining < nInsert) || theLastInterval)
00217 nInsert = nRemaining;
00218 nRemaining -= nInsert;
00219
00220
00221 if (false && sbug. show)
00222 {
00223 sbug << "Inserting " << nInsert <<
00224 " points into " <<
00225 i << " of [" << left << ", " <<
00226 right << "], " << nRemaining <<
00227 " remaining.\n";
00228 }
00229
00230
00231 (*this) [partCur] = coarse [i];
00232 (*this) [partCur + nInsert + 1] = coarse [i + 1];
00233 fillUniform (*this, partCur, partCur + nInsert + 1);
00234 partCur += nInsert + 1;
00235 ++ coarseCur;
00236 }
00237
00238
00239 if (n != nPoints - 1)
00240 {
00241 if (false && sbug. show)
00242 {
00243 sbug << "*Critical: " <<
00244 (*this) [partCur] << "\n";
00245 }
00246
00247 this -> addCritical (partCur);
00248 ++ partCur;
00249 }
00250 }
00251
00252 return;
00253 }
00254
00255
00256 }
00257
00258 #endif // _partderiv_h_
00259
00260
00261