homtools.h

Go to the documentation of this file.
00001 
00002 
00003 
00016 
00017 // Copyright (C) 1997-2010 by Pawel Pilarczyk.
00018 //
00019 // This file is part of the Homology Library.  This library is free software;
00020 // you can redistribute it and/or modify it under the terms of the GNU
00021 // General Public License as published by the Free Software Foundation;
00022 // either version 2 of the License, or (at your option) any later version.
00023 //
00024 // This library is distributed in the hope that it will be useful,
00025 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00027 // GNU General Public License for more details.
00028 //
00029 // You should have received a copy of the GNU General Public License along
00030 // with this software; see the file "license.txt".  If not, write to the
00031 // Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
00032 // MA 02111-1307, USA.
00033 
00034 // Started on April 16, 2003. Last revision: June 30, 2007.
00035 
00036 
00037 #ifndef _CHOMP_HOMOLOGY_HOMTOOLS_H_
00038 #define _CHOMP_HOMOLOGY_HOMTOOLS_H_
00039 
00040 #include "chomp/homology/cubisets.h"
00041 #include "chomp/cubes/cubmaps.h"
00042 #include "chomp/simplices/simplex.h"
00043 #include "chomp/bitmaps/bitmaps.h"
00044 
00045 namespace chomp {
00046 namespace homology {
00047 
00048 
00049 // --------------------------------------------------
00050 // ---------------------- READ ----------------------
00051 // --------------------------------------------------
00052 
00055 template <class tCube>
00056 inline void scancubes (const char *name)
00057 {
00058         if (!name || !*name)
00059                 return;
00060         std::ifstream in (name);
00061         if (!in)
00062                 fileerror (name);
00063 
00064         // read all the cubes contained in the file,
00065         // but ignore lines not starting with a parenthesis
00066         sout << "Scanning the file '" << name << "' for cubes... ";
00067         int_t count = 0;
00068         int dim = -19;
00069         bool warned = false;
00070         ignorecomments (in);
00071         while (in)
00072         {
00073                 typename tCube::CoordType c [tCube::MaxDim];
00074                 if (closingparenthesis (in. peek ()) == EOF)
00075                         ignoreline (in);
00076                 else
00077                 {
00078                         // read the point from the file
00079                         int d = readcoordinates (in, c, tCube::MaxDim);
00080 
00081                         // verify the dimension of the point
00082                         if (dim < 0)
00083                                 dim = d;
00084                         else if ((dim != d) && !warned)
00085                         {
00086                                 sout << "\nWARNING: Not all the cubes have "
00087                                         "the same dimension.\n";
00088                                 warned = true;
00089                         }
00090 
00091                         // add the point to the point base
00092                         // and verify its number
00093                         int_t n = tCube::PointBase::number (c, d);
00094                         if ((n != count) && !warned)
00095                         {
00096                                 cube q (c, d);
00097                                 sout << "\nWARNING: Some cubes are "
00098                                         "repeated - " << q <<
00099                                         " for example.\n";
00100                                 warned = true;
00101                         }
00102 
00103                         // count the point
00104                         ++ count;
00105                 }
00106                 ignorecomments (in);
00107         }
00108         sout << count << " cubes analyzed.\n";
00109         return;
00110 } /* scancubes */
00111 
00117 template <class settype>
00118 void readtheset (const char *name, settype &s, const char *pluralname,
00119         const char *what/*, bool digitOk = false*/)
00120 {
00121         // if no file name is given, do nothing
00122         if (!name)
00123                 return;
00124 
00125         // show what you are doing
00126         sout << "Reading " << pluralname;
00127         if (what)
00128                 sout << " to " << what;
00129         sout << " from '" << name << "'... ";
00130 
00131         // open the file
00132         std::ifstream in (name);
00133         if (!in)
00134                 fileerror (name);
00135 
00136         // ignore all the introductory data
00137         ignorecomments (in);
00138         while (!!in && (closingparenthesis (in. peek ()) == EOF) &&
00139                 ((in. peek () < '0') || (in. peek () > '9')) &&
00140                 (in. peek () != '-'))
00141         {
00142                 ignoreline (in);
00143                 ignorecomments (in);
00144         }
00145 
00146         // read the set and show how many elements have been read
00147         int_t prev = s. size ();
00148         in >> s;
00149         sout << (s. size () - prev) << " " << pluralname << " read.\n";
00150 
00151         return;
00152 } /* readtheset */
00153 
00155 template <class cell, class euclidom>
00156 inline void readcells (const char *name, gcomplex<cell,euclidom> &s,
00157         const char *what)
00158 {
00159         readtheset (name, s, cell::pluralname (), what);
00160         return;
00161 } /* readcells */
00162 
00164 template <class element>
00165 inline void readelements (const char *name, hashedset<element> &s,
00166         const char *what)
00167 {
00168         readtheset (name, s, element::pluralname (), what);
00169         return;
00170 } /* readelements */
00171 
00174 inline void readelements (const char *name, cubes &cub, const char *what)
00175 {
00176         readtheset (name, cub, cube::pluralname (), what);
00177         return;
00178 } /* readelements */
00179 
00181 template <class element>
00182 inline void readmapdomain (const char *name, hashedset<element> &cub)
00183 {
00184         if (!name)
00185                 return;
00186         sout << "Reading the domain of the map from '" << name << "'... ";
00187         std::ifstream in (name);
00188         if (!in)
00189                 fileerror (name);
00190         int_t prev = cub. size ();
00191         readdomain (in, cub);
00192         sout << (cub. size () - prev) << " " << element::pluralname () <<
00193                 " read.\n";
00194         return;
00195 } /* readmapdomain */
00196 
00198 template <class element>
00199 inline void readmapimage (const char *name, hashedset<element> &cub)
00200 {
00201         if (!name)
00202                 return;
00203         sout << "Reading the image of the map from '" << name << "'... ";
00204         std::ifstream in (name);
00205         if (!in)
00206                 fileerror (name);
00207         int_t prev = cub. size ();
00208         readimage (in, cub);
00209         sout << (cub. size () - prev) << " " << element::pluralname () <<
00210                 " read.\n";
00211         return;
00212 } /* readmapimage */
00213 
00216 template<class element>
00217 inline void readmapimage (const char *filename,
00218         const hashedset<element> &dom, const char *domname,
00219         hashedset<element> &cub)
00220 {
00221         if (!filename)
00222                 return;
00223         sout << "Reading the image of " << domname << " by the map '" <<
00224                 filename << "'... ";
00225         std::ifstream in (filename);
00226         if (!in)
00227                 fileerror (filename);
00228         int_t prev = cub. size ();
00229         readimage (in, dom, cub);
00230         sout << (cub. size () - prev) << " " << element::pluralname () <<
00231                 " read.\n";
00232         return;
00233 } /* readmapimage */
00234 
00236 template <class element>
00237 inline void readmaprestriction (mvmap<element,element> &Fcubmap,
00238         const char *mapname,
00239         const hashedset<element> &Xcubes, const hashedset<element> &Acubes,
00240         const char *Xname, const char *purpose = 0)
00241 {
00242         if (!mapname || (Xcubes. empty () && Acubes. empty ()))
00243                 return;
00244         sout << "Reading the map on " << Xname << " from '" << mapname;
00245         if (purpose)
00246                 sout << "' " << purpose << "... ";
00247         else
00248                 sout << "'... ";
00249         std::ifstream in (mapname);
00250         if (!in)
00251                 fileerror (mapname);
00252         readselective (in, Xcubes, Acubes, Fcubmap);
00253         if (Fcubmap. getdomain (). size () !=
00254                 Xcubes. size () + Acubes. size ())
00255         {
00256                 sout << "\nWARNING: The map is not defined "
00257                         "on some cubes in " << Xname << ".\n";
00258         }
00259         else
00260                 sout << "Done.\n";
00261         return;
00262 } /* readmaprestriction */
00263 
00265 template <class element>
00266 inline void readmaprestriction (mvmap<element,element> &Fcubmap,
00267         const char *mapname,
00268         const hashedset<element> &Xcubes, const char *Xname,
00269         const char *purpose = NULL)
00270 {
00271         hashedset<element> empty;
00272         readmaprestriction (Fcubmap, mapname, Xcubes, empty, Xname, purpose);
00273         return;
00274 } /* readmaprestriction */
00275 
00276 
00277 // --------------------------------------------------
00278 // ---------------------- SAVE ----------------------
00279 // --------------------------------------------------
00280 
00283 template <class settype>
00284 void savetheset (const char *name, const settype &s, const char *pluralname,
00285         const char *what, const char *filecomment = 0)
00286 {
00287         // if no file name is given, do nothing
00288         if (!name)
00289                 return;
00290 
00291         // show what you are doing
00292         sout << "Saving " << pluralname;
00293         if (what)
00294                 sout << " in " << what;
00295         sout << " to '" << name << "'... ";
00296 
00297         // open the file
00298         std::ofstream out (name);
00299         if (!out)
00300                 fileerror (name, "create");
00301                 
00302         // save the data
00303         if (filecomment)
00304                 out << filecomment;
00305         out << s;
00306         if (!out)
00307                 fileerror (name, "save");
00308 
00309         // show how many elements have been written
00310         sout << s. size () << " " << pluralname << " written.\n";
00311 
00312         return;
00313 } /* writetheset */
00314 
00316 template <class cell, class euclidom>
00317 inline void savecells (const char *name, const gcomplex<cell,euclidom> &s,
00318         const char *what, const char *filecomment = 0)
00319 {
00320         savetheset (name, s, cell::pluralname (), what, filecomment);
00321         return;
00322 } /* savecells */
00323 
00325 template <class element>
00326 inline void saveelements (const char *name, const hashedset<element> &s,
00327         const char *what, const char *filecomment = 0)
00328 {
00329         savetheset (name, s, element::pluralname (), what, filecomment);
00330         return;
00331 } /* saveelements */
00332 
00335 inline void saveelements (const char *name, const cubes &cub,
00336         const char *what, const char *filecomment = 0)
00337 {
00338         savetheset (name, cub, cube::pluralname (), what, filecomment);
00339         return;
00340 } /* saveelements */
00341 
00342 
00343 // --------------------------------------------------
00344 // --------------------- VERIFY ---------------------
00345 // --------------------------------------------------
00346 
00349 template <class cubsettype>
00350 bool checkinclusion (const cubsettype &Xcubes, const cubsettype &Ycubes,
00351         const cubsettype &Bcubes, const char *Xname, const char *YBname)
00352 {
00353         sout << "Verifying if " << Xname << " is contained in " <<
00354                 YBname << "... ";
00355         bool failed = false;
00356         for (int_t i = 0; !failed && (i < Xcubes. size ()); ++ i)
00357         {
00358                 if (!Ycubes. check (Xcubes [i]) &&
00359                         !Bcubes. check (Xcubes [i]))
00360                 {
00361                         failed = true;
00362                 }
00363         }
00364         if (failed)
00365                 sout << "Failed.\nWARNING: The set " << Xname <<
00366                         " is NOT contained in " << YBname << ".\n";
00367         else
00368                 sout << "Passed.\n";
00369         return !failed;
00370 } /* checkinclusion */
00371 
00374 template <class cubsettype>
00375 inline bool checkinclusion (const cubsettype &Xcubes,
00376         const cubsettype &Ycubes, const char *Xname, const char *Yname)
00377 {
00378         cubsettype empty;
00379         return checkinclusion (Xcubes, Ycubes, empty, Xname, Yname);
00380 } /* checkinclusion */
00381 
00384 template <class maptype, class cubsettype>
00385 bool checkimagecontained (const maptype &Fcubmap, const cubsettype &Xcubes,
00386         const cubsettype &Ycubes, const cubsettype &Bcubes,
00387         const char *Xname, const char *Yname)
00388 {
00389         sout << "Verifying if the image of " << Xname <<
00390                 " is contained in " << Yname << "... ";
00391         bool failed = false;
00392         for (int_t i = 0; !failed && (i < Xcubes. size ()); ++ i)
00393         {
00394                 if (!Fcubmap. getdomain (). check (Xcubes [i]))
00395                         continue;
00396                 const cubsettype &cset = Fcubmap (Xcubes [i]);
00397                 for (int_t j = 0; !failed && (j < cset. size ()); ++ j)
00398                 {
00399                         if (!Ycubes. check (cset [j]) &&
00400                                 !Bcubes. check (cset [j]))
00401                         {
00402                                 failed = true;
00403                         }
00404                 }
00405         }
00406         if (failed)
00407                 sout << "Failed.\nWARNING: The image of " << Xname <<
00408                         " is NOT contained in " << Yname << ".\n";
00409         else
00410                 sout << "Passed.\n";
00411         return !failed;
00412 } /* checkimagecontained */
00413 
00416 template <class maptype, class cubsettype>
00417 inline bool checkimagecontained (const maptype &Fcubmap,
00418         const cubsettype &Xcubes, const cubsettype &Ycubes,
00419         const char *Xname, const char *Yname)
00420 {
00421         cubsettype empty;
00422         return checkimagecontained (Fcubmap, Xcubes, Ycubes, empty,
00423                 Xname, Yname);
00424 } /* checkimagecontained */
00425 
00428 template <class maptype, class cubsettype>
00429 bool checkimagedisjoint (const maptype &Fcubmap, const cubsettype &Acubes,
00430         const cubsettype &Ycubes, const char *Aname, const char *Yname)
00431 {
00432         sout << "Verifying if the image of " << Aname <<
00433                 " is disjoint from " << Yname << "... ";
00434         bool failed = false;
00435         for (int_t i = 0; !failed && (i < Acubes. size ()); ++ i)
00436         {
00437                 if (!Fcubmap. getdomain (). check (Acubes [i]))
00438                         continue;
00439                 const cubsettype &cset = Fcubmap (Acubes [i]);
00440                 for (int_t j = 0; !failed && (j < cset. size ()); ++ j)
00441                         if (Ycubes. check (cset [j]))
00442                                 failed = true;
00443         }
00444         if (failed)
00445                 sout << "Failed.\nSERIOUS WARNING: The image of " << Aname <<
00446                         " is NOT disjoint from " << Yname << ".\n";
00447         else
00448                 sout << "Passed.\n";
00449         return !failed;
00450 } /* checkimagedisjoint */
00451 
00454 template <class tCell, class tCube, class tCoef>
00455 bool checkacyclicmap (const mvcellmap<tCell,tCoef,tCube> &Fcellcubmap,
00456         const char *Xname)
00457 {
00458         sout << "Verifying if the map on " << Xname << " is acyclic... ";
00459 
00460         // retrieve the domain cell complex and analyze each dimension
00461         const gcomplex<tCell,tCoef> &dom = Fcellcubmap. getdomain ();
00462         int_t counter = 0;
00463         bool failed = false;
00464         for (int_t d = 0; !failed && (d <= dom. dim ()); ++ d)
00465         {
00466                 // retrieve the set of cells in this dimension and analyze it
00467                 const hashedset<tCell> &qset = dom [d];
00468                 for (int_t i = 0; !failed && (i < qset. size ()); ++ i)
00469                 {
00470                         // show progress indicator
00471                         if (counter && !(counter % 373))
00472                                 scon << std::setw (10) << counter <<
00473                                         "\b\b\b\b\b\b\b\b\b\b";
00474                         ++ counter;
00475 
00476                         // reduce the image of this cell
00477                         const hashedset<tCube> &img = Fcellcubmap (qset [i]);
00478                         if (img. size () == 1)
00479                                 continue;
00480 
00481                         // if could not be reduced, compute the homology
00482                         if (!acyclic (img))
00483                                 failed = true;
00484                 }
00485         }
00486         if (failed)
00487                 sout << "Failed.\n*** WARNING: The map on " << Xname <<
00488                         " is NOT acyclic. ***\n"
00489                         "*** The result of the computations "
00490                         "may be totally wrong. ***\n";
00491         else
00492                 sout << "Passed.         \n";
00493         return !failed;
00494 } /* checkacyclicmap */
00495 
00496 
00497 // --------------------------------------------------
00498 // --------------------- REDUCE ---------------------
00499 // --------------------------------------------------
00500 
00503 template <class cubsettype>
00504 void restrictAtoneighbors (const cubsettype &Xcubes, cubsettype &Acubes,
00505         const char *Xname, const char *Aname,
00506         const cubsettype *keepcubes = 0)
00507 {
00508         // if the set 'A' is empty, there is no point in doing anything
00509         if (Acubes. empty ())
00510                 return;
00511 
00512         // display the message what is being done now
00513         sout << "Restricting " << Aname << " to the neighbors of " <<
00514                 Xname << "\\" << Aname << "... ";
00515 
00516         // remember the previous number of cubes in 'A'
00517         int_t prev = Acubes. size ();
00518 
00519         // if the set 'X' is empty, the result is obvious
00520         if (Xcubes. empty ())
00521         {
00522                 cubsettype empty;
00523                 Acubes = empty;
00524         }
00525 
00526         // remove from 'A' these cubes which are not neighbors of 'X'
00527         sseq << "D 0\n";
00528         for (int_t i = 0; i < Acubes. size (); ++ i)
00529         {
00530                 if (keepcubes && keepcubes -> check (Acubes [i]))
00531                         continue;
00532                 if (getneighbors (Acubes [i], 0, Xcubes, 1))
00533                         continue;
00534                 sseq << '0' << Acubes [i] << '\n';
00535                 Acubes. removenum (i);
00536                 -- i;
00537         }
00538         sseq << "D 100\n";
00539 
00540         // display the result
00541         sout << (prev - Acubes. size ()) << " cubes removed, " <<
00542                 Acubes. size () << " left.\n";
00543 
00544         return;
00545 } /* restrictAtoneighbors */
00546 
00548 template <class cubsettype>
00549 void removeAfromX (cubsettype &Xcubes, const cubsettype &Acubes,
00550         const char *Xname, const char *Aname)
00551 {
00552         if (Xcubes. empty () || Acubes. empty ())
00553                 return;
00554         sout << "Computing " << Xname << "\\" << Aname << "... ";
00555         int_t prev = Xcubes. size ();
00556         Xcubes. remove (Acubes);
00557         sout << (prev - Xcubes. size ()) << " cubes removed from " <<
00558                 Xname << ", " << Xcubes. size () << " left.\n";
00559         return;
00560 } /* removeAfromX */
00561 
00563 template <class cell, class euclidom>
00564 void removeAfromX (gcomplex<cell,euclidom> &X,
00565         const gcomplex<cell,euclidom> &A,
00566         const char *Xname, const char *Aname)
00567 {
00568         if (X. empty () || A. empty ())
00569                 return;
00570         sout << "Computing " << Xname << "\\" << Aname << "... ";
00571         int_t prev = X. size ();
00572         X. remove (A);
00573         sout << (prev - X. size ()) << ' ' << cell::pluralname () <<
00574                 " removed from " << Xname << ", " << X. size () <<
00575                 " left.\n";
00576         return;
00577 } /* removeAfromX */
00578 
00580 template <class cubsettype>
00581 void expandAinX (cubsettype &Xcubes, cubsettype &Acubes,
00582         const char *Xname, const char *Aname)
00583 {
00584         if (Xcubes. empty () || Acubes. empty ())
00585                 return;
00586         sout << "Expanding " << Aname << " in " << Xname << "... ";
00587         int_t count = cubexpand (Xcubes, Acubes);
00588         sout << count << " cubes moved to " << Aname << ", " <<
00589                 Xcubes. size () << " left in " << Xname << "\\" << Aname <<
00590                 ".\n";
00591         return;
00592 } /* expandAinX */
00593 
00595 template <class cubsettype, class maptype>
00596 void expandAinX (cubsettype &Xcubes, cubsettype &Acubes, cubsettype &Ycubes,
00597         cubsettype &Bcubes, const maptype &Fcubmap,
00598         const char *Xname, const char *Aname, const char *Bname,
00599         bool indexmap, bool checkacyclic)
00600 {
00601         if (Xcubes. empty () || Acubes. empty ())
00602                 return;
00603         sout << "Expanding " << Aname << " in " << Xname << "... ";
00604         int_t prevB = Bcubes. size ();
00605         int_t prevY = Ycubes. size ();
00606         int_t count = cubexpand (Xcubes, Acubes, Ycubes, Bcubes,
00607                 Fcubmap, indexmap, checkacyclic);
00608         sout << count << " moved to " << Aname << ", " << Xcubes. size () <<
00609                 " left in " << Xname << "\\" << Aname << ", " <<
00610                 (Bcubes. size () - prevB) << " added to " << Bname << ".\n";
00611         if (prevY - Ycubes. size () != Bcubes. size () - prevB)
00612                 sout << "WARNING: The image of " << Xname << "\\" << Aname <<
00613                         " was not contained in Y. "
00614                         "The result can be wrong!\n";
00615         return;
00616 } /* expandAinX */
00617 
00619 template <class cubsettype>
00620 void reducepair (cubsettype &Xcubes, cubsettype &Acubes,
00621         const cubsettype &Xkeepcubes, const char *Xname, const char *Aname)
00622 {
00623         if (Xcubes. empty ())
00624                 return;
00625         sout << "Reducing full-dim cubes from ";
00626         if (!Acubes. empty ())
00627                 sout << '(' << Xname << ',' << Aname << ")... ";
00628         else
00629                 sout << Xname << "... ";
00630         int_t count = cubreduce (Xcubes, Acubes, Xkeepcubes);
00631         sout << count << " removed, " <<
00632                 (Xcubes. size () + Acubes. size ()) << " left.\n";
00633         return;
00634 } /* reducepair */
00635 
00638 template <class maptype, class cubsettype>
00639 void reducepair (cubsettype &Xcubes, cubsettype &Acubes, maptype &Fcubmap,
00640         const cubsettype &Xkeepcubes, const char *Xname, const char *Aname)
00641 {
00642         if (Xcubes. empty ())
00643                 return;
00644         sout << "Reducing cubes from ";
00645         if (!Acubes. empty ())
00646                 sout << '(' << Xname << ',' << Aname << ") [acyclic]... ";
00647         else
00648                 sout << Xname << " [acyclic]... ";
00649         int_t count = cubreduce (Xcubes, Acubes, Fcubmap, Xkeepcubes);
00650         sout << count << " removed, " <<
00651                 (Xcubes. size () + Acubes. size ()) << " left.\n";
00652         return;
00653 } /* reducepair */
00654 
00658 template <class maptype, class cubsettype>
00659 void addmapimg (const maptype &Fcubmap, const maptype &FcubmapA,
00660         const cubsettype &Xcubes, const cubsettype &Acubes,
00661         cubsettype &Ykeepcubes, bool indexmap)
00662 {
00663         if (Fcubmap. getdomain (). empty () &&
00664                 FcubmapA. getdomain (). empty ())
00665         {
00666                 return;
00667         }
00668         sout << "Computing the image of the map... ";
00669         int_t prev = Ykeepcubes. size ();
00670         const cubsettype &Fdomain = Fcubmap. getdomain ();
00671         if (!Fdomain. empty ())
00672         {
00673                 if (Fdomain. size () == Xcubes. size ())
00674                         retrieveimage (Fcubmap, Ykeepcubes);
00675                 else
00676                 {
00677                         int_t n = Xcubes. size ();
00678                         for (int_t i = 0; i < n; ++ i)
00679                                 Ykeepcubes. add (Fcubmap (Xcubes [i]));
00680                 }
00681         }
00682         const cubsettype &FdomainA = FcubmapA. getdomain ();
00683         if (!FdomainA. empty ())
00684         {
00685                 if (FdomainA. size () == Acubes. size ())
00686                         retrieveimage (FcubmapA, Ykeepcubes);
00687                 else
00688                 {
00689                         int_t n = Acubes. size ();
00690                         for (int_t i = 0; i < n; ++ i)
00691                                 Ykeepcubes. add (FcubmapA (Acubes [i]));
00692                 }
00693         }
00694         if (indexmap)
00695         {
00696                 sout << "and of the inclusion... ";
00697                 Ykeepcubes. add (Xcubes);
00698                 Ykeepcubes. add (Acubes);
00699         }
00700         sout << (Ykeepcubes. size () - prev) << " cubes.\n";
00701         return;
00702 } /* addmapimg */
00703 
00706 template <class maptype, class cubsettype>
00707 inline void addmapimg (const maptype &Fcubmap,
00708         const cubsettype &Xcubes, const cubsettype &Acubes,
00709         cubsettype &Ykeepcubes, bool indexmap)
00710 {
00711         addmapimg (Fcubmap, Fcubmap, Xcubes, Acubes, Ykeepcubes, indexmap);
00712         return;
00713 } /* addmapimg */
00714 
00716 template <class tCubes, class tCell, class tCoef>
00717 void cubes2cells (tCubes &Xcubes, gcomplex<tCell,tCoef> &Xcompl,
00718         const char *Xname, bool deletecubes = true)
00719 {
00720         // if there are no cubes to transform, do nothing
00721         if (Xcubes. empty ())
00722                 return;
00723 
00724         // transform cubes into the cells of the same dimension
00725         int_t prev = Xcompl. size ();
00726         sout << "Transforming " << Xname << " into cells... ";
00727         for (int_t i = 0; i < Xcubes. size (); ++ i)
00728                 Xcompl. add (tCell (Xcubes [i]));
00729         sout << (Xcompl. size () - prev) << " cells added.\n";
00730 
00731         // forget the set of cubes if requested to
00732         if (deletecubes)
00733         {
00734                 tCubes empty;
00735                 Xcubes = empty;
00736         }
00737 
00738         return;
00739 } /* cubes2cells */
00740 
00742 template <class cell, class euclidom>
00743 void collapse (gcomplex<cell,euclidom> &Xcompl,
00744         gcomplex<cell,euclidom> &Acompl, gcomplex<cell,euclidom> &Xkeepcompl,
00745         const char *Xname, const char *Aname, bool addbd = true,
00746         bool addcob = false, bool disjoint = true, const int *level = NULL)
00747 {
00748         // say what you are about to do
00749         sout << "Collapsing faces in " << Xname;
00750         if (!Acompl. empty ())
00751                 sout << " and " << Aname;
00752         sout << "... ";
00753 
00754         // collapse the faces as requested to
00755         int_t count = Xcompl. collapse (Acompl, Xkeepcompl,
00756                 addbd, addcob, disjoint, level);
00757 
00758         // say something about the result
00759         sout << (count << 1) << " removed, " <<
00760                 Xcompl. size () << " left.\n";
00761 
00762         // if something remains in A, say it
00763         if (!Acompl. empty ())
00764                 sout << "There are " << Acompl. size () << " faces "
00765                         "of dimension up to " << Acompl. dim () <<
00766                         " left in " << Aname << ".\n";
00767 
00768         return;
00769 } /* collapse */
00770 
00773 template <class cell, class euclidom>
00774 inline void collapse (gcomplex<cell,euclidom> &Xcompl,
00775         gcomplex<cell,euclidom> &Acompl,
00776         const char *Xname, const char *Aname, bool addbd = true,
00777         bool addcob = false, bool disjoint = true, const int *level = NULL)
00778 {
00779         gcomplex<cell,euclidom> empty;
00780         collapse (Xcompl, Acompl, empty, Xname, Aname,
00781                 addbd, addcob, disjoint, level);
00782         return;
00783 } /* collapse */
00784 
00786 template <class cell, class euclidom>
00787 inline void collapse (gcomplex<cell,euclidom> &Xcompl,
00788         gcomplex<cell,euclidom> &Xkeepcompl,
00789         const char *Xname, bool addbd = true, bool addcob = false,
00790         bool disjoint = true, const int *level = NULL)
00791 {
00792         gcomplex<cell,euclidom> empty;
00793         collapse (Xcompl, empty, Xkeepcompl, Xname, "",
00794                 addbd, addcob, disjoint, level);
00795         return;
00796 } /* collapse */
00797 
00800 template <class cell, class euclidom>
00801 inline void collapse (gcomplex<cell,euclidom> &Xcompl,
00802         const char *Xname, bool addbd = true, bool addcob = false,
00803         bool disjoint = true, const int *level = NULL)
00804 {
00805         gcomplex<cell,euclidom> empty;
00806         collapse (Xcompl, empty, empty, Xname, "",
00807                 addbd, addcob, disjoint, level);
00808         return;
00809 } /* collapse */
00810 
00813 template <class cell, class euclidom>
00814 void decreasedimension (gcomplex<cell,euclidom> &Acompl,
00815         int dim, const char *name)
00816 {
00817         if (Acompl. dim () <= dim)
00818                 return;
00819         if (dim < 0)
00820                 dim = 0;
00821         sout << "Adding to " << name << " boundaries of high-dim " <<
00822                 cell::pluralname () << "... ";
00823         int_t howmany = 0;
00824         for (int i = Acompl. dim (); i > dim; -- i)
00825         {
00826                 sout << '.';
00827                 howmany += Acompl. addboundaries (i);
00828                 Acompl. removeall (i);
00829         }
00830         sout << ' ' << howmany << " added.\n";
00831         return;
00832 } /* decreasedimension */
00833 
00835 template <class cell, class euclidom>
00836 void addboundaries (gcomplex<cell,euclidom> &Xcompl,
00837         gcomplex<cell,euclidom> &Acompl,
00838         int minlevel, bool bothsets, const char *Xname, const char *Aname)
00839 {
00840         // if there are no cells in the complex, there is nothing to do
00841         if (Xcompl. empty ())
00842                 return;
00843 
00844         // say what you are doing
00845         sout << "Adding boundaries of " << cell::pluralname () << " in ";
00846         if (!Acompl. empty ())
00847                 sout << Xname << " and " << Aname << "... ";
00848         else
00849                 sout << Xname << "... ";
00850 
00851         // add the boundaries and count the number of added cells
00852         int_t howmany = 0;
00853         for (int i = Xcompl. dim (); (i >= minlevel) && i; -- i)
00854         {
00855                 if (bothsets)
00856                 {
00857                         howmany += Xcompl. addboundaries (i, true);
00858                         if (Acompl. dim () >= i)
00859                                 howmany += Acompl. addboundaries (i,
00860                                         true);
00861                 }
00862                 else
00863                         howmany += Xcompl. addboundaries (i, Acompl);
00864         }
00865 
00866         // show the total number of added cells
00867         sout << howmany << ' ' << cell::pluralname () << " added.\n";
00868         return;
00869 } /* addboundaries */
00870 
00871 // Add boundaries to X or to X and A.
00872 //void addboundaries (cubicalcomplex &Xcompl, cubicalcomplex &Acompl,
00873 //      int minlevel, bool bothsets, const char *Xname, const char *Aname);
00874 
00875 // Add boundaries to X or to X and A.
00876 //void addboundaries (simplicialcomplex &Xcompl, simplicialcomplex &Acompl,
00877 //      int minlevel, bool bothsets, const char *Xname, const char *Aname);
00878 
00879 
00880 // --------------------------------------------------
00881 // ---------------- READ BITMAP FILE ----------------
00882 // --------------------------------------------------
00883 
00891 template <class tCube>
00892 int ReadBitmapFile (const char *bmpname, hashedset<tCube> &cset,
00893         int mingray = 0, int maxgray = 128)
00894 {
00895         // prepare a bitmap file with the vertical axis like in mathematics
00896         bmpfile bmp;
00897         bmp. invertedpicture ();
00898 
00899         // open the bitmap file
00900         if (bmp. open (bmpname) < 0)
00901                 fileerror (bmpname);
00902         
00903         // scan the picture and produce the list of hypercubes
00904         coordinate c [2];
00905         for (c [1] = 0; c [1] < bmp. picture_height (); ++ (c [1]))
00906         {
00907                 for (c [0] = 0; c [0] < bmp. picture_width (); ++ (c [0]))
00908                 {
00909                         long color = bmp. getpixel (c [0], c [1]);
00910                         long gray = (77 * ((color & 0xFF0000) >> 16) +
00911                                 154 * ((color & 0xFF00) >> 8) +
00912                                 25 * (color & 0xFF)) >> 8;
00913                         if ((gray >= mingray) && (gray <= maxgray))
00914                                 cset. add (tCube (c, 2));
00915                 }
00916         }
00917 
00918         return 0;
00919 } /* ReadBitmapFile */
00920 
00921 
00922 } // namespace homology
00923 } // namespace chomp
00924 
00925 #endif // _CHOMP_HOMOLOGY_HOMTOOLS_H
00926 
00928