Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef _CHAINCON_HOMGVF3_H_
00029 #define _CHAINCON_HOMGVF3_H_
00030
00031
00032
00033 #include <istream>
00034 #include <ostream>
00035
00036
00037 #include "chomp/system/config.h"
00038 #include "chomp/system/timeused.h"
00039 #include "chomp/system/textfile.h"
00040 #include "chomp/struct/hashsets.h"
00041 #include "chomp/struct/multitab.h"
00042 #include "chomp/struct/integer.h"
00043 #include "chomp/homology/chains.h"
00044
00045
00046 #include "chaincon/combchain.h"
00047 #include "chaincon/comblinmap.h"
00048
00049
00050
00051
00052
00053
00054
00055 inline bool is_identity (const chomp::homology::mmatrix
00056 <chomp::homology::integer> &M)
00057 {
00058 int nCols = M. getncols ();
00059 for (int col = 0; col < nCols; ++ col)
00060 {
00061 const chomp::homology::chain<chomp::homology::integer>
00062 &column = M. getcol (col);
00063 if (column. size () != 1)
00064 return false;
00065 if (column. num (0) != col)
00066 return false;
00067 }
00068 return true;
00069 }
00070
00071
00072
00073
00074
00075
00076
00077 template <class CellT, class CellArray1, class CellArray2>
00078 void homologyGVF3 (const CellArray1 &K, CellArray2 &H,
00079 tCombLinMap<CellT,CellT> &pi,
00080 tCombLinMap<CellT,CellT> &incl,
00081 tCombLinMap<CellT,CellT> &phi)
00082 {
00083 using chomp::homology::chaincomplex;
00084 using chomp::homology::chain;
00085 using chomp::homology::mmatrix;
00086 using chomp::homology::timeused;
00087 using chomp::homology::sout;
00088
00089 using chomp::homology::integer;
00090 using chomp::homology::hashedset;
00091 using chomp::homology::multitable;
00092
00093
00094 if (K. empty ())
00095 return;
00096
00097
00098 timeused compTime;
00099 compTime = 0;
00100
00101
00102 sout << "Constructing the chain complex of K...\n";
00103 timeused constrTime;
00104 constrTime = 0;
00105
00106
00107 integer::initialize (2);
00108 integer zero;
00109 zero = 0;
00110 integer one;
00111 one = 1;
00112
00113
00114 int_t KSize = K. size ();
00115 int dim = K [KSize - 1]. dim ();
00116 chaincomplex<integer> cx (dim, 1, 1);
00117
00118
00119 multitable<hashedset<CellT> > cells;
00120 for (int_t i = 0; i < KSize; ++ i)
00121 {
00122
00123 const CellT &c = K [i];
00124
00125
00126 int d = c. dim ();
00127
00128
00129 int_t cNum = cells [d]. size ();
00130 cells [d]. add (c);
00131
00132
00133 int_t bLen = c. boundaryLength ();
00134 for (int_t j = 0; j < bLen; ++ j)
00135 {
00136
00137 CellT bCell (c, j);
00138
00139
00140
00141
00142
00143 int_t bNum = cells [d - 1]. getnumber (bCell);
00144
00145
00146 cx. add (d, bNum, cNum, one);
00147 }
00148 }
00149
00150
00151 for (int d = 0; d <= dim; ++ d)
00152 {
00153 cx. def_gen (d, cells [d]. size ());
00154 }
00155
00156
00157 sout << "The chain complex created in " << constrTime << ".\n";
00158
00159
00160 sout << "Computing the SNF of the boundary operator...\n";
00161 timeused snfTime;
00162 snfTime = 0;
00163
00164 int *level = 0;
00165 bool quiet = false;
00166 cx. simple_form (level, quiet);
00167
00168
00169 if (false)
00170 {
00171 sout << "DEBUG CHECK: change of basis (this will take "
00172 "a while)...\n";
00173 for (int q = 0; q <= dim; ++ q)
00174 {
00175 mmatrix<integer> M, N;
00176 M. multiply (cx. gethomgen (q),
00177 cx. getchgbasis (q));
00178 N. multiply (cx. getchgbasis (q),
00179 cx. gethomgen (q));
00180 if (!is_identity (M) || !is_identity (N))
00181 {
00182 sout << "\nDEBUG ERROR: Wrong change of basis "
00183 "detected at level " << q << ".\n";
00184 }
00185 }
00186 sout << "Note: The change of basis matrices were verified "
00187 "successfully.\n";
00188 }
00189
00190
00191 sout << "The SNF computed in " << snfTime << ".\n";
00192
00193
00194 sout << "Composing a homology gradient vector field "
00195 "from the SNF...\n";
00196 timeused gvfTime;
00197 gvfTime = 0;
00198
00199
00200
00201
00202
00203
00204 multitable <mmatrix<integer> > psi;
00205
00206
00207 const mmatrix<integer> zeroMatrix;
00208 for (int q = 0; q <= dim; ++ q)
00209 {
00210
00211
00212 const mmatrix<integer> &Dq = cx. getboundary (q);
00213
00214 const mmatrix<integer> &Dq1 = (q < dim) ?
00215 cx. getboundary (q + 1) : zeroMatrix;
00216
00217 const mmatrix<integer> &Gq = cx. gethomgen (q);
00218
00219 const mmatrix<integer> &Aq = cx. getchgbasis (q);
00220
00221
00222 if (q)
00223 {
00224 psi [q - 1]. define (cells [q]. size (),
00225 cells [q - 1]. size ());
00226 }
00227
00228
00229 int ncells = cells [q]. size ();
00230 for (int i = 0; i < ncells; ++ i)
00231 {
00232
00233 const chain<integer> &column = Dq. getcol (i);
00234
00235
00236 if (!column. empty ())
00237 {
00238 int b = column. num (0);
00239 if (!q)
00240 throw "Negative psi index.";
00241 psi [q - 1]. add (i, b, one);
00242 }
00243
00244
00245 else if ((q == dim) || (Dq1. getrow (i). empty ()))
00246 {
00247
00248
00249
00250
00251
00252 const chain<integer> &genChain =
00253 Gq. getcol (i);
00254
00255
00256 const CellT &repr =
00257 cells [q] [genChain. num (0)];
00258 H. push_back (repr);
00259
00260
00261 int_t genSize = genChain. size ();
00262 for (int_t j = 0; j < genSize; ++ j)
00263 {
00264 int_t n = genChain. num (j);
00265 const CellT &genCell = cells [q] [n];
00266 incl. add (repr, genCell);
00267 }
00268
00269
00270 const chain<integer> &piRow =
00271 Aq. getrow (i);
00272 int_t piRowSize = piRow. size ();
00273 for (int_t j = 0; j < piRowSize; ++ j)
00274 {
00275 int_t num = piRow. num (j);
00276 const CellT &cell = cells [q] [num];
00277 pi. add (cell, repr);
00278 }
00279 }
00280 }
00281 }
00282
00283
00284
00285 sout << "Transferring the computed gvf to the original basis...\n";
00286 for (int q = 1; q <= dim; ++ q)
00287 {
00288
00289 const mmatrix<integer> &M_A = cx. getchgbasis (q - 1);
00290 const mmatrix<integer> &M_psi = psi [q - 1];
00291 const mmatrix<integer> &M_A1 = cx. gethomgen (q);
00292
00293
00294 int_t sizeA = M_A. getncols ();
00295 int_t sizePsi = M_psi. getncols ();
00296 int_t sizeA1 = M_A1. getncols ();
00297
00298
00299 for (int_t i = 0; i < sizeA; ++ i)
00300 {
00301
00302 const chain<integer> &column = M_A. getcol (i);
00303
00304
00305 chain<integer> psiC;
00306 int_t sizeC = column. size ();
00307 for (int_t j = 0; j < sizeC; ++ j)
00308 {
00309 int_t n = column. num (j);
00310 if (n >= sizePsi)
00311 continue;
00312 psiC. add (M_psi. getcol (n), one);
00313 }
00314
00315
00316 chain<integer> phiColumn;
00317 int_t sizePsiC = psiC. size ();
00318 for (int j = 0; j < sizePsiC; ++ j)
00319 {
00320 int_t n = psiC. num (j);
00321 if (n >= sizeA1)
00322 continue;
00323 phiColumn. add (M_A1. getcol (n), one);
00324 }
00325
00326
00327 int_t sizePhiColumn = phiColumn. size ();
00328 for (int j = 0; j < sizePhiColumn; ++ j)
00329 {
00330 int_t n = phiColumn. num (j);
00331 phi. add (cells [q - 1] [i],
00332 cells [q] [n]);
00333 }
00334 }
00335 }
00336
00337
00338 sout << "Homology gvf composed from the SNF in " << gvfTime << ".\n";
00339
00340
00341 sout << "Homology gvf computed in " << compTime << ".\n";
00342
00343 return;
00344 }
00345
00346
00347 #endif // _CHAINCON_HOMGVF3_H_
00348