File indexing completed on 2025-01-18 09:37:26
0001
0002
0003
0004
0005
0006
0007
0008
0009 #ifndef BOOST_GRAPH_DIMACS_HPP
0010 #define BOOST_GRAPH_DIMACS_HPP
0011
0012 #include <string>
0013 #include <sstream>
0014 #include <iostream>
0015 #include <fstream>
0016 #include <iterator>
0017 #include <exception>
0018 #include <vector>
0019 #include <queue>
0020 #include <boost/assert.hpp>
0021
0022 namespace boost
0023 {
0024 namespace graph
0025 {
0026
0027 class BOOST_SYMBOL_VISIBLE dimacs_exception : public std::exception
0028 {
0029 };
0030
0031 class dimacs_basic_reader
0032 {
0033 public:
0034 typedef std::size_t vertices_size_type;
0035 typedef std::size_t edges_size_type;
0036 typedef double vertex_weight_type;
0037 typedef double edge_weight_type;
0038 typedef std::pair< vertices_size_type, vertices_size_type > edge_type;
0039 enum incr_mode
0040 {
0041 edge,
0042 edge_weight
0043 };
0044
0045 dimacs_basic_reader(std::istream& in, bool want_weights = true)
0046 : inpt(in), seen_edges(0), want_weights(want_weights)
0047 {
0048 while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c')
0049 ;
0050
0051 if (buf[0] != 'p')
0052 {
0053 boost::throw_exception(dimacs_exception());
0054 }
0055
0056 std::stringstream instr(buf);
0057 std::string junk;
0058
0059 instr >> junk >> junk >> num_vertices >> num_edges;
0060 read_edge_weights.push(-1);
0061 incr(edge_weight);
0062 }
0063
0064
0065 dimacs_basic_reader()
0066 : inpt(std::cin)
0067 , num_vertices(0)
0068 , num_edges(0)
0069 , seen_edges(0)
0070 , want_weights(false)
0071 {
0072 }
0073
0074 edge_type edge_deref()
0075 {
0076 BOOST_ASSERT(!read_edges.empty());
0077 return read_edges.front();
0078 }
0079
0080 inline edge_type* edge_ref()
0081 {
0082 BOOST_ASSERT(!read_edges.empty());
0083 return &read_edges.front();
0084 }
0085
0086 inline edge_weight_type edge_weight_deref()
0087 {
0088 BOOST_ASSERT(!read_edge_weights.empty());
0089 return read_edge_weights.front();
0090 }
0091
0092 inline dimacs_basic_reader incr(incr_mode mode)
0093 {
0094 if (mode == edge)
0095 {
0096 BOOST_ASSERT(!read_edges.empty());
0097 read_edges.pop();
0098 }
0099 else if (mode == edge_weight)
0100 {
0101 BOOST_ASSERT(!read_edge_weights.empty());
0102 read_edge_weights.pop();
0103 }
0104
0105 if ((mode == edge && read_edges.empty())
0106 || (mode == edge_weight && read_edge_weights.empty()))
0107 {
0108
0109 if (seen_edges > num_edges)
0110 {
0111 boost::throw_exception(dimacs_exception());
0112 }
0113
0114 while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c')
0115 ;
0116
0117 if (!inpt.eof())
0118 {
0119 int source, dest, weight;
0120 read_edge_line((char*)buf.c_str(), source, dest, weight);
0121
0122 seen_edges++;
0123 source--;
0124 dest--;
0125
0126 read_edges.push(edge_type(source, dest));
0127 if (want_weights)
0128 {
0129 read_edge_weights.push(weight);
0130 }
0131 }
0132 BOOST_ASSERT(read_edges.size() < 100);
0133 BOOST_ASSERT(read_edge_weights.size() < 100);
0134 }
0135
0136
0137
0138
0139
0140
0141
0142
0143 return *this;
0144 }
0145
0146 inline bool done_edges()
0147 {
0148 return inpt.eof() && read_edges.size() == 0;
0149 }
0150
0151 inline bool done_edge_weights()
0152 {
0153 return inpt.eof() && read_edge_weights.size() == 0;
0154 }
0155
0156 inline vertices_size_type n_vertices() { return num_vertices; }
0157
0158 inline vertices_size_type processed_edges()
0159 {
0160 return seen_edges - read_edges.size();
0161 }
0162
0163 inline vertices_size_type processed_edge_weights()
0164 {
0165 return seen_edges - read_edge_weights.size();
0166 }
0167
0168 inline vertices_size_type n_edges() { return num_edges; }
0169
0170 protected:
0171 bool read_edge_line(char* linebuf, int& from, int& to, int& weight)
0172 {
0173 char *fs = NULL, *ts = NULL, *ws = NULL;
0174 char* tmp = linebuf + 2;
0175
0176 fs = tmp;
0177 if ('e' == linebuf[0])
0178 {
0179 while (*tmp != '\n' && *tmp != '\0')
0180 {
0181 if (*tmp == ' ')
0182 {
0183 *tmp = '\0';
0184 ts = ++tmp;
0185 break;
0186 }
0187 tmp++;
0188 }
0189 *tmp = '\0';
0190 if (NULL == fs || NULL == ts)
0191 return false;
0192 from = atoi(fs);
0193 to = atoi(ts);
0194 weight = 0;
0195 }
0196 else if ('a' == linebuf[0])
0197 {
0198 while (*tmp != '\n' && *tmp != '\0')
0199 {
0200 if (*tmp == ' ')
0201 {
0202 *tmp = '\0';
0203 ts = ++tmp;
0204 break;
0205 }
0206 tmp++;
0207 }
0208 while (*tmp != '\n' && *tmp != '\0')
0209 {
0210 if (*tmp == ' ')
0211 {
0212 *tmp = '\0';
0213 ws = ++tmp;
0214 break;
0215 }
0216 tmp++;
0217 }
0218 while (*tmp != '\n' && *tmp != '\0')
0219 tmp++;
0220 *tmp = '\0';
0221 if (fs == NULL || ts == NULL || ws == NULL)
0222 return false;
0223 from = atoi(fs);
0224 to = atoi(ts);
0225 if (want_weights)
0226 weight = atoi(ws);
0227 else
0228 weight = 0;
0229 }
0230 else
0231 {
0232 return false;
0233 }
0234
0235 return true;
0236 }
0237
0238 std::queue< edge_type > read_edges;
0239 std::queue< edge_weight_type > read_edge_weights;
0240
0241 std::istream& inpt;
0242 std::string buf;
0243 vertices_size_type num_vertices, num_edges, seen_edges;
0244 bool want_weights;
0245 };
0246
0247 template < typename T > class dimacs_edge_iterator
0248 {
0249 public:
0250 typedef dimacs_basic_reader::edge_type edge_type;
0251 typedef dimacs_basic_reader::incr_mode incr_mode;
0252
0253 typedef std::input_iterator_tag iterator_category;
0254 typedef edge_type value_type;
0255 typedef value_type reference;
0256 typedef edge_type* pointer;
0257 typedef std::ptrdiff_t difference_type;
0258
0259 dimacs_edge_iterator(T& reader) : reader(reader) {}
0260
0261 inline dimacs_edge_iterator& operator++()
0262 {
0263 reader.incr(dimacs_basic_reader::edge);
0264 return *this;
0265 }
0266
0267 inline edge_type operator*() { return reader.edge_deref(); }
0268
0269 inline edge_type* operator->() { return reader.edge_ref(); }
0270
0271
0272
0273
0274 inline bool operator==(dimacs_edge_iterator arg)
0275 {
0276 if (reader.n_vertices() == 0)
0277 {
0278 return arg.reader.done_edges();
0279 }
0280 else if (arg.reader.n_vertices() == 0)
0281 {
0282 return reader.done_edges();
0283 }
0284 else
0285 {
0286 return false;
0287 }
0288 return false;
0289 }
0290
0291 inline bool operator!=(dimacs_edge_iterator arg)
0292 {
0293 if (reader.n_vertices() == 0)
0294 {
0295 return !arg.reader.done_edges();
0296 }
0297 else if (arg.reader.n_vertices() == 0)
0298 {
0299 return !reader.done_edges();
0300 }
0301 else
0302 {
0303 return true;
0304 }
0305 return true;
0306 }
0307
0308 private:
0309 T& reader;
0310 };
0311
0312 template < typename T > class dimacs_edge_weight_iterator
0313 {
0314 public:
0315 typedef dimacs_basic_reader::edge_weight_type edge_weight_type;
0316 typedef dimacs_basic_reader::incr_mode incr_mode;
0317
0318 dimacs_edge_weight_iterator(T& reader) : reader(reader) {}
0319
0320 inline dimacs_edge_weight_iterator& operator++()
0321 {
0322 reader.incr(dimacs_basic_reader::edge_weight);
0323 return *this;
0324 }
0325
0326 inline edge_weight_type operator*()
0327 {
0328 return reader.edge_weight_deref();
0329 }
0330
0331
0332
0333
0334 inline bool operator==(dimacs_edge_weight_iterator arg)
0335 {
0336 if (reader.n_vertices() == 0)
0337 {
0338 return arg.reader.done_edge_weights();
0339 }
0340 else if (arg.reader.n_vertices() == 0)
0341 {
0342 return reader.done_edge_weights();
0343 }
0344 else
0345 {
0346 return false;
0347 }
0348 return false;
0349 }
0350
0351 inline bool operator!=(dimacs_edge_weight_iterator arg)
0352 {
0353 if (reader.n_vertices() == 0)
0354 {
0355 return !arg.reader.done_edge_weights();
0356 }
0357 else if (arg.reader.n_vertices() == 0)
0358 {
0359 return !reader.done_edge_weights();
0360 }
0361 else
0362 {
0363 return true;
0364 }
0365 return true;
0366 }
0367
0368 private:
0369 T& reader;
0370 };
0371
0372 }
0373 }
0374 #endif