Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:34:59

0001 // Copyright 2005 The Trustees of Indiana University.
0002 
0003 // Use, modification and distribution is subject to the Boost Software
0004 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
0005 // http://www.boost.org/LICENSE_1_0.txt)
0006 
0007 //  Authors: Alex Breuer
0008 //           Andrew Lumsdaine
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         // for a past the end iterator
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             // the 1000000 just happens to be about how many edges can be read
0138             // in 10s
0139             //     if( !(seen_edges % 1000000) && !process_id( pg ) && mode ==
0140             //     edge ) {
0141             //       std::cout << "read " << seen_edges << " edges" <<
0142             //       std::endl;
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         // don't expect this to do the right thing if you're not comparing
0273         // against a general past-the-end-iterator made with the default
0274         // constructor for dimacs_basic_reader
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         // don't expect this to do the right thing if you're not comparing
0333         // against a general past-the-end-iterator made with the default
0334         // constructor for dimacs_basic_reader
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 } // end namespace boost::graph
0375 #endif