The ChainCon Software (Release 0.03)
atmodel4r.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file
4 ///
5 /// Algebraic topological model computation: Algorithm 4, using the SNF;
6 /// version for an arbitrary commutative ring of coefficients.
7 /// This is in fact Algorithm 3 implemented using the generic SNF interface.
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 10, 2013.
28 
29 
30 #ifndef _CHAINCON_ATMODEL4R_H_
31 #define _CHAINCON_ATMODEL4R_H_
32 
33 
34 // include some standard C++ header files
35 #include <istream>
36 #include <ostream>
37 #include <vector>
38 
39 // include selected header files from the CHomP library
40 #include "chomp/system/config.h"
41 #include "chomp/system/textfile.h"
42 #include "chomp/system/timeused.h"
43 #include "chomp/struct/hashsets.h"
44 #include "chomp/struct/multitab.h"
45 #include "chomp/struct/integer.h"
46 #include "chomp/homology/chains.h"
47 
48 // include relevant local header files
49 #include "chaincon/chain.h"
50 #include "chaincon/linmap.h"
51 //#include "chaincon/filtcomplex.h"
52 #include "chaincon/algcell.h"
53 #include "chaincon/snf.h"
54 #include "chaincon/emptycell.h"
55 
56 
57 // --------------------------------------------------
58 // -------------------- AT model --------------------
59 // --------------------------------------------------
60 
61 /// Computes an algebraic topological model for the given
62 /// filtered finite cell complex "K".
63 /// Cells that represent homology generators are appended to the vector "H".
64 /// The projection map "pi", the inclusion from "H" to the complex "K",
65 /// and the homology gradient vector field "phi"
66 /// are assumed to be initially zero and are constructed.
67 template <class CellT, class CoefT, class CellArray1, class CellArray2,
68  class CellRestrT>
69 void algTopModel4 (const CellArray1 &K, CellArray2 &H,
73  const CellRestrT &restr)
74 {
75  using chomp::homology::sout;
76 // using chomp::homology::scon;
77  using chomp::homology::sbug;
78  using chomp::homology::timeused;
79  using chomp::homology::multitable;
80  using chomp::homology::hashedset;
81 
82  typedef typename tMatrixSNF<CoefT>::CellType AlgCellType;
83  typedef typename tMatrixSNF<CoefT>::ChainType AlgChainType;
84 
85  // don't do anything for the empty complex
86  if (K. empty ())
87  return;
88 
89  // start measuring total computation time of this routine
90  timeused compTime;
91  compTime = 0;
92 
93  // split K into cells of each dimension
94  sbug << "[AT Model Algorithm 4r.]\n";
95  sout << "Splitting K into sets of cells of each dimension...\n";
96  timeused splitTime;
97  splitTime = 0;
98 
99  // prepare an array of sets of cells
100  multitable<hashedset<CellT> > cells;
101 
102  // prepare a strict upper bound on the dimension of the cells
103  int maxDim = 0;
104 
105  // split the set of cells in the filtration into the subsets
106  const int_t KSize = K. size ();
107  for (int_t k = 0; k < KSize; ++ k)
108  {
109  const CellT &cell (K [k]);
110  int dim (cell. dim ());
111  if (dim >= 0)
112  cells [dim]. add (cell);
113  if (dim >= maxDim)
114  maxDim = dim + 1;
115  }
116 
117  // show timing information
118  sout << "K split in " << splitTime << ".\n";
119 
120  // construct the matrices of the boundary operator
121  sout << "Creating the matrices of the boundary operator on K...\n";
122  timeused constrTime;
123  constrTime = 0;
124 
125  // create the collection of matrices for the boundary operator
126  tMatrixSNF<CoefT> matrix;
127 
128  // set the correct sizes of the matrices
129  for (int q = 0; q < maxDim; ++ q)
130  {
131  int_t nRows = (q > 0) ? cells [q - 1]. size () :
132  (CellT::EmptyType::exists () ? 1 : 0);
133  int_t nCols = cells [q]. size ();
134  // sbug << "DEBUG: q = " << q << ", nRows = " << nRows <<
135  // ", nCols = " << nCols << ".\n";
136  matrix. setSize (q, nRows, nCols);
137  }
138 
139  // go through all the cells in the filter and compute boundaries
140  for (int q = 0; q < maxDim; ++ q)
141  {
142  if ((q == 0) && !CellT::EmptyType::exists ())
143  continue;
144  int_t size (cells [q]. size ());
145  for (int_t cNum = 0; cNum < size; ++ cNum)
146  {
147  // retrieve the i-th cell in the filter
148  const CellT &c = cells [q] [cNum];
149 
150  // compute the boundary of this cell
151  int_t bLen = c. boundaryLength ();
152  for (int_t j = 0; j < bLen; ++ j)
153  {
154  // create the j-th boundary cell
155  CellT bCell (c, j);
156 
157  // determine the number of the boundary cell
158  int_t bNum = (q > 0) ?
159  cells [q - 1]. getnumber (bCell) : 0;
160 
161  // ignore the cell is it is not in the set
162  if (bNum < 0)
163  continue;
164 
165  // determine the coefficient
166  CoefT bCoef (c. boundaryCoef (j));
167 
168  // add the boundary coefficient to the matrix
169  // sbug << "DEBUG: q = " << q << ", bNum = " <<
170  // bNum << ", cNum = " << cNum <<
171  // ", bCoef = " << bCoef << ".\n";
172  matrix. add (q, bNum, cNum, bCoef);
173  }
174  }
175  }
176 
177  // show timing information
178  sout << "The boundary matrices created in " << constrTime << ".\n";
179 
180  // compute the SNF
181  sout << "Computing the SNF of the boundary operator...\n";
182  timeused snfTime;
183  snfTime = 0;
184  matrix. computeSNF (maxDim);
185 
186  // show timing information
187  sout << "The SNF computed in " << snfTime << ".\n";
188 
189  // DEBUG: Check if the change of basis matrices are correct.
190  if (true)
191  verifyChangeOfBasisSNF (matrix, maxDim);
192 
193  // compute the g.v.f. together with the projection and the inclusion
194  sout << "Composing an algebraic topological model from the SNF...\n";
195  timeused composingTime;
196  composingTime = 0;
197 
198  // prepare the matrices for psi
199  typedef tLinMap<AlgCellType,AlgCellType,CoefT> AlgMapType;
200  multitable<AlgMapType> psi;
201 
202  // scan through the boundary matrices in the SNF
203  for (int q = 0; q < maxDim; ++ q)
204  {
205  // prepare a counter of homology generator representants
206  int_t genNumber (0);
207 
208  // scan the coefficients in this subsequent matrix
209  int_t nCols = cells [q]. size ();
210  for (int_t cell = 0; cell < nCols; ++ cell)
211  {
212  // determine the row with a nonzero coef if any
213  int_t bcell = matrix. getColCell (q, cell);
214 
215  // if the column is non-zero
216  if (bcell >= 0)
217  {
218  const CoefT e (matrix. getColCoef (q, cell));
219  const int delta (e. delta ());
220  if (delta == 1)
221  {
222  const AlgCellType dom (bcell);
223  const AlgCellType img (cell);
224  if (q)
225  psi [q - 1]. add (dom, img, e);
226  }
227  else
228  {
229  throw "Non-invertible coefficient "
230  "encountered in the SNF.";
231  }
232  continue;
233  }
234 
235  // otherwise, if the cell is a boundary then skip it
236  if ((q < maxDim - 1) &&
237  (matrix. getRowCell (q + 1, cell) >= 0))
238  {
239  continue;
240  }
241 
242  // define a representant of this generator
243  const CellT &repr = cells [q] [genNumber];
244  ++ genNumber;
245  H. push_back (repr);
246 
247  // determine the real homology generator
248  const AlgChainType genChain
249  (matrix. getOldChain (q, cell));
250 
251  // compute the inclusion map on this generator
252  int_t genSize = genChain. size ();
253  for (int_t j = 0; j < genSize; ++ j)
254  {
255  int_t n = genChain. getCell (j). getId ();
256  CoefT e = genChain. getCoef (j);
257  const CellT &genCell = cells [q] [n];
258  incl. add (repr, genCell, e);
259  }
260 
261  // add this generator to the image of all the cells
262  // by the projection, whenever the cells have it
263  // in their images by the change-of-basis matrix
264  const AlgChainType piRow
265  (matrix. getNewChainRow (q, cell));
266  int_t piRowSize = piRow. size ();
267  for (int_t j = 0; j < piRowSize; ++ j)
268  {
269  int_t n = piRow. getCell (j). getId ();
270  CoefT e = piRow. getCoef (j);
271  const CellT &cell = cells [q] [n];
272  pi. add (cell, repr, e);
273  }
274  }
275  }
276 
277  // compute the matrices for phi_q and compose them into one map:
278  // \phi_{q - 1} := A^{-1}_q \circ \psi_{q - 1} \circ A_{q - 1}
279  sout << "Transferring the computed maps to the original basis...\n";
280  for (int q = 1; q < maxDim; ++ q)
281  {
282  // for all the cells of dimension q - 1
283  int_t nCells (cells [q - 1]. size ());
284  for (int_t cell = 0; cell < nCells; ++ cell)
285  {
286  // compute the chain in the new basis
287  AlgChainType ch (matrix. getNewChain (q - 1, cell));
288 
289  // apply psi to this chain
290  AlgChainType psich (psi [q - 1] (ch));
291 
292  // compute the resulting chain in the original basis
293  AlgChainType algImage;
294  int_t size (psich. size ());
295  for (int_t i = 0; i < size; ++ i)
296  {
297  // compute the algebraic chain for this part
298  int_t n (psich. getCell (i). getId ());
299  const CoefT &e (psich. getCoef (i));
300  AlgChainType a (matrix. getOldChain (q, n));
301  a *= e;
302  algImage += a;
303  }
304 
305  // translate the algebraic chain to the real one
306  tChain<CellT,CoefT> image;
307  int_t algSize (algImage. size ());
308  for (int_t i = 0; i < algSize; ++ i)
309  {
310  const CoefT &coef (algImage. getCoef (i));
311  int_t n (algImage. getCell (i). getId ());
312  const CellT &cell (cells [q] [n]);
313  image. add (cell, coef);
314  }
315 
316  // set the image in the map phi
317  phi. getImage (cells [q - 1] [cell]). swap (image);
318  }
319  }
320 
321  // show timing information
322  sout << "AT model composed from the SNF in " << composingTime <<
323  ".\n";
324 
325  // show information on the total computation time of this routine
326  sout << "AT model computed in " << compTime << ".\n";
327 
328  return;
329 } /* algTopModel4 */
330 
331 
332 #endif // _CHAINCON_ATMODEL4R_H_
333 
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 linear map.
Definition: linmap.h:55
void algTopModel4(const CellArray1 &K, CellArray2 &H, tLinMap< CellT, CellT, CoefT > &pi, tLinMap< CellT, CellT, CoefT > &incl, tLinMap< CellT, CellT, CoefT > &phi, const CellRestrT &restr)
Computes an algebraic topological model for the given filtered finite cell complex "K"...
Definition: atmodel4r.h:69
An abstract algebraic cell.
A chain with coefficients in an arbitrary commutative ring.
The decision on whether the empty cell should be used as a valid cell of dimension -1...
void verifyChangeOfBasisSNF(const MatrixT &matrix, int maxDim)
Verifies if the change of basis matrices match each other.
Definition: snf.h:59
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