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

partderiv.h

Go to the documentation of this file.
00001 /// @addtogroup unifexp
00002 /// @{
00003 
00004 /////////////////////////////////////////////////////////////////////////////
00005 ///
00006 /// @file partderiv.h
00007 ///
00008 /// This file contains the definition of a special partition type in which
00009 /// the size of the intervals on which the derivative of f is large
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 November 14, 2007. Last revision: November 14, 2007.
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" // for debugging only
00042 #include "parttype.h"
00043 
00044 
00045 namespace unifexp {
00046 
00047 // --------------------------------------------------
00048 // -------------- derivative partition --------------
00049 // --------------------------------------------------
00050 
00051 /// A derivative-based partition type.
00052 /// The complement of the critical neighborhood is divided into intervals
00053 /// of approximately the same length.
00054 template <class numType>
00055 class partDerivative: public partType<numType>
00056 {
00057 public:
00058         /// Returns the name of the object.
00059         std::string name () const;
00060 
00061         /// Creates a partition based on the given map, the requested
00062         /// number of elements in the partition, and the width of the
00063         /// critical neighborhood.
00064         void create (const mapType<numType> &theMap, int partCount,
00065                 const numType &delta);
00066 
00067 private:
00068         /// Fills part of the partition table between the given entries
00069         /// in a uniform way based on the values at these ends.
00070         template <class vectType>
00071         static void fillUniform (vectType &tab, int first, int last);
00072 
00073 }; /* class partDerivative */
00074 
00075 // --------------------------------------------------
00076 
00077 template <class numType>
00078 std::string partDerivative<numType>::name () const
00079 {
00080         return std::string ("derivative");
00081 } /* partDerivative::name */
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 } /* partDerivative::fillUniform */
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         // the fraction of all partition points to use for a coarse partition
00102         const int coarseFraction = 10;
00103 
00104         // make sure that the number of partition elements is large enough
00105         // to create a reasonable partition
00106         int nCrit = theMap. countCritical ();
00107         if (partCount < 2 * coarseFraction * (nCrit + 1))
00108                 throw "Too small derivative-based partition requested.";
00109 
00110         // prepare a coarse partition and fill in the two extreme bounds
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         // compute the width of the entire area to partition, that is,
00117         // the sum of the widths of intervals in the domain of the map
00118         // after the critical neighborhood intervals have been removed
00119         numType width = coarse [coarseCount] - coarse [0] -
00120                 2 * delta * nCrit;
00121         if (width <= 0)
00122                 throw "Too wide critical neighborhood requested.";
00123 
00124         // create an initial coarse uniform partition
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         // show the coarse partition
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         // compute the weights for each interval in the coarse partition
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                         // show the weight of the midpoint
00186                         if (false && sbug. show)
00187                         {
00188                                 sbug << "Weight of " << midPoint << " = " <<
00189                                         weight << "\n";
00190                         }
00191                 }
00192         }
00193 
00194         // allocate the full partition array
00195         this -> allocate (partCount);
00196 
00197         // create the full partition as a refinement of the coarse partition
00198         // by subdividing each coarse interval uniformly into a number of
00199         // intervals proportional to the weight associated with it
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                         // remember if this is the last interval to fill in
00210                         bool theLastInterval = (i == right - 1) &&
00211                                 (n == nPoints - 1);
00212                         // compute the number of points to insert
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                         // show how many points are inserted to this interval
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                         // fill in the bounds of the partition segment
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                 // add to the list of critical intervals
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 } /* partDerivative::create */
00254 
00255 
00256 } // namespace unifexp
00257 
00258 #endif // _partderiv_h_
00259 
00260 /// @}
00261 

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