Teuchos - Trilinos Tools Package Version of the Day
Loading...
Searching...
No Matches
Teuchos_MatrixMarket_Raw_Reader.hpp
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
45#include "Teuchos_MatrixMarket_Raw_Adder.hpp"
46#include "Teuchos_MatrixMarket_SymmetrizingAdder.hpp"
47#include "Teuchos_MatrixMarket_CoordDataReader.hpp"
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) :
110 tolerant_ (tolerant), debug_ (debug)
111 {
112 init ();
113 }
114
117 tolerant_ (false), debug_ (false)
118 {
119 init ();
120 }
121
130 tolerant_ (false), debug_ (false)
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.
152 tolerant_ = tolerant;
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;
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 {
270 banner = readBanner (in, lineNumber);
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 =
382 reader.read (in, lineNumber, tolerant_, debug_);
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;
388 reportBadness (err, results);
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:
428 bool tolerant_;
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
487 commentLine = checkCommentLine (line, start, size, lineNumber,
488 tolerant_, maybeBannerLine);
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.
504 RCP<Banner> banner;
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 }
512 return rcp_const_cast<const Banner> (banner);
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;
528 if (numErrors > maxNumErrorsToReport) {
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
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.
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.
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.
Reader()
Constructor that sets default Boolean parameters.
void setParameters(const RCP< ParameterList > &params)
Set parameters from the given ParameterList.
Smart reference counting pointer class for automatic garbage collection.
T * get() const
Get the raw C++ pointer to the underlying object.
#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.
The Teuchos namespace contains all of the classes, structs and enums used by Teuchos,...
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.