indxpalg.h

Go to the documentation of this file.
00001 
00002 
00003 
00014 
00015 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00016 //
00017 // This file is part of the Homology Library.  This library is free software;
00018 // you can redistribute it and/or modify it under the terms of the GNU
00019 // General Public License as published by the Free Software Foundation;
00020 // either version 2 of the License, or (at your option) any later version.
00021 //
00022 // This library is distributed in the hope that it will be useful,
00023 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00024 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025 // GNU General Public License for more details.
00026 //
00027 // You should have received a copy of the GNU General Public License along
00028 // with this software; see the file "license.txt".  If not, write to the
00029 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00030 // MA 02111-1307, USA.
00031 
00032 // Started on May 17, 2006. Last revision: August 30, 2006.
00033 
00034 
00035 #ifndef _CHOMP_HOMOLOGY_INDXPALG_H_
00036 #define _CHOMP_HOMOLOGY_INDXPALG_H_
00037 
00038 #include "chomp/homology/cubisets.h"
00039 #include "chomp/cubes/cube.h"
00040 #include "chomp/cubes/cell.h"
00041 #include "chomp/struct/digraph.h"
00042 
00043 #include <iostream>
00044 #include <fstream>
00045 #include <cstdlib>
00046 
00047 namespace chomp {
00048 namespace homology {
00049 
00050 
00051 // --------------------------------------------------
00052 // ------------------- Map Class --------------------
00053 // --------------------------------------------------
00054 
00057 template <class TCube, class TSetOfCubes>
00058 class MapClass
00059 {
00060 public:
00063         const TSetOfCubes &operator () (const TCube &q) const
00064         {
00065                 throw "The map has not been defined.";
00066         }
00067 
00068 }; /* class MapClass */
00069 
00070 
00075 template <class TCube = Cube>
00076 class BufferedMapClass: public MapClass<TCube,hashedset<TCube> >
00077 {
00078 public:
00080         typedef hashedset<TCube> TSetOfCubes;
00081 
00083         typedef typename TCube::CoordType TCoordType;
00084         
00086         typedef int (*map) (const TCoordType *coord,
00087                 double *left, double *right);
00088 
00090         BufferedMapClass (map _f): f (_f) {}
00091 
00094         const TSetOfCubes &operator () (const TCube &q) const;
00095 
00097         mutable mvmap<TCube,TCube> F;
00098 
00099 private:
00101         map f;
00102 
00103 }; /* class BufferedMapClass */
00104 
00105 template <class TCube>
00106 const typename BufferedMapClass<TCube>::TSetOfCubes &
00107         BufferedMapClass<TCube>::operator () (const TCube &q) const
00108 {
00109         // if the image of the cube is already known, then return it
00110         const TSetOfCubes &dom = F. getdomain ();
00111         if (dom. check (q))
00112                 return F (q);
00113 
00114         // determine the dimension
00115         const int dim = q. dim ();
00116         
00117         // compute the image of the cube
00118         TCoordType *coord = new TCoordType [dim];
00119         q. coord (coord);
00120         double *left = new double [dim];
00121         double *right = new double [dim];
00122         f (coord, left, right);
00123         delete [] coord;
00124 
00125         // compute the minimal and maximal corner of the rectangular
00126         // cubical set that covers the computed image of the cube
00127         TCoordType *ileft = new TCoordType [dim];
00128         TCoordType *iright = new TCoordType [dim];
00129         for (int i = 0; i < dim; ++ i)
00130         {
00131                 ileft [i] = static_cast<TCoordType> (left [i]);
00132                 if ((ileft [i] + 1 < left [i]) ||
00133                         (ileft [i] - 1 > left [i]))
00134                         throw "Conversion error: double to coord - "
00135                                 "out of range.";
00136                 for (int j = 0; j < 10; ++ j)
00137                 {
00138                         if (ileft [i] >= left [i])
00139                                 -- ileft [i];
00140                         else
00141                                 break;
00142                 }
00143                 if (ileft [i] >= left [i])
00144                         throw "Outer approximation failure (left).";
00145                 iright [i] = static_cast<TCoordType> (right [i]);
00146                 if ((iright [i] + 1 < right [i]) ||
00147                         (iright [i] - 1 > right [i]))
00148                         throw "Conversion error: double to coord - "
00149                                 "out of range.";
00150                 for (int j = 0; j < 10; ++ j)
00151                 {
00152                         if (iright [i] <= right [i])
00153                                 ++ iright [i];
00154                         else
00155                                 break;
00156                 }
00157                 if (iright [i] <= right [i])
00158                         throw "Outer approximation failure (right).";
00159         }
00160         delete [] right;
00161         delete [] left;
00162 
00163         // create the image of the cube and add all the cubes to it
00164         hashedset<TCube> &img = F [q];
00165         tRectangle<TCoordType> r (ileft, iright, dim);
00166         const TCoordType *c;
00167         while ((c = r. get ()) != 0)
00168                 img. add (TCube (c, dim));
00169         delete [] iright;
00170         delete [] ileft;
00171 
00172         // return the image of the cube
00173         return F (q);
00174 } /* operator () */
00175 
00176 template <class TCube>
00177 std::ostream &operator << (std::ostream &out,
00178         const BufferedMapClass<TCube> &map)
00179 {
00180         out << map. F;
00181         return out;
00182 } /* operator << */
00183 
00184 
00185 // --------------------------------------------------
00186 // ------------------ Neighborhood ------------------
00187 // --------------------------------------------------
00188 
00190 template <class TSetOfCubes>
00191 int neighborhood (const TSetOfCubes &X, TSetOfCubes &result)
00192 {
00193         // extract the necessary types and constants
00194         using namespace chomp::homology;
00195         typedef typename TSetOfCubes::value_type cubetype;
00196         typedef typename cubetype::CoordType coordtype;
00197         typedef tRectangle<coordtype> rectangle;
00198         const int maxdim = cubetype::MaxDim;
00199 
00200         // create arrays for the corners of a rectangle around each cube
00201         coordtype mincoord [maxdim], maxcoord [maxdim];
00202 
00203         // for all the cubes in X
00204         int_t ncount = X. size ();
00205         for (int_t n = 0; n < ncount; ++ n)
00206         {
00207                 // get the coordinates of the cube
00208                 int dim = X [n]. dim ();
00209                 X [n]. coord (mincoord);
00210 
00211                 // prepare the corners of a rectangle for the cube
00212                 // and its neighbors
00213                 for (int i = 0; i < dim; ++ i)
00214                 {
00215                         maxcoord [i] = mincoord [i];
00216                         ++ maxcoord [i];
00217                         ++ maxcoord [i];
00218                         -- mincoord [i];
00219                 }
00220 
00221                 // add cubes from the rectangle to the resulting set
00222                 rectangle r (mincoord, maxcoord, dim);
00223                 const coordtype *c;
00224                 while ((c = r. get ()) != 0)
00225                         result. add (cubetype (c, dim));
00226         }
00227         return 0;
00228 } /* neighborhood */
00229 
00230 
00231 // --------------------------------------------------
00232 // ----------------- Invariant Part -----------------
00233 // --------------------------------------------------
00234 
00238 template <class TSetOfCubes, class TMap>
00239 void invariantpart (TSetOfCubes &X, const TMap &F, TSetOfCubes &result)
00240 {
00241         // do nothing if the set X is empty
00242         int_t ncount = X. size ();
00243         if (!ncount)
00244                 return;
00245 
00246         // create a digraph of the map
00247         diGraph<> g;
00248         for (int_t n = 0; n < ncount; ++ n)
00249         {
00250                 g. addVertex ();
00251                 const TSetOfCubes &img = F (X [n]);
00252                 int_t icount = img. size ();
00253                 for (int_t i = 0; i < icount; ++ i)
00254                 {
00255                         int_t number = X. getnumber (img [i]);
00256                         if (number < 0)
00257                                 continue;
00258                         g. addEdge (number);
00259                 }
00260         }
00261 
00262         // compute the chain recurrent set of the graph
00263         // and remember the transposed graph
00264         multitable<int_t> compVertices, compEnds;
00265         diGraph<> gT;
00266         int_t count = SCC (g, compVertices, compEnds,
00267                 static_cast<diGraph<> *> (0), &gT);
00268 
00269         // retrieve vertices that can be reached from the chain recurrent set
00270         int_t nVertices = ncount;
00271         char *forward = new char [nVertices];
00272         for (int_t i = 0; i < nVertices; ++ i)
00273                 forward [i] = 0;
00274         for (int_t cur = 0; cur < count; ++ cur)
00275         {
00276                 g. DFScolor (forward, '\1',
00277                         compVertices [cur ? compEnds [cur - 1] :
00278                         static_cast<int_t> (0)]);
00279         }
00280 
00281         // retrieve vertices that can reach the chein recurrent set
00282         char *backward = new char [nVertices];
00283         for (int_t i = 0; i < nVertices; ++ i)
00284                 backward [i] = 0;
00285         for (int_t cur = 0; cur < count; ++ cur)
00286         {
00287                 gT. DFScolor (backward, '\1',
00288                         compVertices [cur ? compEnds [cur - 1] :
00289                         static_cast<int_t> (0)]);
00290         }
00291 
00292         // compute the new set of cubes
00293         for (int_t i = 0; i < nVertices; ++ i)
00294                 if (forward [i] && backward [i])
00295                         result. add (X [i]);
00296 
00297         // clean the memory and return
00298         delete [] backward;
00299         delete [] forward;
00300         return;
00301 } /* invariantpart */
00302 
00303 
00304 // --------------------------------------------------
00305 // ------------------- inclusion --------------------
00306 // --------------------------------------------------
00307 
00309 template <class HSet>
00310 bool inclusion (const HSet &X, const HSet &Y)
00311 {
00312         int_t countX = X. size ();
00313         if (countX && Y. empty ())
00314                 return false;
00315 
00316         for (int_t i = 0; i < countX; ++ i)
00317                 if (!Y. check (X [i]))
00318                         return false;
00319         return true;
00320 } /* inclusion */
00321 
00322 
00323 // --------------------------------------------------
00324 // ------------------ Index Pair M ------------------
00325 // --------------------------------------------------
00326 
00328 template <class TSetOfCubes, class TMap>
00329 int ExitSetM (const TSetOfCubes &N, const TSetOfCubes &Q1,
00330         const TMap &F, TSetOfCubes &resultQ2)
00331 {
00332         // compute Q2 := (F (Q1 \cup Q2) \setminus Q1) \cap N
00333         int_t countQ1 = Q1. size ();
00334         int_t n = 0;
00335 
00336         // for all the cubes in Q1 and Q2
00337         while (n < countQ1 + resultQ2. size ())
00338         {
00339                 // compute the image of the cube
00340                 const TSetOfCubes &img =
00341                         F ((n < countQ1) ? Q1 [n] : resultQ2 [n - countQ1]);
00342 
00343                 // add those image cubes to Q2 which are in N \setminus Q1
00344                 int_t countImg = img. size ();
00345                 for (int_t i = 0; i < countImg; ++ i)
00346                 {
00347                         if (!N. check (img [i]))
00348                                 continue;
00349                         if (Q1. check (img [i]))
00350                                 continue;
00351                         resultQ2. add (img [i]);
00352                 }
00353                 ++ n;
00354         }
00355         return 0;
00356 } /* ExitSetM */
00357 
00361 template <class TSetOfCubes, class TMap>
00362 int IndexPairM (const TMap &F, const TSetOfCubes &initialS,
00363         TSetOfCubes &resultQ1, TSetOfCubes &resultQ2)
00364 {
00365         // prepare the initial guess for S and N
00366         TSetOfCubes S = initialS;
00367         TSetOfCubes N;
00368         neighborhood (S, N);
00369 
00370         sout << "Starting with " << S. size () << " cubes in S_0, " <<
00371                 N. size () << " cubes in N.\n";
00372         while (1)
00373         {
00374 
00375                 // compute S := Inv (N)
00376                 sout << "S := Inv(N)... ";
00377                 scon << "(computing)\b\b\b\b\b\b\b\b\b\b\b";
00378                 TSetOfCubes empty;
00379                 S = empty;
00380         //      S = initialS;
00381                 invariantpart (N, F, S);
00382                 sout << S. size () << " cubes; o(S) has ";
00383 
00384                 // compute N' := o (S)
00385                 TSetOfCubes newN;
00386                 neighborhood (S, newN);
00387                 sout << newN. size () << " cubes.\n";
00388                 
00389                 // if Int (N) contains Inv (N), then exit
00390                 if (inclusion (newN, N))
00391                         break;
00392                 // otherwise take a larget N and repeat
00393                 else
00394                 {
00395                         sout << "Set N := o(S). ";
00396                         N = newN;
00397                 }
00398         }
00399 
00400         // compute the index pair (Q1 \cup Q2, Q2)
00401         resultQ1 = S;
00402         ExitSetM (N, S, F, resultQ2);
00403         return 0;
00404 } /* IndexPairM */
00405 
00406 
00407 // --------------------------------------------------
00408 // ------------------ Index Pair P ------------------
00409 // --------------------------------------------------
00410 
00414 template <class TSetOfCubes, class TMap>
00415 int IndexPairP (const TMap &F, const TSetOfCubes &initialS,
00416         TSetOfCubes &resultQ1, TSetOfCubes &resultQ2)
00417 {
00418         resultQ1 = initialS;
00419 
00420         // compute the initial Q2 = f (Q1) - Q1
00421         sout << "Computing the map on Q1 (" << resultQ1. size () <<
00422                 " cubes)... ";
00423         for (int_t i = 0; i < resultQ1. size (); ++ i)
00424         {
00425                 const TSetOfCubes &img = F (resultQ1 [i]);
00426                 for (int_t j = 0; j < img. size (); ++ j)
00427                 {
00428                         if (!resultQ1. check (img [j]))
00429                                 resultQ2. add (img [j]);
00430                 }
00431         }
00432         sout << resultQ2. size () << " cubes added to Q2.\n";
00433 
00434 //      sout << "Starting with " << resultQ1. size () <<
00435 //              " cubes in Q1, " << resultQ2. size () <<
00436 //              " cubes in Q2.\n";
00437 
00438         // compute images of cubes in Q2 and if any of them intersects Q1
00439         // then move this cube from Q2 to Q1
00440         sout << "Increasing Q1 and Q2 until F(Q2) is disjoint from Q1... ";
00441         int_t counter = 0;
00442         int_t countimages = 0;
00443         int_t cur = 0;
00444         TSetOfCubes removed;
00445         while (1)
00446         {
00447                 // if there are no cubes in Q2, repeat or finish
00448                 if (cur >= resultQ2. size ())
00449                 {
00450                         if (removed. empty ())
00451                                 break;
00452                         resultQ2. remove (removed);
00453                         TSetOfCubes empty;
00454                         removed = empty;
00455                         cur = 0;
00456                         continue;
00457                 }
00458 
00459                 // display a counter
00460                 ++ counter;
00461                 if (!(counter % 373))
00462                         scon << std::setw (12) << counter <<
00463                                 "\b\b\b\b\b\b\b\b\b\b\b\b";
00464 
00465                 // verify whether F(q) intersects Q1
00466                 bool intersects = false;
00467                 const TSetOfCubes &img = F (resultQ2 [cur]);
00468                 ++ countimages;
00469                 for (int_t j = 0; j < img. size (); ++ j)
00470                 {
00471                         if (resultQ1. check (img [j]))
00472                         {
00473                                 intersects = true;
00474                                 break;
00475                         }
00476                 }
00477                 
00478                 if (intersects)
00479                 {
00480                         // add F(q)\Q1 to Q2
00481                         for (int_t j = 0; j < img. size (); ++ j)
00482                         {
00483                                 if (!resultQ1. check (img [j]))
00484                                         resultQ2. add (img [j]);
00485                         }
00486                         // move q from Q2 to Q1
00487                         resultQ1. add (resultQ2 [cur]);
00488                         removed. add (resultQ2 [cur]);
00489                 }
00490 
00491                 // take the next cube from Q2
00492                 ++ cur;
00493         }
00494         sout << countimages << " analyzed.\n";
00495         return 0;
00496 } /* IndexPairP */
00497 
00498 
00499 } // namespace homology
00500 } // namespace chomp
00501 
00502 #endif // _CHOMP_HOMOLOGY_INDXPALG_H_
00503 
00505