00001
00002
00003
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #ifndef _CHOMP_HOMOLOGY_GCOMPLEX_H_
00038 #define _CHOMP_HOMOLOGY_GCOMPLEX_H_
00039
00040 #include "chomp/system/config.h"
00041 #include "chomp/system/textfile.h"
00042 #include "chomp/struct/integer.h"
00043 #include "chomp/struct/hashsets.h"
00044 #include "chomp/homology/chains.h"
00045 #include "chomp/homology/gcomplex.h"
00046
00047 #include <iostream>
00048 #include <fstream>
00049 #include <iomanip>
00050 #include <cstdlib>
00051
00052 namespace chomp {
00053 namespace homology {
00054
00055
00056
00057 template <class cell, class euclidom>
00058 class gcomplex;
00059 template <class cell, class euclidom, class element>
00060 class mvcellmap;
00061
00062
00063
00064
00065
00066
00067 template <class cell>
00068 int boundarycoef (const cell &, int i);
00069
00070 template <class cell>
00071 int boundarylength (const cell &);
00072
00073 template <class cell>
00074 cell boundarycell (const cell &, int i);
00075
00084 template <class cell, class euclidom>
00085 class gcomplex
00086 {
00087 public:
00089 gcomplex ();
00090
00092 gcomplex (const gcomplex<cell,euclidom> &c);
00093
00095 ~gcomplex ();
00096
00098 gcomplex &operator = (const gcomplex<cell,euclidom> &c);
00099
00102 int dim () const;
00103
00105 int_t size () const;
00106
00108 bool empty () const;
00109
00111 const hashedset<cell> &operator [] (int d) const;
00112
00114 const hashedset<cell> &getcob (const cell &c) const;
00115
00118 const hashedset<cell> &getcob (const cell &c, int d) const;
00119
00121 gcomplex<cell,euclidom> &add (const cell &c);
00122
00125 gcomplex<cell,euclidom> &add (const hashedset<cell> &c, int d);
00126
00128 gcomplex<cell,euclidom> &add (const hashedset<cell> &c);
00129
00131 gcomplex<cell,euclidom> &add (const gcomplex<cell,euclidom> &c);
00132
00134 gcomplex<cell,euclidom> &remove (const cell &c);
00135
00138 gcomplex<cell,euclidom> &remove (const hashedset<cell> &c, int d);
00139
00141 gcomplex<cell,euclidom> &remove (const hashedset<cell> &c);
00142
00144 gcomplex<cell,euclidom> &remove (const gcomplex<cell,euclidom> &c);
00145
00147 gcomplex<cell,euclidom> &removeall (int d);
00148
00151 bool check (const cell &c) const;
00152
00156 int_t addboundaries (int d, bool addcob = false);
00157
00161 int_t addboundaries (bool addcob = false);
00162
00169 int_t addboundaries (int d, gcomplex<cell,euclidom> ¬these,
00170 bool keepused = false);
00171
00178 int_t addboundaries (gcomplex<cell,euclidom> ¬these,
00179 bool keepused = false);
00180
00182 int_t addboundaries (int d, chaincomplex<euclidom> &c);
00183
00185 int_t addboundaries (chaincomplex<euclidom> &c);
00186
00188 int_t addboundaries (int d, chaincomplex<euclidom> &c,
00189 gcomplex<cell,euclidom> ¬these,
00190 bool keepused = false);
00191
00193 int_t addboundaries (chaincomplex<euclidom> &c,
00194 gcomplex<cell,euclidom> ¬these,
00195 bool keepused = false);
00196
00199 int_t addboundaries (int d, chaincomplex<euclidom> *c,
00200 gcomplex<cell,euclidom> *notthese,
00201 bool dontadd, bool keepused, bool addcob);
00202
00205 int_t addboundaries (chaincomplex<euclidom> *c,
00206 gcomplex<cell,euclidom> *notthese,
00207 bool dontadd, bool keepused, bool addcob);
00208
00214 int_t collapse (int d,
00215 gcomplex<cell,euclidom> &other,
00216 const gcomplex<cell,euclidom> &keep,
00217 bool addbd, bool addcob, bool disjoint,
00218 bool quiet = false);
00219
00227 int_t collapse (gcomplex<cell,euclidom> &other,
00228 gcomplex<cell,euclidom> &keep,
00229 bool addbd, bool addcob, bool disjoint,
00230 const int *level = NULL, bool quiet = false);
00231
00232 private:
00234 hashedset<cell> **tab;
00235
00237 mvmap<cell,cell> **cob;
00238
00240 int n;
00241
00243 void increasedimension (int d);
00244
00246 void decreasedimension ();
00247
00248 };
00249
00250
00251
00252 template <class cell, class euclidom>
00253 inline gcomplex<cell,euclidom>::gcomplex (): tab (NULL), cob (NULL), n (0)
00254 {
00255 return;
00256 }
00257
00258 template <class cell, class euclidom>
00259 gcomplex<cell,euclidom>::gcomplex (const gcomplex<cell,euclidom> &c)
00260 {
00261 n = c. n;
00262 if (n > 0)
00263 {
00264 tab = new hashedset<cell> *[n];
00265 cob = new mvmap<cell,cell> *[n];
00266 if (!tab || !cob)
00267 throw "Cannot copy a geometric complex.";
00268 }
00269 else
00270 {
00271 tab = NULL;
00272 cob = NULL;
00273 }
00274 for (int i = 0; i < n; ++ i)
00275 {
00276 tab [i] = new hashedset<cell> (*(c. tab [i]));
00277 cob [i] = new mvmap<cell,cell> (*(c. cob [i]));
00278 if (!tab [i] || !cob [i])
00279 throw "Cannot copy part of a geometric complex.";
00280 }
00281 return;
00282 }
00283
00284 template <class cell, class euclidom>
00285 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::operator =
00286 (const gcomplex<cell,euclidom> &c)
00287 {
00288
00289
00290 if (n != c. n)
00291 {
00292 if (tab)
00293 {
00294 for (int i = 0; i < n; ++ i)
00295 delete tab [i];
00296 delete [] tab;
00297 }
00298 if (cob)
00299 {
00300 for (int i = 0; i < n; ++ i)
00301 delete cob [i];
00302 delete [] cob;
00303 }
00304 n = c. n;
00305 if (n > 0)
00306 {
00307 tab = new hashedset<cell> *[n];
00308 cob = new mvmap<cell,cell> *[n];
00309 if (!tab || !cob)
00310 throw "Cannot copy a geometric complex.";
00311 }
00312 else
00313 {
00314 tab = NULL;
00315 cob = NULL;
00316 }
00317 for (int i = 0; i < n; ++ i)
00318 {
00319 tab [i] = new hashedset<cell> (*(c. tab [i]));
00320 cob [i] = new mvmap<cell,cell> (*(c. cob [i]));
00321 if (!tab [i] || !cob [i])
00322 throw "Cannot copy part of a geom. complex.";
00323 }
00324 }
00325
00326 else
00327 {
00328 for (int i = 0; i < n; ++ i)
00329 {
00330 *(tab [i]) = *(c. tab [i]);
00331 *(cob [i]) = *(c. cob [i]);
00332 }
00333 }
00334 return *this;
00335 }
00336
00337 template <class cell, class euclidom>
00338 gcomplex<cell,euclidom>::~gcomplex ()
00339 {
00340 for (int i = 0; i < n; ++ i)
00341 {
00342 if (tab [i])
00343 delete tab [i];
00344 if (cob [i])
00345 delete cob [i];
00346 }
00347 if (tab)
00348 delete [] tab;
00349 if (cob)
00350 delete [] cob;
00351 return;
00352 }
00353
00354 template <class cell, class euclidom>
00355 inline int gcomplex<cell,euclidom>::dim () const
00356 {
00357 return n - 1;
00358 }
00359
00360 template <class cell, class euclidom>
00361 int_t gcomplex<cell,euclidom>::size () const
00362 {
00363 int_t count = 0;
00364 for (int i = 0; i < n; ++ i)
00365 count += tab [i] -> size ();
00366 return count;
00367 }
00368
00369 template <class cell, class euclidom>
00370 bool gcomplex<cell,euclidom>::empty () const
00371 {
00372 if (!n)
00373 return true;
00374 for (int i = 0; i < n; ++ i)
00375 if (!(*(tab [i])). empty ())
00376 return false;
00377 return true;
00378 }
00379
00380 template <class cell, class euclidom>
00381 inline const hashedset<cell> &gcomplex<cell,euclidom>::operator [] (int d)
00382 const
00383 {
00384 if ((d < 0) || (d >= n))
00385 throw "Dimension out of range for retrieving cells.";
00386 return *(tab [d]);
00387 }
00388
00389 template <class cell, class euclidom>
00390 inline const hashedset<cell> &gcomplex<cell,euclidom>::getcob (const cell &c)
00391 const
00392 {
00393 return getcob (c, c. dim ());
00394 }
00395
00396 template <class cell, class euclidom>
00397 inline const hashedset<cell> &gcomplex<cell,euclidom>::getcob (const cell &c,
00398 int d) const
00399 {
00400 if ((d < 0) || (d >= n))
00401 throw "Dimension out of range for coboundary.";
00402 return (*(cob [d])) (c);
00403 }
00404
00405 template <class cell, class euclidom>
00406 inline gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::add (const cell &c)
00407 {
00408
00409 int d = c. dim ();
00410 if (d < 0)
00411 throw "Negative dimension of a cell to be added.";
00412
00413
00414
00415 if (n <= d)
00416 increasedimension (d);
00417
00418
00419 tab [d] -> add (c);
00420
00421 return *this;
00422 }
00423
00424 template <class cell, class euclidom>
00425 inline gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::add
00426 (const hashedset<cell> &c, int d)
00427 {
00428
00429 if (d > n)
00430 increasedimension (d);
00431
00432
00433 tab [d] -> add (c);
00434
00435 return *this;
00436 }
00437
00438 template <class cell, class euclidom>
00439 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::add
00440 (const hashedset<cell> &c)
00441 {
00442 int_t size = c. size ();
00443 for (int_t i = 0; i < size; ++ i)
00444 add (c [i]);
00445
00446 return *this;
00447 }
00448
00449 template <class cell, class euclidom>
00450 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::add
00451 (const gcomplex<cell,euclidom> &c)
00452 {
00453
00454 if (c. n > n)
00455 increasedimension (c. dim ());
00456
00457
00458 for (int i = 0; i < c. n; ++ i)
00459 {
00460 tab [i] -> add (*(c. tab [i]));
00461
00462
00463
00464
00465
00466
00467
00468
00469
00470
00471 }
00472
00473 return *this;
00474 }
00475
00476 template <class cell, class euclidom>
00477 inline gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::remove
00478 (const cell &c)
00479 {
00480
00481 int d = c. dim ();
00482 if (d < 0)
00483 throw "Negative dimension of a cell to be removed.";
00484
00485
00486
00487 if (n <= d)
00488 return *this;
00489
00490
00491 tab [d] -> remove (c);
00492
00493
00494 if ((d == n - 1) && tab [d] -> empty ())
00495 decreasedimension ();
00496
00497 return *this;
00498 }
00499
00500 template <class cell, class euclidom>
00501 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::remove
00502 (const gcomplex<cell,euclidom> &c)
00503 {
00504
00505 int m = c. n;
00506 if (m > n)
00507 m = n;
00508
00509
00510 for (int i = 0; i < m; ++ i)
00511 tab [i] -> remove (*(c. tab [i]));
00512
00513
00514 decreasedimension ();
00515
00516 return *this;
00517 }
00518
00519 template <class cell, class euclidom>
00520 inline gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::remove
00521 (const hashedset<cell> &c, int d)
00522 {
00523
00524 tab [d] -> remove (c);
00525
00526
00527 decreasedimension ();
00528
00529 return *this;
00530 }
00531
00532 template <class cell, class euclidom>
00533 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::remove
00534 (const hashedset<cell> &c)
00535 {
00536 int_t size = c. size ();
00537 for (int_t i = 0; i < size; ++ i)
00538 remove (c [i]);
00539
00540 return *this;
00541 }
00542
00543 template <class cell, class euclidom>
00544 gcomplex<cell,euclidom> &gcomplex<cell,euclidom>::removeall (int d)
00545 {
00546 if (d == n - 1)
00547 {
00548 -- n;
00549 delete tab [n];
00550 delete cob [n];
00551 decreasedimension ();
00552 }
00553 else if ((d >= 0) && (d < n))
00554 {
00555 delete tab [d];
00556 tab [d] = new hashedset<cell>;
00557 }
00558
00559 return *this;
00560 }
00561
00562 template <class cell, class euclidom>
00563 bool gcomplex<cell,euclidom>::check (const cell &c) const
00564 {
00565
00566 int d = c. dim ();
00567 if (d < 0)
00568 throw "Negative dimension of a cell to be checked.";
00569
00570
00571
00572 if (n <= d)
00573 return false;
00574
00575
00576 return tab [d] -> check (c);
00577 }
00578
00579 template <class cell, class euclidom>
00580 int_t gcomplex<cell,euclidom>::addboundaries (int d,
00581 chaincomplex<euclidom> *c, gcomplex<cell,euclidom> *notthese,
00582 bool dontadd, bool keepused, bool addcob)
00583 {
00584
00585 if ((d <= 0) || (d >= n))
00586 return 0;
00587
00588
00589 if (notthese && !dontadd)
00590 notthese -> addboundaries (d);
00591
00592 int_t prevsize = tab [d - 1] -> size ();
00593 hashedset<cell> &cset = *(tab [d]);
00594 for (int_t i = 0; i < cset. size (); ++ i)
00595 {
00596 const cell &thecell = cset [i];
00597 int len = boundarylength (thecell);
00598 for (int j = 0; j < len; ++ j)
00599 {
00600
00601 cell bcell = boundarycell (thecell, j);
00602
00603
00604 if (!notthese || !notthese -> check (bcell))
00605 {
00606 tab [d - 1] -> add (bcell);
00607 if (c)
00608 {
00609 int icoef = boundarycoef (thecell, j);
00610 euclidom coef;
00611 if (icoef < 0)
00612 {
00613 coef = -icoef;
00614 coef = -coef;
00615 }
00616 else
00617 coef = icoef;
00618 c -> add (d, tab [d - 1] ->
00619 getnumber (bcell), i, coef);
00620 }
00621 if (addcob)
00622 (*(cob [d - 1])) [bcell].
00623 add (thecell);
00624 }
00625 }
00626 }
00627
00628
00629 if (notthese && !keepused)
00630 notthese -> removeall (d);
00631
00632 return tab [d - 1] -> size () - prevsize;
00633 }
00634
00635 template <class cell, class euclidom>
00636 int_t gcomplex<cell,euclidom>::addboundaries (chaincomplex<euclidom> *c,
00637 gcomplex<cell,euclidom> *notthese, bool dontadd, bool keepused,
00638 bool addcob)
00639 {
00640 int_t countadded = 0;
00641 for (int d = n - 1; d > 0; -- d)
00642 countadded += addboundaries (d, c, notthese,
00643 dontadd, keepused, addcob);
00644 return countadded;
00645 }
00646
00647 template <class cell, class euclidom>
00648 inline int_t gcomplex<cell,euclidom>::addboundaries (int d, bool addcob)
00649 {
00650 return addboundaries (d, NULL, NULL, false, false, addcob);
00651 }
00652
00653 template <class cell, class euclidom>
00654 inline int_t gcomplex<cell,euclidom>::addboundaries (bool addcob)
00655 {
00656 return addboundaries (NULL, NULL, false, false, addcob);
00657 }
00658
00659 template <class cell, class euclidom>
00660 inline int_t gcomplex<cell,euclidom>::addboundaries (int d,
00661 gcomplex<cell,euclidom> ¬these, bool keepused)
00662 {
00663 return addboundaries (d, NULL, ¬these, false, keepused, false);
00664 }
00665
00666 template <class cell, class euclidom>
00667 int_t gcomplex<cell,euclidom>::addboundaries
00668 (gcomplex<cell,euclidom> ¬these, bool keepused)
00669 {
00670 return addboundaries (NULL, ¬these, false, keepused, false);
00671 }
00672
00673 template <class cell, class euclidom>
00674 inline int_t gcomplex<cell,euclidom>::addboundaries (int d,
00675 chaincomplex<euclidom> &c)
00676 {
00677 return addboundaries (d, &c, NULL, false, false, false);
00678 }
00679
00680 template <class cell, class euclidom>
00681 inline int_t gcomplex<cell,euclidom>::addboundaries (chaincomplex<euclidom> &c)
00682 {
00683 return addboundaries (&c, NULL, false, false, false);
00684 }
00685
00686 template <class cell, class euclidom>
00687 inline int_t gcomplex<cell,euclidom>::addboundaries (int d,
00688 chaincomplex<euclidom> &c, gcomplex<cell,euclidom> ¬these,
00689 bool keepused)
00690 {
00691 return addboundaries (d, &c, ¬these, false, keepused, false);
00692 }
00693
00694 template <class cell, class euclidom>
00695 inline int_t gcomplex<cell,euclidom>::addboundaries (chaincomplex<euclidom> &c,
00696 gcomplex<cell,euclidom> ¬these, bool keepused)
00697 {
00698 return addboundaries (&c, ¬these, false, keepused, false);
00699 }
00700
00701
00702
00705 template <class element>
00706 int_t findelem (const multitable<element> &tab, const element &e, int_t len)
00707 {
00708 if (len <= 0)
00709 return -1;
00710
00711
00712 int_t i = static_cast<int_t> (std::rand ()) % len;
00713 if (i < 0)
00714 i = static_cast<int_t> (1) - i;
00715 int_t step = static_cast<int_t> (std::rand () + 17) % len;
00716 if (step < 0)
00717 step = static_cast<int_t> (1) - step;
00718 if (step < 17)
00719 step = 17;
00720 if (step > len)
00721 step = len >> 1;
00722 if (step < 1)
00723 step = 1;
00724
00725
00726 int_t jumping = len >> 1;
00727 while (jumping --)
00728 {
00729
00730
00731 if (tab (i) == e)
00732 return i;
00733
00734
00735 if (jumping)
00736 {
00737 i += step;
00738 if (i >= len)
00739 i -= len;
00740 }
00741 }
00742
00743
00744 for (int_t i = 0; i < len; ++ i)
00745 {
00746 if (tab (i) == e)
00747 return i;
00748 }
00749 return -1;
00750 }
00751
00752 template <class cell, class euclidom>
00753 int_t gcomplex<cell,euclidom>::collapse (int d,
00754 gcomplex<cell,euclidom> &other, const gcomplex<cell,euclidom> &keep,
00755 bool addbd, bool addcob, bool disjoint, bool quiet)
00756 {
00757 if ((d <= 0) || (d > dim ()))
00758 return 0;
00759
00760
00761 hashedset<cell> &cset = *(tab [d]);
00762 hashedset<cell> &bset = *(tab [d - 1]);
00763 hashedset<cell> empty;
00764 hashedset<cell> &cother = (other. dim () >= d) ?
00765 *(other. tab [d]) : empty;
00766 hashedset<cell> &bother = (other. dim () >= d - 1) ?
00767 *(other. tab [d - 1]) : empty;
00768 const hashedset<cell> &ckeep = (keep. dim () >= d) ?
00769 *(keep. tab [d]) : empty;
00770 const hashedset<cell> &bkeep = (keep. dim () >= d - 1) ?
00771 *(keep. tab [d - 1]) : empty;
00772
00773
00774 if (!quiet)
00775 {
00776 if (d > 9)
00777 scon << "#\b";
00778 else
00779 scon << d << '\b';
00780 }
00781
00782
00783 if (addbd)
00784 {
00785 if (!quiet)
00786 {
00787 sseq << "\"Adding boundaries of cells in A...\"\n";
00788 sseq << "D 0\n";
00789 }
00790 for (int_t i = 0; i < cother. size (); ++ i)
00791 {
00792
00793 const cell &thecell = cother [i];
00794
00795
00796 int blen = boundarylength (thecell);
00797
00798
00799 for (int j = 0; j < blen; ++ j)
00800 bother. add (boundarycell (thecell, j));
00801
00802
00803 if (!quiet && (sseq. show || sseq. log))
00804 {
00805 for (int j = 0; j < blen; ++ j)
00806 sseq << '2' << boundarycell
00807 (thecell, j) << '\n';
00808 }
00809 }
00810 }
00811 if (!quiet)
00812 sseq << "D 100\n";
00813
00814
00815 if (disjoint)
00816 bset. remove (bother);
00817
00818
00819 multitable<int> coblen;
00820 multitable<hashedset <cell> > coboundary;
00821 if (!bset. empty ())
00822 coblen. fill (0, bset. size ());
00823
00824
00825
00826
00827 if (!quiet)
00828 sseq << "\"Adding boundaries of cells of dimension " <<
00829 d << "\"\nD 0\n";
00830 bool maximal = (d == dim ());
00831 for (int_t i = 0; i < cset. size (); ++ i)
00832 {
00833
00834 const cell &thecell = cset [i];
00835
00836
00837 bool cbelongs = cother. check (thecell);
00838
00839
00840 if (cbelongs && (disjoint || maximal))
00841 {
00842
00843
00844 cother. remove (thecell);
00845 cset. removenum (i --);
00846 continue;
00847 }
00848
00849
00850 int blen = boundarylength (thecell);
00851
00852
00853 bool keepit = ckeep. check (thecell);
00854
00855
00856 for (int j = 0; j < blen; ++ j)
00857 {
00858
00859 cell bcell = boundarycell (thecell, j);
00860
00861
00862 bool bbelongs = bother. check (bcell);
00863
00864
00865 if (bbelongs && disjoint)
00866 continue;
00867
00868
00869 int_t prev = bset. size ();
00870 int_t number = addbd ? bset. add (bcell) :
00871 bset. getnumber (bcell);
00872
00873
00874 if (number < 0)
00875 continue;
00876
00877
00878 if ((prev < bset. size ()) || (coblen [number] == 0))
00879 {
00880
00881 if (!quiet && !bbelongs)
00882 sseq << '1' << bcell << '\n';
00883
00884
00885 if (keepit || bkeep. check (bset [number]) ||
00886 bother. check (bset [number]))
00887 coblen [number] = 13;
00888 else
00889 coblen [number] = 1;
00890 coboundary [number]. add (thecell);
00891 }
00892
00893
00894 else
00895 {
00896 ++ (coblen [number]);
00897 coboundary [number]. add (thecell);
00898 }
00899 }
00900 }
00901 if (!quiet)
00902 sseq << "D 100\n";
00903
00904
00905 if (!quiet)
00906 scon << "*\b";
00907
00908
00909 hashedset<cell> cremove, bremove;
00910 int_t nremove = 0;
00911
00912
00913 if (!quiet)
00914 sseq << "\"Collapsing free faces...\"\n";
00915 while (1)
00916 {
00917
00918 int_t ncell = findelem (coblen, 1, bset. size ());
00919
00920
00921 if (ncell < 0)
00922 break;
00923
00924
00925 const cell &parent = coboundary [ncell] [0];
00926 int blen = boundarylength (parent);
00927 coblen [ncell] = 0;
00928
00929
00930 for (int j = 0; j < blen; ++ j)
00931 {
00932 cell thecell = boundarycell (parent, j);
00933 int_t number = bset. getnumber (thecell);
00934 if ((number >= 0) && (coblen [number] > 0))
00935 {
00936 coboundary [number]. remove (parent);
00937 -- (coblen [number]);
00938 }
00939 }
00940
00941
00942 if (!quiet)
00943 {
00944 sseq << '0' << bset [ncell] << '\n';
00945 sseq << '0' << parent << '\n';
00946 }
00947
00948
00949 cremove. add (parent);
00950 bremove. add (bset [ncell]);
00951 ++ nremove;
00952
00953
00954 coboundary [ncell] = empty;
00955 }
00956
00957
00958 if (addcob)
00959 {
00960 for (int_t i = 0; i < bset. size (); ++ i)
00961 if (!bremove. check (bset [i]))
00962 {
00963 coboundary [i]. remove (cremove);
00964 (*(cob [d - 1])) [bset [i]]. add
00965 (coboundary [i]);
00966 }
00967 }
00968
00969
00970 if (nremove == cset. size ())
00971 {
00972 removeall (d);
00973 other. removeall (d);
00974 }
00975 else
00976 {
00977 for (int_t i = 0; i < nremove; ++ i)
00978 cset. remove (cremove [i]);
00979 }
00980
00981
00982 for (int_t i = 0; i < nremove; ++ i)
00983 bset. remove (bremove [i]);
00984
00985
00986 decreasedimension ();
00987
00988
00989 if (!quiet)
00990 scon << '.';
00991
00992 return nremove;
00993 }
00994
00995 template <class cell, class euclidom>
00996 int_t gcomplex<cell,euclidom>::collapse (gcomplex<cell,euclidom> &other,
00997 gcomplex<cell,euclidom> &keep, bool addbd, bool addcob,
00998 bool disjoint, const int *level, bool quiet)
00999 {
01000
01001 int dmin = 0;
01002 if (level)
01003 {
01004 while ((dmin < dim ()) && (!level [dmin]))
01005 ++ dmin;
01006 if (dmin && level [dmin])
01007 -- dmin;
01008 }
01009
01010
01011 while (keep. dim () > dim ())
01012 {
01013 keep. addboundaries (keep. dim ());
01014 keep. removeall (keep. dim ());
01015 }
01016
01017
01018 if (other. dim () > dim ())
01019 {
01020 other. addboundaries (other. dim ());
01021 other. removeall (other. dim ());
01022 }
01023
01024
01025 int_t counter = 0;
01026 for (int d = dim (); d > dmin; -- d)
01027 {
01028
01029 keep. addboundaries (d);
01030
01031
01032 counter += collapse (d, other, keep, addbd, addcob, disjoint,
01033 quiet);
01034
01035
01036 if (disjoint)
01037 other. removeall (d);
01038
01039
01040 keep. removeall (d);
01041 }
01042
01043
01044 if (!disjoint && (dim () >= dmin) && (other. dim () >= dmin))
01045 {
01046 hashedset<cell> &cset = *(tab [dmin]);
01047 hashedset<cell> &cother = *(other. tab [dmin]);
01048 for (int_t i = 0; i < cother. size (); ++ i)
01049 {
01050 if (!(cset. check (cother [i])))
01051 cother. removenum (i --);
01052 }
01053 }
01054
01055
01056 if (!keep. empty ())
01057 {
01058 gcomplex<cell,euclidom> empty;
01059 keep = empty;
01060 }
01061
01062 if (!quiet)
01063 scon << ' ';
01064
01065 return counter;
01066 }
01067
01068 template <class cell, class euclidom>
01069 void gcomplex<cell,euclidom>::increasedimension (int d)
01070 {
01071
01072 hashedset<cell> **newtab = new hashedset<cell> *[d + 1];
01073 mvmap<cell,cell> **newcob = new mvmap<cell,cell> *[d + 1];
01074
01075
01076 for (int i = 0; i < n; ++ i)
01077 {
01078 newtab [i] = tab [i];
01079 newcob [i] = cob [i];
01080 }
01081
01082
01083 if (tab)
01084 delete [] tab;
01085 if (cob)
01086 delete [] cob;
01087
01088
01089 tab = newtab;
01090 cob = newcob;
01091 for (int i = n; i < d + 1; ++ i)
01092 {
01093 tab [i] = new hashedset<cell>;
01094 cob [i] = new mvmap<cell,cell>;
01095 }
01096
01097
01098 n = d + 1;
01099
01100 return;
01101 }
01102
01103 template <class cell, class euclidom>
01104 void gcomplex<cell,euclidom>::decreasedimension ()
01105 {
01106 while (n && tab [n - 1] -> empty ())
01107 {
01108 -- n;
01109 delete tab [n];
01110 delete cob [n];
01111 }
01112 if (!n)
01113 {
01114 delete [] tab;
01115 tab = NULL;
01116 delete [] cob;
01117 cob = NULL;
01118 }
01119 return;
01120 }
01121
01122
01123
01128 template <class cell, class euclidom>
01129 chaincomplex<euclidom> &createchaincomplex (chaincomplex<euclidom> &c,
01130 const gcomplex<cell,euclidom> &g, bool quiet = false)
01131 {
01132 if (g. dim () < 0)
01133 return c;
01134 c. def_gen (0, g [0]. size ());
01135 for (int d = 1; d <= g. dim (); ++ d)
01136 {
01137 c. def_gen (d, g [d]. size ());
01138 for (int_t i = 0; i < g [d]. size (); ++ i)
01139 {
01140 int len = boundarylength (g [d] [i]);
01141 for (int j = 0; j < len; ++ j)
01142 {
01143
01144 cell thecell = boundarycell (g [d] [i], j);
01145
01146
01147 if (g. check (thecell))
01148 {
01149 int icoef = boundarycoef
01150 (g [d] [i], j);
01151 euclidom coef;
01152 if (icoef < 0)
01153 {
01154 coef = -icoef;
01155 coef = -coef;
01156 }
01157 else
01158 coef = icoef;
01159 c. add (d, g [d - 1]. getnumber
01160 (thecell), i, coef);
01161 }
01162 }
01163 }
01164 if (!quiet)
01165 {
01166 if (d < g. dim ())
01167 scon << '.';
01168 else
01169 scon << ". ";
01170 }
01171 }
01172 return c;
01173 }
01174
01180 template <class cell, class euclidom>
01181 std::ostream &writechaincomplex (std::ostream &out,
01182 const gcomplex<cell,euclidom> &g, bool symbolicnames = false,
01183 bool quiet = false)
01184 {
01185 if (g. dim () < 0)
01186 return out;
01187 out << "chaincomplex\n\n";
01188 out << "maxdimension " << g. dim () << "\n\n";
01189 out << "dimension 0: " << g [0]. size () << "\n\n";
01190 for (int d = 1; d <= g. dim (); ++ d)
01191 {
01192 out << "dimension " << d << ": " << g [d]. size () << "\n";
01193 for (int_t i = 0; i < g [d]. size (); ++ i)
01194 {
01195 bool cellwritten = false;
01196 int len = boundarylength (g [d] [i]);
01197 for (int j = 0; j < len; ++ j)
01198 {
01199
01200 cell thecell = boundarycell (g [d] [i], j);
01201
01202
01203 if (g. check (thecell))
01204 {
01205 int icoef = boundarycoef
01206 (g [d] [i], j);
01207 euclidom coef;
01208 if (icoef < 0)
01209 {
01210 coef = -icoef;
01211 coef = -coef;
01212 }
01213 else
01214 coef = icoef;
01215 if (!cellwritten)
01216 {
01217 out << "\t# ";
01218 if (symbolicnames)
01219 out << g [d] [i];
01220 else
01221 out << (i + 1);
01222 out << " = ";
01223 if (-coef == 1)
01224 out << "- ";
01225 }
01226 else if (coef == 1)
01227 out << " + ";
01228 else if (-coef == 1)
01229 out << " - ";
01230 else
01231 out << " + " << coef <<
01232 " * ";
01233 if (symbolicnames)
01234 out << thecell;
01235 else
01236 out << (1 + g [d - 1].
01237 getnumber (thecell));
01238 cellwritten = true;
01239 }
01240 }
01241 if (cellwritten)
01242 out << '\n';
01243 }
01244 if (!quiet)
01245 {
01246 if (d < g. dim ())
01247 scon << '.';
01248 else
01249 scon << ". ";
01250 }
01251 out << '\n';
01252 }
01253 return out;
01254 }
01255
01260 template <class cell, class euclidom>
01261 chaincomplex<euclidom> &createchaincomplex (chaincomplex<euclidom> &c,
01262 const gcomplex<cell,euclidom> &g, const gcomplex<cell,euclidom> &rel,
01263 bool quiet = false)
01264 {
01265
01266 if (g. dim () < 0)
01267 return c;
01268
01269
01270 multitable<int_t> *numbers0 = new multitable<int_t>;
01271 int_t count0 = g [0]. size ();
01272 if (rel. dim () >= 0)
01273 {
01274 count0 -= rel [0]. size ();
01275 int_t j = 0;
01276 for (int_t i = 0; i < rel [0]. size (); ++ i)
01277 {
01278 (*numbers0) [j] = g [0]. getnumber (rel [0] [i]);
01279 if ((*numbers0) [j] < 0)
01280 ++ count0;
01281 else
01282 ++ j;
01283 }
01284 }
01285
01286
01287 c. def_gen (0, count0);
01288
01289
01290 for (int d = 1; d <= g. dim (); ++ d)
01291 {
01292
01293 multitable<int_t> *numbers1 = new multitable<int_t>;
01294 int_t count1 = g [d]. size ();
01295 if (rel. dim () >= d)
01296 {
01297 count1 -= rel [d]. size ();
01298 int_t j = 0;
01299 for (int_t i = 0; i < rel [d]. size (); ++ i)
01300 {
01301 (*numbers1) [j] =
01302 g [d]. getnumber (rel [d] [i]);
01303 if ((*numbers1) [j] < 0)
01304 ++ count1;
01305 else
01306 ++ j;
01307 }
01308 }
01309
01310
01311 c. def_gen (d, count1);
01312
01313
01314 for (int_t i = 0; i < g [d]. size (); ++ i)
01315 {
01316
01317 if ((rel. dim () >= d) &&
01318 (rel [d]. check (g [d] [i])))
01319 continue;
01320
01321
01322 int_t n1 = i;
01323 if (n1 >= count1)
01324 n1 = (*numbers1) [n1 - count1];
01325
01326
01327 int len = boundarylength (g [d] [i]);
01328
01329
01330 for (int j = 0; j < len; ++ j)
01331 {
01332
01333 cell thecell = boundarycell (g [d] [i], j);
01334
01335
01336 if (g [d - 1]. check (thecell) &&
01337 ((rel. dim () < d - 1) ||
01338 (!rel [d - 1]. check (thecell))))
01339 {
01340
01341 int_t n0 = g [d - 1].
01342 getnumber (thecell);
01343
01344
01345 if (n0 >= count0)
01346 n0 = (*numbers0)
01347 [n0 - count0];
01348
01349
01350 int icoef = boundarycoef
01351 (g [d] [i], j);
01352 euclidom coef;
01353 if (icoef < 0)
01354 {
01355 coef = -icoef;
01356 coef = -coef;
01357 }
01358 else
01359 coef = icoef;
01360
01361
01362 c. add (d, n0, n1, coef);
01363 }
01364 }
01365 }
01366
01367
01368 delete numbers0;
01369 numbers0 = numbers1;
01370 count0 = count1;
01371
01372
01373 if (!quiet)
01374 {
01375 if (d < g. dim ())
01376 scon << '.';
01377 else
01378 scon << ". ";
01379 }
01380 }
01381
01382
01383 delete numbers0;
01384
01385
01386 return c;
01387 }
01388
01390 template <class cell, class euclidom>
01391 std::ostream &writegenerators (std::ostream &out, const chain<euclidom> *hom,
01392 const chaincomplex<euclidom> &c,
01393 const gcomplex<cell,euclidom> &g, const int *level = NULL)
01394 {
01395 bool firstlist = true;
01396 for (int d = 0; d <= c. dim (); ++ d)
01397 {
01398 if ((!level || level [d]) && !hom [d]. empty ())
01399 {
01400 if (firstlist)
01401 firstlist = false;
01402 else
01403 out << '\n';
01404 if (hom [d]. size () == 1)
01405 out << "The generator of H_" << d <<
01406 " follows:" << '\n';
01407 else
01408 out << "The " << hom [d]. size () <<
01409 " generators of H_" << d <<
01410 " follow:" << '\n';
01411 const hashedset<cell> &cset = g [d];
01412 for (int_t i = 0; i < hom [d]. size (); ++ i)
01413 {
01414 if (hom [d]. size () > 1)
01415 out << "generator " << (i + 1) <<
01416 '\n';
01417 const chain<euclidom> &lst =
01418 c. gethomgen (d, hom [d]. num (i));
01419 for (int_t j = 0; j < lst. size (); ++ j)
01420 out << lst. coef (j) << " * " <<
01421 cset [lst. num (j)] << '\n';
01422 }
01423 }
01424 }
01425 return out;
01426 }
01427
01429 template <class cell, class euclidom>
01430 gcomplex<cell,euclidom> &creategraph (const mvmap<cell,cell> &m,
01431 gcomplex<cell,euclidom> &graph)
01432 {
01433 for (int_t i = 0; i < m. size (); ++ i)
01434 {
01435 const cell &e = m. get (i);
01436 const hashedset<cell> &f = m (i);
01437 for (int_t j = 0; j < f. size (); ++ j)
01438 graph. add (e * f [j]);
01439 }
01440 return graph;
01441 }
01442
01447 template <class cell, class euclidom>
01448 bool acyclic (gcomplex<cell,euclidom> &c)
01449 {
01450
01451 gcomplex<cell,euclidom> empty;
01452 c. collapse (empty, empty, true, false, false, NULL, true);
01453 if (c. size () == 1)
01454 return true;
01455
01456
01457 chaincomplex<euclidom> cx (c. dim ());
01458 createchaincomplex (cx, c, true);
01459 chain<euclidom> *hom;
01460 cx. simple_form (static_cast<int *> (0), true);
01461 cx. simple_homology (hom, 0);
01462
01463
01464 for (int i = 1; i <= cx. dim (); ++ i)
01465 {
01466 if (!hom [i]. empty ())
01467 {
01468 delete [] hom;
01469 return false;
01470 }
01471 }
01472
01473
01474 if (hom [0]. size () != 1)
01475 {
01476 delete [] hom;
01477 return false;
01478 }
01479
01480
01481 if (hom [0]. getcoefficient (0) == 1)
01482 {
01483 delete [] hom;
01484 return true;
01485 }
01486 else
01487 {
01488 delete [] hom;
01489 return false;
01490 }
01491 }
01492
01493
01494
01496 template <class cell, class euclidom>
01497 std::ostream &operator << (std::ostream &out,
01498 const gcomplex<cell,euclidom> &c)
01499 {
01500 out << "; Geometric complex of dimension " << c. dim () <<
01501 " (" << c. size () << " cells total)." << '\n';
01502 for (int i = 0; i <= c. dim (); ++ i)
01503 out << "; Cells of dimension " << i << ':' << '\n' << c [i];
01504 return out;
01505 }
01506
01508 template <class cell, class euclidom>
01509 std::istream &operator >> (std::istream &in, gcomplex<cell,euclidom> &c)
01510 {
01511 ignorecomments (in);
01512 while (closingparenthesis (in. peek ()) != EOF)
01513 {
01514 cell x;
01515 in >> x;
01516 c. add (x);
01517 ignorecomments (in);
01518 }
01519 return in;
01520 }
01521
01522
01523
01524
01525
01526
01529 template <class cell, class euclidom, class element>
01530 class mvcellmap
01531 {
01532 public:
01536 mvcellmap (gcomplex<cell,euclidom> *_g = 0);
01537
01541 mvcellmap (gcomplex<cell,euclidom> &_g);
01542
01544 mvcellmap (const mvcellmap<cell,euclidom,element> &m);
01545
01547 mvcellmap &operator = (const mvcellmap<cell,euclidom,element> &m);
01548
01550 ~mvcellmap ();
01551
01553 int dim () const;
01554
01556 const hashedset<cell> &get (int d) const;
01557
01559 const gcomplex<cell,euclidom> &getdomain () const;
01560
01562 const hashedset<element> &operator () (const cell &c) const;
01563
01566 void add (int d, const cell &c,
01567 const hashedset<element> &set);
01568
01570 void add (const cell &c, const hashedset<element> &set);
01571
01574 void add (int d, int_t n, const hashedset<element> &set);
01575
01578 void add (int d, const cell &c, const element &e);
01579
01581 void add (const cell &c, const element &e);
01582
01585 void add (int d, int_t n, const element &e);
01586
01587 private:
01589 gcomplex<cell,euclidom> *g;
01590
01592 multitable <hashedset<element> > *images;
01593
01595 int dimension;
01596
01597 };
01598
01599
01600
01601 template <class cell, class euclidom, class element>
01602 inline mvcellmap<cell,euclidom,element>::mvcellmap
01603 (gcomplex<cell,euclidom> *_g)
01604 {
01605 g = _g;
01606 if (!g || (g -> dim () < 0))
01607 {
01608 images = NULL;
01609 dimension = -1;
01610 return;
01611 }
01612 dimension = g -> dim ();
01613 images = new multitable <hashedset<element> > [dimension + 1];
01614 if (!images)
01615 throw "Cannot create a multivalued cellular map.";
01616 return;
01617 }
01618
01619 template <class cell, class euclidom, class element>
01620 inline mvcellmap<cell,euclidom,element>::mvcellmap
01621 (gcomplex<cell,euclidom> &_g)
01622 {
01623 g = &_g;
01624 if (!g || (g -> dim () < 0))
01625 {
01626 images = NULL;
01627 dimension = -1;
01628 return;
01629 }
01630 dimension = g -> dim ();
01631 images = new multitable <hashedset<element> > [dimension + 1];
01632 if (!images)
01633 throw "Cannot create a multivalued cellular map.";
01634 return;
01635 }
01636
01637 template <class cell, class euclidom, class element>
01638 mvcellmap<cell,euclidom,element>::mvcellmap
01639 (const mvcellmap<cell,euclidom,element> &m)
01640 {
01641 g = m. g;
01642 if (!g || (g -> dim () < 0))
01643 {
01644 images = NULL;
01645 dimension = -1;
01646 return;
01647 }
01648 dimension = g -> dim ();
01649 images = new multitable <hashedset<element> > [dimension + 1];
01650 if (!images)
01651 throw "Unable to construct a copy of a multivalued "
01652 "cellular map.";
01653 for (int i = 0; i < dimension + 1; ++ i)
01654 images [i] = m. images [i];
01655 return;
01656 }
01657
01658 template <class cell, class euclidom, class element>
01659 mvcellmap<cell,euclidom,element> &mvcellmap<cell,euclidom,element>::operator =
01660 (const mvcellmap<cell,euclidom,element> &m)
01661 {
01662 if (images)
01663 delete [] images;
01664 g = m. g;
01665 dimension = m. dimension;
01666 if (!g || (dimension < 0))
01667 {
01668 images = NULL;
01669 return *this;
01670 }
01671 images = new multitable <hashedset<element> > [dimension + 1];
01672 if (!images)
01673 throw "Cannot copy a multivalued cellular map.";
01674 for (int i = 0; i < dimension + 1; ++ i)
01675 images [i] = m. images [i];
01676 return *this;
01677 }
01678
01679 template <class cell, class euclidom, class element>
01680 inline mvcellmap<cell,euclidom,element>::~mvcellmap ()
01681 {
01682 if (images)
01683 delete [] images;
01684 return;
01685 }
01686
01687 template <class cell, class euclidom, class element>
01688 int mvcellmap<cell,euclidom,element>::dim () const
01689 {
01690 return dimension;
01691 }
01692
01693 template <class cell, class euclidom, class element>
01694 const hashedset<cell> &mvcellmap<cell,euclidom,element>::get (int d) const
01695 {
01696 if ((d < 0) || (d > dimension))
01697 throw "Wrong dimension to retrieve from mvcellmap.";
01698 return (*g) [d];
01699 }
01700
01701 template <class cell, class euclidom, class element>
01702 const gcomplex<cell,euclidom> &mvcellmap<cell,euclidom,element>::getdomain ()
01703 const
01704 {
01705 return *g;
01706 }
01707
01708 template <class cell, class euclidom, class element>
01709 const hashedset<element> &mvcellmap<cell,euclidom,element>::operator ()
01710 (const cell &c) const
01711 {
01712 int d = c. dim ();
01713 if (d > dimension)
01714 throw "Trying to get the image of a cell of dim too high.";
01715 int_t n = (*g) [d]. getnumber (c);
01716 if (n < 0)
01717 throw "Trying to get the image of a cell not in the domain.";
01718 return images [d] [n];
01719 }
01720
01721 template <class cell, class euclidom, class element>
01722 inline void mvcellmap<cell,euclidom,element>::add (int d, const cell &c,
01723 const hashedset<element> &set)
01724 {
01725 if ((d < 0) || (d > dimension))
01726 throw "Wrong dimension for adding a cell to a map.";
01727 if (!g -> check (c))
01728
01729 g -> add (c);
01730 images [d] [(*g) [d]. getnumber (c)]. add (set);
01731 return;
01732 }
01733
01734 template <class cell, class euclidom, class element>
01735 inline void mvcellmap<cell,euclidom,element>::add (const cell &c,
01736 const hashedset<element> &set)
01737 {
01738 add (c. dim (), c, set);
01739 return;
01740 }
01741
01742 template <class cell, class euclidom, class element>
01743 inline void mvcellmap<cell,euclidom,element>::add (int d, int_t n,
01744 const hashedset<element> &set)
01745 {
01746 if ((d < 0) || (d > dimension))
01747 throw "Wrong dimension for adding an element to the image.";
01748 images [d] [n]. add (set);
01749 return;
01750 }
01751
01752 template <class cell, class euclidom, class element>
01753 inline void mvcellmap<cell,euclidom,element>::add (int d, const cell &c,
01754 const element &e)
01755 {
01756 if ((d < 0) || (d > dimension))
01757 throw "Wrong dimension for adding a cell to a map.";
01758 if (!g -> check (c))
01759
01760 g -> add (c);
01761 images [d] [(*g) [d]. getnumber (c)]. add (e);
01762 return;
01763 }
01764
01765 template <class cell, class euclidom, class element>
01766 inline void mvcellmap<cell,euclidom,element>::add (const cell &c,
01767 const element &e)
01768 {
01769 add (c. dim (), c, e);
01770 return;
01771 }
01772
01773 template <class cell, class euclidom, class element>
01774 inline void mvcellmap<cell,euclidom,element>::add (int d, int_t n,
01775 const element &set)
01776 {
01777 if ((d < 0) || (d > dimension))
01778 throw "Wrong dimension for adding an element to the image.";
01779 images [d] [n]. add (set);
01780 return;
01781 }
01782
01783
01784
01788 template <class cell, class euclidom, class element>
01789 void creategraph (const mvcellmap<cell,euclidom,element> &m,
01790 gcomplex<cell,euclidom> &c, bool addbd)
01791 {
01792
01793 for (int d1 = 0; d1 <= m. dim (); ++ d1)
01794 {
01795
01796 const hashedset<cell> &cset = m. get (d1);
01797 for (int_t i = 0; i < cset. size (); ++ i)
01798 {
01799
01800 const cell &thecell = cset [i];
01801 const hashedset<element> &set = m (thecell);
01802 gcomplex<cell,euclidom> img;
01803 for (int_t j = 0; j < set. size (); ++ j)
01804 img. add (cell (set [j]));
01805 if (addbd)
01806 img. addboundaries ();
01807
01808
01809 for (int d2 = 0; d2 <= img. dim (); ++ d2)
01810 {
01811
01812 const hashedset<cell> &cs = img [d2];
01813 for (int_t j = 0; j < cs. size (); ++ j)
01814 c. add (thecell * cs [j]);
01815 }
01816 }
01817 if (d1 < m. dim ())
01818 scon << '.';
01819 else
01820 scon << ' ';
01821 }
01822 return;
01823 }
01824
01828 template <class cell, class euclidom, class element>
01829 void creategraph (const mvcellmap<cell,euclidom,element> &m,
01830 const gcomplex<cell,euclidom> &rel,
01831 gcomplex<cell,euclidom> &c, bool addbd)
01832 {
01833
01834 for (int d1 = 0; d1 <= m. dim (); ++ d1)
01835 {
01836
01837 const hashedset<cell> &cset = m. get (d1);
01838 for (int_t i = 0; i < cset. size (); ++ i)
01839 {
01840
01841 const cell &thecell = cset [i];
01842 const hashedset<element> &set = m (thecell);
01843 gcomplex<cell,euclidom> img;
01844 for (int_t j = 0; j < set. size (); ++ j)
01845 img. add (cell (set [j]));
01846 if (addbd)
01847 img. addboundaries ();
01848
01849
01850 for (int d2 = 0; d2 <= img. dim (); ++ d2)
01851 {
01852
01853 const hashedset<cell> &cs = img [d2];
01854 for (int_t j = 0; j < cs. size (); ++ j)
01855 {
01856 cell bigcell = thecell * cs [j];
01857 if (!rel. check (bigcell))
01858 c. add (bigcell);
01859 }
01860 }
01861 }
01862 if (d1 < m. dim ())
01863 scon << '.';
01864 else
01865 scon << ' ';
01866 }
01867 return;
01868 }
01869
01874 template <class cell, class euclidom, class element>
01875 void createcellmap (const mvcellmap<cell,euclidom,element> &m,
01876 mvcellmap<cell,euclidom,cell> &cm)
01877 {
01878
01879 int spacedim = -1;
01880 const gcomplex<cell,euclidom> &dom = m. getdomain ();
01881 for (int d = m. dim (); d >= 0; -- d)
01882 {
01883
01884 const hashedset<cell> &cset = m. get (d);
01885 for (int_t i = 0; i < cset. size (); ++ i)
01886 {
01887
01888 const cell &thecell = cset [i];
01889 const hashedset<element> &set = m (thecell);
01890
01891
01892 if (set. empty ())
01893 throw "An empty image of a cell found.";
01894
01895
01896 if (spacedim < 0)
01897 spacedim = set [0]. dim ();
01898
01899
01900 if (d == spacedim)
01901 {
01902
01903
01904 cm. add (d, thecell, cell (set [0], 0));
01905 continue;
01906 }
01907
01908
01909 gcomplex<cell,euclidom> img;
01910 for (int_t j = 0; j < set. size (); ++ j)
01911 img. add (cell (set [j]));
01912
01913
01914 gcomplex<cell,euclidom> keep;
01915 const hashedset<cell> &cob =
01916 dom. getcob (thecell, d);
01917 for (int_t j = 0; j < cob. size (); ++ j)
01918 keep. add (cm (cob [j]));
01919
01920
01921 gcomplex<cell,euclidom> empty;
01922 img. collapse (empty, keep, 1, 0, 0, NULL, 1);
01923
01924
01925
01926 for (int j = 0; j <= img. dim (); ++ j)
01927 cm. add (d, thecell, img [j]);
01928
01929
01930 if (i && !(i % 373))
01931 scon << std::setw (12) << i <<
01932 "\b\b\b\b\b\b\b\b\b\b\b\b";
01933 }
01934 if (cset. size () > 373)
01935 scon << " \b\b\b\b\b\b\b\b\b\b\b\b";
01936 scon << '.';
01937 }
01938 scon << ' ';
01939 return;
01940 }
01941
01948 template <class cell, class euclidom, class element>
01949 bool createcellmap (const mvcellmap<cell,euclidom,element> &m,
01950 const mvcellmap<cell,euclidom,element> &rel,
01951 mvcellmap<cell,euclidom,cell> &cm, bool verifyacyclicity)
01952 {
01953
01954 bool result = true;
01955
01956
01957 const gcomplex<cell,euclidom> &dom = m. getdomain ();
01958 const gcomplex<cell,euclidom> &reldom = rel. getdomain ();
01959
01960 int maxdim = m. dim ();
01961 for (int d = maxdim; d >= 0; -- d)
01962 {
01963
01964 const hashedset<cell> &cset = m. get (d);
01965 for (int_t i = 0; i < cset. size (); ++ i)
01966 {
01967
01968 const cell &thecell = cset [i];
01969 const hashedset<element> &set = m (thecell);
01970
01971
01972 if (set. empty ())
01973 throw "An empty image of a cell found.";
01974
01975
01976 if (d == maxdim)
01977 {
01978 if (reldom. check (thecell))
01979 continue;
01980
01981
01982
01983 cm. add (d, thecell, cell (set [0], 0));
01984 continue;
01985 }
01986
01987
01988 gcomplex<cell,euclidom> img;
01989 for (int_t j = 0; j < set. size (); ++ j)
01990 img. add (cell (set [j]));
01991
01992
01993 gcomplex<cell,euclidom> keep;
01994 const hashedset<cell> &cob =
01995 dom. getcob (thecell, d);
01996
01997 for (int_t j = 0; j < cob. size (); ++ j)
01998 keep. add (cm (cob [j]));
01999
02000
02001 gcomplex<cell,euclidom> other;
02002 if (reldom. check (thecell))
02003 {
02004 const hashedset<element> &relset =
02005 rel (thecell);
02006 for (int_t j = 0; j < relset. size (); ++ j)
02007 {
02008 cell c = cell (relset [j]);
02009 keep. add (c);
02010 other. add (c);
02011
02012 }
02013 }
02014
02015
02016 gcomplex<cell,euclidom> empty;
02017 img. collapse (empty, keep, 1, 0, 0, NULL, 1);
02018
02019
02020 if (verifyacyclicity)
02021 {
02022 gcomplex<cell,euclidom> imgdupl (img);
02023 if (!acyclic (imgdupl))
02024 {
02025 result = false;
02026 verifyacyclicity = false;
02027 }
02028 }
02029
02030
02031 other. addboundaries ();
02032 img. remove (other);
02033
02034
02035 if (verifyacyclicity && other. size ())
02036 {
02037
02038 if (!acyclic (other))
02039 {
02040 result = false;
02041 verifyacyclicity = false;
02042 }
02043 }
02044
02045
02046
02047 for (int j = 0; j <= img. dim (); ++ j)
02048 cm. add (d, thecell, img [j]);
02049
02050
02051 if (i && !(i % 373))
02052 scon << std::setw (12) << i <<
02053 "\b\b\b\b\b\b\b\b\b\b\b\b";
02054 }
02055 if (cset. size () > 373)
02056 scon << " \b\b\b\b\b\b\b\b\b\b\b\b";
02057 scon << '.';
02058 }
02059 scon << ' ';
02060 return result;
02061 }
02062
02063
02064
02066 template <class cell, class euclidom, class element>
02067 std::ostream &operator << (std::ostream &out,
02068 const mvcellmap<cell,euclidom,element> &m)
02069 {
02070 for (int d = 0; d <= m. dim (); ++ d)
02071 {
02072 out << "; Dimension " << d << ':' << '\n';
02073 const hashedset<cell> &cset = m. get (d);
02074 for (int_t i = 0; i < cset. size (); ++ i)
02075 {
02076 out << cset [i] << " -> ";
02077 write (out, m (cset [i]), SMALL_SIZE) << '\n';
02078 }
02079 }
02080 return out;
02081 }
02082
02083
02084 }
02085 }
02086
02087 #endif // _CHOMP_HOMOLOGY_GCOMPLEX_H_
02088
02090