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

partcrit.h

Go to the documentation of this file.
00001 /// @addtogroup unifexp
00002 /// @{
00003 
00004 /////////////////////////////////////////////////////////////////////////////
00005 ///
00006 /// @file partcrit.h
00007 ///
00008 /// This file contains the definition of a special partition type in which
00009 /// the size of the intervals close to a few images of critical points
00010 /// is much smaller than in other areas.
00011 ///
00012 /// @author Pawel Pilarczyk
00013 ///
00014 /////////////////////////////////////////////////////////////////////////////
00015 
00016 // Copyright (C) 2007 by Pawel Pilarczyk.
00017 //
00018 // This file is part of my research program package.  This 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 software 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 on August 25, 2007. Last revision: August 29, 2007.
00034 
00035 #ifndef _partcrit_h_
00036 #define _partcrit_h_
00037 
00038 #include <vector>
00039 #include <string>
00040 #include "chomp/system/textfile.h" // for debugging only
00041 #include "parttype.h"
00042 
00043 
00044 namespace unifexp {
00045 
00046 // --------------------------------------------------
00047 // --------------- critical partition ----------------
00048 // --------------------------------------------------
00049 
00050 /// A critical orbit based partition type.
00051 /// The complement of the critical neighborhood is divided into intervals
00052 /// of approximately the same length.
00053 template <class numType>
00054 class partCritical: public partType<numType>
00055 {
00056 public:
00057         /// Returns the name of the object.
00058         std::string name () const;
00059 
00060         /// Creates a partition based on the given map, the requested
00061         /// number of elements in the partition, and the width of the
00062         /// critical neighborhood.
00063         void create (const mapType<numType> &theMap, int partCount,
00064                 const numType &delta);
00065 
00066 private:
00067         /// A small helper functin that computes the distance
00068         /// between two numbers.
00069         static numType dist (const numType &x, const numType &y);
00070 
00071         /// Fills part of the partition table between the given entries
00072         /// in a uniform way based on the values at these ends.
00073         template <class vectType>
00074         static void fillUniform (vectType &tab, int first, int last);
00075 
00076 }; /* class partCritical */
00077 
00078 // --------------------------------------------------
00079 
00080 template <class numType>
00081 std::string partCritical<numType>::name () const
00082 {
00083         return std::string ("critical");
00084 } /* partCritical::name */
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 } /* partCritical::dist */
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 } /* partCritical::fillUniform */
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         // some parameters of this partition which can be tweaked
00113         const int coarseFraction = 10;
00114         const int nImages = 30;
00115         const int widthFraction = 100;
00116         const int iterCoef = 3;
00117 
00118         // make sure that the number of partition elements is large enough
00119         // to create a reasonable partition
00120         int nCrit = theMap. countCritical ();
00121         if (partCount < 2 * coarseFraction * (nCrit + 1))
00122                 throw "Too small critical partition requested.";
00123 
00124         // prepare a coarse partition and fill in the two extreme bounds
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         // compute the width of the entire area to partition, that is,
00131         // the sum of the widths of intervals in the domain of the map
00132         // after the critical neighborhood intervals have been removed
00133         numType width = coarse [coarseCount] - coarse [0] -
00134                 2 * delta * nCrit;
00135         if (width <= 0)
00136                 throw "Too wide critical neighborhood requested.";
00137 
00138         // compute several images of all the critical points
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                 // update the iterate number
00148                 if (curIndex == iterateIndex)
00149                 {
00150                         ++ iterate;
00151                         iterateIndex = maxIndex;
00152                 }
00153 
00154                 // take one of the critical points or one of their images
00155                 numType prevPoint = (curIndex < 0) ?
00156                         theMap. criticalPoint (-curIndex - 1) :
00157                         images [curIndex];
00158                 ++ curIndex;
00159 
00160                 // compute the image of this point
00161                 numType image1, image2;
00162                 theMap. image (prevPoint, prevPoint, image1, image2);
00163                 numType image = (image1 == image2) ? image1 :
00164                         ((image1 + image2) / 2);
00165 
00166                 // make sure that it is inside the domain bounds
00167                 if ((image < theMap. leftBound ()) ||
00168                         (theMap. rightBound () < image))
00169                 {
00170                         continue;
00171                 }
00172 
00173                 // make sure that it is not inside any critical neighborhood
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                 // add this image to the list
00187                 images [maxIndex] = image;
00188                 iterates [maxIndex] = iterate;
00189                 ++ maxIndex;
00190         }
00191 
00192         // show the critical points and their iterates
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         // create an initial coarse uniform partition
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         // show the coarse partition
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         // compute the weights for each interval in the coarse partition
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                         // show the weight of the midpoint
00271                         if (false && sbug. show)
00272                         {
00273                                 sbug << "Weight of " << midPoint << " = " <<
00274                                         weight << "\n";
00275                         }
00276                 }
00277         }
00278 
00279         // allocate the full partition array
00280         this -> allocate (partCount);
00281 
00282         // create the full partition as a refinement of the coarse partition
00283         // by subdividing each coarse interval uniformly into a number of
00284         // intervals proportional to the weight associated with it
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                         // remember if this is the last interval to fill in
00295                         bool theLastInterval = (i == right - 1) &&
00296                                 (n == nPoints - 1);
00297                         // compute the number of points to insert
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                         // show how many points are inserted to this interval
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                         // fill in the bounds of the partition segment
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                 // add to the list of critical intervals
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 } /* partCritical::create */
00339 
00340 
00341 } // namespace unifexp
00342 
00343 #endif // _partcrit_h_
00344 
00345 /// @}
00346 

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