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