The Original CHomP Software
homology.h
Go to the documentation of this file.
1
3
38
39// Copyright (C) 1997-2020 by Pawel Pilarczyk.
40//
41// This file is part of my research software package. This is free software:
42// you can redistribute it and/or modify it under the terms of the GNU
43// General Public License as published by the Free Software Foundation,
44// either version 3 of the License, or (at your option) any later version.
45//
46// This software is distributed in the hope that it will be useful,
47// but WITHOUT ANY WARRANTY; without even the implied warranty of
48// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49// GNU General Public License for more details.
50//
51// You should have received a copy of the GNU General Public License
52// along with this software; see the file "license.txt". If not,
53// please, see <https://www.gnu.org/licenses/>.
54
55// Started on August 14, 2003. Last revision: July 27, 2012.
56
57
58#ifndef _CHOMP_HOMOLOGY_HOMOLOGY_H_
59#define _CHOMP_HOMOLOGY_HOMOLOGY_H_
60
61#include "chomp/system/config.h"
64#include "chomp/system/arg.h"
65#include "chomp/struct/words.h"
68#include "chomp/cubes/bincube.h"
70
71namespace chomp {
72
76namespace homology {
77
78
81
84
87
90
93
94
95// --------------------------------------------------
96// ------------ DECODE AND SHOW HOMOLOGY ------------
97// --------------------------------------------------
98// This is a set of procedures which help interprete
99// the various form of homology encoding.
100
103template <class euclidom>
105{
106 int betti = 0;
107 for (int i = 0; i < c. size (); ++ i)
108 {
109 if (c. coef (i). delta () == 1)
110 ++ betti;
111 }
112 return betti;
113} /* BettiNumber */
114
119template <class euclidom>
120int TorsionCoefficient (const chain<euclidom> &c, int start = 0)
121{
122 if (start < 0)
123 return -1;
124 while (start < c. size ())
125 {
126 if (c. coef (start). delta () != 1)
127 return start;
128 else
129 ++ start;
130 }
131 return -1;
132} /* TorsionCoefficient */
133
136template <class euclidom>
137inline void ShowHomology (const chain<euclidom> &c)
138{
139 int countfree = 0;
140 bool writeplus = false;
141
142 // write the homology module exactly in the order it appears in 'c'
143 for (int i = 0; i < c. size (); ++ i)
144 {
145 // if the coefficient is invertible, it will be shown later
146 if (c. coef (i). delta () == 1)
147 ++ countfree;
148 // otherwise show the corresponding torsion part now
149 else
150 {
151 sout << (writeplus ? " + " : "") <<
152 euclidom::ringsymbol () << "_" <<
153 c. coef (i);
154 writeplus = true;
155 }
156
157 // if there were some free ingredients show them if necessary
158 if (countfree && ((i == c. size () - 1) ||
159 (c. coef (i + 1). delta () != 1)))
160 {
161 sout << (writeplus ? " + " : "") <<
163 if (countfree > 1)
164 sout << "^" << countfree;
165 countfree = 0;
166 writeplus = true;
167 }
168 }
169
170 // if there was nothing to show, then just show zero
171 if (!c. size ())
172 sout << "0";
173
174 return;
175} /* ShowHomology */
176
179template <class euclidom>
180void ShowHomology (const chain<euclidom> *hom, int maxlevel)
181{
182 if (!hom)
183 return;
184
185 for (int q = 0; q <= maxlevel; ++ q)
186 {
187 sout << "H_" << q << " = ";
188 ShowHomology (hom [q]);
189 sout << '\n';
190 }
191 return;
192} /* ShowHomology */
193
196template <class euclidom>
197inline void ShowHomology (const chainmap<euclidom> &hmap)
198{
199 hmap. show (sout, "\tf", "x", "y");
200 return;
201} /* ShowHomology */
202
207template <class euclidom>
208inline void ShowGenerator (const chain<euclidom> &c)
209{
210 c. show (sout, "c");
211 return;
212} /* ShowGenerator */
213
217template <class euclidom>
218void ShowGenerators (const chain<euclidom> *c, int count)
219{
220 for (int i = 0; i < count; ++ i)
221 {
222 sout << 'g' << (i + 1) << " = ";
223 ShowGenerator (c [i]);
224 sout << '\n';
225 }
226 return;
227} /* ShowGenerators */
228
232template <class euclidom>
233void ShowGenerators (chain<euclidom> const * const * const gen,
234 const chain<euclidom> *hom, int maxlevel)
235{
236 for (int q = 0; q <= maxlevel; ++ q)
237 {
238 if (!hom [q]. size ())
239 continue;
240 sout << "[H_" << q << "]\n";
241 ShowGenerators (gen [q], hom [q]. size ());
242 sout << '\n';
243 }
244 return;
245} /* ShowGenerators */
246
250template <class euclidom>
252 const chain<euclidom> *hom, int maxlevel)
253{
254 for (int q = 0; q <= maxlevel; ++ q)
255 {
256 if (!hom [q]. size ())
257 continue;
258 sout << "[H_" << q << "]\n";
259 for (int i = 0; i < hom [q]. size (); ++ i)
260 {
261 ShowGenerator (c. gethomgen (q, hom [q]. num (i)));
262 sout << '\n';
263 }
264 sout << '\n';
265 }
266 return;
267} /* ShowGenerators */
268
271template <class cell,class euclidom>
273{
274 if (!c. size ())
275 sout << '0';
276 for (int i = 0; i < c. size (); ++ i)
277 {
278 euclidom e = c. coef (i);
279 if (e == 1)
280 sout << (i ? " + " : "") << s [c. num (i)];
281 else if (-e == 1)
282 sout << (i ? " - " : "-") << s [c. num (i)];
283 else
284 {
285 sout << (i ? " + " : "") << e << " * " <<
286 s [c. num (i)];
287 }
288 }
289 return;
290} /* ShowGenerator */
291
295template <class cell,class euclidom>
296void ShowGenerators (const chain<euclidom> *c, int count,
297 const hashedset<cell> &s)
298{
299 for (int i = 0; i < count; ++ i)
300 {
301 sout << 'g' << (i + 1) << " = ";
302 ShowGenerator (c [i], s);
303 sout << '\n';
304 }
305 return;
306} /* ShowGenerators */
307
310template <class euclidom,class cell>
312 const chain<euclidom> *hom,
313 int maxlevel, const gcomplex<cell,euclidom> &gcompl)
314{
315 for (int q = 0; q <= maxlevel; ++ q)
316 {
317 if (!hom [q]. size ())
318 continue;
319 sout << "[H_" << q << "]\n";
320 ShowGenerators (gen [q], hom [q]. size (), gcompl [q]);
321 sout << '\n';
322 }
323 return;
324} /* ShowGenerators */
325
326
327// --------------------------------------------------
328// ---------------- HOMOLOGY OF SETS ----------------
329// --------------------------------------------------
330// This is a set of procedures for the homology computation
331// of various sets: chain complexes, geometric complexes
332// (including cubical and simplicial complexes) and sets of cubes.
333
338template <class euclidom>
340 chain<euclidom> *hom, int maxlevel)
341// For instance: Chain **ExtractGenerators (const ChainComplex cx,
342// Chain *hom, int maxlevel).
343{
344 // if the maximal level is negative, then there is nothing to do
345 if (maxlevel < 0)
346 return 0;
347
348 // create a table of tables of chains
349 chain<euclidom> **gen = new chain<euclidom> * [maxlevel + 1];
350
351 // extract generators for each homology level separately
352 for (int q = 0; q <= maxlevel; ++ q)
353 {
354 // create a table of chains to hold the generators
355 gen [q] = (hom [q]. size ()) ?
356 new chain<euclidom> [hom [q]. size ()] : 0;
357
358 // copy the corresponding chain from internal data of 'cx'
359 for (int i = 0; i < hom [q]. size (); ++ i)
360 {
361 gen [q] [i] =
362 cx. gethomgen (q, hom [q]. num (i));
363 }
364 }
365
366 return gen;
367} /* ExtractGenerators */
368
378template <class euclidom>
379int Homology (chaincomplex<euclidom> &cx, const char *Xname,
380 chain<euclidom> *&hom)
381// For instance: int Homology (ChainComplex &cx, const char *Xname,
382// Chain *&hom).
383{
384 // initialize the empty table
385 hom = 0;
386
387 // determine the dimension of the chain complex
388 int Xdim = cx. dim ();
389 if (Xdim < 0)
390 return -1;
391
392 // compute the homology of the chain complex of X
393 sout << "Computing the homology of " << Xname << " over " <<
394 euclidom::ringname () << "...\n";
395 cx. simple_form ((int *) 0, false);
396 cx. simple_homology (hom);
397
398 // determine the highest non-trivial homology level
399 int maxlevel = Xdim;
400 while ((maxlevel >= 0) && (hom [maxlevel]. size () <= 0))
401 -- maxlevel;
402
403 // if the homology is trivial, delete the allocated table (if any)
404 if (hom && (maxlevel < 0))
405 {
406 delete [] hom;
407 hom = 0;
408 }
409
410 return maxlevel;
411} /* Homology */
412
424template <class cell, class euclidom>
425int Homology (gcomplex<cell,euclidom> &Xcompl, const char *Xname,
426 chain<euclidom> *&hom, chain<euclidom> ***gen = 0)
427// For instance: Homology (CubicalComplex &Xcompl, const char *Xname,
428// Chain *&hom, Chain ***gen = 0).
429{
430 // initialize the empty table
431 hom = 0;
432
433 // determine the dimension of the cubical complex
434 int Xdim = Xcompl. dim ();
435 if (Xdim < 0)
436 return -1;
437
438 // create a chain complex from the cubical complex X without adding
439 // boundaries, as this might be a relative complex with A removed
440 chaincomplex<euclidom> cx (Xdim, !!gen);
441 sout << "Creating the chain complex of " << Xname << "... ";
442 createchaincomplex (cx, Xcompl);
443 sout << "Done.\n";
444
445 // forget the geometric cubical complex to release memory
446 if (!gen)
447 {
449 Xcompl = empty;
450 }
451
452 // compute the homology of this chain complex
453 int maxlevel = Homology (cx, Xname, hom);
454
455 // extract the generators of homology ('cx' will be lost on 'return')
456 if (gen)
457 *gen = ExtractGenerators (cx, hom, maxlevel);
458
459 return maxlevel;
460} /* Homology */
461
468template <class euclidom, class cubetype>
469int Homology (hashedset<cubetype> &Xcubes, const char *Xname,
470 chain<euclidom> *&hom, chain<euclidom> ***gen = 0,
472// For instance: Homology (SetOfCubes &Xcubes, const char *Xname,
473// Chain *&hom, Chain ***gen = 0, CubicalComplex **gcompl = 0).
474{
475 // define the type of a set of cubes
476 typedef hashedset<cubetype> cubsettype;
477
478 // define the type of a cubical cell
479 typedef typename cubetype::CellType celltype;
480
481 // initialize the empty table
482 hom = 0;
483
484 // if the set X is empty, the answer is obvious
485 if (Xcubes. empty ())
486 return -1;
487
488 // determine the dimension of X (note: X is nonempty!)
489 int Xspacedim = Xcubes [0]. dim ();
490
491 // allocate a suitable bit field set for the reduction and show msg
492 knownbits [Xspacedim];
493
494 // reduce the cubes in X
495 cubsettype emptycubes;
496 reducepair (Xcubes, emptycubes, emptycubes, Xname, 0);
497
498 // transform the set of cubes X into a set of cells and forget Xcubes
501 cubes2cells (Xcubes, *Xcompl, Xname);
502 Xcubes = emptycubes;
503
504 // collapse the set and add boundaries of cells
505 collapse (*Xcompl, Xname);
506
507 // if the complex is empty, the result is trivial
508 if (Xcompl -> empty ())
509 {
510 delete Xcompl;
511 return -1;
512 }
513
514 // make a correction to the dimension of X
515 int Xdim = Xcompl -> dim ();
516 if (Xdim != Xspacedim)
517 {
518 sout << "Note: The dimension of " << Xname <<
519 " decreased from " << Xspacedim <<
520 " to " << Xdim << ".\n";
521 }
522
523 // compute the homology of the cubical complex
524 int maxlevel = Homology (*Xcompl, Xname, hom, gen);
525
526 // deallocate the cubical complex if necessary
527 if (!gcompl)
528 delete Xcompl;
529 else
530 *gcompl = Xcompl;
531
532 return maxlevel;
533} /* Homology */
534
543template <class cell, class euclidom>
544int Homology (gcomplex<cell,euclidom> &Xcompl, const char *Xname,
545 gcomplex<cell,euclidom> &Acompl, const char *Aname,
546 chain<euclidom> *&hom, chain<euclidom> ***gen = 0)
547// For instance: Homology (CubicalComplex &Xcompl, const char *Xname,
548// CubicalComplex &Acompl, const char *Aname, Chain *&hom,
549// Chain ***gen = 0).
550{
551 // initialize the empty table
552 hom = 0;
553
554 // determine the dimension of the first cubical complex
555 int Xdim = Xcompl. dim ();
556 if (Xdim < 0)
557 return -1;
558
559 // prepare the right name for the pair (to be used later)
560 word pairname;
561 if (!Acompl. empty ())
562 pairname << '(' << Xname << "," << Aname << ')';
563 else
564 pairname << Xname;
565
566 // collapse the pair of sets into a relative cubical complex
567 // and add boundaries of cells where necessary
568 collapse (Xcompl, Acompl, Xname, Aname);
569
570 // forget the remains of the other cubical complex
571 gcomplex<cell,euclidom> emptycompl;
572 Acompl = emptycompl;
573
574 // make a correction to the dimension of X
575 if (Xdim != Xcompl. dim ())
576 {
577 sout << "Note: The dimension of " << Xname <<
578 " decreased from " << Xdim << " to " <<
579 Xcompl. dim () << ".\n";
580 }
581
582 // compute the homology of the relative cubical complex
583 int maxlevel = Homology (Xcompl, pairname, hom, gen);
584
585 // release memory used by the name of the pair and exit
586 return maxlevel;
587} /* Homology */
588
598template <class euclidom, class cubetype>
599int Homology (hashedset<cubetype> &Xcubes, const char *Xname,
600 hashedset<cubetype> &Acubes, const char *Aname,
601 chain<euclidom> *&hom, chain<euclidom> ***gen = 0,
603// For instance: int Homology (SetOfCubes &X, const char *Xname,
604// SetOfCubes &A, const char *Aname, Chain *&hom,
605// Chain ***gen = 0, CubicalComplex **gcompl = 0).
606{
607 // define the type of a set of cubes
608 typedef hashedset<cubetype> cubsettype;
609
610 // define the type of a cubical cell
611 typedef typename cubetype::CellType celltype;
612
613 // initialize the empty table
614 hom = 0;
615
616 // if the set A is empty, call the other procedure
617 if (Acubes. empty ())
618 return Homology (Xcubes, Xname, hom, gen, gcompl);
619
620 // remove from X cubes which are in A
621 removeAfromX (Xcubes, Acubes, Xname, Aname);
622
623 // if the set X is empty, the answer is obvious
624 if (Xcubes. empty ())
625 return -1;
626
627 // leave in A only the neighbors of X\\A
628 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
629
630 // determine the dimension of X (note: X is nonempty!)
631 int Xspacedim = Xcubes [0]. dim ();
632
633 // allocate a suitable bit field set for the reduction and show msg
634 knownbits [Xspacedim];
635
636 // expand A within X
637 if (!gcompl)
638 expandAinX (Xcubes, Acubes, Xname, Aname);
639
640 // if everything was moved to A, then the result is trivial
641 if (Xcubes. empty ())
642 return -1;
643
644 // restrict A to neighbors
645 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
646
647 // reduce the pair (X,A)
648 cubsettype emptycubes;
649 reducepair (Xcubes, Acubes, emptycubes, Xname, Aname);
650
651 // if nothing remains in X, then the result is trivial
652 if (Xcubes. empty ())
653 return -1;
654
655 // prepare the right name for the difference of the two sets
656 word diffname;
657 diffname << Xname << '\\' << Aname;
658
659 // transform the set of cubes X into a set of cells and forget Xcubes
662 cubes2cells (Xcubes, *Xcompl, diffname);
663 Xcubes = emptycubes;
664
665 // transform the set of cubes A into a set of cubical cells
667 cubes2cells (Acubes, Acompl, Aname);
668 Acubes = emptycubes;
669
670 // continue the homology computations
671 int maxlevel = Homology (*Xcompl, Xname, Acompl, Aname, hom, gen);
672
673 // deallocate the cubical complex if necessary
674 if (!gcompl)
675 delete Xcompl;
676 else
677 *gcompl = Xcompl;
678
679 return maxlevel;
680} /* Homology */
681
682
683// --------------------------------------------------
684// ---------------- HOMOLOGY OF MAPS ----------------
685// --------------------------------------------------
686// This is a set of procedures for the homology computation
687// of chain maps and combinatorial cubical multivalued maps.
688
705template <class euclidom>
707 const chain<euclidom> *hom_cx,
708 const chain<euclidom> *hom_cy, int maxlevel)
709// For instance: ChainMap *HomologyMap (const ChainMap &cmap,
710// const Chain *hom_cx, const Chain *hom_cy, int maxlevel).
711{
712 // if the maximal level is wrong, return 0
713 if (maxlevel < 0)
714 return 0;
715
716 // allocate chain complexes of appropriate dimension and a chain map
717 chaincomplex<euclidom> hx (maxlevel);
718 chaincomplex<euclidom> hy (maxlevel);
719 chainmap<euclidom> *hmap = new chainmap<euclidom> (hx, hy);
720
721 // create the chain complexes reflecting the homology module(s)
722 hx. take_homology (hom_cx);
723 hy. take_homology (hom_cy);
724
725 // create the chain map accordingly
726 hmap -> take_homology (cmap, hom_cx, hom_cy);
727 return hmap;
728} /* HomologyMap */
729
733template <class euclidom>
735 const chain<euclidom> *hom_cx, int maxlevel)
736// For instance: ChainMap *HomologyMap (const ChainMap &cmap,
737// const Chain *hom_cx, int maxlevel).
738{
739 // if the maximal level is wrong, return 0
740 if (maxlevel < 0)
741 return 0;
742
743 // allocate chain complexes of appropriate dimension and a chain map
744 chaincomplex<euclidom> hx (maxlevel);
745 chainmap<euclidom> *hmap = new chainmap<euclidom> (hx, hx);
746
747 // create the chain complexes reflecting the homology module(s)
748 hx. take_homology (hom_cx);
749
750 // create the chain map accordingly
751 hmap -> take_homology (cmap, hom_cx, hom_cx);
752 return hmap;
753} /* HomologyMap */
754
767template <class euclidom, class cubetype>
768int Homology (mvmap<cubetype,cubetype> &Fcubmap, const char *Fname,
769 hashedset<cubetype> &Xcubes, const char *Xname,
770 hashedset<cubetype> &Acubes, const char *Aname,
771 hashedset<cubetype> &Ycubes, const char *Yname,
772 hashedset<cubetype> &Bcubes, const char *Bname,
773 chain<euclidom> *&hom_cx, int &maxlevel_cx,
774 chain<euclidom> *&hom_cy, int &maxlevel_cy,
775 chainmap<euclidom> *&hom_f,
776 bool inclusion = false, int careful = 0x01,
777 chain<euclidom> ***gfgen = 0,
779 chain<euclidom> ***gygen = 0,
781{
782 // define the type of a set of cubes
783 typedef hashedset<cubetype> cubsettype;
784
785 // define the type of a cubical cell
786 typedef typename cubetype::CellType celltype;
787
788 // define the type of a combinatorial cubical multivalued map
789 typedef mvmap<cubetype,cubetype> cubmaptype;
790
791 // transform the 'careful' bits into separate variables
792 bool verify = careful & 0x01;
793 bool checkacyclic = careful & 0x02;
794
795 // prepare the right names for X\A and Y\B
796 word XAname, YBname;
797 if (!Acubes. empty ())
798 XAname << Xname << '\\' << Aname;
799 else
800 XAname << Xname;
801 if (!Bcubes. empty ())
802 YBname << Yname << '\\' << Bname;
803 else
804 YBname << Yname;
805
806 // ----- prepare the sets of cubes -----
807
808 // if the pointers to both sets are the same, then this is an error
809 if (&Xcubes == &Ycubes)
810 throw "You must clone the sets passed to Homology.";
811
812 // remove from X cubes which are in A
813 removeAfromX (Xcubes, Acubes, Xname, Aname);
814
815 // leave in A only the neighbors of X\\A
816 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
817
818 // remove from Y cubes which are in B
819 removeAfromX (Ycubes, Bcubes, Yname, Bname);
820
821 // if one of the main sets is empty, the answer is trivial
822 if (Xcubes. empty () || Ycubes. empty ())
823 return -1;
824
825 // remember the original size of the set A and of the set X
826 int_t origAsize = Acubes. size ();
827 int_t origXsize = Xcubes. size ();
828
829 // determine the dimension of X and Y (both sets are non-empty)
830 int Xspacedim = Xcubes [0]. dim ();
831 int Yspacedim = Ycubes [0]. dim ();
832
833 // check if F (X\A) \subset Y
834 if (verify)
835 checkimagecontained (Fcubmap, Xcubes, Ycubes, Bcubes,
836 XAname, Yname);
837
838 // check if F (A) \subset B
839 if (verify && !Acubes. empty ())
840 checkimagecontained (Fcubmap, Acubes, Bcubes, Aname, Bname);
841
842 // check if F (A) is disjoint from Y
843 if (verify && !Acubes. empty ())
844 checkimagedisjoint (Fcubmap, Acubes, Ycubes, Aname, YBname);
845
846 // verify if X\A \subset Y and A \subset B if inclusion is considered
847 if (verify && inclusion)
848 checkinclusion (Xcubes, Ycubes, Bcubes, XAname, Yname);
849 if (verify && inclusion)
850 checkinclusion (Acubes, Bcubes, Aname, Bname);
851
852 // ----- reduce the sets of cubes -----
853
854 // allocate a suitable bit field set for the reduction and show msg
855 knownbits [Xspacedim];
856 knownbits [Yspacedim];
857
858 // reduce the pair of sets of cubes (X,A) without acyclicity check
859 if (!checkacyclic)
860 {
861 // reduce the pair (X,A)
862 cubsettype empty;
863 reducepair (Xcubes, Acubes, empty, Xname, Aname);
864
865 // if nothing remains in X, then the result is trivial
866 if (Xcubes. empty ())
867 return -1;
868 }
869
870 // expand A towards X and modify (Y,B) accordingly
871 if (!Acubes. empty () && !gfgen && !gygen)
872 {
873 expandAinX (Xcubes, Acubes, Ycubes, Bcubes, Fcubmap,
874 Xname, Aname, Bname, inclusion, checkacyclic);
875 }
876
877 // reduce the pair (X,A) or the set X with acyclicity check
878 if (checkacyclic)//[???] && !Acubes. empty ())
879 {
880 // leave in A only the neighbors of X\\A
881 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
882
883 // reduce the pair (X,A) with acyclicity check
884 cubsettype emptycubes;
885 reducepair (Xcubes, Acubes, Fcubmap, emptycubes,
886 Xname, Aname);
887
888 // if nothing remains in X, then the result is trivial
889 if (Xcubes. empty ())
890 return -1;
891 }
892
893 // reduce the pair (X,A) even further
894 if (!checkacyclic && !Acubes. empty ())
895 {
896 // leave in A only the neighbors of X\\A
897 restrictAtoneighbors (Xcubes, Acubes, Xname, Aname);
898
899 // continue the reduction of the pair (X,A)
900 cubsettype empty;
901 reducepair (Xcubes, Acubes, empty, Xname, Aname);
902 }
903
904 // indicate that the acyclicity of the map should be verified
905 if (!verify)
906 {
907 if (!checkacyclic && ((origAsize != Acubes. size ()) ||
908 (origXsize != Xcubes. size ())))
909 {
910 sout << "*** Important note: " << Xname << " or " <<
911 Aname << " changed. You must make sure\n"
912 "*** that the restriction of " << Fname <<
913 " to the new sets is acyclic.\n";
914 }
915 else
916 {
917 sout << "*** Note: The program assumes "
918 "that the input map is acyclic.\n";
919 }
920 }
921
922 // create the set of cubes to keep in Y as the image of the domain
923 // and include the domain if the inclusion is considered
924 cubsettype Ykeepcubes;
925 sout << "Computing the image of the map... ";
926 for (int_t i = 0; i < Xcubes. size (); ++ i)
927 Ykeepcubes. add (Fcubmap (Xcubes [i]));
928 for (int_t i = 0; i < Acubes. size (); ++ i)
929 Ykeepcubes. add (Fcubmap (Acubes [i]));
930 if (inclusion)
931 {
932 sout << "and of the inclusion... ";
933 Ykeepcubes. add (Xcubes);
934 Ykeepcubes. add (Acubes);
935 }
936 sout << Ykeepcubes. size () << " cubes.\n";
937
938 // reduce the pair of cubical sets (Y,B) towards the image of F
939 if (Xspacedim == Yspacedim)
940 {
941 if (!gygen)
942 expandAinX (Ycubes, Bcubes, Yname, Bname);
943 restrictAtoneighbors (Ycubes, Bcubes, Yname, Bname,
944 &Ykeepcubes);
945 reducepair (Ycubes, Bcubes, Ykeepcubes, Yname, Bname);
946 }
947
948 // forget the cubes to keep in Y as no longer of any use
949 if (!Ykeepcubes. empty ())
950 {
951 cubsettype empty;
952 Ykeepcubes = empty;
953 }
954
955 // ----- create the cubical complexes -----
956
957 // transform the set of cubes X into a set of cells and forget Xcubes
959 cubes2cells (Xcubes, Xcompl, XAname, false);
960
961 // transform the set of cubes A into a set of cubical cells
963 cubes2cells (Acubes, Acompl, Aname, false);
964
965 // transform the cubes in Y into cubical cells and forget the cubes
968 cubes2cells (Ycubes, *Ycompl, YBname);
969
970 // transform the cubes in B into cubical cells and forget the cubes
972 cubes2cells (Bcubes, Bcompl, Bname);
973
974 // determine the dimension of X and Y as cubical complexes
975 int Xdim = Xcompl. dim ();
976 int Ydim = Ycompl -> dim ();
977
978 // ----- collapse the cubical sets (X,A) -----
979
980 // reduce the pair of sets (Xcompl, Acompl) while adding to them
981 // boundaries of all the cells
983 collapse (Xcompl, Acompl, emptycompl, Xname, Aname,
984 true, true, false);
985
986 // if nothing remains in X, then the result is trivial
987 if (Xcompl. empty ())
988 return -1;
989
990 // make a correction to the dimension of X
991 if (Xdim != Xcompl. dim ())
992 {
993 sout << "Note: The dimension of " << Xname << " decreased "
994 "from " << Xdim << " to " << Xcompl. dim () << ".\n";
995
996 Xdim = Xcompl. dim ();
997 }
998
999 // ----- create a reduced graph of F -----
1000
1001 // create the map F defined on the cells in its domain
1002 mvcellmap<celltype,euclidom,cubetype> Fcellcubmap (Xcompl);
1003 sout << "Creating the map " << Fname << " on cells in " <<
1004 Xname << "... ";
1005 int_t countimages = createimages (Fcellcubmap, Fcubmap, Fcubmap,
1006 Xcubes, Acubes);
1007 sout << countimages << " cubes added.\n";
1008
1009 // create the map F defined on the cells in its domain subcomplex A
1010 mvcellmap<celltype,euclidom,cubetype> FcellcubmapA (Acompl);
1011 if (!Acompl. empty ())
1012 {
1013 sout << "Creating the map " << Fname << " on cells in " <<
1014 Aname << "... ";
1015 int_t count = createimages (FcellcubmapA, Fcubmap, Acubes);
1016 sout << count << " cubes added.\n";
1017 }
1018
1019 // get rid of the sets of cubes X and A as no longer needed,
1020 // as well as the cubical map
1021 {
1022 cubsettype emptycubes;
1023 Acubes = emptycubes;
1024 Xcubes = emptycubes;
1025 cubmaptype emptymap;
1026 Fcubmap = emptymap;
1027 }
1028
1029 // create the graph of F as a cubical cell complex
1030 sout << "Creating a cell map for " << Fname << "... ";
1031 mvcellmap<celltype,euclidom,celltype> Fcellmap (Xcompl);
1032 bool acyclic = createcellmap (Fcellcubmap, FcellcubmapA,
1033 Fcellmap, verify);
1034 sout << "Done.\n";
1035 if (verify && !acyclic)
1036 {
1037 sout << "*** SERIOUS PROBLEM: The map is not "
1038 "acyclic. THE RESULT WILL BE WRONG.\n"
1039 "*** You must verify the acyclicity of the "
1040 "initial map with 'chkmvmap'\n"
1041 "*** and, if successful, set the "
1042 "'careful reduction' bit.\n";
1043 }
1044 if (verify && acyclic)
1045 {
1046 sout << "Note: It has been verified successfully "
1047 "that the map is acyclic.\n";
1048 }
1049
1050 sout << "Creating the graph of " << Fname << "... ";
1053 creategraph (Fcellmap, *Fcompl, false);
1054 sout << Fcompl -> size () << " cells added.\n";
1055
1056 // forget the cubical maps on the cells and the cubical complex of X
1058 Fcellcubmap = emptycellcubmap;
1059 FcellcubmapA = emptycellcubmap;
1060 mvcellmap<celltype,euclidom,celltype> emptycellmap (emptycompl);
1061 Fcellmap = emptycellmap;
1062 Xcompl = emptycompl;
1063
1064 // ----- collapse the cubical sets (Y,B) -----
1065
1066 // decrease the dimension of B to the dimension of Y
1067 decreasedimension (Bcompl, Ydim, Bname);
1068
1069 // create a full cubical complex (with all the faces) of Y\B
1070 addboundaries (*Ycompl, Bcompl, 0, false, Yname, Bname);
1071
1072 // forget the cubical complex of B
1073 if (!Bcompl. empty ())
1074 {
1075 sout << "Forgetting " << Bcompl. size () << " cells from " <<
1076 Bname << ".\n";
1078 Bcompl = empty;
1079 }
1080
1081 // collapse the codomain of the map towards the image of F
1082 gcomplex<celltype,euclidom> Ykeepcompl;
1083 sout << "Computing the image of " << Fname << "... ";
1084 project (*Fcompl, Ykeepcompl, *Ycompl, Xspacedim, Yspacedim,
1085 0, 0, false);
1086 if (inclusion)
1087 {
1088 project (*Fcompl, Ykeepcompl, *Ycompl, 0, Xspacedim,
1089 Yspacedim, 0, false);
1090 }
1091 sout << Ykeepcompl. size () << " cells.\n";
1092
1093 sout << "Collapsing " << Yname << " to img of " << Xname << "... ";
1094 int_t countremoved = Ycompl -> collapse (emptycompl, Ykeepcompl,
1095 0, 0, 0);
1096 sout << 2 * countremoved << " cells removed, " <<
1097 Ycompl -> size () << " left.\n";
1098
1099 // forget the cells to keep in Y
1100 if (!Ykeepcompl. empty ())
1101 {
1103 Ykeepcompl = empty;
1104 }
1105
1106 // make a correction to the dimension of Y
1107 if (Ydim != Ycompl -> dim ())
1108 {
1109 sout << "Note: The dimension of " << Yname << " decreased "
1110 "from " << Ydim << " to " << Ycompl -> dim () <<
1111 ".\n";
1112
1113 Ydim = Ycompl -> dim ();
1114 }
1115
1116 // ----- create chain complexes from the cubical sets ------
1117
1118 // create a chain complex from the graph of F (it is relative)
1119 chaincomplex<euclidom> cgraph (Fcompl -> dim (), !!gfgen);
1120 sout << "Creating the chain complex of the graph of " << Fname <<
1121 "... ";
1122 createchaincomplex (cgraph, *Fcompl);
1123 sout << "Done.\n";
1124
1125 // create the chain complex from Y (this is a relative complex)
1126 chaincomplex<euclidom> cy (Ydim, !!gygen);
1127 sout << "Creating the chain complex of " << Yname << "... ";
1128 createchaincomplex (cy, *Ycompl);
1129 sout << "Done.\n";
1130
1131 // create the projection map from the graph of the map to Y
1132 chainmap<euclidom> cmap (cgraph, cy);
1133 sout << "Creating the chain map of the projection... ";
1134 createprojection (*Fcompl, *Ycompl, cmap, Xspacedim, Yspacedim, 0);
1135 sout << "Done.\n";
1136
1137 // if this is an index map, create the projection map from the graph
1138 // of the map to X composed with the inclusion into Y
1139 chainmap<euclidom> imap (cgraph, cy);
1140 if (inclusion)
1141 {
1142 sout << "Creating the chain map of the inclusion... ";
1143 createprojection (*Fcompl, *Ycompl, imap, 0, Xspacedim,
1144 Yspacedim);
1145 sout << "Done.\n";
1146 }
1147
1148 // forget the graph of F if it is not going to be used anymore
1149 if (gfcompl)
1150 (*gfcompl) = Fcompl;
1151 else
1152 delete Fcompl;
1153
1154 // forget the cubical complex Y unless requested to keep it
1155 if (gycompl)
1156 (*gycompl) = Ycompl;
1157 else
1158 delete Ycompl;
1159
1160 // ----- compute and show homology, save generators -----
1161
1162 // prepare the name of the graph of F
1163 word gFname;
1164 gFname << "the graph of " << Fname;
1165
1166 // compute the homology of the chain complex of the graph of the map
1167 maxlevel_cx = Homology (cgraph, gFname, hom_cx);
1168
1169 // extract the computed generators of the graph if requested to
1170 if (gfgen)
1171 *gfgen = ExtractGenerators (cgraph, hom_cx, maxlevel_cx);
1172
1173 // compute the homology of the chain complex of Y
1174 maxlevel_cy = Homology (cy, Yname, hom_cy);
1175
1176 // extract the computed generators of Y if requested to
1177 if (gygen)
1178 *gygen = ExtractGenerators (cy, hom_cy, maxlevel_cy);
1179
1180 // ----- show the map(s) -----
1181
1182 // prepare the data structures for the homology
1183 chaincomplex<euclidom> hgraph (maxlevel_cx);
1184 chaincomplex<euclidom> hy (maxlevel_cy);
1185 chainmap<euclidom> *hmap = new chainmap<euclidom> (hgraph, hy);
1186 chainmap<euclidom> hincl (hgraph, hy);
1187// chainmap<euclidom> *hcomp = new chainmap<euclidom> (hgraph, hgraph);
1188 chainmap<euclidom> *hcomp = new chainmap<euclidom> (hy, hy);
1189
1190 // show the map induced in homology by the chain map
1191 sout << "The map induced in homology is as follows:\n";
1192 hgraph. take_homology (hom_cx);
1193 hy. take_homology (hom_cy);
1194 hmap -> take_homology (cmap, hom_cx, hom_cy);
1195 hmap -> show (sout, "\tf", "x", "y");
1196
1197 // show the map induced in homology by the inclusion map
1198 bool invertible = true;
1199 if (inclusion)
1200 {
1201 sout << "The map induced in homology by the inclusion:\n";
1202 hincl. take_homology (imap, hom_cx, hom_cy);
1203 hincl. show (sout, "\ti", "x", "y");
1204
1205 try
1206 {
1207 hincl. invert ();
1208 }
1209 catch (...)
1210 {
1211 sout << "Oh, my goodness! This map is apparently "
1212 "not invertible.\n";
1213 invertible = false;
1214 }
1215
1216 if (invertible)
1217 {
1218 sout << "The inverse of the map "
1219 "induced by the inclusion:\n";
1220 hincl. show (sout, "\tI", "y", "x");
1221
1222 // debug: verify if the map was inverted correctly
1223 chainmap<euclidom> hincl1 (hgraph, hy);
1224 hincl1. take_homology (imap, hom_cx, hom_cy);
1225 chainmap<euclidom> hident (hy, hy);
1226 hident. compose (hincl1, hincl);
1227 sbug << "The composition of the inclusion and "
1228 "its inverse (should be the identity):\n";
1229 hident. show (sbug, "\tid", "y", "y");
1230 for (int i = 0; i <= hident. dim (); ++ i)
1231 {
1232 const mmatrix<euclidom> &m = hident [i];
1233 if (m. getnrows () != m. getncols ())
1234 throw "INV: Inequal rows and cols.";
1235 euclidom zero, one;
1236 zero = 0;
1237 one = 1;
1238 for (int c = 0; c < m. getncols (); ++ c)
1239 {
1240 for (int r = 0; r < m. getnrows ();
1241 ++ r)
1242 {
1243 if ((r == c) && (m. get
1244 (r, c) == one))
1245 {
1246 continue;
1247 }
1248 if (m. get (r, c) == zero)
1249 continue;
1250 throw "INV: Non-identity.";
1251 }
1252 }
1253 }
1254 // debug: end of the verification
1255
1256 sout << "The composition of F and the inverse "
1257 "of the map induced by the inclusion:\n";
1258 // hcomp -> compose (hincl, *hmap);
1259 hcomp -> compose (*hmap, hincl);
1260 // hcomp -> show (sout, "\tF", "x", "x");
1261 hcomp -> show (sout, "\tF", "y", "y");
1262 }
1263 }
1264
1265 // set the appropriate map
1266 if (inclusion && invertible)
1267 {
1268 hom_f = hcomp;
1269 delete hmap;
1270 }
1271 else
1272 {
1273 hom_f = hmap;
1274 delete hcomp;
1275 }
1276
1277 // throw an exception if the map is not invertible
1278 if (inclusion && !invertible)
1279 throw "Unable to invert the inclusion map.";
1280
1281 return ((maxlevel_cx < maxlevel_cy) ? maxlevel_cx : maxlevel_cy);
1282} /* Homology */
1283
1285template <class euclidom, class cubetype>
1289 chain<euclidom> *&hom_cx, int &maxlevel_cx,
1290 chain<euclidom> *&hom_cy, int &maxlevel_cy,
1291 chainmap<euclidom> *&hom_f,
1292 bool inclusion = false, int careful = 0x01,
1293 chain<euclidom> ***gfgen = 0,
1295 chain<euclidom> ***gygen = 0,
1297{
1298 return Homology (Fcubmap, "F", Xcubes, "X", Acubes, "A",
1299 Ycubes, "Y", Bcubes, "B", hom_cx, maxlevel_cx,
1300 hom_cy, maxlevel_cy, hom_f, inclusion, careful,
1301 gfgen, gfcompl, gygen, gycompl);
1302} /* Homology */
1303
1307template <class euclidom, class cubetype>
1308int Homology (mvmap<cubetype,cubetype> &Fcubmap, const char *Fname,
1309 hashedset<cubetype> &Xcubes, const char *Xname,
1310 hashedset<cubetype> &Acubes, const char *Aname,
1311 chain<euclidom> *&hom, int &maxlevel,
1312 chainmap<euclidom> *&hom_f, int careful = 0x01,
1313 chain<euclidom> ***gfgen = 0,
1315 chain<euclidom> ***gygen = 0,
1317{
1318 hashedset<cubetype> Ycubes = Xcubes, Bcubes = Acubes;
1319 chain<euclidom> *hom_cy = 0;
1320 int maxlevel_cy;
1321 int result = Homology (Fcubmap, Fname, Xcubes, Xname, Acubes, Aname,
1322 Ycubes, Xname, Bcubes, Aname, hom, maxlevel,
1323 hom_cy, maxlevel_cy, hom_f, true, careful,
1324 gfgen, gfcompl, gygen, gycompl);
1325 delete [] hom_cy;
1326 return result;
1327} /* Homology */
1328
1330template <class euclidom, class cubetype>
1333 chain<euclidom> *&hom, int &maxlevel,
1334 chainmap<euclidom> *&hom_f, int careful = 0x01,
1335 chain<euclidom> ***gfgen = 0,
1337 chain<euclidom> ***gygen = 0,
1339{
1340 return Homology (Fcubmap, "F", Xcubes, "X", Acubes, "A", hom,
1341 maxlevel, hom_f, careful, gfgen, gfcompl, gygen, gycompl);
1342} /* Homology */
1343
1344
1345// --------------------------------------------------
1346// --------- TWO-LAYER HOMOLOGY COMPUTATION ---------
1347// --------------------------------------------------
1348
1352template <class euclidom, class cubetype>
1353int Homology2l (mvmap<cubetype,cubetype> &Fcubmap0, const char *Fname,
1354 hashedset<cubetype> &Xcubes0, const char *Xname,
1355 hashedset<cubetype> &Acubes0, const char *Aname,
1356 chain<euclidom> *&hom_cx, int &maxlevel,
1357 chainmap<euclidom> *&hom_f, int careful = 0x01,
1358 chain<euclidom> ***gfgen = 0,
1360 **gfcompl = 0, chain<euclidom> ***gygen = 0,
1362 **gycompl = 0)
1363{
1364 // define the type of a 2-layer cube and 2-layer cell
1365 typedef tCube2l<cubetype> cube2ltype;
1366 typedef typename cube2ltype::CellType cell2ltype;
1367
1368 // turn off locally the usage of binary decision diagrams
1369 local_var<int> TurnOffMaxBddDim (MaxBddDim, 0);
1370
1371 // transform the 'careful' bits into separate variables
1372 bool verify = careful & 0x01;
1373 bool checkacyclic = careful & 0x02;
1374 bool keepacyclic = careful & 0x04;
1375
1376 // remove from X cubes which are in A
1377 removeAfromX (Xcubes0, Acubes0, "X", "A");
1378
1379 // leave in A only the neighbors of X\\A
1380 restrictAtoneighbors (Xcubes0, Acubes0, "X", "A");
1381
1382 // if the set X is empty, the answer is obvious
1383 if (Xcubes0. empty ())
1384 {
1385 sout << "X is a subset of A. The homology of (X,A) "
1386 "is trivial and the map is 0.";
1387 return -1;
1388 }
1389
1390 // ----- define the layers ------
1391
1392 // define the two-layer structure
1393 sout << "Defining the two-layer structure... ";
1394 cube2ltype::setlayers (Xcubes0, Acubes0);
1395
1396 // transform the cubes in X and in A to the two-layer sets
1397 hashedset<cube2ltype> Xcubes;
1398 for (int_t i = 0; i < Xcubes0. size (); ++ i)
1399 Xcubes. add (cube2ltype (Xcubes0 [i], 1));
1400 hashedset<cube2ltype> Acubes;
1401 for (int_t i = 0; i < Acubes0. size (); ++ i)
1402 Acubes. add (cube2ltype (Acubes0 [i], 0));
1403
1404 // say that defining the two-layer structure is done
1405 sout << cube2ltype::layer1 (). size () << "+" <<
1406 cube2ltype::layer0 (). size () << " cubes, " <<
1407 cell2ltype::identify (). size () << " cells.\n";
1408
1409 // ----- transform the map ------
1410
1411 // determine Y and B
1412 sout << "Creating the sets Y and B... ";
1413 hashedset<cube2ltype> Ycubes (Xcubes);
1414 hashedset<cube2ltype> Bcubes (Acubes);
1415 for (int_t i = 0; i < Xcubes0. size (); ++ i)
1416 {
1417 const hashedset<cubetype> &img = Fcubmap0 (Xcubes0 [i]);
1418 for (int_t j = 0; j < img. size (); ++ j)
1419 {
1420 if (!Xcubes0. check (img [j]))
1421 Bcubes. add (cube2ltype (img [j], 0));
1422 }
1423 }
1424 for (int_t i = 0; i < Acubes0. size (); ++ i)
1425 {
1426 const hashedset<cubetype> &img = Fcubmap0 (Acubes0 [i]);
1427 for (int_t j = 0; j < img. size (); ++ j)
1428 Bcubes. add (cube2ltype (img [j], 0));
1429 }
1430 sout << Ycubes. size () << " cubes in Y\\B, " <<
1431 Bcubes. size () << " in B.\n";
1432
1433 // lift the map to the two-layer structure
1435 for (int_t i = 0; i < Xcubes0. size (); ++ i)
1436 {
1437 // Fcubmap [Xcubes [i]]. size ();
1438 const hashedset<cubetype> &img = Fcubmap0 (Xcubes0 [i]);
1439 if (img. empty ())
1440 throw "Empty image of a box in X.\n";
1441 for (int_t j = 0; j < img. size (); ++ j)
1442 {
1443 int layer = Xcubes0. check (img [j]) ? 1 : 0;
1444 Fcubmap [Xcubes [i]]. add
1445 (cube2ltype (img [j], layer));
1446 }
1447 }
1448 for (int_t i = 0; i < Acubes0. size (); ++ i)
1449 {
1450 // Fcubmap [Acubes [i]]. size ();
1451 const hashedset<cubetype> &img = Fcubmap0 (Acubes0 [i]);
1452 if (img. empty ())
1453 throw "Empty image of a box in A.\n";
1454 for (int_t j = 0; j < img. size (); ++ j)
1455 Fcubmap [Acubes [i]]. add
1456 (cube2ltype (img [j], 0));
1457 }
1458
1459 // forget the initial single-layer sets and the map
1460 {
1461 hashedset<cubetype> empty;
1462 Xcubes0 = empty;
1463 Acubes0 = empty;
1464 }
1465 {
1467 Fcubmap0 = empty;
1468 }
1469
1470 // remember the original size of the set A and of the set X
1471 int_t origAsize = Acubes. size ();
1472 int_t origXsize = Xcubes. size ();
1473
1474 // determine the dimension of X and Y if possible
1475 int Xspacedim = Xcubes. empty () ? -1 : Xcubes [0]. dim ();
1476 int Yspacedim = Ycubes. empty () ? -1 : Ycubes [0]. dim ();
1477
1478 // ----- reduce the sets of cubes -----
1479
1480 // prepare the set of cubes to keep in X (unused in this program)
1481 hashedset<cube2ltype> Xkeepcubes;
1482
1483 // allocate a suitable bit field set for the reduction and show msg
1484 if (Xspacedim > 0)
1485 knownbits [Xspacedim];
1486
1487 // reduce the pair of sets of cubes (X,A) without acyclicity check
1488 if (!Acubes. empty () && !checkacyclic)
1489 {
1490 // reduce the pair (X,A)
1491 reducepair (Xcubes, Acubes, Xkeepcubes, "X", "A");
1492
1493 // if nothing remains in X, then the result is trivial
1494 if (Xcubes. empty ())
1495 {
1496 sout << "There are no cubes left "
1497 "in X\\A. The homology of (X,A) "
1498 "is trivial and the map is 0.";
1499 return -1;
1500 }
1501 }
1502
1503 // remember which inclusions have been verified
1504 bool inclFABchecked = false;
1505 bool inclFXYchecked = false;
1506
1507 // do the careful or extended reduction
1508 if (checkacyclic)
1509 {
1510 // check if F (X\A) \subset Y
1511 if (verify)
1512 {
1513 checkimagecontained (Fcubmap,
1514 Xcubes, Ycubes, Bcubes,
1515 Acubes. empty () ? "X" : "X\\A", "Y");
1516 inclFXYchecked = true;
1517 }
1518 // check if F (A) \subset B and if F (A) is disjoint from Y
1519 if (verify && !Acubes. empty ())
1520 {
1521 checkimagecontained (Fcubmap, Acubes, Bcubes,
1522 "A", "B");
1523 checkimagedisjoint (Fcubmap, Acubes, Ycubes,
1524 "A", "Y\\B");
1525 inclFABchecked = true;
1526 }
1527 }
1528 else if (!Acubes. empty ())
1529 {
1530 // check if F (X\A) \subset Y
1531 if (verify)
1532 {
1533 checkimagecontained (Fcubmap,
1534 Xcubes, Ycubes, Bcubes,
1535 Acubes. empty () ? "X" : "X\\A", "Y");
1536 inclFXYchecked = true;
1537 }
1538 }
1539
1540 // expand A within X and modify (Y,B)
1541 if (!Acubes. empty ())
1542 {
1543 // expand A towards X and modify (Y,B) accordingly
1544 expandAinX (Xcubes, Acubes, Ycubes, Bcubes, Fcubmap,
1545 "X", "A", "B", true /*indexmap*/, checkacyclic);
1546 }
1547
1548 // reduce the pair (X,A) or the set X with acyclicity check
1549 if (checkacyclic)
1550 {
1551 // leave in A only the neighbors of X\\A
1552 restrictAtoneighbors (Xcubes, Acubes, "X", "A");
1553
1554 // reduce the pair (X,A) with acyclicity check
1555 // NOTE: This doesn't seem to work well, so I have turned
1556 // this off if the additional bit of 'careful' is set,
1557 // until I find out what is going on; sorry! [Dec 18, 2010]
1558 if (!keepacyclic)
1559 {
1560 reducepair (Xcubes, Acubes, Fcubmap,
1561 Xkeepcubes, "X", "A");
1562 }
1563
1564 // if nothing remains in X, then the result is trivial
1565 if (Xcubes. empty ())
1566 {
1567 sout << "There are no cubes left "
1568 "in X\\A. The homology of (X,A) "
1569 "is trivial and the map is 0.";
1570 return -1;
1571 }
1572 }
1573
1574 // reduce the pair (X,A) even further
1575 if (!checkacyclic && !Acubes. empty ())
1576 {
1577 // leave in A only the neighbors of X\\A
1578 restrictAtoneighbors (Xcubes, Acubes, "X", "A");
1579
1580 // continue the reduction of the pair (X,A)
1581 reducepair (Xcubes, Acubes, Xkeepcubes, "X", "A");
1582 }
1583
1584 // indicate that the acyclicity of the map should be verified
1585 if (!verify)
1586 {
1587 if (!checkacyclic && ((origAsize != Acubes. size ()) ||
1588 (origXsize != Xcubes. size ())))
1589 {
1590 sout << "*** Important note: X or A changed. "
1591 "You must make sure\n"
1592 "*** that the restriction of F "
1593 "to the new sets is acyclic.\n";
1594 }
1595 else
1596 {
1597 sout << "*** Note: The program assumes "
1598 "that the input map is acyclic.\n";
1599 }
1600 }
1601
1602 // check if F (X\A) \subset Y
1603 if (verify && !inclFXYchecked)
1604 {
1605 checkimagecontained (Fcubmap, Xcubes, Ycubes, Bcubes,
1606 Acubes. empty () ? "X" : "X\\A", "Y");
1607 inclFXYchecked = true;
1608 }
1609
1610 // check if F (A) \subset B [this should always be satisfied]
1611 if (verify && !inclFABchecked && !Acubes. empty ())
1612 {
1613 checkimagecontained (Fcubmap, Acubes, Bcubes, "A", "B");
1614 checkimagedisjoint (Fcubmap, Acubes, Ycubes, "A", "Y\\B");
1615 inclFABchecked = true;
1616 }
1617
1618 // set the union of the domain of the map of interest
1619 // and the image of the map as the cubes to keep in Y
1620 hashedset<cube2ltype> Ykeepcubes;
1621 addmapimg (Fcubmap, Xcubes, Acubes, Ykeepcubes,
1622 true /*indexmap*/);
1623
1624 // reduce the pair of cubical sets (Y,B) towards the image of F
1625 if (Xspacedim == Yspacedim)
1626 {
1627 expandAinX (Ycubes, Bcubes, "Y", "B");
1628 restrictAtoneighbors (Ycubes, Bcubes, "Y", "B", &Ykeepcubes);
1629 reducepair (Ycubes, Bcubes, Ykeepcubes, "Y", "B");
1630 }
1631
1632 // ----- create the cubical complexes -----
1633
1634 // transform the set of cubes X into a set of cells,
1635 // but do not forget Xcubes yet
1637 cubes2cells (Xcubes, Xcompl, Acubes. size () ? "X\\A" : "X", false);
1638
1639 // transform the set of cubes A into a set of cubical cells
1640 // but do not forget Acubes yet
1642 cubes2cells (Acubes, Acompl, "A", false);
1643
1644 // if the set X is empty, no computations are necessary
1645 if (Xcompl. empty ())
1646 {
1647 if (!Acompl. empty ())
1648 sout << "The set X is contained in A. "
1649 "The homology of (X,A) is trivial.";
1650 else
1651 sout << "The set X is empty. "
1652 "The homology of X is trivial.";
1653 return -1;
1654 }
1655
1656 // transform the cubes in Y into cubical cells and forget the cubes
1659 cubes2cells (Ycubes, *Ycompl, Bcubes. empty () ? "Y" : "Y\\B");
1660 if (!Ycubes. empty ())
1661 {
1663 Ycubes = empty;
1664 }
1665
1666 // transform the cubes in B into cubical cells and forget the cubes
1668 cubes2cells (Bcubes, Bcompl, "B");
1669 if (!Bcubes. empty ())
1670 {
1672 Bcubes = empty;
1673 }
1674
1675 // transform the cubes to keep in Y into cells and forget the cubes
1677 cubes2cells (Ykeepcubes, Ykeepcompl, "Ykeep");
1678 if (!Ykeepcubes. empty ())
1679 {
1681 Ykeepcubes = empty;
1682 }
1683
1684 // determine the dimension of X and Y as cubical complexes
1685 int Xdim = Xcompl. dim ();
1686 if ((Xspacedim < 0) && (Xdim >= 0))
1687 Xspacedim = Xcompl [Xdim] [0]. spacedim ();
1688 int Ydim = Ycompl -> dim ();
1689 if ((Yspacedim < 0) && (Ydim >= 0))
1690 Yspacedim = (*Ycompl) [Ydim] [0]. spacedim ();
1691
1692 // ----- collapse the cubical sets (X,A) -----
1693
1694 // create an empty set of cells to keep in X
1696
1697 // reduce the pair of sets (Xcompl, Acompl) while adding to them
1698 // boundaries of all the cells
1699 collapse (Xcompl, Acompl, Xkeepcompl, "X", "A",
1700 true, true, false);
1701
1702 // if nothing remains in X, then the result is trivial
1703 if (Xcompl. empty ())
1704 {
1705 sout << "Nothing remains in X. "
1706 "The homology of (X,A) is trivial.";
1707 return -1;
1708 }
1709
1710 // forget the cells to keep in X
1711 if (!Xkeepcompl. empty ())
1712 {
1714 Xkeepcompl = empty;
1715 }
1716
1717 // make a correction to the dimension of X
1718 if (Xdim != Xcompl. dim ())
1719 {
1720 sout << "Note: The dimension of X decreased from " <<
1721 Xdim << " to " << Xcompl. dim () << ".\n";
1722
1723 Xdim = Xcompl. dim ();
1724 }
1725
1726 // ----- create a reduced graph of F -----
1727
1728 // create the map F defined on the cells in its domain
1729 mvcellmap<cell2ltype,euclidom,cube2ltype> Fcellcubmap (Xcompl);
1730 sout << "Creating the map F on cells in X... ";
1731 int_t countimages = createimages (Fcellcubmap, Fcubmap, Fcubmap,
1732 Xcubes, Acubes);
1733 sout << countimages << " cubes added.\n";
1734
1735 // forget the full cubical set X
1736 if (Xcubes. size ())
1737 {
1739 Xcubes = empty;
1740 }
1741
1742 // create the map F defined on the cells in its domain subcomplex A
1743 mvcellmap<cell2ltype,euclidom,cube2ltype> FcellcubmapA (Acompl);
1744 if (!Acompl. empty ())
1745 {
1746 sout << "Creating the map F on cells in A... ";
1747 int_t count = createimages (FcellcubmapA, Fcubmap, Acubes);
1748 sout << count << " cubes added.\n";
1749 }
1750
1751 // forget the full cubical set A
1752 if (Acubes. size ())
1753 {
1755 Acubes = empty;
1756 }
1757
1758 // create the graph of F as a cubical cell complex
1761 sout << "Creating a cell map for F... ";
1763 bool acyclic = createcellmap (Fcellcubmap, FcellcubmapA,
1764 Fcellmap, verify);
1765 sout << "Done.\n";
1766 if (checkacyclic && !acyclic)
1767 {
1768 sout << "*** SERIOUS PROBLEM: The map is not "
1769 "acyclic. THE RESULT WILL BE WRONG.\n"
1770 "*** You must verify the acyclicity of the "
1771 "initial map with 'chkmvmap'\n"
1772 "*** and, if successful, run this program "
1773 "with the '-a' switch.\n";
1774 }
1775 if (checkacyclic && acyclic)
1776 {
1777 sout << "Note: It has been verified successfully "
1778 "that the map is acyclic.\n";
1779 }
1780
1781 sout << "Creating the graph of F... ";
1782 creategraph (Fcellmap, *Fcompl, false);
1783 sout << Fcompl -> size () << " cells added.\n";
1784
1785 // forget the cubical map on the cells
1786 {
1788 Fcellcubmap = empty;
1789 FcellcubmapA = empty;
1790 }
1791
1792 // ----- collapse the cubical sets (Y,B) -----
1793
1794 // decrease the dimension of B to the dimension of Y
1795 decreasedimension (Bcompl, Ydim, "B");
1796
1797 // create a full cubical complex (with all the faces) of Y\B
1798 if (!Ycompl -> empty ())
1799 {
1800 addboundaries (*Ycompl, Bcompl, 0, false, "Y", "B");
1801
1802 // forget the cubical complex of B
1803 if (!Bcompl. empty ())
1804 {
1805 sout << "Forgetting " << Bcompl. size () <<
1806 " cells from B.\n";
1808 Bcompl = empty;
1809 }
1810 }
1811
1812 // collapse the codomain of the map towards the image of F
1813 {
1814 sout << "Computing the image of F... ";
1815 int_t prev = Ykeepcompl. size ();
1816 project (*Fcompl, Ykeepcompl, *Ycompl, Xspacedim, Yspacedim,
1817 0, 0, false);
1818 project (*Fcompl, Ykeepcompl, *Ycompl, 0, Xspacedim,
1819 Yspacedim, 0, false);
1820 sout << (Ykeepcompl. size () - prev) << " cells added.\n";
1821
1822 sout << "Collapsing Y towards F(X)... ";
1824 int_t count = Ycompl -> collapse (empty, Ykeepcompl,
1825 0, 0, 0, 0);
1826 sout << 2 * count << " cells removed, " <<
1827 Ycompl -> size () << " left.\n";
1828 }
1829
1830 // forget the cells to keep in Y
1831 if (!Ykeepcompl. empty ())
1832 {
1834 Ykeepcompl = empty;
1835 }
1836
1837 // make a correction to the dimension of Y
1838 if (Ydim != Ycompl -> dim ())
1839 {
1840 sout << "Note: The dimension of Y decreased from " <<
1841 Ydim << " to " << Ycompl -> dim () << ".\n";
1842
1843 Ydim = Ycompl -> dim ();
1844 }
1845
1846 // ----- create chain complexes from the cubical sets ------
1847
1848 // create a chain complex from X (this is a relative chain complex!)
1849// chaincomplex<euclidom> cx (Xcompl. dim (), false /*generators*/);
1850
1851 // create a chain complex from the graph of F (it is relative)
1852 chaincomplex<euclidom> cgraph (Fcompl -> dim (), false);
1853 sout << "Creating the chain complex of the graph of F... ";
1854 createchaincomplex (cgraph, *Fcompl);
1855 sout << "Done.\n";
1856
1857 // create the chain complex from Y (this is a relative complex)
1858 chaincomplex<euclidom> cy (Ydim, false);
1859 sout << "Creating the chain complex of Y... ";
1860 createchaincomplex (cy, *Ycompl);
1861 sout << "Done.\n";
1862
1863 // create the projection map from the graph of the map to Y
1864 chainmap<euclidom> cmap (cgraph, cy);
1865 sout << "Creating the chain map of the projection... ";
1866 createprojection (*Fcompl, *Ycompl, cmap, Xspacedim,
1867 Yspacedim, 0);
1868 sout << "Done.\n";
1869
1870 // if this is an index map, create the projection map from the graph
1871 // of the map to X composed with the inclusion into Y
1872 chainmap<euclidom> imap (cgraph, cy);
1873 sout << "Creating the chain map of the inclusion... ";
1874 createprojection (*Fcompl, *Ycompl, imap, 0, Xspacedim, Yspacedim);
1875 sout << "Done.\n";
1876
1877 // forget the graph of F if it is not going to be used anymore
1878 if (gfcompl)
1879 (*gfcompl) = Fcompl;
1880 else
1881 delete Fcompl;
1882
1883 // forget the cubical complex Y unless requested to keep it
1884 if (gycompl)
1885 (*gycompl) = Ycompl;
1886 else
1887 delete Ycompl;
1888
1889 // ----- compute and show homology, save generators -----
1890
1891 // prepare the name of the graph of F
1892 word gFname;
1893 gFname << "the graph of " << Fname;
1894
1895 // compute the homology of the chain complex of the graph of the map
1896 int maxlevel_cx = Homology (cgraph, gFname, hom_cx);
1897
1898 // extract the computed generators of the graph if requested to
1899 if (gfgen)
1900 *gfgen = ExtractGenerators (cgraph, hom_cx, maxlevel_cx);
1901
1902 // compute the homology of the chain complex of Y
1903 chain<euclidom> *hom_cy = 0;
1904 int maxlevel_cy = Homology (cy, Xname, hom_cy);
1905
1906 // extract the computed generators of Y if requested to
1907 if (gygen)
1908 *gygen = ExtractGenerators (cy, hom_cy, maxlevel_cy);
1909
1910 // ----- show the map(s) -----
1911
1912 // determine the maximal non-trivial homology level for maps
1913 int homdimgraph = maxlevel_cx; // cgraph. dim ();
1914// while ((homdimgraph >= 0) && (!hom_cx [homdimgraph]. size ()))
1915// -- homdimgraph;
1916 int homdimy = maxlevel_cy; // cy. dim ();
1917// while ((homdimy >= 0) && (!hom_cy [homdimy]. size ()))
1918// -- homdimy;
1919// sout << "Maximal homology level considered for the map "
1920// "is " << homdim << ".\n";
1921
1922 // prepare the data structures for the homology
1923 chaincomplex<euclidom> hgraph (homdimgraph);
1924 chaincomplex<euclidom> hy (homdimy);
1925 chainmap<euclidom> *hmap = new chainmap<euclidom> (hgraph, hy);
1926 chainmap<euclidom> hincl (hgraph, hy);
1927 chainmap<euclidom> *hcomp = new chainmap<euclidom> (hgraph, hgraph);
1928
1929 // show the map induced in homology by the chain map
1930 sout << "The map induced in homology is as follows:\n";
1931 hgraph. take_homology (hom_cx);
1932 hy. take_homology (hom_cy);
1933 hmap -> take_homology (cmap, hom_cx, hom_cy);
1934 hmap -> show (sout, "\tf", "x", "y");
1935
1936 // show the map induced in homology by the inclusion map
1937 sout << "The map induced in homology by the inclusion:\n";
1938 hincl. take_homology (imap, hom_cx, hom_cy);
1939 hincl. show (sout, "\ti", "x", "y");
1940
1941 sout << "The inverse of the map induced by the inclusion:\n";
1942 bool invertible = true;
1943 try
1944 {
1945 hincl. invert ();
1946 }
1947 catch (...)
1948 {
1949 sout << "Oh, my goodness! This map is apparently "
1950 "not invertible.\n";
1951 invertible = false;
1952 }
1953
1954 if (invertible)
1955 {
1956 hincl. show (sout, "\tI", "y", "x");
1957
1958 sout << "The composition of F and the inverse "
1959 "of the map induced by the inclusion:\n";
1960 hcomp -> compose (hincl, *hmap);
1961 hcomp -> show (sout, "\tF", "x", "x");
1962 }
1963
1964 // set the appropriate map
1965 if (invertible)
1966 {
1967 hom_f = hcomp;
1968 delete hmap;
1969 }
1970 else
1971 {
1972 hom_f = hmap;
1973 delete hcomp;
1974 }
1975
1976 // throw an exception if the map is not invertible
1977 if (!invertible)
1978 throw "Unable to invert the inclusion map.";
1979
1980 maxlevel = (maxlevel_cx < maxlevel_cy) ? maxlevel_cx : maxlevel_cy;
1981 return maxlevel;
1982} /* Homology2l */
1983
1985template <class euclidom, class cubetype>
1988 chain<euclidom> *&hom, int &maxlevel,
1989 chainmap<euclidom> *&hom_f, int careful = 0x01,
1990 chain<euclidom> ***gfgen = 0,
1992 **gfcompl = 0, chain<euclidom> ***gygen = 0,
1994 **gycompl = 0)
1995{
1996 return Homology2l (Fcubmap, "F", Xcubes, "X", Acubes, "A", hom,
1997 maxlevel, hom_f, careful, gfgen, gfcompl, gygen, gycompl);
1998} /* Homology2l */
1999
2000
2001// --------------------------------------------------
2002// ------------ ACYCLICITY VERIFICATION -------------
2003// --------------------------------------------------
2004
2007inline bool acyclic (const cube &q, const cubes &X)
2008{
2009 int dim = q. dim ();
2010 BitField b;
2011 int_t maxneighbors = getmaxneighbors (dim);
2012 b. allocate (maxneighbors);
2013 bool result = acyclic (q, dim, X, &b, maxneighbors);
2014 b. free ();
2015 return result;
2016} /* acyclic */
2017
2018
2019// --------------------------------------------------
2020// ------------- BINARY CUBE FUNCTIONS --------------
2021// --------------------------------------------------
2022
2027template <int dim, int twoPower>
2029{
2030 using namespace chomp::homology;
2031 typedef typename bincube<dim,twoPower>::iterator cubetype;
2033 neighbortype;
2034
2035 // perform the reduction of full cubes in the binary cube first
2036 sout << "Reducing the binary cube";
2037 int prev = b. count ();
2038 reduceFullCubes (b);
2039 sout << (prev - b. count ()) << " cubes removed, " <<
2040 b. count () << " left.\n";
2041
2042 // create an extra binary cube to store connected components
2044
2045 // set the correct wrapping for the new binary cube and the space
2046 coordinate wrap [dim];
2047 bool setwrapping = false;
2048 for (int i = 0; i < dim; ++ i)
2049 {
2050 if (b. wrapped (i))
2051 {
2052 wrap [i] = 1 << twoPower;
2053 setwrapping = true;
2054 c. wrap (i);
2055 }
2056 else
2057 wrap [i] = 0;
2058 }
2059 if (setwrapping)
2061
2062 // reset the table to store Betti numbers
2063 for (int i = 0; i <= dim; ++ i)
2064 result [i] = 0;
2065
2066 // gather Betti numbers for each connected component separately
2067 bool first_run = true;
2068 while (!b. empty ())
2069 {
2070 // increase the 0th Betti number which counts conn. comp.
2071 ++ *result;
2072
2073 // extract a connected component
2074 if (first_run)
2075 first_run = false;
2076 else
2077 c. clear ();
2078 hashIntQueue s;
2079 s. push (static_cast<int> (b. begin ()));
2080 while (!s. empty ())
2081 {
2082 int n = s. front ();
2083 s. pop ();
2084 neighbortype cur = b. neighborhood_begin (n);
2085 neighbortype end = b. neighborhood_end (n);
2086 while (cur != end)
2087 {
2088 s. push (static_cast<int> (cur));
2089 ++ cur;
2090 }
2091 c. add (n);
2092 b. remove (n);
2093 }
2094
2095 // if the component has just one cube, the answer is obvious
2096 if (c. count () == 1)
2097 continue;
2098
2099 // transform the binary cube into the usual set of cubes
2100 // (in the future this step will be postponed)
2101 SetOfCubes X;
2102 cubetype cur (c. begin ()), end (c. end ());
2103 while (cur != end)
2104 {
2105 X. add (cube_cast<Cube> (cur));
2106 ++ cur;
2107 }
2108
2109 // say which connected component is processed
2110 sout << "Connected component no. " << *result <<
2111 " (" << X. size () << " cubes):\n";
2112
2113 // prepare a pair of sets for relative homology computation
2114 SetOfCubes A;
2115 int_t number = X. size () - 1;
2116 A. add (X [number]);
2117 X. removenum (number);
2118
2119 // compute the relative homology
2120 Chain *chn = 0;
2121 int maxlevel = Homology (X, "X", A, "A", chn);
2122
2123 // display the result
2124 ShowHomology (chn, maxlevel);
2125
2126 // update the Betti number count
2127 for (int i = 1; i <= maxlevel; ++ i)
2128 result [i] += BettiNumber (chn [i]);
2129
2130 // release the memory assigned to the table of chains
2131 if (chn)
2132 delete [] chn;
2133 }
2134
2135 sout << "Computed Betti numbers:";
2136 for (int i = 0; i <= dim; ++ i)
2137 sout << " " << result [i];
2138 sout << ".\n";
2139
2140 return;
2141} /* ComputeBettiNumbers */
2142
2151template <int dim, int twoPower, class coordtype>
2152void ComputeBettiNumbers (char *binary_buffer, int *result,
2153 const coordtype *space_wrapping = 0)
2154{
2155 using namespace chomp::homology;
2156
2157 // create a binary cube based on the binary buffer
2158 bincube<dim,twoPower> b (binary_buffer);
2159
2160 // set the space wrapping if requested to
2161 if (space_wrapping)
2162 {
2163 for (int i = 0; i < dim; ++ i)
2164 {
2165 if (!space_wrapping [i])
2166 continue;
2167 int w = space_wrapping [i];
2168 if (w != (1 << twoPower))
2169 sout << "WARNING: Wrapping [" << i <<
2170 "] set to " << (1 << twoPower) <<
2171 ".\n";
2172 b. wrap (i);
2173 }
2174 }
2175
2176 ComputeBettiNumbers (b, result);
2177 return;
2178} /* ComputeBettiNumbers */
2179
2180
2181// --------------------------------------------------
2182// -------------- SIMPLIFIED INTERFACE --------------
2183// --------------------------------------------------
2184
2193template <class coordtype>
2194void ComputeBettiNumbers (coordtype *coord, int n, int dim, int *result)
2195{
2196 using namespace chomp::homology;
2197
2198 // create a corresponding set of cubes
2199 SetOfCubes X;
2201 coordtype const *coordpointer = coord;
2202 for (int i = 0; i < n; ++ i)
2203 {
2204 for (int j = 0; j < dim; ++ j)
2205 c [j] = static_cast<coordtype> (*(coordpointer ++));
2206 X. add (Cube (c, dim));
2207 }
2208
2209 // turn off screen output
2210 bool soutput = sout. show;
2211 sout. show = false;
2212 bool coutput = scon. show;
2213 scon. show = false;
2214
2215 // compute the homology of the constructed cubical set
2216 Chain *hom;
2217 int maxlevel = Homology (X, "X", hom);
2218
2219 // fill out the resulting table of Betti numbers
2220 for (int j = 0; j <= dim; ++ j)
2221 result [j] = (j <= maxlevel) ? BettiNumber (hom [j]) : 0;
2222
2223 // free unused memory and finish
2224 if (hom)
2225 delete [] hom;
2226 sout. show = soutput;
2227 scon. show = coutput;
2228 return;
2229} /* ComputeBettiNumbers */
2230
2236template <class coordtype>
2237inline void SetSpaceWrapping (int dim, const coordtype *wrap)
2238{
2239 if ((dim < 0) || (dim >= Cube::MaxDim))
2240 return;
2241
2242 // set space wrapping if requested to
2244 for (int j = 0; j < dim; ++ j)
2245 wrapcoord [j] = static_cast <coordtype>
2246 ((wrap [j] >= 0) ? wrap [j] : -wrap [j]);
2248 return;
2249} /* SetSpaceWrapping */
2250
2251
2252} // namespace homology
2253} // namespace chomp
2254
2255#endif // _CHOMP_HOMOLOGY_HOMOLOGY_H_
2256
2258
This file contains the definition of a class which can be used to parse the command line of a program...
This file contains the definition of a cubical set represented as a bitmap.
This class defines a bit field that is part of some larger array or that uses an allocated piece of m...
Definition: bitfield.h:73
The iterator of the set of cubes within a bitmap.
Definition: bincube.h:152
A binary n-dimensional hypercube for storing cubes as bits.
Definition: bincube.h:121
This class defines objects which represent chains as finite sequences of elements identified by integ...
Definition: chains.h:94
This is an implementation of a chain complex over an arbitrary ring.
Definition: chains.h:2662
This class defines a chain map between two chain complexes.
Definition: chains.h:3243
The class that defines a geometric complex - a set of cells (cubes, simplices, etc).
Definition: gcomplex.h:85
This is a template for a set of objects of the given type.
Definition: hashsets.h:185
Local variable guardian.
Definition: localvar.h:54
A class for representing sparse matrices containing elements of the 'euclidom' type.
Definition: chains.h:1067
This class represents a multivalued map whose domain is a geometric complex.
Definition: gcomplex.h:1530
This class defines a multivalued map.
Definition: hashsets.h:945
A general cubical cell with additional information about the layer number.
Definition: twolayer.h:483
A (hyper)cube with additional information about the layer number.
Definition: twolayer.h:80
This class defines a hypercube in R^n with edges parallel to the axes and with size 1 in each directi...
Definition: cubebase.h:72
static const int MaxDim
The maximal dimension of a cube.
Definition: cubebase.h:81
static void setwrapping(const coordtype *c, int mindim=1, int maxdim=MaxBasDim)
Sets space wrapping for all the dimensions in the range starting with 'mindim' and strictly smaller t...
Definition: pointbas.h:248
A word, that is, a string with very few properties.
Definition: words.h:65
This file contains some precompiler definitions which indicate the operating system and/or compiler u...
int int_t
Index type for indexing arrays, counting cubes, etc.
Definition: config.h:115
This file contains various small procedures that might be useful in programs which compute homology.
This file contains the definition of a template of a class whose object can define a local value of a...
const char * ringsymbol()
Definition: algstruct.h:216
This namespace contains the core of the homology computation procedures and related classes and templ...
Definition: bitmaps.h:52
void ShowHomology(const chain< euclidom > &c)
Shows (that is, writes to 'sout') one level of the homology module encoded in the given chain.
Definition: homology.h:137
int MaxBddDim
The maximal dimension for which binary decision diagrams are used.
bool acyclic(int dim, BitField &b)
Checks whether this cube's nieghbors form an acyclic set.
Definition: cubacycl.h:70
bool checkimagecontained(const maptype &Fcubmap, const cubsettype &Xcubes, const cubsettype &Ycubes, const cubsettype &Bcubes, const char *Xname, const char *Yname)
Checks if the image of X by F is contained in the union of Y and B.
Definition: homtools.h:384
hashedset< simplex > SetOfSimplices
A class for representing a set of simplices.
Definition: homology.h:89
chaincomplex< integer > ChainComplex
A class for representing a chain complex with integral coefficients.
Definition: homology.h:80
chain< euclidom > ** ExtractGenerators(const chaincomplex< euclidom > &cx, chain< euclidom > *hom, int maxlevel)
Extracts homology generators from a chain complex in the simple form.
Definition: homology.h:339
outputstream sout
A replacement for standard output stream, with optional logging and other features provided by the cl...
int TorsionCoefficient(const chain< euclidom > &c, int start=0)
Returns the next position in the chain containing a torsion coefficient.
Definition: homology.h:120
void ShowGenerators(const chain< euclidom > *c, int count)
Shows (that is, writes to 'sout') all the generators of one level of the homology module of a chain c...
Definition: homology.h:218
void wrapcoord(coordtype *destination, const coordtype *source, const coordtype *wrap, int dim)
Wraps coordinates stored in 'c' accordint to the wrap table 'wrap' and store the result in the table ...
Definition: pointset.h:119
int Homology2l(mvmap< cubetype, cubetype > &Fcubmap0, const char *Fname, hashedset< cubetype > &Xcubes0, const char *Xname, hashedset< cubetype > &Acubes0, const char *Aname, chain< euclidom > *&hom_cx, int &maxlevel, chainmap< euclidom > *&hom_f, int careful=0x01, chain< euclidom > ***gfgen=0, gcomplex< tCell2l< typename cubetype::CellType >, euclidom > **gfcompl=0, chain< euclidom > ***gygen=0, gcomplex< tCell2l< typename cubetype::CellType >, euclidom > **gycompl=0)
Computes the endomorphism induced in homology by a combinatorial cubical multivalued map using the tw...
Definition: homology.h:1353
void reducepair(cubsettype &Xcubes, cubsettype &Acubes, const cubsettype &Xkeepcubes, const char *Xname, const char *Aname)
Reduces the pair of sets of cubes. Keeps the given cubes untouched.
Definition: homtools.h:619
bool inclusion(const HSet &X, const HSet &Y)
Verifies if X is a subset of Y. Returns true if yes, false if not.
Definition: indxpalg.h:309
outputstream sbug
An output stream for writing additional debug messages.
void project(const gcomplex< tCell, euclidom > &c, gcomplex< tCell, euclidom > &img, const gcomplex< tCell, euclidom > &only, int offset, int outdim, int discarddim, const int *level, bool watchforimages)
Creates the image of the projection from the set of cubical cells in the given geometric complex to t...
Definition: cubmaps.h:320
void cubes2cells(tCubes &Xcubes, gcomplex< tCell, tCoef > &Xcompl, const char *Xname, bool deletecubes=true)
Transforms cubes to full-dimensional cells.
Definition: homtools.h:716
int_t getmaxneighbors(int dim)
Returns the maximal number of neighbors of a cube: 3^dim - 1.
Definition: neighbor.h:60
void createprojection(const gcomplex< tCell, euclidom > &Fcompl, const gcomplex< tCell, euclidom > &Ycompl, chainmap< euclidom > &cmap, int offset, int outdim, int discarddim, int *level=NULL)
Creates the chain map of the projection from a cell complex of the graph of a map to a cell complex o...
Definition: cubmaps.h:237
BitFields knownbits
The global table of BitFields which store the acyclicity information for reducing full cubical sets.
void addboundaries(gcomplex< cell, euclidom > &Xcompl, gcomplex< cell, euclidom > &Acompl, int minlevel, bool bothsets, const char *Xname, const char *Aname)
Adds boundaries to the geometric complex X or to both X and A.
Definition: homtools.h:835
bool checkinclusion(const cubsettype &Xcubes, const cubsettype &Ycubes, const cubsettype &Bcubes, const char *Xname, const char *YBname)
Checks if X is a subset of the union of Y and B.
Definition: homtools.h:349
int_t createimages(mvcellmap< tCell, euclidom, tCube > &m, const mvmap< tCube, tCube > &f1, const mvmap< tCube, tCube > &f2, const hashedset< tCube > &dom1, const hashedset< tCube > &dom2)
Creates images of cells in 'm' as unions of cubes determined by f1 and f2.
Definition: cubmaps.h:147
void SetSpaceWrapping(int dim, const coordtype *wrap)
Sets space wrapping in each direction separately.
Definition: homology.h:2237
void collapse(gcomplex< cell, euclidom > &Xcompl, gcomplex< cell, euclidom > &Acompl, gcomplex< cell, euclidom > &Xkeepcompl, const char *Xname, const char *Aname, bool addbd=true, bool addcob=false, bool disjoint=true, const int *level=NULL)
Collapses a pair of geometric complexes.
Definition: homtools.h:742
void createcellmap(const mvcellmap< cell, euclidom, element > &m, mvcellmap< cell, euclidom, cell > &cm)
Creates the graph of the map as a cell complex while reducing as possible.
Definition: gcomplex.h:1874
chainmap< euclidom > * HomologyMap(const chainmap< euclidom > &cmap, const chain< euclidom > *hom_cx, const chain< euclidom > *hom_cy, int maxlevel)
Extracts the homomorphism induced in homology from the chain map on two chain complexes whose homolog...
Definition: homology.h:706
short int coordinate
The default type of coordinates.
Definition: pointset.h:63
chain< integer > Chain
A class for representing a chain with integral coefficients.
Definition: homology.h:86
void expandAinX(cubsettype &Xcubes, cubsettype &Acubes, const char *Xname, const char *Aname)
Expands the other element of the pair into the main portion of the set.
Definition: homtools.h:580
chainmap< integer > ChainMap
A class for representing a chain map with integral coefficients.
Definition: homology.h:83
void ShowGenerator(const chain< euclidom > &c)
Shows (that is, writes to 'sout') one generator of the homology module of a chain complex.
Definition: homology.h:208
bool checkimagedisjoint(const maptype &Fcubmap, const cubsettype &Acubes, const cubsettype &Ycubes, const char *Aname, const char *Yname)
Checks if the image of A by F is disjoint from Y (actually, from Y\B).
Definition: homtools.h:428
int BettiNumber(const chain< euclidom > &c)
Returns the Betti number that corresponds to the given chain which describes one homology group.
Definition: homology.h:104
void decreasedimension(gcomplex< cell, euclidom > &Acompl, int dim, const char *name)
Decreases the dimension of the geometric complex by adding boundary cells to all the cells on higher ...
Definition: homtools.h:813
outputstream scon
The console output stream to which one should put all the junk that spoils the log file,...
chaincomplex< euclidom > & createchaincomplex(chaincomplex< euclidom > &c, const gcomplex< cell, euclidom > &g, bool quiet=false)
Creates an algebraic chain complex based on the data from the given geometric cell complex.
Definition: gcomplex.h:1128
gcomplex< simplex, integer > SimplicialComplex
A class for representing a simplicial complex.
Definition: homology.h:92
int reduceFullCubes(FullCubSet &X, bool quiet=false)
Reduces the set of full cubes.
Definition: bincube.h:1167
void ComputeBettiNumbers(bincube< dim, twoPower > &b, int *result)
Computes the Betti Numbers of a set of full cubes in a bincube.
Definition: homology.h:2028
int Homology(chaincomplex< euclidom > &cx, const char *Xname, chain< euclidom > *&hom)
Transforms the chain complex into a simple form and compute its homology.
Definition: homology.h:379
void restrictAtoneighbors(const cubsettype &Xcubes, cubsettype &Acubes, const char *Xname, const char *Aname, const cubsettype *keepcubes=0)
Restricts the set of cubes 'Acubes' to these cubes which are neighbors of any of the cubes in 'Xcubes...
Definition: homtools.h:503
void removeAfromX(cubsettype &Xcubes, const cubsettype &Acubes, const char *Xname, const char *Aname)
Removes 'Acubes' from 'Xcubes' and shows messages.
Definition: homtools.h:548
void addmapimg(const maptype &Fcubmap, const maptype &FcubmapA, const cubsettype &Xcubes, const cubsettype &Acubes, cubsettype &Ykeepcubes, bool indexmap)
Adds the images of both maps to the set of cubes to be kept.
Definition: homtools.h:658
gcomplex< cell, euclidom > & creategraph(const mvmap< cell, cell > &m, gcomplex< cell, euclidom > &graph)
Add a graph of a multivalued cell map to the cell complex.
Definition: gcomplex.h:1429
This namespace contains the entire CHomP library interface.
Definition: bitmaps.h:51
This file contains some useful functions related to the text input/output procedures.
This file defines a simple data structure which can be used to measure time used by the program (or s...
This file contains the definition of two-layer cubical sets, as introduced in the paper "Excision-pre...
This file contains a definition of the class "word" which is used to store a string and has some addi...