cubisets.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 in January 2002. Last revision: June 25, 2010.
00033 
00034 
00035 #ifndef _CHOMP_HOMOLOGY_CUBISETS_H_
00036 #define _CHOMP_HOMOLOGY_CUBISETS_H_
00037 
00038 #include "chomp/system/config.h"
00039 #include "chomp/system/textfile.h"
00040 #include "chomp/cubes/pointset.h"
00041 #include "chomp/homology/chains.h"
00042 #include "chomp/struct/bitfield.h"
00043 #include "chomp/struct/integer.h"
00044 #include "chomp/struct/hashsets.h"
00045 #include "chomp/struct/setunion.h"
00046 #include "chomp/homology/gcomplex.h"
00047 #include "chomp/cubes/pointbas.h"
00048 #include "chomp/cubes/cube.h"
00049 #include "chomp/cubes/cell.h"
00050 #include "chomp/cubes/cubmaps.h"
00051 #include "chomp/cubes/neighbor.h"
00052 #include "chomp/homology/cubacycl.h"
00053 #include "chomp/homology/tabulate.h"
00054 #include "chomp/homology/known.h"
00055 
00056 #include <iostream>
00057 #include <fstream>
00058 #include <cstdlib>
00059 
00060 namespace chomp {
00061 namespace homology {
00062 
00063 // --------------------------------------------------
00064 // ------------ acyclicity verification -------------
00065 // --------------------------------------------------
00066 
00069 inline int acyclic (int dim, BitField &b)
00070 {
00071         // look for the answer in the tabulated data
00072         const char *table = tabulated [dim];
00073         if (table)
00074         {
00075                 return Tabulated::get (table,
00076                         bits2int (b, getmaxneighbors (dim)));
00077         }
00078 
00079         // look for the answer among the known combinations
00080         SetOfBitFields *known = knownbits [dim];
00081         int answer = known ? known -> check (b) : -1;
00082 
00083         // if the answer is known then return it
00084         if (answer >= 0)
00085                 return answer;
00086 
00087         // create a model cube for building the neighborhood
00088         coordinate c [Cube::MaxDim];
00089         for (int i = 0; i < dim; ++ i)
00090                 c [i] = 0;
00091         Cube qzero (c, dim);
00092 
00093         // find out whether the set of neighbors is acyclic or not
00094 /*      SetOfCubes neighbors;
00095         addneighbors (qzero, b, neighbors, true);
00096         SetOfCubes empty;
00097         cubreducequiet (empty, neighbors, empty, known); // nie ma takiego
00098         answer = (neighbors. size () == 1);
00099 */
00100 // /*
00101         gcomplex<CubicalCell,integer> neighbors;
00102         addneighbors (qzero, b, neighbors, true);
00103         answer = static_cast<int> (acyclic (neighbors));
00104 //*/
00105         // add the answer to the list of known ones
00106         if (known)
00107                 known -> add (b, answer);
00108 
00109         return answer;
00110 } /* acyclic */
00111 
00114 template <class tCube>
00115 inline bool acyclic (const hashedset<tCube> &cset)
00116 {
00117         // the empty set is not acyclic
00118         if (cset. empty ())
00119                 return false;
00120 
00121         // a singleton is acyclic
00122         if (cset. size () == 1)
00123                 return true;
00124 
00125         // reduce the set and see if there is only one cube remaining
00126         hashedset<tCube> emptycubes;
00127         hashedset<tCube> theset = cset;
00128         cubreducequiet (emptycubes, theset, emptycubes); // !!!
00129         if (theset. size () == 1)
00130                 return true;
00131 
00132         // create a cubical complex from this set of cubes
00133         gcomplex<typename tCube::CellType,integer> ccompl;
00134         int_t size = cset. size ();
00135         for (int_t i = 0; i < size; ++ i)
00136                 ccompl. add (typename tCube::CellType (cset [i]));
00137 
00138         // check whether this geometric complex is acyclic or not
00139         return acyclic (ccompl);
00140 } /* acyclic */
00141 
00152 template <class tCube, class tCubeSet1, class tCubeSet2>
00153 inline bool acyclic (const tCube &q, int dim, const tCubeSet1 &cset,
00154         BitField *b, int_t maxneighbors, tCubeSet2 *neighbors)
00155 {
00156         // use a binary decision diagram code if possible
00157         if (dim <= MaxBddDim)
00158                 return bddacyclic (q, dim, cset, *b);
00159 
00160         // get the neighbors of the cube
00161         int_t n = getneighbors (q, b, cset, neighbors, 0);
00162 
00163         // if the answer is obvious from the number of neighbors, return it
00164         if ((n == 0) || (n == maxneighbors))
00165                 return false;
00166         if (n == 1)
00167                 return true;
00168 
00169         // return the information on whether this set of neighbors is acyclic
00170         return acyclic (dim, *b);
00171 } /* acyclic */
00172 
00175 template <class tCube, class tCubeSet>
00176 inline bool acyclic (const tCube &q, int dim, const tCubeSet &cset,
00177         BitField *b, int_t maxneighbors)
00178 {
00179         hashedset<tCube> *neighbors = 0;
00180         return acyclic (q, dim, cset, b, maxneighbors, neighbors);
00181 } /* acyclic */
00182 
00184 template <class tCube>
00185 bool acyclic_rel (const tCube &q, int dim, const hashedset<tCube> &cset,
00186         const hashedset<tCube> &other, BitField *b, int_t maxneighbors,
00187         hashedset<tCube> *neighbors_main, hashedset<tCube> *neighbors_other)
00188 {
00189         // use a binary decision diagram code if possible
00190         if (dim <= MaxBddDim)
00191         {
00192                 if (!getneighbors (q, b, cset, 1))
00193                         return true;
00194                 if (!bddacyclic (q, dim, other, *b))
00195                         return false;
00196                 return bddacyclic (q, dim, makesetunion (cset, other), *b);
00197         }
00198 
00199         // get the neighbors from the other set
00200         int_t nother = getneighbors (q, b, other, neighbors_other, 0);
00201 
00202         // verify if this set of neighbors is acyclic
00203         bool otheracyclic = (nother < maxneighbors) &&
00204                 ((nother == 1) || (nother && acyclic (dim, *b)));
00205 
00206         // add the neighbors from 'cset'
00207         int_t ncset = getneighbors (q, b, cset, neighbors_main, 0);
00208 
00209         // if there are no cubes in 'cset', then this cube is ok
00210         if (!ncset)
00211                 return true;
00212 
00213         // if there are neighbors in 'cset' and the neighbors
00214         // from 'other' are not acyclic, skip this cube
00215         if (!otheracyclic)
00216                 return false;
00217 
00218         // if there are neighbors from 'cset' then check if the neighbors
00219         // from both 'cset' and 'other' taken together form an acyclic set
00220         if ((ncset + nother > 1) && ((ncset + nother == maxneighbors) ||
00221                 !acyclic (dim, *b)))
00222         {
00223                 return false;
00224         }
00225         return true;
00226 } /* acyclic_rel */
00227 
00228 
00229 // --------------------------------------------------
00230 // ------------------ reduce cubes ------------------
00231 // --------------------------------------------------
00232 
00236 template <class tCube, class tCell>
00237 int_t computeimage (hashedset<tCube> &img, const tCell &face,
00238         const mvmap<tCube,tCube> &map, const hashedset<tCube> &cset,
00239         const tCube &ignore)
00240 {
00241         // get the coordinates of the cubical cell
00242         typename tCell::CoordType left [tCell::MaxDim];
00243         face. leftcoord (left);
00244         typename tCell::CoordType right [tCell::MaxDim];
00245         face. rightcoord (right);
00246 
00247         // find the images of all the cubes containing this cell
00248         int spacedim = face. spacedim ();
00249         typename tCell::CoordType leftb [tCell::MaxDim];
00250         typename tCell::CoordType rightb [tCell::MaxDim];
00251         for (int j = 0; j < spacedim; ++ j)
00252         {
00253                 typename tCell::CoordType diff =
00254                         (left [j] == right [j]) ? 1 : 0;
00255                 leftb [j] = (left [j] - diff);
00256                 rightb [j] = (right [j] + diff);
00257         }
00258         tRectangle<typename tCell::CoordType> r (leftb, rightb, spacedim);
00259         const typename tCell::CoordType *c;
00260         int_t countimages = 0;
00261         while ((c = r. get ()) != NULL)
00262         {
00263                 if (!tCube::PointBase::check (c, spacedim))
00264                         continue;
00265                 tCube q (c, spacedim);
00266                 if (q == ignore)
00267                         continue;
00268                 if (!cset. check (q))
00269                         continue;
00270                 img. add (map (q));
00271                 ++ countimages;
00272         }
00273 
00274         return countimages;
00275 } /* computeimage */
00276 
00281 template <class tCube>
00282 bool remainsacyclic (const mvmap<tCube,tCube> &map, const tCube &q,
00283         const hashedset<tCube> &cset1, const hashedset<tCube> *cset2 = 0)
00284 {
00285         // compute the maximal number of neighbors of a cube
00286         int_t maxneighbors = getmaxneighbors (q. dim ());
00287 
00288         // prepare a bitfield and allocate it if necessary
00289         static BitField b;
00290         static int_t _maxneighbors = 0;
00291         if (maxneighbors != _maxneighbors)
00292         {
00293                 if (_maxneighbors > 0)
00294                         b. free ();
00295                 _maxneighbors = maxneighbors;
00296                 b. allocate (maxneighbors);
00297         }
00298 
00299         // clear the neighborbits
00300         b. clearall (maxneighbors);
00301 
00302         // get the bitfield representing the set of the neighbors of the cube
00303         if (cset2)
00304                 getneighbors (q, &b, makesetunion (cset1, *cset2), 0);
00305         else
00306                 getneighbors (q, &b, cset1, 0);
00307 
00308         // create all the faces of the cube
00309         gcomplex<typename tCube::CellType,integer> faces;
00310         addneighbors (q, b, faces);
00311         faces. addboundaries ();
00312 
00313         // compute the new images of all the faces
00314         // and determine if they are acyclic
00315         int startdim = faces. dim ();
00316         for (int d = startdim; d >= 0; -- d)
00317         {
00318                 for (int_t i = 0; i < faces [d]. size (); ++ i)
00319                 {
00320                         // compute the image of the face in the first set
00321                         hashedset<tCube> img;
00322                         int_t n = computeimage (img, faces [d] [i], map,
00323                                 cset1, q);
00324 
00325                         // add the image of the second set if applicable
00326                         if (cset2)
00327                         {
00328                                 n += computeimage (img, faces [d] [i], map,
00329                                         *cset2, q);
00330                         }
00331 
00332                         // if this is the image of only one cube, it is Ok
00333                         if (n == 1)
00334                                 continue;
00335 
00336                         // verify whether the large image (with 'q')
00337                         // can be reduced towards the small one (without 'q')
00338                         hashedset<tCube> imgsurplus = map (q);
00339                         imgsurplus. remove (img);
00340                         cubreducequiet (img, imgsurplus);
00341                         if (!imgsurplus. empty ())
00342                                 return false;
00343                 }
00344         }
00345 
00346         return true;
00347 } /* remainsacyclic */
00348 
00356 template <class tCube, class tCubeSet>
00357 inline void addcubeneighbors (const tCube &q, int dim,
00358         const tCubeSet &cubset, bitfield *b, hashedset<tCube> &neighbors,
00359         hashedset<tCube> &queue, const hashedset<tCube> &notthese)
00360 {
00361         // determine the neighbors of this cube (if not done yet)
00362         if (dim <= MaxBddDim)
00363                 getneighbors (q, b, cubset, &neighbors, 0);
00364 
00365         // add the computed neighbors of this cube to the queue
00366         for (int_t j = 0; j < neighbors. size (); ++ j)
00367         {
00368                 if (!notthese. check (neighbors [j]))
00369                         queue. add (neighbors [j]);
00370         }
00371 
00372         return;
00373 } /* addcubeneighbors */
00374 
00378 template <class tCube>
00379 int_t cubreducequiet (const hashedset<tCube> &maincset, hashedset<tCube> &cset,
00380         bool quiet = true)
00381 {
00382         // remember the initial number of cubes in the set to be reduced
00383         int_t prev = cset. size ();
00384 
00385         // if the case is trivial, return the answer
00386         if (!prev)
00387                 return 0;
00388 
00389         // determine the space dimension
00390         int dim = cset [0]. dim ();
00391 
00392         // compute the maximal number of neighbors of a cube
00393         int_t maxneighbors = getmaxneighbors (dim);
00394 
00395         // prepare a bitfield and allocate it if necessary
00396         static BitField b;
00397         static int_t _maxneighbors = 0;
00398         if (maxneighbors != _maxneighbors)
00399         {
00400                 if (_maxneighbors > 0)
00401                         b. free ();
00402                 _maxneighbors = maxneighbors;
00403                 b. allocate (maxneighbors);
00404         }
00405 
00406         // prepare a queue for cubes to check
00407         hashedset<tCube> queue;
00408 
00409         // prepare a counter for displaying the progress of computations
00410         int_t count = 0;
00411 
00412         // remove cubes which can be removed
00413         // and add their neighbors to the queue
00414         for (int_t i = 0; i < cset. size (); ++ i)
00415         {
00416                 // show progress indicator
00417                 ++ count;
00418                 if (!quiet && !(count % 373))
00419                         scon << std::setw (10) << count <<
00420                                 "\b\b\b\b\b\b\b\b\b\b";
00421 
00422                 // clear the neighborbits
00423                 b. clearall (maxneighbors);
00424 
00425                 // prepare a set for storing the neighbors of the cube
00426                 hashedset<tCube> neighbors;
00427 
00428                 // if the neighborhood of the cube is not acyclic, skip it
00429                 if (!acyclic (cset [i], dim, makesetunion (maincset, cset),
00430                         &b, maxneighbors, &neighbors))
00431                 {
00432                         continue;
00433                 }
00434 
00435                 // remove this cube from the queue
00436                 queue. remove (cset [i]);
00437 
00438                 // determine the neighbors of this cube (if not done yet)
00439                 // and add the computed neighbors of this cube to the queue
00440                 addcubeneighbors (cset [i], dim, cset, &b, neighbors,
00441                         queue, maincset);
00442 
00443                 // remove this cube from 'cset'
00444                 if (!quiet)
00445                         sseq << '0' << cset [i] << '\n';
00446                 cset. removenum (i);
00447                 -- i;
00448         }
00449 
00450         // add a temporary progress indicator and reset the counter
00451         if (!quiet)
00452                 scon << "*";
00453         count = 0;
00454 
00455         // take cubes from the queue and remove them if possible
00456         while (!queue. empty ())
00457         {
00458                 // update the progress indicator
00459                 if (!quiet && !(count % 373))
00460                         scon << std::setw (10) << count <<
00461                                 "\b\b\b\b\b\b\b\b\b\b";
00462                 ++ count;
00463 
00464                 // take a cube from the queue
00465                 tCube c = queue [0];
00466                 queue. removenum (0);
00467 
00468                 // clear the neighborbits
00469                 b. clearall (maxneighbors);
00470 
00471                 // prepare a set for storing the neighbors of the cube
00472                 hashedset<tCube> neighbors;
00473 
00474                 // if the neighborhood of the cube is not acyclic, skip it
00475                 if (!acyclic (c, dim, makesetunion (maincset, cset),
00476                         &b, maxneighbors, &neighbors))
00477                 {
00478                         continue;
00479                 }
00480 
00481                 // determine the neighbors of this cube (if not done yet)
00482                 // and add the computed neighbors of this cube to the queue
00483                 addcubeneighbors (c, dim, cset, &b, neighbors,
00484                         queue, maincset);
00485 
00486                 // remove the cube from 'cset'
00487                 if (!quiet)
00488                         sseq << '0' << c << '\n';
00489                 cset. remove (c);
00490         }
00491 
00492         // erase the temporary progress indicator
00493         if (!quiet)
00494                 scon << "\b \b";
00495 
00496         // return the number of cubes removed from 'added'
00497         return prev - cset. size ();
00498 } /* cubreducequiet */
00499 
00500 // ??? - this description seems to be wrong!
00503 template <class tCube>
00504 inline int_t cubreduce (const hashedset<tCube> &maincset,
00505         hashedset<tCube> &cset)
00506 {
00507         return cubreducequiet (maincset, cset, false);
00508 } /* cubreduce */
00509 
00515 template <class tCube>
00516 int_t cubreducequiet (hashedset<tCube> &cset, hashedset<tCube> &other,
00517         mvmap<tCube,tCube> &map, const hashedset<tCube> &keep,
00518         bool quiet = true)
00519 {
00520         // determine if the acyclicity of the map should be considered
00521         bool checkacyclic = !map. getdomain (). empty ();
00522 
00523         // remember the initial number of cubes in both sets
00524         int_t prev = cset. size () + other. size ();
00525 
00526         // if the case is trivial, return the answer
00527         if (cset. empty ())
00528         {
00529                 if (!other. empty ())
00530                 {
00531                         hashedset<tCube> empty;
00532                         other = empty;
00533                 }
00534                 return prev;
00535         }
00536 
00537         // determine the space dimension
00538         int dim = cset [0]. dim ();
00539 
00540         // compute the maximal number of neighbors of a cube
00541         int_t maxneighbors = getmaxneighbors (dim);
00542 
00543         // prepare a bitfield and allocate it if necessary
00544         static BitField b;
00545         static int_t _maxneighbors = 0;
00546         if (maxneighbors != _maxneighbors)
00547         {
00548                 if (_maxneighbors > 0)
00549                         b. free ();
00550                 _maxneighbors = maxneighbors;
00551                 b. allocate (maxneighbors);
00552         }
00553 
00554         // prepare a queue for cubes to check
00555         hashedset<tCube> queue;
00556 
00557         // prepare a counter for displaying the progress of computations
00558         int_t count = 0;
00559 
00560         // go through the other set, remove cubes which can be removed,
00561         // and add their neighbors to the queue
00562         for (int_t i = 0; i < other. size (); ++ i)
00563         {
00564                 // show the progress indicator
00565                 ++ count;
00566                 if (!quiet && !(count % 373))
00567                         scon << std::setw (10) << count <<
00568                                 "\b\b\b\b\b\b\b\b\b\b";
00569 
00570                 // if the cube should be kept, skip it
00571                 if (keep. check (other [i]))
00572                         continue;
00573 
00574                 // clear the neighborbits
00575                 b. clearall (maxneighbors);
00576 
00577                 // prepare a set for storing the neighbors of the cube
00578                 hashedset<tCube> neighbors, *none = 0;
00579 
00580                 // if the cube cannot be removed, skip it
00581                 if (!acyclic_rel (other [i], dim, cset, other, &b,
00582                         maxneighbors, none, &neighbors))
00583                 {
00584                         continue;
00585                 }
00586 
00587                 // make sure that the acyclicity of the map on A is OK
00588                 if (checkacyclic && !remainsacyclic (map, other [i], other))
00589                         continue;
00590 
00591                 // make sure that the acyclicity of the map on X is OK
00592                 if (checkacyclic && !remainsacyclic (map, other [i],
00593                         other, &cset))
00594                         continue;
00595 
00596                 // remove this cube from the queue
00597                 queue. remove (other [i]);
00598 
00599                 // determine the neighbors of this cube (if not done yet)
00600                 // and add the computed neighbors of this cube to the queue
00601                 addcubeneighbors (other [i], dim, other, &b, neighbors,
00602                         queue, keep);
00603 
00604                 // remove this cube from 'other'
00605                 if (!quiet)
00606                         sseq << '0' << other [i] << '\n';
00607                 other. removenum (i);
00608                 -- i;
00609         }
00610 
00611         // show a temporary progress indicator and reset the counter
00612         if (!quiet)
00613                 scon << '.';
00614         count = 0;
00615 
00616         // go through the main set, remove cubes which can be removed,
00617         // and add their neighbors to the queue
00618         for (int_t i = 0; i < cset. size (); ++ i)
00619         {
00620                 // show progress indicator
00621                 if (!quiet && !(count % 373))
00622                         scon << std::setw (10) << count <<
00623                                 "\b\b\b\b\b\b\b\b\b\b";
00624                 ++ count;
00625 
00626                 // if this cube should be kept, skip it
00627                 if (keep. check (cset [i]))
00628                         continue;
00629 
00630                 // clear the neighborbits
00631                 b. clearall (maxneighbors);
00632 
00633                 // prepare a set for storing the neighbors of the cube
00634                 hashedset<tCube> neighbors;
00635 
00636                 // if the neighborhood of the cube is not acyclic, skip it
00637                 if (!acyclic (cset [i], dim, makesetunion (cset, other),
00638                         &b, maxneighbors, &neighbors))
00639                 {
00640                         continue;
00641                 }
00642 
00643                 // make sure that the acyclicity of the map on X is OK
00644                 if (checkacyclic && !remainsacyclic (map, cset [i],
00645                         cset, &other))
00646                 {
00647                         continue;
00648                 }
00649 
00650                 // remove this cube from the queue
00651                 queue. remove (cset [i]);
00652 
00653                 // determine the neighbors of this cube (if not done yet)
00654                 // and add the computed neighbors of this cube to the queue
00655                 addcubeneighbors (cset [i], dim, makesetunion (cset, other),
00656                         &b, neighbors, queue, keep);
00657 
00658                 // remove this cube from 'cset'
00659                 if (!quiet)
00660                         sseq << '0' << cset [i] << '\n';
00661                 cset. removenum (i);
00662                 -- i;
00663         }
00664 
00665         // update the temporary progress indicator and reset the counter
00666         if (!quiet)
00667                 scon << "\b*";
00668         count = 0;
00669 
00670         // take cubes from the queue and remove them if possible
00671         while (!queue. empty ())
00672         {
00673                 // update the progress indicator
00674                 if (!quiet && !(count % 373))
00675                         scon << std::setw (10) << count <<
00676                                 "\b\b\b\b\b\b\b\b\b\b";
00677                 ++ count;
00678 
00679                 // take a cube from the queue and remove it from the queue
00680                 tCube c = queue [0];
00681                 queue. removenum (0);
00682 
00683                 // clean the neighborbits
00684                 b. clearall (maxneighbors);
00685 
00686                 // if this cube belongs to the other set...
00687                 if (other. check (c))
00688                 {
00689                         // prepare a set for storing the neighbors
00690                         hashedset<tCube> neighbors;
00691 
00692                         if (!acyclic_rel (c, dim, cset, other, &b,
00693                                 maxneighbors, &cset, &other))
00694                         {
00695                                 continue;
00696                         }
00697 
00698                         // make sure that the map's acyclicity on A is OK
00699                         if (checkacyclic && !remainsacyclic (map, c, other))
00700                                 continue;
00701 
00702                         // make sure that the map's acyclicity on X is OK
00703                         if (checkacyclic && !remainsacyclic (map, c,
00704                                 other, &cset))
00705                                 continue;
00706 
00707                         // determine the neighbors of this cube (if not yet)
00708                         // and add the computed neighbors to the queue
00709                         addcubeneighbors (c, dim, makesetunion (cset, other),
00710                                 &b, neighbors, queue, keep);
00711 
00712                         // remove the cube from the other set
00713                         if (!quiet)
00714                                 sseq << '0' << c << '\n';
00715                         other. remove (c);
00716                 }
00717 
00718                 // otherwise, if this cube belongs to 'cset'...
00719                 else
00720                 {
00721                         // prepare a set for storing the neighbors
00722                         hashedset<tCube> neighbors;
00723 
00724                         // if the neighborhood of the cube is not acyclic
00725                         // then skip it
00726                         if (!acyclic (c, dim, makesetunion (cset, other),
00727                                 &b, maxneighbors, &neighbors))
00728                         {
00729                                 continue;
00730                         }
00731 
00732                         // make sure that the acyclicity of the map on X is OK
00733                         if (checkacyclic && !remainsacyclic (map, c,
00734                                 cset, &other))
00735                         {
00736                                 continue;
00737                         }
00738 
00739                         // determine the neighbors of this cube (if not yet)
00740                         // and add the computed neighbors to the queue
00741                         addcubeneighbors (c, dim, makesetunion (cset, other),
00742                                 &b, neighbors, queue, keep);
00743 
00744                         // remove the cube from 'cset'
00745                         if (!quiet)
00746                                 sseq << '0' << c << '\n';
00747                         cset. remove (c);
00748                 }
00749         }
00750 
00751         // erase the temporary progress indicator
00752         if (!quiet)
00753                 scon << "\b \b";
00754 
00755         // return the number of cubes removed from both sets
00756         return prev - cset. size () - other. size ();
00757 } /* cubreducequiet */
00758 
00763 template <class tCube>
00764 inline int_t cubreduce (hashedset<tCube> &cset, hashedset<tCube> &other,
00765         mvmap<tCube,tCube> &cubmap, const hashedset<tCube> &keep)
00766 {
00767         return cubreducequiet (cset, other, cubmap, keep, false);
00768 } /* cubreduce */
00769 
00774 template <class tCube>
00775 inline int_t cubreducequiet (hashedset<tCube> &cset, hashedset<tCube> &other,
00776         const hashedset<tCube> &keep, bool quiet = true)
00777 {
00778         mvmap<tCube,tCube> emptymap;
00779         return cubreducequiet (cset, other, emptymap, keep, quiet);
00780 } /* cubreducequiet */
00781 
00785 template <class tCube>
00786 inline int_t cubreduce (hashedset<tCube> &cset, hashedset<tCube> &other,
00787         const hashedset<tCube> &keep)
00788 {
00789         return cubreducequiet (cset, other, keep, false);
00790 } /* cubreduce */
00791 
00792 
00793 // --------------------------------------------------
00794 // ------------------ expand cubes ------------------
00795 // --------------------------------------------------
00796 
00799 template <class tCube>
00800 int_t cubexpand (hashedset<tCube> &cset, hashedset<tCube> &other,
00801         bool quiet = false)
00802 {
00803         // if the case is trivial, return the answer
00804         if (cset. empty () || other. empty ())
00805                 return 0;
00806 
00807         // remember the initial number of cubes in the main set
00808         int_t prev = cset. size ();
00809 
00810         // determine the dimension of the cubes
00811         int dim = cset [0]. dim ();
00812 
00813         // compute the maximal number of neighbors of a cube
00814         int_t maxneighbors = getmaxneighbors (dim);
00815 
00816         // prepare a bitfield and allocate it if necessary
00817         static BitField b;
00818         static int_t _maxneighbors = 0;
00819         if (maxneighbors != _maxneighbors)
00820         {
00821                 if (_maxneighbors > 0)
00822                         b. free ();
00823                 _maxneighbors = maxneighbors;
00824                 b. allocate (maxneighbors);
00825         }
00826 
00827         // prepare a queue for cubes to check
00828         hashedset<tCube> queue;
00829 
00830         // prepare a counter for displaying the progress of computations
00831         int_t count = 0;
00832 
00833         // go through the main set, move cubes to the other set
00834         // if possible, and add their neighbors to the queue
00835         for (int_t i = 0; i < cset. size (); ++ i)
00836         {
00837                 // show progress indicator if suitable
00838                 ++ count;
00839                 if (!quiet && !(count % 373))
00840                         scon << std::setw (10) << count <<
00841                                 "\b\b\b\b\b\b\b\b\b\b";
00842 
00843                 // clear the neighborbits
00844                 b. clearall (maxneighbors);
00845 
00846                 // if the neighborhood of the cube is not acyclic, skip it
00847                 if (!acyclic (cset [i], dim, other, &b, maxneighbors))
00848                         continue;
00849                 
00850                 // remove this cube from the queue
00851                 queue. remove (cset [i]);
00852 
00853                 // add neighbors from 'cset' to the queue
00854                 b. clearall (maxneighbors);
00855                 getneighbors (cset [i], &b, cset, &queue, 0);
00856 
00857                 // move the cube to the other set
00858                 if (!quiet)
00859                         sseq << '2' << cset [i] << '\n';
00860                 other. add (cset [i]);
00861                 cset. removenum (i);
00862                 -- i;
00863         }
00864 
00865         // show a temporary progress indicator and reset the counter
00866         if (!quiet)
00867                 scon << '*';
00868         count = 0;
00869 
00870         // take cubes from the queue and move them from 'cset' to 'other'
00871         while (queue. size ())
00872         {
00873                 // show progress indicator
00874                 if (!quiet && !(count % 373))
00875                         scon << std::setw (10) << count <<
00876                                 "\b\b\b\b\b\b\b\b\b\b";
00877                 ++ count;
00878 
00879                 // take a cube from the queue
00880                 const tCube c = queue [0];
00881                 queue. removenum (0);
00882 
00883                 // clear the neighborbits
00884                 b. clearall (maxneighbors);
00885 
00886                 // if the neighborhood of the cube is not acyclic, skip it
00887                 if (!acyclic (c, dim, other, &b, maxneighbors))
00888                         continue;
00889 
00890                 // add the neighbors from 'cset' to the queue
00891                 b. clearall (maxneighbors);
00892                 getneighbors (c, &b, cset, &queue, 0);
00893 
00894                 // move this cube from 'cset' to 'other'
00895                 if (!quiet)
00896                         sseq << '2' << c << '\n';
00897                 cset. remove (c);
00898                 other. add (c);
00899         }
00900 
00901         // erase the temporary progress indicator
00902         if (!quiet)
00903                 scon << "\b \b";
00904 
00905         // return the number of cubes removed from 'cset'
00906         return prev - cset. size ();
00907 } /* cubexpand */
00908 
00915 template <class tCube>
00916 int_t cubexpand (hashedset<tCube> &cset, hashedset<tCube> &other,
00917         hashedset<tCube> &imgsrc, hashedset<tCube> &img,
00918         const mvmap<tCube,tCube> &map, bool indexmap,
00919         bool checkacyclic, bool quiet = false)
00920 {
00921         // if the case is trivial, return the answer
00922         if (cset. empty () || other. empty ())
00923                 return 0;
00924 
00925         // remember the initial number of cubes in the main set
00926         int_t prev = cset. size ();
00927 
00928         // determine the space dimension
00929         int dim = cset [0]. dim ();
00930 
00931         // compute the maximal number of neighbors of a cube
00932         int_t maxneighbors = getmaxneighbors (dim);
00933 
00934         // prepare a bitfield and allocate it if necessary
00935         static BitField b;
00936         static int_t _maxneighbors = 0;
00937         if (maxneighbors != _maxneighbors)
00938         {
00939                 if (_maxneighbors > 0)
00940                         b. free ();
00941                 _maxneighbors = maxneighbors;
00942                 b. allocate (maxneighbors);
00943         }
00944 
00945         // prepare a queue for cubes to check
00946         hashedset<tCube> queue;
00947 
00948         // prepare a counter for displaying the progress of computations
00949         int_t count = 0;
00950 
00951         // go through the main set, move cubes to the other set
00952         // if possible, and add their neighbors to the queue
00953         for (int_t i = 0; i < cset. size (); ++ i)
00954         {
00955                 // show progress indicator
00956                 ++ count;
00957                 if (!quiet && !(count % 373))
00958                         scon << std::setw (10) << count <<
00959                                 "\b\b\b\b\b\b\b\b\b\b";
00960 
00961                 // take a cube from 'cset'
00962                 const tCube &c = cset [i];
00963 
00964                 // clear the neighborbits
00965                 b. clearall (maxneighbors);
00966 
00967                 // if the neighborhood of the cube is not acyclic, skip it
00968                 if (!acyclic (c, dim, other, &b, maxneighbors))
00969                         continue;
00970                 
00971                 // take the image and reduce what is outside 'img'
00972                 const hashedset<tCube> &cubimage = map (c);
00973                 hashedset<tCube> ximage = cubimage;
00974                 if (indexmap)
00975                         ximage. add (c);
00976                 ximage. remove (img);
00977                 cubreducequiet (img, ximage);
00978 
00979                 // if the image could not be reduced, skip the cube
00980                 if (!ximage. empty ())
00981                         continue;
00982 
00983                 // make sure that the acyclicity of the map is not spoiled
00984                 if (checkacyclic && !remainsacyclic (map, c, other))
00985                         continue;
00986 
00987                 // add the image of this cube to the image of the map
00988                 if (!quiet && !cubimage. empty ())
00989                 {
00990                         sseq << "R\n";
00991                         for (int_t j = 0; j < cubimage. size (); ++ j)
00992                                 sseq << '2' << cubimage [j] << '\n';
00993                         if (indexmap)
00994                                 sseq << '2' << c << '\n';
00995                 }
00996                 img. add (cubimage);
00997                 if (indexmap)
00998                         img. add (c);
00999 
01000                 // remove from 'imgsrc' all the cubes added to 'img'
01001                 imgsrc. remove (cubimage);
01002                 if (indexmap)
01003                         imgsrc. remove (c);
01004 
01005                 // remove this cube from the queue
01006                 queue. remove (c);
01007 
01008                 // add neighbors from 'cset' to the queue
01009                 b. clearall (maxneighbors);
01010                 getneighbors (c, &b, cset, &queue, 0);
01011 
01012                 // move the cube to the other set
01013                 if (!quiet)
01014                         sseq << "L\n" << '2' << c << '\n';
01015                 other. add (c);
01016                 cset. removenum (i);
01017                 -- i;
01018         }
01019 
01020         // show a temporary progress indicator and reset the counter
01021         if (!quiet)
01022                 scon << '*';
01023         count = 0;
01024 
01025         // take cubes from the queue and move them from 'cset' to 'other'
01026         while (!queue. empty ())
01027         {
01028                 // show progress indicator
01029                 if (!quiet && !(count % 373))
01030                         scon << std::setw (10) << count <<
01031                                 "\b\b\b\b\b\b\b\b\b\b";
01032                 ++ count;
01033 
01034                 // take a cube from the queue
01035                 tCube c = queue [0];
01036                 queue. removenum (0);
01037 
01038                 // clear the neighborbits
01039                 b. clearall (maxneighbors);
01040 
01041                 // if the neighborhood of the cube is not acyclic, skip it
01042                 if (!acyclic (c, dim, other, &b, maxneighbors))
01043                         continue;
01044                 
01045                 // take the image and reduce what is outside 'img'
01046                 const hashedset<tCube> &cubimage = map (c);
01047                 hashedset<tCube> ximage = cubimage;
01048                 if (indexmap)
01049                         ximage. add (c);
01050                 ximage. remove (img);
01051                 cubreducequiet (img, ximage);
01052 
01053                 // if the image could not be reduced, skip the cube
01054                 if (!ximage. empty ())
01055                         continue;
01056 
01057                 // make sure that the acyclicity of the map is not spoiled
01058                 if (checkacyclic && !remainsacyclic (map, c, other))
01059                         continue;
01060 
01061                 // add the image of this cube to the image of the map
01062                 if (!quiet && !cubimage. empty ())
01063                 {
01064                         sseq << "R\n";
01065                         for (int_t i = 0; i < cubimage. size (); ++ i)
01066                                 sseq << '2' << cubimage [i] << '\n';
01067                         if (indexmap)
01068                                 sseq << '2' << c << '\n';
01069                 }
01070                 img. add (cubimage);
01071                 if (indexmap)
01072                         img. add (c);
01073 
01074                 // remove from 'imgsrc' all the cubes added to 'img'
01075                 imgsrc. remove (cubimage);
01076                 if (indexmap)
01077                         imgsrc. remove (c);
01078 
01079                 // add the neighbors from 'cset' to the queue
01080                 b. clearall (maxneighbors);
01081                 getneighbors (c, &b, cset, &queue, 0);
01082 
01083                 // move this cube from 'cset' to 'other'
01084                 if (!quiet)
01085                         sseq << "L\n" << '2' << c << '\n';
01086                 cset. remove (c);
01087                 other. add (c);
01088         }
01089 
01090         // erase the temporary progress indicator
01091         if (!quiet)
01092                 scon << "\b \b";
01093 
01094         // return the number of cubes removed from 'cset'
01095         return prev - cset. size ();
01096 } /* cubexpand */
01097 
01098 
01099 } // namespace homology
01100 } // namespace chomp
01101 
01102 #endif // _CHOMP_HOMOLOGY_CUBISETS_H_
01103 
01105