1 /* ========================================================================== */
2 /* === Source/Mongoose_IO.cpp =============================================== */
3 /* ========================================================================== */
4
5 /* -----------------------------------------------------------------------------
6 * Mongoose Graph Partitioning Library Copyright (C) 2017-2018,
7 * Scott P. Kolodziej, Nuri S. Yeralan, Timothy A. Davis, William W. Hager
8 * Mongoose is licensed under Version 3 of the GNU General Public License.
9 * Mongoose is also available under other licenses; contact authors for details.
10 * -------------------------------------------------------------------------- */
11
12 /**
13 * Simplified I/O functions for reading matrices and graphs
14 *
15 * For reading Matrix Market files into Mongoose, read_graph and read_matrix
16 * are provided (depending on if a Graph class instance or CSparse matrix
17 * instance is needed). The filename can be specified as either a const char*
18 * (easier for C programmers) or std::string (easier from C++).
19 */
20
21 #include "Mongoose_IO.hpp"
22 #include "Mongoose_Internal.hpp"
23 #include "Mongoose_Logger.hpp"
24 #include "Mongoose_Sanitize.hpp"
25 #include <iostream>
26
27 using namespace std;
28
29 namespace Mongoose
30 {
31
read_graph(const std::string & filename)32 Graph *read_graph(const std::string &filename)
33 {
34 return read_graph(filename.c_str());
35 }
36
read_matrix(const std::string & filename,MM_typecode & matcode)37 cs *read_matrix(const std::string &filename, MM_typecode &matcode)
38 {
39 return read_matrix(filename.c_str(), matcode);
40 }
41
read_graph(const char * filename)42 Graph *read_graph(const char *filename)
43 {
44 Logger::tic(IOTiming);
45 LogInfo("Reading graph from file " << std::string(filename) << "\n");
46
47 MM_typecode matcode;
48 cs *A = read_matrix(filename, matcode);
49 if (!A)
50 {
51 LogError("Error reading matrix from file\n");
52 return NULL;
53 }
54 cs *sanitized_A = sanitizeMatrix(A, mm_is_symmetric(matcode), false);
55 cs_spfree(A);
56 if (!sanitized_A)
57 return NULL;
58
59 Graph *G = Graph::create(sanitized_A, true);
60
61 if (!G)
62 {
63 LogError("Ran out of memory in Mongoose::read_graph\n");
64 cs_spfree(sanitized_A);
65 Logger::toc(IOTiming);
66 return NULL;
67 }
68
69 sanitized_A->p = NULL;
70 sanitized_A->i = NULL;
71 sanitized_A->x = NULL;
72 cs_spfree(sanitized_A);
73
74 Logger::toc(IOTiming);
75
76 return G;
77 }
78
read_matrix(const char * filename,MM_typecode & matcode)79 cs *read_matrix(const char *filename, MM_typecode &matcode)
80 {
81 LogInfo("Reading Matrix from " << std::string(filename) << "\n");
82 FILE *file = fopen(filename, "r");
83 if (!file)
84 {
85 LogError("Error: Cannot read file " << std::string(filename) << "\n");
86 return NULL;
87 }
88
89 LogInfo("Reading Matrix Market banner...");
90 if (mm_read_banner(file, &matcode) != 0)
91 {
92 LogError("Error: Could not process Matrix Market banner\n");
93 fclose(file);
94 return NULL;
95 }
96 if (!mm_is_matrix(matcode) || !mm_is_sparse(matcode)
97 || mm_is_complex(matcode))
98 {
99 LogError(
100 "Error: Unsupported matrix format - Must be real and sparse\n");
101 fclose(file);
102 return NULL;
103 }
104
105 Int M, N, nz;
106 if ((mm_read_mtx_crd_size(file, &M, &N, &nz)) != 0)
107 {
108 LogError("Error: Could not parse matrix dimension and size.\n");
109 fclose(file);
110 return NULL;
111 }
112 if (M != N)
113 {
114 LogError("Error: Matrix must be square.\n");
115 fclose(file);
116 return NULL;
117 }
118
119 LogInfo("Reading matrix data...\n");
120 Int *I = (Int *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(Int));
121 Int *J = (Int *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(Int));
122 double *val
123 = (double *)SuiteSparse_malloc(static_cast<size_t>(nz), sizeof(double));
124
125 if (!I || !J || !val)
126 {
127 LogError("Error: Ran out of memory in Mongoose::read_matrix\n");
128 SuiteSparse_free(I);
129 SuiteSparse_free(J);
130 SuiteSparse_free(val);
131 fclose(file);
132 return NULL;
133 }
134
135 mm_read_mtx_crd_data(file, M, N, nz, I, J, val, matcode);
136 fclose(file); // Close the file
137
138 for (Int k = 0; k < nz; k++)
139 {
140 --I[k];
141 --J[k];
142 if (mm_is_pattern(matcode))
143 val[k] = 1;
144 }
145
146 cs *A = (cs *)SuiteSparse_malloc(1, sizeof(cs));
147 if (!A)
148 {
149 LogError("Error: Ran out of memory in Mongoose::read_matrix\n");
150 SuiteSparse_free(I);
151 SuiteSparse_free(J);
152 SuiteSparse_free(val);
153 return NULL;
154 }
155
156 A->nzmax = nz;
157 A->m = M;
158 A->n = N;
159 A->p = J;
160 A->i = I;
161 A->x = val;
162 A->nz = nz;
163
164 LogInfo("Compressing matrix from triplet to CSC format...\n");
165 cs *compressed_A = cs_compress(A);
166 cs_spfree(A);
167 if (!compressed_A)
168 {
169 LogError("Error: Ran out of memory in Mongoose::read_matrix\n");
170 return NULL;
171 }
172
173 return compressed_A;
174 }
175
176 } // end namespace Mongoose
177