The ChainCon Software (Release 0.03)
ammodel.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file
4 ///
5 /// Computation of the algebraic minimal model using the SNF.
6 /// This algorithm works for an arbitrary commutative ring of coefficients
7 /// that is an Euclidean domain.
8 ///
9 /////////////////////////////////////////////////////////////////////////////
10 
11 // Copyright (C) 2009-2016 by Pawel Pilarczyk.
12 //
13 // This file is part of my research software package. This is free software:
14 // you can redistribute it and/or modify it under the terms of the GNU
15 // General Public License as published by the Free Software Foundation,
16 // either version 3 of the License, or (at your option) any later version.
17 //
18 // This software is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU General Public License for more details.
22 //
23 // You should have received a copy of the GNU General Public License
24 // along with this software; see the file "license.txt". If not,
25 // please, see <http://www.gnu.org/licenses/>.
26 
27 // Started on March 24, 2009. Last revision: January 13, 2013.
28 
29 
30 #ifndef _CHAINCON_AMMODEL_H_
31 #define _CHAINCON_AMMODEL_H_
32 
33 
34 // include relevant local header files
35 #include "chaincon/chain.h"
36 #include "chaincon/linmap.h"
37 #include "chaincon/comblinmap.h"
38 #include "chaincon/filtcomplex.h"
39 #include "chaincon/algcell.h"
40 #include "chaincon/snf.h"
41 
42 // include selected header files from the CHomP library
43 #include "chomp/system/config.h"
44 #include "chomp/system/textfile.h"
45 #include "chomp/system/timeused.h"
46 #include "chomp/struct/hashsets.h"
47 #include "chomp/struct/multitab.h"
48 #include "chomp/struct/integer.h"
49 #include "chomp/homology/chains.h"
50 
51 // include some standard C++ header files
52 #include <istream>
53 #include <ostream>
54 #include <vector>
55 
56 
57 // --------------------------------------------------
58 // -------------------- AM Model --------------------
59 // --------------------------------------------------
60 
61 /// Computes a minimal model for a given filtered finite cell complex "K".
62 /// Cells that represent those generators of M whose boundary and coboundary
63 /// are both zero are appended to the vector "H"; note that they represent
64 /// (co)homology generators corresponding to the free part
65 /// of the (co)homology module.
66 /// The other generators of "M" are appended to the vectors "A" and "B"
67 /// with the corresponding coefficients stored in the vector "Q"
68 /// in such a way that the boundary of "A[i]" equals the coefficient "Q[i]"
69 /// times "B[i]".
70 /// The projection map "pi" onto M, the inclusion from "H+A+B" to "K",
71 /// and the chain contraction "phi" on "K" are assumed to be initially zero
72 /// and are constructed.
73 template <class CellT, class CoefT, class CellArray1, class CellArray2,
74  class CellArray3, class CoefArray>
75 void algMinModel (const tFilteredComplex<CellT> &K, CellArray1 &H,
76  CellArray2 &A, CellArray3 &B, CoefArray &Q,
80 {
81  using chomp::homology::sout;
82 // using chomp::homology::scon;
83  using chomp::homology::sbug;
84  using chomp::homology::timeused;
85  using chomp::homology::multitable;
86  using chomp::homology::hashedset;
87 
88  typedef typename tMatrixSNF<CoefT>::CellType AlgCellType;
89  typedef typename tMatrixSNF<CoefT>::ChainType AlgChainType;
90 
91  // don't do anything for the empty complex
92  if (K. empty ())
93  return;
94 
95  // start measuring total computation time of this routine
96  timeused compTime;
97  compTime = 0;
98 
99  // split K into cells of each dimension
100  sout << "Splitting K into sets of cells of each dimension...\n";
101  timeused splitTime;
102  splitTime = 0;
103 
104  // prepare an array of sets of cells
105  multitable<hashedset<CellT> > cells;
106 
107  // prepare a strict upper bound on the dimension of the cells
108  int maxDim = 0;
109 
110  // split the set of cells in the filtration into the subsets
111  const int_t KSize = K. size ();
112  for (int_t k = 0; k < KSize; ++ k)
113  {
114  const CellT &cell (K [k]);
115  int dim (cell. dim ());
116  if (dim >= 0)
117  cells [dim]. add (cell);
118  if (dim >= maxDim)
119  maxDim = dim + 1;
120  }
121 
122  // show timing information
123  sout << "K split in " << splitTime << ".\n";
124 
125  // construct the matrices of the boundary operator
126  sout << "Creating the matrices of the boundary operator on K...\n";
127  timeused constrTime;
128  constrTime = 0;
129 
130  // create the collection of matrices for the boundary operator
131  tMatrixSNF<CoefT> matrix;
132 
133  // set the correct sizes of the matrices
134  for (int q = 0; q < maxDim; ++ q)
135  {
136  int_t nRows = (q > 0) ? cells [q - 1]. size () :
137  (CellT::EmptyType::exists () ? 1 : 0);
138  int_t nCols = cells [q]. size ();
139  matrix. setSize (q, nRows, nCols);
140  // sbug << "DEBUG: Boundary " << q << " matrix: " <<
141  // nRows << " rows, " << nCols << " columns.\n";
142  }
143 
144  // go through all the cells in the filter and compute boundaries
145  for (int q = 0; q < maxDim; ++ q)
146  {
147  if ((q == 0) && !CellT::EmptyType::exists ())
148  continue;
149  int_t size (cells [q]. size ());
150  for (int_t cNum = 0; cNum < size; ++ cNum)
151  {
152  // retrieve the i-th cell in the filter
153  const CellT &c = cells [q] [cNum];
154 
155  // compute the boundary of this cell
156  int_t bLen = c. boundaryLength ();
157  for (int_t j = 0; j < bLen; ++ j)
158  {
159  // create the j-th boundary cell
160  CellT bCell (c, j);
161 
162  // determine the coefficient
163  CoefT bCoef (c. boundaryCoef (j));
164 
165  // determine the number of the boundary cell
166  int_t bNum = (q > 0) ?
167  cells [q - 1]. getnumber (bCell) : 0;
168 
169  // ignore the cell is it is not in the set
170  if (bNum < 0)
171  continue;
172 
173  // add the boundary coefficient to the matrix
174  // sbug << "DEBUG: Boundary matrix " << q <<
175  // " add " << bCoef << " at row " <<
176  // bNum << " and col " << cNum << ".\n";
177  matrix. add (q, bNum, cNum, bCoef);
178  }
179  }
180  }
181 
182  // show timing information
183  sout << "The boundary matrices created in " << constrTime << ".\n";
184 
185  // compute the SNF
186  sout << "Computing the SNF of the boundary operator...\n";
187  timeused snfTime;
188  snfTime = 0;
189  matrix. computeSNF (maxDim);
190 
191  // show timing information
192  sout << "The SNF computed in " << snfTime << ".\n";
193 
194  // DEBUG: Check if the change of basis matrices are correct.
195  if (true)
196  verifyChangeOfBasisSNF (matrix, maxDim);
197 
198  // compute the g.v.f. together with the projection and the inclusion
199  sout << "Composing a chain contraction from the SNF...\n";
200  timeused composingTime;
201  composingTime = 0;
202 
203  // prepare the matrices for psi
204  typedef tLinMap<AlgCellType,AlgCellType,CoefT> AlgMapType;
205  multitable<AlgMapType> psi;
206 
207  // prepare matrices for storing representant cells for generators
208  multitable<tCombLinMap<AlgCellType,CellT> > representants;
209 
210  // prepare data for storing torsion relations:
211  // torsionUp (cell) = higher-dimensional cell with the torsion coef
212 // multitable<AlgMapType> torsionUp;
213 
214  // scan through the boundary matrices in the SNF
215  for (int q = 0; q < maxDim; ++ q)
216  {
217  // prepare a counter of homology generator representants
218  int_t genNumber (0);
219 
220  // scan the coefficients in this matrix
221  int_t nCols = cells [q]. size ();
222  for (int_t cell = 0; cell < nCols; ++ cell)
223  {
224  // determine the row with a nonzero coef if any
225  int_t bcell = matrix. getColCell (q, cell);
226  bool torsionCell = false;
227  // CoefT torsionCoef (0);
228 
229  // if the column is non-zero
230  if (bcell >= 0)
231  {
232  const CoefT e (matrix. getColCoef (q, cell));
233  const int delta (e. delta ());
234  if (delta == 1)
235  {
236  const AlgCellType dom (bcell);
237  const AlgCellType img (cell);
238  if (q)
239  psi [q - 1]. add (dom, img, e);
240  continue;
241  }
242  else
243  {
244  const AlgCellType c (bcell);
245  B. push_back (representants [q - 1].
246  getImage (c). getCell (0));
247  Q. push_back (e);
248  torsionCell = true;
249  // torsionCoef = e;
250  }
251  }
252 
253  // otherwise check the preimage of the cell
254  // by the boundary operator in the SNF
255  bool torsionImage = false;
256  if (q < maxDim - 1)
257  {
258  CoefT e (matrix. getRowCoef (q + 1, cell));
259 
260  // if the cell is a boundary then skip it
261  if (e. delta () == 1)
262  continue;
263 
264  // if the cell is an image of torsion part
265  else if (e. delta () > 1)
266  {
267  // const AlgCellType higher (matrix.
268  // getRowCell (q + 1, cell));
269  // torsionUp [q]. add (cell, higher, e);
270  torsionImage = true;
271  // torsionCoef = e;
272  }
273  }
274 
275  // define a representant of this generator
276  const CellT &repr = cells [q] [genNumber];
277  representants [q]. add (AlgCellType (cell), repr);
278  ++ genNumber;
279  if (torsionCell)
280  A. push_back (repr);
281  else if (!torsionImage)
282  H. push_back (repr);
283 
284  // determine the real homology generator
285  const AlgChainType genChain
286  (matrix. getOldChain (q, cell));
287 
288  // compute the inclusion map on this generator
289  int_t genSize = genChain. size ();
290  for (int_t j = 0; j < genSize; ++ j)
291  {
292  int_t n = genChain. getCell (j). getId ();
293  CoefT e = genChain. getCoef (j);
294  const CellT &genCell = cells [q] [n];
295  incl. add (repr, genCell, e);
296  }
297 
298  // add this generator to the image of all the cells
299  // by the projection, whenever the cells have it
300  // in their images by the change-of-basis matrix
301  const AlgChainType piRow
302  (matrix. getNewChainRow (q, cell));
303  int_t piRowSize = piRow. size ();
304  for (int_t j = 0; j < piRowSize; ++ j)
305  {
306  int_t n = piRow. getCell (j). getId ();
307  CoefT e = piRow. getCoef (j);
308  const CellT &cell = cells [q] [n];
309  pi. add (cell, repr, e);
310  }
311  }
312  }
313 
314  // compute the matrices for phi_q and compose them into one map:
315  // \phi_{q - 1} := A^{-1}_q \circ \psi_{q - 1} \circ A_{q - 1}
316  sout << "Transferring the computed chain contraction "
317  "to the original basis...\n";
318  for (int q = 1; q < maxDim; ++ q)
319  {
320  // for all the cells of dimension q - 1
321  int_t nCells (cells [q - 1]. size ());
322  for (int_t cell = 0; cell < nCells; ++ cell)
323  {
324  // compute the chain in the new basis
325  AlgChainType ch (matrix. getNewChain (q - 1, cell));
326 
327  // apply psi to this chain
328  AlgChainType psich (psi [q - 1] (ch));
329 
330  // compute the resulting chain in the original basis
331  AlgChainType algImage;
332  int_t size (psich. size ());
333  for (int_t i = 0; i < size; ++ i)
334  {
335  // compute the algebraic chain for this part
336  int_t n (psich. getCell (i). getId ());
337  const CoefT &e (psich. getCoef (i));
338  AlgChainType a (matrix. getOldChain (q, n));
339  a *= e;
340  algImage += a;
341  }
342 
343  // translate the algebraic chain to the real one
344  tChain<CellT,CoefT> image;
345  int_t algSize (algImage. size ());
346  for (int_t i = 0; i < algSize; ++ i)
347  {
348  const CoefT &coef (algImage. getCoef (i));
349  int_t n (algImage. getCell (i). getId ());
350  const CellT &cell (cells [q] [n]);
351  image. add (cell, coef);
352  }
353 
354  // set the image in the map phi
355  phi. getImage (cells [q - 1] [cell]). swap (image);
356  }
357  }
358 
359  // show timing information
360  sout << "Chain contraction composed in " << composingTime << ".\n";
361 
362  // show information on the total computation time of this routine
363  sout << "AM model computed in " << compTime << ".\n";
364 
365  return;
366 } /* algMinModel */
367 
368 
369 #endif // _CHAINCON_AMMODEL_H_
370 
A linear map for coefficients in an arbitrary commutative ring.
This file includes a specific interface to an SNF computation algorithm.
A chain with coefficients in an arbitrary ring.
Definition: chain.h:50
A combinatorial linear map (for coefficients in Z_2).
A filtered cell complex.
A linear map.
Definition: linmap.h:55
A filtered complex.
Definition: filtcomplex.h:53
An abstract algebraic cell.
A chain with coefficients in an arbitrary commutative ring.
void verifyChangeOfBasisSNF(const MatrixT &matrix, int maxDim)
Verifies if the change of basis matrices match each other.
Definition: snf.h:59
void algMinModel(const tFilteredComplex< CellT > &K, CellArray1 &H, CellArray2 &A, CellArray3 &B, CoefArray &Q, tLinMap< CellT, CellT, CoefT > &pi, tLinMap< CellT, CellT, CoefT > &incl, tLinMap< CellT, CellT, CoefT > &phi)
Computes a minimal model for a given filtered finite cell complex "K".
Definition: ammodel.h:75
An abstract algebraic cell, characterized by a unique identifier, dimension, and a formula for its bo...
Definition: algcell.h:54
An interface for the computation of the Smith Normal Form of a series of a few rectangular matrices w...
Definition: snfchomp.h:86