From e7903fa391ec100c7512a549f3bf9f15a2ff65b0 Mon Sep 17 00:00:00 2001 From: Matti Pellika <matti.pellikka@tut.fi> Date: Fri, 3 Apr 2009 11:06:13 +0000 Subject: [PATCH] Forming ChainComplex class. Coreduction update. Added copy_gmp_matrix method to kbipack. --- Geo/CellComplex.cpp | 267 ++++++++++++++++++++--------------- Geo/CellComplex.h | 61 +++++++- contrib/kbipack/gmp_matrix.c | 85 ++++++++++- contrib/kbipack/gmp_matrix.h | 11 +- 4 files changed, 301 insertions(+), 123 deletions(-) diff --git a/Geo/CellComplex.cpp b/Geo/CellComplex.cpp index 2980645832..ce80a05b9b 100644 --- a/Geo/CellComplex.cpp +++ b/Geo/CellComplex.cpp @@ -290,7 +290,7 @@ int CellComplex::coreduction(int dim){ removeCell(cell); removeCell(bd_c.at(0)); count++; - coreduced =true; + coreduced = true; } } @@ -317,7 +317,7 @@ int CellComplex::reduction(int dim){ removeCell(cell); removeCell(cbd_c.at(0)); count++; - reduced =true; + reduced = true; } } @@ -335,130 +335,86 @@ void CellComplex::reduceComplex(){ getSize(3), getSize(2), getSize(1), getSize(0)); } void CellComplex::coreduceComplex(){ - printf("Cell complex before coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", - getSize(3), getSize(2), getSize(1), getSize(0)); - while (getSize(0) != 0){ - citer cit = firstCell(0); - Cell* cell = *cit; - removeCell(cell); - //complex.coreductionMrozek(kaka); - coreduction(0); - coreduction(1); - coreduction(2); - - } - printf("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", - getSize(3), getSize(2), getSize(1), getSize(0)); -} -/* -void CellComplex::constructHMatrix(int dim){ + std::set<Cell*, Less_Cell> removedCells[4]; - // h_dim: C_dim -> C_(dim-1) - - - if(dim > 3 || dim < 1){ - return; - } - - destroy_gmp_matrix(_HMatrix[dim]); - - if( _cells[dim].size() == 0 ){ - _HMatrix[dim] = create_gmp_matrix_zero(1, 1); - //gmp_matrix_printf(_HMatrix[dim]); - return; - } - unsigned int cols = _cells[dim].size(); - - if( _cells[dim-1].size() == 0){ - _HMatrix[dim] = create_gmp_matrix_zero(1, cols); - //gmp_matrix_printf(_HMatrix[dim]); - return; - } - unsigned int rows = _cells[dim-1].size(); - - mpz_t elems[rows*cols]; - mpz_array_init( elems[0], rows*cols, sizeof(mpz_t) ); - - citer high = firstCell(dim); - citer low = firstCell(dim-1); - - /* - printf("laa %d %d %d \n", rows, cols, rows*cols); - for(unsigned int i=0; i < rows*cols; i++){ - printf(" %d, ", i); - if(low == lastCell(dim-1)){ - printf("rowfull %d ", i); - high++; - low = firstCell(dim-1); + printf("Cell complex before coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", + getSize(3), getSize(2), getSize(1), getSize(0)); + for(int i = 0; i < 3; i++){ + while (getSize(i) != 0){ + citer cit = firstCell(i); + Cell* cell = *cit; + removedCells[i].insert(cell); + _cells[i].erase(cell); + //removeCell(cell); + //complex.coreductionMrozek(kaka); + coreduction(0); + coreduction(1); + coreduction(2); } - mpz_set_ui(elems[i], kappa(*high, *low)); - low++; + } - */ - /* - unsigned int i = 0; - while(i < rows*cols){ - while(low != lastCell(dim-1)){ - mpz_set_si(elems[i], kappa(*high, *low)); - //printf(" %d %d, ",i, kappa(*high, *low)); - i++; - low++; + for(int i = 0; i < 3; i++){ + for(citer cit = removedCells[i].begin(); cit != removedCells[i].end(); cit++){ + Cell* cell = *cit; + _cells[i].insert(cell); } - low = firstCell(dim-1); - high++; } - - _HMatrix[dim] = create_gmp_matrix(rows, cols,(const mpz_t *) elems); - - //gmp_matrix_printf(_HMatrix[dim]); - - return; + printf("Cell complex after coreduction: %d volumes, %d faces, %d edges and %d vertices.\n", + getSize(3), getSize(2), getSize(1), getSize(0)); } -*/ + std::vector<gmp_matrix*> CellComplex::constructHMatrices(){ // h_dim: C_dim -> C_(dim-1) std::vector<gmp_matrix*> HMatrix; - - HMatrix.push_back(create_gmp_matrix_zero(1, 1)); - + + HMatrix.push_back(NULL); + for(int dim = 1; dim < 4; dim++){ - if( _cells[dim].size() == 0 ){ - HMatrix.push_back( create_gmp_matrix_zero(1, 1)); - //gmp_matrix_printf(HMatrix[dim]); - break; - } - unsigned int cols = _cells[dim].size(); + unsigned int cols = _cells[dim].size(); + unsigned int rows = _cells[dim-1].size(); - if( _cells[dim-1].size() == 0){ - HMatrix.push_back(create_gmp_matrix_zero(1, cols)); - //gmp_matrix_printf(HMatrix[dim]); - break; + for(citer cit = firstCell(dim); cit != lastCell(dim); cit++){ + Cell* cell = *cit; + if(cell->inSubdomain()) cols--; + } + for(citer cit = firstCell(dim-1); cit != lastCell(dim-1); cit++){ + Cell* cell = *cit; + if(cell->inSubdomain()) rows--; } - unsigned int rows = _cells[dim-1].size(); - mpz_t elems[rows*cols]; - mpz_array_init( elems[0], rows*cols, sizeof(mpz_t) ); - citer high = firstCell(dim); - citer low = firstCell(dim-1); - - unsigned int i = 0; - while(i < rows*cols){ - while(low != lastCell(dim-1)){ - mpz_set_si(elems[i], kappa(*high, *low)); - //printf(" %d %d, ",i, kappa(*high, *low)); - i++; - low++; + if( cols == 0 ){ + HMatrix.push_back(NULL); + } + else if( rows == 0){ + HMatrix.push_back(create_gmp_matrix_zero(1, cols)); + } + else{ + long int elems[rows*cols]; + + citer high = firstCell(dim); + citer low = firstCell(dim-1); + + unsigned int i = 0; + while(i < rows*cols){ + while(low != lastCell(dim-1)){ + Cell* lowcell = *low; + Cell* highcell = *high; + if(!(highcell->inSubdomain() || lowcell->inSubdomain())){ + elems[i] = kappa(*high, *low); + i++; + } + low++; + } + low = firstCell(dim-1); + high++; } - low = firstCell(dim-1); - high++; + HMatrix.push_back(create_gmp_matrix_int(rows, cols, elems)); + } - HMatrix.push_back(create_gmp_matrix(rows, cols,(const mpz_t *) elems)); - - //gmp_matrix_printf(_HMatrix[dim]); } return HMatrix; } @@ -575,29 +531,112 @@ int CellComplex::writeComplexMSH(const std::string &name){ } -void CellComplex::printComplex(int dim){ +void CellComplex::printComplex(int dim, bool subcomplex){ for (citer cit = firstCell(dim); cit != lastCell(dim); cit++){ Cell* cell = *cit; for(int i = 0; i < cell->getNumVertices(); i++){ - printf("%d ", cell->getVertex(i)); + if(!subcomplex && !cell->inSubdomain()) printf("%d ", cell->getVertex(i)); } printf("\n"); } } -gmp_matrix* ChainComplex::ker(gmp_matrix* HMatrix){ +void ChainComplex::KerCod(int dim){ + + if(dim < 1 || dim > 3 || _HMatrix[dim] == NULL) return; + + gmp_matrix* HMatrix = copy_gmp_matrix(_HMatrix[dim], 1, 1, + gmp_matrix_rows(_HMatrix[dim]), gmp_matrix_cols(_HMatrix[dim])); + + gmp_normal_form* normalForm = create_gmp_Hermite_normal_form(HMatrix, NOT_INVERTED, INVERTED); + //printMatrix(normalForm->left); + //printMatrix(normalForm->canonical); + //printMatrix(normalForm->right); + + int minRowCol = std::min(gmp_matrix_rows(normalForm->canonical), gmp_matrix_cols(normalForm->canonical)); + int rank = 0; + mpz_t elem; + mpz_init(elem); + + while(rank < minRowCol){ + gmp_matrix_get_elem(elem, rank+1, rank+1, normalForm->canonical); + if(mpz_cmp_si(elem,0) == 0) break; + rank++; + } - // H = USV -> WH = US, W = inv(V) - gmp_normal_form* W_USform = create_gmp_Smith_normal_form(HMatrix, NOT_INVERTED, INVERTED); - + if(rank != gmp_matrix_cols(normalForm->canonical)){ + _kerH[dim] = copy_gmp_matrix(normalForm->right, 1, rank+1, + gmp_matrix_rows(normalForm->right), gmp_matrix_cols(normalForm->right)); + } + if(rank > 0){ + _codH[dim] = copy_gmp_matrix(normalForm->canonical, 1, 1, + gmp_matrix_rows(normalForm->canonical), rank); + gmp_matrix_left_mult(normalForm->left, _codH[dim]); + } - return W_USform->canonical; + mpz_clear(elem); + destroy_gmp_normal_form(normalForm); + return; } +/* +//j:B->Z +void ChainComplex::Inclusion(int dim){ + + if(dim < 1 || dim > 3 || _kerH[dim] == NULL || _codH[dim] == NULL) return; + + int rows = gmp_matrix_rows(Zbasis); + int cols = gmp_matrix_cols(Zbasis); + if(rows < cols) return; + + rows = gmp_matrix_rows(Bbasis); + cols = gmp_matrix_cols(Bbasis); + if(rows < cols) return; + + gmp_matrix* Zbasis = copy_gmp_matrix(_ker[dim], 1, 1, + gmp_matrix_rows(_kerH[dim]), gmp_matrix_cols(_kerH[dim])); + gmp_matrix* Bbasis = copy_gmp_matrix(_cod[dim], 1, 1, + gmp_matrix_rows(_codH[dim]), gmp_matrix_cols(_codH[dim])); + + // A*inv(V) = U*S + normalForm = create_gmp_Smith_normal_form(Zbasis, NOT_INVERTED, INVERTED); + + mpz_t elem; + mpz_init(elem); + + for(int i = 1; i < cols; i++){ + gmp_matrix_get_elem(elem, i, i, normalForm->canonical); + if(mpz_cmp_si(elem,0) == 0){ + destroy_gmp_normal_form(normalForm); + return; + } + } + + gmp_matrix_left_mult(normalForm->left, Bbasis); + +} +*/ +void ChainComplex::matrixTest(){ + + int rows = 3; + int cols = 6; + + long int elems[rows*cols]; + for(int i = 1; i<=rows*cols; i++) elems[i-1] = i; + + gmp_matrix* matrix = create_gmp_matrix_int(rows, cols, elems); + + gmp_matrix* copymatrix = copy_gmp_matrix(matrix, 3, 2, 3, 5); + + printMatrix(matrix); + printMatrix(copymatrix); + + return; +} #endif diff --git a/Geo/CellComplex.h b/Geo/CellComplex.h index b7f4dcc619..5f73d241d7 100644 --- a/Geo/CellComplex.h +++ b/Geo/CellComplex.h @@ -44,7 +44,7 @@ class Cell int _cbdSize; // whether this cell belongs to a subdomain - // used to in relative homology computation + // used in relative homology computation bool _inSubdomain; public: @@ -294,9 +294,19 @@ class ThreeSimplex : public Simplex class Less_Cell{ public: bool operator()(const Cell* c1, const Cell* c2) const { + + // subcomplex cells in the end + //if(c1->inSubdomain() != c2->inSubdomain()){ + // if(c1->inSubdomain()) return false; + // else return true; + //} + + // cells with fever vertices first if(c1->getNumVertices() != c2->getNumVertices()){ return (c1->getNumVertices() < c2->getNumVertices()); } + + // "natural number" -like ordering (the number of a vertice corresponds a digit) for(int i=0; i < c1->getNumVertices();i++){ if(c1->getVertex(i) < c2->getVertex(i)) return true; else if (c1->getVertex(i) > c2->getVertex(i)) return false; @@ -327,7 +337,7 @@ class CellComplex // sorted containers of unique cells in this cell complex // one for each dimension std::set<Cell*, Less_Cell> _cells[4]; - + // boundary operator matrices for this chain complex // h_k: C_k -> C_(k-1) //gmp_matrix* _HMatrix[4]; @@ -356,7 +366,7 @@ class CellComplex public: CellComplex( std::set<Cell*, Less_Cell>* cells ) { for(int i = 0; i < 4; i++){ - _cells[i] = cells[i]; + //_cells[i] = cells[i]; } } CellComplex( std::vector<GEntity*> domain, std::vector<GEntity*> subdomain ); @@ -409,7 +419,7 @@ class CellComplex virtual int coreductionMrozek(Cell* generator); // print the vertices of cells of certain dimension - virtual void printComplex(int dim); + virtual void printComplex(int dim, bool subcomplex); // write this cell complex in legacy .msh format virtual int writeComplexMSH(const std::string &name); @@ -419,39 +429,76 @@ class CellComplex // get the boundary operator matrix dim->dim-1 //virtual gmp_matrix* getHMatrix(int dim) { return _HMatrix[dim]; } + // construct boundary operator matrices of this cell complex + // used to construct a chain complex virtual std::vector<gmp_matrix*> constructHMatrices(); }; +// A class representing a chain complex of a cell complex. +// This should only be constructed for a reduced cell complex because of +// dense matrix reprentations and great computational complexity in its methods. class ChainComplex{ private: // boundary operator matrices for this chain complex // h_k: C_k -> C_(k-1) gmp_matrix* _HMatrix[4]; + // Basis matrices for the kernels and codomains of the boundary operator matrices + gmp_matrix* _kerH[4]; + gmp_matrix* _codH[4]; + + gmp_matrix* _JMatrix[4]; + gmp_matrix* _QMatrix[4]; + std::vector<int> _torsion[4]; + public: ChainComplex( std::vector<gmp_matrix*> HMatrix ){ for(int i = 0; i < HMatrix.size(); i++){ _HMatrix[i] = HMatrix.at(i); - } + } + for(int i = 0; i < 4; i++){ + _kerH[i] = NULL; + _codH[i] = NULL; + _JMatrix[i] = NULL; + _QMatrix[i] = NULL; + } + } ChainComplex(){ for(int i = 0; i < 4; i++){ _HMatrix[i] = create_gmp_matrix_zero(1,1); + _kerH[i] = NULL; + _codH[i] = NULL; + _JMatrix[i] = NULL; + _QMatrix[i] = NULL; } } virtual ~ChainComplex(){} // get the boundary operator matrix dim->dim-1 virtual gmp_matrix* getHMatrix(int dim) { return _HMatrix[dim]; } - - virtual gmp_matrix* ker(gmp_matrix* HMatrix); + virtual gmp_matrix* getKerHMatrix(int dim) { return _kerH[dim]; } + virtual gmp_matrix* getCodHMatrix(int dim) { return _codH[dim]; } + virtual gmp_matrix* getJMatrix(int dim) { return _JMatrix[dim]; } + virtual gmp_matrix* getQMatrix(int dim) { return _QMatrix[dim]; } + + // Compute basis for kernel and codomain of boundary operator matrix of dimension dim (ie. ker(h_dim) and cod(h_dim) ) + virtual void KerCod(int dim); + // Compute matrix representation J for inclusion relation from dim-cells who are boundary of dim+1-cells + // to cycles of dim-cells (ie. j: cod(h_(dim+1)) -> ker(h_dim) ) + virtual void Inclusion(int dim){} + // Compute quotient problem for given inclusion relation j to find representatives of homology groups + // and possible torsion coeffcients + virtual void Quotient(int dim){} virtual int printMatrix(gmp_matrix* matrix){ printf("%d rows and %d columns\n", gmp_matrix_rows(matrix), gmp_matrix_cols(matrix)); return gmp_matrix_printf(matrix); } + // debugging aid + virtual void matrixTest(); }; diff --git a/contrib/kbipack/gmp_matrix.c b/contrib/kbipack/gmp_matrix.c index 23d648c89e..2d07724b08 100755 --- a/contrib/kbipack/gmp_matrix.c +++ b/contrib/kbipack/gmp_matrix.c @@ -22,7 +22,7 @@ P.O.Box 692, FIN-33101 Tampere, Finland saku.suuriniemi@tut.fi - $Id: gmp_matrix.c,v 1.1 2009-03-30 14:10:57 matti Exp $ + $Id: gmp_matrix.c,v 1.2 2009-04-03 11:06:12 matti Exp $ */ @@ -61,6 +61,38 @@ create_gmp_matrix(size_t r, size_t c, return new_matrix; } +gmp_matrix * +create_gmp_matrix_int(size_t r, size_t c, + const long int * e) +{ + gmp_matrix * new_matrix; + size_t ind; + + new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); + if(new_matrix == NULL) + { + return NULL; + } + + new_matrix -> storage = (mpz_t *) calloc(r*c, sizeof(mpz_t)); + if(new_matrix -> storage == NULL) + { + free(new_matrix); + return NULL; + } + + new_matrix -> rows = r; + new_matrix -> cols = c; + + for(ind = 0; ind < r*c; ind ++) + { + mpz_init (new_matrix -> storage[ind]); + mpz_set_si (new_matrix -> storage[ind], e[ind]); + } + + return new_matrix; +} + gmp_matrix * create_gmp_matrix_identity(size_t dim) @@ -128,6 +160,57 @@ create_gmp_matrix_zero(size_t rows, size_t cols) return new_matrix; } +gmp_matrix * +copy_gmp_matrix(const gmp_matrix * matrix, + const size_t start_row, const size_t start_col, + const size_t end_row, const size_t end_col) +{ + gmp_matrix * new_matrix; + size_t ind; + size_t r; + size_t c; + size_t old_rows; + size_t old_cols; + size_t i; + size_t j; + + new_matrix = (gmp_matrix * ) malloc(sizeof(gmp_matrix)); + if(new_matrix == NULL) + { + return NULL; + } + + r = end_row-start_row+1; + c = end_col-start_col+1; + new_matrix -> storage = (mpz_t *) calloc(r*c, sizeof(mpz_t)); + if(new_matrix -> storage == NULL) + { + free(new_matrix); + return NULL; + } + + new_matrix -> rows = r; + new_matrix -> cols = c; + + old_rows = matrix -> rows; + old_cols = matrix -> cols; + + ind = 0; + for(j = 1; j <= old_cols; j++){ + if(j >= start_col && j <= end_col){ + for(i = 1; i <= old_rows; i++){ + if(i >= start_row && i <= end_row){ + mpz_init (new_matrix -> storage[ind]); + mpz_set (new_matrix -> storage[ind], matrix -> storage[(j-1)*old_rows+(i-1)]); + ind++; + } + } + } + } + + return new_matrix; +} + int destroy_gmp_matrix(gmp_matrix * m) { diff --git a/contrib/kbipack/gmp_matrix.h b/contrib/kbipack/gmp_matrix.h index 6e32583db3..784a87c206 100755 --- a/contrib/kbipack/gmp_matrix.h +++ b/contrib/kbipack/gmp_matrix.h @@ -22,7 +22,7 @@ P.O.Box 692, FIN-33101 Tampere, Finland saku.suuriniemi@tut.fi - $Id: gmp_matrix.h,v 1.1 2009-03-30 14:10:57 matti Exp $ + $Id: gmp_matrix.h,v 1.2 2009-04-03 11:06:13 matti Exp $ */ #ifndef __GMP_MATRIX_H__ @@ -42,6 +42,9 @@ typedef struct gmp_matrix * create_gmp_matrix(size_t rows, size_t cols, const mpz_t * elems); +gmp_matrix * +create_gmp_matrix_int(size_t rows, size_t cols, + const long int * elems); gmp_matrix * create_gmp_matrix_identity(size_t dim); @@ -49,6 +52,12 @@ create_gmp_matrix_identity(size_t dim); gmp_matrix * create_gmp_matrix_zero(size_t rows, size_t cols); +/* Copies a block of a matrix to another matrix. No resizing (yet). */ +gmp_matrix * +copy_gmp_matrix(const gmp_matrix * matrix, + const size_t start_row, const size_t start_col, + const size_t end_row, const size_t end_col); + int destroy_gmp_matrix(gmp_matrix *); -- GitLab