matcharr.h

Go to the documentation of this file.
00001 /////////////////////////////////////////////////////////////////////////////
00002 /// @file matcharr.h
00003 ///
00004 /// Array for matching Morse decompositions.
00005 /// This file defines a class for storing a multi-dimensional array
00006 /// whose entries can be efficiently joined into chains which define
00007 /// separate classes of matching entries.
00008 ///
00009 /// @author Pawel Pilarczyk
00010 /////////////////////////////////////////////////////////////////////////////
00011 
00012 // Copyright (C) 1997-2008 by Pawel Pilarczyk.
00013 //
00014 // This file is part of my research software package.  This is free software;
00015 // you can redistribute it and/or modify it under the terms of the GNU
00016 // General Public License as published by the Free Software Foundation;
00017 // either version 2 of the License, or (at your option) any later version.
00018 //
00019 // This software is distributed in the hope that it will be useful,
00020 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00021 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00022 // GNU General Public License for more details.
00023 //
00024 // You should have received a copy of the GNU General Public License along
00025 // with this software; see the file "license.txt".  If not, write to the
00026 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00027 // MA 02111-1307, USA.
00028 
00029 // Started on November 16, 2006. Last revision: February 19, 2008.
00030 
00031 
00032 #ifndef _CMGRAPHS_MATCHARR_H_
00033 #define _CMGRAPHS_MATCHARR_H_
00034 
00035 
00036 // include some standard C++ header files
00037 #include <iostream>
00038 #include <fstream>
00039 #include <string>
00040 #include <sstream>
00041 #include <vector>
00042 #include <map>
00043 #include <algorithm>
00044 #include <cstring>
00045 
00046 // include selected header files from the CHomP library
00047 #include "chomp/system/config.h"
00048 #include "chomp/system/textfile.h"
00049 
00050 
00051 // --------------------------------------------------
00052 // ------------------- MATCHARRAY -------------------
00053 // --------------------------------------------------
00054 
00055 /// A multi-dimensional array with links forward/backward between
00056 /// the entries. Note that the type of integers
00057 /// provided as template's argument must be large enough
00058 /// to allow indexing of all the entries in a linear array.
00059 template <class CoordType, class IntType>
00060 class MatchArray
00061 {
00062 public:
00063         /// The only allowed constructor in which the size of the array
00064         /// and its dimension must be given.
00065         /// Optionally the coordinates of the minimal corner may be provided.
00066         MatchArray (int _dim, const CoordType *_sizes,
00067                 const CoordType *_corner = 0);
00068 
00069         /// The destructor.
00070         ~MatchArray ();
00071 
00072         /// Joins the chains corresponding to the two parameter n-tuples.
00073         void join (const CoordType *x, const CoordType *y);
00074 
00075         /// Checks if the two parameters have already been joined, that is,
00076         /// if they belong to the same chain.
00077         /// Returns "true" if yes, "false" if not.
00078         bool joined (const CoordType *x, const CoordType *y) const;
00079 
00080         /// Saves the equivalence classes larger than 1 element
00081         /// to the provided vector of vectors (the classes are appended).
00082         /// The type of coordinates of the cube type must match "CoordType".
00083         template <class CubeType>
00084         void saveClasses (std::vector<std::vector<CubeType> > &matchClasses)
00085                 const;
00086 
00087         /// Saves the sets to separate files. Sorts the sets by their size.
00088         void saveSets (const char *prefix) const;
00089 
00090 private:
00091         /// The copy constructor is not allowed.
00092         MatchArray (const MatchArray<CoordType,IntType> &a);
00093 
00094         /// The assignment operator is not allowed.
00095         MatchArray &operator = (const MatchArray<CoordType,IntType> &a);
00096 
00097         /// Backward links for chains.
00098         IntType *link1;
00099 
00100         /// Forward links for chains.
00101         IntType *link2;
00102 
00103         /// The unique number for each chain. This is stored here
00104         /// to speed up the verification if two boxes are in the same chain.
00105         IntType *num;
00106 
00107         /// The size of the multi-dimensional array in each direction.
00108         CoordType *sizes;
00109 
00110         /// The coordinates of the minimal corner of the array if any.
00111         CoordType *corner;
00112 
00113         /// The dimension of the array.
00114         int dim;
00115 
00116         /// The length of the allocated memory arrays.
00117         int length;
00118 
00119         /// Translates a flat offset array into a multidimensional one.
00120         void link2coords (IntType link, CoordType *x) const;
00121 
00122         /// Computes the memory offset that corresponds to the given
00123         /// multidimensional position in the array.
00124         IntType coords2link (const CoordType *x) const;
00125 
00126         /// A small class whose objects store an IntType object
00127         /// and an int value. The objects are compared by the value.
00128         struct pair2
00129         {
00130                 pair2 (IntType _x, int _value): x (_x), value (_value) {}
00131                 IntType x;
00132                 int value;
00133                 bool operator < (const pair2 &other) const
00134                 {
00135                         return (this -> value < other. value);
00136                 }
00137         }; /* struct pair2 */
00138 
00139         /// Retrieves a set of first elements of all the chains
00140         /// which have at least two elements.
00141         /// The list is sorted according to the lengths of the chains
00142         /// in the descending order.
00143         void getChains (std::vector <MatchArray<CoordType,IntType>::pair2>
00144                 &chains) const;
00145 
00146         /// Saves one set to a file.
00147         void saveSet (const char *prefix, int counter, int pos,
00148                 CoordType *workspace, int ndigits) const;
00149 
00150         /// Joins two sets, given the offsets in the flat arrays.
00151         void join (IntType xpos, IntType ypos);
00152 
00153 }; /* class MatchArray */
00154 
00155 // --------------------------------------------------
00156 
00157 template <class CoordType, class IntType>
00158 inline MatchArray<CoordType,IntType>::MatchArray (int _dim,
00159         const CoordType *_sizes, const CoordType *_corner):
00160         link1 (0), link2 (0), num (0), sizes (0), corner (0),
00161         dim (_dim), length (0)
00162 {
00163         if (!_sizes)
00164                 throw "Undefined array sizes.";
00165         if (_dim <= 0)
00166                 throw "Non-positive dimension.";
00167         sizes = new CoordType [dim];
00168         length = 1;
00169         for (int i = 0; i < dim; ++ i)
00170         {
00171                 sizes [i] = _sizes [i];
00172                 long prevLength = length;
00173                 length *= sizes [i];
00174                 if (length < prevLength)
00175                         throw "Too large matching array requested.";
00176         }
00177         if (_corner)
00178         {
00179                 corner = new CoordType [dim];
00180                 for (int i = 0; i < dim; ++ i)
00181                         corner [i] = _corner [i];
00182         }
00183         link1 = new IntType [length];
00184         link2 = new IntType [length];
00185         num = new IntType [length];
00186         for (int offset = 0; offset < length; ++ offset)
00187         {
00188                 num [offset] = offset;
00189                 link1 [offset] = -1;
00190                 link2 [offset] = -1;
00191         }
00192 
00193         if (false) // DEBUG
00194         {
00195                 CoordType *c = new CoordType [dim];
00196                 for (int i = 0; i < dim; ++ i)
00197                         c [i] = corner ? corner [i] : 0;
00198                 for (int offset = 0; offset < length; ++ offset)
00199                 {
00200                         // verify the correctness of the entry
00201                         if (coords2link (c) != offset)
00202                                 chomp::homology::sbug << "Mismatch at "
00203                                         "array offset " << offset <<
00204                                         ": " << coords2link (c) << ".\n";
00205                         // increase the multi-counter
00206                         int i = 0;
00207                         while (1)
00208                         {
00209                                 if (++ c [i] < sizes [i] +
00210                                         (corner ? corner [i] : 0))
00211                                         break;
00212                                 c [i] = corner ? corner [i] : 0;
00213                                 ++ i;
00214                                 if (i >= dim)
00215                                         break;
00216                         }
00217                 }
00218                 delete [] c;
00219         //      chomp::homology::sbug << "Note: Array offsets verified "
00220         //              "successfully.\n";
00221         }
00222 
00223         return;
00224 } /* MatchArray::MatchArray */
00225 
00226 template <class CoordType, class IntType>
00227 inline MatchArray<CoordType,IntType>::~MatchArray ()
00228 {
00229         if (corner)
00230                 delete [] corner;
00231         delete [] sizes;
00232         delete [] num;
00233         delete [] link2;
00234         delete [] link1;
00235         return;
00236 } /* MatchArray::~MatchArray */
00237 
00238 template <class CoordType, class IntType>
00239 inline MatchArray<CoordType,IntType> &MatchArray<CoordType,IntType>::
00240 	operator = (const MatchArray &)
00241 {
00242         throw "Array assignment operator not allowed.";
00243         return *this;
00244 } /* MatchArray::operator = */
00245 
00246 template <class CoordType, class IntType>
00247 inline MatchArray<CoordType,IntType>::MatchArray
00248         (const MatchArray<CoordType,IntType> &)
00249 {
00250         throw "Array copy constructor not allowed.";
00251         return;
00252 } /* MatchArray::MatchArray */
00253 
00254 // --------------------------------------------------
00255 
00256 template <class CoordType, class IntType>
00257 inline void MatchArray<CoordType,IntType>::link2coords (IntType link,
00258         CoordType *x) const
00259 {
00260         int n = link;
00261         for (int i = 0; i < dim - 1; ++ i)
00262         {
00263                 x [i] = n % sizes [i] + (corner ? corner [i] : 0);
00264                 n /= sizes [i];
00265         }
00266         x [dim - 1] = n % sizes [dim - 1] + (corner ? corner [dim - 1] : 0);
00267         return;
00268 } /* MatchArray::link2coords */
00269 
00270 template <class CoordType, class IntType>
00271 inline IntType MatchArray<CoordType,IntType>::coords2link
00272         (const CoordType *x) const
00273 {
00274         IntType n = x [dim - 1] - (corner ? corner [dim - 1] : 0);
00275         for (int i = dim - 2; i >= 0; -- i)
00276         {
00277                 n *= sizes [i];
00278                 n += x [i] - (corner ? corner [i] : 0);
00279         }
00280         return n;
00281 } /* MatchArray::coords2link */
00282 
00283 template <class CoordType, class IntType>
00284 inline void MatchArray<CoordType,IntType>::join (IntType xpos, IntType ypos)
00285 {
00286         if (num [xpos] == num [ypos])
00287                 return;
00288         IntType newnum = num [xpos];
00289         while (link1 [xpos] >= 0)
00290                 xpos = link1 [xpos];
00291         while (link2 [ypos] >= 0)
00292                 ypos = link2 [ypos];
00293         link1 [xpos] = ypos;
00294         link2 [ypos] = xpos;
00295         while (1)
00296         {
00297                 num [ypos] = newnum;
00298                 if (link1 [ypos] < 0)
00299                         break;
00300                 ypos = link1 [ypos];
00301         }
00302         return;
00303 } /* MatchArray::join */
00304 
00305 // --------------------------------------------------
00306 
00307 template <class CoordType, class IntType>
00308 inline void MatchArray<CoordType,IntType>::saveSet (const char *prefix,
00309         int counter, int pos, CoordType *workspace, int ndigits) const
00310 {
00311         // create the file name and open the file
00312         std::ostringstream fname;
00313         fname << prefix;
00314         int ten = 1;
00315         for (int i = 1; i < ndigits; ++ i)
00316                 ten *= 10;
00317         while (counter < ten)
00318         {
00319                 fname << '0';
00320                 ten /= 10;
00321         }
00322         fname << counter << ".cub";
00323         std::ofstream out (fname. str (). c_str ());
00324 
00325         // go to the beginning of the list
00326         while (link1 [pos] >= 0)
00327                 pos = link1 [pos];
00328 
00329         // write all the elements of the list to the file
00330         while (pos >= 0)
00331         {
00332                 link2coords (pos, workspace);
00333                 for (int i = 0; i < dim; ++ i)
00334                         out << (i ? "," : "(") << workspace [i];
00335                 out << ")\n";
00336         //      link1 [x] [y] = -1;
00337         //      IntType link = link2 [pos];
00338         //      link2 [pos] = -1;
00339         //      pos = link;
00340                 pos = link2 [pos];
00341         }
00342         return;
00343 } /* MatchArray::saveSet */
00344 
00345 // --------------------------------------------------
00346 
00347 //template <class CoordType, class IntType>
00348 //inline bool operator <
00349 //      (const typename MatchArray<CoordType,IntType>::pair2 &x,
00350 //      const typename MatchArray<CoordType,IntType>::pair2 &y)
00351 //{
00352 //      return (x. value < y. value);
00353 //} /* operator < */
00354 
00355 template <class CoordType, class IntType>
00356 inline void MatchArray<CoordType,IntType>::join (const CoordType *x,
00357         const CoordType *y)
00358 {
00359         join (coords2link (x), coords2link (y));
00360         return;
00361 } /* MatchArray::join */
00362 
00363 template <class CoordType, class IntType>
00364 inline bool MatchArray<CoordType,IntType>::joined (const CoordType *x,
00365         const CoordType *y) const
00366 {
00367         int xpos = coords2link (x);
00368         if (xpos < 0)
00369                 return false;
00370         int ypos = coords2link (y);
00371         if (ypos < 0)
00372                 return false;
00373         return (num [xpos] == num [ypos]);
00374 } /* MatchArray::joined */
00375 
00376 template <class CoordType, class IntType>
00377 inline void MatchArray<CoordType,IntType>::getChains
00378         (std::vector<MatchArray<CoordType,IntType>::pair2> &chains) const
00379 {
00380         // create a list of chain beginnings
00381         chomp::homology::sbug << "Analyzing the sets of matched boxes... ";
00382         for (IntType cur = 0; cur < length; ++ cur)
00383         {
00384                 if ((link1 [cur] < 0) && (link2 [cur] >= 0))
00385                 {
00386                         int setsize = 0;
00387                         IntType pos = cur;
00388                         while (pos >= 0)
00389                         {
00390                                 ++ setsize;
00391                                 pos = link2 [pos];
00392                         }
00393                         chains. push_back (pair2 (cur, setsize));
00394                 }
00395         }
00396         chomp::homology::sbug << chains. size () << " nontrivial classes.\n";
00397 
00398         // sort the list of chain beginnings
00399         std::sort (chains. begin (), chains. end ());
00400 
00401         return;
00402 } /* MatchArray::getChains */
00403 
00404 template <class CoordType, class IntType>
00405 inline void MatchArray<CoordType,IntType>::saveSets (const char *prefix)
00406         const
00407 {
00408         // create a list of chain beginnings
00409         std::vector<pair2> sets;
00410         this -> getChains (sets);
00411 
00412         // compute the number of digits to be used in the file names
00413         int ndigits = 1;
00414         unsigned ten = 10;
00415         while (sets. size () >= ten)
00416         {
00417                 ++ ndigits;
00418                 ten *= 10;
00419         }
00420 
00421         // write the sets to files
00422         int counter = 0;
00423         chomp::homology::sbug << "Saving the nontrivial "
00424                 "equivalence classes... ";
00425         CoordType *workspace = new CoordType [dim];
00426         for (int i = sets. size () - 1; i >= 0; -- i)
00427         {
00428                 saveSet (prefix, ++ counter, sets [i]. x, workspace,
00429                         ndigits);
00430         }
00431         delete [] workspace;
00432         chomp::homology::sout << "Done.\n";
00433         
00434         return;
00435 } /* MatchArray::saveSets */
00436 
00437 template <class CoordType, class IntType>
00438 template <class CubeType>
00439 inline void MatchArray<CoordType,IntType>::saveClasses
00440         (std::vector<std::vector<CubeType> > &matchClasses) const
00441 {
00442         // create a list of chain beginnings
00443         std::vector<pair2> sets;
00444         getChains (sets);
00445 
00446         // create vectors of cubes and add them to the given one
00447         CoordType *coord = new CoordType [dim];
00448         std::vector<CubeType> emptyVector;
00449         for (int i = sets. size () - 1; i >= 0; -- i)
00450         {
00451                 // go to the beginning of the list
00452                 IntType pos = sets [i]. x;
00453                 while (link1 [pos] >= 0)
00454                         pos = link1 [pos];
00455 
00456                 // create a vector with all the elements of the list
00457                 matchClasses. push_back (emptyVector);
00458                 std::vector<CubeType> &vect =
00459                         matchClasses [matchClasses. size () - 1];
00460                 vect. resize (sets [i]. value);
00461                 int j = 0;
00462                 while (pos >= 0)
00463                 {
00464                         link2coords (pos, coord);
00465                         vect [j ++] = CubeType (coord, dim);
00466                         pos = link2 [pos];
00467                 }
00468         }
00469         delete [] coord;
00470         return;
00471 } /* MatchArray::saveClasses */
00472 
00473 
00474 #endif // _CMGRAPHS_MATCHARR_H
00475 

Generated on Sun Mar 28 17:47:57 2010 for The Conley-Morse Graphs Software by  doxygen 1.5.3