00001
00002
00003
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059 #ifndef _CHOMP_HOMOLOGY_HOMOLOGY_H_
00060 #define _CHOMP_HOMOLOGY_HOMOLOGY_H_
00061
00062 #include "chomp/system/config.h"
00063 #include "chomp/system/textfile.h"
00064 #include "chomp/system/timeused.h"
00065 #include "chomp/system/arg.h"
00066 #include "chomp/struct/words.h"
00067 #include "chomp/struct/localvar.h"
00068 #include "chomp/homology/homtools.h"
00069 #include "chomp/cubes/bincube.h"
00070 #include "chomp/cubes/twolayer.h"
00071
00072 namespace chomp {
00073
00077 namespace homology {
00078
00079
00081 typedef chaincomplex<integer> ChainComplex;
00082
00084 typedef chainmap<integer> ChainMap;
00085
00087 typedef chain<integer> Chain;
00088
00090 typedef hashedset<simplex> SetOfSimplices;
00091
00093 typedef gcomplex<simplex,integer> SimplicialComplex;
00094
00095
00096
00097
00098
00099
00100
00101
00104 template <class euclidom>
00105 int BettiNumber (const chain<euclidom> &c)
00106 {
00107 int betti = 0;
00108 for (int i = 0; i < c. size (); ++ i)
00109 {
00110 if (c. coef (i). delta () == 1)
00111 ++ betti;
00112 }
00113 return betti;
00114 }
00115
00120 template <class euclidom>
00121 int TorsionCoefficient (const chain<euclidom> &c, int start = 0)
00122 {
00123 if (start < 0)
00124 return -1;
00125 while (start < c. size ())
00126 {
00127 if (c. coef (start). delta () != 1)
00128 return start;
00129 else
00130 ++ start;
00131 }
00132 return -1;
00133 }
00134
00137 template <class euclidom>
00138 inline void ShowHomology (const chain<euclidom> &c)
00139 {
00140 int countfree = 0;
00141 bool writeplus = false;
00142
00143
00144 for (int i = 0; i < c. size (); ++ i)
00145 {
00146
00147 if (c. coef (i). delta () == 1)
00148 ++ countfree;
00149
00150 else
00151 {
00152 sout << (writeplus ? " + " : "") <<
00153 euclidom::ringsymbol () << "_" <<
00154 c. coef (i);
00155 writeplus = true;
00156 }
00157
00158
00159 if (countfree && ((i == c. size () - 1) ||
00160 (c. coef (i + 1). delta () != 1)))
00161 {
00162 sout << (writeplus ? " + " : "") <<
00163 euclidom::ringsymbol ();
00164 if (countfree > 1)
00165 sout << "^" << countfree;
00166 countfree = 0;
00167 writeplus = true;
00168 }
00169 }
00170
00171
00172 if (!c. size ())
00173 sout << "0";
00174
00175 return;
00176 }
00177
00180 template <class euclidom>
00181 void ShowHomology (const chain<euclidom> *hom, int maxlevel)
00182 {
00183 if (!hom)
00184 return;
00185
00186 for (int q = 0; q <= maxlevel; ++ q)
00187 {
00188 sout << "H_" << q << " = ";
00189 ShowHomology (hom [q]);
00190 sout << '\n';
00191 }
00192 return;
00193 }
00194
00197 template <class euclidom>
00198 inline void ShowHomology (const chainmap<euclidom> &hmap)
00199 {
00200 hmap. show (sout, "\tf", "x", "y");
00201 return;
00202 }
00203
00208 template <class euclidom>
00209 inline void ShowGenerator (const chain<euclidom> &c)
00210 {
00211 c. show (sout, "c");
00212 return;
00213 }
00214
00218 template <class euclidom>
00219 void ShowGenerators (const chain<euclidom> *c, int count)
00220 {
00221 for (int i = 0; i < count; ++ i)
00222 {
00223 sout << 'g' << (i + 1) << " = ";
00224 ShowGenerator (c [i]);
00225 sout << '\n';
00226 }
00227 return;
00228 }
00229
00233 template <class euclidom>
00234 void ShowGenerators (chain<euclidom> const * const * const gen,
00235 const chain<euclidom> *hom, int maxlevel)
00236 {
00237 for (int q = 0; q <= maxlevel; ++ q)
00238 {
00239 if (!hom [q]. size ())
00240 continue;
00241 sout << "[H_" << q << "]\n";
00242 ShowGenerators (gen [q], hom [q]. size ());
00243 sout << '\n';
00244 }
00245 return;
00246 }
00247
00251 template <class euclidom>
00252 void ShowGenerators (const chaincomplex<euclidom> &c,
00253 const chain<euclidom> *hom, int maxlevel)
00254 {
00255 for (int q = 0; q <= maxlevel; ++ q)
00256 {
00257 if (!hom [q]. size ())
00258 continue;
00259 sout << "[H_" << q << "]\n";
00260 for (int i = 0; i < hom [q]. size (); ++ i)
00261 {
00262 ShowGenerator (c. gethomgen (q, hom [q]. num (i)));
00263 sout << '\n';
00264 }
00265 sout << '\n';
00266 }
00267 return;
00268 }
00269
00272 template <class cell,class euclidom>
00273 void ShowGenerator (const chain<euclidom> &c, const hashedset<cell> &s)
00274 {
00275 if (!c. size ())
00276 sout << '0';
00277 for (int i = 0; i < c. size (); ++ i)
00278 {
00279 euclidom e = c. coef (i);
00280 if (e == 1)
00281 sout << (i ? " + " : "") << s [c. num (i)];
00282 else if (-e == 1)
00283 sout << (i ? " - " : "-") << s [c. num (i)];
00284 else
00285 {
00286 sout << (i ? " + " : "") << e << " * " <<
00287 s [c. num (i)];
00288 }
00289 }
00290 return;
00291 }
00292
00296 template <class cell,class euclidom>
00297 void ShowGenerators (const chain<euclidom> *c, int count,
00298 const hashedset<cell> &s)
00299 {
00300 for (int i = 0; i < count; ++ i)
00301 {
00302 sout << 'g' << (i + 1) << " = ";
00303 ShowGenerator (c [i], s);
00304 sout << '\n';
00305 }
00306 return;
00307 }
00308
00311 template <class euclidom,class cell>
00312 void ShowGenerators (chain<euclidom> * const *gen,
00313 const chain<euclidom> *hom,
00314 int maxlevel, const gcomplex<cell,euclidom> &gcompl)
00315 {
00316 for (int q = 0; q <= maxlevel; ++ q)
00317 {
00318 if (!hom [q]. size ())
00319 continue;
00320 sout << "[H_" << q << "]\n";
00321 ShowGenerators (gen [q], hom [q]. size (), gcompl [q]);
00322 sout << '\n';
00323 }
00324 return;
00325 }
00326
00327
00328
00329
00330
00331
00332
00333
00334
00339 template <class euclidom>
00340 chain<euclidom> **ExtractGenerators (const chaincomplex<euclidom> &cx,
00341 chain<euclidom> *hom, int maxlevel)
00342
00343
00344 {
00345
00346 if (maxlevel < 0)
00347 return 0;
00348
00349
00350 chain<euclidom> **gen = new chain<euclidom> * [maxlevel + 1];
00351
00352
00353 for (int q = 0; q <= maxlevel; ++ q)
00354 {
00355
00356 gen [q] = (hom [q]. size ()) ?
00357 new chain<euclidom> [hom [q]. size ()] : 0;
00358
00359
00360 for (int i = 0; i < hom [q]. size (); ++ i)
00361 {
00362 gen [q] [i] =
00363 cx. gethomgen (q, hom [q]. num (i));
00364 }
00365 }
00366
00367 return gen;
00368 }
00369
00379 template <class euclidom>
00380 int Homology (chaincomplex<euclidom> &cx, const char *Xname,
00381 chain<euclidom> *&hom)
00382
00383
00384 {
00385
00386 hom = 0;
00387
00388
00389 int Xdim = cx. dim ();
00390 if (Xdim < 0)
00391 return -1;
00392
00393
00394 sout << "Computing the homology of " << Xname << " over " <<
00395 euclidom::ringname () << "...\n";
00396 cx. simple_form ((int *) 0, false);
00397 cx. simple_homology (hom);
00398
00399
00400 int maxlevel = Xdim;
00401 while ((maxlevel >= 0) && (hom [maxlevel]. size () <= 0))
00402 -- maxlevel;
00403
00404
00405 if (hom && (maxlevel < 0))
00406 {
00407 delete [] hom;
00408 hom = 0;
00409 }
00410
00411 return maxlevel;
00412 }
00413
00425 template <class cell, class euclidom>
00426 int Homology (gcomplex<cell,euclidom> &Xcompl, const char *Xname,
00427 chain<euclidom> *&hom, chain<euclidom> ***gen = 0)
00428
00429
00430 {
00431
00432 hom = 0;
00433
00434
00435 int Xdim = Xcompl. dim ();
00436 if (Xdim < 0)
00437 return -1;
00438
00439
00440
00441 chaincomplex<euclidom> cx (Xdim, !!gen);
00442 sout << "Creating the chain complex of " << Xname << "... ";
00443 createchaincomplex (cx, Xcompl);
00444 sout << "Done.\n";
00445
00446
00447 if (!gen)
00448 {
00449 gcomplex<cell,euclidom> empty;
00450 Xcompl = empty;
00451 }
00452
00453
00454 int maxlevel = Homology (cx, Xname, hom);
00455
00456
00457 if (gen)
00458 *gen = ExtractGenerators (cx, hom, maxlevel);
00459
00460 return maxlevel;
00461 }
00462
00469 template <class euclidom, class cubetype>
00470 int Homology (hashedset<cubetype> &Xcubes, const char *Xname,
00471 chain<euclidom> *&hom, chain<euclidom> ***gen = 0,
00472 gcomplex<typename cubetype::CellType,euclidom> **gcompl = 0)
00473
00474
00475 {
00476
00477 typedef hashedset<cubetype> cubsettype;
00478
00479
00480 typedef typename cubetype::CellType celltype;
00481
00482
00483 hom = 0;
00484
00485
00486 if (Xcubes. empty ())
00487 return -1;
00488
00489
00490 int Xspacedim = Xcubes [0]. dim ();
00491
00492
00493 knownbits [Xspacedim];
00494
00495
00496 cubsettype emptycubes;
00497 reducepair (Xcubes, emptycubes, emptycubes, Xname, 0);
00498
00499
00500 gcomplex<celltype,euclidom> *Xcompl =
00501 new gcomplex<celltype,euclidom>;
00502 cubes2cells (Xcubes, *Xcompl, Xname);
00503 Xcubes = emptycubes;
00504
00505
00506 collapse (*Xcompl, Xname);
00507
00508
00509 if (Xcompl -> empty ())
00510 {
00511 delete Xcompl;
00512 return -1;
00513 }
00514
00515
00516 int Xdim = Xcompl -> dim ();
00517 if (Xdim != Xspacedim)
00518 {
00519 sout << "Note: The dimension of " << Xname <<
00520 " decreased from " << Xspacedim <<
00521 " to " << Xdim << ".\n";
00522 }
00523
00524
00525 int maxlevel = Homology (*Xcompl, Xname, hom, gen);
00526
00527
00528 if (!gcompl)
00529 delete Xcompl;
00530 else
00531 *gcompl = Xcompl;
00532
00533 return maxlevel;
00534 }
00535
00544 template <class cell, class euclidom>
00545 int Homology (gcomplex<cell,euclidom> &Xcompl, const char *Xname,
00546 gcomplex<cell,euclidom> &Acompl, const char *Aname,
00547 chain<euclidom> *&hom, chain<euclidom> ***gen = 0)
00548
00549
00550
00551 {
00552
00553 hom = 0;
00554
00555
00556 int Xdim = Xcompl. dim ();
00557 if (Xdim < 0)
00558 return -1;
00559
00560
00561 word pairname;
00562 if (!Acompl. empty ())
00563 pairname << '(' << Xname << "," << Aname << ')';
00564 else
00565 pairname << Xname;
00566
00567
00568
00569 collapse (Xcompl, Acompl, Xname, Aname);
00570
00571
00572 gcomplex<cell,euclidom> emptycompl;
00573 Acompl = emptycompl;
00574
00575
00576 if (Xdim != Xcompl. dim ())
00577 {
00578 sout << "Note: The dimension of " << Xname <<
00579 " decreased from " << Xdim << " to " <<
00580 Xcompl. dim () << ".\n";
00581 }
00582
00583
00584 int maxlevel = Homology (Xcompl, pairname, hom, gen);
00585
00586
00587 return maxlevel;
00588 }
00589
00599 template <class euclidom, class cubetype>
00600 int Homology (hashedset<cubetype> &Xcubes, const char *Xname,
00601 hashedset<cubetype> &Acubes, const char *Aname,
00602 chain<euclidom> *&hom, chain<euclidom> ***gen = 0,
00603 gcomplex<typename cubetype::CellType,euclidom> **gcompl = 0)
00604
00605
00606
00607 {
00608
00609 typedef hashedset<cubetype> cubsettype;
00610
00611
00612 typedef typename cubetype::CellType celltype;
00613
00614
00615 hom = 0;
00616
00617
00618 if (Acubes. empty ())
00619 return Homology (Xcubes, Xname, hom, gen, gcompl);
00620
00621
00622 removeAfromX (Xcubes, Acubes, Xname, Aname);
00623
00624
00625 if (Xcubes. empty ())
00626 return -1;
00627
00628
00629 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
00630
00631
00632 int Xspacedim = Xcubes [0]. dim ();
00633
00634
00635 knownbits [Xspacedim];
00636
00637
00638 if (!gcompl)
00639 expandAinX (Xcubes, Acubes, Xname, Aname);
00640
00641
00642 if (Xcubes. empty ())
00643 return -1;
00644
00645
00646 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
00647
00648
00649 cubsettype emptycubes;
00650 reducepair (Xcubes, Acubes, emptycubes, Xname, Aname);
00651
00652
00653 if (Xcubes. empty ())
00654 return -1;
00655
00656
00657 word diffname;
00658 diffname << Xname << '\\' << Aname;
00659
00660
00661 gcomplex<celltype,euclidom> *Xcompl =
00662 new gcomplex<celltype,euclidom>;
00663 cubes2cells (Xcubes, *Xcompl, diffname);
00664 Xcubes = emptycubes;
00665
00666
00667 gcomplex<celltype,euclidom> Acompl;
00668 cubes2cells (Acubes, Acompl, Aname);
00669 Acubes = emptycubes;
00670
00671
00672 int maxlevel = Homology (*Xcompl, Xname, Acompl, Aname, hom, gen);
00673
00674
00675 if (!gcompl)
00676 delete Xcompl;
00677 else
00678 *gcompl = Xcompl;
00679
00680 return maxlevel;
00681 }
00682
00683
00684
00685
00686
00687
00688
00689
00706 template <class euclidom>
00707 chainmap<euclidom> *HomologyMap (const chainmap<euclidom> &cmap,
00708 const chain<euclidom> *hom_cx,
00709 const chain<euclidom> *hom_cy, int maxlevel)
00710
00711
00712 {
00713
00714 if (maxlevel < 0)
00715 return 0;
00716
00717
00718 chaincomplex<euclidom> hx (maxlevel);
00719 chaincomplex<euclidom> hy (maxlevel);
00720 chainmap<euclidom> *hmap = new chainmap<euclidom> (hx, hy);
00721
00722
00723 hx. take_homology (hom_cx);
00724 hy. take_homology (hom_cy);
00725
00726
00727 hmap -> take_homology (cmap, hom_cx, hom_cy);
00728 return hmap;
00729 }
00730
00734 template <class euclidom>
00735 chainmap<euclidom> *HomologyMap (const chainmap<euclidom> &cmap,
00736 const chain<euclidom> *hom_cx, int maxlevel)
00737
00738
00739 {
00740
00741 if (maxlevel < 0)
00742 return 0;
00743
00744
00745 chaincomplex<euclidom> hx (maxlevel);
00746 chainmap<euclidom> *hmap = new chainmap<euclidom> (hx, hx);
00747
00748
00749 hx. take_homology (hom_cx);
00750
00751
00752 hmap -> take_homology (cmap, hom_cx, hom_cx);
00753 return hmap;
00754 }
00755
00768 template <class euclidom, class cubetype>
00769 int Homology (mvmap<cubetype,cubetype> &Fcubmap, const char *Fname,
00770 hashedset<cubetype> &Xcubes, const char *Xname,
00771 hashedset<cubetype> &Acubes, const char *Aname,
00772 hashedset<cubetype> &Ycubes, const char *Yname,
00773 hashedset<cubetype> &Bcubes, const char *Bname,
00774 chain<euclidom> *&hom_cx, int &maxlevel_cx,
00775 chain<euclidom> *&hom_cy, int &maxlevel_cy,
00776 chainmap<euclidom> *&hom_f,
00777 bool inclusion = false, int careful = 0x01,
00778 chain<euclidom> ***gfgen = 0,
00779 gcomplex<typename cubetype::CellType,euclidom> **gfcompl = 0,
00780 chain<euclidom> ***gygen = 0,
00781 gcomplex<typename cubetype::CellType,euclidom> **gycompl = 0)
00782 {
00783
00784 typedef hashedset<cubetype> cubsettype;
00785
00786
00787 typedef typename cubetype::CellType celltype;
00788
00789
00790 typedef mvmap<cubetype,cubetype> cubmaptype;
00791
00792
00793 bool verify = careful & 0x01;
00794 bool checkacyclic = careful & 0x02;
00795
00796
00797 word XAname, YBname;
00798 if (!Acubes. empty ())
00799 XAname << Xname << '\\' << Aname;
00800 else
00801 XAname << Xname;
00802 if (!Bcubes. empty ())
00803 YBname << Yname << '\\' << Bname;
00804 else
00805 YBname << Yname;
00806
00807
00808
00809
00810 if (&Xcubes == &Ycubes)
00811 throw "You must clone the sets passed to Homology.";
00812
00813
00814 removeAfromX (Xcubes, Acubes, Xname, Aname);
00815
00816
00817 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
00818
00819
00820 removeAfromX (Ycubes, Bcubes, Yname, Bname);
00821
00822
00823 if (Xcubes. empty () || Ycubes. empty ())
00824 return -1;
00825
00826
00827 int_t origAsize = Acubes. size ();
00828 int_t origXsize = Xcubes. size ();
00829
00830
00831 int Xspacedim = Xcubes [0]. dim ();
00832 int Yspacedim = Ycubes [0]. dim ();
00833
00834
00835 if (verify)
00836 checkimagecontained (Fcubmap, Xcubes, Ycubes, Bcubes,
00837 XAname, Yname);
00838
00839
00840 if (verify && !Acubes. empty ())
00841 checkimagecontained (Fcubmap, Acubes, Bcubes, Aname, Bname);
00842
00843
00844 if (verify && !Acubes. empty ())
00845 checkimagedisjoint (Fcubmap, Acubes, Ycubes, Aname, YBname);
00846
00847
00848 if (verify && inclusion)
00849 checkinclusion (Xcubes, Ycubes, Bcubes, XAname, Yname);
00850 if (verify && inclusion)
00851 checkinclusion (Acubes, Bcubes, Aname, Bname);
00852
00853
00854
00855
00856 knownbits [Xspacedim];
00857 knownbits [Yspacedim];
00858
00859
00860 if (!checkacyclic)
00861 {
00862
00863 cubsettype empty;
00864 reducepair (Xcubes, Acubes, empty, Xname, Aname);
00865
00866
00867 if (Xcubes. empty ())
00868 return -1;
00869 }
00870
00871
00872 if (!Acubes. empty () && !gfgen && !gygen)
00873 {
00874 expandAinX (Xcubes, Acubes, Ycubes, Bcubes, Fcubmap,
00875 Xname, Aname, Bname, inclusion, checkacyclic);
00876 }
00877
00878
00879 if (checkacyclic && !Acubes. empty ())
00880 {
00881
00882 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
00883
00884
00885 cubsettype emptycubes;
00886 reducepair (Xcubes, Acubes, Fcubmap, emptycubes,
00887 Xname, Aname);
00888
00889
00890 if (Xcubes. empty ())
00891 return -1;
00892 }
00893
00894
00895 if (!checkacyclic && !Acubes. empty ())
00896 {
00897
00898 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
00899
00900
00901 cubsettype empty;
00902 reducepair (Xcubes, Acubes, empty, Xname, Aname);
00903 }
00904
00905
00906 if (!verify)
00907 {
00908 if (!checkacyclic && ((origAsize != Acubes. size ()) ||
00909 (origXsize != Xcubes. size ())))
00910 {
00911 sout << "*** Important note: " << Xname << " or " <<
00912 Aname << " changed. You must make sure\n"
00913 "*** that the restriction of " << Fname <<
00914 " to the new sets is acyclic.\n";
00915 }
00916 else
00917 {
00918 sout << "*** Note: The program assumes "
00919 "that the input map is acyclic.\n";
00920 }
00921 }
00922
00923
00924
00925 cubsettype Ykeepcubes;
00926 sout << "Computing the image of the map... ";
00927 for (int_t i = 0; i < Xcubes. size (); ++ i)
00928 Ykeepcubes. add (Fcubmap (Xcubes [i]));
00929 for (int_t i = 0; i < Acubes. size (); ++ i)
00930 Ykeepcubes. add (Fcubmap (Acubes [i]));
00931 if (inclusion)
00932 {
00933 sout << "and of the inclusion... ";
00934 Ykeepcubes. add (Xcubes);
00935 Ykeepcubes. add (Acubes);
00936 }
00937 sout << Ykeepcubes. size () << " cubes.\n";
00938
00939
00940 if (Xspacedim == Yspacedim)
00941 {
00942 if (!gygen)
00943 expandAinX (Ycubes, Bcubes, Yname, Bname);
00944 restrictAtoneighbors (Ycubes, Bcubes, Yname, Bname,
00945 &Ykeepcubes);
00946 reducepair (Ycubes, Bcubes, Ykeepcubes, Yname, Bname);
00947 }
00948
00949
00950 if (!Ykeepcubes. empty ())
00951 {
00952 cubsettype empty;
00953 Ykeepcubes = empty;
00954 }
00955
00956
00957
00958
00959 gcomplex<celltype,euclidom> Xcompl;
00960 cubes2cells (Xcubes, Xcompl, XAname, false);
00961
00962
00963 gcomplex<celltype,euclidom> Acompl;
00964 cubes2cells (Acubes, Acompl, Aname, false);
00965
00966
00967 gcomplex<celltype,euclidom> *Ycompl =
00968 new gcomplex<celltype,euclidom>;
00969 cubes2cells (Ycubes, *Ycompl, YBname);
00970
00971
00972 gcomplex<celltype,euclidom> Bcompl;
00973 cubes2cells (Bcubes, Bcompl, Bname);
00974
00975
00976 int Xdim = Xcompl. dim ();
00977 int Ydim = Ycompl -> dim ();
00978
00979
00980
00981
00982
00983 gcomplex<celltype,euclidom> emptycompl;
00984 collapse (Xcompl, Acompl, emptycompl, Xname, Aname,
00985 true, true, false);
00986
00987
00988 if (Xcompl. empty ())
00989 return -1;
00990
00991
00992 if (Xdim != Xcompl. dim ())
00993 {
00994 sout << "Note: The dimension of " << Xname << " decreased "
00995 "from " << Xdim << " to " << Xcompl. dim () << ".\n";
00996
00997 Xdim = Xcompl. dim ();
00998 }
00999
01000
01001
01002
01003 mvcellmap<celltype,euclidom,cubetype> Fcellcubmap (Xcompl);
01004 sout << "Creating the map " << Fname << " on cells in " <<
01005 Xname << "... ";
01006 int_t countimages = createimages (Fcellcubmap, Fcubmap, Fcubmap,
01007 Xcubes, Acubes);
01008 sout << countimages << " cubes added.\n";
01009
01010
01011 mvcellmap<celltype,euclidom,cubetype> FcellcubmapA (Acompl);
01012 if (!Acompl. empty ())
01013 {
01014 sout << "Creating the map " << Fname << " on cells in " <<
01015 Aname << "... ";
01016 int_t count = createimages (FcellcubmapA, Fcubmap, Acubes);
01017 sout << count << " cubes added.\n";
01018 }
01019
01020
01021
01022 {
01023 cubsettype emptycubes;
01024 Acubes = emptycubes;
01025 Xcubes = emptycubes;
01026 cubmaptype emptymap;
01027 Fcubmap = emptymap;
01028 }
01029
01030
01031 sout << "Creating a cell map for " << Fname << "... ";
01032 mvcellmap<celltype,euclidom,celltype> Fcellmap (Xcompl);
01033 bool acyclic = createcellmap (Fcellcubmap, FcellcubmapA,
01034 Fcellmap, verify);
01035 sout << "Done.\n";
01036 if (verify && !acyclic)
01037 {
01038 sout << "*** SERIOUS PROBLEM: The map is not "
01039 "acyclic. THE RESULT WILL BE WRONG.\n"
01040 "*** You must verify the acyclicity of the "
01041 "initial map with 'chkmvmap'\n"
01042 "*** and, if successful, set the "
01043 "'careful reduction' bit.\n";
01044 }
01045 if (verify && acyclic)
01046 {
01047 sout << "Note: It has been verified successfully "
01048 "that the map is acyclic.\n";
01049 }
01050
01051 sout << "Creating the graph of " << Fname << "... ";
01052 gcomplex<celltype,euclidom> *Fcompl =
01053 new gcomplex<celltype,euclidom>;
01054 creategraph (Fcellmap, *Fcompl, false);
01055 sout << Fcompl -> size () << " cells added.\n";
01056
01057
01058 mvcellmap<celltype,euclidom,cubetype> emptycellcubmap;
01059 Fcellcubmap = emptycellcubmap;
01060 FcellcubmapA = emptycellcubmap;
01061 mvcellmap<celltype,euclidom,celltype> emptycellmap (emptycompl);
01062 Fcellmap = emptycellmap;
01063 Xcompl = emptycompl;
01064
01065
01066
01067
01068 decreasedimension (Bcompl, Ydim, Bname);
01069
01070
01071 addboundaries (*Ycompl, Bcompl, 0, false, Yname, Bname);
01072
01073
01074 if (!Bcompl. empty ())
01075 {
01076 sout << "Forgetting " << Bcompl. size () << " cells from " <<
01077 Bname << ".\n";
01078 gcomplex<celltype,euclidom> empty;
01079 Bcompl = empty;
01080 }
01081
01082
01083 gcomplex<celltype,euclidom> Ykeepcompl;
01084 sout << "Computing the image of " << Fname << "... ";
01085 project (*Fcompl, Ykeepcompl, *Ycompl, Xspacedim, Yspacedim,
01086 0, 0, false);
01087 if (inclusion)
01088 {
01089 project (*Fcompl, Ykeepcompl, *Ycompl, 0, Xspacedim,
01090 Yspacedim, 0, false);
01091 }
01092 sout << Ykeepcompl. size () << " cells.\n";
01093
01094 sout << "Collapsing " << Yname << " to img of " << Xname << "... ";
01095 int_t countremoved = Ycompl -> collapse (emptycompl, Ykeepcompl,
01096 0, 0, 0);
01097 sout << 2 * countremoved << " cells removed, " <<
01098 Ycompl -> size () << " left.\n";
01099
01100
01101 if (!Ykeepcompl. empty ())
01102 {
01103 gcomplex<celltype,euclidom> empty;
01104 Ykeepcompl = empty;
01105 }
01106
01107
01108 if (Ydim != Ycompl -> dim ())
01109 {
01110 sout << "Note: The dimension of " << Yname << " decreased "
01111 "from " << Ydim << " to " << Ycompl -> dim () <<
01112 ".\n";
01113
01114 Ydim = Ycompl -> dim ();
01115 }
01116
01117
01118
01119
01120 chaincomplex<euclidom> cgraph (Fcompl -> dim (), !!gfgen);
01121 sout << "Creating the chain complex of the graph of " << Fname <<
01122 "... ";
01123 createchaincomplex (cgraph, *Fcompl);
01124 sout << "Done.\n";
01125
01126
01127 chaincomplex<euclidom> cy (Ydim, !!gygen);
01128 sout << "Creating the chain complex of " << Yname << "... ";
01129 createchaincomplex (cy, *Ycompl);
01130 sout << "Done.\n";
01131
01132
01133 chainmap<euclidom> cmap (cgraph, cy);
01134 sout << "Creating the chain map of the projection... ";
01135 createprojection (*Fcompl, *Ycompl, cmap, Xspacedim, Yspacedim, 0);
01136 sout << "Done.\n";
01137
01138
01139
01140 chainmap<euclidom> imap (cgraph, cy);
01141 if (inclusion)
01142 {
01143 sout << "Creating the chain map of the inclusion... ";
01144 createprojection (*Fcompl, *Ycompl, imap, 0, Xspacedim,
01145 Yspacedim);
01146 sout << "Done.\n";
01147 }
01148
01149
01150 if (gfcompl)
01151 (*gfcompl) = Fcompl;
01152 else
01153 delete Fcompl;
01154
01155
01156 if (gycompl)
01157 (*gycompl) = Ycompl;
01158 else
01159 delete Ycompl;
01160
01161
01162
01163
01164 word gFname;
01165 gFname << "the graph of " << Fname;
01166
01167
01168 maxlevel_cx = Homology (cgraph, gFname, hom_cx);
01169
01170
01171 if (gfgen)
01172 *gfgen = ExtractGenerators (cgraph, hom_cx, maxlevel_cx);
01173
01174
01175 maxlevel_cy = Homology (cy, Yname, hom_cy);
01176
01177
01178 if (gygen)
01179 *gygen = ExtractGenerators (cy, hom_cy, maxlevel_cy);
01180
01181
01182
01183
01184 chaincomplex<euclidom> hgraph (maxlevel_cx);
01185 chaincomplex<euclidom> hy (maxlevel_cy);
01186 chainmap<euclidom> *hmap = new chainmap<euclidom> (hgraph, hy);
01187 chainmap<euclidom> hincl (hgraph, hy);
01188
01189 chainmap<euclidom> *hcomp = new chainmap<euclidom> (hy, hy);
01190
01191
01192 sout << "The map induced in homology is as follows:\n";
01193 hgraph. take_homology (hom_cx);
01194 hy. take_homology (hom_cy);
01195 hmap -> take_homology (cmap, hom_cx, hom_cy);
01196 hmap -> show (sout, "\tf", "x", "y");
01197
01198
01199 bool invertible = true;
01200 if (inclusion)
01201 {
01202 sout << "The map induced in homology by the inclusion:\n";
01203 hincl. take_homology (imap, hom_cx, hom_cy);
01204 hincl. show (sout, "\ti", "x", "y");
01205
01206 try
01207 {
01208 hincl. invert ();
01209 }
01210 catch (...)
01211 {
01212 sout << "Oh, my goodness! This map is apparently "
01213 "not invertible.\n";
01214 invertible = false;
01215 }
01216
01217 if (invertible)
01218 {
01219 sout << "The inverse of the map "
01220 "induced by the inclusion:\n";
01221 hincl. show (sout, "\tI", "y", "x");
01222
01223
01224 chainmap<euclidom> hincl1 (hgraph, hy);
01225 hincl1. take_homology (imap, hom_cx, hom_cy);
01226 chainmap<euclidom> hident (hy, hy);
01227 hident. compose (hincl1, hincl);
01228 sbug << "The composition of the inclusion and "
01229 "its inverse (should be the identity):\n";
01230 hident. show (sbug, "\tid", "y", "y");
01231 for (int i = 0; i <= hident. dim (); ++ i)
01232 {
01233 const mmatrix<euclidom> &m = hident [i];
01234 if (m. getnrows () != m. getncols ())
01235 throw "INV: Inequal rows and cols.";
01236 euclidom zero, one;
01237 zero = 0;
01238 one = 1;
01239 for (int c = 0; c < m. getncols (); ++ c)
01240 {
01241 for (int r = 0; r < m. getnrows ();
01242 ++ r)
01243 {
01244 if ((r == c) && (m. get
01245 (r, c) == one))
01246 {
01247 continue;
01248 }
01249 if (m. get (r, c) == zero)
01250 continue;
01251 throw "INV: Non-identity.";
01252 }
01253 }
01254 }
01255
01256
01257 sout << "The composition of F and the inverse "
01258 "of the map induced by the inclusion:\n";
01259
01260 hcomp -> compose (*hmap, hincl);
01261
01262 hcomp -> show (sout, "\tF", "y", "y");
01263 }
01264 }
01265
01266
01267 if (inclusion && invertible)
01268 {
01269 hom_f = hcomp;
01270 delete hmap;
01271 }
01272 else
01273 {
01274 hom_f = hmap;
01275 delete hcomp;
01276 }
01277
01278
01279 if (inclusion && !invertible)
01280 throw "Unable to invert the inclusion map.";
01281
01282 return ((maxlevel_cx < maxlevel_cy) ? maxlevel_cx : maxlevel_cy);
01283 }
01284
01286 template <class euclidom, class cubetype>
01287 int Homology (mvmap<cubetype,cubetype> &Fcubmap,
01288 hashedset<cubetype> &Xcubes, hashedset<cubetype> &Acubes,
01289 hashedset<cubetype> &Ycubes, hashedset<cubetype> &Bcubes,
01290 chain<euclidom> *&hom_cx, int &maxlevel_cx,
01291 chain<euclidom> *&hom_cy, int &maxlevel_cy,
01292 chainmap<euclidom> *&hom_f,
01293 bool inclusion = false, int careful = 0x01,
01294 chain<euclidom> ***gfgen = 0,
01295 gcomplex<typename cubetype::CellType,euclidom> **gfcompl = 0,
01296 chain<euclidom> ***gygen = 0,
01297 gcomplex<typename cubetype::CellType,euclidom> **gycompl = 0)
01298 {
01299 return Homology (Fcubmap, "F", Xcubes, "X", Acubes, "A",
01300 Ycubes, "Y", Bcubes, "B", hom_cx, maxlevel_cx,
01301 hom_cy, maxlevel_cy, hom_f, inclusion, careful,
01302 gfgen, gfcompl, gygen, gycompl);
01303 }
01304
01308 template <class euclidom, class cubetype>
01309 int Homology (mvmap<cubetype,cubetype> &Fcubmap, const char *Fname,
01310 hashedset<cubetype> &Xcubes, const char *Xname,
01311 hashedset<cubetype> &Acubes, const char *Aname,
01312 chain<euclidom> *&hom, int &maxlevel,
01313 chainmap<euclidom> *&hom_f, int careful = 0x01,
01314 chain<euclidom> ***gfgen = 0,
01315 gcomplex<typename cubetype::CellType,euclidom> **gfcompl = 0,
01316 chain<euclidom> ***gygen = 0,
01317 gcomplex<typename cubetype::CellType,euclidom> **gycompl = 0)
01318 {
01319 hashedset<cubetype> Ycubes = Xcubes, Bcubes = Acubes;
01320 chain<euclidom> *hom_cy = 0;
01321 int maxlevel_cy;
01322 int result = Homology (Fcubmap, Fname, Xcubes, Xname, Acubes, Aname,
01323 Ycubes, Xname, Bcubes, Aname, hom, maxlevel,
01324 hom_cy, maxlevel_cy, hom_f, true, careful,
01325 gfgen, gfcompl, gygen, gycompl);
01326 delete [] hom_cy;
01327 return result;
01328 }
01329
01331 template <class euclidom, class cubetype>
01332 int Homology (mvmap<cubetype,cubetype> &Fcubmap,
01333 hashedset<cubetype> &Xcubes, hashedset<cubetype> &Acubes,
01334 chain<euclidom> *&hom, int &maxlevel,
01335 chainmap<euclidom> *&hom_f, int careful = 0x01,
01336 chain<euclidom> ***gfgen = 0,
01337 gcomplex<typename cubetype::CellType,euclidom> **gfcompl = 0,
01338 chain<euclidom> ***gygen = 0,
01339 gcomplex<typename cubetype::CellType,euclidom> **gycompl = 0)
01340 {
01341 return Homology (Fcubmap, "F", Xcubes, "X", Acubes, "A", hom,
01342 maxlevel, hom_f, careful, gfgen, gfcompl, gygen, gycompl);
01343 }
01344
01345
01346
01347
01348
01349
01353 template <class euclidom, class cubetype>
01354 int Homology2l (mvmap<cubetype,cubetype> &Fcubmap0, const char *Fname,
01355 hashedset<cubetype> &Xcubes0, const char *Xname,
01356 hashedset<cubetype> &Acubes0, const char *Aname,
01357 chain<euclidom> *&hom_cx, int &maxlevel,
01358 chainmap<euclidom> *&hom_f, int careful = 0x01,
01359 chain<euclidom> ***gfgen = 0,
01360 gcomplex<tCell2l<typename cubetype::CellType>,euclidom>
01361 **gfcompl = 0, chain<euclidom> ***gygen = 0,
01362 gcomplex<tCell2l<typename cubetype::CellType>,euclidom>
01363 **gycompl = 0)
01364 {
01365
01366 typedef tCube2l<cubetype> cube2ltype;
01367 typedef typename cube2ltype::CellType cell2ltype;
01368
01369
01370 local_var<int> TurnOffMaxBddDim (MaxBddDim, 0);
01371
01372
01373 bool verify = careful & 0x01;
01374 bool checkacyclic = careful & 0x02;
01375
01376
01377 removeAfromX (Xcubes0, Acubes0, "X", "A");
01378
01379
01380 restrictAtoneighbors (Xcubes0, Acubes0, "X", "A");
01381
01382
01383 if (Xcubes0. empty ())
01384 {
01385 sout << "X is a subset of A. The homology of (X,A) "
01386 "is trivial and the map is 0.";
01387 return -1;
01388 }
01389
01390
01391
01392
01393 sout << "Defining the two-layer structure... ";
01394 cube2ltype::setlayers (Xcubes0, Acubes0);
01395
01396
01397 hashedset<cube2ltype> Xcubes;
01398 for (int_t i = 0; i < Xcubes0. size (); ++ i)
01399 Xcubes. add (cube2ltype (Xcubes0 [i], 1));
01400 hashedset<cube2ltype> Acubes;
01401 for (int_t i = 0; i < Acubes0. size (); ++ i)
01402 Acubes. add (cube2ltype (Acubes0 [i], 0));
01403
01404
01405 sout << cube2ltype::layer1 (). size () << "+" <<
01406 cube2ltype::layer0 (). size () << " cubes, " <<
01407 cell2ltype::identify (). size () << " cells.\n";
01408
01409
01410
01411
01412 sout << "Creating the sets Y and B... ";
01413 hashedset<cube2ltype> Ycubes (Xcubes);
01414 hashedset<cube2ltype> Bcubes (Acubes);
01415 for (int_t i = 0; i < Xcubes0. size (); ++ i)
01416 {
01417 const hashedset<cubetype> &img = Fcubmap0 (Xcubes0 [i]);
01418 for (int_t j = 0; j < img. size (); ++ j)
01419 {
01420 if (!Xcubes0. check (img [j]))
01421 Bcubes. add (cube2ltype (img [j], 0));
01422 }
01423 }
01424 for (int_t i = 0; i < Acubes0. size (); ++ i)
01425 {
01426 const hashedset<cubetype> &img = Fcubmap0 (Acubes0 [i]);
01427 for (int_t j = 0; j < img. size (); ++ j)
01428 Bcubes. add (cube2ltype (img [j], 0));
01429 }
01430 sout << Ycubes. size () << " cubes in Y\\B, " <<
01431 Bcubes. size () << " in B.\n";
01432
01433
01434 mvmap<cube2ltype,cube2ltype> Fcubmap;
01435 for (int_t i = 0; i < Xcubes0. size (); ++ i)
01436 {
01437
01438 const hashedset<cubetype> &img = Fcubmap0 (Xcubes0 [i]);
01439 if (img. empty ())
01440 throw "Empty image of a box in X.\n";
01441 for (int_t j = 0; j < img. size (); ++ j)
01442 {
01443 int layer = Xcubes0. check (img [j]) ? 1 : 0;
01444 Fcubmap [Xcubes [i]]. add
01445 (cube2ltype (img [j], layer));
01446 }
01447 }
01448 for (int_t i = 0; i < Acubes0. size (); ++ i)
01449 {
01450
01451 const hashedset<cubetype> &img = Fcubmap0 (Acubes0 [i]);
01452 if (img. empty ())
01453 throw "Empty image of a box in A.\n";
01454 for (int_t j = 0; j < img. size (); ++ j)
01455 Fcubmap [Acubes [i]]. add
01456 (cube2ltype (img [j], 0));
01457 }
01458
01459
01460 {
01461 hashedset<cubetype> empty;
01462 Xcubes0 = empty;
01463 Acubes0 = empty;
01464 }
01465 {
01466 mvmap<cubetype,cubetype> empty;
01467 Fcubmap0 = empty;
01468 }
01469
01470
01471 int_t origAsize = Acubes. size ();
01472 int_t origXsize = Xcubes. size ();
01473
01474
01475 int Xspacedim = Xcubes. empty () ? -1 : Xcubes [0]. dim ();
01476 int Yspacedim = Ycubes. empty () ? -1 : Ycubes [0]. dim ();
01477
01478
01479
01480
01481 hashedset<cube2ltype> Xkeepcubes;
01482
01483
01484 if (Xspacedim > 0)
01485 knownbits [Xspacedim];
01486
01487
01488 if (!Acubes. empty () && !checkacyclic)
01489 {
01490
01491 reducepair (Xcubes, Acubes, Xkeepcubes, "X", "A");
01492
01493
01494 if (Xcubes. empty ())
01495 {
01496 sout << "There are no cubes left "
01497 "in X\\A. The homology of (X,A) "
01498 "is trivial and the map is 0.";
01499 return -1;
01500 }
01501 }
01502
01503
01504 bool inclFABchecked = false;
01505 bool inclFXYchecked = false;
01506
01507
01508 if (checkacyclic)
01509 {
01510
01511 if (verify)
01512 {
01513 checkimagecontained (Fcubmap,
01514 Xcubes, Ycubes, Bcubes,
01515 Acubes. empty () ? "X" : "X\\A", "Y");
01516 inclFXYchecked = true;
01517 }
01518
01519 if (verify && !Acubes. empty ())
01520 {
01521 checkimagecontained (Fcubmap, Acubes, Bcubes,
01522 "A", "B");
01523 checkimagedisjoint (Fcubmap, Acubes, Ycubes,
01524 "A", "Y\\B");
01525 inclFABchecked = true;
01526 }
01527 }
01528 else if (!Acubes. empty ())
01529 {
01530
01531 if (verify)
01532 {
01533 checkimagecontained (Fcubmap,
01534 Xcubes, Ycubes, Bcubes,
01535 Acubes. empty () ? "X" : "X\\A", "Y");
01536 inclFXYchecked = true;
01537 }
01538 }
01539
01540
01541 if (!Acubes. empty ())
01542 {
01543
01544 expandAinX (Xcubes, Acubes, Ycubes, Bcubes, Fcubmap,
01545 "X", "A", "B", true , checkacyclic);
01546 }
01547
01548
01549 if (checkacyclic)
01550 {
01551
01552 restrictAtoneighbors (Xcubes, Acubes, "X", "A");
01553
01554
01555 reducepair (Xcubes, Acubes, Fcubmap, Xkeepcubes, "X", "A");
01556
01557
01558 if (Xcubes. empty ())
01559 {
01560 sout << "There are no cubes left "
01561 "in X\\A. The homology of (X,A) "
01562 "is trivial and the map is 0.";
01563 return -1;
01564 }
01565 }
01566
01567
01568 if (!checkacyclic && !Acubes. empty ())
01569 {
01570
01571 restrictAtoneighbors (Xcubes, Acubes, "X", "A");
01572
01573
01574 reducepair (Xcubes, Acubes, Xkeepcubes, "X", "A");
01575 }
01576
01577
01578 if (!verify)
01579 {
01580 if (!checkacyclic && ((origAsize != Acubes. size ()) ||
01581 (origXsize != Xcubes. size ())))
01582 {
01583 sout << "*** Important note: X or A changed. "
01584 "You must make sure\n"
01585 "*** that the restriction of F "
01586 "to the new sets is acyclic.\n";
01587 }
01588 else
01589 {
01590 sout << "*** Note: The program assumes "
01591 "that the input map is acyclic.\n";
01592 }
01593 }
01594
01595
01596 if (verify && !inclFXYchecked)
01597 {
01598 checkimagecontained (Fcubmap, Xcubes, Ycubes, Bcubes,
01599 Acubes. empty () ? "X" : "X\\A", "Y");
01600 inclFXYchecked = true;
01601 }
01602
01603
01604 if (verify && !inclFABchecked && !Acubes. empty ())
01605 {
01606 checkimagecontained (Fcubmap, Acubes, Bcubes, "A", "B");
01607 checkimagedisjoint (Fcubmap, Acubes, Ycubes, "A", "Y\\B");
01608 inclFABchecked = true;
01609 }
01610
01611
01612
01613 hashedset<cube2ltype> Ykeepcubes;
01614 addmapimg (Fcubmap, Xcubes, Acubes, Ykeepcubes,
01615 true );
01616
01617
01618 if (Xspacedim == Yspacedim)
01619 {
01620 expandAinX (Ycubes, Bcubes, "Y", "B");
01621 restrictAtoneighbors (Ycubes, Bcubes, "Y", "B", &Ykeepcubes);
01622 reducepair (Ycubes, Bcubes, Ykeepcubes, "Y", "B");
01623 }
01624
01625
01626
01627
01628
01629 gcomplex<cell2ltype,euclidom> Xcompl;
01630 cubes2cells (Xcubes, Xcompl, Acubes. size () ? "X\\A" : "X", false);
01631
01632
01633
01634 gcomplex<cell2ltype,euclidom> Acompl;
01635 cubes2cells (Acubes, Acompl, "A", false);
01636
01637
01638 if (Xcompl. empty ())
01639 {
01640 if (!Acompl. empty ())
01641 sout << "The set X is contained in A. "
01642 "The homology of (X,A) is trivial.";
01643 else
01644 sout << "The set X is empty. "
01645 "The homology of X is trivial.";
01646 return -1;
01647 }
01648
01649
01650 gcomplex<cell2ltype,euclidom> *Ycompl =
01651 new gcomplex<cell2ltype,euclidom>;
01652 cubes2cells (Ycubes, *Ycompl, Bcubes. empty () ? "Y" : "Y\\B");
01653 if (!Ycubes. empty ())
01654 {
01655 hashedset<cube2ltype> empty;
01656 Ycubes = empty;
01657 }
01658
01659
01660 gcomplex<cell2ltype,euclidom> Bcompl;
01661 cubes2cells (Bcubes, Bcompl, "B");
01662 if (!Bcubes. empty ())
01663 {
01664 hashedset<cube2ltype> empty;
01665 Bcubes = empty;
01666 }
01667
01668
01669 gcomplex<cell2ltype,euclidom> Ykeepcompl;
01670 cubes2cells (Ykeepcubes, Ykeepcompl, "Ykeep");
01671 if (!Ykeepcubes. empty ())
01672 {
01673 hashedset<cube2ltype> empty;
01674 Ykeepcubes = empty;
01675 }
01676
01677
01678 int Xdim = Xcompl. dim ();
01679 if ((Xspacedim < 0) && (Xdim >= 0))
01680 Xspacedim = Xcompl [Xdim] [0]. spacedim ();
01681 int Ydim = Ycompl -> dim ();
01682 if ((Yspacedim < 0) && (Ydim >= 0))
01683 Yspacedim = (*Ycompl) [Ydim] [0]. spacedim ();
01684
01685
01686
01687
01688 gcomplex<cell2ltype,euclidom> Xkeepcompl;
01689
01690
01691
01692 collapse (Xcompl, Acompl, Xkeepcompl, "X", "A",
01693 true, true, false);
01694
01695
01696 if (Xcompl. empty ())
01697 {
01698 sout << "Nothing remains in X. "
01699 "The homology of (X,A) is trivial.";
01700 return -1;
01701 }
01702
01703
01704 if (!Xkeepcompl. empty ())
01705 {
01706 gcomplex<cell2ltype,euclidom> empty;
01707 Xkeepcompl = empty;
01708 }
01709
01710
01711 if (Xdim != Xcompl. dim ())
01712 {
01713 sout << "Note: The dimension of X decreased from " <<
01714 Xdim << " to " << Xcompl. dim () << ".\n";
01715
01716 Xdim = Xcompl. dim ();
01717 }
01718
01719
01720
01721
01722 mvcellmap<cell2ltype,euclidom,cube2ltype> Fcellcubmap (Xcompl);
01723 sout << "Creating the map F on cells in X... ";
01724 int_t countimages = createimages (Fcellcubmap, Fcubmap, Fcubmap,
01725 Xcubes, Acubes);
01726 sout << countimages << " cubes added.\n";
01727
01728
01729 if (Xcubes. size ())
01730 {
01731 hashedset<cube2ltype> empty;
01732 Xcubes = empty;
01733 }
01734
01735
01736 mvcellmap<cell2ltype,euclidom,cube2ltype> FcellcubmapA (Acompl);
01737 if (!Acompl. empty ())
01738 {
01739 sout << "Creating the map F on cells in A... ";
01740 int_t count = createimages (FcellcubmapA, Fcubmap, Acubes);
01741 sout << count << " cubes added.\n";
01742 }
01743
01744
01745 if (Acubes. size ())
01746 {
01747 hashedset<cube2ltype> empty;
01748 Acubes = empty;
01749 }
01750
01751
01752 gcomplex<cell2ltype,euclidom> *Fcompl =
01753 new gcomplex<cell2ltype,euclidom>;
01754 sout << "Creating a cell map for F... ";
01755 mvcellmap<cell2ltype,euclidom,cell2ltype> Fcellmap (Xcompl);
01756 bool acyclic = createcellmap (Fcellcubmap, FcellcubmapA,
01757 Fcellmap, verify);
01758 sout << "Done.\n";
01759 if (checkacyclic && !acyclic)
01760 {
01761 sout << "*** SERIOUS PROBLEM: The map is not "
01762 "acyclic. THE RESULT WILL BE WRONG.\n"
01763 "*** You must verify the acyclicity of the "
01764 "initial map with 'chkmvmap'\n"
01765 "*** and, if successful, run this program "
01766 "with the '-a' switch.\n";
01767 }
01768 if (checkacyclic && acyclic)
01769 {
01770 sout << "Note: It has been verified successfully "
01771 "that the map is acyclic.\n";
01772 }
01773
01774 sout << "Creating the graph of F... ";
01775 creategraph (Fcellmap, *Fcompl, false);
01776 sout << Fcompl -> size () << " cells added.\n";
01777
01778
01779 {
01780 mvcellmap<cell2ltype,euclidom,cube2ltype> empty;
01781 Fcellcubmap = empty;
01782 FcellcubmapA = empty;
01783 }
01784
01785
01786
01787
01788 decreasedimension (Bcompl, Ydim, "B");
01789
01790
01791 if (!Ycompl -> empty ())
01792 {
01793 addboundaries (*Ycompl, Bcompl, 0, false, "Y", "B");
01794
01795
01796 if (!Bcompl. empty ())
01797 {
01798 sout << "Forgetting " << Bcompl. size () <<
01799 " cells from B.\n";
01800 gcomplex<cell2ltype,euclidom> empty;
01801 Bcompl = empty;
01802 }
01803 }
01804
01805
01806 {
01807 sout << "Computing the image of F... ";
01808 int_t prev = Ykeepcompl. size ();
01809 project (*Fcompl, Ykeepcompl, *Ycompl, Xspacedim, Yspacedim,
01810 0, 0, false);
01811 project (*Fcompl, Ykeepcompl, *Ycompl, 0, Xspacedim,
01812 Yspacedim, 0, false);
01813 sout << (Ykeepcompl. size () - prev) << " cells added.\n";
01814
01815 sout << "Collapsing Y towards F(X)... ";
01816 gcomplex<cell2ltype,euclidom> empty;
01817 int_t count = Ycompl -> collapse (empty, Ykeepcompl,
01818 0, 0, 0, 0);
01819 sout << 2 * count << " cells removed, " <<
01820 Ycompl -> size () << " left.\n";
01821 }
01822
01823
01824 if (!Ykeepcompl. empty ())
01825 {
01826 gcomplex<cell2ltype,euclidom> empty;
01827 Ykeepcompl = empty;
01828 }
01829
01830
01831 if (Ydim != Ycompl -> dim ())
01832 {
01833 sout << "Note: The dimension of Y decreased from " <<
01834 Ydim << " to " << Ycompl -> dim () << ".\n";
01835
01836 Ydim = Ycompl -> dim ();
01837 }
01838
01839
01840
01841
01842
01843
01844
01845 chaincomplex<euclidom> cgraph (Fcompl -> dim (), false);
01846 sout << "Creating the chain complex of the graph of F... ";
01847 createchaincomplex (cgraph, *Fcompl);
01848 sout << "Done.\n";
01849
01850
01851 chaincomplex<euclidom> cy (Ydim, false);
01852 sout << "Creating the chain complex of Y... ";
01853 createchaincomplex (cy, *Ycompl);
01854 sout << "Done.\n";
01855
01856
01857 chainmap<euclidom> cmap (cgraph, cy);
01858 sout << "Creating the chain map of the projection... ";
01859 createprojection (*Fcompl, *Ycompl, cmap, Xspacedim,
01860 Yspacedim, 0);
01861 sout << "Done.\n";
01862
01863
01864
01865 chainmap<euclidom> imap (cgraph, cy);
01866 sout << "Creating the chain map of the inclusion... ";
01867 createprojection (*Fcompl, *Ycompl, imap, 0, Xspacedim, Yspacedim);
01868 sout << "Done.\n";
01869
01870
01871 if (gfcompl)
01872 (*gfcompl) = Fcompl;
01873 else
01874 delete Fcompl;
01875
01876
01877 if (gycompl)
01878 (*gycompl) = Ycompl;
01879 else
01880 delete Ycompl;
01881
01882
01883
01884
01885 word gFname;
01886 gFname << "the graph of " << Fname;
01887
01888
01889 int maxlevel_cx = Homology (cgraph, gFname, hom_cx);
01890
01891
01892 if (gfgen)
01893 *gfgen = ExtractGenerators (cgraph, hom_cx, maxlevel_cx);
01894
01895
01896 chain<euclidom> *hom_cy = 0;
01897 int maxlevel_cy = Homology (cy, Xname, hom_cy);
01898
01899
01900 if (gygen)
01901 *gygen = ExtractGenerators (cy, hom_cy, maxlevel_cy);
01902
01903
01904
01905
01906 int homdimgraph = cgraph. dim ();
01907 while ((homdimgraph >= 0) && (!hom_cx [homdimgraph]. size ()))
01908 -- homdimgraph;
01909 int homdimy = cy. dim ();
01910 while ((homdimy >= 0) && (!hom_cy [homdimy]. size ()))
01911 -- homdimy;
01912
01913
01914
01915
01916 chaincomplex<euclidom> hgraph (homdimgraph);
01917 chaincomplex<euclidom> hy (homdimy);
01918 chainmap<euclidom> *hmap = new chainmap<euclidom> (hgraph, hy);
01919 chainmap<euclidom> hincl (hgraph, hy);
01920 chainmap<euclidom> *hcomp = new chainmap<euclidom> (hgraph, hgraph);
01921
01922
01923 sout << "The map induced in homology is as follows:\n";
01924 hgraph. take_homology (hom_cx);
01925 hy. take_homology (hom_cy);
01926 hmap -> take_homology (cmap, hom_cx, hom_cy);
01927 hmap -> show (sout, "\tf", "x", "y");
01928
01929
01930 sout << "The map induced in homology by the inclusion:\n";
01931 hincl. take_homology (imap, hom_cx, hom_cy);
01932 hincl. show (sout, "\ti", "x", "y");
01933
01934 sout << "The inverse of the map induced by the inclusion:\n";
01935 bool invertible = true;
01936 try
01937 {
01938 hincl. invert ();
01939 }
01940 catch (...)
01941 {
01942 sout << "Oh, my goodness! This map is apparently "
01943 "not invertible.\n";
01944 invertible = false;
01945 }
01946
01947 if (invertible)
01948 {
01949 hincl. show (sout, "\tI", "y", "x");
01950
01951 sout << "The composition of F and the inverse "
01952 "of the map induced by the inclusion:\n";
01953 hcomp -> compose (hincl, *hmap);
01954 hcomp -> show (sout, "\tF", "x", "x");
01955 }
01956
01957
01958 if (invertible)
01959 {
01960 hom_f = hcomp;
01961 delete hmap;
01962 }
01963 else
01964 {
01965 hom_f = hmap;
01966 delete hcomp;
01967 }
01968
01969
01970 if (!invertible)
01971 throw "Unable to invert the inclusion map.";
01972
01973 maxlevel = (maxlevel_cx < maxlevel_cy) ? maxlevel_cx : maxlevel_cy;
01974 return maxlevel;
01975 }
01976
01978 template <class euclidom, class cubetype>
01979 int Homology2l (mvmap<cubetype,cubetype> &Fcubmap,
01980 hashedset<cubetype> &Xcubes, hashedset<cubetype> &Acubes,
01981 chain<euclidom> *&hom, int &maxlevel,
01982 chainmap<euclidom> *&hom_f, int careful = 0x01,
01983 chain<euclidom> ***gfgen = 0,
01984 gcomplex<tCell2l<typename cubetype::CellType>,euclidom>
01985 **gfcompl = 0, chain<euclidom> ***gygen = 0,
01986 gcomplex<tCell2l<typename cubetype::CellType>,euclidom>
01987 **gycompl = 0)
01988 {
01989 return Homology2l (Fcubmap, "F", Xcubes, "X", Acubes, "A", hom,
01990 maxlevel, hom_f, careful, gfgen, gfcompl, gygen, gycompl);
01991 }
01992
01993
01994
01995
01996
01997
02000 inline bool acyclic (const cube &q, const cubes &X)
02001 {
02002 int dim = q. dim ();
02003 BitField b;
02004 int_t maxneighbors = getmaxneighbors (dim);
02005 b. allocate (maxneighbors);
02006 bool result = acyclic (q, dim, X, &b, maxneighbors);
02007 b. free ();
02008 return result;
02009 }
02010
02011
02012
02013
02014
02015
02020 template <int dim, int twoPower>
02021 void ComputeBettiNumbers (bincube<dim,twoPower> &b, int *result)
02022 {
02023 using namespace chomp::homology;
02024 typedef typename bincube<dim,twoPower>::iterator cubetype;
02025 typedef typename bincube<dim,twoPower>::neighborhood_iterator
02026 neighbortype;
02027
02028
02029 sout << "Reducing the binary cube";
02030 int prev = b. count ();
02031 reduceFullCubes (b);
02032 sout << (prev - b. count ()) << " cubes removed, " <<
02033 b. count () << " left.\n";
02034
02035
02036 bincube<dim,twoPower> c;
02037
02038
02039 coordinate wrap [dim];
02040 bool setwrapping = false;
02041 for (int i = 0; i < dim; ++ i)
02042 {
02043 if (b. wrapped (i))
02044 {
02045 wrap [i] = 1 << twoPower;
02046 setwrapping = true;
02047 c. wrap (i);
02048 }
02049 else
02050 wrap [i] = 0;
02051 }
02052 if (setwrapping)
02053 tPointBase<coordinate>::setwrapping (wrap);
02054
02055
02056 for (int i = 0; i <= dim; ++ i)
02057 result [i] = 0;
02058
02059
02060 bool first_run = true;
02061 while (!b. empty ())
02062 {
02063
02064 ++ *result;
02065
02066
02067 if (first_run)
02068 first_run = false;
02069 else
02070 c. clear ();
02071 hashIntQueue s;
02072 s. push (static_cast<int> (b. begin ()));
02073 while (!s. empty ())
02074 {
02075 int n = s. front ();
02076 s. pop ();
02077 neighbortype cur = b. neighborhood_begin (n);
02078 neighbortype end = b. neighborhood_end (n);
02079 while (cur != end)
02080 {
02081 s. push (static_cast<int> (cur));
02082 ++ cur;
02083 }
02084 c. add (n);
02085 b. remove (n);
02086 }
02087
02088
02089 if (c. count () == 1)
02090 continue;
02091
02092
02093
02094 SetOfCubes X;
02095 cubetype cur (c. begin ()), end (c. end ());
02096 while (cur != end)
02097 {
02098 X. add (cube_cast<Cube> (cur));
02099 ++ cur;
02100 }
02101
02102
02103 sout << "Connected component no. " << *result <<
02104 " (" << X. size () << " cubes):\n";
02105
02106
02107 SetOfCubes A;
02108 int_t number = X. size () - 1;
02109 A. add (X [number]);
02110 X. removenum (number);
02111
02112
02113 Chain *chn = 0;
02114 int maxlevel = Homology (X, "X", A, "A", chn);
02115
02116
02117 ShowHomology (chn, maxlevel);
02118
02119
02120 for (int i = 1; i <= maxlevel; ++ i)
02121 result [i] += BettiNumber (chn [i]);
02122
02123
02124 if (chn)
02125 delete [] chn;
02126 }
02127
02128 sout << "Computed Betti numbers:";
02129 for (int i = 0; i <= dim; ++ i)
02130 sout << " " << result [i];
02131 sout << ".\n";
02132
02133 return;
02134 }
02135
02144 template <int dim, int twoPower, class coordtype>
02145 void ComputeBettiNumbers (char *binary_buffer, int *result,
02146 const coordtype *space_wrapping = 0)
02147 {
02148 using namespace chomp::homology;
02149
02150
02151 bincube<dim,twoPower> b (binary_buffer);
02152
02153
02154 if (space_wrapping)
02155 {
02156 for (int i = 0; i < dim; ++ i)
02157 {
02158 if (!space_wrapping [i])
02159 continue;
02160 int w = space_wrapping [i];
02161 if (w != (1 << twoPower))
02162 sout << "WARNING: Wrapping [" << i <<
02163 "] set to " << (1 << twoPower) <<
02164 ".\n";
02165 b. wrap (i);
02166 }
02167 }
02168
02169 ComputeBettiNumbers (b, result);
02170 return;
02171 }
02172
02173
02174
02175
02176
02177
02186 template <class coordtype>
02187 void ComputeBettiNumbers (coordtype *coord, int n, int dim, int *result)
02188 {
02189 using namespace chomp::homology;
02190
02191
02192 SetOfCubes X;
02193 coordinate c [Cube::MaxDim];
02194 coordtype const *coordpointer = coord;
02195 for (int i = 0; i < n; ++ i)
02196 {
02197 for (int j = 0; j < dim; ++ j)
02198 c [j] = static_cast<coordtype> (*(coordpointer ++));
02199 X. add (Cube (c, dim));
02200 }
02201
02202
02203 bool soutput = sout. show;
02204 sout. show = false;
02205 bool coutput = scon. show;
02206 scon. show = false;
02207
02208
02209 Chain *hom;
02210 int maxlevel = Homology (X, "X", hom);
02211
02212
02213 for (int j = 0; j <= dim; ++ j)
02214 result [j] = (j <= maxlevel) ? BettiNumber (hom [j]) : 0;
02215
02216
02217 if (hom)
02218 delete [] hom;
02219 sout. show = soutput;
02220 scon. show = coutput;
02221 return;
02222 }
02223
02229 template <class coordtype>
02230 inline void SetSpaceWrapping (int dim, const coordtype *wrap)
02231 {
02232 if ((dim < 0) || (dim >= Cube::MaxDim))
02233 return;
02234
02235
02236 coordinate wrapcoord [Cube::MaxDim];
02237 for (int j = 0; j < dim; ++ j)
02238 wrapcoord [j] = static_cast <coordtype>
02239 ((wrap [j] >= 0) ? wrap [j] : -wrap [j]);
02240 tPointBase<coordinate>::setwrapping (wrapcoord, dim, dim + 1);
02241 return;
02242 }
02243
02244
02245 }
02246 }
02247
02248 #endif // _CHOMP_HOMOLOGY_HOMOLOGY_H_
02249
02251