1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24 package org.dishevelled.matrix.io.impl;
25
26 import java.io.BufferedReader;
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.io.InputStreamReader;
30
31 import java.util.HashMap;
32 import java.util.Map;
33
34 import java.util.regex.Matcher;
35 import java.util.regex.Pattern;
36
37 import org.dishevelled.matrix.Matrix2D;
38
39
40
41
42
43
44
45 public abstract class AbstractMatrixMarketReader
46 extends AbstractMatrix2DReader<Double>
47 {
48
49 private static final Map<String, ReaderStrategy> STRATEGIES;
50
51
52 private static final Pattern HEADER = Pattern.compile("^%%MatrixMarket matrix\\s+(\\S+)\\s+(\\S+)\\s+(\\S+)\\s*$");
53
54 static
55 {
56 STRATEGIES = new HashMap<String, ReaderStrategy>();
57 STRATEGIES.put("general", new GeneralReaderStrategy());
58 STRATEGIES.put("symmetric", new SymmetricReaderStrategy());
59 STRATEGIES.put("skew-symmetric", new SkewSymmetricReaderStrategy());
60
61 STRATEGIES.put("hermitian", new HermitianReaderStrategy());
62 }
63
64
65
66
67
68
69 protected Double parse(final String value)
70 {
71 return null;
72 }
73
74
75 public final Matrix2D<Double> read(final InputStream inputStream) throws IOException
76 {
77 if (inputStream == null)
78 {
79 throw new IllegalArgumentException ("inputStream must not be null");
80 }
81 int lineNumber = 0;
82 BufferedReader reader = null;
83 ReaderStrategy readerStrategy = null;
84 Matrix2D<Double> matrix = null;
85 try
86 {
87 reader = new BufferedReader(new InputStreamReader(inputStream));
88 while (reader.ready())
89 {
90 String line = reader.readLine();
91 if (line.startsWith("%"))
92 {
93 Matcher m = HEADER.matcher(line);
94 if (m.matches())
95 {
96 String format = m.group(1);
97 if (!("coordinate".equals(format)))
98 {
99 throw new IOException("header line format must be coordinate, was " + format);
100 }
101 String type = m.group(2);
102 if (!("real".equals(type) || "integer".equals(type)))
103 {
104 throw new IOException("header line type must be real or integer, was " + type);
105 }
106 String symmetryStructure = m.group(3);
107 readerStrategy = STRATEGIES.get(symmetryStructure);
108 if (readerStrategy == null)
109 {
110 throw new IOException("header line symmetry structure must be one of: general, symmetric,"
111 + "skew-symmetric, or hermitian; was " + symmetryStructure);
112 }
113 }
114 }
115 else
116 {
117 String[] tokens = line.split("\\s+");
118 if (matrix == null)
119 {
120 long rows = Long.parseLong(tokens[0]);
121 long columns = Long.parseLong(tokens[1]);
122 int entries = Integer.parseInt(tokens[2]);
123 if (readerStrategy == null)
124 {
125 throw new IOException("read matrix size definition at line number " + lineNumber
126 + " before reading header line");
127 }
128 int cardinality = readerStrategy.cardinality(entries);
129 matrix = createMatrix2D(rows, columns, cardinality);
130 }
131 else
132 {
133 long row = Long.parseLong(tokens[0]);
134 long column = Long.parseLong(tokens[1]);
135 double value = Double.parseDouble(tokens[2]);
136 if (readerStrategy == null)
137 {
138 throw new IOException("read values at line number " + lineNumber
139 + " before reading header line");
140 }
141
142 readerStrategy.read(matrix, row - 1, column - 1, value);
143 }
144 }
145 lineNumber++;
146 }
147 }
148 catch (NumberFormatException e)
149 {
150 throw new IOException("caught NumberFormatException at line number " + lineNumber
151 + "\n" + e.getMessage());
152
153
154 }
155 catch (IndexOutOfBoundsException e)
156 {
157 throw new IOException("caught IndexOutOfBoundsException at line number " + lineNumber
158 + "\n" + e.getMessage());
159
160
161 }
162 finally
163 {
164 MatrixIOUtils.closeQuietly(reader);
165 }
166 if (matrix == null)
167 {
168 throw new IOException("could not create create matrix, check header and first non-comment line");
169 }
170 return matrix;
171 }
172
173
174
175
176 interface ReaderStrategy
177 {
178
179
180
181
182
183
184
185
186
187 int cardinality(int entries);
188
189
190
191
192
193
194
195
196
197
198 void read(Matrix2D<Double> matrix, long row, long column, double value);
199 }
200
201
202
203
204 private static class GeneralReaderStrategy implements ReaderStrategy
205 {
206
207 public int cardinality(final int entries)
208 {
209 return entries;
210 }
211
212
213 public void read(final Matrix2D<Double> matrix, final long row, final long column, final double value)
214 {
215 matrix.set(row, column, value);
216 }
217 }
218
219
220
221
222 private static class SymmetricReaderStrategy implements ReaderStrategy
223 {
224
225 public int cardinality(final int entries)
226 {
227 return (2 * entries);
228 }
229
230
231 public void read(final Matrix2D<Double> matrix, final long row, final long column, final double value)
232 {
233
234 matrix.set(row, column, value);
235
236 if (row != column)
237 {
238 matrix.set(column, row, value);
239 }
240 }
241 }
242
243
244
245
246 private static class SkewSymmetricReaderStrategy implements ReaderStrategy
247 {
248
249 public int cardinality(final int entries)
250 {
251 return (2 * entries);
252 }
253
254
255 public void read(final Matrix2D<Double> matrix, final long row, final long column, final double value)
256 {
257
258
259 if (row != column)
260 {
261
262 matrix.set(row, column, value);
263
264 matrix.set(column, row, -1.0d * value);
265 }
266 }
267 }
268
269
270
271
272 private static class HermitianReaderStrategy implements ReaderStrategy
273 {
274
275 public int cardinality(final int entries)
276 {
277 return entries;
278 }
279
280
281 public void read(final Matrix2D<Double> matrix, final long row, final long column, final double value)
282 {
283 matrix.set(row, column, value);
284 matrix.set(column, row, value);
285 }
286 }
287 }