Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_Raw_Reader.hpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Tpetra: Templated Linear Algebra Services Package
5// Copyright (2008) Sandia Corporation
6//
7// Under the terms of Contract DE-AC04-94AL85000 with Sandia Corporation,
8// the U.S. Government retains certain rights in this software.
9//
10// Redistribution and use in source and binary forms, with or without
11// modification, are permitted provided that the following conditions are
12// met:
13//
14// 1. Redistributions of source code must retain the above copyright
15// notice, this list of conditions and the following disclaimer.
16//
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// 3. Neither the name of the Corporation nor the names of the
22// contributors may be used to endorse or promote products derived from
23// this software without specific prior written permission.
24//
25// THIS SOFTWARE IS PROVIDED BY SANDIA CORPORATION "AS IS" AND ANY
26// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SANDIA CORPORATION OR THE
29// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
31// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36//
37// Questions? Contact Michael A. Heroux (maherou@sandia.gov)
38//
39// ************************************************************************
40// @HEADER
41
42#ifndef __Teuchos_MatrixMarket_Raw_Reader_hpp
43#define __Teuchos_MatrixMarket_Raw_Reader_hpp
44
48
49
50namespace Teuchos {
71 namespace MatrixMarket {
87 namespace Raw {
100 template<class Scalar, class Ordinal>
101 class Reader {
102 public:
109 Reader (const bool tolerant, const bool debug) :
111 {
112 init ();
113 }
114
118 {
119 init ();
120 }
121
131 {
133 init ();
134 }
135
139 void
141 {
142 // Default parameter values.
143 bool tolerant = false;
144 bool debug = false;
145
146 // Read parameters.
147 tolerant = params->get ("Parse tolerantly", tolerant);
148 debug = params->get ("Debug mode", debug);
149
150 // No side effects on the class until ParameterList
151 // processing is complete.
153 debug_ = debug;
154 }
155
159 {
160 // Default parameter values.
161 const bool tolerant = false;
162 const bool debug = false;
163
164 // Set default parameters with documentation.
165 RCP<ParameterList> params = parameterList ("Matrix Market Reader");
166 params->set ("Parse tolerantly", tolerant, "Whether to tolerate "
167 "syntax errors when parsing the Matrix Market file");
168 params->set ("Debug mode", debug, "Whether to print debugging output "
169 "to stderr, on all participating MPI processes");
170
172 }
173
199 bool
202 ArrayRCP<Scalar>& values,
203 Ordinal& numRows,
204 Ordinal& numCols,
205 const std::string& filename)
206 {
207 std::ifstream in (filename.c_str ());
208 TEUCHOS_TEST_FOR_EXCEPTION(! in, std::runtime_error,
209 "Failed to open file \"" << filename << "\" for reading.");
210 return read (rowptr, colind, values, numRows, numCols, in);
211 }
212
239 bool
242 ArrayRCP<Scalar>& values,
243 Ordinal& numRows,
244 Ordinal& numCols,
245 std::istream& in)
246 {
247 using std::cerr;
248 using std::cout;
249 using std::endl;
250 typedef ScalarTraits<Scalar> STS;
251
252 // This "Adder" knows how to add sparse matrix entries,
253 // given a line of data from the file. It also stores the
254 // entries and can sort them.
256 // SymmetrizingAdder "advices" (yes, I'm using that as a verb)
257 // the original Adder, so that additional entries are filled
258 // in symmetrically, if the Matrix Market banner line
259 // specified a symmetry type other than "general".
261
262 // Current line number of the input stream.
263 size_t lineNumber = 1;
264
265 // Construct the "Banner" (matrix metadata, including type
266 // and symmetry information, but not dimensions).
268 std::ostringstream err;
269 try {
271 }
272 catch (std::exception& e) {
273 err << "Failed to read Matrix Market input's Banner: " << e.what();
274 if (tolerant_) {
275 if (debug_) {
276 cerr << err.str() << endl;
277 }
278 return false;
279 }
280 else {
281 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, err.str());
282 }
283 }
284
285 //
286 // Validate the metadata in the Banner.
287 //
288 bool ok = true;
289 if (banner->matrixType () != "coordinate") {
290 err << "Matrix Market input file must contain a \"coordinate\"-"
291 "format sparse matrix in order to create a sparse matrix object "
292 "from it.";
293 ok = false;
294 }
295 else if (! STS::isComplex && banner->dataType () == "complex") {
296 err << "The Matrix Market sparse matrix file contains complex-"
297 "valued data, but you are try to read the data into a sparse "
298 "matrix containing real values (your matrix's Scalar type is "
299 "real).";
300 ok = false;
301 }
302 else if (banner->dataType () != "real" &&
303 banner->dataType () != "complex") {
304 err << "Only real or complex data types (no pattern or integer "
305 "matrices) are currently supported.";
306 ok = false;
307 }
308 if (! ok) {
309 if (tolerant_) {
310 if (debug_) {
311 cerr << "Matrix Market banner is invalid: " << err.str () << endl;
312 return false;
313 }
314 }
315 else {
316 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error,
317 "Matrix Market banner is invalid: " << err.str ());
318 }
319 }
320 if (debug_) {
321 cerr << "Matrix Market Banner line:" << endl << *banner << endl;
322 }
323
324 // The reader will invoke the adder (see below) once for
325 // each matrix entry it reads from the input stream.
327 // We will set the adder below, after calling readDimensions().
329
330 // Read in the dimensions of the sparse matrix: (# rows, #
331 // columns, # matrix entries (counting duplicates as
332 // separate entries)). The second element of the pair tells
333 // us whether the values were gotten successfully.
334 std::pair<Tuple<Ordinal, 3>, bool> dims =
335 reader.readDimensions (in, lineNumber, tolerant_);
336 if (! dims.second) {
337 err << "Error reading Matrix Market sparse matrix file: failed to "
338 "read coordinate dimensions.";
339 if (tolerant_) {
340 if (debug_) {
341 cerr << err.str () << endl;
342 }
343 return false;
344 }
345 else {
346 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, err.str ());
347 }
348 }
349
350 // These are "expected" values read from the input stream's
351 // metadata. The actual matrix entries read from the input
352 // stream might not conform to their constraints. We allow
353 // such nonconformity only in "tolerant" mode; otherwise, we
354 // throw an exception.
355 numRows = dims.first[0];
356 numCols = dims.first[1];
357 const Ordinal numEntries = dims.first[2];
358 if (debug_) {
359 cerr << "Reported dimensions: " << numRows << " x " << numCols
360 << ", with " << numEntries << " entries (counting possible "
361 << "duplicates)." << endl;
362 }
363
364 // The "raw" adder knows about the expected matrix
365 // dimensions, but doesn't know about symmetry.
367 rcp (new raw_adder_type (numRows, numCols, numEntries,
368 tolerant_, debug_));
369 // The symmetrizing adder knows about symmetry. It mediates
370 // adding entries to the "raw" adder. We'll use the raw
371 // adder to compute the CSR arrays.
373 rcp (new adder_type (rawAdder, banner->symmType ()));
374
375 // Give the adder to the reader.
376 reader.setAdder (adder);
377
378 // Read the sparse matrix entries. "results" just tells us if
379 // and where there were any bad lines of input. The actual
380 // sparse matrix entries are stored in the (raw) Adder object.
381 std::pair<bool, std::vector<size_t> > results =
383
384 // Report any bad line number(s).
385 if (! results.first) {
386 err << "The Matrix Market input stream had syntax error(s)."
387 " Here is the error report." << endl;
389 if (tolerant_) {
390 if (debug_) {
391 cerr << err.str() << endl;
392 }
393 return false;
394 }
395 else {
396 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, err.str ());
397 }
398 }
399 // Done reading the sparse matrix; now extract CSR arrays.
400 size_t numUnique, numRemoved;
404 try {
405 rawAdder->mergeAndConvertToCSR (numUnique, numRemoved, ptr, ind, val);
406 }
407 catch (std::exception& e) {
408 err << "Failed to convert sparse matrix data to CSR (compressed "
409 "sparse row) format. Reported error: " << e.what ();
410 if (tolerant_) {
411 if (debug_) {
412 cerr << err.str () << endl;
413 }
414 return false;
415 }
416 else {
417 TEUCHOS_TEST_FOR_EXCEPTION(true, std::runtime_error, err.str ());
418 }
419 }
420 rowptr = ptr;
421 colind = ind;
422 values = val;
423 return true;
424 }
425
426 private:
430 bool debug_;
431
438 void init () {
439 using std::cerr;
440 using std::endl;
441
442 if (debug_) {
443 cerr << "MatrixMarket::Raw::Reader:" << endl
444 << "- Tolerant mode: " << tolerant_ << endl
445 << "- Debug mode: " << debug_ << endl;
446 }
447 }
448
462 readBanner (std::istream& in, size_t& lineNumber)
463 {
464 using std::cerr;
465 using std::endl;
466 std::string line; // The presumed banner line
467
468 // The first line of the Matrix Market file should always be
469 // the banner line. In tolerant mode, we allow comment
470 // lines before the banner line. This complicates detection
471 // of comment lines a bit.
472 if (tolerant_) {
473 // Keep reading lines until we get a noncomment line.
474 const bool maybeBannerLine = true;
475 size_t numLinesRead = 0;
476 bool commentLine = false;
477 do {
478 // Try to read a line from the input stream.
479 const bool readFailed = ! getline (in, line);
480 TEUCHOS_TEST_FOR_EXCEPTION(readFailed, std::invalid_argument,
481 "Failed to get Matrix Market banner line from input, after reading "
482 << numLinesRead << "line" << (numLinesRead != 1 ? "s." : "."));
483 // We read a line from the input stream.
484 ++lineNumber;
485 ++numLinesRead;
486 size_t start, size; // Output args of checkCommentLine
489 } while (commentLine); // Loop until we find a noncomment line.
490 }
491 else {
492 const bool readFailed = ! getline (in, line);
493 TEUCHOS_TEST_FOR_EXCEPTION(readFailed, std::invalid_argument,
494 "Failed to get Matrix Market banner line from input. This "
495 "probably means that the file is empty (contains zero lines).");
496 }
497
498 if (debug_) {
499 cerr << "Raw::Reader::readBanner: Here is the presumed banner line:"
500 << endl << line << endl;
501 }
502
503 // Assume that the noncomment line we found is the banner line.
505 try {
506 banner = rcp (new Banner (line, tolerant_));
507 } catch (std::exception& e) {
508 TEUCHOS_TEST_FOR_EXCEPTION(true, std::invalid_argument,
509 "Matrix Market file's banner line contains syntax error(s): "
510 << e.what ());
511 }
513 }
514
519 void
520 reportBadness (std::ostream& out,
521 const std::pair<bool, std::vector<size_t> >& results)
522 {
523 using std::endl;
524 const size_t numErrors = results.second.size();
525 const size_t maxNumErrorsToReport = 20;
526 out << numErrors << " errors when reading Matrix Market sparse "
527 "matrix file." << endl;
529 out << "-- We do not report individual errors when there "
530 "are more than " << maxNumErrorsToReport << ".";
531 }
532 else if (numErrors == 1) {
533 out << "Error on line " << results.second[0] << endl;
534 }
535 else if (numErrors > 1) {
536 out << "Errors on lines {";
537 for (size_t k = 0; k < numErrors-1; ++k) {
538 out << results.second[k] << ", ";
539 }
540 out << results.second[numErrors-1] << "}" << endl;
541 }
542 }
543 }; // end of class Reader
544 } // namespace Raw
545 } // namespace MatrixMarket
546} // namespace Teuchos
547
548#endif // __Teuchos_MatrixMarket_Raw_Reader_hpp
int size(const Comm< Ordinal > &comm)
Get the number of processes in the communicator.
Parse a Matrix Market banner line.
Read a sparse matrix from a Matrix Market file into raw CSR (compressed sparse row) storage.
RCP< const ParameterList > getValidParameters() const
Get a list of valid default parameters, with documentation.
RCP< const Banner > readBanner(std::istream &in, size_t &lineNumber)
Read in the Banner line from the given input stream.
bool read(ArrayRCP< Ordinal > &rowptr, ArrayRCP< Ordinal > &colind, ArrayRCP< Scalar > &values, Ordinal &numRows, Ordinal &numCols, std::istream &in)
Read the sparse matrix from the given input stream into CSR storage.
Reader(const bool tolerant, const bool debug)
Constructor that takes Boolean parameters.
void reportBadness(std::ostream &out, const std::pair< bool, std::vector< size_t > > &results)
Reader(const RCP< ParameterList > &params)
Constructor that takes a ParameterList of parameters.
bool readFile(ArrayRCP< Ordinal > &rowptr, ArrayRCP< Ordinal > &colind, ArrayRCP< Scalar > &values, Ordinal &numRows, Ordinal &numCols, const std::string &filename)
Read the sparse matrix from the given file into CSR storage.
bool tolerant_
Whether to parse the Matrix Market file tolerantly.
Reader()
Constructor that sets default Boolean parameters.
void setParameters(const RCP< ParameterList > &params)
Set parameters from the given ParameterList.
bool debug_
Whether to print debugging output to stderr.
Concrete serial communicator subclass.
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
Matrix Market file utilities.
"Raw" input of sparse matrices from Matrix Market files.
bool checkCommentLine(const std::string &line, size_t &start, size_t &size, const size_t lineNumber, const bool tolerant, const bool maybeBannerLine)
True if the line is a comment line, false otherwise.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.