annotate DEPENDENCIES/generic/include/boost/graph/read_dimacs.hpp @ 133:4acb5d8d80b6 tip

Don't fail environmental check if README.md exists (but .txt and no-suffix don't)
author Chris Cannam
date Tue, 30 Jul 2019 12:25:44 +0100
parents 2665513ce2d3
children
rev   line source
Chris@16 1 //=======================================================================
Chris@16 2 // Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
Chris@16 3 // Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee
Chris@16 4 //
Chris@16 5 // Distributed under the Boost Software License, Version 1.0. (See
Chris@16 6 // accompanying file LICENSE_1_0.txt or copy at
Chris@16 7 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 8 //=======================================================================
Chris@16 9
Chris@16 10 /*
Chris@16 11 Reads maximal flow problem in extended DIMACS format.
Chris@16 12 This works, but could use some polishing.
Chris@16 13 */
Chris@16 14
Chris@16 15 /* ----------------------------------------------------------------- */
Chris@16 16
Chris@16 17 #ifndef BOOST_GRAPH_READ_DIMACS_HPP
Chris@16 18 #define BOOST_GRAPH_READ_DIMACS_HPP
Chris@16 19
Chris@16 20 #include <vector>
Chris@16 21 #include <iostream>
Chris@16 22 #include <string>
Chris@16 23 #include <cstdio>
Chris@16 24 #include <cstring>
Chris@16 25 #include <cstdlib>
Chris@16 26
Chris@16 27 #include <boost/graph/graph_traits.hpp>
Chris@16 28
Chris@16 29 namespace boost {
Chris@16 30
Chris@16 31 namespace detail {
Chris@16 32
Chris@16 33 template <class Graph, class CapacityMap, class ReverseEdgeMap>
Chris@16 34 int read_dimacs_max_flow_internal(Graph& g,
Chris@16 35 CapacityMap capacity,
Chris@16 36 ReverseEdgeMap reverse_edge,
Chris@16 37 typename graph_traits<Graph>::vertex_descriptor& src,
Chris@16 38 typename graph_traits<Graph>::vertex_descriptor& sink,
Chris@16 39 std::istream& in,
Chris@16 40 bool require_source_and_sink,
Chris@16 41 const std::string& problem_type)
Chris@16 42 {
Chris@16 43 // const int MAXLINE = 100; /* max line length in the input file */
Chris@16 44 const int ARC_FIELDS = 3; /* no of fields in arc line */
Chris@16 45 const int NODE_FIELDS = 2; /* no of fields in node line */
Chris@16 46 const int P_FIELDS = 3; /* no of fields in problem line */
Chris@16 47
Chris@16 48 typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
Chris@16 49 typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
Chris@16 50
Chris@16 51 std::vector<vertex_descriptor> verts;
Chris@16 52
Chris@16 53 long m, n, /* number of edges and nodes */
Chris@16 54 i, head, tail, cap;
Chris@16 55
Chris@16 56 long no_lines=0, /* no of current input line */
Chris@16 57 no_plines=0, /* no of problem-lines */
Chris@16 58 no_nslines=0, /* no of node-source-lines */
Chris@16 59 no_nklines=0, /* no of node-source-lines */
Chris@16 60 no_alines=0; /* no of arc-lines */
Chris@16 61
Chris@16 62 std::string in_line; /* for reading input line */
Chris@16 63 char pr_type[4]; /* for reading type of the problem */
Chris@16 64 char nd; /* source (s) or sink (t) */
Chris@16 65
Chris@16 66 int k, /* temporary */
Chris@16 67 err_no; /* no of detected error */
Chris@16 68
Chris@16 69 /* -------------- error numbers & error messages ---------------- */
Chris@16 70 const int EN1 = 0;
Chris@16 71 const int EN2 = 1;
Chris@16 72 const int EN3 = 2;
Chris@16 73 const int EN4 = 3;
Chris@16 74 // const int EN6 = 4;
Chris@16 75 // const int EN10 = 5;
Chris@16 76 // const int EN7 = 6;
Chris@16 77 const int EN8 = 7;
Chris@16 78 const int EN9 = 8;
Chris@16 79 const int EN11 = 9;
Chris@16 80 const int EN12 = 10;
Chris@16 81 // const int EN13 = 11;
Chris@16 82 const int EN14 = 12;
Chris@16 83 const int EN16 = 13;
Chris@16 84 const int EN15 = 14;
Chris@16 85 const int EN17 = 15;
Chris@16 86 const int EN18 = 16;
Chris@16 87 const int EN21 = 17;
Chris@16 88 const int EN19 = 18;
Chris@16 89 const int EN20 = 19;
Chris@16 90 const int EN22 = 20;
Chris@16 91
Chris@16 92 static const char *err_message[] =
Chris@16 93 {
Chris@16 94 /* 0*/ "more than one problem line.",
Chris@16 95 /* 1*/ "wrong number of parameters in the problem line.",
Chris@16 96 /* 2*/ "it is not a Max Flow problem line.",
Chris@16 97 /* 3*/ "bad value of a parameter in the problem line.",
Chris@16 98 /* 4*/ "can't obtain enough memory to solve this problem.",
Chris@16 99 /* 5*/ "more than one line with the problem name.",
Chris@16 100 /* 6*/ "can't read problem name.",
Chris@16 101 /* 7*/ "problem description must be before node description.",
Chris@16 102 /* 8*/ "this parser doesn't support multiply sources and sinks.",
Chris@16 103 /* 9*/ "wrong number of parameters in the node line.",
Chris@16 104 /*10*/ "wrong value of parameters in the node line.",
Chris@16 105 /*11*/ " ",
Chris@16 106 /*12*/ "source and sink descriptions must be before arc descriptions.",
Chris@16 107 /*13*/ "too many arcs in the input.",
Chris@16 108 /*14*/ "wrong number of parameters in the arc line.",
Chris@16 109 /*15*/ "wrong value of parameters in the arc line.",
Chris@16 110 /*16*/ "unknown line type in the input.",
Chris@16 111 /*17*/ "reading error.",
Chris@16 112 /*18*/ "not enough arcs in the input.",
Chris@16 113 /*19*/ "source or sink doesn't have incident arcs.",
Chris@16 114 /*20*/ "can't read anything from the input file."
Chris@16 115 };
Chris@16 116 /* --------------------------------------------------------------- */
Chris@16 117
Chris@16 118 /* The main loop:
Chris@16 119 - reads the line of the input,
Chris@16 120 - analyses its type,
Chris@16 121 - checks correctness of parameters,
Chris@16 122 - puts data to the arrays,
Chris@16 123 - does service functions
Chris@16 124 */
Chris@16 125
Chris@16 126 while (std::getline(in, in_line)) {
Chris@16 127 ++no_lines;
Chris@16 128
Chris@16 129 switch (in_line[0]) {
Chris@16 130 case 'c': /* skip lines with comments */
Chris@16 131 case '\n': /* skip empty lines */
Chris@16 132 case '\0': /* skip empty lines at the end of file */
Chris@16 133 break;
Chris@16 134
Chris@16 135 case 'p': /* problem description */
Chris@16 136 if ( no_plines > 0 )
Chris@16 137 /* more than one problem line */
Chris@16 138 { err_no = EN1 ; goto error; }
Chris@16 139
Chris@16 140 no_plines = 1;
Chris@16 141
Chris@16 142 if (
Chris@16 143 /* reading problem line: type of problem, no of nodes, no of arcs */
Chris@16 144 std::sscanf ( in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m )
Chris@16 145 != P_FIELDS
Chris@16 146 )
Chris@16 147 /*wrong number of parameters in the problem line*/
Chris@16 148 { err_no = EN2; goto error; }
Chris@16 149
Chris@16 150 if ( pr_type != problem_type )
Chris@16 151 /*wrong problem type*/
Chris@16 152 { err_no = EN3; goto error; }
Chris@16 153
Chris@16 154 if ( n <= 0 || m <= 0 )
Chris@16 155 /*wrong value of no of arcs or nodes*/
Chris@16 156 { err_no = EN4; goto error; }
Chris@16 157
Chris@16 158 {
Chris@16 159 for (long vi = 0; vi < n; ++vi)
Chris@16 160 verts.push_back(add_vertex(g));
Chris@16 161 }
Chris@16 162 break;
Chris@16 163
Chris@16 164 case 'n': /* source(s) description */
Chris@16 165 if ( no_plines == 0 )
Chris@16 166 /* there was not problem line above */
Chris@16 167 { err_no = EN8; goto error; }
Chris@16 168
Chris@16 169 /* reading source or sink */
Chris@16 170 k = std::sscanf ( in_line.c_str(),"%*c %ld %c", &i, &nd );
Chris@16 171 --i; // index from 0
Chris@16 172 if ( k < NODE_FIELDS )
Chris@16 173 /* node line is incorrect */
Chris@16 174 { err_no = EN11; goto error; }
Chris@16 175
Chris@16 176 if ( i < 0 || i > n )
Chris@16 177 /* wrong value of node */
Chris@16 178 { err_no = EN12; goto error; }
Chris@16 179
Chris@16 180 switch (nd) {
Chris@16 181 case 's': /* source line */
Chris@16 182
Chris@16 183 if ( no_nslines != 0)
Chris@16 184 /* more than one source line */
Chris@16 185 { err_no = EN9; goto error; }
Chris@16 186
Chris@16 187 no_nslines = 1;
Chris@16 188 src = verts[i];
Chris@16 189 break;
Chris@16 190
Chris@16 191 case 't': /* sink line */
Chris@16 192
Chris@16 193 if ( no_nklines != 0)
Chris@16 194 /* more than one sink line */
Chris@16 195 { err_no = EN9; goto error; }
Chris@16 196
Chris@16 197 no_nklines = 1;
Chris@16 198 sink = verts[i];
Chris@16 199 break;
Chris@16 200
Chris@16 201 default:
Chris@16 202 /* wrong type of node-line */
Chris@16 203 err_no = EN12; goto error;
Chris@16 204 }
Chris@16 205 break;
Chris@16 206
Chris@16 207 case 'a': /* arc description */
Chris@16 208 if ( require_source_and_sink && (no_nslines == 0 || no_nklines == 0) )
Chris@16 209 /* there was not source and sink description above */
Chris@16 210 { err_no = EN14; goto error; }
Chris@16 211
Chris@16 212 if ( no_alines >= m )
Chris@16 213 /*too many arcs on input*/
Chris@16 214 { err_no = EN16; goto error; }
Chris@16 215
Chris@16 216 if (
Chris@16 217 /* reading an arc description */
Chris@16 218 std::sscanf ( in_line.c_str(),"%*c %ld %ld %ld",
Chris@16 219 &tail, &head, &cap )
Chris@16 220 != ARC_FIELDS
Chris@16 221 )
Chris@16 222 /* arc description is not correct */
Chris@16 223 { err_no = EN15; goto error; }
Chris@16 224
Chris@16 225 --tail; // index from 0, not 1
Chris@16 226 --head;
Chris@16 227 if ( tail < 0 || tail > n ||
Chris@16 228 head < 0 || head > n
Chris@16 229 )
Chris@16 230 /* wrong value of nodes */
Chris@16 231 { err_no = EN17; goto error; }
Chris@16 232
Chris@16 233 {
Chris@16 234 edge_descriptor e1, e2;
Chris@16 235 bool in1, in2;
Chris@16 236 boost::tie(e1, in1) = add_edge(verts[tail], verts[head], g);
Chris@16 237 boost::tie(e2, in2) = add_edge(verts[head], verts[tail], g);
Chris@16 238 if (!in1 || !in2) {
Chris@16 239 std::cerr << "unable to add edge (" << head << "," << tail << ")"
Chris@16 240 << std::endl;
Chris@16 241 return -1;
Chris@16 242 }
Chris@16 243 capacity[e1] = cap;
Chris@16 244 capacity[e2] = 0;
Chris@16 245 reverse_edge[e1] = e2;
Chris@16 246 reverse_edge[e2] = e1;
Chris@16 247 }
Chris@16 248 ++no_alines;
Chris@16 249 break;
Chris@16 250
Chris@16 251 default:
Chris@16 252 /* unknown type of line */
Chris@16 253 err_no = EN18; goto error;
Chris@16 254
Chris@16 255 } /* end of switch */
Chris@16 256 } /* end of input loop */
Chris@16 257
Chris@16 258 /* ----- all is red or error while reading ----- */
Chris@16 259
Chris@16 260 if ( in.eof() == 0 ) /* reading error */
Chris@16 261 { err_no=EN21; goto error; }
Chris@16 262
Chris@16 263 if ( no_lines == 0 ) /* empty input */
Chris@16 264 { err_no = EN22; goto error; }
Chris@16 265
Chris@16 266 if ( no_alines < m ) /* not enough arcs */
Chris@16 267 { err_no = EN19; goto error; }
Chris@16 268
Chris@16 269 if ( require_source_and_sink &&
Chris@16 270 (out_degree(src, g) == 0 || out_degree(sink, g) == 0) )
Chris@16 271 /* no arc goes out of the source */
Chris@16 272 { err_no = EN20; goto error; }
Chris@16 273
Chris@16 274 /* Thanks God! all is done */
Chris@16 275 return (0);
Chris@16 276
Chris@16 277 /* ---------------------------------- */
Chris@16 278 error: /* error found reading input */
Chris@16 279
Chris@16 280 std::printf ( "\nline %ld of input - %s\n",
Chris@16 281 no_lines, err_message[err_no] );
Chris@16 282
Chris@16 283 return -1;
Chris@16 284 }
Chris@16 285 /* -------------------- end of parser -------------------*/
Chris@16 286
Chris@16 287 } // namespace detail
Chris@16 288
Chris@16 289 template <class Graph, class CapacityMap, class ReverseEdgeMap>
Chris@16 290 int read_dimacs_max_flow(Graph& g,
Chris@16 291 CapacityMap capacity,
Chris@16 292 ReverseEdgeMap reverse_edge,
Chris@16 293 typename graph_traits<Graph>::vertex_descriptor& src,
Chris@16 294 typename graph_traits<Graph>::vertex_descriptor& sink,
Chris@16 295 std::istream& in = std::cin) {
Chris@16 296 return detail::read_dimacs_max_flow_internal(g, capacity, reverse_edge, src, sink, in, true, "max");
Chris@16 297 }
Chris@16 298
Chris@16 299 template <class Graph, class CapacityMap, class ReverseEdgeMap>
Chris@16 300 int read_dimacs_min_cut(Graph& g,
Chris@16 301 CapacityMap capacity,
Chris@16 302 ReverseEdgeMap reverse_edge,
Chris@16 303 std::istream& in = std::cin) {
Chris@16 304 typename graph_traits<Graph>::vertex_descriptor dummy_src, dummy_sink; // Not filled in
Chris@16 305 return detail::read_dimacs_max_flow_internal(g, capacity, reverse_edge, dummy_src, dummy_sink, in, false, "cut");
Chris@16 306 }
Chris@16 307
Chris@16 308 } // namespace boost
Chris@16 309
Chris@16 310 #endif // BOOST_GRAPH_READ_DIMACS_HPP