lemongraph 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.yardopts +8 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/ext/lemon-1.3.1/AUTHORS +26 -0
- data/ext/lemon-1.3.1/CMakeLists.txt +371 -0
- data/ext/lemon-1.3.1/INSTALL +167 -0
- data/ext/lemon-1.3.1/LICENSE +32 -0
- data/ext/lemon-1.3.1/NEWS +337 -0
- data/ext/lemon-1.3.1/README +50 -0
- data/ext/lemon-1.3.1/cmake/FindCOIN.cmake +110 -0
- data/ext/lemon-1.3.1/cmake/FindGLPK.cmake +55 -0
- data/ext/lemon-1.3.1/cmake/FindGhostscript.cmake +10 -0
- data/ext/lemon-1.3.1/cmake/FindILOG.cmake +102 -0
- data/ext/lemon-1.3.1/cmake/FindSOPLEX.cmake +23 -0
- data/ext/lemon-1.3.1/cmake/LEMONConfig.cmake.in +13 -0
- data/ext/lemon-1.3.1/cmake/nsis/lemon.ico +0 -0
- data/ext/lemon-1.3.1/cmake/nsis/uninstall.ico +0 -0
- data/ext/lemon-1.3.1/cmake/version.cmake +1 -0
- data/ext/lemon-1.3.1/cmake/version.cmake.in +1 -0
- data/ext/lemon-1.3.1/contrib/CMakeLists.txt +19 -0
- data/ext/lemon-1.3.1/lemon/CMakeLists.txt +91 -0
- data/ext/lemon-1.3.1/lemon/adaptors.h +3638 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.cc +474 -0
- data/ext/lemon-1.3.1/lemon/arg_parser.h +440 -0
- data/ext/lemon-1.3.1/lemon/assert.h +214 -0
- data/ext/lemon-1.3.1/lemon/base.cc +37 -0
- data/ext/lemon-1.3.1/lemon/bellman_ford.h +1116 -0
- data/ext/lemon-1.3.1/lemon/bfs.h +1754 -0
- data/ext/lemon-1.3.1/lemon/bin_heap.h +347 -0
- data/ext/lemon-1.3.1/lemon/binomial_heap.h +445 -0
- data/ext/lemon-1.3.1/lemon/bits/alteration_notifier.h +472 -0
- data/ext/lemon-1.3.1/lemon/bits/array_map.h +351 -0
- data/ext/lemon-1.3.1/lemon/bits/bezier.h +174 -0
- data/ext/lemon-1.3.1/lemon/bits/default_map.h +182 -0
- data/ext/lemon-1.3.1/lemon/bits/edge_set_extender.h +627 -0
- data/ext/lemon-1.3.1/lemon/bits/enable_if.h +131 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_adaptor_extender.h +401 -0
- data/ext/lemon-1.3.1/lemon/bits/graph_extender.h +1332 -0
- data/ext/lemon-1.3.1/lemon/bits/lock.h +65 -0
- data/ext/lemon-1.3.1/lemon/bits/map_extender.h +332 -0
- data/ext/lemon-1.3.1/lemon/bits/path_dump.h +177 -0
- data/ext/lemon-1.3.1/lemon/bits/solver_bits.h +194 -0
- data/ext/lemon-1.3.1/lemon/bits/traits.h +388 -0
- data/ext/lemon-1.3.1/lemon/bits/variant.h +494 -0
- data/ext/lemon-1.3.1/lemon/bits/vector_map.h +244 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.cc +166 -0
- data/ext/lemon-1.3.1/lemon/bits/windows.h +44 -0
- data/ext/lemon-1.3.1/lemon/bucket_heap.h +594 -0
- data/ext/lemon-1.3.1/lemon/capacity_scaling.h +1014 -0
- data/ext/lemon-1.3.1/lemon/cbc.cc +460 -0
- data/ext/lemon-1.3.1/lemon/cbc.h +129 -0
- data/ext/lemon-1.3.1/lemon/christofides_tsp.h +254 -0
- data/ext/lemon-1.3.1/lemon/circulation.h +807 -0
- data/ext/lemon-1.3.1/lemon/clp.cc +464 -0
- data/ext/lemon-1.3.1/lemon/clp.h +164 -0
- data/ext/lemon-1.3.1/lemon/color.cc +44 -0
- data/ext/lemon-1.3.1/lemon/color.h +204 -0
- data/ext/lemon-1.3.1/lemon/concept_check.h +77 -0
- data/ext/lemon-1.3.1/lemon/concepts/bpgraph.h +1029 -0
- data/ext/lemon-1.3.1/lemon/concepts/digraph.h +491 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph.h +788 -0
- data/ext/lemon-1.3.1/lemon/concepts/graph_components.h +2134 -0
- data/ext/lemon-1.3.1/lemon/concepts/heap.h +324 -0
- data/ext/lemon-1.3.1/lemon/concepts/maps.h +223 -0
- data/ext/lemon-1.3.1/lemon/concepts/path.h +312 -0
- data/ext/lemon-1.3.1/lemon/config.h.in +22 -0
- data/ext/lemon-1.3.1/lemon/connectivity.h +1688 -0
- data/ext/lemon-1.3.1/lemon/core.h +2506 -0
- data/ext/lemon-1.3.1/lemon/cost_scaling.h +1607 -0
- data/ext/lemon-1.3.1/lemon/counter.h +249 -0
- data/ext/lemon-1.3.1/lemon/cplex.cc +994 -0
- data/ext/lemon-1.3.1/lemon/cplex.h +292 -0
- data/ext/lemon-1.3.1/lemon/cycle_canceling.h +1230 -0
- data/ext/lemon-1.3.1/lemon/dfs.h +1637 -0
- data/ext/lemon-1.3.1/lemon/dheap.h +352 -0
- data/ext/lemon-1.3.1/lemon/dijkstra.h +1303 -0
- data/ext/lemon-1.3.1/lemon/dim2.h +726 -0
- data/ext/lemon-1.3.1/lemon/dimacs.h +448 -0
- data/ext/lemon-1.3.1/lemon/edge_set.h +1420 -0
- data/ext/lemon-1.3.1/lemon/edmonds_karp.h +556 -0
- data/ext/lemon-1.3.1/lemon/elevator.h +982 -0
- data/ext/lemon-1.3.1/lemon/error.h +276 -0
- data/ext/lemon-1.3.1/lemon/euler.h +287 -0
- data/ext/lemon-1.3.1/lemon/fib_heap.h +475 -0
- data/ext/lemon-1.3.1/lemon/fractional_matching.h +2139 -0
- data/ext/lemon-1.3.1/lemon/full_graph.h +1082 -0
- data/ext/lemon-1.3.1/lemon/glpk.cc +1012 -0
- data/ext/lemon-1.3.1/lemon/glpk.h +263 -0
- data/ext/lemon-1.3.1/lemon/gomory_hu.h +568 -0
- data/ext/lemon-1.3.1/lemon/graph_to_eps.h +1186 -0
- data/ext/lemon-1.3.1/lemon/greedy_tsp.h +251 -0
- data/ext/lemon-1.3.1/lemon/grid_graph.h +699 -0
- data/ext/lemon-1.3.1/lemon/grosso_locatelli_pullan_mc.h +840 -0
- data/ext/lemon-1.3.1/lemon/hao_orlin.h +1015 -0
- data/ext/lemon-1.3.1/lemon/hartmann_orlin_mmc.h +654 -0
- data/ext/lemon-1.3.1/lemon/howard_mmc.h +651 -0
- data/ext/lemon-1.3.1/lemon/hypercube_graph.h +459 -0
- data/ext/lemon-1.3.1/lemon/insertion_tsp.h +533 -0
- data/ext/lemon-1.3.1/lemon/karp_mmc.h +590 -0
- data/ext/lemon-1.3.1/lemon/kruskal.h +324 -0
- data/ext/lemon-1.3.1/lemon/lemon.pc.in +10 -0
- data/ext/lemon-1.3.1/lemon/lgf_reader.h +3854 -0
- data/ext/lemon-1.3.1/lemon/lgf_writer.h +2687 -0
- data/ext/lemon-1.3.1/lemon/list_graph.h +2510 -0
- data/ext/lemon-1.3.1/lemon/lp.h +95 -0
- data/ext/lemon-1.3.1/lemon/lp_base.cc +30 -0
- data/ext/lemon-1.3.1/lemon/lp_base.h +2147 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.cc +143 -0
- data/ext/lemon-1.3.1/lemon/lp_skeleton.h +234 -0
- data/ext/lemon-1.3.1/lemon/maps.h +4057 -0
- data/ext/lemon-1.3.1/lemon/matching.h +3505 -0
- data/ext/lemon-1.3.1/lemon/math.h +77 -0
- data/ext/lemon-1.3.1/lemon/max_cardinality_search.h +794 -0
- data/ext/lemon-1.3.1/lemon/min_cost_arborescence.h +808 -0
- data/ext/lemon-1.3.1/lemon/nagamochi_ibaraki.h +702 -0
- data/ext/lemon-1.3.1/lemon/nauty_reader.h +113 -0
- data/ext/lemon-1.3.1/lemon/nearest_neighbor_tsp.h +238 -0
- data/ext/lemon-1.3.1/lemon/network_simplex.h +1659 -0
- data/ext/lemon-1.3.1/lemon/opt2_tsp.h +367 -0
- data/ext/lemon-1.3.1/lemon/pairing_heap.h +474 -0
- data/ext/lemon-1.3.1/lemon/path.h +1164 -0
- data/ext/lemon-1.3.1/lemon/planarity.h +2754 -0
- data/ext/lemon-1.3.1/lemon/preflow.h +985 -0
- data/ext/lemon-1.3.1/lemon/quad_heap.h +343 -0
- data/ext/lemon-1.3.1/lemon/radix_heap.h +438 -0
- data/ext/lemon-1.3.1/lemon/radix_sort.h +487 -0
- data/ext/lemon-1.3.1/lemon/random.cc +29 -0
- data/ext/lemon-1.3.1/lemon/random.h +1005 -0
- data/ext/lemon-1.3.1/lemon/smart_graph.h +1344 -0
- data/ext/lemon-1.3.1/lemon/soplex.cc +465 -0
- data/ext/lemon-1.3.1/lemon/soplex.h +158 -0
- data/ext/lemon-1.3.1/lemon/static_graph.h +476 -0
- data/ext/lemon-1.3.1/lemon/suurballe.h +776 -0
- data/ext/lemon-1.3.1/lemon/time_measure.h +610 -0
- data/ext/lemon-1.3.1/lemon/tolerance.h +242 -0
- data/ext/lemon-1.3.1/lemon/unionfind.h +1824 -0
- data/ext/lemon-1.3.1/scripts/unify-sources.sh +390 -0
- data/ext/lemon-1.3.1/scripts/valgrind-wrapper.sh +22 -0
- data/ext/lemongraph/arc_map.cc +1007 -0
- data/ext/lemongraph/digraph.cc +282 -0
- data/ext/lemongraph/digraph_arc.cc +153 -0
- data/ext/lemongraph/digraph_node.cc +277 -0
- data/ext/lemongraph/edge_map.cc +770 -0
- data/ext/lemongraph/extconf.rb +53 -0
- data/ext/lemongraph/graph.cc +351 -0
- data/ext/lemongraph/graph_arc.cc +95 -0
- data/ext/lemongraph/graph_edge.cc +153 -0
- data/ext/lemongraph/graph_item.cc +76 -0
- data/ext/lemongraph/graph_node.cc +321 -0
- data/ext/lemongraph/lemongraph.cc +260 -0
- data/ext/lemongraph/lemongraph.hh +295 -0
- data/ext/lemongraph/lemongraph.map +6 -0
- data/ext/lemongraph/lemongraph_export.hh +31 -0
- data/ext/lemongraph/node_map.cc +1011 -0
- data/lemongraph.gemspec +176 -0
- data/lib/lemongraph/graphviz.rb +240 -0
- data/lib/lemongraph/version.rb +4 -0
- data/lib/lemongraph.rb +21 -0
- data/samples/lemondeps.rb +38 -0
- metadata +202 -0
|
@@ -0,0 +1,3854 @@
|
|
|
1
|
+
/* -*- mode: C++; indent-tabs-mode: nil; -*-
|
|
2
|
+
*
|
|
3
|
+
* This file is a part of LEMON, a generic C++ optimization library.
|
|
4
|
+
*
|
|
5
|
+
* Copyright (C) 2003-2013
|
|
6
|
+
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
|
7
|
+
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
|
8
|
+
*
|
|
9
|
+
* Permission to use, modify and distribute this software is granted
|
|
10
|
+
* provided that this copyright notice appears in all copies. For
|
|
11
|
+
* precise terms see the accompanying LICENSE file.
|
|
12
|
+
*
|
|
13
|
+
* This software is provided "AS IS" with no warranty of any kind,
|
|
14
|
+
* express or implied, and with no claim as to its suitability for any
|
|
15
|
+
* purpose.
|
|
16
|
+
*
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
///\ingroup lemon_io
|
|
20
|
+
///\file
|
|
21
|
+
///\brief \ref lgf-format "LEMON Graph Format" reader.
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
#ifndef LEMON_LGF_READER_H
|
|
25
|
+
#define LEMON_LGF_READER_H
|
|
26
|
+
|
|
27
|
+
#include <iostream>
|
|
28
|
+
#include <fstream>
|
|
29
|
+
#include <sstream>
|
|
30
|
+
|
|
31
|
+
#include <set>
|
|
32
|
+
#include <map>
|
|
33
|
+
|
|
34
|
+
#include <lemon/core.h>
|
|
35
|
+
|
|
36
|
+
#include <lemon/lgf_writer.h>
|
|
37
|
+
|
|
38
|
+
#include <lemon/concept_check.h>
|
|
39
|
+
#include <lemon/concepts/maps.h>
|
|
40
|
+
|
|
41
|
+
namespace lemon {
|
|
42
|
+
|
|
43
|
+
namespace _reader_bits {
|
|
44
|
+
|
|
45
|
+
template <typename Value>
|
|
46
|
+
struct DefaultConverter {
|
|
47
|
+
Value operator()(const std::string& str) {
|
|
48
|
+
std::istringstream is(str);
|
|
49
|
+
Value value;
|
|
50
|
+
if (!(is >> value)) {
|
|
51
|
+
throw FormatError("Cannot read token");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
char c;
|
|
55
|
+
if (is >> std::ws >> c) {
|
|
56
|
+
throw FormatError("Remaining characters in token");
|
|
57
|
+
}
|
|
58
|
+
return value;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
template <>
|
|
63
|
+
struct DefaultConverter<std::string> {
|
|
64
|
+
std::string operator()(const std::string& str) {
|
|
65
|
+
return str;
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
template <typename _Item>
|
|
70
|
+
class MapStorageBase {
|
|
71
|
+
public:
|
|
72
|
+
typedef _Item Item;
|
|
73
|
+
|
|
74
|
+
public:
|
|
75
|
+
MapStorageBase() {}
|
|
76
|
+
virtual ~MapStorageBase() {}
|
|
77
|
+
|
|
78
|
+
virtual void set(const Item& item, const std::string& value) = 0;
|
|
79
|
+
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
template <typename _Item, typename _Map,
|
|
83
|
+
typename _Converter = DefaultConverter<typename _Map::Value> >
|
|
84
|
+
class MapStorage : public MapStorageBase<_Item> {
|
|
85
|
+
public:
|
|
86
|
+
typedef _Map Map;
|
|
87
|
+
typedef _Converter Converter;
|
|
88
|
+
typedef _Item Item;
|
|
89
|
+
|
|
90
|
+
private:
|
|
91
|
+
Map& _map;
|
|
92
|
+
Converter _converter;
|
|
93
|
+
|
|
94
|
+
public:
|
|
95
|
+
MapStorage(Map& map, const Converter& converter = Converter())
|
|
96
|
+
: _map(map), _converter(converter) {}
|
|
97
|
+
virtual ~MapStorage() {}
|
|
98
|
+
|
|
99
|
+
virtual void set(const Item& item ,const std::string& value) {
|
|
100
|
+
_map.set(item, _converter(value));
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
template <typename _GR, bool _dir, typename _Map,
|
|
105
|
+
typename _Converter = DefaultConverter<typename _Map::Value> >
|
|
106
|
+
class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
|
|
107
|
+
public:
|
|
108
|
+
typedef _Map Map;
|
|
109
|
+
typedef _Converter Converter;
|
|
110
|
+
typedef _GR GR;
|
|
111
|
+
typedef typename GR::Edge Item;
|
|
112
|
+
static const bool dir = _dir;
|
|
113
|
+
|
|
114
|
+
private:
|
|
115
|
+
const GR& _graph;
|
|
116
|
+
Map& _map;
|
|
117
|
+
Converter _converter;
|
|
118
|
+
|
|
119
|
+
public:
|
|
120
|
+
GraphArcMapStorage(const GR& graph, Map& map,
|
|
121
|
+
const Converter& converter = Converter())
|
|
122
|
+
: _graph(graph), _map(map), _converter(converter) {}
|
|
123
|
+
virtual ~GraphArcMapStorage() {}
|
|
124
|
+
|
|
125
|
+
virtual void set(const Item& item ,const std::string& value) {
|
|
126
|
+
_map.set(_graph.direct(item, dir), _converter(value));
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
class ValueStorageBase {
|
|
131
|
+
public:
|
|
132
|
+
ValueStorageBase() {}
|
|
133
|
+
virtual ~ValueStorageBase() {}
|
|
134
|
+
|
|
135
|
+
virtual void set(const std::string&) = 0;
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
template <typename _Value, typename _Converter = DefaultConverter<_Value> >
|
|
139
|
+
class ValueStorage : public ValueStorageBase {
|
|
140
|
+
public:
|
|
141
|
+
typedef _Value Value;
|
|
142
|
+
typedef _Converter Converter;
|
|
143
|
+
|
|
144
|
+
private:
|
|
145
|
+
Value& _value;
|
|
146
|
+
Converter _converter;
|
|
147
|
+
|
|
148
|
+
public:
|
|
149
|
+
ValueStorage(Value& value, const Converter& converter = Converter())
|
|
150
|
+
: _value(value), _converter(converter) {}
|
|
151
|
+
|
|
152
|
+
virtual void set(const std::string& value) {
|
|
153
|
+
_value = _converter(value);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
template <typename Value,
|
|
158
|
+
typename Map = std::map<std::string, Value> >
|
|
159
|
+
struct MapLookUpConverter {
|
|
160
|
+
const Map& _map;
|
|
161
|
+
|
|
162
|
+
MapLookUpConverter(const Map& map)
|
|
163
|
+
: _map(map) {}
|
|
164
|
+
|
|
165
|
+
Value operator()(const std::string& str) {
|
|
166
|
+
typename Map::const_iterator it = _map.find(str);
|
|
167
|
+
if (it == _map.end()) {
|
|
168
|
+
std::ostringstream msg;
|
|
169
|
+
msg << "Item not found: " << str;
|
|
170
|
+
throw FormatError(msg.str());
|
|
171
|
+
}
|
|
172
|
+
return it->second;
|
|
173
|
+
}
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
template <typename Value,
|
|
177
|
+
typename Map1 = std::map<std::string, Value>,
|
|
178
|
+
typename Map2 = std::map<std::string, Value> >
|
|
179
|
+
struct DoubleMapLookUpConverter {
|
|
180
|
+
const Map1& _map1;
|
|
181
|
+
const Map2& _map2;
|
|
182
|
+
|
|
183
|
+
DoubleMapLookUpConverter(const Map1& map1, const Map2& map2)
|
|
184
|
+
: _map1(map1), _map2(map2) {}
|
|
185
|
+
|
|
186
|
+
Value operator()(const std::string& str) {
|
|
187
|
+
typename Map1::const_iterator it1 = _map1.find(str);
|
|
188
|
+
typename Map2::const_iterator it2 = _map2.find(str);
|
|
189
|
+
if (it1 == _map1.end()) {
|
|
190
|
+
if (it2 == _map2.end()) {
|
|
191
|
+
std::ostringstream msg;
|
|
192
|
+
msg << "Item not found: " << str;
|
|
193
|
+
throw FormatError(msg.str());
|
|
194
|
+
} else {
|
|
195
|
+
return it2->second;
|
|
196
|
+
}
|
|
197
|
+
} else {
|
|
198
|
+
if (it2 == _map2.end()) {
|
|
199
|
+
return it1->second;
|
|
200
|
+
} else {
|
|
201
|
+
std::ostringstream msg;
|
|
202
|
+
msg << "Item is ambigous: " << str;
|
|
203
|
+
throw FormatError(msg.str());
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
template <typename GR>
|
|
210
|
+
struct GraphArcLookUpConverter {
|
|
211
|
+
const GR& _graph;
|
|
212
|
+
const std::map<std::string, typename GR::Edge>& _map;
|
|
213
|
+
|
|
214
|
+
GraphArcLookUpConverter(const GR& graph,
|
|
215
|
+
const std::map<std::string,
|
|
216
|
+
typename GR::Edge>& map)
|
|
217
|
+
: _graph(graph), _map(map) {}
|
|
218
|
+
|
|
219
|
+
typename GR::Arc operator()(const std::string& str) {
|
|
220
|
+
if (str.empty() || (str[0] != '+' && str[0] != '-')) {
|
|
221
|
+
throw FormatError("Item must start with '+' or '-'");
|
|
222
|
+
}
|
|
223
|
+
typename std::map<std::string, typename GR::Edge>
|
|
224
|
+
::const_iterator it = _map.find(str.substr(1));
|
|
225
|
+
if (it == _map.end()) {
|
|
226
|
+
throw FormatError("Item not found");
|
|
227
|
+
}
|
|
228
|
+
return _graph.direct(it->second, str[0] == '+');
|
|
229
|
+
}
|
|
230
|
+
};
|
|
231
|
+
|
|
232
|
+
inline bool isWhiteSpace(char c) {
|
|
233
|
+
return c == ' ' || c == '\t' || c == '\v' ||
|
|
234
|
+
c == '\n' || c == '\r' || c == '\f';
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
inline bool isOct(char c) {
|
|
238
|
+
return '0' <= c && c <='7';
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
inline int valueOct(char c) {
|
|
242
|
+
LEMON_ASSERT(isOct(c), "The character is not octal.");
|
|
243
|
+
return c - '0';
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
inline bool isHex(char c) {
|
|
247
|
+
return ('0' <= c && c <= '9') ||
|
|
248
|
+
('a' <= c && c <= 'z') ||
|
|
249
|
+
('A' <= c && c <= 'Z');
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
inline int valueHex(char c) {
|
|
253
|
+
LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
|
|
254
|
+
if ('0' <= c && c <= '9') return c - '0';
|
|
255
|
+
if ('a' <= c && c <= 'z') return c - 'a' + 10;
|
|
256
|
+
return c - 'A' + 10;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
inline bool isIdentifierFirstChar(char c) {
|
|
260
|
+
return ('a' <= c && c <= 'z') ||
|
|
261
|
+
('A' <= c && c <= 'Z') || c == '_';
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
inline bool isIdentifierChar(char c) {
|
|
265
|
+
return isIdentifierFirstChar(c) ||
|
|
266
|
+
('0' <= c && c <= '9');
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
inline char readEscape(std::istream& is) {
|
|
270
|
+
char c;
|
|
271
|
+
if (!is.get(c))
|
|
272
|
+
throw FormatError("Escape format error");
|
|
273
|
+
|
|
274
|
+
switch (c) {
|
|
275
|
+
case '\\':
|
|
276
|
+
return '\\';
|
|
277
|
+
case '\"':
|
|
278
|
+
return '\"';
|
|
279
|
+
case '\'':
|
|
280
|
+
return '\'';
|
|
281
|
+
case '\?':
|
|
282
|
+
return '\?';
|
|
283
|
+
case 'a':
|
|
284
|
+
return '\a';
|
|
285
|
+
case 'b':
|
|
286
|
+
return '\b';
|
|
287
|
+
case 'f':
|
|
288
|
+
return '\f';
|
|
289
|
+
case 'n':
|
|
290
|
+
return '\n';
|
|
291
|
+
case 'r':
|
|
292
|
+
return '\r';
|
|
293
|
+
case 't':
|
|
294
|
+
return '\t';
|
|
295
|
+
case 'v':
|
|
296
|
+
return '\v';
|
|
297
|
+
case 'x':
|
|
298
|
+
{
|
|
299
|
+
int code;
|
|
300
|
+
if (!is.get(c) || !isHex(c))
|
|
301
|
+
throw FormatError("Escape format error");
|
|
302
|
+
else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c);
|
|
303
|
+
else code = code * 16 + valueHex(c);
|
|
304
|
+
return code;
|
|
305
|
+
}
|
|
306
|
+
default:
|
|
307
|
+
{
|
|
308
|
+
int code;
|
|
309
|
+
if (!isOct(c))
|
|
310
|
+
throw FormatError("Escape format error");
|
|
311
|
+
else if (code = valueOct(c), !is.get(c) || !isOct(c))
|
|
312
|
+
is.putback(c);
|
|
313
|
+
else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c))
|
|
314
|
+
is.putback(c);
|
|
315
|
+
else code = code * 8 + valueOct(c);
|
|
316
|
+
return code;
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
inline std::istream& readToken(std::istream& is, std::string& str) {
|
|
322
|
+
std::ostringstream os;
|
|
323
|
+
|
|
324
|
+
char c;
|
|
325
|
+
is >> std::ws;
|
|
326
|
+
|
|
327
|
+
if (!is.get(c))
|
|
328
|
+
return is;
|
|
329
|
+
|
|
330
|
+
if (c == '\"') {
|
|
331
|
+
while (is.get(c) && c != '\"') {
|
|
332
|
+
if (c == '\\')
|
|
333
|
+
c = readEscape(is);
|
|
334
|
+
os << c;
|
|
335
|
+
}
|
|
336
|
+
if (!is)
|
|
337
|
+
throw FormatError("Quoted format error");
|
|
338
|
+
} else {
|
|
339
|
+
is.putback(c);
|
|
340
|
+
while (is.get(c) && !isWhiteSpace(c)) {
|
|
341
|
+
if (c == '\\')
|
|
342
|
+
c = readEscape(is);
|
|
343
|
+
os << c;
|
|
344
|
+
}
|
|
345
|
+
if (!is) {
|
|
346
|
+
is.clear();
|
|
347
|
+
} else {
|
|
348
|
+
is.putback(c);
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
str = os.str();
|
|
352
|
+
return is;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
class Section {
|
|
356
|
+
public:
|
|
357
|
+
virtual ~Section() {}
|
|
358
|
+
virtual void process(std::istream& is, int& line_num) = 0;
|
|
359
|
+
};
|
|
360
|
+
|
|
361
|
+
template <typename Functor>
|
|
362
|
+
class LineSection : public Section {
|
|
363
|
+
private:
|
|
364
|
+
|
|
365
|
+
Functor _functor;
|
|
366
|
+
|
|
367
|
+
public:
|
|
368
|
+
|
|
369
|
+
LineSection(const Functor& functor) : _functor(functor) {}
|
|
370
|
+
virtual ~LineSection() {}
|
|
371
|
+
|
|
372
|
+
virtual void process(std::istream& is, int& line_num) {
|
|
373
|
+
char c;
|
|
374
|
+
std::string line;
|
|
375
|
+
while (is.get(c) && c != '@') {
|
|
376
|
+
if (c == '\n') {
|
|
377
|
+
++line_num;
|
|
378
|
+
} else if (c == '#') {
|
|
379
|
+
getline(is, line);
|
|
380
|
+
++line_num;
|
|
381
|
+
} else if (!isWhiteSpace(c)) {
|
|
382
|
+
is.putback(c);
|
|
383
|
+
getline(is, line);
|
|
384
|
+
_functor(line);
|
|
385
|
+
++line_num;
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (is) is.putback(c);
|
|
389
|
+
else if (is.eof()) is.clear();
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
template <typename Functor>
|
|
394
|
+
class StreamSection : public Section {
|
|
395
|
+
private:
|
|
396
|
+
|
|
397
|
+
Functor _functor;
|
|
398
|
+
|
|
399
|
+
public:
|
|
400
|
+
|
|
401
|
+
StreamSection(const Functor& functor) : _functor(functor) {}
|
|
402
|
+
virtual ~StreamSection() {}
|
|
403
|
+
|
|
404
|
+
virtual void process(std::istream& is, int& line_num) {
|
|
405
|
+
_functor(is, line_num);
|
|
406
|
+
char c;
|
|
407
|
+
std::string line;
|
|
408
|
+
while (is.get(c) && c != '@') {
|
|
409
|
+
if (c == '\n') {
|
|
410
|
+
++line_num;
|
|
411
|
+
} else if (!isWhiteSpace(c)) {
|
|
412
|
+
getline(is, line);
|
|
413
|
+
++line_num;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
if (is) is.putback(c);
|
|
417
|
+
else if (is.eof()) is.clear();
|
|
418
|
+
}
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
template <typename DGR>
|
|
424
|
+
class DigraphReader;
|
|
425
|
+
|
|
426
|
+
template <typename TDGR>
|
|
427
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is = std::cin);
|
|
428
|
+
template <typename TDGR>
|
|
429
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn);
|
|
430
|
+
template <typename TDGR>
|
|
431
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
|
|
432
|
+
|
|
433
|
+
/// \ingroup lemon_io
|
|
434
|
+
///
|
|
435
|
+
/// \brief \ref lgf-format "LGF" reader for directed graphs
|
|
436
|
+
///
|
|
437
|
+
/// This utility reads an \ref lgf-format "LGF" file.
|
|
438
|
+
///
|
|
439
|
+
/// The reading method does a batch processing. The user creates a
|
|
440
|
+
/// reader object, then various reading rules can be added to the
|
|
441
|
+
/// reader, and eventually the reading is executed with the \c run()
|
|
442
|
+
/// member function. A map reading rule can be added to the reader
|
|
443
|
+
/// with the \c nodeMap() or \c arcMap() members. An optional
|
|
444
|
+
/// converter parameter can also be added as a standard functor
|
|
445
|
+
/// converting from \c std::string to the value type of the map. If it
|
|
446
|
+
/// is set, it will determine how the tokens in the file should be
|
|
447
|
+
/// converted to the value type of the map. If the functor is not set,
|
|
448
|
+
/// then a default conversion will be used. One map can be read into
|
|
449
|
+
/// multiple map objects at the same time. The \c attribute(), \c
|
|
450
|
+
/// node() and \c arc() functions are used to add attribute reading
|
|
451
|
+
/// rules.
|
|
452
|
+
///
|
|
453
|
+
///\code
|
|
454
|
+
/// DigraphReader<DGR>(digraph, std::cin).
|
|
455
|
+
/// nodeMap("coordinates", coord_map).
|
|
456
|
+
/// arcMap("capacity", cap_map).
|
|
457
|
+
/// node("source", src).
|
|
458
|
+
/// node("target", trg).
|
|
459
|
+
/// attribute("caption", caption).
|
|
460
|
+
/// run();
|
|
461
|
+
///\endcode
|
|
462
|
+
///
|
|
463
|
+
/// By default, the reader uses the first section in the file of the
|
|
464
|
+
/// proper type. If a section has an optional name, then it can be
|
|
465
|
+
/// selected for reading by giving an optional name parameter to the
|
|
466
|
+
/// \c nodes(), \c arcs() or \c attributes() functions.
|
|
467
|
+
///
|
|
468
|
+
/// The \c useNodes() and \c useArcs() functions are used to tell the reader
|
|
469
|
+
/// that the nodes or arcs should not be constructed (added to the
|
|
470
|
+
/// graph) during the reading, but instead the label map of the items
|
|
471
|
+
/// are given as a parameter of these functions. An
|
|
472
|
+
/// application of these functions is multipass reading, which is
|
|
473
|
+
/// important if two \c \@arcs sections must be read from the
|
|
474
|
+
/// file. In this case the first phase would read the node set and one
|
|
475
|
+
/// of the arc sets, while the second phase would read the second arc
|
|
476
|
+
/// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet).
|
|
477
|
+
/// The previously read label node map should be passed to the \c
|
|
478
|
+
/// useNodes() functions. Another application of multipass reading when
|
|
479
|
+
/// paths are given as a node map or an arc map.
|
|
480
|
+
/// It is impossible to read this in
|
|
481
|
+
/// a single pass, because the arcs are not constructed when the node
|
|
482
|
+
/// maps are read.
|
|
483
|
+
template <typename DGR>
|
|
484
|
+
class DigraphReader {
|
|
485
|
+
public:
|
|
486
|
+
|
|
487
|
+
typedef DGR Digraph;
|
|
488
|
+
|
|
489
|
+
private:
|
|
490
|
+
|
|
491
|
+
TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
|
|
492
|
+
|
|
493
|
+
std::istream* _is;
|
|
494
|
+
bool local_is;
|
|
495
|
+
std::string _filename;
|
|
496
|
+
|
|
497
|
+
DGR& _digraph;
|
|
498
|
+
|
|
499
|
+
std::string _nodes_caption;
|
|
500
|
+
std::string _arcs_caption;
|
|
501
|
+
std::string _attributes_caption;
|
|
502
|
+
|
|
503
|
+
typedef std::map<std::string, Node> NodeIndex;
|
|
504
|
+
NodeIndex _node_index;
|
|
505
|
+
typedef std::map<std::string, Arc> ArcIndex;
|
|
506
|
+
ArcIndex _arc_index;
|
|
507
|
+
|
|
508
|
+
typedef std::vector<std::pair<std::string,
|
|
509
|
+
_reader_bits::MapStorageBase<Node>*> > NodeMaps;
|
|
510
|
+
NodeMaps _node_maps;
|
|
511
|
+
|
|
512
|
+
typedef std::vector<std::pair<std::string,
|
|
513
|
+
_reader_bits::MapStorageBase<Arc>*> >ArcMaps;
|
|
514
|
+
ArcMaps _arc_maps;
|
|
515
|
+
|
|
516
|
+
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
|
|
517
|
+
Attributes;
|
|
518
|
+
Attributes _attributes;
|
|
519
|
+
|
|
520
|
+
bool _use_nodes;
|
|
521
|
+
bool _use_arcs;
|
|
522
|
+
|
|
523
|
+
bool _skip_nodes;
|
|
524
|
+
bool _skip_arcs;
|
|
525
|
+
|
|
526
|
+
int line_num;
|
|
527
|
+
std::istringstream line;
|
|
528
|
+
|
|
529
|
+
public:
|
|
530
|
+
|
|
531
|
+
/// \brief Constructor
|
|
532
|
+
///
|
|
533
|
+
/// Construct a directed graph reader, which reads from the given
|
|
534
|
+
/// input stream.
|
|
535
|
+
DigraphReader(DGR& digraph, std::istream& is = std::cin)
|
|
536
|
+
: _is(&is), local_is(false), _digraph(digraph),
|
|
537
|
+
_use_nodes(false), _use_arcs(false),
|
|
538
|
+
_skip_nodes(false), _skip_arcs(false) {}
|
|
539
|
+
|
|
540
|
+
/// \brief Constructor
|
|
541
|
+
///
|
|
542
|
+
/// Construct a directed graph reader, which reads from the given
|
|
543
|
+
/// file.
|
|
544
|
+
DigraphReader(DGR& digraph, const std::string& fn)
|
|
545
|
+
: _is(new std::ifstream(fn.c_str())), local_is(true),
|
|
546
|
+
_filename(fn), _digraph(digraph),
|
|
547
|
+
_use_nodes(false), _use_arcs(false),
|
|
548
|
+
_skip_nodes(false), _skip_arcs(false) {
|
|
549
|
+
if (!(*_is)) {
|
|
550
|
+
delete _is;
|
|
551
|
+
throw IoError("Cannot open file", fn);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/// \brief Constructor
|
|
556
|
+
///
|
|
557
|
+
/// Construct a directed graph reader, which reads from the given
|
|
558
|
+
/// file.
|
|
559
|
+
DigraphReader(DGR& digraph, const char* fn)
|
|
560
|
+
: _is(new std::ifstream(fn)), local_is(true),
|
|
561
|
+
_filename(fn), _digraph(digraph),
|
|
562
|
+
_use_nodes(false), _use_arcs(false),
|
|
563
|
+
_skip_nodes(false), _skip_arcs(false) {
|
|
564
|
+
if (!(*_is)) {
|
|
565
|
+
delete _is;
|
|
566
|
+
throw IoError("Cannot open file", fn);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
/// \brief Destructor
|
|
571
|
+
~DigraphReader() {
|
|
572
|
+
for (typename NodeMaps::iterator it = _node_maps.begin();
|
|
573
|
+
it != _node_maps.end(); ++it) {
|
|
574
|
+
delete it->second;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
for (typename ArcMaps::iterator it = _arc_maps.begin();
|
|
578
|
+
it != _arc_maps.end(); ++it) {
|
|
579
|
+
delete it->second;
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
583
|
+
it != _attributes.end(); ++it) {
|
|
584
|
+
delete it->second;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
if (local_is) {
|
|
588
|
+
delete _is;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
private:
|
|
594
|
+
|
|
595
|
+
template <typename TDGR>
|
|
596
|
+
friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
|
|
597
|
+
template <typename TDGR>
|
|
598
|
+
friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
|
|
599
|
+
const std::string& fn);
|
|
600
|
+
template <typename TDGR>
|
|
601
|
+
friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
|
|
602
|
+
|
|
603
|
+
DigraphReader(DigraphReader& other)
|
|
604
|
+
: _is(other._is), local_is(other.local_is), _digraph(other._digraph),
|
|
605
|
+
_use_nodes(other._use_nodes), _use_arcs(other._use_arcs),
|
|
606
|
+
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
|
|
607
|
+
|
|
608
|
+
other._is = 0;
|
|
609
|
+
other.local_is = false;
|
|
610
|
+
|
|
611
|
+
_node_index.swap(other._node_index);
|
|
612
|
+
_arc_index.swap(other._arc_index);
|
|
613
|
+
|
|
614
|
+
_node_maps.swap(other._node_maps);
|
|
615
|
+
_arc_maps.swap(other._arc_maps);
|
|
616
|
+
_attributes.swap(other._attributes);
|
|
617
|
+
|
|
618
|
+
_nodes_caption = other._nodes_caption;
|
|
619
|
+
_arcs_caption = other._arcs_caption;
|
|
620
|
+
_attributes_caption = other._attributes_caption;
|
|
621
|
+
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
DigraphReader& operator=(const DigraphReader&);
|
|
625
|
+
|
|
626
|
+
public:
|
|
627
|
+
|
|
628
|
+
/// \name Reading Rules
|
|
629
|
+
/// @{
|
|
630
|
+
|
|
631
|
+
/// \brief Node map reading rule
|
|
632
|
+
///
|
|
633
|
+
/// Add a node map reading rule to the reader.
|
|
634
|
+
template <typename Map>
|
|
635
|
+
DigraphReader& nodeMap(const std::string& caption, Map& map) {
|
|
636
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
637
|
+
_reader_bits::MapStorageBase<Node>* storage =
|
|
638
|
+
new _reader_bits::MapStorage<Node, Map>(map);
|
|
639
|
+
_node_maps.push_back(std::make_pair(caption, storage));
|
|
640
|
+
return *this;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/// \brief Node map reading rule
|
|
644
|
+
///
|
|
645
|
+
/// Add a node map reading rule with specialized converter to the
|
|
646
|
+
/// reader.
|
|
647
|
+
template <typename Map, typename Converter>
|
|
648
|
+
DigraphReader& nodeMap(const std::string& caption, Map& map,
|
|
649
|
+
const Converter& converter = Converter()) {
|
|
650
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
651
|
+
_reader_bits::MapStorageBase<Node>* storage =
|
|
652
|
+
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
|
|
653
|
+
_node_maps.push_back(std::make_pair(caption, storage));
|
|
654
|
+
return *this;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/// \brief Arc map reading rule
|
|
658
|
+
///
|
|
659
|
+
/// Add an arc map reading rule to the reader.
|
|
660
|
+
template <typename Map>
|
|
661
|
+
DigraphReader& arcMap(const std::string& caption, Map& map) {
|
|
662
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
663
|
+
_reader_bits::MapStorageBase<Arc>* storage =
|
|
664
|
+
new _reader_bits::MapStorage<Arc, Map>(map);
|
|
665
|
+
_arc_maps.push_back(std::make_pair(caption, storage));
|
|
666
|
+
return *this;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
/// \brief Arc map reading rule
|
|
670
|
+
///
|
|
671
|
+
/// Add an arc map reading rule with specialized converter to the
|
|
672
|
+
/// reader.
|
|
673
|
+
template <typename Map, typename Converter>
|
|
674
|
+
DigraphReader& arcMap(const std::string& caption, Map& map,
|
|
675
|
+
const Converter& converter = Converter()) {
|
|
676
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
677
|
+
_reader_bits::MapStorageBase<Arc>* storage =
|
|
678
|
+
new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter);
|
|
679
|
+
_arc_maps.push_back(std::make_pair(caption, storage));
|
|
680
|
+
return *this;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
/// \brief Attribute reading rule
|
|
684
|
+
///
|
|
685
|
+
/// Add an attribute reading rule to the reader.
|
|
686
|
+
template <typename Value>
|
|
687
|
+
DigraphReader& attribute(const std::string& caption, Value& value) {
|
|
688
|
+
_reader_bits::ValueStorageBase* storage =
|
|
689
|
+
new _reader_bits::ValueStorage<Value>(value);
|
|
690
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
691
|
+
return *this;
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
/// \brief Attribute reading rule
|
|
695
|
+
///
|
|
696
|
+
/// Add an attribute reading rule with specialized converter to the
|
|
697
|
+
/// reader.
|
|
698
|
+
template <typename Value, typename Converter>
|
|
699
|
+
DigraphReader& attribute(const std::string& caption, Value& value,
|
|
700
|
+
const Converter& converter = Converter()) {
|
|
701
|
+
_reader_bits::ValueStorageBase* storage =
|
|
702
|
+
new _reader_bits::ValueStorage<Value, Converter>(value, converter);
|
|
703
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
704
|
+
return *this;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
/// \brief Node reading rule
|
|
708
|
+
///
|
|
709
|
+
/// Add a node reading rule to reader.
|
|
710
|
+
DigraphReader& node(const std::string& caption, Node& node) {
|
|
711
|
+
typedef _reader_bits::MapLookUpConverter<Node> Converter;
|
|
712
|
+
Converter converter(_node_index);
|
|
713
|
+
_reader_bits::ValueStorageBase* storage =
|
|
714
|
+
new _reader_bits::ValueStorage<Node, Converter>(node, converter);
|
|
715
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
716
|
+
return *this;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
/// \brief Arc reading rule
|
|
720
|
+
///
|
|
721
|
+
/// Add an arc reading rule to reader.
|
|
722
|
+
DigraphReader& arc(const std::string& caption, Arc& arc) {
|
|
723
|
+
typedef _reader_bits::MapLookUpConverter<Arc> Converter;
|
|
724
|
+
Converter converter(_arc_index);
|
|
725
|
+
_reader_bits::ValueStorageBase* storage =
|
|
726
|
+
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
|
|
727
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
728
|
+
return *this;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
/// @}
|
|
732
|
+
|
|
733
|
+
/// \name Select Section by Name
|
|
734
|
+
/// @{
|
|
735
|
+
|
|
736
|
+
/// \brief Set \c \@nodes section to be read
|
|
737
|
+
///
|
|
738
|
+
/// Set \c \@nodes section to be read
|
|
739
|
+
DigraphReader& nodes(const std::string& caption) {
|
|
740
|
+
_nodes_caption = caption;
|
|
741
|
+
return *this;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/// \brief Set \c \@arcs section to be read
|
|
745
|
+
///
|
|
746
|
+
/// Set \c \@arcs section to be read
|
|
747
|
+
DigraphReader& arcs(const std::string& caption) {
|
|
748
|
+
_arcs_caption = caption;
|
|
749
|
+
return *this;
|
|
750
|
+
}
|
|
751
|
+
|
|
752
|
+
/// \brief Set \c \@attributes section to be read
|
|
753
|
+
///
|
|
754
|
+
/// Set \c \@attributes section to be read
|
|
755
|
+
DigraphReader& attributes(const std::string& caption) {
|
|
756
|
+
_attributes_caption = caption;
|
|
757
|
+
return *this;
|
|
758
|
+
}
|
|
759
|
+
|
|
760
|
+
/// @}
|
|
761
|
+
|
|
762
|
+
/// \name Using Previously Constructed Node or Arc Set
|
|
763
|
+
/// @{
|
|
764
|
+
|
|
765
|
+
/// \brief Use previously constructed node set
|
|
766
|
+
///
|
|
767
|
+
/// Use previously constructed node set, and specify the node
|
|
768
|
+
/// label map.
|
|
769
|
+
template <typename Map>
|
|
770
|
+
DigraphReader& useNodes(const Map& map) {
|
|
771
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
772
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
773
|
+
_use_nodes = true;
|
|
774
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
775
|
+
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
776
|
+
_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
777
|
+
}
|
|
778
|
+
return *this;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
/// \brief Use previously constructed node set
|
|
782
|
+
///
|
|
783
|
+
/// Use previously constructed node set, and specify the node
|
|
784
|
+
/// label map and a functor which converts the label map values to
|
|
785
|
+
/// \c std::string.
|
|
786
|
+
template <typename Map, typename Converter>
|
|
787
|
+
DigraphReader& useNodes(const Map& map,
|
|
788
|
+
const Converter& converter = Converter()) {
|
|
789
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
790
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
791
|
+
_use_nodes = true;
|
|
792
|
+
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
793
|
+
_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
794
|
+
}
|
|
795
|
+
return *this;
|
|
796
|
+
}
|
|
797
|
+
|
|
798
|
+
/// \brief Use previously constructed arc set
|
|
799
|
+
///
|
|
800
|
+
/// Use previously constructed arc set, and specify the arc
|
|
801
|
+
/// label map.
|
|
802
|
+
template <typename Map>
|
|
803
|
+
DigraphReader& useArcs(const Map& map) {
|
|
804
|
+
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
|
|
805
|
+
LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
|
|
806
|
+
_use_arcs = true;
|
|
807
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
808
|
+
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
809
|
+
_arc_index.insert(std::make_pair(converter(map[a]), a));
|
|
810
|
+
}
|
|
811
|
+
return *this;
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
/// \brief Use previously constructed arc set
|
|
815
|
+
///
|
|
816
|
+
/// Use previously constructed arc set, and specify the arc
|
|
817
|
+
/// label map and a functor which converts the label map values to
|
|
818
|
+
/// \c std::string.
|
|
819
|
+
template <typename Map, typename Converter>
|
|
820
|
+
DigraphReader& useArcs(const Map& map,
|
|
821
|
+
const Converter& converter = Converter()) {
|
|
822
|
+
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
|
|
823
|
+
LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
|
|
824
|
+
_use_arcs = true;
|
|
825
|
+
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
826
|
+
_arc_index.insert(std::make_pair(converter(map[a]), a));
|
|
827
|
+
}
|
|
828
|
+
return *this;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/// \brief Skips the reading of node section
|
|
832
|
+
///
|
|
833
|
+
/// Omit the reading of the node section. This implies that each node
|
|
834
|
+
/// map reading rule will be abandoned, and the nodes of the graph
|
|
835
|
+
/// will not be constructed, which usually cause that the arc set
|
|
836
|
+
/// could not be read due to lack of node name resolving.
|
|
837
|
+
/// Therefore \c skipArcs() function should also be used, or
|
|
838
|
+
/// \c useNodes() should be used to specify the label of the nodes.
|
|
839
|
+
DigraphReader& skipNodes() {
|
|
840
|
+
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
|
|
841
|
+
_skip_nodes = true;
|
|
842
|
+
return *this;
|
|
843
|
+
}
|
|
844
|
+
|
|
845
|
+
/// \brief Skips the reading of arc section
|
|
846
|
+
///
|
|
847
|
+
/// Omit the reading of the arc section. This implies that each arc
|
|
848
|
+
/// map reading rule will be abandoned, and the arcs of the graph
|
|
849
|
+
/// will not be constructed.
|
|
850
|
+
DigraphReader& skipArcs() {
|
|
851
|
+
LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
|
|
852
|
+
_skip_arcs = true;
|
|
853
|
+
return *this;
|
|
854
|
+
}
|
|
855
|
+
|
|
856
|
+
/// @}
|
|
857
|
+
|
|
858
|
+
private:
|
|
859
|
+
|
|
860
|
+
bool readLine() {
|
|
861
|
+
std::string str;
|
|
862
|
+
while(++line_num, std::getline(*_is, str)) {
|
|
863
|
+
line.clear(); line.str(str);
|
|
864
|
+
char c;
|
|
865
|
+
if (line >> std::ws >> c && c != '#') {
|
|
866
|
+
line.putback(c);
|
|
867
|
+
return true;
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
return false;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
bool readSuccess() {
|
|
874
|
+
return static_cast<bool>(*_is);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
void skipSection() {
|
|
878
|
+
char c;
|
|
879
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
880
|
+
readLine();
|
|
881
|
+
}
|
|
882
|
+
if (readSuccess()) {
|
|
883
|
+
line.putback(c);
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
void readNodes() {
|
|
888
|
+
|
|
889
|
+
std::vector<int> map_index(_node_maps.size());
|
|
890
|
+
int map_num, label_index;
|
|
891
|
+
|
|
892
|
+
char c;
|
|
893
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
894
|
+
if (readSuccess() && line) line.putback(c);
|
|
895
|
+
if (!_node_maps.empty())
|
|
896
|
+
throw FormatError("Cannot find map names");
|
|
897
|
+
return;
|
|
898
|
+
}
|
|
899
|
+
line.putback(c);
|
|
900
|
+
|
|
901
|
+
{
|
|
902
|
+
std::map<std::string, int> maps;
|
|
903
|
+
|
|
904
|
+
std::string map;
|
|
905
|
+
int index = 0;
|
|
906
|
+
while (_reader_bits::readToken(line, map)) {
|
|
907
|
+
if (maps.find(map) != maps.end()) {
|
|
908
|
+
std::ostringstream msg;
|
|
909
|
+
msg << "Multiple occurence of node map: " << map;
|
|
910
|
+
throw FormatError(msg.str());
|
|
911
|
+
}
|
|
912
|
+
maps.insert(std::make_pair(map, index));
|
|
913
|
+
++index;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
917
|
+
std::map<std::string, int>::iterator jt =
|
|
918
|
+
maps.find(_node_maps[i].first);
|
|
919
|
+
if (jt == maps.end()) {
|
|
920
|
+
std::ostringstream msg;
|
|
921
|
+
msg << "Map not found: " << _node_maps[i].first;
|
|
922
|
+
throw FormatError(msg.str());
|
|
923
|
+
}
|
|
924
|
+
map_index[i] = jt->second;
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
{
|
|
928
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
929
|
+
if (jt != maps.end()) {
|
|
930
|
+
label_index = jt->second;
|
|
931
|
+
} else {
|
|
932
|
+
label_index = -1;
|
|
933
|
+
}
|
|
934
|
+
}
|
|
935
|
+
map_num = maps.size();
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
while (readLine() && line >> c && c != '@') {
|
|
939
|
+
line.putback(c);
|
|
940
|
+
|
|
941
|
+
std::vector<std::string> tokens(map_num);
|
|
942
|
+
for (int i = 0; i < map_num; ++i) {
|
|
943
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
944
|
+
std::ostringstream msg;
|
|
945
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
946
|
+
throw FormatError(msg.str());
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
if (line >> std::ws >> c)
|
|
950
|
+
throw FormatError("Extra character at the end of line");
|
|
951
|
+
|
|
952
|
+
Node n;
|
|
953
|
+
if (!_use_nodes) {
|
|
954
|
+
n = _digraph.addNode();
|
|
955
|
+
if (label_index != -1)
|
|
956
|
+
_node_index.insert(std::make_pair(tokens[label_index], n));
|
|
957
|
+
} else {
|
|
958
|
+
if (label_index == -1)
|
|
959
|
+
throw FormatError("Label map not found");
|
|
960
|
+
typename std::map<std::string, Node>::iterator it =
|
|
961
|
+
_node_index.find(tokens[label_index]);
|
|
962
|
+
if (it == _node_index.end()) {
|
|
963
|
+
std::ostringstream msg;
|
|
964
|
+
msg << "Node with label not found: " << tokens[label_index];
|
|
965
|
+
throw FormatError(msg.str());
|
|
966
|
+
}
|
|
967
|
+
n = it->second;
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
971
|
+
_node_maps[i].second->set(n, tokens[map_index[i]]);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
}
|
|
975
|
+
if (readSuccess()) {
|
|
976
|
+
line.putback(c);
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
|
|
980
|
+
void readArcs() {
|
|
981
|
+
|
|
982
|
+
std::vector<int> map_index(_arc_maps.size());
|
|
983
|
+
int map_num, label_index;
|
|
984
|
+
|
|
985
|
+
char c;
|
|
986
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
987
|
+
if (readSuccess() && line) line.putback(c);
|
|
988
|
+
if (!_arc_maps.empty())
|
|
989
|
+
throw FormatError("Cannot find map names");
|
|
990
|
+
return;
|
|
991
|
+
}
|
|
992
|
+
line.putback(c);
|
|
993
|
+
|
|
994
|
+
{
|
|
995
|
+
std::map<std::string, int> maps;
|
|
996
|
+
|
|
997
|
+
std::string map;
|
|
998
|
+
int index = 0;
|
|
999
|
+
while (_reader_bits::readToken(line, map)) {
|
|
1000
|
+
if(map == "-") {
|
|
1001
|
+
if(index!=0)
|
|
1002
|
+
throw FormatError("'-' is not allowed as a map name");
|
|
1003
|
+
else if (line >> std::ws >> c)
|
|
1004
|
+
throw FormatError("Extra character at the end of line");
|
|
1005
|
+
else break;
|
|
1006
|
+
}
|
|
1007
|
+
if (maps.find(map) != maps.end()) {
|
|
1008
|
+
std::ostringstream msg;
|
|
1009
|
+
msg << "Multiple occurence of arc map: " << map;
|
|
1010
|
+
throw FormatError(msg.str());
|
|
1011
|
+
}
|
|
1012
|
+
maps.insert(std::make_pair(map, index));
|
|
1013
|
+
++index;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
1017
|
+
std::map<std::string, int>::iterator jt =
|
|
1018
|
+
maps.find(_arc_maps[i].first);
|
|
1019
|
+
if (jt == maps.end()) {
|
|
1020
|
+
std::ostringstream msg;
|
|
1021
|
+
msg << "Map not found: " << _arc_maps[i].first;
|
|
1022
|
+
throw FormatError(msg.str());
|
|
1023
|
+
}
|
|
1024
|
+
map_index[i] = jt->second;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
{
|
|
1028
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
1029
|
+
if (jt != maps.end()) {
|
|
1030
|
+
label_index = jt->second;
|
|
1031
|
+
} else {
|
|
1032
|
+
label_index = -1;
|
|
1033
|
+
}
|
|
1034
|
+
}
|
|
1035
|
+
map_num = maps.size();
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
while (readLine() && line >> c && c != '@') {
|
|
1039
|
+
line.putback(c);
|
|
1040
|
+
|
|
1041
|
+
std::string source_token;
|
|
1042
|
+
std::string target_token;
|
|
1043
|
+
|
|
1044
|
+
if (!_reader_bits::readToken(line, source_token))
|
|
1045
|
+
throw FormatError("Source not found");
|
|
1046
|
+
|
|
1047
|
+
if (!_reader_bits::readToken(line, target_token))
|
|
1048
|
+
throw FormatError("Target not found");
|
|
1049
|
+
|
|
1050
|
+
std::vector<std::string> tokens(map_num);
|
|
1051
|
+
for (int i = 0; i < map_num; ++i) {
|
|
1052
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
1053
|
+
std::ostringstream msg;
|
|
1054
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
1055
|
+
throw FormatError(msg.str());
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
if (line >> std::ws >> c)
|
|
1059
|
+
throw FormatError("Extra character at the end of line");
|
|
1060
|
+
|
|
1061
|
+
Arc a;
|
|
1062
|
+
if (!_use_arcs) {
|
|
1063
|
+
|
|
1064
|
+
typename NodeIndex::iterator it;
|
|
1065
|
+
|
|
1066
|
+
it = _node_index.find(source_token);
|
|
1067
|
+
if (it == _node_index.end()) {
|
|
1068
|
+
std::ostringstream msg;
|
|
1069
|
+
msg << "Item not found: " << source_token;
|
|
1070
|
+
throw FormatError(msg.str());
|
|
1071
|
+
}
|
|
1072
|
+
Node source = it->second;
|
|
1073
|
+
|
|
1074
|
+
it = _node_index.find(target_token);
|
|
1075
|
+
if (it == _node_index.end()) {
|
|
1076
|
+
std::ostringstream msg;
|
|
1077
|
+
msg << "Item not found: " << target_token;
|
|
1078
|
+
throw FormatError(msg.str());
|
|
1079
|
+
}
|
|
1080
|
+
Node target = it->second;
|
|
1081
|
+
|
|
1082
|
+
a = _digraph.addArc(source, target);
|
|
1083
|
+
if (label_index != -1)
|
|
1084
|
+
_arc_index.insert(std::make_pair(tokens[label_index], a));
|
|
1085
|
+
} else {
|
|
1086
|
+
if (label_index == -1)
|
|
1087
|
+
throw FormatError("Label map not found");
|
|
1088
|
+
typename std::map<std::string, Arc>::iterator it =
|
|
1089
|
+
_arc_index.find(tokens[label_index]);
|
|
1090
|
+
if (it == _arc_index.end()) {
|
|
1091
|
+
std::ostringstream msg;
|
|
1092
|
+
msg << "Arc with label not found: " << tokens[label_index];
|
|
1093
|
+
throw FormatError(msg.str());
|
|
1094
|
+
}
|
|
1095
|
+
a = it->second;
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
1099
|
+
_arc_maps[i].second->set(a, tokens[map_index[i]]);
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
}
|
|
1103
|
+
if (readSuccess()) {
|
|
1104
|
+
line.putback(c);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
|
|
1108
|
+
void readAttributes() {
|
|
1109
|
+
|
|
1110
|
+
std::set<std::string> read_attr;
|
|
1111
|
+
|
|
1112
|
+
char c;
|
|
1113
|
+
while (readLine() && line >> c && c != '@') {
|
|
1114
|
+
line.putback(c);
|
|
1115
|
+
|
|
1116
|
+
std::string attr, token;
|
|
1117
|
+
if (!_reader_bits::readToken(line, attr))
|
|
1118
|
+
throw FormatError("Attribute name not found");
|
|
1119
|
+
if (!_reader_bits::readToken(line, token))
|
|
1120
|
+
throw FormatError("Attribute value not found");
|
|
1121
|
+
if (line >> c)
|
|
1122
|
+
throw FormatError("Extra character at the end of line");
|
|
1123
|
+
|
|
1124
|
+
{
|
|
1125
|
+
std::set<std::string>::iterator it = read_attr.find(attr);
|
|
1126
|
+
if (it != read_attr.end()) {
|
|
1127
|
+
std::ostringstream msg;
|
|
1128
|
+
msg << "Multiple occurence of attribute: " << attr;
|
|
1129
|
+
throw FormatError(msg.str());
|
|
1130
|
+
}
|
|
1131
|
+
read_attr.insert(attr);
|
|
1132
|
+
}
|
|
1133
|
+
|
|
1134
|
+
{
|
|
1135
|
+
typename Attributes::iterator it = _attributes.lower_bound(attr);
|
|
1136
|
+
while (it != _attributes.end() && it->first == attr) {
|
|
1137
|
+
it->second->set(token);
|
|
1138
|
+
++it;
|
|
1139
|
+
}
|
|
1140
|
+
}
|
|
1141
|
+
|
|
1142
|
+
}
|
|
1143
|
+
if (readSuccess()) {
|
|
1144
|
+
line.putback(c);
|
|
1145
|
+
}
|
|
1146
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
1147
|
+
it != _attributes.end(); ++it) {
|
|
1148
|
+
if (read_attr.find(it->first) == read_attr.end()) {
|
|
1149
|
+
std::ostringstream msg;
|
|
1150
|
+
msg << "Attribute not found: " << it->first;
|
|
1151
|
+
throw FormatError(msg.str());
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1155
|
+
|
|
1156
|
+
public:
|
|
1157
|
+
|
|
1158
|
+
/// \name Execution of the Reader
|
|
1159
|
+
/// @{
|
|
1160
|
+
|
|
1161
|
+
/// \brief Start the batch processing
|
|
1162
|
+
///
|
|
1163
|
+
/// This function starts the batch processing
|
|
1164
|
+
void run() {
|
|
1165
|
+
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
|
|
1166
|
+
|
|
1167
|
+
bool nodes_done = _skip_nodes;
|
|
1168
|
+
bool arcs_done = _skip_arcs;
|
|
1169
|
+
bool attributes_done = false;
|
|
1170
|
+
|
|
1171
|
+
line_num = 0;
|
|
1172
|
+
readLine();
|
|
1173
|
+
skipSection();
|
|
1174
|
+
|
|
1175
|
+
while (readSuccess()) {
|
|
1176
|
+
try {
|
|
1177
|
+
char c;
|
|
1178
|
+
std::string section, caption;
|
|
1179
|
+
line >> c;
|
|
1180
|
+
_reader_bits::readToken(line, section);
|
|
1181
|
+
_reader_bits::readToken(line, caption);
|
|
1182
|
+
|
|
1183
|
+
if (line >> c)
|
|
1184
|
+
throw FormatError("Extra character at the end of line");
|
|
1185
|
+
|
|
1186
|
+
if (section == "nodes" && !nodes_done) {
|
|
1187
|
+
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
1188
|
+
readNodes();
|
|
1189
|
+
nodes_done = true;
|
|
1190
|
+
}
|
|
1191
|
+
} else if ((section == "arcs" || section == "edges") &&
|
|
1192
|
+
!arcs_done) {
|
|
1193
|
+
if (_arcs_caption.empty() || _arcs_caption == caption) {
|
|
1194
|
+
readArcs();
|
|
1195
|
+
arcs_done = true;
|
|
1196
|
+
}
|
|
1197
|
+
} else if (section == "attributes" && !attributes_done) {
|
|
1198
|
+
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
1199
|
+
readAttributes();
|
|
1200
|
+
attributes_done = true;
|
|
1201
|
+
}
|
|
1202
|
+
} else {
|
|
1203
|
+
readLine();
|
|
1204
|
+
skipSection();
|
|
1205
|
+
}
|
|
1206
|
+
} catch (FormatError& error) {
|
|
1207
|
+
error.line(line_num);
|
|
1208
|
+
error.file(_filename);
|
|
1209
|
+
throw;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
if (!nodes_done) {
|
|
1214
|
+
throw FormatError("Section @nodes not found");
|
|
1215
|
+
}
|
|
1216
|
+
|
|
1217
|
+
if (!arcs_done) {
|
|
1218
|
+
throw FormatError("Section @arcs not found");
|
|
1219
|
+
}
|
|
1220
|
+
|
|
1221
|
+
if (!attributes_done && !_attributes.empty()) {
|
|
1222
|
+
throw FormatError("Section @attributes not found");
|
|
1223
|
+
}
|
|
1224
|
+
|
|
1225
|
+
}
|
|
1226
|
+
|
|
1227
|
+
/// @}
|
|
1228
|
+
|
|
1229
|
+
};
|
|
1230
|
+
|
|
1231
|
+
/// \ingroup lemon_io
|
|
1232
|
+
///
|
|
1233
|
+
/// \brief Return a \ref lemon::DigraphReader "DigraphReader" class
|
|
1234
|
+
///
|
|
1235
|
+
/// This function just returns a \ref lemon::DigraphReader
|
|
1236
|
+
/// "DigraphReader" class.
|
|
1237
|
+
///
|
|
1238
|
+
/// With this function a digraph can be read from an
|
|
1239
|
+
/// \ref lgf-format "LGF" file or input stream with several maps and
|
|
1240
|
+
/// attributes. For example, there is network flow problem on a
|
|
1241
|
+
/// digraph, i.e. a digraph with a \e capacity map on the arcs and
|
|
1242
|
+
/// \e source and \e target nodes. This digraph can be read with the
|
|
1243
|
+
/// following code:
|
|
1244
|
+
///
|
|
1245
|
+
///\code
|
|
1246
|
+
///ListDigraph digraph;
|
|
1247
|
+
///ListDigraph::ArcMap<int> cm(digraph);
|
|
1248
|
+
///ListDigraph::Node src, trg;
|
|
1249
|
+
///digraphReader(digraph, std::cin).
|
|
1250
|
+
/// arcMap("capacity", cap).
|
|
1251
|
+
/// node("source", src).
|
|
1252
|
+
/// node("target", trg).
|
|
1253
|
+
/// run();
|
|
1254
|
+
///\endcode
|
|
1255
|
+
///
|
|
1256
|
+
/// For a complete documentation, please see the
|
|
1257
|
+
/// \ref lemon::DigraphReader "DigraphReader"
|
|
1258
|
+
/// class documentation.
|
|
1259
|
+
/// \warning Don't forget to put the \ref lemon::DigraphReader::run() "run()"
|
|
1260
|
+
/// to the end of the parameter list.
|
|
1261
|
+
/// \relates DigraphReader
|
|
1262
|
+
/// \sa digraphReader(TDGR& digraph, const std::string& fn)
|
|
1263
|
+
/// \sa digraphReader(TDGR& digraph, const char* fn)
|
|
1264
|
+
template <typename TDGR>
|
|
1265
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is) {
|
|
1266
|
+
DigraphReader<TDGR> tmp(digraph, is);
|
|
1267
|
+
return tmp;
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
/// \brief Return a \ref DigraphReader class
|
|
1271
|
+
///
|
|
1272
|
+
/// This function just returns a \ref DigraphReader class.
|
|
1273
|
+
/// \relates DigraphReader
|
|
1274
|
+
/// \sa digraphReader(TDGR& digraph, std::istream& is)
|
|
1275
|
+
template <typename TDGR>
|
|
1276
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, const std::string& fn) {
|
|
1277
|
+
DigraphReader<TDGR> tmp(digraph, fn);
|
|
1278
|
+
return tmp;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/// \brief Return a \ref DigraphReader class
|
|
1282
|
+
///
|
|
1283
|
+
/// This function just returns a \ref DigraphReader class.
|
|
1284
|
+
/// \relates DigraphReader
|
|
1285
|
+
/// \sa digraphReader(TDGR& digraph, std::istream& is)
|
|
1286
|
+
template <typename TDGR>
|
|
1287
|
+
DigraphReader<TDGR> digraphReader(TDGR& digraph, const char* fn) {
|
|
1288
|
+
DigraphReader<TDGR> tmp(digraph, fn);
|
|
1289
|
+
return tmp;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
template <typename GR>
|
|
1293
|
+
class GraphReader;
|
|
1294
|
+
|
|
1295
|
+
template <typename TGR>
|
|
1296
|
+
GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
|
|
1297
|
+
template <typename TGR>
|
|
1298
|
+
GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
|
|
1299
|
+
template <typename TGR>
|
|
1300
|
+
GraphReader<TGR> graphReader(TGR& graph, const char *fn);
|
|
1301
|
+
|
|
1302
|
+
/// \ingroup lemon_io
|
|
1303
|
+
///
|
|
1304
|
+
/// \brief \ref lgf-format "LGF" reader for undirected graphs
|
|
1305
|
+
///
|
|
1306
|
+
/// This utility reads an \ref lgf-format "LGF" file.
|
|
1307
|
+
///
|
|
1308
|
+
/// It can be used almost the same way as \c DigraphReader.
|
|
1309
|
+
/// The only difference is that this class can handle edges and
|
|
1310
|
+
/// edge maps as well as arcs and arc maps.
|
|
1311
|
+
///
|
|
1312
|
+
/// The columns in the \c \@edges (or \c \@arcs) section are the
|
|
1313
|
+
/// edge maps. However, if there are two maps with the same name
|
|
1314
|
+
/// prefixed with \c '+' and \c '-', then these can be read into an
|
|
1315
|
+
/// arc map. Similarly, an attribute can be read into an arc, if
|
|
1316
|
+
/// it's value is an edge label prefixed with \c '+' or \c '-'.
|
|
1317
|
+
template <typename GR>
|
|
1318
|
+
class GraphReader {
|
|
1319
|
+
public:
|
|
1320
|
+
|
|
1321
|
+
typedef GR Graph;
|
|
1322
|
+
|
|
1323
|
+
private:
|
|
1324
|
+
|
|
1325
|
+
TEMPLATE_GRAPH_TYPEDEFS(GR);
|
|
1326
|
+
|
|
1327
|
+
std::istream* _is;
|
|
1328
|
+
bool local_is;
|
|
1329
|
+
std::string _filename;
|
|
1330
|
+
|
|
1331
|
+
GR& _graph;
|
|
1332
|
+
|
|
1333
|
+
std::string _nodes_caption;
|
|
1334
|
+
std::string _edges_caption;
|
|
1335
|
+
std::string _attributes_caption;
|
|
1336
|
+
|
|
1337
|
+
typedef std::map<std::string, Node> NodeIndex;
|
|
1338
|
+
NodeIndex _node_index;
|
|
1339
|
+
typedef std::map<std::string, Edge> EdgeIndex;
|
|
1340
|
+
EdgeIndex _edge_index;
|
|
1341
|
+
|
|
1342
|
+
typedef std::vector<std::pair<std::string,
|
|
1343
|
+
_reader_bits::MapStorageBase<Node>*> > NodeMaps;
|
|
1344
|
+
NodeMaps _node_maps;
|
|
1345
|
+
|
|
1346
|
+
typedef std::vector<std::pair<std::string,
|
|
1347
|
+
_reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
|
|
1348
|
+
EdgeMaps _edge_maps;
|
|
1349
|
+
|
|
1350
|
+
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
|
|
1351
|
+
Attributes;
|
|
1352
|
+
Attributes _attributes;
|
|
1353
|
+
|
|
1354
|
+
bool _use_nodes;
|
|
1355
|
+
bool _use_edges;
|
|
1356
|
+
|
|
1357
|
+
bool _skip_nodes;
|
|
1358
|
+
bool _skip_edges;
|
|
1359
|
+
|
|
1360
|
+
int line_num;
|
|
1361
|
+
std::istringstream line;
|
|
1362
|
+
|
|
1363
|
+
public:
|
|
1364
|
+
|
|
1365
|
+
/// \brief Constructor
|
|
1366
|
+
///
|
|
1367
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
1368
|
+
/// input stream.
|
|
1369
|
+
GraphReader(GR& graph, std::istream& is = std::cin)
|
|
1370
|
+
: _is(&is), local_is(false), _graph(graph),
|
|
1371
|
+
_use_nodes(false), _use_edges(false),
|
|
1372
|
+
_skip_nodes(false), _skip_edges(false) {}
|
|
1373
|
+
|
|
1374
|
+
/// \brief Constructor
|
|
1375
|
+
///
|
|
1376
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
1377
|
+
/// file.
|
|
1378
|
+
GraphReader(GR& graph, const std::string& fn)
|
|
1379
|
+
: _is(new std::ifstream(fn.c_str())), local_is(true),
|
|
1380
|
+
_filename(fn), _graph(graph),
|
|
1381
|
+
_use_nodes(false), _use_edges(false),
|
|
1382
|
+
_skip_nodes(false), _skip_edges(false) {
|
|
1383
|
+
if (!(*_is)) {
|
|
1384
|
+
delete _is;
|
|
1385
|
+
throw IoError("Cannot open file", fn);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1389
|
+
/// \brief Constructor
|
|
1390
|
+
///
|
|
1391
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
1392
|
+
/// file.
|
|
1393
|
+
GraphReader(GR& graph, const char* fn)
|
|
1394
|
+
: _is(new std::ifstream(fn)), local_is(true),
|
|
1395
|
+
_filename(fn), _graph(graph),
|
|
1396
|
+
_use_nodes(false), _use_edges(false),
|
|
1397
|
+
_skip_nodes(false), _skip_edges(false) {
|
|
1398
|
+
if (!(*_is)) {
|
|
1399
|
+
delete _is;
|
|
1400
|
+
throw IoError("Cannot open file", fn);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
|
|
1404
|
+
/// \brief Destructor
|
|
1405
|
+
~GraphReader() {
|
|
1406
|
+
for (typename NodeMaps::iterator it = _node_maps.begin();
|
|
1407
|
+
it != _node_maps.end(); ++it) {
|
|
1408
|
+
delete it->second;
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
for (typename EdgeMaps::iterator it = _edge_maps.begin();
|
|
1412
|
+
it != _edge_maps.end(); ++it) {
|
|
1413
|
+
delete it->second;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
1417
|
+
it != _attributes.end(); ++it) {
|
|
1418
|
+
delete it->second;
|
|
1419
|
+
}
|
|
1420
|
+
|
|
1421
|
+
if (local_is) {
|
|
1422
|
+
delete _is;
|
|
1423
|
+
}
|
|
1424
|
+
|
|
1425
|
+
}
|
|
1426
|
+
|
|
1427
|
+
private:
|
|
1428
|
+
template <typename TGR>
|
|
1429
|
+
friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
|
|
1430
|
+
template <typename TGR>
|
|
1431
|
+
friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
|
|
1432
|
+
template <typename TGR>
|
|
1433
|
+
friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
|
|
1434
|
+
|
|
1435
|
+
GraphReader(GraphReader& other)
|
|
1436
|
+
: _is(other._is), local_is(other.local_is), _graph(other._graph),
|
|
1437
|
+
_use_nodes(other._use_nodes), _use_edges(other._use_edges),
|
|
1438
|
+
_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
|
|
1439
|
+
|
|
1440
|
+
other._is = 0;
|
|
1441
|
+
other.local_is = false;
|
|
1442
|
+
|
|
1443
|
+
_node_index.swap(other._node_index);
|
|
1444
|
+
_edge_index.swap(other._edge_index);
|
|
1445
|
+
|
|
1446
|
+
_node_maps.swap(other._node_maps);
|
|
1447
|
+
_edge_maps.swap(other._edge_maps);
|
|
1448
|
+
_attributes.swap(other._attributes);
|
|
1449
|
+
|
|
1450
|
+
_nodes_caption = other._nodes_caption;
|
|
1451
|
+
_edges_caption = other._edges_caption;
|
|
1452
|
+
_attributes_caption = other._attributes_caption;
|
|
1453
|
+
|
|
1454
|
+
}
|
|
1455
|
+
|
|
1456
|
+
GraphReader& operator=(const GraphReader&);
|
|
1457
|
+
|
|
1458
|
+
public:
|
|
1459
|
+
|
|
1460
|
+
/// \name Reading Rules
|
|
1461
|
+
/// @{
|
|
1462
|
+
|
|
1463
|
+
/// \brief Node map reading rule
|
|
1464
|
+
///
|
|
1465
|
+
/// Add a node map reading rule to the reader.
|
|
1466
|
+
template <typename Map>
|
|
1467
|
+
GraphReader& nodeMap(const std::string& caption, Map& map) {
|
|
1468
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
1469
|
+
_reader_bits::MapStorageBase<Node>* storage =
|
|
1470
|
+
new _reader_bits::MapStorage<Node, Map>(map);
|
|
1471
|
+
_node_maps.push_back(std::make_pair(caption, storage));
|
|
1472
|
+
return *this;
|
|
1473
|
+
}
|
|
1474
|
+
|
|
1475
|
+
/// \brief Node map reading rule
|
|
1476
|
+
///
|
|
1477
|
+
/// Add a node map reading rule with specialized converter to the
|
|
1478
|
+
/// reader.
|
|
1479
|
+
template <typename Map, typename Converter>
|
|
1480
|
+
GraphReader& nodeMap(const std::string& caption, Map& map,
|
|
1481
|
+
const Converter& converter = Converter()) {
|
|
1482
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
1483
|
+
_reader_bits::MapStorageBase<Node>* storage =
|
|
1484
|
+
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
|
|
1485
|
+
_node_maps.push_back(std::make_pair(caption, storage));
|
|
1486
|
+
return *this;
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
/// \brief Edge map reading rule
|
|
1490
|
+
///
|
|
1491
|
+
/// Add an edge map reading rule to the reader.
|
|
1492
|
+
template <typename Map>
|
|
1493
|
+
GraphReader& edgeMap(const std::string& caption, Map& map) {
|
|
1494
|
+
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
|
|
1495
|
+
_reader_bits::MapStorageBase<Edge>* storage =
|
|
1496
|
+
new _reader_bits::MapStorage<Edge, Map>(map);
|
|
1497
|
+
_edge_maps.push_back(std::make_pair(caption, storage));
|
|
1498
|
+
return *this;
|
|
1499
|
+
}
|
|
1500
|
+
|
|
1501
|
+
/// \brief Edge map reading rule
|
|
1502
|
+
///
|
|
1503
|
+
/// Add an edge map reading rule with specialized converter to the
|
|
1504
|
+
/// reader.
|
|
1505
|
+
template <typename Map, typename Converter>
|
|
1506
|
+
GraphReader& edgeMap(const std::string& caption, Map& map,
|
|
1507
|
+
const Converter& converter = Converter()) {
|
|
1508
|
+
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
|
|
1509
|
+
_reader_bits::MapStorageBase<Edge>* storage =
|
|
1510
|
+
new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
|
|
1511
|
+
_edge_maps.push_back(std::make_pair(caption, storage));
|
|
1512
|
+
return *this;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
/// \brief Arc map reading rule
|
|
1516
|
+
///
|
|
1517
|
+
/// Add an arc map reading rule to the reader.
|
|
1518
|
+
template <typename Map>
|
|
1519
|
+
GraphReader& arcMap(const std::string& caption, Map& map) {
|
|
1520
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
1521
|
+
_reader_bits::MapStorageBase<Edge>* forward_storage =
|
|
1522
|
+
new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
|
|
1523
|
+
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
|
1524
|
+
_reader_bits::MapStorageBase<Edge>* backward_storage =
|
|
1525
|
+
new _reader_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
|
|
1526
|
+
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
|
1527
|
+
return *this;
|
|
1528
|
+
}
|
|
1529
|
+
|
|
1530
|
+
/// \brief Arc map reading rule
|
|
1531
|
+
///
|
|
1532
|
+
/// Add an arc map reading rule with specialized converter to the
|
|
1533
|
+
/// reader.
|
|
1534
|
+
template <typename Map, typename Converter>
|
|
1535
|
+
GraphReader& arcMap(const std::string& caption, Map& map,
|
|
1536
|
+
const Converter& converter = Converter()) {
|
|
1537
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
1538
|
+
_reader_bits::MapStorageBase<Edge>* forward_storage =
|
|
1539
|
+
new _reader_bits::GraphArcMapStorage<GR, true, Map, Converter>
|
|
1540
|
+
(_graph, map, converter);
|
|
1541
|
+
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
|
1542
|
+
_reader_bits::MapStorageBase<Edge>* backward_storage =
|
|
1543
|
+
new _reader_bits::GraphArcMapStorage<GR, false, Map, Converter>
|
|
1544
|
+
(_graph, map, converter);
|
|
1545
|
+
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
|
1546
|
+
return *this;
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
/// \brief Attribute reading rule
|
|
1550
|
+
///
|
|
1551
|
+
/// Add an attribute reading rule to the reader.
|
|
1552
|
+
template <typename Value>
|
|
1553
|
+
GraphReader& attribute(const std::string& caption, Value& value) {
|
|
1554
|
+
_reader_bits::ValueStorageBase* storage =
|
|
1555
|
+
new _reader_bits::ValueStorage<Value>(value);
|
|
1556
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
1557
|
+
return *this;
|
|
1558
|
+
}
|
|
1559
|
+
|
|
1560
|
+
/// \brief Attribute reading rule
|
|
1561
|
+
///
|
|
1562
|
+
/// Add an attribute reading rule with specialized converter to the
|
|
1563
|
+
/// reader.
|
|
1564
|
+
template <typename Value, typename Converter>
|
|
1565
|
+
GraphReader& attribute(const std::string& caption, Value& value,
|
|
1566
|
+
const Converter& converter = Converter()) {
|
|
1567
|
+
_reader_bits::ValueStorageBase* storage =
|
|
1568
|
+
new _reader_bits::ValueStorage<Value, Converter>(value, converter);
|
|
1569
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
1570
|
+
return *this;
|
|
1571
|
+
}
|
|
1572
|
+
|
|
1573
|
+
/// \brief Node reading rule
|
|
1574
|
+
///
|
|
1575
|
+
/// Add a node reading rule to reader.
|
|
1576
|
+
GraphReader& node(const std::string& caption, Node& node) {
|
|
1577
|
+
typedef _reader_bits::MapLookUpConverter<Node> Converter;
|
|
1578
|
+
Converter converter(_node_index);
|
|
1579
|
+
_reader_bits::ValueStorageBase* storage =
|
|
1580
|
+
new _reader_bits::ValueStorage<Node, Converter>(node, converter);
|
|
1581
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
1582
|
+
return *this;
|
|
1583
|
+
}
|
|
1584
|
+
|
|
1585
|
+
/// \brief Edge reading rule
|
|
1586
|
+
///
|
|
1587
|
+
/// Add an edge reading rule to reader.
|
|
1588
|
+
GraphReader& edge(const std::string& caption, Edge& edge) {
|
|
1589
|
+
typedef _reader_bits::MapLookUpConverter<Edge> Converter;
|
|
1590
|
+
Converter converter(_edge_index);
|
|
1591
|
+
_reader_bits::ValueStorageBase* storage =
|
|
1592
|
+
new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
|
|
1593
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
1594
|
+
return *this;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/// \brief Arc reading rule
|
|
1598
|
+
///
|
|
1599
|
+
/// Add an arc reading rule to reader.
|
|
1600
|
+
GraphReader& arc(const std::string& caption, Arc& arc) {
|
|
1601
|
+
typedef _reader_bits::GraphArcLookUpConverter<GR> Converter;
|
|
1602
|
+
Converter converter(_graph, _edge_index);
|
|
1603
|
+
_reader_bits::ValueStorageBase* storage =
|
|
1604
|
+
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
|
|
1605
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
1606
|
+
return *this;
|
|
1607
|
+
}
|
|
1608
|
+
|
|
1609
|
+
/// @}
|
|
1610
|
+
|
|
1611
|
+
/// \name Select Section by Name
|
|
1612
|
+
/// @{
|
|
1613
|
+
|
|
1614
|
+
/// \brief Set \c \@nodes section to be read
|
|
1615
|
+
///
|
|
1616
|
+
/// Set \c \@nodes section to be read.
|
|
1617
|
+
GraphReader& nodes(const std::string& caption) {
|
|
1618
|
+
_nodes_caption = caption;
|
|
1619
|
+
return *this;
|
|
1620
|
+
}
|
|
1621
|
+
|
|
1622
|
+
/// \brief Set \c \@edges section to be read
|
|
1623
|
+
///
|
|
1624
|
+
/// Set \c \@edges section to be read.
|
|
1625
|
+
GraphReader& edges(const std::string& caption) {
|
|
1626
|
+
_edges_caption = caption;
|
|
1627
|
+
return *this;
|
|
1628
|
+
}
|
|
1629
|
+
|
|
1630
|
+
/// \brief Set \c \@attributes section to be read
|
|
1631
|
+
///
|
|
1632
|
+
/// Set \c \@attributes section to be read.
|
|
1633
|
+
GraphReader& attributes(const std::string& caption) {
|
|
1634
|
+
_attributes_caption = caption;
|
|
1635
|
+
return *this;
|
|
1636
|
+
}
|
|
1637
|
+
|
|
1638
|
+
/// @}
|
|
1639
|
+
|
|
1640
|
+
/// \name Using Previously Constructed Node or Edge Set
|
|
1641
|
+
/// @{
|
|
1642
|
+
|
|
1643
|
+
/// \brief Use previously constructed node set
|
|
1644
|
+
///
|
|
1645
|
+
/// Use previously constructed node set, and specify the node
|
|
1646
|
+
/// label map.
|
|
1647
|
+
template <typename Map>
|
|
1648
|
+
GraphReader& useNodes(const Map& map) {
|
|
1649
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
1650
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
1651
|
+
_use_nodes = true;
|
|
1652
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
1653
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
1654
|
+
_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
1655
|
+
}
|
|
1656
|
+
return *this;
|
|
1657
|
+
}
|
|
1658
|
+
|
|
1659
|
+
/// \brief Use previously constructed node set
|
|
1660
|
+
///
|
|
1661
|
+
/// Use previously constructed node set, and specify the node
|
|
1662
|
+
/// label map and a functor which converts the label map values to
|
|
1663
|
+
/// \c std::string.
|
|
1664
|
+
template <typename Map, typename Converter>
|
|
1665
|
+
GraphReader& useNodes(const Map& map,
|
|
1666
|
+
const Converter& converter = Converter()) {
|
|
1667
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
1668
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
1669
|
+
_use_nodes = true;
|
|
1670
|
+
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
1671
|
+
_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
1672
|
+
}
|
|
1673
|
+
return *this;
|
|
1674
|
+
}
|
|
1675
|
+
|
|
1676
|
+
/// \brief Use previously constructed edge set
|
|
1677
|
+
///
|
|
1678
|
+
/// Use previously constructed edge set, and specify the edge
|
|
1679
|
+
/// label map.
|
|
1680
|
+
template <typename Map>
|
|
1681
|
+
GraphReader& useEdges(const Map& map) {
|
|
1682
|
+
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
|
|
1683
|
+
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
|
|
1684
|
+
_use_edges = true;
|
|
1685
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
1686
|
+
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
|
1687
|
+
_edge_index.insert(std::make_pair(converter(map[a]), a));
|
|
1688
|
+
}
|
|
1689
|
+
return *this;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
/// \brief Use previously constructed edge set
|
|
1693
|
+
///
|
|
1694
|
+
/// Use previously constructed edge set, and specify the edge
|
|
1695
|
+
/// label map and a functor which converts the label map values to
|
|
1696
|
+
/// \c std::string.
|
|
1697
|
+
template <typename Map, typename Converter>
|
|
1698
|
+
GraphReader& useEdges(const Map& map,
|
|
1699
|
+
const Converter& converter = Converter()) {
|
|
1700
|
+
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
|
|
1701
|
+
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
|
|
1702
|
+
_use_edges = true;
|
|
1703
|
+
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
|
1704
|
+
_edge_index.insert(std::make_pair(converter(map[a]), a));
|
|
1705
|
+
}
|
|
1706
|
+
return *this;
|
|
1707
|
+
}
|
|
1708
|
+
|
|
1709
|
+
/// \brief Skip the reading of node section
|
|
1710
|
+
///
|
|
1711
|
+
/// Omit the reading of the node section. This implies that each node
|
|
1712
|
+
/// map reading rule will be abandoned, and the nodes of the graph
|
|
1713
|
+
/// will not be constructed, which usually cause that the edge set
|
|
1714
|
+
/// could not be read due to lack of node name
|
|
1715
|
+
/// could not be read due to lack of node name resolving.
|
|
1716
|
+
/// Therefore \c skipEdges() function should also be used, or
|
|
1717
|
+
/// \c useNodes() should be used to specify the label of the nodes.
|
|
1718
|
+
GraphReader& skipNodes() {
|
|
1719
|
+
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
|
|
1720
|
+
_skip_nodes = true;
|
|
1721
|
+
return *this;
|
|
1722
|
+
}
|
|
1723
|
+
|
|
1724
|
+
/// \brief Skip the reading of edge section
|
|
1725
|
+
///
|
|
1726
|
+
/// Omit the reading of the edge section. This implies that each edge
|
|
1727
|
+
/// map reading rule will be abandoned, and the edges of the graph
|
|
1728
|
+
/// will not be constructed.
|
|
1729
|
+
GraphReader& skipEdges() {
|
|
1730
|
+
LEMON_ASSERT(!_skip_edges, "Skip edges already set");
|
|
1731
|
+
_skip_edges = true;
|
|
1732
|
+
return *this;
|
|
1733
|
+
}
|
|
1734
|
+
|
|
1735
|
+
/// @}
|
|
1736
|
+
|
|
1737
|
+
private:
|
|
1738
|
+
|
|
1739
|
+
bool readLine() {
|
|
1740
|
+
std::string str;
|
|
1741
|
+
while(++line_num, std::getline(*_is, str)) {
|
|
1742
|
+
line.clear(); line.str(str);
|
|
1743
|
+
char c;
|
|
1744
|
+
if (line >> std::ws >> c && c != '#') {
|
|
1745
|
+
line.putback(c);
|
|
1746
|
+
return true;
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
return false;
|
|
1750
|
+
}
|
|
1751
|
+
|
|
1752
|
+
bool readSuccess() {
|
|
1753
|
+
return static_cast<bool>(*_is);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
void skipSection() {
|
|
1757
|
+
char c;
|
|
1758
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
1759
|
+
readLine();
|
|
1760
|
+
}
|
|
1761
|
+
if (readSuccess()) {
|
|
1762
|
+
line.putback(c);
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
|
|
1766
|
+
void readNodes() {
|
|
1767
|
+
|
|
1768
|
+
std::vector<int> map_index(_node_maps.size());
|
|
1769
|
+
int map_num, label_index;
|
|
1770
|
+
|
|
1771
|
+
char c;
|
|
1772
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
1773
|
+
if (readSuccess() && line) line.putback(c);
|
|
1774
|
+
if (!_node_maps.empty())
|
|
1775
|
+
throw FormatError("Cannot find map names");
|
|
1776
|
+
return;
|
|
1777
|
+
}
|
|
1778
|
+
line.putback(c);
|
|
1779
|
+
|
|
1780
|
+
{
|
|
1781
|
+
std::map<std::string, int> maps;
|
|
1782
|
+
|
|
1783
|
+
std::string map;
|
|
1784
|
+
int index = 0;
|
|
1785
|
+
while (_reader_bits::readToken(line, map)) {
|
|
1786
|
+
if (maps.find(map) != maps.end()) {
|
|
1787
|
+
std::ostringstream msg;
|
|
1788
|
+
msg << "Multiple occurence of node map: " << map;
|
|
1789
|
+
throw FormatError(msg.str());
|
|
1790
|
+
}
|
|
1791
|
+
maps.insert(std::make_pair(map, index));
|
|
1792
|
+
++index;
|
|
1793
|
+
}
|
|
1794
|
+
|
|
1795
|
+
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
1796
|
+
std::map<std::string, int>::iterator jt =
|
|
1797
|
+
maps.find(_node_maps[i].first);
|
|
1798
|
+
if (jt == maps.end()) {
|
|
1799
|
+
std::ostringstream msg;
|
|
1800
|
+
msg << "Map not found: " << _node_maps[i].first;
|
|
1801
|
+
throw FormatError(msg.str());
|
|
1802
|
+
}
|
|
1803
|
+
map_index[i] = jt->second;
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
{
|
|
1807
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
1808
|
+
if (jt != maps.end()) {
|
|
1809
|
+
label_index = jt->second;
|
|
1810
|
+
} else {
|
|
1811
|
+
label_index = -1;
|
|
1812
|
+
}
|
|
1813
|
+
}
|
|
1814
|
+
map_num = maps.size();
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
while (readLine() && line >> c && c != '@') {
|
|
1818
|
+
line.putback(c);
|
|
1819
|
+
|
|
1820
|
+
std::vector<std::string> tokens(map_num);
|
|
1821
|
+
for (int i = 0; i < map_num; ++i) {
|
|
1822
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
1823
|
+
std::ostringstream msg;
|
|
1824
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
1825
|
+
throw FormatError(msg.str());
|
|
1826
|
+
}
|
|
1827
|
+
}
|
|
1828
|
+
if (line >> std::ws >> c)
|
|
1829
|
+
throw FormatError("Extra character at the end of line");
|
|
1830
|
+
|
|
1831
|
+
Node n;
|
|
1832
|
+
if (!_use_nodes) {
|
|
1833
|
+
n = _graph.addNode();
|
|
1834
|
+
if (label_index != -1)
|
|
1835
|
+
_node_index.insert(std::make_pair(tokens[label_index], n));
|
|
1836
|
+
} else {
|
|
1837
|
+
if (label_index == -1)
|
|
1838
|
+
throw FormatError("Label map not found");
|
|
1839
|
+
typename std::map<std::string, Node>::iterator it =
|
|
1840
|
+
_node_index.find(tokens[label_index]);
|
|
1841
|
+
if (it == _node_index.end()) {
|
|
1842
|
+
std::ostringstream msg;
|
|
1843
|
+
msg << "Node with label not found: " << tokens[label_index];
|
|
1844
|
+
throw FormatError(msg.str());
|
|
1845
|
+
}
|
|
1846
|
+
n = it->second;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
1850
|
+
_node_maps[i].second->set(n, tokens[map_index[i]]);
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
}
|
|
1854
|
+
if (readSuccess()) {
|
|
1855
|
+
line.putback(c);
|
|
1856
|
+
}
|
|
1857
|
+
}
|
|
1858
|
+
|
|
1859
|
+
void readEdges() {
|
|
1860
|
+
|
|
1861
|
+
std::vector<int> map_index(_edge_maps.size());
|
|
1862
|
+
int map_num, label_index;
|
|
1863
|
+
|
|
1864
|
+
char c;
|
|
1865
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
1866
|
+
if (readSuccess() && line) line.putback(c);
|
|
1867
|
+
if (!_edge_maps.empty())
|
|
1868
|
+
throw FormatError("Cannot find map names");
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
line.putback(c);
|
|
1872
|
+
|
|
1873
|
+
{
|
|
1874
|
+
std::map<std::string, int> maps;
|
|
1875
|
+
|
|
1876
|
+
std::string map;
|
|
1877
|
+
int index = 0;
|
|
1878
|
+
while (_reader_bits::readToken(line, map)) {
|
|
1879
|
+
if(map == "-") {
|
|
1880
|
+
if(index!=0)
|
|
1881
|
+
throw FormatError("'-' is not allowed as a map name");
|
|
1882
|
+
else if (line >> std::ws >> c)
|
|
1883
|
+
throw FormatError("Extra character at the end of line");
|
|
1884
|
+
else break;
|
|
1885
|
+
}
|
|
1886
|
+
if (maps.find(map) != maps.end()) {
|
|
1887
|
+
std::ostringstream msg;
|
|
1888
|
+
msg << "Multiple occurence of edge map: " << map;
|
|
1889
|
+
throw FormatError(msg.str());
|
|
1890
|
+
}
|
|
1891
|
+
maps.insert(std::make_pair(map, index));
|
|
1892
|
+
++index;
|
|
1893
|
+
}
|
|
1894
|
+
|
|
1895
|
+
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
1896
|
+
std::map<std::string, int>::iterator jt =
|
|
1897
|
+
maps.find(_edge_maps[i].first);
|
|
1898
|
+
if (jt == maps.end()) {
|
|
1899
|
+
std::ostringstream msg;
|
|
1900
|
+
msg << "Map not found: " << _edge_maps[i].first;
|
|
1901
|
+
throw FormatError(msg.str());
|
|
1902
|
+
}
|
|
1903
|
+
map_index[i] = jt->second;
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
{
|
|
1907
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
1908
|
+
if (jt != maps.end()) {
|
|
1909
|
+
label_index = jt->second;
|
|
1910
|
+
} else {
|
|
1911
|
+
label_index = -1;
|
|
1912
|
+
}
|
|
1913
|
+
}
|
|
1914
|
+
map_num = maps.size();
|
|
1915
|
+
}
|
|
1916
|
+
|
|
1917
|
+
while (readLine() && line >> c && c != '@') {
|
|
1918
|
+
line.putback(c);
|
|
1919
|
+
|
|
1920
|
+
std::string source_token;
|
|
1921
|
+
std::string target_token;
|
|
1922
|
+
|
|
1923
|
+
if (!_reader_bits::readToken(line, source_token))
|
|
1924
|
+
throw FormatError("Node u not found");
|
|
1925
|
+
|
|
1926
|
+
if (!_reader_bits::readToken(line, target_token))
|
|
1927
|
+
throw FormatError("Node v not found");
|
|
1928
|
+
|
|
1929
|
+
std::vector<std::string> tokens(map_num);
|
|
1930
|
+
for (int i = 0; i < map_num; ++i) {
|
|
1931
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
1932
|
+
std::ostringstream msg;
|
|
1933
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
1934
|
+
throw FormatError(msg.str());
|
|
1935
|
+
}
|
|
1936
|
+
}
|
|
1937
|
+
if (line >> std::ws >> c)
|
|
1938
|
+
throw FormatError("Extra character at the end of line");
|
|
1939
|
+
|
|
1940
|
+
Edge e;
|
|
1941
|
+
if (!_use_edges) {
|
|
1942
|
+
|
|
1943
|
+
typename NodeIndex::iterator it;
|
|
1944
|
+
|
|
1945
|
+
it = _node_index.find(source_token);
|
|
1946
|
+
if (it == _node_index.end()) {
|
|
1947
|
+
std::ostringstream msg;
|
|
1948
|
+
msg << "Item not found: " << source_token;
|
|
1949
|
+
throw FormatError(msg.str());
|
|
1950
|
+
}
|
|
1951
|
+
Node source = it->second;
|
|
1952
|
+
|
|
1953
|
+
it = _node_index.find(target_token);
|
|
1954
|
+
if (it == _node_index.end()) {
|
|
1955
|
+
std::ostringstream msg;
|
|
1956
|
+
msg << "Item not found: " << target_token;
|
|
1957
|
+
throw FormatError(msg.str());
|
|
1958
|
+
}
|
|
1959
|
+
Node target = it->second;
|
|
1960
|
+
|
|
1961
|
+
e = _graph.addEdge(source, target);
|
|
1962
|
+
if (label_index != -1)
|
|
1963
|
+
_edge_index.insert(std::make_pair(tokens[label_index], e));
|
|
1964
|
+
} else {
|
|
1965
|
+
if (label_index == -1)
|
|
1966
|
+
throw FormatError("Label map not found");
|
|
1967
|
+
typename std::map<std::string, Edge>::iterator it =
|
|
1968
|
+
_edge_index.find(tokens[label_index]);
|
|
1969
|
+
if (it == _edge_index.end()) {
|
|
1970
|
+
std::ostringstream msg;
|
|
1971
|
+
msg << "Edge with label not found: " << tokens[label_index];
|
|
1972
|
+
throw FormatError(msg.str());
|
|
1973
|
+
}
|
|
1974
|
+
e = it->second;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
1978
|
+
_edge_maps[i].second->set(e, tokens[map_index[i]]);
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
}
|
|
1982
|
+
if (readSuccess()) {
|
|
1983
|
+
line.putback(c);
|
|
1984
|
+
}
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
void readAttributes() {
|
|
1988
|
+
|
|
1989
|
+
std::set<std::string> read_attr;
|
|
1990
|
+
|
|
1991
|
+
char c;
|
|
1992
|
+
while (readLine() && line >> c && c != '@') {
|
|
1993
|
+
line.putback(c);
|
|
1994
|
+
|
|
1995
|
+
std::string attr, token;
|
|
1996
|
+
if (!_reader_bits::readToken(line, attr))
|
|
1997
|
+
throw FormatError("Attribute name not found");
|
|
1998
|
+
if (!_reader_bits::readToken(line, token))
|
|
1999
|
+
throw FormatError("Attribute value not found");
|
|
2000
|
+
if (line >> c)
|
|
2001
|
+
throw FormatError("Extra character at the end of line");
|
|
2002
|
+
|
|
2003
|
+
{
|
|
2004
|
+
std::set<std::string>::iterator it = read_attr.find(attr);
|
|
2005
|
+
if (it != read_attr.end()) {
|
|
2006
|
+
std::ostringstream msg;
|
|
2007
|
+
msg << "Multiple occurence of attribute: " << attr;
|
|
2008
|
+
throw FormatError(msg.str());
|
|
2009
|
+
}
|
|
2010
|
+
read_attr.insert(attr);
|
|
2011
|
+
}
|
|
2012
|
+
|
|
2013
|
+
{
|
|
2014
|
+
typename Attributes::iterator it = _attributes.lower_bound(attr);
|
|
2015
|
+
while (it != _attributes.end() && it->first == attr) {
|
|
2016
|
+
it->second->set(token);
|
|
2017
|
+
++it;
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
}
|
|
2022
|
+
if (readSuccess()) {
|
|
2023
|
+
line.putback(c);
|
|
2024
|
+
}
|
|
2025
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
2026
|
+
it != _attributes.end(); ++it) {
|
|
2027
|
+
if (read_attr.find(it->first) == read_attr.end()) {
|
|
2028
|
+
std::ostringstream msg;
|
|
2029
|
+
msg << "Attribute not found: " << it->first;
|
|
2030
|
+
throw FormatError(msg.str());
|
|
2031
|
+
}
|
|
2032
|
+
}
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
public:
|
|
2036
|
+
|
|
2037
|
+
/// \name Execution of the Reader
|
|
2038
|
+
/// @{
|
|
2039
|
+
|
|
2040
|
+
/// \brief Start the batch processing
|
|
2041
|
+
///
|
|
2042
|
+
/// This function starts the batch processing
|
|
2043
|
+
void run() {
|
|
2044
|
+
|
|
2045
|
+
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
|
|
2046
|
+
|
|
2047
|
+
bool nodes_done = _skip_nodes;
|
|
2048
|
+
bool edges_done = _skip_edges;
|
|
2049
|
+
bool attributes_done = false;
|
|
2050
|
+
|
|
2051
|
+
line_num = 0;
|
|
2052
|
+
readLine();
|
|
2053
|
+
skipSection();
|
|
2054
|
+
|
|
2055
|
+
while (readSuccess()) {
|
|
2056
|
+
try {
|
|
2057
|
+
char c;
|
|
2058
|
+
std::string section, caption;
|
|
2059
|
+
line >> c;
|
|
2060
|
+
_reader_bits::readToken(line, section);
|
|
2061
|
+
_reader_bits::readToken(line, caption);
|
|
2062
|
+
|
|
2063
|
+
if (line >> c)
|
|
2064
|
+
throw FormatError("Extra character at the end of line");
|
|
2065
|
+
|
|
2066
|
+
if (section == "nodes" && !nodes_done) {
|
|
2067
|
+
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
2068
|
+
readNodes();
|
|
2069
|
+
nodes_done = true;
|
|
2070
|
+
}
|
|
2071
|
+
} else if ((section == "edges" || section == "arcs") &&
|
|
2072
|
+
!edges_done) {
|
|
2073
|
+
if (_edges_caption.empty() || _edges_caption == caption) {
|
|
2074
|
+
readEdges();
|
|
2075
|
+
edges_done = true;
|
|
2076
|
+
}
|
|
2077
|
+
} else if (section == "attributes" && !attributes_done) {
|
|
2078
|
+
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
2079
|
+
readAttributes();
|
|
2080
|
+
attributes_done = true;
|
|
2081
|
+
}
|
|
2082
|
+
} else {
|
|
2083
|
+
readLine();
|
|
2084
|
+
skipSection();
|
|
2085
|
+
}
|
|
2086
|
+
} catch (FormatError& error) {
|
|
2087
|
+
error.line(line_num);
|
|
2088
|
+
error.file(_filename);
|
|
2089
|
+
throw;
|
|
2090
|
+
}
|
|
2091
|
+
}
|
|
2092
|
+
|
|
2093
|
+
if (!nodes_done) {
|
|
2094
|
+
throw FormatError("Section @nodes not found");
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
if (!edges_done) {
|
|
2098
|
+
throw FormatError("Section @edges not found");
|
|
2099
|
+
}
|
|
2100
|
+
|
|
2101
|
+
if (!attributes_done && !_attributes.empty()) {
|
|
2102
|
+
throw FormatError("Section @attributes not found");
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
}
|
|
2106
|
+
|
|
2107
|
+
/// @}
|
|
2108
|
+
|
|
2109
|
+
};
|
|
2110
|
+
|
|
2111
|
+
/// \ingroup lemon_io
|
|
2112
|
+
///
|
|
2113
|
+
/// \brief Return a \ref lemon::GraphReader "GraphReader" class
|
|
2114
|
+
///
|
|
2115
|
+
/// This function just returns a \ref lemon::GraphReader "GraphReader" class.
|
|
2116
|
+
///
|
|
2117
|
+
/// With this function a graph can be read from an
|
|
2118
|
+
/// \ref lgf-format "LGF" file or input stream with several maps and
|
|
2119
|
+
/// attributes. For example, there is weighted matching problem on a
|
|
2120
|
+
/// graph, i.e. a graph with a \e weight map on the edges. This
|
|
2121
|
+
/// graph can be read with the following code:
|
|
2122
|
+
///
|
|
2123
|
+
///\code
|
|
2124
|
+
///ListGraph graph;
|
|
2125
|
+
///ListGraph::EdgeMap<int> weight(graph);
|
|
2126
|
+
///graphReader(graph, std::cin).
|
|
2127
|
+
/// edgeMap("weight", weight).
|
|
2128
|
+
/// run();
|
|
2129
|
+
///\endcode
|
|
2130
|
+
///
|
|
2131
|
+
/// For a complete documentation, please see the
|
|
2132
|
+
/// \ref lemon::GraphReader "GraphReader"
|
|
2133
|
+
/// class documentation.
|
|
2134
|
+
/// \warning Don't forget to put the \ref lemon::GraphReader::run() "run()"
|
|
2135
|
+
/// to the end of the parameter list.
|
|
2136
|
+
/// \relates GraphReader
|
|
2137
|
+
/// \sa graphReader(TGR& graph, const std::string& fn)
|
|
2138
|
+
/// \sa graphReader(TGR& graph, const char* fn)
|
|
2139
|
+
template <typename TGR>
|
|
2140
|
+
GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
|
|
2141
|
+
GraphReader<TGR> tmp(graph, is);
|
|
2142
|
+
return tmp;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2145
|
+
/// \brief Return a \ref GraphReader class
|
|
2146
|
+
///
|
|
2147
|
+
/// This function just returns a \ref GraphReader class.
|
|
2148
|
+
/// \relates GraphReader
|
|
2149
|
+
/// \sa graphReader(TGR& graph, std::istream& is)
|
|
2150
|
+
template <typename TGR>
|
|
2151
|
+
GraphReader<TGR> graphReader(TGR& graph, const std::string& fn) {
|
|
2152
|
+
GraphReader<TGR> tmp(graph, fn);
|
|
2153
|
+
return tmp;
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
/// \brief Return a \ref GraphReader class
|
|
2157
|
+
///
|
|
2158
|
+
/// This function just returns a \ref GraphReader class.
|
|
2159
|
+
/// \relates GraphReader
|
|
2160
|
+
/// \sa graphReader(TGR& graph, std::istream& is)
|
|
2161
|
+
template <typename TGR>
|
|
2162
|
+
GraphReader<TGR> graphReader(TGR& graph, const char* fn) {
|
|
2163
|
+
GraphReader<TGR> tmp(graph, fn);
|
|
2164
|
+
return tmp;
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
template <typename BGR>
|
|
2168
|
+
class BpGraphReader;
|
|
2169
|
+
|
|
2170
|
+
template <typename TBGR>
|
|
2171
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
|
|
2172
|
+
template <typename TBGR>
|
|
2173
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
|
|
2174
|
+
template <typename TBGR>
|
|
2175
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
|
|
2176
|
+
|
|
2177
|
+
/// \ingroup lemon_io
|
|
2178
|
+
///
|
|
2179
|
+
/// \brief \ref lgf-format "LGF" reader for bipartite graphs
|
|
2180
|
+
///
|
|
2181
|
+
/// This utility reads an \ref lgf-format "LGF" file.
|
|
2182
|
+
///
|
|
2183
|
+
/// It can be used almost the same way as \c GraphReader, but it
|
|
2184
|
+
/// reads the red and blue nodes from separate sections, and these
|
|
2185
|
+
/// sections can contain different set of maps.
|
|
2186
|
+
///
|
|
2187
|
+
/// The red and blue node maps are read from the corresponding
|
|
2188
|
+
/// sections. If a map is defined with the same name in both of
|
|
2189
|
+
/// these sections, then it can be read as a node map.
|
|
2190
|
+
template <typename BGR>
|
|
2191
|
+
class BpGraphReader {
|
|
2192
|
+
public:
|
|
2193
|
+
|
|
2194
|
+
typedef BGR Graph;
|
|
2195
|
+
|
|
2196
|
+
private:
|
|
2197
|
+
|
|
2198
|
+
TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
|
|
2199
|
+
|
|
2200
|
+
std::istream* _is;
|
|
2201
|
+
bool local_is;
|
|
2202
|
+
std::string _filename;
|
|
2203
|
+
|
|
2204
|
+
BGR& _graph;
|
|
2205
|
+
|
|
2206
|
+
std::string _nodes_caption;
|
|
2207
|
+
std::string _edges_caption;
|
|
2208
|
+
std::string _attributes_caption;
|
|
2209
|
+
|
|
2210
|
+
typedef std::map<std::string, RedNode> RedNodeIndex;
|
|
2211
|
+
RedNodeIndex _red_node_index;
|
|
2212
|
+
typedef std::map<std::string, BlueNode> BlueNodeIndex;
|
|
2213
|
+
BlueNodeIndex _blue_node_index;
|
|
2214
|
+
typedef std::map<std::string, Edge> EdgeIndex;
|
|
2215
|
+
EdgeIndex _edge_index;
|
|
2216
|
+
|
|
2217
|
+
typedef std::vector<std::pair<std::string,
|
|
2218
|
+
_reader_bits::MapStorageBase<RedNode>*> > RedNodeMaps;
|
|
2219
|
+
RedNodeMaps _red_node_maps;
|
|
2220
|
+
typedef std::vector<std::pair<std::string,
|
|
2221
|
+
_reader_bits::MapStorageBase<BlueNode>*> > BlueNodeMaps;
|
|
2222
|
+
BlueNodeMaps _blue_node_maps;
|
|
2223
|
+
|
|
2224
|
+
typedef std::vector<std::pair<std::string,
|
|
2225
|
+
_reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
|
|
2226
|
+
EdgeMaps _edge_maps;
|
|
2227
|
+
|
|
2228
|
+
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
|
|
2229
|
+
Attributes;
|
|
2230
|
+
Attributes _attributes;
|
|
2231
|
+
|
|
2232
|
+
bool _use_nodes;
|
|
2233
|
+
bool _use_edges;
|
|
2234
|
+
|
|
2235
|
+
bool _skip_nodes;
|
|
2236
|
+
bool _skip_edges;
|
|
2237
|
+
|
|
2238
|
+
int line_num;
|
|
2239
|
+
std::istringstream line;
|
|
2240
|
+
|
|
2241
|
+
public:
|
|
2242
|
+
|
|
2243
|
+
/// \brief Constructor
|
|
2244
|
+
///
|
|
2245
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
2246
|
+
/// input stream.
|
|
2247
|
+
BpGraphReader(BGR& graph, std::istream& is = std::cin)
|
|
2248
|
+
: _is(&is), local_is(false), _graph(graph),
|
|
2249
|
+
_use_nodes(false), _use_edges(false),
|
|
2250
|
+
_skip_nodes(false), _skip_edges(false) {}
|
|
2251
|
+
|
|
2252
|
+
/// \brief Constructor
|
|
2253
|
+
///
|
|
2254
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
2255
|
+
/// file.
|
|
2256
|
+
BpGraphReader(BGR& graph, const std::string& fn)
|
|
2257
|
+
: _is(new std::ifstream(fn.c_str())), local_is(true),
|
|
2258
|
+
_filename(fn), _graph(graph),
|
|
2259
|
+
_use_nodes(false), _use_edges(false),
|
|
2260
|
+
_skip_nodes(false), _skip_edges(false) {
|
|
2261
|
+
if (!(*_is)) {
|
|
2262
|
+
delete _is;
|
|
2263
|
+
throw IoError("Cannot open file", fn);
|
|
2264
|
+
}
|
|
2265
|
+
}
|
|
2266
|
+
|
|
2267
|
+
/// \brief Constructor
|
|
2268
|
+
///
|
|
2269
|
+
/// Construct an undirected graph reader, which reads from the given
|
|
2270
|
+
/// file.
|
|
2271
|
+
BpGraphReader(BGR& graph, const char* fn)
|
|
2272
|
+
: _is(new std::ifstream(fn)), local_is(true),
|
|
2273
|
+
_filename(fn), _graph(graph),
|
|
2274
|
+
_use_nodes(false), _use_edges(false),
|
|
2275
|
+
_skip_nodes(false), _skip_edges(false) {
|
|
2276
|
+
if (!(*_is)) {
|
|
2277
|
+
delete _is;
|
|
2278
|
+
throw IoError("Cannot open file", fn);
|
|
2279
|
+
}
|
|
2280
|
+
}
|
|
2281
|
+
|
|
2282
|
+
/// \brief Destructor
|
|
2283
|
+
~BpGraphReader() {
|
|
2284
|
+
for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
|
|
2285
|
+
it != _red_node_maps.end(); ++it) {
|
|
2286
|
+
delete it->second;
|
|
2287
|
+
}
|
|
2288
|
+
|
|
2289
|
+
for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
|
|
2290
|
+
it != _blue_node_maps.end(); ++it) {
|
|
2291
|
+
delete it->second;
|
|
2292
|
+
}
|
|
2293
|
+
|
|
2294
|
+
for (typename EdgeMaps::iterator it = _edge_maps.begin();
|
|
2295
|
+
it != _edge_maps.end(); ++it) {
|
|
2296
|
+
delete it->second;
|
|
2297
|
+
}
|
|
2298
|
+
|
|
2299
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
2300
|
+
it != _attributes.end(); ++it) {
|
|
2301
|
+
delete it->second;
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
if (local_is) {
|
|
2305
|
+
delete _is;
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
}
|
|
2309
|
+
|
|
2310
|
+
private:
|
|
2311
|
+
template <typename TBGR>
|
|
2312
|
+
friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
|
|
2313
|
+
template <typename TBGR>
|
|
2314
|
+
friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
|
|
2315
|
+
const std::string& fn);
|
|
2316
|
+
template <typename TBGR>
|
|
2317
|
+
friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
|
|
2318
|
+
|
|
2319
|
+
BpGraphReader(BpGraphReader& other)
|
|
2320
|
+
: _is(other._is), local_is(other.local_is), _graph(other._graph),
|
|
2321
|
+
_use_nodes(other._use_nodes), _use_edges(other._use_edges),
|
|
2322
|
+
_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
|
|
2323
|
+
|
|
2324
|
+
other._is = 0;
|
|
2325
|
+
other.local_is = false;
|
|
2326
|
+
|
|
2327
|
+
_red_node_index.swap(other._red_node_index);
|
|
2328
|
+
_blue_node_index.swap(other._blue_node_index);
|
|
2329
|
+
_edge_index.swap(other._edge_index);
|
|
2330
|
+
|
|
2331
|
+
_red_node_maps.swap(other._red_node_maps);
|
|
2332
|
+
_blue_node_maps.swap(other._blue_node_maps);
|
|
2333
|
+
_edge_maps.swap(other._edge_maps);
|
|
2334
|
+
_attributes.swap(other._attributes);
|
|
2335
|
+
|
|
2336
|
+
_nodes_caption = other._nodes_caption;
|
|
2337
|
+
_edges_caption = other._edges_caption;
|
|
2338
|
+
_attributes_caption = other._attributes_caption;
|
|
2339
|
+
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
BpGraphReader& operator=(const BpGraphReader&);
|
|
2343
|
+
|
|
2344
|
+
public:
|
|
2345
|
+
|
|
2346
|
+
/// \name Reading Rules
|
|
2347
|
+
/// @{
|
|
2348
|
+
|
|
2349
|
+
/// \brief Node map reading rule
|
|
2350
|
+
///
|
|
2351
|
+
/// Add a node map reading rule to the reader.
|
|
2352
|
+
template <typename Map>
|
|
2353
|
+
BpGraphReader& nodeMap(const std::string& caption, Map& map) {
|
|
2354
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
2355
|
+
_reader_bits::MapStorageBase<RedNode>* red_storage =
|
|
2356
|
+
new _reader_bits::MapStorage<RedNode, Map>(map);
|
|
2357
|
+
_red_node_maps.push_back(std::make_pair(caption, red_storage));
|
|
2358
|
+
_reader_bits::MapStorageBase<BlueNode>* blue_storage =
|
|
2359
|
+
new _reader_bits::MapStorage<BlueNode, Map>(map);
|
|
2360
|
+
_blue_node_maps.push_back(std::make_pair(caption, blue_storage));
|
|
2361
|
+
return *this;
|
|
2362
|
+
}
|
|
2363
|
+
|
|
2364
|
+
/// \brief Node map reading rule
|
|
2365
|
+
///
|
|
2366
|
+
/// Add a node map reading rule with specialized converter to the
|
|
2367
|
+
/// reader.
|
|
2368
|
+
template <typename Map, typename Converter>
|
|
2369
|
+
BpGraphReader& nodeMap(const std::string& caption, Map& map,
|
|
2370
|
+
const Converter& converter = Converter()) {
|
|
2371
|
+
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
|
|
2372
|
+
_reader_bits::MapStorageBase<RedNode>* red_storage =
|
|
2373
|
+
new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
|
|
2374
|
+
_red_node_maps.push_back(std::make_pair(caption, red_storage));
|
|
2375
|
+
_reader_bits::MapStorageBase<BlueNode>* blue_storage =
|
|
2376
|
+
new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
|
|
2377
|
+
_blue_node_maps.push_back(std::make_pair(caption, blue_storage));
|
|
2378
|
+
return *this;
|
|
2379
|
+
}
|
|
2380
|
+
|
|
2381
|
+
/// Add a red node map reading rule to the reader.
|
|
2382
|
+
template <typename Map>
|
|
2383
|
+
BpGraphReader& redNodeMap(const std::string& caption, Map& map) {
|
|
2384
|
+
checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
|
|
2385
|
+
_reader_bits::MapStorageBase<RedNode>* storage =
|
|
2386
|
+
new _reader_bits::MapStorage<RedNode, Map>(map);
|
|
2387
|
+
_red_node_maps.push_back(std::make_pair(caption, storage));
|
|
2388
|
+
return *this;
|
|
2389
|
+
}
|
|
2390
|
+
|
|
2391
|
+
/// \brief Red node map reading rule
|
|
2392
|
+
///
|
|
2393
|
+
/// Add a red node map node reading rule with specialized converter to
|
|
2394
|
+
/// the reader.
|
|
2395
|
+
template <typename Map, typename Converter>
|
|
2396
|
+
BpGraphReader& redNodeMap(const std::string& caption, Map& map,
|
|
2397
|
+
const Converter& converter = Converter()) {
|
|
2398
|
+
checkConcept<concepts::WriteMap<RedNode, typename Map::Value>, Map>();
|
|
2399
|
+
_reader_bits::MapStorageBase<RedNode>* storage =
|
|
2400
|
+
new _reader_bits::MapStorage<RedNode, Map, Converter>(map, converter);
|
|
2401
|
+
_red_node_maps.push_back(std::make_pair(caption, storage));
|
|
2402
|
+
return *this;
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
/// Add a blue node map reading rule to the reader.
|
|
2406
|
+
template <typename Map>
|
|
2407
|
+
BpGraphReader& blueNodeMap(const std::string& caption, Map& map) {
|
|
2408
|
+
checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
|
|
2409
|
+
_reader_bits::MapStorageBase<BlueNode>* storage =
|
|
2410
|
+
new _reader_bits::MapStorage<BlueNode, Map>(map);
|
|
2411
|
+
_blue_node_maps.push_back(std::make_pair(caption, storage));
|
|
2412
|
+
return *this;
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
/// \brief Blue node map reading rule
|
|
2416
|
+
///
|
|
2417
|
+
/// Add a blue node map reading rule with specialized converter to
|
|
2418
|
+
/// the reader.
|
|
2419
|
+
template <typename Map, typename Converter>
|
|
2420
|
+
BpGraphReader& blueNodeMap(const std::string& caption, Map& map,
|
|
2421
|
+
const Converter& converter = Converter()) {
|
|
2422
|
+
checkConcept<concepts::WriteMap<BlueNode, typename Map::Value>, Map>();
|
|
2423
|
+
_reader_bits::MapStorageBase<BlueNode>* storage =
|
|
2424
|
+
new _reader_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
|
|
2425
|
+
_blue_node_maps.push_back(std::make_pair(caption, storage));
|
|
2426
|
+
return *this;
|
|
2427
|
+
}
|
|
2428
|
+
|
|
2429
|
+
/// \brief Edge map reading rule
|
|
2430
|
+
///
|
|
2431
|
+
/// Add an edge map reading rule to the reader.
|
|
2432
|
+
template <typename Map>
|
|
2433
|
+
BpGraphReader& edgeMap(const std::string& caption, Map& map) {
|
|
2434
|
+
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
|
|
2435
|
+
_reader_bits::MapStorageBase<Edge>* storage =
|
|
2436
|
+
new _reader_bits::MapStorage<Edge, Map>(map);
|
|
2437
|
+
_edge_maps.push_back(std::make_pair(caption, storage));
|
|
2438
|
+
return *this;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
/// \brief Edge map reading rule
|
|
2442
|
+
///
|
|
2443
|
+
/// Add an edge map reading rule with specialized converter to the
|
|
2444
|
+
/// reader.
|
|
2445
|
+
template <typename Map, typename Converter>
|
|
2446
|
+
BpGraphReader& edgeMap(const std::string& caption, Map& map,
|
|
2447
|
+
const Converter& converter = Converter()) {
|
|
2448
|
+
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
|
|
2449
|
+
_reader_bits::MapStorageBase<Edge>* storage =
|
|
2450
|
+
new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
|
|
2451
|
+
_edge_maps.push_back(std::make_pair(caption, storage));
|
|
2452
|
+
return *this;
|
|
2453
|
+
}
|
|
2454
|
+
|
|
2455
|
+
/// \brief Arc map reading rule
|
|
2456
|
+
///
|
|
2457
|
+
/// Add an arc map reading rule to the reader.
|
|
2458
|
+
template <typename Map>
|
|
2459
|
+
BpGraphReader& arcMap(const std::string& caption, Map& map) {
|
|
2460
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
2461
|
+
_reader_bits::MapStorageBase<Edge>* forward_storage =
|
|
2462
|
+
new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
|
|
2463
|
+
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
|
2464
|
+
_reader_bits::MapStorageBase<Edge>* backward_storage =
|
|
2465
|
+
new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
|
|
2466
|
+
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
|
2467
|
+
return *this;
|
|
2468
|
+
}
|
|
2469
|
+
|
|
2470
|
+
/// \brief Arc map reading rule
|
|
2471
|
+
///
|
|
2472
|
+
/// Add an arc map reading rule with specialized converter to the
|
|
2473
|
+
/// reader.
|
|
2474
|
+
template <typename Map, typename Converter>
|
|
2475
|
+
BpGraphReader& arcMap(const std::string& caption, Map& map,
|
|
2476
|
+
const Converter& converter = Converter()) {
|
|
2477
|
+
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
|
|
2478
|
+
_reader_bits::MapStorageBase<Edge>* forward_storage =
|
|
2479
|
+
new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
|
|
2480
|
+
(_graph, map, converter);
|
|
2481
|
+
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
|
2482
|
+
_reader_bits::MapStorageBase<Edge>* backward_storage =
|
|
2483
|
+
new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
|
|
2484
|
+
(_graph, map, converter);
|
|
2485
|
+
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
|
2486
|
+
return *this;
|
|
2487
|
+
}
|
|
2488
|
+
|
|
2489
|
+
/// \brief Attribute reading rule
|
|
2490
|
+
///
|
|
2491
|
+
/// Add an attribute reading rule to the reader.
|
|
2492
|
+
template <typename Value>
|
|
2493
|
+
BpGraphReader& attribute(const std::string& caption, Value& value) {
|
|
2494
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2495
|
+
new _reader_bits::ValueStorage<Value>(value);
|
|
2496
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2497
|
+
return *this;
|
|
2498
|
+
}
|
|
2499
|
+
|
|
2500
|
+
/// \brief Attribute reading rule
|
|
2501
|
+
///
|
|
2502
|
+
/// Add an attribute reading rule with specialized converter to the
|
|
2503
|
+
/// reader.
|
|
2504
|
+
template <typename Value, typename Converter>
|
|
2505
|
+
BpGraphReader& attribute(const std::string& caption, Value& value,
|
|
2506
|
+
const Converter& converter = Converter()) {
|
|
2507
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2508
|
+
new _reader_bits::ValueStorage<Value, Converter>(value, converter);
|
|
2509
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2510
|
+
return *this;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
/// \brief Node reading rule
|
|
2514
|
+
///
|
|
2515
|
+
/// Add a node reading rule to reader.
|
|
2516
|
+
BpGraphReader& node(const std::string& caption, Node& node) {
|
|
2517
|
+
typedef _reader_bits::DoubleMapLookUpConverter<
|
|
2518
|
+
Node, RedNodeIndex, BlueNodeIndex> Converter;
|
|
2519
|
+
Converter converter(_red_node_index, _blue_node_index);
|
|
2520
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2521
|
+
new _reader_bits::ValueStorage<Node, Converter>(node, converter);
|
|
2522
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2523
|
+
return *this;
|
|
2524
|
+
}
|
|
2525
|
+
|
|
2526
|
+
/// \brief Red node reading rule
|
|
2527
|
+
///
|
|
2528
|
+
/// Add a red node reading rule to reader.
|
|
2529
|
+
BpGraphReader& redNode(const std::string& caption, RedNode& node) {
|
|
2530
|
+
typedef _reader_bits::MapLookUpConverter<RedNode> Converter;
|
|
2531
|
+
Converter converter(_red_node_index);
|
|
2532
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2533
|
+
new _reader_bits::ValueStorage<RedNode, Converter>(node, converter);
|
|
2534
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2535
|
+
return *this;
|
|
2536
|
+
}
|
|
2537
|
+
|
|
2538
|
+
/// \brief Blue node reading rule
|
|
2539
|
+
///
|
|
2540
|
+
/// Add a blue node reading rule to reader.
|
|
2541
|
+
BpGraphReader& blueNode(const std::string& caption, BlueNode& node) {
|
|
2542
|
+
typedef _reader_bits::MapLookUpConverter<BlueNode> Converter;
|
|
2543
|
+
Converter converter(_blue_node_index);
|
|
2544
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2545
|
+
new _reader_bits::ValueStorage<BlueNode, Converter>(node, converter);
|
|
2546
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2547
|
+
return *this;
|
|
2548
|
+
}
|
|
2549
|
+
|
|
2550
|
+
/// \brief Edge reading rule
|
|
2551
|
+
///
|
|
2552
|
+
/// Add an edge reading rule to reader.
|
|
2553
|
+
BpGraphReader& edge(const std::string& caption, Edge& edge) {
|
|
2554
|
+
typedef _reader_bits::MapLookUpConverter<Edge> Converter;
|
|
2555
|
+
Converter converter(_edge_index);
|
|
2556
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2557
|
+
new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
|
|
2558
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2559
|
+
return *this;
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
/// \brief Arc reading rule
|
|
2563
|
+
///
|
|
2564
|
+
/// Add an arc reading rule to reader.
|
|
2565
|
+
BpGraphReader& arc(const std::string& caption, Arc& arc) {
|
|
2566
|
+
typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
|
|
2567
|
+
Converter converter(_graph, _edge_index);
|
|
2568
|
+
_reader_bits::ValueStorageBase* storage =
|
|
2569
|
+
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
|
|
2570
|
+
_attributes.insert(std::make_pair(caption, storage));
|
|
2571
|
+
return *this;
|
|
2572
|
+
}
|
|
2573
|
+
|
|
2574
|
+
/// @}
|
|
2575
|
+
|
|
2576
|
+
/// \name Select Section by Name
|
|
2577
|
+
/// @{
|
|
2578
|
+
|
|
2579
|
+
/// \brief Set \c \@nodes section to be read
|
|
2580
|
+
///
|
|
2581
|
+
/// Set \c \@nodes section to be read.
|
|
2582
|
+
BpGraphReader& nodes(const std::string& caption) {
|
|
2583
|
+
_nodes_caption = caption;
|
|
2584
|
+
return *this;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
/// \brief Set \c \@edges section to be read
|
|
2588
|
+
///
|
|
2589
|
+
/// Set \c \@edges section to be read.
|
|
2590
|
+
BpGraphReader& edges(const std::string& caption) {
|
|
2591
|
+
_edges_caption = caption;
|
|
2592
|
+
return *this;
|
|
2593
|
+
}
|
|
2594
|
+
|
|
2595
|
+
/// \brief Set \c \@attributes section to be read
|
|
2596
|
+
///
|
|
2597
|
+
/// Set \c \@attributes section to be read.
|
|
2598
|
+
BpGraphReader& attributes(const std::string& caption) {
|
|
2599
|
+
_attributes_caption = caption;
|
|
2600
|
+
return *this;
|
|
2601
|
+
}
|
|
2602
|
+
|
|
2603
|
+
/// @}
|
|
2604
|
+
|
|
2605
|
+
/// \name Using Previously Constructed Node or Edge Set
|
|
2606
|
+
/// @{
|
|
2607
|
+
|
|
2608
|
+
/// \brief Use previously constructed node set
|
|
2609
|
+
///
|
|
2610
|
+
/// Use previously constructed node set, and specify the node
|
|
2611
|
+
/// label map.
|
|
2612
|
+
template <typename Map>
|
|
2613
|
+
BpGraphReader& useNodes(const Map& map) {
|
|
2614
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
2615
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
2616
|
+
_use_nodes = true;
|
|
2617
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
2618
|
+
for (RedNodeIt n(_graph); n != INVALID; ++n) {
|
|
2619
|
+
_red_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
2620
|
+
}
|
|
2621
|
+
for (BlueNodeIt n(_graph); n != INVALID; ++n) {
|
|
2622
|
+
_blue_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
2623
|
+
}
|
|
2624
|
+
return *this;
|
|
2625
|
+
}
|
|
2626
|
+
|
|
2627
|
+
/// \brief Use previously constructed node set
|
|
2628
|
+
///
|
|
2629
|
+
/// Use previously constructed node set, and specify the node
|
|
2630
|
+
/// label map and a functor which converts the label map values to
|
|
2631
|
+
/// \c std::string.
|
|
2632
|
+
template <typename Map, typename Converter>
|
|
2633
|
+
BpGraphReader& useNodes(const Map& map,
|
|
2634
|
+
const Converter& converter = Converter()) {
|
|
2635
|
+
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
|
|
2636
|
+
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
|
|
2637
|
+
_use_nodes = true;
|
|
2638
|
+
for (RedNodeIt n(_graph); n != INVALID; ++n) {
|
|
2639
|
+
_red_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
2640
|
+
}
|
|
2641
|
+
for (BlueNodeIt n(_graph); n != INVALID; ++n) {
|
|
2642
|
+
_blue_node_index.insert(std::make_pair(converter(map[n]), n));
|
|
2643
|
+
}
|
|
2644
|
+
return *this;
|
|
2645
|
+
}
|
|
2646
|
+
|
|
2647
|
+
/// \brief Use previously constructed edge set
|
|
2648
|
+
///
|
|
2649
|
+
/// Use previously constructed edge set, and specify the edge
|
|
2650
|
+
/// label map.
|
|
2651
|
+
template <typename Map>
|
|
2652
|
+
BpGraphReader& useEdges(const Map& map) {
|
|
2653
|
+
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
|
|
2654
|
+
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
|
|
2655
|
+
_use_edges = true;
|
|
2656
|
+
_writer_bits::DefaultConverter<typename Map::Value> converter;
|
|
2657
|
+
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
|
2658
|
+
_edge_index.insert(std::make_pair(converter(map[a]), a));
|
|
2659
|
+
}
|
|
2660
|
+
return *this;
|
|
2661
|
+
}
|
|
2662
|
+
|
|
2663
|
+
/// \brief Use previously constructed edge set
|
|
2664
|
+
///
|
|
2665
|
+
/// Use previously constructed edge set, and specify the edge
|
|
2666
|
+
/// label map and a functor which converts the label map values to
|
|
2667
|
+
/// \c std::string.
|
|
2668
|
+
template <typename Map, typename Converter>
|
|
2669
|
+
BpGraphReader& useEdges(const Map& map,
|
|
2670
|
+
const Converter& converter = Converter()) {
|
|
2671
|
+
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
|
|
2672
|
+
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
|
|
2673
|
+
_use_edges = true;
|
|
2674
|
+
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
|
2675
|
+
_edge_index.insert(std::make_pair(converter(map[a]), a));
|
|
2676
|
+
}
|
|
2677
|
+
return *this;
|
|
2678
|
+
}
|
|
2679
|
+
|
|
2680
|
+
/// \brief Skip the reading of node section
|
|
2681
|
+
///
|
|
2682
|
+
/// Omit the reading of the node section. This implies that each node
|
|
2683
|
+
/// map reading rule will be abandoned, and the nodes of the graph
|
|
2684
|
+
/// will not be constructed, which usually cause that the edge set
|
|
2685
|
+
/// could not be read due to lack of node name
|
|
2686
|
+
/// could not be read due to lack of node name resolving.
|
|
2687
|
+
/// Therefore \c skipEdges() function should also be used, or
|
|
2688
|
+
/// \c useNodes() should be used to specify the label of the nodes.
|
|
2689
|
+
BpGraphReader& skipNodes() {
|
|
2690
|
+
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
|
|
2691
|
+
_skip_nodes = true;
|
|
2692
|
+
return *this;
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
/// \brief Skip the reading of edge section
|
|
2696
|
+
///
|
|
2697
|
+
/// Omit the reading of the edge section. This implies that each edge
|
|
2698
|
+
/// map reading rule will be abandoned, and the edges of the graph
|
|
2699
|
+
/// will not be constructed.
|
|
2700
|
+
BpGraphReader& skipEdges() {
|
|
2701
|
+
LEMON_ASSERT(!_skip_edges, "Skip edges already set");
|
|
2702
|
+
_skip_edges = true;
|
|
2703
|
+
return *this;
|
|
2704
|
+
}
|
|
2705
|
+
|
|
2706
|
+
/// @}
|
|
2707
|
+
|
|
2708
|
+
private:
|
|
2709
|
+
|
|
2710
|
+
bool readLine() {
|
|
2711
|
+
std::string str;
|
|
2712
|
+
while(++line_num, std::getline(*_is, str)) {
|
|
2713
|
+
line.clear(); line.str(str);
|
|
2714
|
+
char c;
|
|
2715
|
+
if (line >> std::ws >> c && c != '#') {
|
|
2716
|
+
line.putback(c);
|
|
2717
|
+
return true;
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
return false;
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
bool readSuccess() {
|
|
2724
|
+
return static_cast<bool>(*_is);
|
|
2725
|
+
}
|
|
2726
|
+
|
|
2727
|
+
void skipSection() {
|
|
2728
|
+
char c;
|
|
2729
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
2730
|
+
readLine();
|
|
2731
|
+
}
|
|
2732
|
+
if (readSuccess()) {
|
|
2733
|
+
line.putback(c);
|
|
2734
|
+
}
|
|
2735
|
+
}
|
|
2736
|
+
|
|
2737
|
+
void readRedNodes() {
|
|
2738
|
+
|
|
2739
|
+
std::vector<int> map_index(_red_node_maps.size());
|
|
2740
|
+
int map_num, label_index;
|
|
2741
|
+
|
|
2742
|
+
char c;
|
|
2743
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
2744
|
+
if (readSuccess() && line) line.putback(c);
|
|
2745
|
+
if (!_red_node_maps.empty())
|
|
2746
|
+
throw FormatError("Cannot find map names");
|
|
2747
|
+
return;
|
|
2748
|
+
}
|
|
2749
|
+
line.putback(c);
|
|
2750
|
+
|
|
2751
|
+
{
|
|
2752
|
+
std::map<std::string, int> maps;
|
|
2753
|
+
|
|
2754
|
+
std::string map;
|
|
2755
|
+
int index = 0;
|
|
2756
|
+
while (_reader_bits::readToken(line, map)) {
|
|
2757
|
+
if (maps.find(map) != maps.end()) {
|
|
2758
|
+
std::ostringstream msg;
|
|
2759
|
+
msg << "Multiple occurence of red node map: " << map;
|
|
2760
|
+
throw FormatError(msg.str());
|
|
2761
|
+
}
|
|
2762
|
+
maps.insert(std::make_pair(map, index));
|
|
2763
|
+
++index;
|
|
2764
|
+
}
|
|
2765
|
+
|
|
2766
|
+
for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
|
|
2767
|
+
std::map<std::string, int>::iterator jt =
|
|
2768
|
+
maps.find(_red_node_maps[i].first);
|
|
2769
|
+
if (jt == maps.end()) {
|
|
2770
|
+
std::ostringstream msg;
|
|
2771
|
+
msg << "Map not found: " << _red_node_maps[i].first;
|
|
2772
|
+
throw FormatError(msg.str());
|
|
2773
|
+
}
|
|
2774
|
+
map_index[i] = jt->second;
|
|
2775
|
+
}
|
|
2776
|
+
|
|
2777
|
+
{
|
|
2778
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
2779
|
+
if (jt != maps.end()) {
|
|
2780
|
+
label_index = jt->second;
|
|
2781
|
+
} else {
|
|
2782
|
+
label_index = -1;
|
|
2783
|
+
}
|
|
2784
|
+
}
|
|
2785
|
+
map_num = maps.size();
|
|
2786
|
+
}
|
|
2787
|
+
|
|
2788
|
+
while (readLine() && line >> c && c != '@') {
|
|
2789
|
+
line.putback(c);
|
|
2790
|
+
|
|
2791
|
+
std::vector<std::string> tokens(map_num);
|
|
2792
|
+
for (int i = 0; i < map_num; ++i) {
|
|
2793
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
2794
|
+
std::ostringstream msg;
|
|
2795
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
2796
|
+
throw FormatError(msg.str());
|
|
2797
|
+
}
|
|
2798
|
+
}
|
|
2799
|
+
if (line >> std::ws >> c)
|
|
2800
|
+
throw FormatError("Extra character at the end of line");
|
|
2801
|
+
|
|
2802
|
+
RedNode n;
|
|
2803
|
+
if (!_use_nodes) {
|
|
2804
|
+
n = _graph.addRedNode();
|
|
2805
|
+
if (label_index != -1)
|
|
2806
|
+
_red_node_index.insert(std::make_pair(tokens[label_index], n));
|
|
2807
|
+
} else {
|
|
2808
|
+
if (label_index == -1)
|
|
2809
|
+
throw FormatError("Label map not found");
|
|
2810
|
+
typename std::map<std::string, RedNode>::iterator it =
|
|
2811
|
+
_red_node_index.find(tokens[label_index]);
|
|
2812
|
+
if (it == _red_node_index.end()) {
|
|
2813
|
+
std::ostringstream msg;
|
|
2814
|
+
msg << "Node with label not found: " << tokens[label_index];
|
|
2815
|
+
throw FormatError(msg.str());
|
|
2816
|
+
}
|
|
2817
|
+
n = it->second;
|
|
2818
|
+
}
|
|
2819
|
+
|
|
2820
|
+
for (int i = 0; i < static_cast<int>(_red_node_maps.size()); ++i) {
|
|
2821
|
+
_red_node_maps[i].second->set(n, tokens[map_index[i]]);
|
|
2822
|
+
}
|
|
2823
|
+
|
|
2824
|
+
}
|
|
2825
|
+
if (readSuccess()) {
|
|
2826
|
+
line.putback(c);
|
|
2827
|
+
}
|
|
2828
|
+
}
|
|
2829
|
+
|
|
2830
|
+
void readBlueNodes() {
|
|
2831
|
+
|
|
2832
|
+
std::vector<int> map_index(_blue_node_maps.size());
|
|
2833
|
+
int map_num, label_index;
|
|
2834
|
+
|
|
2835
|
+
char c;
|
|
2836
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
2837
|
+
if (readSuccess() && line) line.putback(c);
|
|
2838
|
+
if (!_blue_node_maps.empty())
|
|
2839
|
+
throw FormatError("Cannot find map names");
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
line.putback(c);
|
|
2843
|
+
|
|
2844
|
+
{
|
|
2845
|
+
std::map<std::string, int> maps;
|
|
2846
|
+
|
|
2847
|
+
std::string map;
|
|
2848
|
+
int index = 0;
|
|
2849
|
+
while (_reader_bits::readToken(line, map)) {
|
|
2850
|
+
if (maps.find(map) != maps.end()) {
|
|
2851
|
+
std::ostringstream msg;
|
|
2852
|
+
msg << "Multiple occurence of blue node map: " << map;
|
|
2853
|
+
throw FormatError(msg.str());
|
|
2854
|
+
}
|
|
2855
|
+
maps.insert(std::make_pair(map, index));
|
|
2856
|
+
++index;
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
|
|
2860
|
+
std::map<std::string, int>::iterator jt =
|
|
2861
|
+
maps.find(_blue_node_maps[i].first);
|
|
2862
|
+
if (jt == maps.end()) {
|
|
2863
|
+
std::ostringstream msg;
|
|
2864
|
+
msg << "Map not found: " << _blue_node_maps[i].first;
|
|
2865
|
+
throw FormatError(msg.str());
|
|
2866
|
+
}
|
|
2867
|
+
map_index[i] = jt->second;
|
|
2868
|
+
}
|
|
2869
|
+
|
|
2870
|
+
{
|
|
2871
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
2872
|
+
if (jt != maps.end()) {
|
|
2873
|
+
label_index = jt->second;
|
|
2874
|
+
} else {
|
|
2875
|
+
label_index = -1;
|
|
2876
|
+
}
|
|
2877
|
+
}
|
|
2878
|
+
map_num = maps.size();
|
|
2879
|
+
}
|
|
2880
|
+
|
|
2881
|
+
while (readLine() && line >> c && c != '@') {
|
|
2882
|
+
line.putback(c);
|
|
2883
|
+
|
|
2884
|
+
std::vector<std::string> tokens(map_num);
|
|
2885
|
+
for (int i = 0; i < map_num; ++i) {
|
|
2886
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
2887
|
+
std::ostringstream msg;
|
|
2888
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
2889
|
+
throw FormatError(msg.str());
|
|
2890
|
+
}
|
|
2891
|
+
}
|
|
2892
|
+
if (line >> std::ws >> c)
|
|
2893
|
+
throw FormatError("Extra character at the end of line");
|
|
2894
|
+
|
|
2895
|
+
BlueNode n;
|
|
2896
|
+
if (!_use_nodes) {
|
|
2897
|
+
n = _graph.addBlueNode();
|
|
2898
|
+
if (label_index != -1)
|
|
2899
|
+
_blue_node_index.insert(std::make_pair(tokens[label_index], n));
|
|
2900
|
+
} else {
|
|
2901
|
+
if (label_index == -1)
|
|
2902
|
+
throw FormatError("Label map not found");
|
|
2903
|
+
typename std::map<std::string, BlueNode>::iterator it =
|
|
2904
|
+
_blue_node_index.find(tokens[label_index]);
|
|
2905
|
+
if (it == _blue_node_index.end()) {
|
|
2906
|
+
std::ostringstream msg;
|
|
2907
|
+
msg << "Node with label not found: " << tokens[label_index];
|
|
2908
|
+
throw FormatError(msg.str());
|
|
2909
|
+
}
|
|
2910
|
+
n = it->second;
|
|
2911
|
+
}
|
|
2912
|
+
|
|
2913
|
+
for (int i = 0; i < static_cast<int>(_blue_node_maps.size()); ++i) {
|
|
2914
|
+
_blue_node_maps[i].second->set(n, tokens[map_index[i]]);
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
}
|
|
2918
|
+
if (readSuccess()) {
|
|
2919
|
+
line.putback(c);
|
|
2920
|
+
}
|
|
2921
|
+
}
|
|
2922
|
+
|
|
2923
|
+
void readEdges() {
|
|
2924
|
+
|
|
2925
|
+
std::vector<int> map_index(_edge_maps.size());
|
|
2926
|
+
int map_num, label_index;
|
|
2927
|
+
|
|
2928
|
+
char c;
|
|
2929
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
2930
|
+
if (readSuccess() && line) line.putback(c);
|
|
2931
|
+
if (!_edge_maps.empty())
|
|
2932
|
+
throw FormatError("Cannot find map names");
|
|
2933
|
+
return;
|
|
2934
|
+
}
|
|
2935
|
+
line.putback(c);
|
|
2936
|
+
|
|
2937
|
+
{
|
|
2938
|
+
std::map<std::string, int> maps;
|
|
2939
|
+
|
|
2940
|
+
std::string map;
|
|
2941
|
+
int index = 0;
|
|
2942
|
+
while (_reader_bits::readToken(line, map)) {
|
|
2943
|
+
if (maps.find(map) != maps.end()) {
|
|
2944
|
+
std::ostringstream msg;
|
|
2945
|
+
msg << "Multiple occurence of edge map: " << map;
|
|
2946
|
+
throw FormatError(msg.str());
|
|
2947
|
+
}
|
|
2948
|
+
maps.insert(std::make_pair(map, index));
|
|
2949
|
+
++index;
|
|
2950
|
+
}
|
|
2951
|
+
|
|
2952
|
+
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
2953
|
+
std::map<std::string, int>::iterator jt =
|
|
2954
|
+
maps.find(_edge_maps[i].first);
|
|
2955
|
+
if (jt == maps.end()) {
|
|
2956
|
+
std::ostringstream msg;
|
|
2957
|
+
msg << "Map not found: " << _edge_maps[i].first;
|
|
2958
|
+
throw FormatError(msg.str());
|
|
2959
|
+
}
|
|
2960
|
+
map_index[i] = jt->second;
|
|
2961
|
+
}
|
|
2962
|
+
|
|
2963
|
+
{
|
|
2964
|
+
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
2965
|
+
if (jt != maps.end()) {
|
|
2966
|
+
label_index = jt->second;
|
|
2967
|
+
} else {
|
|
2968
|
+
label_index = -1;
|
|
2969
|
+
}
|
|
2970
|
+
}
|
|
2971
|
+
map_num = maps.size();
|
|
2972
|
+
}
|
|
2973
|
+
|
|
2974
|
+
while (readLine() && line >> c && c != '@') {
|
|
2975
|
+
line.putback(c);
|
|
2976
|
+
|
|
2977
|
+
std::string source_token;
|
|
2978
|
+
std::string target_token;
|
|
2979
|
+
|
|
2980
|
+
if (!_reader_bits::readToken(line, source_token))
|
|
2981
|
+
throw FormatError("Red node not found");
|
|
2982
|
+
|
|
2983
|
+
if (!_reader_bits::readToken(line, target_token))
|
|
2984
|
+
throw FormatError("Blue node not found");
|
|
2985
|
+
|
|
2986
|
+
std::vector<std::string> tokens(map_num);
|
|
2987
|
+
for (int i = 0; i < map_num; ++i) {
|
|
2988
|
+
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
2989
|
+
std::ostringstream msg;
|
|
2990
|
+
msg << "Column not found (" << i + 1 << ")";
|
|
2991
|
+
throw FormatError(msg.str());
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
if (line >> std::ws >> c)
|
|
2995
|
+
throw FormatError("Extra character at the end of line");
|
|
2996
|
+
|
|
2997
|
+
Edge e;
|
|
2998
|
+
if (!_use_edges) {
|
|
2999
|
+
typename RedNodeIndex::iterator rit =
|
|
3000
|
+
_red_node_index.find(source_token);
|
|
3001
|
+
if (rit == _red_node_index.end()) {
|
|
3002
|
+
std::ostringstream msg;
|
|
3003
|
+
msg << "Item not found: " << source_token;
|
|
3004
|
+
throw FormatError(msg.str());
|
|
3005
|
+
}
|
|
3006
|
+
RedNode source = rit->second;
|
|
3007
|
+
typename BlueNodeIndex::iterator it =
|
|
3008
|
+
_blue_node_index.find(target_token);
|
|
3009
|
+
if (it == _blue_node_index.end()) {
|
|
3010
|
+
std::ostringstream msg;
|
|
3011
|
+
msg << "Item not found: " << target_token;
|
|
3012
|
+
throw FormatError(msg.str());
|
|
3013
|
+
}
|
|
3014
|
+
BlueNode target = it->second;
|
|
3015
|
+
|
|
3016
|
+
// It is checked that source is red and
|
|
3017
|
+
// target is blue, so this should be safe:
|
|
3018
|
+
e = _graph.addEdge(source, target);
|
|
3019
|
+
if (label_index != -1)
|
|
3020
|
+
_edge_index.insert(std::make_pair(tokens[label_index], e));
|
|
3021
|
+
} else {
|
|
3022
|
+
if (label_index == -1)
|
|
3023
|
+
throw FormatError("Label map not found");
|
|
3024
|
+
typename std::map<std::string, Edge>::iterator it =
|
|
3025
|
+
_edge_index.find(tokens[label_index]);
|
|
3026
|
+
if (it == _edge_index.end()) {
|
|
3027
|
+
std::ostringstream msg;
|
|
3028
|
+
msg << "Edge with label not found: " << tokens[label_index];
|
|
3029
|
+
throw FormatError(msg.str());
|
|
3030
|
+
}
|
|
3031
|
+
e = it->second;
|
|
3032
|
+
}
|
|
3033
|
+
|
|
3034
|
+
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
3035
|
+
_edge_maps[i].second->set(e, tokens[map_index[i]]);
|
|
3036
|
+
}
|
|
3037
|
+
|
|
3038
|
+
}
|
|
3039
|
+
if (readSuccess()) {
|
|
3040
|
+
line.putback(c);
|
|
3041
|
+
}
|
|
3042
|
+
}
|
|
3043
|
+
|
|
3044
|
+
void readAttributes() {
|
|
3045
|
+
|
|
3046
|
+
std::set<std::string> read_attr;
|
|
3047
|
+
|
|
3048
|
+
char c;
|
|
3049
|
+
while (readLine() && line >> c && c != '@') {
|
|
3050
|
+
line.putback(c);
|
|
3051
|
+
|
|
3052
|
+
std::string attr, token;
|
|
3053
|
+
if (!_reader_bits::readToken(line, attr))
|
|
3054
|
+
throw FormatError("Attribute name not found");
|
|
3055
|
+
if (!_reader_bits::readToken(line, token))
|
|
3056
|
+
throw FormatError("Attribute value not found");
|
|
3057
|
+
if (line >> c)
|
|
3058
|
+
throw FormatError("Extra character at the end of line");
|
|
3059
|
+
|
|
3060
|
+
{
|
|
3061
|
+
std::set<std::string>::iterator it = read_attr.find(attr);
|
|
3062
|
+
if (it != read_attr.end()) {
|
|
3063
|
+
std::ostringstream msg;
|
|
3064
|
+
msg << "Multiple occurence of attribute: " << attr;
|
|
3065
|
+
throw FormatError(msg.str());
|
|
3066
|
+
}
|
|
3067
|
+
read_attr.insert(attr);
|
|
3068
|
+
}
|
|
3069
|
+
|
|
3070
|
+
{
|
|
3071
|
+
typename Attributes::iterator it = _attributes.lower_bound(attr);
|
|
3072
|
+
while (it != _attributes.end() && it->first == attr) {
|
|
3073
|
+
it->second->set(token);
|
|
3074
|
+
++it;
|
|
3075
|
+
}
|
|
3076
|
+
}
|
|
3077
|
+
|
|
3078
|
+
}
|
|
3079
|
+
if (readSuccess()) {
|
|
3080
|
+
line.putback(c);
|
|
3081
|
+
}
|
|
3082
|
+
for (typename Attributes::iterator it = _attributes.begin();
|
|
3083
|
+
it != _attributes.end(); ++it) {
|
|
3084
|
+
if (read_attr.find(it->first) == read_attr.end()) {
|
|
3085
|
+
std::ostringstream msg;
|
|
3086
|
+
msg << "Attribute not found: " << it->first;
|
|
3087
|
+
throw FormatError(msg.str());
|
|
3088
|
+
}
|
|
3089
|
+
}
|
|
3090
|
+
}
|
|
3091
|
+
|
|
3092
|
+
public:
|
|
3093
|
+
|
|
3094
|
+
/// \name Execution of the Reader
|
|
3095
|
+
/// @{
|
|
3096
|
+
|
|
3097
|
+
/// \brief Start the batch processing
|
|
3098
|
+
///
|
|
3099
|
+
/// This function starts the batch processing
|
|
3100
|
+
void run() {
|
|
3101
|
+
|
|
3102
|
+
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
|
|
3103
|
+
|
|
3104
|
+
bool red_nodes_done = _skip_nodes;
|
|
3105
|
+
bool blue_nodes_done = _skip_nodes;
|
|
3106
|
+
bool edges_done = _skip_edges;
|
|
3107
|
+
bool attributes_done = false;
|
|
3108
|
+
|
|
3109
|
+
line_num = 0;
|
|
3110
|
+
readLine();
|
|
3111
|
+
skipSection();
|
|
3112
|
+
|
|
3113
|
+
while (readSuccess()) {
|
|
3114
|
+
try {
|
|
3115
|
+
char c;
|
|
3116
|
+
std::string section, caption;
|
|
3117
|
+
line >> c;
|
|
3118
|
+
_reader_bits::readToken(line, section);
|
|
3119
|
+
_reader_bits::readToken(line, caption);
|
|
3120
|
+
|
|
3121
|
+
if (line >> c)
|
|
3122
|
+
throw FormatError("Extra character at the end of line");
|
|
3123
|
+
|
|
3124
|
+
if (section == "red_nodes" && !red_nodes_done) {
|
|
3125
|
+
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
3126
|
+
readRedNodes();
|
|
3127
|
+
red_nodes_done = true;
|
|
3128
|
+
}
|
|
3129
|
+
} else if (section == "blue_nodes" && !blue_nodes_done) {
|
|
3130
|
+
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
3131
|
+
readBlueNodes();
|
|
3132
|
+
blue_nodes_done = true;
|
|
3133
|
+
}
|
|
3134
|
+
} else if ((section == "edges" || section == "arcs") &&
|
|
3135
|
+
!edges_done) {
|
|
3136
|
+
if (_edges_caption.empty() || _edges_caption == caption) {
|
|
3137
|
+
readEdges();
|
|
3138
|
+
edges_done = true;
|
|
3139
|
+
}
|
|
3140
|
+
} else if (section == "attributes" && !attributes_done) {
|
|
3141
|
+
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
3142
|
+
readAttributes();
|
|
3143
|
+
attributes_done = true;
|
|
3144
|
+
}
|
|
3145
|
+
} else {
|
|
3146
|
+
readLine();
|
|
3147
|
+
skipSection();
|
|
3148
|
+
}
|
|
3149
|
+
} catch (FormatError& error) {
|
|
3150
|
+
error.line(line_num);
|
|
3151
|
+
error.file(_filename);
|
|
3152
|
+
throw;
|
|
3153
|
+
}
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
if (!red_nodes_done) {
|
|
3157
|
+
throw FormatError("Section @red_nodes not found");
|
|
3158
|
+
}
|
|
3159
|
+
|
|
3160
|
+
if (!blue_nodes_done) {
|
|
3161
|
+
throw FormatError("Section @blue_nodes not found");
|
|
3162
|
+
}
|
|
3163
|
+
|
|
3164
|
+
if (!edges_done) {
|
|
3165
|
+
throw FormatError("Section @edges not found");
|
|
3166
|
+
}
|
|
3167
|
+
|
|
3168
|
+
if (!attributes_done && !_attributes.empty()) {
|
|
3169
|
+
throw FormatError("Section @attributes not found");
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
/// @}
|
|
3175
|
+
|
|
3176
|
+
};
|
|
3177
|
+
|
|
3178
|
+
/// \ingroup lemon_io
|
|
3179
|
+
///
|
|
3180
|
+
/// \brief Return a \ref lemon::BpGraphReader "BpGraphReader" class
|
|
3181
|
+
///
|
|
3182
|
+
/// This function just returns a \ref lemon::BpGraphReader
|
|
3183
|
+
/// "BpGraphReader" class.
|
|
3184
|
+
///
|
|
3185
|
+
/// With this function a graph can be read from an
|
|
3186
|
+
/// \ref lgf-format "LGF" file or input stream with several maps and
|
|
3187
|
+
/// attributes. For example, there is bipartite weighted matching problem
|
|
3188
|
+
/// on a graph, i.e. a graph with a \e weight map on the edges. This
|
|
3189
|
+
/// graph can be read with the following code:
|
|
3190
|
+
///
|
|
3191
|
+
///\code
|
|
3192
|
+
///ListBpGraph graph;
|
|
3193
|
+
///ListBpGraph::EdgeMap<int> weight(graph);
|
|
3194
|
+
///bpGraphReader(graph, std::cin).
|
|
3195
|
+
/// edgeMap("weight", weight).
|
|
3196
|
+
/// run();
|
|
3197
|
+
///\endcode
|
|
3198
|
+
///
|
|
3199
|
+
/// For a complete documentation, please see the
|
|
3200
|
+
/// \ref lemon::BpGraphReader "BpGraphReader"
|
|
3201
|
+
/// class documentation.
|
|
3202
|
+
/// \warning Don't forget to put the \ref lemon::BpGraphReader::run() "run()"
|
|
3203
|
+
/// to the end of the parameter list.
|
|
3204
|
+
/// \relates BpGraphReader
|
|
3205
|
+
/// \sa bpGraphReader(TBGR& graph, const std::string& fn)
|
|
3206
|
+
/// \sa bpGraphReader(TBGR& graph, const char* fn)
|
|
3207
|
+
template <typename TBGR>
|
|
3208
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
|
|
3209
|
+
BpGraphReader<TBGR> tmp(graph, is);
|
|
3210
|
+
return tmp;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
/// \brief Return a \ref BpGraphReader class
|
|
3214
|
+
///
|
|
3215
|
+
/// This function just returns a \ref BpGraphReader class.
|
|
3216
|
+
/// \relates BpGraphReader
|
|
3217
|
+
/// \sa bpGraphReader(TBGR& graph, std::istream& is)
|
|
3218
|
+
template <typename TBGR>
|
|
3219
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
|
|
3220
|
+
BpGraphReader<TBGR> tmp(graph, fn);
|
|
3221
|
+
return tmp;
|
|
3222
|
+
}
|
|
3223
|
+
|
|
3224
|
+
/// \brief Return a \ref BpGraphReader class
|
|
3225
|
+
///
|
|
3226
|
+
/// This function just returns a \ref BpGraphReader class.
|
|
3227
|
+
/// \relates BpGraphReader
|
|
3228
|
+
/// \sa bpGraphReader(TBGR& graph, std::istream& is)
|
|
3229
|
+
template <typename TBGR>
|
|
3230
|
+
BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
|
|
3231
|
+
BpGraphReader<TBGR> tmp(graph, fn);
|
|
3232
|
+
return tmp;
|
|
3233
|
+
}
|
|
3234
|
+
|
|
3235
|
+
class SectionReader;
|
|
3236
|
+
|
|
3237
|
+
SectionReader sectionReader(std::istream& is);
|
|
3238
|
+
SectionReader sectionReader(const std::string& fn);
|
|
3239
|
+
SectionReader sectionReader(const char* fn);
|
|
3240
|
+
|
|
3241
|
+
/// \ingroup lemon_io
|
|
3242
|
+
///
|
|
3243
|
+
/// \brief Section reader class
|
|
3244
|
+
///
|
|
3245
|
+
/// In the \ref lgf-format "LGF" file extra sections can be placed,
|
|
3246
|
+
/// which contain any data in arbitrary format. Such sections can be
|
|
3247
|
+
/// read with this class. A reading rule can be added to the class
|
|
3248
|
+
/// with two different functions. With the \c sectionLines() function a
|
|
3249
|
+
/// functor can process the section line-by-line, while with the \c
|
|
3250
|
+
/// sectionStream() member the section can be read from an input
|
|
3251
|
+
/// stream.
|
|
3252
|
+
class SectionReader {
|
|
3253
|
+
private:
|
|
3254
|
+
|
|
3255
|
+
std::istream* _is;
|
|
3256
|
+
bool local_is;
|
|
3257
|
+
std::string _filename;
|
|
3258
|
+
|
|
3259
|
+
typedef std::map<std::string, _reader_bits::Section*> Sections;
|
|
3260
|
+
Sections _sections;
|
|
3261
|
+
|
|
3262
|
+
int line_num;
|
|
3263
|
+
std::istringstream line;
|
|
3264
|
+
|
|
3265
|
+
public:
|
|
3266
|
+
|
|
3267
|
+
/// \brief Constructor
|
|
3268
|
+
///
|
|
3269
|
+
/// Construct a section reader, which reads from the given input
|
|
3270
|
+
/// stream.
|
|
3271
|
+
SectionReader(std::istream& is)
|
|
3272
|
+
: _is(&is), local_is(false) {}
|
|
3273
|
+
|
|
3274
|
+
/// \brief Constructor
|
|
3275
|
+
///
|
|
3276
|
+
/// Construct a section reader, which reads from the given file.
|
|
3277
|
+
SectionReader(const std::string& fn)
|
|
3278
|
+
: _is(new std::ifstream(fn.c_str())), local_is(true),
|
|
3279
|
+
_filename(fn) {
|
|
3280
|
+
if (!(*_is)) {
|
|
3281
|
+
delete _is;
|
|
3282
|
+
throw IoError("Cannot open file", fn);
|
|
3283
|
+
}
|
|
3284
|
+
}
|
|
3285
|
+
|
|
3286
|
+
/// \brief Constructor
|
|
3287
|
+
///
|
|
3288
|
+
/// Construct a section reader, which reads from the given file.
|
|
3289
|
+
SectionReader(const char* fn)
|
|
3290
|
+
: _is(new std::ifstream(fn)), local_is(true),
|
|
3291
|
+
_filename(fn) {
|
|
3292
|
+
if (!(*_is)) {
|
|
3293
|
+
delete _is;
|
|
3294
|
+
throw IoError("Cannot open file", fn);
|
|
3295
|
+
}
|
|
3296
|
+
}
|
|
3297
|
+
|
|
3298
|
+
/// \brief Destructor
|
|
3299
|
+
~SectionReader() {
|
|
3300
|
+
for (Sections::iterator it = _sections.begin();
|
|
3301
|
+
it != _sections.end(); ++it) {
|
|
3302
|
+
delete it->second;
|
|
3303
|
+
}
|
|
3304
|
+
|
|
3305
|
+
if (local_is) {
|
|
3306
|
+
delete _is;
|
|
3307
|
+
}
|
|
3308
|
+
|
|
3309
|
+
}
|
|
3310
|
+
|
|
3311
|
+
private:
|
|
3312
|
+
|
|
3313
|
+
friend SectionReader sectionReader(std::istream& is);
|
|
3314
|
+
friend SectionReader sectionReader(const std::string& fn);
|
|
3315
|
+
friend SectionReader sectionReader(const char* fn);
|
|
3316
|
+
|
|
3317
|
+
SectionReader(SectionReader& other)
|
|
3318
|
+
: _is(other._is), local_is(other.local_is) {
|
|
3319
|
+
|
|
3320
|
+
other._is = 0;
|
|
3321
|
+
other.local_is = false;
|
|
3322
|
+
|
|
3323
|
+
_sections.swap(other._sections);
|
|
3324
|
+
}
|
|
3325
|
+
|
|
3326
|
+
SectionReader& operator=(const SectionReader&);
|
|
3327
|
+
|
|
3328
|
+
public:
|
|
3329
|
+
|
|
3330
|
+
/// \name Section Readers
|
|
3331
|
+
/// @{
|
|
3332
|
+
|
|
3333
|
+
/// \brief Add a section processor with line oriented reading
|
|
3334
|
+
///
|
|
3335
|
+
/// The first parameter is the type descriptor of the section, the
|
|
3336
|
+
/// second is a functor, which takes just one \c std::string
|
|
3337
|
+
/// parameter. At the reading process, each line of the section
|
|
3338
|
+
/// will be given to the functor object. However, the empty lines
|
|
3339
|
+
/// and the comment lines are filtered out, and the leading
|
|
3340
|
+
/// whitespaces are trimmed from each processed string.
|
|
3341
|
+
///
|
|
3342
|
+
/// For example, let's see a section, which contain several
|
|
3343
|
+
/// integers, which should be inserted into a vector.
|
|
3344
|
+
///\code
|
|
3345
|
+
/// @numbers
|
|
3346
|
+
/// 12 45 23
|
|
3347
|
+
/// 4
|
|
3348
|
+
/// 23 6
|
|
3349
|
+
///\endcode
|
|
3350
|
+
///
|
|
3351
|
+
/// The functor is implemented as a struct:
|
|
3352
|
+
///\code
|
|
3353
|
+
/// struct NumberSection {
|
|
3354
|
+
/// std::vector<int>& _data;
|
|
3355
|
+
/// NumberSection(std::vector<int>& data) : _data(data) {}
|
|
3356
|
+
/// void operator()(const std::string& line) {
|
|
3357
|
+
/// std::istringstream ls(line);
|
|
3358
|
+
/// int value;
|
|
3359
|
+
/// while (ls >> value) _data.push_back(value);
|
|
3360
|
+
/// }
|
|
3361
|
+
/// };
|
|
3362
|
+
///
|
|
3363
|
+
/// // ...
|
|
3364
|
+
///
|
|
3365
|
+
/// reader.sectionLines("numbers", NumberSection(vec));
|
|
3366
|
+
///\endcode
|
|
3367
|
+
template <typename Functor>
|
|
3368
|
+
SectionReader& sectionLines(const std::string& type, Functor functor) {
|
|
3369
|
+
LEMON_ASSERT(!type.empty(), "Type is empty.");
|
|
3370
|
+
LEMON_ASSERT(_sections.find(type) == _sections.end(),
|
|
3371
|
+
"Multiple reading of section.");
|
|
3372
|
+
_sections.insert(std::make_pair(type,
|
|
3373
|
+
new _reader_bits::LineSection<Functor>(functor)));
|
|
3374
|
+
return *this;
|
|
3375
|
+
}
|
|
3376
|
+
|
|
3377
|
+
|
|
3378
|
+
/// \brief Add a section processor with stream oriented reading
|
|
3379
|
+
///
|
|
3380
|
+
/// The first parameter is the type of the section, the second is
|
|
3381
|
+
/// a functor, which takes an \c std::istream& and an \c int&
|
|
3382
|
+
/// parameter, the latter regard to the line number of stream. The
|
|
3383
|
+
/// functor can read the input while the section go on, and the
|
|
3384
|
+
/// line number should be modified accordingly.
|
|
3385
|
+
template <typename Functor>
|
|
3386
|
+
SectionReader& sectionStream(const std::string& type, Functor functor) {
|
|
3387
|
+
LEMON_ASSERT(!type.empty(), "Type is empty.");
|
|
3388
|
+
LEMON_ASSERT(_sections.find(type) == _sections.end(),
|
|
3389
|
+
"Multiple reading of section.");
|
|
3390
|
+
_sections.insert(std::make_pair(type,
|
|
3391
|
+
new _reader_bits::StreamSection<Functor>(functor)));
|
|
3392
|
+
return *this;
|
|
3393
|
+
}
|
|
3394
|
+
|
|
3395
|
+
/// @}
|
|
3396
|
+
|
|
3397
|
+
private:
|
|
3398
|
+
|
|
3399
|
+
bool readLine() {
|
|
3400
|
+
std::string str;
|
|
3401
|
+
while(++line_num, std::getline(*_is, str)) {
|
|
3402
|
+
line.clear(); line.str(str);
|
|
3403
|
+
char c;
|
|
3404
|
+
if (line >> std::ws >> c && c != '#') {
|
|
3405
|
+
line.putback(c);
|
|
3406
|
+
return true;
|
|
3407
|
+
}
|
|
3408
|
+
}
|
|
3409
|
+
return false;
|
|
3410
|
+
}
|
|
3411
|
+
|
|
3412
|
+
bool readSuccess() {
|
|
3413
|
+
return static_cast<bool>(*_is);
|
|
3414
|
+
}
|
|
3415
|
+
|
|
3416
|
+
void skipSection() {
|
|
3417
|
+
char c;
|
|
3418
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
3419
|
+
readLine();
|
|
3420
|
+
}
|
|
3421
|
+
if (readSuccess()) {
|
|
3422
|
+
line.putback(c);
|
|
3423
|
+
}
|
|
3424
|
+
}
|
|
3425
|
+
|
|
3426
|
+
public:
|
|
3427
|
+
|
|
3428
|
+
|
|
3429
|
+
/// \name Execution of the Reader
|
|
3430
|
+
/// @{
|
|
3431
|
+
|
|
3432
|
+
/// \brief Start the batch processing
|
|
3433
|
+
///
|
|
3434
|
+
/// This function starts the batch processing.
|
|
3435
|
+
void run() {
|
|
3436
|
+
|
|
3437
|
+
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
|
|
3438
|
+
|
|
3439
|
+
std::set<std::string> extra_sections;
|
|
3440
|
+
|
|
3441
|
+
line_num = 0;
|
|
3442
|
+
readLine();
|
|
3443
|
+
skipSection();
|
|
3444
|
+
|
|
3445
|
+
while (readSuccess()) {
|
|
3446
|
+
try {
|
|
3447
|
+
char c;
|
|
3448
|
+
std::string section, caption;
|
|
3449
|
+
line >> c;
|
|
3450
|
+
_reader_bits::readToken(line, section);
|
|
3451
|
+
_reader_bits::readToken(line, caption);
|
|
3452
|
+
|
|
3453
|
+
if (line >> c)
|
|
3454
|
+
throw FormatError("Extra character at the end of line");
|
|
3455
|
+
|
|
3456
|
+
if (extra_sections.find(section) != extra_sections.end()) {
|
|
3457
|
+
std::ostringstream msg;
|
|
3458
|
+
msg << "Multiple occurence of section: " << section;
|
|
3459
|
+
throw FormatError(msg.str());
|
|
3460
|
+
}
|
|
3461
|
+
Sections::iterator it = _sections.find(section);
|
|
3462
|
+
if (it != _sections.end()) {
|
|
3463
|
+
extra_sections.insert(section);
|
|
3464
|
+
it->second->process(*_is, line_num);
|
|
3465
|
+
}
|
|
3466
|
+
readLine();
|
|
3467
|
+
skipSection();
|
|
3468
|
+
} catch (FormatError& error) {
|
|
3469
|
+
error.line(line_num);
|
|
3470
|
+
error.file(_filename);
|
|
3471
|
+
throw;
|
|
3472
|
+
}
|
|
3473
|
+
}
|
|
3474
|
+
for (Sections::iterator it = _sections.begin();
|
|
3475
|
+
it != _sections.end(); ++it) {
|
|
3476
|
+
if (extra_sections.find(it->first) == extra_sections.end()) {
|
|
3477
|
+
std::ostringstream os;
|
|
3478
|
+
os << "Cannot find section: " << it->first;
|
|
3479
|
+
throw FormatError(os.str());
|
|
3480
|
+
}
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3483
|
+
|
|
3484
|
+
/// @}
|
|
3485
|
+
|
|
3486
|
+
};
|
|
3487
|
+
|
|
3488
|
+
/// \ingroup lemon_io
|
|
3489
|
+
///
|
|
3490
|
+
/// \brief Return a \ref SectionReader class
|
|
3491
|
+
///
|
|
3492
|
+
/// This function just returns a \ref SectionReader class.
|
|
3493
|
+
///
|
|
3494
|
+
/// Please see SectionReader documentation about the custom section
|
|
3495
|
+
/// input.
|
|
3496
|
+
///
|
|
3497
|
+
/// \relates SectionReader
|
|
3498
|
+
/// \sa sectionReader(const std::string& fn)
|
|
3499
|
+
/// \sa sectionReader(const char *fn)
|
|
3500
|
+
inline SectionReader sectionReader(std::istream& is) {
|
|
3501
|
+
SectionReader tmp(is);
|
|
3502
|
+
return tmp;
|
|
3503
|
+
}
|
|
3504
|
+
|
|
3505
|
+
/// \brief Return a \ref SectionReader class
|
|
3506
|
+
///
|
|
3507
|
+
/// This function just returns a \ref SectionReader class.
|
|
3508
|
+
/// \relates SectionReader
|
|
3509
|
+
/// \sa sectionReader(std::istream& is)
|
|
3510
|
+
inline SectionReader sectionReader(const std::string& fn) {
|
|
3511
|
+
SectionReader tmp(fn);
|
|
3512
|
+
return tmp;
|
|
3513
|
+
}
|
|
3514
|
+
|
|
3515
|
+
/// \brief Return a \ref SectionReader class
|
|
3516
|
+
///
|
|
3517
|
+
/// This function just returns a \ref SectionReader class.
|
|
3518
|
+
/// \relates SectionReader
|
|
3519
|
+
/// \sa sectionReader(std::istream& is)
|
|
3520
|
+
inline SectionReader sectionReader(const char* fn) {
|
|
3521
|
+
SectionReader tmp(fn);
|
|
3522
|
+
return tmp;
|
|
3523
|
+
}
|
|
3524
|
+
|
|
3525
|
+
/// \ingroup lemon_io
|
|
3526
|
+
///
|
|
3527
|
+
/// \brief Reader for the contents of the \ref lgf-format "LGF" file
|
|
3528
|
+
///
|
|
3529
|
+
/// This class can be used to read the sections, the map names and
|
|
3530
|
+
/// the attributes from a file. Usually, the LEMON programs know
|
|
3531
|
+
/// that, which type of graph, which maps and which attributes
|
|
3532
|
+
/// should be read from a file, but in general tools (like glemon)
|
|
3533
|
+
/// the contents of an LGF file should be guessed somehow. This class
|
|
3534
|
+
/// reads the graph and stores the appropriate information for
|
|
3535
|
+
/// reading the graph.
|
|
3536
|
+
///
|
|
3537
|
+
///\code
|
|
3538
|
+
/// LgfContents contents("graph.lgf");
|
|
3539
|
+
/// contents.run();
|
|
3540
|
+
///
|
|
3541
|
+
/// // Does it contain any node section and arc section?
|
|
3542
|
+
/// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
|
|
3543
|
+
/// std::cerr << "Failure, cannot find graph." << std::endl;
|
|
3544
|
+
/// return -1;
|
|
3545
|
+
/// }
|
|
3546
|
+
/// std::cout << "The name of the default node section: "
|
|
3547
|
+
/// << contents.nodeSection(0) << std::endl;
|
|
3548
|
+
/// std::cout << "The number of the arc maps: "
|
|
3549
|
+
/// << contents.arcMaps(0).size() << std::endl;
|
|
3550
|
+
/// std::cout << "The name of second arc map: "
|
|
3551
|
+
/// << contents.arcMaps(0)[1] << std::endl;
|
|
3552
|
+
///\endcode
|
|
3553
|
+
class LgfContents {
|
|
3554
|
+
private:
|
|
3555
|
+
|
|
3556
|
+
std::istream* _is;
|
|
3557
|
+
bool local_is;
|
|
3558
|
+
|
|
3559
|
+
std::vector<std::string> _node_sections;
|
|
3560
|
+
std::vector<std::string> _edge_sections;
|
|
3561
|
+
std::vector<std::string> _attribute_sections;
|
|
3562
|
+
std::vector<std::string> _extra_sections;
|
|
3563
|
+
|
|
3564
|
+
std::vector<bool> _arc_sections;
|
|
3565
|
+
|
|
3566
|
+
std::vector<std::vector<std::string> > _node_maps;
|
|
3567
|
+
std::vector<std::vector<std::string> > _edge_maps;
|
|
3568
|
+
|
|
3569
|
+
std::vector<std::vector<std::string> > _attributes;
|
|
3570
|
+
|
|
3571
|
+
|
|
3572
|
+
int line_num;
|
|
3573
|
+
std::istringstream line;
|
|
3574
|
+
|
|
3575
|
+
public:
|
|
3576
|
+
|
|
3577
|
+
/// \brief Constructor
|
|
3578
|
+
///
|
|
3579
|
+
/// Construct an \e LGF contents reader, which reads from the given
|
|
3580
|
+
/// input stream.
|
|
3581
|
+
LgfContents(std::istream& is)
|
|
3582
|
+
: _is(&is), local_is(false) {}
|
|
3583
|
+
|
|
3584
|
+
/// \brief Constructor
|
|
3585
|
+
///
|
|
3586
|
+
/// Construct an \e LGF contents reader, which reads from the given
|
|
3587
|
+
/// file.
|
|
3588
|
+
LgfContents(const std::string& fn)
|
|
3589
|
+
: _is(new std::ifstream(fn.c_str())), local_is(true) {
|
|
3590
|
+
if (!(*_is)) {
|
|
3591
|
+
delete _is;
|
|
3592
|
+
throw IoError("Cannot open file", fn);
|
|
3593
|
+
}
|
|
3594
|
+
}
|
|
3595
|
+
|
|
3596
|
+
/// \brief Constructor
|
|
3597
|
+
///
|
|
3598
|
+
/// Construct an \e LGF contents reader, which reads from the given
|
|
3599
|
+
/// file.
|
|
3600
|
+
LgfContents(const char* fn)
|
|
3601
|
+
: _is(new std::ifstream(fn)), local_is(true) {
|
|
3602
|
+
if (!(*_is)) {
|
|
3603
|
+
delete _is;
|
|
3604
|
+
throw IoError("Cannot open file", fn);
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
|
|
3608
|
+
/// \brief Destructor
|
|
3609
|
+
~LgfContents() {
|
|
3610
|
+
if (local_is) delete _is;
|
|
3611
|
+
}
|
|
3612
|
+
|
|
3613
|
+
private:
|
|
3614
|
+
|
|
3615
|
+
LgfContents(const LgfContents&);
|
|
3616
|
+
LgfContents& operator=(const LgfContents&);
|
|
3617
|
+
|
|
3618
|
+
public:
|
|
3619
|
+
|
|
3620
|
+
|
|
3621
|
+
/// \name Node Sections
|
|
3622
|
+
/// @{
|
|
3623
|
+
|
|
3624
|
+
/// \brief Gives back the number of node sections in the file.
|
|
3625
|
+
///
|
|
3626
|
+
/// Gives back the number of node sections in the file.
|
|
3627
|
+
int nodeSectionNum() const {
|
|
3628
|
+
return _node_sections.size();
|
|
3629
|
+
}
|
|
3630
|
+
|
|
3631
|
+
/// \brief Returns the node section name at the given position.
|
|
3632
|
+
///
|
|
3633
|
+
/// Returns the node section name at the given position.
|
|
3634
|
+
const std::string& nodeSection(int i) const {
|
|
3635
|
+
return _node_sections[i];
|
|
3636
|
+
}
|
|
3637
|
+
|
|
3638
|
+
/// \brief Gives back the node maps for the given section.
|
|
3639
|
+
///
|
|
3640
|
+
/// Gives back the node maps for the given section.
|
|
3641
|
+
const std::vector<std::string>& nodeMapNames(int i) const {
|
|
3642
|
+
return _node_maps[i];
|
|
3643
|
+
}
|
|
3644
|
+
|
|
3645
|
+
/// @}
|
|
3646
|
+
|
|
3647
|
+
/// \name Arc/Edge Sections
|
|
3648
|
+
/// @{
|
|
3649
|
+
|
|
3650
|
+
/// \brief Gives back the number of arc/edge sections in the file.
|
|
3651
|
+
///
|
|
3652
|
+
/// Gives back the number of arc/edge sections in the file.
|
|
3653
|
+
/// \note It is synonym of \c edgeSectionNum().
|
|
3654
|
+
int arcSectionNum() const {
|
|
3655
|
+
return _edge_sections.size();
|
|
3656
|
+
}
|
|
3657
|
+
|
|
3658
|
+
/// \brief Returns the arc/edge section name at the given position.
|
|
3659
|
+
///
|
|
3660
|
+
/// Returns the arc/edge section name at the given position.
|
|
3661
|
+
/// \note It is synonym of \c edgeSection().
|
|
3662
|
+
const std::string& arcSection(int i) const {
|
|
3663
|
+
return _edge_sections[i];
|
|
3664
|
+
}
|
|
3665
|
+
|
|
3666
|
+
/// \brief Gives back the arc/edge maps for the given section.
|
|
3667
|
+
///
|
|
3668
|
+
/// Gives back the arc/edge maps for the given section.
|
|
3669
|
+
/// \note It is synonym of \c edgeMapNames().
|
|
3670
|
+
const std::vector<std::string>& arcMapNames(int i) const {
|
|
3671
|
+
return _edge_maps[i];
|
|
3672
|
+
}
|
|
3673
|
+
|
|
3674
|
+
/// @}
|
|
3675
|
+
|
|
3676
|
+
/// \name Synonyms
|
|
3677
|
+
/// @{
|
|
3678
|
+
|
|
3679
|
+
/// \brief Gives back the number of arc/edge sections in the file.
|
|
3680
|
+
///
|
|
3681
|
+
/// Gives back the number of arc/edge sections in the file.
|
|
3682
|
+
/// \note It is synonym of \c arcSectionNum().
|
|
3683
|
+
int edgeSectionNum() const {
|
|
3684
|
+
return _edge_sections.size();
|
|
3685
|
+
}
|
|
3686
|
+
|
|
3687
|
+
/// \brief Returns the section name at the given position.
|
|
3688
|
+
///
|
|
3689
|
+
/// Returns the section name at the given position.
|
|
3690
|
+
/// \note It is synonym of \c arcSection().
|
|
3691
|
+
const std::string& edgeSection(int i) const {
|
|
3692
|
+
return _edge_sections[i];
|
|
3693
|
+
}
|
|
3694
|
+
|
|
3695
|
+
/// \brief Gives back the edge maps for the given section.
|
|
3696
|
+
///
|
|
3697
|
+
/// Gives back the edge maps for the given section.
|
|
3698
|
+
/// \note It is synonym of \c arcMapNames().
|
|
3699
|
+
const std::vector<std::string>& edgeMapNames(int i) const {
|
|
3700
|
+
return _edge_maps[i];
|
|
3701
|
+
}
|
|
3702
|
+
|
|
3703
|
+
/// @}
|
|
3704
|
+
|
|
3705
|
+
/// \name Attribute Sections
|
|
3706
|
+
/// @{
|
|
3707
|
+
|
|
3708
|
+
/// \brief Gives back the number of attribute sections in the file.
|
|
3709
|
+
///
|
|
3710
|
+
/// Gives back the number of attribute sections in the file.
|
|
3711
|
+
int attributeSectionNum() const {
|
|
3712
|
+
return _attribute_sections.size();
|
|
3713
|
+
}
|
|
3714
|
+
|
|
3715
|
+
/// \brief Returns the attribute section name at the given position.
|
|
3716
|
+
///
|
|
3717
|
+
/// Returns the attribute section name at the given position.
|
|
3718
|
+
const std::string& attributeSectionNames(int i) const {
|
|
3719
|
+
return _attribute_sections[i];
|
|
3720
|
+
}
|
|
3721
|
+
|
|
3722
|
+
/// \brief Gives back the attributes for the given section.
|
|
3723
|
+
///
|
|
3724
|
+
/// Gives back the attributes for the given section.
|
|
3725
|
+
const std::vector<std::string>& attributes(int i) const {
|
|
3726
|
+
return _attributes[i];
|
|
3727
|
+
}
|
|
3728
|
+
|
|
3729
|
+
/// @}
|
|
3730
|
+
|
|
3731
|
+
/// \name Extra Sections
|
|
3732
|
+
/// @{
|
|
3733
|
+
|
|
3734
|
+
/// \brief Gives back the number of extra sections in the file.
|
|
3735
|
+
///
|
|
3736
|
+
/// Gives back the number of extra sections in the file.
|
|
3737
|
+
int extraSectionNum() const {
|
|
3738
|
+
return _extra_sections.size();
|
|
3739
|
+
}
|
|
3740
|
+
|
|
3741
|
+
/// \brief Returns the extra section type at the given position.
|
|
3742
|
+
///
|
|
3743
|
+
/// Returns the section type at the given position.
|
|
3744
|
+
const std::string& extraSection(int i) const {
|
|
3745
|
+
return _extra_sections[i];
|
|
3746
|
+
}
|
|
3747
|
+
|
|
3748
|
+
/// @}
|
|
3749
|
+
|
|
3750
|
+
private:
|
|
3751
|
+
|
|
3752
|
+
bool readLine() {
|
|
3753
|
+
std::string str;
|
|
3754
|
+
while(++line_num, std::getline(*_is, str)) {
|
|
3755
|
+
line.clear(); line.str(str);
|
|
3756
|
+
char c;
|
|
3757
|
+
if (line >> std::ws >> c && c != '#') {
|
|
3758
|
+
line.putback(c);
|
|
3759
|
+
return true;
|
|
3760
|
+
}
|
|
3761
|
+
}
|
|
3762
|
+
return false;
|
|
3763
|
+
}
|
|
3764
|
+
|
|
3765
|
+
bool readSuccess() {
|
|
3766
|
+
return static_cast<bool>(*_is);
|
|
3767
|
+
}
|
|
3768
|
+
|
|
3769
|
+
void skipSection() {
|
|
3770
|
+
char c;
|
|
3771
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
3772
|
+
readLine();
|
|
3773
|
+
}
|
|
3774
|
+
if (readSuccess()) {
|
|
3775
|
+
line.putback(c);
|
|
3776
|
+
}
|
|
3777
|
+
}
|
|
3778
|
+
|
|
3779
|
+
void readMaps(std::vector<std::string>& maps) {
|
|
3780
|
+
char c;
|
|
3781
|
+
if (!readLine() || !(line >> c) || c == '@') {
|
|
3782
|
+
if (readSuccess() && line) line.putback(c);
|
|
3783
|
+
return;
|
|
3784
|
+
}
|
|
3785
|
+
line.putback(c);
|
|
3786
|
+
std::string map;
|
|
3787
|
+
while (_reader_bits::readToken(line, map)) {
|
|
3788
|
+
maps.push_back(map);
|
|
3789
|
+
}
|
|
3790
|
+
}
|
|
3791
|
+
|
|
3792
|
+
void readAttributes(std::vector<std::string>& attrs) {
|
|
3793
|
+
readLine();
|
|
3794
|
+
char c;
|
|
3795
|
+
while (readSuccess() && line >> c && c != '@') {
|
|
3796
|
+
line.putback(c);
|
|
3797
|
+
std::string attr;
|
|
3798
|
+
_reader_bits::readToken(line, attr);
|
|
3799
|
+
attrs.push_back(attr);
|
|
3800
|
+
readLine();
|
|
3801
|
+
}
|
|
3802
|
+
line.putback(c);
|
|
3803
|
+
}
|
|
3804
|
+
|
|
3805
|
+
public:
|
|
3806
|
+
|
|
3807
|
+
/// \name Execution of the Contents Reader
|
|
3808
|
+
/// @{
|
|
3809
|
+
|
|
3810
|
+
/// \brief Starts the reading
|
|
3811
|
+
///
|
|
3812
|
+
/// This function starts the reading.
|
|
3813
|
+
void run() {
|
|
3814
|
+
|
|
3815
|
+
readLine();
|
|
3816
|
+
skipSection();
|
|
3817
|
+
|
|
3818
|
+
while (readSuccess()) {
|
|
3819
|
+
|
|
3820
|
+
char c;
|
|
3821
|
+
line >> c;
|
|
3822
|
+
|
|
3823
|
+
std::string section, caption;
|
|
3824
|
+
_reader_bits::readToken(line, section);
|
|
3825
|
+
_reader_bits::readToken(line, caption);
|
|
3826
|
+
|
|
3827
|
+
if (section == "nodes") {
|
|
3828
|
+
_node_sections.push_back(caption);
|
|
3829
|
+
_node_maps.push_back(std::vector<std::string>());
|
|
3830
|
+
readMaps(_node_maps.back());
|
|
3831
|
+
readLine(); skipSection();
|
|
3832
|
+
} else if (section == "arcs" || section == "edges") {
|
|
3833
|
+
_edge_sections.push_back(caption);
|
|
3834
|
+
_arc_sections.push_back(section == "arcs");
|
|
3835
|
+
_edge_maps.push_back(std::vector<std::string>());
|
|
3836
|
+
readMaps(_edge_maps.back());
|
|
3837
|
+
readLine(); skipSection();
|
|
3838
|
+
} else if (section == "attributes") {
|
|
3839
|
+
_attribute_sections.push_back(caption);
|
|
3840
|
+
_attributes.push_back(std::vector<std::string>());
|
|
3841
|
+
readAttributes(_attributes.back());
|
|
3842
|
+
} else {
|
|
3843
|
+
_extra_sections.push_back(section);
|
|
3844
|
+
readLine(); skipSection();
|
|
3845
|
+
}
|
|
3846
|
+
}
|
|
3847
|
+
}
|
|
3848
|
+
|
|
3849
|
+
/// @}
|
|
3850
|
+
|
|
3851
|
+
};
|
|
3852
|
+
}
|
|
3853
|
+
|
|
3854
|
+
#endif
|