virtual MutableMatrix * submatrix(M2_arrayint cols) const { for (size_t c = 0; c<cols->len; c++) if (cols->array[c] < 0 || cols->array[c] >= n_cols()) { ERROR("column index %d out of bounds 0..%d", cols->array[c], n_cols()-1); return 0; } MutableMat *result = new MutableMat(*this); // zero matrix, over the same ring result->getMat().setFromSubmatrix(getMat(), cols); return result; }
void MutableMatrix::text_out(buffer &o) const { const Ring *R = get_ring(); size_t nrows = n_rows(); size_t ncols = n_cols(); buffer *p = new buffer[nrows]; size_t r; for (size_t c=0; c<ncols; c++) { size_t maxcount = 0; for (r=0; r<nrows; r++) { ring_elem f; get_entry(r,c,f); if (!R->is_zero(f)) R->elem_text_out(p[r], f); else p[r] << "."; if (p[r].size() > maxcount) maxcount = p[r].size(); } for (r=0; r<nrows; r++) for (size_t k=maxcount+1-p[r].size(); k > 0; k--) p[r] << ' '; } for (r=0; r<nrows; r++) { p[r] << '\0'; char *s = p[r].str(); o << s << newline; } delete[] p; }
Raster* Raster::getRasterFromASCFile(std::string const& fname) { std::ifstream in(fname.c_str()); if (!in.is_open()) { WARN("Raster::getRasterFromASCFile(): Could not open file %s.", fname.c_str()); return NULL; } // header information std::size_t n_cols(0), n_rows(0); double xllcorner(0.0), yllcorner(0.0), cell_size(0.0), no_data_val(-9999); if (readASCHeader(in, n_cols, n_rows, xllcorner, yllcorner, cell_size, no_data_val)) { double* values = new double[n_cols*n_rows]; std::string s; // read the data into the double-array for (size_t j(0); j < n_rows; ++j) { const size_t idx ((n_rows - j - 1) * n_cols); for (size_t i(0); i < n_cols; ++i) { in >> s; values[idx+i] = strtod(BaseLib::replaceString(",", ".", s).c_str(),0); } } in.close(); Raster *raster(new Raster(n_cols, n_rows, xllcorner, yllcorner, cell_size, values, values+n_cols*n_rows, no_data_val)); delete [] values; return raster; } else {
virtual bool interchange_columns(size_t i, size_t j) /* swap columns: column(i) <--> column(j) */ { size_t ncols = n_cols(); if (error_column_bound(i,ncols) || error_column_bound(j,ncols)) return false; mat.interchange_columns(i,j); return true; }
/// Get the \p i:th row. std::vector<bool> row(size_t i) const { const size_t n = n_cols(); std::vector<bool> a(n); for (size_t j = 0; j < n; j++) { a[i] = get_bit(i, j); } return a; }
virtual bool set_entry(size_t r, size_t c, const ring_elem a) // Returns false if (r,c) is out of range, or the ring of a is wrong. { if (error_row_bound(r,n_rows())) return false; if (error_column_bound(c,n_cols())) return false; elem b; mat.get_CoeffRing()->from_ring_elem(b,a); mat.set_entry(r,c,b); return true; }
MutableMatrix* MutableMat<T>::invert() const { MutableMat<T>* result = makeZeroMatrix(n_rows(), n_cols()); bool val = mat.invert(result->mat); if (!val) { delete result; return 0; } return result; }
virtual bool insert_columns(size_t i, size_t n_to_add) /* Insert n_to_add columns directly BEFORE column i. */ { if (i < 0 || i > n_cols() || n_to_add < 0) { ERROR("cannot insert %l columns before column %ln",n_to_add,i); return false; } mat.insert_columns(i, n_to_add); return true; }
virtual bool dot_product(size_t c1, size_t c2, ring_elem &result) const { size_t ncols = n_cols(); if (error_column_bound(c1,ncols) || error_column_bound(c2,ncols)) return false; elem a; mat.get_CoeffRing()->set_zero(a); mat.dot_product(c1,c2,a); mat.get_CoeffRing()->to_ring_elem(result,a); return true; }
virtual bool divide_column(size_t i, ring_elem r) /* column(i) <- column(i) / r */ { size_t ncols = n_cols(); if (error_column_bound(i,ncols)) return false; elem b; mat.get_CoeffRing()->from_ring_elem(b,r); mat.divide_column(i,b); return true; }
void backwardSolve ( Matrix<double> const& mat, double* x, double* b) { size_t n_cols (mat.getNCols()); for (int r = (n_cols - 1); r >= 0; r--) { double t = 0.0; for (size_t c = r+1; c < n_cols; c++) { t += mat(r,c) * b[c]; } x[r] = (b[r] - t) / mat(r, r); } }
virtual bool column_op(size_t i, ring_elem r, size_t j) /* column(i) <- column(i) + r * column(j) */ { size_t ncols = n_cols(); if (error_column_bound(i,ncols) || error_column_bound(j,ncols)) return false; if (i == j) return true; elem b; mat.get_CoeffRing()->from_ring_elem(b,r); mat.column_op(i,b,j); return true; }
virtual bool delete_columns(size_t i, size_t j) /* Delete columns i .. j from M */ { size_t ncols = n_cols(); if (error_column_bound(i,ncols) || error_column_bound(j,ncols)) { ERROR("column index out of range"); return false; } mat.delete_columns(i, j); return true; }
/// \name IO. /// \{ void print(std::ostream & os) const { const bit_matrix & mat = *this; os << "[ "; for (size_t i = 0; i < n_rows(); i++) { for (size_t j = 0; j < n_cols(); j++) { os << mat(i,j) << ' '; } if (i != n_rows()-1) { os << "; "; } } os << "]"; }
virtual bool get_entry(size_t r, size_t c, ring_elem &result) const // Returns false if (r,c) is out of range or if result is 0. No error // is returned. result <-- this(r,c), and is set to zero if false is returned. { if (r >= 0 && r < n_rows() && c >= 0 && c < n_cols()) { elem a; mat.get_CoeffRing()->set_zero(a); if (mat.get_entry(r,c,a)) { mat.get_CoeffRing()->to_ring_elem(result,a); return true; } } result = mat.get_ring()->zero(); return false; }
virtual bool column2by2(size_t c1, size_t c2, ring_elem a1, ring_elem a2, ring_elem b1, ring_elem b2) /* column(c1) <- a1 * column(c1) + a2 * column(c2), column(c2) <- b1 * column(c1) + b2 * column(c2) */ { size_t ncols = n_cols(); if (error_column_bound(c1,ncols) || error_column_bound(c2,ncols)) return false; if (c1 == c2) return true; elem aa1, aa2, bb1, bb2; mat.get_CoeffRing()->from_ring_elem(aa1,a1); mat.get_CoeffRing()->from_ring_elem(aa2,a2); mat.get_CoeffRing()->from_ring_elem(bb1,b1); mat.get_CoeffRing()->from_ring_elem(bb2,b2); mat.column2by2(c1,c2,aa1,aa2,bb1,bb2); return true; }
virtual MutableMat * add(const MutableMatrix *B) const // return this + B. return NULL if sizes or types do not match. { const Mat *B1 = B->coerce<Mat>(); if (B1 == NULL) { ERROR("expected matrices with the same ring and sparsity"); return NULL; } if (B->get_ring() != get_ring()) { ERROR("expected matrices with the same ring"); return NULL; } if (B1->n_rows() != n_rows() || B1->n_cols() != n_cols()) { ERROR("expected matrices of the same shape"); return NULL; } MutableMat* result = clone(); result->getMat().addInPlace(*B1); return result; }
TEST(MathLib, DenseGaussAlgorithm) { std::size_t n_rows(100); std::size_t n_cols(n_rows); MathLib::DenseMatrix<double,std::size_t> mat(n_rows, n_cols); // *** fill matrix with arbitrary values // ** initialize random seed srand ( static_cast<unsigned>(time(nullptr)) ); // ** loop over rows and columns for (std::size_t i(0); i<n_rows; i++) { for (std::size_t j(0); j<n_cols; j++) { mat(i,j) = rand()/static_cast<double>(RAND_MAX); } } // *** create solution vector, set all entries to 0.0 double *x(new double[n_cols]); std::fill(x,x+n_cols, 0.0); double *b0(mat * x); // *** create other right hand sides, // set all entries of the solution vector to 1.0 std::fill(x,x+n_cols, 1.0); double *b1(mat * x); std::generate(x,x+n_cols, std::rand); double *b2(mat * x); // right hand side and solution vector with random entries double *b3(mat * x); double *b3_copy(mat * x); double *x3 (new double[n_cols]); std::generate(x3,x3+n_cols, std::rand); MathLib::GaussAlgorithm<MathLib::DenseMatrix<double, std::size_t>, double*> gauss(mat); // solve with b0 as right hand side gauss.solve(b0, true); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(b0[i], 0.0, std::numeric_limits<float>::epsilon()); } // solve with b1 as right hand side gauss.solve(b1, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(b1[i], 1.0, std::numeric_limits<float>::epsilon()); } // solve with b2 as right hand side gauss.solve(b2, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(b2[i]-x[i])/fabs(x[i]), 0.0, std::numeric_limits<float>::epsilon()); } // solve with b3 as right hand side and x3 as solution vector gauss.solve(b3, x3, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(x3[i]-x[i])/fabs(x[i]), 0.0, std::numeric_limits<float>::epsilon()); } // assure entries of vector b3 are not changed for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(b3[i]-b3_copy[i])/fabs(b3[i]), 0.0, std::numeric_limits<float>::epsilon()); } delete [] x; delete [] b0; delete [] b1; delete [] b2; delete [] b3; delete [] x3; delete [] b3_copy; }
TEST(MathLib, DenseGaussAlgorithmDenseVector) { std::size_t n_rows(50); std::size_t n_cols(n_rows); MathLib::DenseMatrix<double,std::size_t> mat(n_rows, n_cols); // *** fill matrix with arbitrary values // ** initialize random seed srand ( static_cast<unsigned>(time(nullptr)) ); // ** loop over rows and columns for (std::size_t i(0); i<n_rows; i++) { for (std::size_t j(0); j<n_cols; j++) { mat(i,j) = rand()/static_cast<double>(RAND_MAX); } } // *** create solution vector, set all entries to 0.0 MathLib::DenseVector<double> x(n_cols); std::fill(std::begin(x), std::end(x), 0.0); MathLib::DenseVector<double> b0(mat * x); // *** create other right hand sides, // set all entries of the solution vector to 1.0 std::fill(std::begin(x), std::end(x), 1.0); MathLib::DenseVector<double> b1(mat * x); std::generate(std::begin(x), std::end(x), std::rand); MathLib::DenseVector<double> b2(mat * x); // right hand side and solution vector with random entries MathLib::DenseVector<double> b3(mat * x); MathLib::DenseVector<double> b3_copy(mat * x); MathLib::DenseVector<double> x3 (n_cols); std::generate(std::begin(x3),std::end(x3), std::rand); MathLib::GaussAlgorithm<MathLib::DenseMatrix<double, std::size_t>, MathLib::DenseVector<double>> gauss(mat); // solve with b0 as right hand side gauss.solve(b0, true); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(b0[i], 0.0, 1e5 * std::numeric_limits<float>::epsilon()); } // solve with b1 as right hand side gauss.solve(b1, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(b1[i], 1.0, std::numeric_limits<float>::epsilon()); } // solve with b2 as right hand side gauss.solve(b2, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(b2[i]-x[i])/fabs(x[i]), 0.0, std::numeric_limits<float>::epsilon()); } gauss.solve(b3, x3, false); for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(x3[i]-x[i])/fabs(x[i]), 0.0, std::numeric_limits<float>::epsilon()); } // assure entries of vector b3 are not changed for (std::size_t i(0); i<n_rows; i++) { ASSERT_NEAR(fabs(b3[i]-b3_copy[i])/fabs(b3[i]), 0.0, std::numeric_limits<float>::epsilon()); } }
int main (int argc, char* argv[]) { LOGOG_INITIALIZE(); logog::Cout* logog_cout (new logog::Cout); BaseLib::LogogSimpleFormatter *custom_format (new BaseLib::LogogSimpleFormatter); logog_cout->SetFormatter(*custom_format); TCLAP::CmdLine cmd( "Generates properties for mesh elements of an input mesh deploying a ASC raster file", ' ', "0.1"); TCLAP::ValueArg<std::string> out_mesh_arg("o", "out-mesh", "the mesh is stored to a file of this name", false, "", "filename for mesh output"); cmd.add( out_mesh_arg ); TCLAP::ValueArg<bool> refinement_raster_output_arg("", "output-refined-raster", "write refined raster to a new ASC file", false, false, "0"); cmd.add( refinement_raster_output_arg ); TCLAP::ValueArg<unsigned> refinement_arg( "r", "refine", "refinement factor that raises the resolution of the raster data", false, 1, "factor (default = 1)"); cmd.add( refinement_arg ); TCLAP::ValueArg<std::string> mapping_arg("", "mapping-name", "file name of mapping", true, "", "file name"); cmd.add( mapping_arg ); TCLAP::ValueArg<std::string> raster_arg("", "raster-file", "the name of the ASC raster file", true, "", "file name"); cmd.add( raster_arg ); TCLAP::ValueArg<std::string> mesh_arg("m", "mesh", "the mesh is read from this file", true, "test.msh", "file name"); cmd.add( mesh_arg ); cmd.parse( argc, argv ); // read mesh MeshLib::Mesh* dest_mesh(FileIO::readMeshFromFile(mesh_arg.getValue())); // read raster and if required manipulate it GeoLib::Raster* raster(FileIO::AsciiRasterInterface::getRasterFromASCFile( raster_arg.getValue())); if (refinement_arg.getValue() > 1) { raster->refineRaster(refinement_arg.getValue()); if (refinement_raster_output_arg.getValue()) { // write new asc file std::string new_raster_fname (BaseLib::dropFileExtension( raster_arg.getValue())); new_raster_fname += "-" + std::to_string(raster->getNRows()) + "x" + std::to_string(raster->getNCols()) + ".asc"; FileIO::AsciiRasterInterface::writeRasterAsASC(*raster, new_raster_fname); } } // put raster data in a std::vector GeoLib::Raster::const_iterator raster_it(raster->begin()); std::size_t n_cols(raster->getNCols()), n_rows(raster->getNRows()); std::size_t size(n_cols * n_rows); std::vector<double> src_properties(size); for (unsigned row(0); row<n_rows; row++) { for (unsigned col(0); col<n_cols; col++) { src_properties[row * n_cols + col] = *raster_it; ++raster_it; } } { double mu, var; std::tie(mu, var) = computeMeanAndVariance(src_properties.begin(), src_properties.end()); INFO("Mean value of source: %f.", mu); INFO("Variance of source: %f.", var); } MeshLib::Mesh* src_mesh(MeshLib::ConvertRasterToMesh(*raster, MeshLib::MeshElemType::QUAD, MeshLib::UseIntensityAs::MATERIAL).execute()); std::vector<std::size_t> src_perm(size); std::iota(src_perm.begin(), src_perm.end(), 0); BaseLib::Quicksort<double>(src_properties, 0, size, src_perm); // compress the property data structure const std::size_t mat_map_size(src_properties.size()); std::vector<std::size_t> mat_map(mat_map_size); mat_map[0] = 0; std::size_t n_mat(1); for (std::size_t k(1); k<mat_map_size; ++k) { if (std::fabs(src_properties[k] - src_properties[k-1]) > std::numeric_limits<double>::epsilon()) { mat_map[k] = mat_map[k - 1] + 1; n_mat++; } else mat_map[k] = mat_map[k - 1]; } std::vector<double> compressed_src_properties(n_mat); compressed_src_properties[0] = src_properties[0]; for (std::size_t k(1), id(1); k<mat_map_size; ++k) { if (std::fabs(src_properties[k] - src_properties[k-1]) > std::numeric_limits<double>::epsilon()) { compressed_src_properties[id] = src_properties[k]; id++; } } compressed_src_properties[n_mat - 1] = src_properties[mat_map_size - 1]; // reset materials in source mesh const std::size_t n_mesh_elements(src_mesh->getNElements()); for (std::size_t k(0); k<n_mesh_elements; k++) { const_cast<MeshLib::Element*>(src_mesh->getElement(src_perm[k]))->setValue(mat_map[k]); } // do the interpolation MeshLib::Mesh2MeshPropertyInterpolation mesh_interpolation(src_mesh, &compressed_src_properties); std::vector<double> dest_properties(dest_mesh->getNElements()); mesh_interpolation.setPropertiesForMesh(const_cast<MeshLib::Mesh*>(dest_mesh), dest_properties); const std::size_t n_dest_mesh_elements(dest_mesh->getNElements()); { // write property file std::string property_fname(mapping_arg.getValue()); std::ofstream property_out(property_fname.c_str()); if (!property_out) { ERR("Could not open file %s for writing the mapping.", property_fname.c_str()); return -1; } for (std::size_t k(0); k < n_dest_mesh_elements; k++) property_out << k << " " << dest_properties[k] << "\n"; property_out.close(); } { double mu, var; std::tie(mu, var) = computeMeanAndVariance(dest_properties.begin(), dest_properties.end()); INFO("Mean value of destination: %f.", mu); INFO("Variance of destination: %f.", var); } if (! out_mesh_arg.getValue().empty()) { std::vector<std::size_t> dest_perm(n_dest_mesh_elements); std::iota(dest_perm.begin(), dest_perm.end(), 0); BaseLib::Quicksort<double>(dest_properties, 0, n_dest_mesh_elements, dest_perm); // reset materials in destination mesh for (std::size_t k(0); k<n_dest_mesh_elements; k++) { const_cast<MeshLib::Element*>(dest_mesh->getElement(dest_perm[k]))->setValue(k); } FileIO::Legacy::MeshIO mesh_writer; mesh_writer.setPrecision(12); mesh_writer.setMesh(dest_mesh); mesh_writer.writeToFile(out_mesh_arg.getValue()); } delete raster; delete src_mesh; delete dest_mesh; delete custom_format; delete logog_cout; LOGOG_SHUTDOWN(); return 0; }