Teuchos Package Browser (Single Doxygen Collection) Version of the Day
Loading...
Searching...
No Matches
MatrixMarket_Raw_InOutTest.cpp
Go to the documentation of this file.
1// @HEADER
2// ***********************************************************************
3//
4// Teuchos: Common Tools Package
5// Copyright (2004) Sandia Corporation
6//
7// Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive
8// license for use of this work by or on behalf of the U.S. Government.
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
50#include <algorithm>
51
52using std::endl;
53
54namespace {
55 // Sample Matrix Market sparse matrix file. We include this so we
56 // can test without needing to read in a file. Notice that all the
57 // decimal floating-point values in this example can be represented
58 // exactly in binary floating point. This example has correct
59 // syntax, so you won't need to use tolerant mode to parse it.
60 const char sampleMatrixMarketFile[] =
61 "%%MatrixMarket matrix coordinate real general\n"
62 "5 5 10\n"
63 "5 5 55.0\n"
64 "4 4 44.0\n"
65 "3 3 33.0\n"
66 "2 2 22.0\n"
67 "1 1 11.0\n"
68 "4 5 45.0\n"
69 "3 4 34.0\n"
70 "2 3 23.0\n"
71 "1 2 12.0\n"
72 "1 5 15.0\n";
73
74 // Sample Matrix Market sparse matrix file for testing symmetric
75 // storage. Matrix Market format for symmetric, skew-symemtric,
76 // etc. specifies that only the lower triangle should be stored.
77 const char symmetricMatrixMarketFile[] =
78 "%%MatrixMarket matrix coordinate real symmetric\n"
79 "5 5 10\n"
80 "5 5 55.0\n"
81 "4 4 44.0\n"
82 "3 3 33.0\n"
83 "2 2 22.0\n"
84 "1 1 11.0\n"
85 "5 4 54.0\n"
86 "4 3 43.0\n"
87 "3 2 32.0\n"
88 "2 1 21.0\n"
89 "5 1 51.0\n";
90
91} // namespace (anonymous)
92
93// Benchmark driver
94 int
95main (int argc, char *argv[])
96{
100 using Teuchos::ArrayView;
101 using Teuchos::Comm;
104 using Teuchos::RCP;
105 using Teuchos::rcp;
106 using Teuchos::rcpFromRef;
108 using std::cout;
109 using std::cerr;
110 typedef double scalar_type;
111 typedef int ordinal_type;
112
113 bool success = false;
114 // Verbosity of output
115 bool verbose = true;
116 try {
117 // Name of the Matrix Market sparse matrix file to read. If empty,
118 // use the Matrix Market example embedded as a string in this file.
119 std::string filename;
120 // If true, just check the sparse matrix file. Otherwise,
121 // do a full conversion to CSR (compressed sparse row) format.
122 bool checkOnly = false;
123 // Whether to echo the sparse matrix to stdout after reading it
124 // successfully.
125 bool echo = false;
126 // Whether to parse the Matrix Market file tolerantly.
127 bool tolerant = false;
128 // Whether to print debugging-level output
129 bool debug = false;
130
131 CommandLineProcessor cmdp (false, true);
132 cmdp.setOption ("filename", &filename,
133 "Name of the Matrix Market sparse matrix file to read.");
134 cmdp.setOption ("checkOnly", "fullTest", &checkOnly,
135 "If true, just check the syntax of the input file. "
136 "Otherwise, do a full test.");
137 cmdp.setOption ("echo", "noecho", &echo,
138 "Whether to echo the sparse matrix contents to stdout "
139 "after reading it successfully.");
140 cmdp.setOption ("tolerant", "strict", &tolerant,
141 "Whether to tolerate syntax errors in the Matrix Market file.");
142 cmdp.setOption ("verbose", "quiet", &verbose,
143 "Print status output to stdout.");
144 cmdp.setOption ("debug", "nodebug", &debug,
145 "Print possibly copious debugging output to stderr.");
146 // Parse the command-line arguments.
147 {
148 const CommandLineProcessor::EParseCommandLineReturn parseResult =
149 cmdp.parse (argc,argv);
150 // If the caller asks us to print the documentation, or does not
151 // explicitly say to run the benchmark, we let this "test" pass
152 // trivially.
153 if (parseResult == CommandLineProcessor::PARSE_HELP_PRINTED) {
154 std::cout << "End Result: TEST PASSED" << endl;
155 return EXIT_SUCCESS;
156 }
158 parseResult != CommandLineProcessor::PARSE_SUCCESSFUL,
159 std::invalid_argument, "Failed to parse command-line arguments.");
160 }
161
162 // Test reading in the sparse matrix. If no filename or an empty
163 // filename is specified, the test passes trivially.
164 success = true;
165 {
166 // The following tests check reading in different banners. A bug was found
167 // in the banner reader wherein banners with multiple consecutive spaces
168 // were not read correctly. These tests assure that banners with or
169 // without multiple consecutive spaces/tabs are read correctly.
170 bool xs;
171 if (verbose) {
172 cout << "Checking MatrixMarket banner parsing\n";
173 }
174 {
175 // Well formatted banner, passes trivially
176 if (verbose) cout << "Reading first banner\n";
177 typedef Checker<scalar_type, ordinal_type> checker_type;
178 checker_type checker (echo, false, false);
179 RCP<const Comm<int> > comm = rcp (new SerialComm<int>);
180 std::stringstream in;
181 in.str("%%MatrixMarket matrix coordinate real symmetric\n0 0 0\n");
182 RCP<std::istream> inStream = rcpFromRef(in);
183 xs = checker.read (*comm, inStream);
184 if (verbose) {
185 cout << "Banner read " << (!xs ? "un" : "") << "successfully\n";
186 }
187 success = success && xs;
188 }
189
190 {
191 // Banner with multiple adjacent/consecutive spaces/tabs
192 if (verbose) cout << "Reading second banner\n";
193 typedef Checker<scalar_type, ordinal_type> checker_type;
194 checker_type checker (echo, false, false);
195 RCP<const Comm<int> > comm = rcp (new SerialComm<int>);
196 std::stringstream in;
197 in.str("%%MatrixMarket\tmatrix\t\tcoordinate real symmetric\n0 0 0\n");
198 RCP<std::istream> inStream = rcpFromRef(in);
199 xs = checker.read (*comm, inStream);
200 if (verbose) {
201 cout << "Banner read " << (!xs ? "un" : "") << "successfully\n";
202 }
203 success = success && xs;
204 }
205
206 {
207 // Bad value in banner. Should throw std::runtime_error
208 if (verbose) cout << "Reading third banner\n";
209 typedef Checker<scalar_type, ordinal_type> checker_type;
210 checker_type checker (echo, false, false);
211 RCP<const Comm<int> > comm = rcp (new SerialComm<int>);
212 std::stringstream in;
213 try {
214 in.str("%%MatrixMarket matrix coordinate real xyz\n0 0 0\n");
215 RCP<std::istream> inStream = rcpFromRef(in);
216 checker.read (*comm, inStream);
217 // The call to read *should* raise an error and the following line
218 // should not be encountered
219 xs = false;
220 }
221 catch (const std::runtime_error& e) {
222 // The error message will include that "xyz" is a bad value. Check
223 // that the string "xyz" is in the error mesage.
224 std::string es(e.what());
225 xs = es.find("xyz") != std::string::npos;
226 }
227 if (verbose) {
228 cout << "Banner read " << (!xs ? "un" : "") << "successfully\n";
229 }
230 success = success && xs;
231 }
232
233 if (verbose) {
234 if (success) {
235 cout << "Banners parsed successfully\n";
236 } else {
237 cout << "Banners not parsed successfully\n";
238 }
239 }
240 }
241
242 if (checkOnly) {
243 typedef Checker<scalar_type, ordinal_type> checker_type;
244 checker_type checker (echo, tolerant, debug);
245
246 RCP<const Comm<int> > comm = rcp (new SerialComm<int>);
247 if (filename != "") {
248 if (verbose) {
249 cout << "Checking syntax of the Matrix Market file \"" << filename
250 << "\"" << endl;
251 }
252 success = success && checker.readFile (*comm, filename);
253 if (verbose) {
254 if (success) {
255 cout << "The given file is a valid Matrix Market file." << endl;
256 }
257 else {
258 cout << "The given file has syntax errors." << endl;
259 }
260 }
261 }
262 else {
263 if (verbose) {
264 cout << "Checking syntax of the first built-in Matrix Market example" << endl
265 << std::flush;// for debug output next
266 }
267 if (debug) {
268 cerr << "First built-in Matrix Market example: " << endl
269 << sampleMatrixMarketFile << endl;
270 }
271 std::istringstream in (sampleMatrixMarketFile);
272 RCP<std::istream> inStream = rcpFromRef (in);
273 success = success && checker.read (*comm, inStream);
274 if (verbose) {
275 if (success) {
276 cout << "The example has valid Matrix Market syntax." << endl;
277 }
278 else {
279 cout << "The example has syntax errors." << endl;
280 }
281 }
282 }
283 }
284 else {
285 typedef Reader<scalar_type, ordinal_type> reader_type;
286 reader_type reader (tolerant, debug);
287 ArrayRCP<ordinal_type> ptr, ind;
288 ArrayRCP<scalar_type> val;
289 ordinal_type numRows, numCols;
290 //
291 // Read the Matrix Market data, either from a file or from a
292 // built-in string.
293 //
294 if (filename != "") {
295 if (verbose) {
296 cout << "Reading the Matrix Market file \"" << filename << "\"" << endl;
297 }
298 success = success && reader.readFile (ptr, ind, val,
299 numRows, numCols, filename);
300 }
301 else {
302 if (verbose) {
303 cout << "Reading the first built-in Matrix Market example" << endl;
304 }
305 if (debug) {
306 cerr << "First built-in Matrix Market example:" << endl
307 << sampleMatrixMarketFile << endl;
308 }
309 std::istringstream inStr (sampleMatrixMarketFile);
310 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr);
311 }
312 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::runtime_error, "Matrix Market "
313 "reader failed to read the given file or input stream.");
314 if (success && verbose) {
315 cout << "Returned from reading the Matrix Market data" << endl
316 << std::flush; // for following debug output
317 }
318 if (debug) {
319 cerr << "CSR output info:" << endl
320 << " ptr.size() = " << ptr.size()
321 << ", ind.size() = " << ind.size()
322 << ", val.size() = " << val.size()
323 << ", numRows = " << numRows
324 << ", numCols = " << numCols
325 << endl;
326 }
327
328 // Here's the fun part. Output the CSR data to an output stream.
329 // Then read in the output stream. The resulting matrix should be
330 // exactly the same (unless the original file had elements at the
331 // same location that were added together with rounding error).
332 // This is a test for both Writer and Reader.
333 std::ostringstream outStr;
334 if (success && verbose) {
335 cout << "Printing the CSR arrays to a Matrix Market output stream"
336 << endl << std::flush;
337 }
339 writer.write (outStr, ptr (), ind (), val (), numRows, numCols);
340
341 if (debug && echo) {
342 cerr << "CSR data:" << endl
343 << "- ptr = [";
344 for (ordinal_type i = 0; i < ptr.size(); ++i) {
345 cerr << ptr[i];
346 if (i+1 != ptr.size()) { // don't subtract from zero if unsigned
347 cerr << ", ";
348 }
349 }
350 cerr << "]" << endl
351 << "- ind = [";
352 for (ordinal_type i = 0; i < ind.size(); ++i) {
353 cerr << ind[i];
354 if (i+1 != ind.size()) { // don't subtract from zero if unsigned
355 cerr << ", ";
356 }
357 }
358 cerr << "]" << endl
359 << "- val = [";
360 for (ordinal_type i = 0; i < val.size(); ++i) {
361 cerr << val[i];
362 if (i+1 != val.size()) { // don't subtract from zero if unsigned
363 cerr << ", ";
364 }
365 }
366 cerr << "]" << endl;
367
368 cerr << "CSR data, converted back to Matrix Market format" << endl;
369 writer.write (cerr, ptr (), ind (), val (), numRows, numCols);
370 cerr << endl;
371 }
372
373 ArrayRCP<ordinal_type> newptr, newind;
374 ArrayRCP<scalar_type> newval;
375 ordinal_type newNumRows, newNumCols;
376 if (success && verbose) {
377 cout << "Reading the Matrix Market output back into CSR arrays" << endl;
378 }
379 {
380 std::istringstream inStr (outStr.str ());
381 success = success && reader.read (newptr, newind, newval,
382 newNumRows, newNumCols, inStr);
383 }
384 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error, "Matrix Market "
385 "reader failed to read the output back into CSR arrays.");
386 if (success && verbose) {
387 cout << "Successfully read the Matrix Market output back into CSR arrays"
388 << endl << std::flush;
389 }
390 if (debug) {
391 cerr << "CSR output info:" << endl
392 << " newptr.size() = " << newptr.size()
393 << ", newind.size() = " << newind.size()
394 << ", newval.size() = " << newval.size()
395 << ", newNumRows = " << newNumRows
396 << ", newNumCols = " << newNumCols
397 << endl;
398 }
399
400 // The old arrays should equal the new arrays.
401 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != newptr.size (), std::logic_error,
402 "New ptr array has a different length than old ptr array");
403 TEUCHOS_TEST_FOR_EXCEPTION(ind.size () != newind.size (), std::logic_error,
404 "New ind array has a different length than old ind array");
405 TEUCHOS_TEST_FOR_EXCEPTION(val.size () != newval.size (), std::logic_error,
406 "New val array has a different length than old val array");
407 TEUCHOS_TEST_FOR_EXCEPTION(newNumRows != numRows || newNumCols != numCols,
408 std::logic_error, "New dimensions differ from old dimensions");
409 TEUCHOS_TEST_FOR_EXCEPTION(ptr.size () != numRows+1, std::logic_error,
410 "ptr.size() != numRows+1");
411 TEUCHOS_TEST_FOR_EXCEPTION(newptr.size () != newNumRows+1, std::logic_error,
412 "newptr.size() != newNumRows+1");
413
414 for (ordinal_type rowIndex = 0; rowIndex < numRows; ++rowIndex) {
415 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex] != newptr[rowIndex],
416 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex] = "
417 << ptr[rowIndex] << " != newptr[rowIndex] = " << newptr[rowIndex]
418 << ".");
419 TEUCHOS_TEST_FOR_EXCEPTION(ptr[rowIndex+1] != newptr[rowIndex+1],
420 std::logic_error, "At row index " << rowIndex << ", ptr[rowIndex+1] = "
421 << ptr[rowIndex+1] << " != newptr[rowIndex+1] = " << newptr[rowIndex+1]
422 << ".");
423 for (ordinal_type k = ptr[rowIndex]; k < ptr[rowIndex+1]; ++k) {
424 TEUCHOS_TEST_FOR_EXCEPTION(ind[k] != newind[k], std::logic_error,
425 "At row index " << rowIndex << ", ind[k=" << k << "] = "
426 << ind[k] << " != newind[k] = " << newind[k] << ".");
427 // You may want to relax this inequality if the original
428 // Matrix Market file had multiple entries at the same
429 // location and if adding them together resulted in rounding
430 // error.
431 TEUCHOS_TEST_FOR_EXCEPTION(val[k] != newval[k], std::logic_error,
432 "At row index " << rowIndex << ", val[k=" << k << "] = "
433 << val[k] << " != newval[k] = " << newval[k] << ".");
434 }
435 }
436
437 // Now test reading symmetric data, if no filename was specified.
438 if (filename == "") {
439 std::istringstream inStr (symmetricMatrixMarketFile);
440 success = success && reader.read (ptr, ind, val, numRows, numCols, inStr);
441 TEUCHOS_TEST_FOR_EXCEPTION(! success, std::logic_error,
442 "Matrix Market reader failed to read the given example string.");
443 if (success && verbose) {
444 cout << "Returned from reading the Matrix Market data" << endl
445 << std::flush; // for following debug output
446 }
447 if (debug) {
448 cerr << "CSR output info:" << endl
449 << " ptr.size() = " << ptr.size()
450 << ", ind.size() = " << ind.size()
451 << ", val.size() = " << val.size()
452 << ", numRows = " << numRows
453 << ", numCols = " << numCols
454 << endl;
455 }
456
457 // This is a bit of a hack, since we know the contents of the
458 // example. Since we "symmetrize" when reading in symmetric
459 // data, there should be 15 entries in the resulting matrix.
460 const ordinal_type correctNumEntries = 15;
462 val.size() != correctNumEntries,
463 std::logic_error,
464 "Incorrect number of entries after symmetrization: There should be "
465 << correctNumEntries << ", but there are " << val.size() << " entries "
466 "instead.");
467 }
468 } // end of the file / string Reader tests
469
470 if (success)
471 std::cout << "End Result: TEST PASSED" << endl;
472 else
473 std::cout << "End Result: TEST FAILED" << endl;
474 }
475 TEUCHOS_STANDARD_CATCH_STATEMENTS(verbose, std::cerr, success);
476
477 return ( success ? EXIT_SUCCESS : EXIT_FAILURE );
478}
Basic command line parser for input from (argc,argv[])
A MPI utilities class, providing methods for initializing, finalizing, and querying the global MPI se...
#define TEUCHOS_STANDARD_CATCH_STATEMENTS(VERBOSE, ERR_STREAM, SUCCESS_FLAG)
Simple macro that catches and reports standard exceptions and other exceptions.
Reference-counted smart pointer for managing arrays.
Nonowning array view.
Abstract interface for distributed-memory communication.
Class that helps parse command line input arguments from (argc,argv[]) and set options.
Tool for debugging the syntax of a Matrix Market file containing a sparse matrix.
Read a sparse matrix from a Matrix Market file into raw CSR (compressed sparse row) storage.
Write a sparse matrix from raw CSR (compressed sparse row) storage to a Matrix Market file.
void write(std::ostream &out, const ArrayView< const OrdinalType > &rowptr, const ArrayView< const OrdinalType > &colind, const ArrayView< const ScalarType > &values, const OrdinalType numRows, const OrdinalType numCols)
Write the sparse matrix to the given output stream.
A list of parameters of arbitrary type.
Smart reference counting pointer class for automatic garbage collection.
Concrete serial communicator subclass.
int main()
Definition evilMain.cpp:75
#define TEUCHOS_TEST_FOR_EXCEPTION(throw_exception_test, Exception, msg)
Macro for throwing an exception with breakpointing to ease debugging.
TEUCHOS_DEPRECATED RCP< T > rcp(T *p, Dealloc_T dealloc, bool owns_mem)
Deprecated.