1 // Copyright 2005 The Trustees of Indiana University.
3 // Use, modification and distribution is subject to the Boost Software
4 // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
5 // http://www.boost.org/LICENSE_1_0.txt)
7 // Authors: Alex Breuer
9 #ifndef BOOST_GRAPH_DIMACS_HPP
10 #define BOOST_GRAPH_DIMACS_HPP
21 namespace boost
{ namespace graph
{
23 class dimacs_exception
: public std::exception
{};
25 class dimacs_basic_reader
{
27 typedef std::size_t vertices_size_type
;
28 typedef std::size_t edges_size_type
;
29 typedef double vertex_weight_type
;
30 typedef double edge_weight_type
;
31 typedef std::pair
<vertices_size_type
,
32 vertices_size_type
> edge_type
;
33 enum incr_mode
{edge
, edge_weight
};
35 dimacs_basic_reader( std::istream
& in
, bool want_weights
= true ) :
36 inpt( in
), seen_edges( 0 ), want_weights(want_weights
)
38 while( getline( inpt
, buf
) && !buf
.empty() && buf
[0] == 'c' );
41 boost::throw_exception(dimacs_exception());
44 std::stringstream
instr( buf
);
47 instr
>> junk
>> junk
>> num_vertices
>> num_edges
;
48 read_edge_weights
.push( -1 );
52 //for a past the end iterator
53 dimacs_basic_reader() : inpt( std::cin
), num_vertices( 0 ),
54 num_edges( 0 ), seen_edges( 0 ), want_weights(false) {}
56 edge_type
edge_deref() {
57 assert( !read_edges
.empty() );
58 return read_edges
.front();
61 inline edge_type
* edge_ref() {
62 assert( !read_edges
.empty() );
63 return &read_edges
.front();
66 inline edge_weight_type
edge_weight_deref() {
67 assert( !read_edge_weights
.empty() );
68 return read_edge_weights
.front();
71 inline dimacs_basic_reader
incr( incr_mode mode
) {
73 assert( !read_edges
.empty() );
76 else if( mode
== edge_weight
) {
77 assert( !read_edge_weights
.empty() );
78 read_edge_weights
.pop();
81 if( (mode
== edge
&& read_edges
.empty()) ||
82 (mode
== edge_weight
&& read_edge_weights
.empty() )) {
84 if( seen_edges
> num_edges
) {
85 boost::throw_exception(dimacs_exception());
88 while( getline( inpt
, buf
) && !buf
.empty() && buf
[0] == 'c' );
91 int source
, dest
, weight
;
92 read_edge_line((char*) buf
.c_str(), source
, dest
, weight
);
98 read_edges
.push( edge_type( source
, dest
) );
100 read_edge_weights
.push( weight
);
103 assert( read_edges
.size() < 100 );
104 assert( read_edge_weights
.size() < 100 );
107 // the 1000000 just happens to be about how many edges can be read in
109 // if( !(seen_edges % 1000000) && !process_id( pg ) && mode == edge ) {
110 // std::cout << "read " << seen_edges << " edges" << std::endl;
115 inline bool done_edges() {
116 return inpt
.eof() && read_edges
.size() == 0;
119 inline bool done_edge_weights() {
120 return inpt
.eof() && read_edge_weights
.size() == 0;
123 inline vertices_size_type
n_vertices() {
127 inline vertices_size_type
processed_edges() {
128 return seen_edges
- read_edges
.size();
131 inline vertices_size_type
processed_edge_weights() {
132 return seen_edges
- read_edge_weights
.size();
135 inline vertices_size_type
n_edges() {
140 bool read_edge_line(char *linebuf
, int &from
, int &to
, int &weight
)
142 char *fs
= NULL
, *ts
= NULL
, *ws
= NULL
;
143 char *tmp
= linebuf
+ 2;
146 if ('e' == linebuf
[0]) {
147 while (*tmp
!= '\n' && *tmp
!= '\0') {
156 if (NULL
== fs
|| NULL
== ts
) return false;
157 from
= atoi(fs
); to
= atoi(ts
); weight
= 0;
159 } else if ('a' == linebuf
[0]) {
160 while (*tmp
!= '\n' && *tmp
!= '\0') {
168 while (*tmp
!= '\n' && *tmp
!= '\0') {
176 while (*tmp
!= '\n' && *tmp
!= '\0') tmp
++;
178 if (fs
== NULL
|| ts
== NULL
|| ws
== NULL
) return false;
179 from
= atoi(fs
); to
= atoi(ts
) ;
180 if (want_weights
) weight
= atoi(ws
); else weight
= 0;
189 std::queue
<edge_type
> read_edges
;
190 std::queue
<edge_weight_type
> read_edge_weights
;
194 vertices_size_type num_vertices
, num_edges
, seen_edges
;
199 class dimacs_edge_iterator
{
201 typedef dimacs_basic_reader::edge_type edge_type
;
202 typedef dimacs_basic_reader::incr_mode incr_mode
;
204 typedef std::input_iterator_tag iterator_category
;
205 typedef edge_type value_type
;
206 typedef value_type reference
;
207 typedef edge_type
* pointer
;
208 typedef std::ptrdiff_t difference_type
;
210 dimacs_edge_iterator( T
& reader
) :
213 inline dimacs_edge_iterator
& operator++() {
214 reader
.incr( dimacs_basic_reader::edge
);
218 inline edge_type
operator*() {
219 return reader
.edge_deref();
222 inline edge_type
* operator->() {
223 return reader
.edge_ref();
226 // don't expect this to do the right thing if you're not comparing against a
227 // general past-the-end-iterator made with the default constructor for
228 // dimacs_basic_reader
229 inline bool operator==( dimacs_edge_iterator arg
) {
230 if( reader
.n_vertices() == 0 ) {
231 return arg
.reader
.done_edges();
233 else if( arg
.reader
.n_vertices() == 0 ) {
234 return reader
.done_edges();
242 inline bool operator!=( dimacs_edge_iterator arg
) {
243 if( reader
.n_vertices() == 0 ) {
244 return !arg
.reader
.done_edges();
246 else if( arg
.reader
.n_vertices() == 0 ) {
247 return !reader
.done_edges();
260 class dimacs_edge_weight_iterator
{
262 typedef dimacs_basic_reader::edge_weight_type edge_weight_type
;
263 typedef dimacs_basic_reader::incr_mode incr_mode
;
265 dimacs_edge_weight_iterator( T
& reader
) : reader( reader
) {}
267 inline dimacs_edge_weight_iterator
& operator++() {
268 reader
.incr( dimacs_basic_reader::edge_weight
);
272 inline edge_weight_type
operator*() {
273 return reader
.edge_weight_deref();
276 // don't expect this to do the right thing if you're not comparing against a
277 // general past-the-end-iterator made with the default constructor for
278 // dimacs_basic_reader
279 inline bool operator==( dimacs_edge_weight_iterator arg
) {
280 if( reader
.n_vertices() == 0 ) {
281 return arg
.reader
.done_edge_weights();
283 else if( arg
.reader
.n_vertices() == 0 ) {
284 return reader
.done_edge_weights();
292 inline bool operator!=( dimacs_edge_weight_iterator arg
) {
293 if( reader
.n_vertices() == 0 ) {
294 return !arg
.reader
.done_edge_weights();
296 else if( arg
.reader
.n_vertices() == 0 ) {
297 return !reader
.done_edge_weights();
308 } } // end namespace boost::graph