The ChainCon Software (Release 0.03)
snfchomp.h
Go to the documentation of this file.
1 /////////////////////////////////////////////////////////////////////////////
2 ///
3 /// \file
4 ///
5 /// An interface to the SNF computation using the CHomP software package.
6 /// If you have a more efficient software library that can be used
7 /// to compute the SNF then you are welcome to use this interface
8 /// as a template for another header file in which you prepare
9 /// an interface to use the better algorithm. Please, leave this file intact,
10 /// create another one, and substitute the header file inclusion in "snf.h".
11 ///
12 /////////////////////////////////////////////////////////////////////////////
13 
14 // Copyright (C) 2009-2016 by Pawel Pilarczyk.
15 //
16 // This file is part of my research software package. This is free software:
17 // you can redistribute it and/or modify it under the terms of the GNU
18 // General Public License as published by the Free Software Foundation,
19 // either version 3 of the License, or (at your option) any later version.
20 //
21 // This software is distributed in the hope that it will be useful,
22 // but WITHOUT ANY WARRANTY; without even the implied warranty of
23 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 // GNU General Public License for more details.
25 //
26 // You should have received a copy of the GNU General Public License
27 // along with this software; see the file "license.txt". If not,
28 // please, see <http://www.gnu.org/licenses/>.
29 
30 // Started on March 24, 2009. Last revision: December 28, 2015.
31 
32 
33 #ifndef _CHAINCON_SNFCHOMP_H_
34 #define _CHAINCON_SNFCHOMP_H_
35 
36 
37 // include some standard C++ header files
38 #include <istream>
39 #include <ostream>
40 #include <algorithm>
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 relevant local header files
52 #include "chaincon/chain.h"
53 #include "chaincon/algcell.h"
54 #include "chaincon/euclwrap.h"
55 
56 
57 // --------------------------------------------------
58 // ------------- SNF computation class --------------
59 // --------------------------------------------------
60 
61 /// An interface for the computation of the Smith Normal Form
62 /// of a series of a few rectangular matrices with coefficients
63 /// in a Euclidean Domain. A Euclidean Domain is a commutative ring
64 /// in which division with remainder is well defined; for example,
65 /// the ring of integers, the ring of polynomials in one variable, or some
66 /// field (like the rationals or the integers modulo a prime number p).
67 /// In fact, what is to be computed, are the changes of bases in the complex
68 /// such that each matrix in the series is in the SNF.
69 /// The columns and rows of each matrix in the set
70 /// are indexed by integer numbers starting at 0.
71 /// In addition to the SNF, the change-of-basis matrices A and G
72 /// are also computed, such that A is a change of basis from the original one
73 /// to the new one, and G is a change of basis from the new basis
74 /// back to the original one. In other words, if {M_q} is the original
75 /// series of matrices and {S_q} is a series of its SNF
76 /// then M_q = G_{q-1} S_q A_q, and G_q A_q = A_q G_q = identity.
77 /// Please, note that it is not possible to make all the boundary matrices
78 /// in the SNF with the non-zero entries starting at the 'diagonal',
79 /// because the boundary of a boundary must be zero.
80 /// Therefore, what is computed here, is a 'simple form' of the boundary matrices
81 /// in which every column and every row has at most one nonzero entry.
82 /// Please, note that the division condition required in the SNF is not satisfied
83 /// either. As a consequence, the collection of coefficients that define
84 /// a homology group may not be the same for isomorphic groups.
85 template <class CoefT>
87 {
88 public:
89  /// The type of coefficients in the chain.
90  typedef CoefT CoefType;
91 
92  /// The type of an abstract algebraic cell that is used
93  /// to carry the numbers of columns or rows in the matrix.
94  /// Please note that only the identifier of this cell is used,
95  /// not its dimension, nor its boundary.
97 
98  /// The type of the corresponding image chain.
100 
101  /// The default constructor of a matrix.
102  tMatrixSNF ();
103 
104  /// The destructor of a matrix.
105  ~tMatrixSNF ();
106 
107  /// Sets the number of rows and columns in a given sub-matrix.
108  void setSize (int q, int_t numRows, int_t numColumns);
109 
110  /// Adds an element to the matrix whose SNF will be computed.
111  void add (int q, int_t row, int_t column, const CoefT &element);
112 
113  /// Returns the number of rows of the matrix.
114  int_t getNumRows (int q) const;
115 
116  /// Returns the number of columns of the matrix.
117  int_t getNumCols (int q) const;
118 
119  /// Computes the almost Smith Normal Form of all the matrices
120  /// whose number is provided (indexing stats from 0 and ends at
121  /// the given mumber minus 1).
122  /// After all the matrices have been defined,
123  /// this procedure must be called once to compute the SNF
124  /// and all the auxiliary data,
125  /// including the change of basis matrices A and G.
126  /// Then the results of the computations can be read
127  /// with the other methods available in this class.
128  void computeSNF (int numMatr);
129 
130  /// Returns the coefficient in the given column of the given matrix
131  /// in the SNF.
132  CoefT getColCoef (int q, int_t n) const;
133 
134  /// Returns the cell number in the given column of the given matrix
135  /// in the SNF, or -1 if the column is zero.
136  int_t getColCell (int q, int_t n) const;
137 
138  /// Returns the coefficient in the given row of the given matrix
139  /// in the SNF.
140  CoefT getRowCoef (int q, int_t n) const;
141 
142  /// Returns the cell number in the given row of the given matrix
143  /// in the SNF, or -1 if the row is zero.
144  int_t getRowCell (int q, int_t n) const;
145 
146  /// For a cell in the original basis, returns the
147  /// corresponding combination of elements in the new basis
148  /// (the column of the change-of-basis matrix in this direction).
149  ChainType getNewChain (int q, int_t n) const;
150 
151  /// For a cell in the original basis, returns the given row
152  /// of the change-of-basis matrix towards the new basis.
153  ChainType getNewChainRow (int q, int_t n) const;
154 
155  /// For a cell in the new basis, returns a combination
156  /// of the original cells that correspond to this cell
157  /// (the column of the change-of-basis matrix in this direction).
158  ChainType getOldChain (int q, int_t n) const;
159 
160  /// For a cell in the new basis, returns the given row
161  /// of the change-of-basis matrix towards the original basis.
162  ChainType getOldChainRow (int q, int_t n) const;
163 
164 private:
165  /// Copy constructor is not allowed.
166  tMatrixSNF (const tMatrixSNF<CoefT> &other);
167 
168  /// Assignment operator is not allowed.
170 
171  /// The matrices whose Smith Normal Form will be computed.
172  chomp::homology::multitable
173  <chomp::homology::mmatrix<tEuclWrap<CoefT> > > matrices;
174 
175  /// Change of basis matrices from the original one to the SNF one.
176  chomp::homology::multitable
177  <chomp::homology::mmatrix<tEuclWrap<CoefT> > > chgBasisA;
178 
179  /// Change of basis matrices from the SNF one to the original one.
180  chomp::homology::multitable
181  <chomp::homology::mmatrix<tEuclWrap<CoefT> > > chgBasisG;
182 
183  /// Coverts a column of a matrix to an abstract algebraic chain.
184  static ChainType abstractChain
185  (const chomp::homology::chain<tEuclWrap<CoefT> > &ch);
186 
187  /// Remembers if the SNF has already been computed.
189 
190 }; /* class tMatrixSNF */
191 
192 // --------------------------------------------------
193 
194 template <class CoefT>
196 {
197  return;
198 } /* tMatrixSNF::tMatrixSNF */
199 
200 template <class CoefT>
202 {
203  return;
204 } /* tMatrixSNF::~tMatrixSNF */
205 
206 template <class CoefT>
208 {
209  throw "Trying to use the undefined copy constructor for tMatrixSNF.";
210  return;
211 } /* tMatrixSNF::tMatrixSNF */
212 
213 template <class CoefT>
215  (const tMatrixSNF<CoefT> &other)
216 {
217  throw "Trying to use the undefined operator = for tMatrixSNF.";
218  return *this;
219 } /* tMatrixSNF::operator = */
220 
221 // --------------------------------------------------
222 
223 template <class CoefT>
224 inline void tMatrixSNF<CoefT>::setSize (int q,
225  int_t numRows, int_t numColumns)
226 {
227  // define the size of the matrix
228  matrices [q]. define (numRows, numColumns);
229 
230  return;
231 } /* tMatrixSNF::setSize */
232 
233 template <class CoefT>
234 inline void tMatrixSNF<CoefT>::add (int q, int_t row, int_t column,
235  const CoefT &element)
236 {
237  matrices [q]. add (row, column, tEuclWrap<CoefT> (element));
238  return;
239 } /* tMatrixSNF::add */
240 
241 template <class CoefT>
242 inline int_t tMatrixSNF<CoefT>::getNumRows (int q) const
243 {
244  return matrices [q]. getnrows ();
245 } /* tMatrixSNF::getNumRows */
246 
247 template <class CoefT>
248 inline int_t tMatrixSNF<CoefT>::getNumCols (int q) const
249 {
250  return matrices [q]. getncols ();
251 } /* tMatrixSNF::getNumCols */
252 
253 template <class CoefT>
254 inline void tMatrixSNF<CoefT>::computeSNF (int numMatr)
255 {
256  using chomp::homology::sout;
257  using chomp::homology::sbug;
258 
259  if (computedSNF)
260  throw "Trying to compute the SNF twice.\n";
261 
262  for (int q = 0; q < numMatr; ++ q)
263  {
264  // determine the size of the matrix
265  // int_t nRows = matrices [q]. getnrows ();
266  int_t nCols = matrices [q]. getncols ();
267 
268  // create the identity matrices for tracing changes of bases
269  chgBasisA [q]. identity (nCols);
270  chgBasisG [q]. identity (nCols);
271 
272  // connect the change of basis matrices to the main matrix
273  matrices [q]. dom_img. add (chgBasisA [q]);
274  matrices [q]. dom_dom. add (chgBasisG [q]);
275  if (q > 0)
276  {
277  matrices [q]. img_img. add (chgBasisA [q - 1]);
278  matrices [q]. img_dom. add (chgBasisG [q - 1]);
279  }
280 
281  // connect the matrices between each other
282  if (q < numMatr - 1)
283  matrices [q]. dom_img. add (matrices [q + 1]);
284  if (q > 0)
285  matrices [q]. img_dom. add (matrices [q - 1]);
286  }
287 
288 // for (int q = 0; q < numMatr; ++ q)
289  for (int q = numMatr - 1; q >= 0; -- q)
290  {
291  if (matrices [q]. getnrows () == 0)
292  continue;
293  if (matrices [q]. getncols () == 0)
294  continue;
295  // sout << "DEBUG: Original matrix:\n" << matrices [q];
296  sout << "SNF " << q << ": ";
297  matrices [q]. simple_form ();
298  sout << "\n";
299  // matrices [q]. simple_form_to_SNF ();
300  // sbug << "DEBUG: nearly SNF:\n" << matrices [q];
301  // sbug << "DEBUG: chgBasisA:\n" << chgBasisA [q];
302  // sbug << "DEBUG: chgBasisG:\n" << chgBasisG [q];
303  }
304 
305  // remember that the SNF has been computed
306  computedSNF = true;
307 
308  return;
309 } /* tMatrixSNF::computeSNF */
310 
311 template <class CoefT>
312 inline CoefT tMatrixSNF<CoefT>::getColCoef (int q, int_t n) const
313 {
314  const chomp::homology::chain<tEuclWrap<CoefT> > &column =
315  matrices [q]. getcol (n);
316  if (column. size () < 1)
317  return CoefT (0);
318  else
319  return tEuclWrap<CoefT> (column. coef (0)). getCoef ();
320 } /* tMatrixSNF::getColCoef */
321 
322 template <class CoefT>
323 inline int_t tMatrixSNF<CoefT>::getColCell (int q, int_t n) const
324 {
325  const chomp::homology::chain<tEuclWrap<CoefT> > &column =
326  matrices [q]. getcol (n);
327  if (column. size () < 1)
328  return -1;
329  else
330  return column. num (0);
331 } /* tMatrixSNF::getColCell */
332 
333 template <class CoefT>
334 inline CoefT tMatrixSNF<CoefT>::getRowCoef (int q, int_t n) const
335 {
336  const chomp::homology::chain<tEuclWrap<CoefT> > &row =
337  matrices [q]. getrow (n);
338  if (row. size () < 1)
339  return CoefT (0);
340  else
341  return tEuclWrap<CoefT> (row. coef (0)). getCoef ();
342 } /* tMatrixSNF::getRowCoef */
343 
344 template <class CoefT>
345 inline int_t tMatrixSNF<CoefT>::getRowCell (int q, int_t n) const
346 {
347  const chomp::homology::chain<tEuclWrap<CoefT> > &row =
348  matrices [q]. getrow (n);
349  if (row. size () < 1)
350  return -1;
351  else
352  return row. num (0);
353 } /* tMatrixSNF::getRowCell */
354 
355 template <class CoefT>
357  (const chomp::homology::chain<tEuclWrap<CoefT> > &ch)
358 {
359  ChainType chResult;
360  int_t size = ch. size ();
361  for (int_t i = 0; i < size; ++ i)
362  {
363  chResult. add (CellType (ch. num (i)),
364  tEuclWrap<CoefT> (ch. coef (i)). getCoef ());
365  }
366  return chResult;
367 } /* tMatrixSNF::abstractChain */
368 
369 template <class CoefT>
370 inline typename tMatrixSNF<CoefT>::ChainType
371  tMatrixSNF<CoefT>::getNewChain (int q, int_t n) const
372 {
373  return abstractChain (chgBasisA [q]. getcol (n));
374 } /* tMatrixSNF::getNewChain */
375 
376 template <class CoefT>
377 inline typename tMatrixSNF<CoefT>::ChainType
378  tMatrixSNF<CoefT>::getNewChainRow (int q, int_t n) const
379 {
380  return abstractChain (chgBasisA [q]. getrow (n));
381 } /* tMatrixSNF::getNewChainRow */
382 
383 template <class CoefT>
384 inline typename tMatrixSNF<CoefT>::ChainType
385  tMatrixSNF<CoefT>::getOldChain (int q, int_t n) const
386 {
387  return abstractChain (chgBasisG [q]. getcol (n));
388 } /* tMatrixSNF::getOldChain */
389 
390 template <class CoefT>
391 inline typename tMatrixSNF<CoefT>::ChainType
392  tMatrixSNF<CoefT>::getOldChainRow (int q, int_t n) const
393 {
394  return abstractChain (chgBasisG [q]. getrow (n));
395 } /* tMatrixSNF::getOldChainRow */
396 
397 
398 #endif // _CHAINCON_SNFCHOMP_H_
399 
CoefT getColCoef(int q, int_t n) const
Returns the coefficient in the given column of the given matrix in the SNF.
Definition: snfchomp.h:312
int_t getNumCols(int q) const
Returns the number of columns of the matrix.
Definition: snfchomp.h:248
tAlgCell< int_t, unsigned char, CoefT > CellType
The type of an abstract algebraic cell that is used to carry the numbers of columns or rows in the ma...
Definition: snfchomp.h:96
~tMatrixSNF()
The destructor of a matrix.
Definition: snfchomp.h:201
int_t getRowCell(int q, int_t n) const
Returns the cell number in the given row of the given matrix in the SNF, or -1 if the row is zero...
Definition: snfchomp.h:345
A wrapper of coefficients as defined in this sofware package for what is required by CHomP...
Definition: euclwrap.h:49
chomp::homology::multitable< chomp::homology::mmatrix< tEuclWrap< CoefT > > > chgBasisA
Change of basis matrices from the original one to the SNF one.
Definition: snfchomp.h:177
tChain< CellType, CoefT > ChainType
The type of the corresponding image chain.
Definition: snfchomp.h:99
ChainType getOldChainRow(int q, int_t n) const
For a cell in the new basis, returns the given row of the change-of-basis matrix towards the original...
Definition: snfchomp.h:392
A chain with coefficients in an arbitrary ring.
Definition: chain.h:50
void computeSNF(int numMatr)
Computes the almost Smith Normal Form of all the matrices whose number is provided (indexing stats fr...
Definition: snfchomp.h:254
tMatrixSNF< CoefT > & operator=(const tMatrixSNF< CoefT > &other)
Assignment operator is not allowed.
Definition: snfchomp.h:215
ChainType getNewChain(int q, int_t n) const
For a cell in the original basis, returns the corresponding combination of elements in the new basis ...
Definition: snfchomp.h:371
chomp::homology::multitable< chomp::homology::mmatrix< tEuclWrap< CoefT > > > chgBasisG
Change of basis matrices from the SNF one to the original one.
Definition: snfchomp.h:181
int_t getColCell(int q, int_t n) const
Returns the cell number in the given column of the given matrix in the SNF, or -1 if the column is ze...
Definition: snfchomp.h:323
int_t getNumRows(int q) const
Returns the number of rows of the matrix.
Definition: snfchomp.h:242
CoefT CoefType
The type of coefficients in the chain.
Definition: snfchomp.h:90
ChainType getOldChain(int q, int_t n) const
For a cell in the new basis, returns a combination of the original cells that correspond to this cell...
Definition: snfchomp.h:385
An abstract algebraic cell.
A chain with coefficients in an arbitrary commutative ring.
void add(int q, int_t row, int_t column, const CoefT &element)
Adds an element to the matrix whose SNF will be computed.
Definition: snfchomp.h:234
An abstract algebraic cell, characterized by a unique identifier, dimension, and a formula for its bo...
Definition: algcell.h:54
bool computedSNF
Remembers if the SNF has already been computed.
Definition: snfchomp.h:188
void setSize(int q, int_t numRows, int_t numColumns)
Sets the number of rows and columns in a given sub-matrix.
Definition: snfchomp.h:224
chomp::homology::multitable< chomp::homology::mmatrix< tEuclWrap< CoefT > > > matrices
The matrices whose Smith Normal Form will be computed.
Definition: snfchomp.h:173
CoefT getRowCoef(int q, int_t n) const
Returns the coefficient in the given row of the given matrix in the SNF.
Definition: snfchomp.h:334
An interface for the computation of the Smith Normal Form of a series of a few rectangular matrices w...
Definition: snfchomp.h:86
static ChainType abstractChain(const chomp::homology::chain< tEuclWrap< CoefT > > &ch)
Coverts a column of a matrix to an abstract algebraic chain.
Definition: snfchomp.h:357
tCombLinMap< CellT, CellT > identity(const CellArray &domain)
Returns the identity map on the given domain.
Definition: comblinmap.h:430
A wrapper of a generic coefficient type for the CHomP library.
ChainType getNewChainRow(int q, int_t n) const
For a cell in the original basis, returns the given row of the change-of-basis matrix towards the new...
Definition: snfchomp.h:378
tMatrixSNF()
The default constructor of a matrix.
Definition: snfchomp.h:195