gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge #382 to branch 1.2
0 4 1
merge 1.2
4 files changed with 205 insertions and 8 deletions:
↑ Collapse diff ↑
Ignore white space 512 line context
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-2011
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
#include <lemon/list_graph.h>
20
#include <lemon/lgf_reader.h>
21
#include "test_tools.h"
22

	
23
using namespace lemon;
24

	
25
char test_lgf[] =
26
  "@nodes\n"
27
  "label\n"
28
  "0\n"
29
  "1\n"
30
  "@arcs\n"
31
  "     label\n"
32
  "0 1  0\n"
33
  "1 0  1\n"
34
  "@attributes\n"
35
  "source 0\n"
36
  "target 1\n";
37

	
38
char test_lgf_nomap[] =
39
  "@nodes\n"
40
  "label\n"
41
  "0\n"
42
  "1\n"
43
  "@arcs\n"
44
  "     -\n"
45
  "0 1\n";
46

	
47
char test_lgf_bad1[] =
48
  "@nodes\n"
49
  "label\n"
50
  "0\n"
51
  "1\n"
52
  "@arcs\n"
53
  "     - another\n"
54
  "0 1\n";
55

	
56
char test_lgf_bad2[] =
57
  "@nodes\n"
58
  "label\n"
59
  "0\n"
60
  "1\n"
61
  "@arcs\n"
62
  "     label -\n"
63
  "0 1\n";
64

	
65

	
66
int main() 
67
{
68
  {
69
    ListDigraph d; 
70
    ListDigraph::Node s,t;
71
    ListDigraph::ArcMap<int> label(d);
72
    std::istringstream input(test_lgf);
73
    digraphReader(d, input).
74
      node("source", s).
75
      node("target", t).
76
      arcMap("label", label).
77
      run();
78
    check(countNodes(d) == 2,"There should be 2 nodes");
79
    check(countArcs(d) == 2,"There should be 2 arcs");
80
  }
81
  {
82
    ListGraph g;
83
    ListGraph::Node s,t;
84
    ListGraph::EdgeMap<int> label(g);
85
    std::istringstream input(test_lgf);
86
    graphReader(g, input).
87
      node("source", s).
88
      node("target", t).
89
      edgeMap("label", label).
90
      run();
91
    check(countNodes(g) == 2,"There should be 2 nodes");
92
    check(countEdges(g) == 2,"There should be 2 arcs");
93
  }
94

	
95
  {
96
    ListDigraph d; 
97
    std::istringstream input(test_lgf_nomap);
98
    digraphReader(d, input).
99
      run();
100
    check(countNodes(d) == 2,"There should be 2 nodes");
101
    check(countArcs(d) == 1,"There should be 1 arc");
102
  }
103
  {
104
    ListGraph g;
105
    std::istringstream input(test_lgf_nomap);
106
    graphReader(g, input).
107
      run();
108
    check(countNodes(g) == 2,"There should be 2 nodes");
109
    check(countEdges(g) == 1,"There should be 1 edge");
110
  }
111

	
112
  {
113
    ListDigraph d; 
114
    std::istringstream input(test_lgf_bad1);
115
    bool ok=false;
116
    try {
117
      digraphReader(d, input).
118
        run();
119
    }
120
    catch (FormatError& error) 
121
      {
122
        ok = true;
123
      }
124
    check(ok,"FormatError exception should have occured");
125
  }
126
  {
127
    ListGraph g;
128
    std::istringstream input(test_lgf_bad1);
129
    bool ok=false;
130
    try {
131
      graphReader(g, input).
132
        run();
133
    }
134
    catch (FormatError& error)
135
      {
136
        ok = true;
137
      }
138
    check(ok,"FormatError exception should have occured");
139
  }
140

	
141
  {
142
    ListDigraph d; 
143
    std::istringstream input(test_lgf_bad2);
144
    bool ok=false;
145
    try {
146
      digraphReader(d, input).
147
        run();
148
    }
149
    catch (FormatError& error)
150
      {
151
        ok = true;
152
      }
153
    check(ok,"FormatError exception should have occured");
154
  }
155
  {
156
    ListGraph g;
157
    std::istringstream input(test_lgf_bad2);
158
    bool ok=false;
159
    try {
160
      graphReader(g, input).
161
        run();
162
    }
163
    catch (FormatError& error)
164
      {
165
        ok = true;
166
      }
167
    check(ok,"FormatError exception should have occured");
168
  }
169
}
Ignore white space 512 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
namespace lemon {
20 20
/*!
21 21

	
22 22

	
23 23

	
24 24
\page lgf-format LEMON Graph Format (LGF)
25 25

	
26 26
The \e LGF is a <em>column oriented</em>
27 27
file format for storing graphs and associated data like
28 28
node and edge maps.
29 29

	
30 30
Each line with \c '#' first non-whitespace
31 31
character is considered as a comment line.
32 32

	
33 33
Otherwise the file consists of sections starting with
34 34
a header line. The header lines starts with an \c '@' character followed by the
35 35
type of section. The standard section types are \c \@nodes, \c
36 36
\@arcs and \c \@edges
37 37
and \@attributes. Each header line may also have an optional
38 38
\e name, which can be use to distinguish the sections of the same
39 39
type.
40 40

	
41 41
The standard sections are column oriented, each line consists of
42 42
<em>token</em>s separated by whitespaces. A token can be \e plain or
43 43
\e quoted. A plain token is just a sequence of non-whitespace characters,
44 44
while a quoted token is a
45 45
character sequence surrounded by double quotes, and it can also
46 46
contain whitespaces and escape sequences.
47 47

	
48 48
The \c \@nodes section describes a set of nodes and associated
49 49
maps. The first is a header line, its columns are the names of the
50 50
maps appearing in the following lines.
51 51
One of the maps must be called \c
52 52
"label", which plays special role in the file.
53 53
The following
54 54
non-empty lines until the next section describes nodes of the
55 55
graph. Each line contains the values of the node maps
56 56
associated to the current node.
57 57

	
58 58
\code
59 59
 @nodes
60 60
 label  coordinates  size    title
61 61
 1      (10,20)      10      "First node"
62 62
 2      (80,80)      8       "Second node"
63 63
 3      (40,10)      10      "Third node"
64 64
\endcode
65 65

	
66
The \c \@arcs section is very similar to the \c \@nodes section,
67
it again starts with a header line describing the names of the maps,
68
but the \c "label" map is not obligatory here. The following lines
69
describe the arcs. The first two tokens of each line are
70
the source and the target node of the arc, respectively, then come the map
66
The \c \@arcs section is very similar to the \c \@nodes section, it
67
again starts with a header line describing the names of the maps, but
68
the \c "label" map is not obligatory here. The following lines
69
describe the arcs. The first two tokens of each line are the source
70
and the target node of the arc, respectively, then come the map
71 71
values. The source and target tokens must be node labels.
72 72

	
73 73
\code
74 74
 @arcs
75 75
         capacity
76 76
 1   2   16
77 77
 1   3   12
78 78
 2   3   18
79 79
\endcode
80 80

	
81
If there is no map in the \c \@arcs section at all, then it must be
82
indicated by a sole '-' sign in the first line.
83

	
84
\code
85
 @arcs
86
         -
87
 1   2
88
 1   3
89
 2   3
90
\endcode
91

	
81 92
The \c \@edges is just a synonym of \c \@arcs. The \@arcs section can
82 93
also store the edge set of an undirected graph. In such case there is
83 94
a conventional method for store arc maps in the file, if two columns
84
has the same caption with \c '+' and \c '-' prefix, then these columns
95
have the same caption with \c '+' and \c '-' prefix, then these columns
85 96
can be regarded as the values of an arc map.
86 97

	
87 98
The \c \@attributes section contains key-value pairs, each line
88 99
consists of two tokens, an attribute name, and then an attribute
89 100
value. The value of the attribute could be also a label value of a
90 101
node or an edge, or even an edge label prefixed with \c '+' or \c '-',
91 102
which regards to the forward or backward directed arc of the
92 103
corresponding edge.
93 104

	
94 105
\code
95 106
 @attributes
96 107
 source 1
97 108
 target 3
98 109
 caption "LEMON test digraph"
99 110
\endcode
100 111

	
101 112
The \e LGF can contain extra sections, but there is no restriction on
102 113
the format of such sections.
103 114

	
104 115
*/
105 116
}
106 117

	
107 118
//  LocalWords:  whitespace whitespaces
Ignore white space 512 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5
 * Copyright (C) 2003-2010
5
 * Copyright (C) 2003-2011
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
///\ingroup lemon_io
20 20
///\file
21 21
///\brief \ref lgf-format "LEMON Graph Format" reader.
22 22

	
23 23

	
24 24
#ifndef LEMON_LGF_READER_H
25 25
#define LEMON_LGF_READER_H
26 26

	
27 27
#include <iostream>
28 28
#include <fstream>
29 29
#include <sstream>
30 30

	
31 31
#include <set>
32 32
#include <map>
33 33

	
34 34
#include <lemon/core.h>
35 35

	
36 36
#include <lemon/lgf_writer.h>
37 37

	
38 38
#include <lemon/concept_check.h>
39 39
#include <lemon/concepts/maps.h>
40 40

	
41 41
namespace lemon {
42 42

	
43 43
  namespace _reader_bits {
44 44

	
45 45
    template <typename Value>
46 46
    struct DefaultConverter {
47 47
      Value operator()(const std::string& str) {
48 48
        std::istringstream is(str);
49 49
        Value value;
50 50
        if (!(is >> value)) {
51 51
          throw FormatError("Cannot read token");
52 52
        }
53 53

	
54 54
        char c;
55 55
        if (is >> std::ws >> c) {
56 56
          throw FormatError("Remaining characters in token");
57 57
        }
58 58
        return value;
59 59
      }
60 60
    };
61 61

	
62 62
    template <>
63 63
    struct DefaultConverter<std::string> {
64 64
      std::string operator()(const std::string& str) {
65 65
        return str;
66 66
      }
67 67
    };
68 68

	
69 69
    template <typename _Item>
70 70
    class MapStorageBase {
71 71
    public:
72 72
      typedef _Item Item;
73 73

	
74 74
    public:
75 75
      MapStorageBase() {}
76 76
      virtual ~MapStorageBase() {}
77 77

	
78 78
      virtual void set(const Item& item, const std::string& value) = 0;
79 79

	
80 80
    };
81 81

	
82 82
    template <typename _Item, typename _Map,
83 83
              typename _Converter = DefaultConverter<typename _Map::Value> >
84 84
    class MapStorage : public MapStorageBase<_Item> {
85 85
    public:
86 86
      typedef _Map Map;
87 87
      typedef _Converter Converter;
88 88
      typedef _Item Item;
89 89

	
90 90
    private:
91 91
      Map& _map;
92 92
      Converter _converter;
93 93

	
94 94
    public:
95 95
      MapStorage(Map& map, const Converter& converter = Converter())
96 96
        : _map(map), _converter(converter) {}
97 97
      virtual ~MapStorage() {}
98 98

	
99 99
      virtual void set(const Item& item ,const std::string& value) {
100 100
        _map.set(item, _converter(value));
101 101
      }
102 102
    };
103 103

	
104 104
    template <typename _GR, bool _dir, typename _Map,
105 105
              typename _Converter = DefaultConverter<typename _Map::Value> >
106 106
    class GraphArcMapStorage : public MapStorageBase<typename _GR::Edge> {
107 107
    public:
108 108
      typedef _Map Map;
109 109
      typedef _Converter Converter;
110 110
      typedef _GR GR;
111 111
      typedef typename GR::Edge Item;
112 112
      static const bool dir = _dir;
113 113

	
114 114
    private:
115 115
      const GR& _graph;
116 116
      Map& _map;
117 117
      Converter _converter;
118 118

	
119 119
    public:
120 120
      GraphArcMapStorage(const GR& graph, Map& map,
121 121
                         const Converter& converter = Converter())
122 122
        : _graph(graph), _map(map), _converter(converter) {}
123 123
      virtual ~GraphArcMapStorage() {}
124 124

	
125 125
      virtual void set(const Item& item ,const std::string& value) {
126 126
        _map.set(_graph.direct(item, dir), _converter(value));
127 127
      }
128 128
    };
129 129

	
130 130
    class ValueStorageBase {
131 131
    public:
132 132
      ValueStorageBase() {}
133 133
      virtual ~ValueStorageBase() {}
134 134

	
135 135
      virtual void set(const std::string&) = 0;
136 136
    };
137 137

	
138 138
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
139 139
    class ValueStorage : public ValueStorageBase {
140 140
    public:
141 141
      typedef _Value Value;
142 142
      typedef _Converter Converter;
143 143

	
144 144
    private:
145 145
      Value& _value;
146 146
      Converter _converter;
147 147

	
148 148
    public:
149 149
      ValueStorage(Value& value, const Converter& converter = Converter())
150 150
        : _value(value), _converter(converter) {}
151 151

	
152 152
      virtual void set(const std::string& value) {
153 153
        _value = _converter(value);
154 154
      }
155 155
    };
156 156

	
157 157
    template <typename Value>
158 158
    struct MapLookUpConverter {
159 159
      const std::map<std::string, Value>& _map;
160 160

	
161 161
      MapLookUpConverter(const std::map<std::string, Value>& map)
162 162
        : _map(map) {}
163 163

	
164 164
      Value operator()(const std::string& str) {
165 165
        typename std::map<std::string, Value>::const_iterator it =
166 166
          _map.find(str);
167 167
        if (it == _map.end()) {
168 168
          std::ostringstream msg;
169 169
          msg << "Item not found: " << str;
170 170
          throw FormatError(msg.str());
171 171
        }
172 172
        return it->second;
173 173
      }
174 174
    };
175 175

	
176 176
    template <typename GR>
177 177
    struct GraphArcLookUpConverter {
178 178
      const GR& _graph;
179 179
      const std::map<std::string, typename GR::Edge>& _map;
180 180

	
181 181
      GraphArcLookUpConverter(const GR& graph,
182 182
                              const std::map<std::string,
183 183
                                             typename GR::Edge>& map)
184 184
        : _graph(graph), _map(map) {}
185 185

	
186 186
      typename GR::Arc operator()(const std::string& str) {
187 187
        if (str.empty() || (str[0] != '+' && str[0] != '-')) {
188 188
          throw FormatError("Item must start with '+' or '-'");
189 189
        }
190 190
        typename std::map<std::string, typename GR::Edge>
191 191
          ::const_iterator it = _map.find(str.substr(1));
192 192
        if (it == _map.end()) {
193 193
          throw FormatError("Item not found");
194 194
        }
195 195
        return _graph.direct(it->second, str[0] == '+');
196 196
      }
197 197
    };
198 198

	
199 199
    inline bool isWhiteSpace(char c) {
200 200
      return c == ' ' || c == '\t' || c == '\v' ||
201 201
        c == '\n' || c == '\r' || c == '\f';
202 202
    }
203 203

	
204 204
    inline bool isOct(char c) {
205 205
      return '0' <= c && c <='7';
206 206
    }
207 207

	
208 208
    inline int valueOct(char c) {
209 209
      LEMON_ASSERT(isOct(c), "The character is not octal.");
210 210
      return c - '0';
211 211
    }
212 212

	
213 213
    inline bool isHex(char c) {
214 214
      return ('0' <= c && c <= '9') ||
215 215
        ('a' <= c && c <= 'z') ||
216 216
        ('A' <= c && c <= 'Z');
217 217
    }
218 218

	
219 219
    inline int valueHex(char c) {
220 220
      LEMON_ASSERT(isHex(c), "The character is not hexadecimal.");
221 221
      if ('0' <= c && c <= '9') return c - '0';
222 222
      if ('a' <= c && c <= 'z') return c - 'a' + 10;
223 223
      return c - 'A' + 10;
224 224
    }
225 225

	
226 226
    inline bool isIdentifierFirstChar(char c) {
227 227
      return ('a' <= c && c <= 'z') ||
228 228
        ('A' <= c && c <= 'Z') || c == '_';
229 229
    }
230 230

	
231 231
    inline bool isIdentifierChar(char c) {
232 232
      return isIdentifierFirstChar(c) ||
233 233
        ('0' <= c && c <= '9');
234 234
    }
235 235

	
236 236
    inline char readEscape(std::istream& is) {
237 237
      char c;
238 238
      if (!is.get(c))
239 239
        throw FormatError("Escape format error");
240 240

	
241 241
      switch (c) {
242 242
      case '\\':
243 243
        return '\\';
244 244
      case '\"':
245 245
        return '\"';
246 246
      case '\'':
247 247
        return '\'';
248 248
      case '\?':
249 249
        return '\?';
250 250
      case 'a':
251 251
        return '\a';
252 252
      case 'b':
253 253
        return '\b';
254 254
      case 'f':
255 255
        return '\f';
256 256
      case 'n':
257 257
        return '\n';
258 258
      case 'r':
259 259
        return '\r';
260 260
      case 't':
261 261
        return '\t';
... ...
@@ -711,512 +711,519 @@
711 711
    /// \brief Set \c \@arcs section to be read
712 712
    ///
713 713
    /// Set \c \@arcs section to be read
714 714
    DigraphReader& arcs(const std::string& caption) {
715 715
      _arcs_caption = caption;
716 716
      return *this;
717 717
    }
718 718

	
719 719
    /// \brief Set \c \@attributes section to be read
720 720
    ///
721 721
    /// Set \c \@attributes section to be read
722 722
    DigraphReader& attributes(const std::string& caption) {
723 723
      _attributes_caption = caption;
724 724
      return *this;
725 725
    }
726 726

	
727 727
    /// @}
728 728

	
729 729
    /// \name Using Previously Constructed Node or Arc Set
730 730
    /// @{
731 731

	
732 732
    /// \brief Use previously constructed node set
733 733
    ///
734 734
    /// Use previously constructed node set, and specify the node
735 735
    /// label map.
736 736
    template <typename Map>
737 737
    DigraphReader& useNodes(const Map& map) {
738 738
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
739 739
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
740 740
      _use_nodes = true;
741 741
      _writer_bits::DefaultConverter<typename Map::Value> converter;
742 742
      for (NodeIt n(_digraph); n != INVALID; ++n) {
743 743
        _node_index.insert(std::make_pair(converter(map[n]), n));
744 744
      }
745 745
      return *this;
746 746
    }
747 747

	
748 748
    /// \brief Use previously constructed node set
749 749
    ///
750 750
    /// Use previously constructed node set, and specify the node
751 751
    /// label map and a functor which converts the label map values to
752 752
    /// \c std::string.
753 753
    template <typename Map, typename Converter>
754 754
    DigraphReader& useNodes(const Map& map,
755 755
                            const Converter& converter = Converter()) {
756 756
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
757 757
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
758 758
      _use_nodes = true;
759 759
      for (NodeIt n(_digraph); n != INVALID; ++n) {
760 760
        _node_index.insert(std::make_pair(converter(map[n]), n));
761 761
      }
762 762
      return *this;
763 763
    }
764 764

	
765 765
    /// \brief Use previously constructed arc set
766 766
    ///
767 767
    /// Use previously constructed arc set, and specify the arc
768 768
    /// label map.
769 769
    template <typename Map>
770 770
    DigraphReader& useArcs(const Map& map) {
771 771
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
772 772
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
773 773
      _use_arcs = true;
774 774
      _writer_bits::DefaultConverter<typename Map::Value> converter;
775 775
      for (ArcIt a(_digraph); a != INVALID; ++a) {
776 776
        _arc_index.insert(std::make_pair(converter(map[a]), a));
777 777
      }
778 778
      return *this;
779 779
    }
780 780

	
781 781
    /// \brief Use previously constructed arc set
782 782
    ///
783 783
    /// Use previously constructed arc set, and specify the arc
784 784
    /// label map and a functor which converts the label map values to
785 785
    /// \c std::string.
786 786
    template <typename Map, typename Converter>
787 787
    DigraphReader& useArcs(const Map& map,
788 788
                           const Converter& converter = Converter()) {
789 789
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
790 790
      LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member");
791 791
      _use_arcs = true;
792 792
      for (ArcIt a(_digraph); a != INVALID; ++a) {
793 793
        _arc_index.insert(std::make_pair(converter(map[a]), a));
794 794
      }
795 795
      return *this;
796 796
    }
797 797

	
798 798
    /// \brief Skips the reading of node section
799 799
    ///
800 800
    /// Omit the reading of the node section. This implies that each node
801 801
    /// map reading rule will be abandoned, and the nodes of the graph
802 802
    /// will not be constructed, which usually cause that the arc set
803 803
    /// could not be read due to lack of node name resolving.
804 804
    /// Therefore \c skipArcs() function should also be used, or
805 805
    /// \c useNodes() should be used to specify the label of the nodes.
806 806
    DigraphReader& skipNodes() {
807 807
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
808 808
      _skip_nodes = true;
809 809
      return *this;
810 810
    }
811 811

	
812 812
    /// \brief Skips the reading of arc section
813 813
    ///
814 814
    /// Omit the reading of the arc section. This implies that each arc
815 815
    /// map reading rule will be abandoned, and the arcs of the graph
816 816
    /// will not be constructed.
817 817
    DigraphReader& skipArcs() {
818 818
      LEMON_ASSERT(!_skip_arcs, "Skip arcs already set");
819 819
      _skip_arcs = true;
820 820
      return *this;
821 821
    }
822 822

	
823 823
    /// @}
824 824

	
825 825
  private:
826 826

	
827 827
    bool readLine() {
828 828
      std::string str;
829 829
      while(++line_num, std::getline(*_is, str)) {
830 830
        line.clear(); line.str(str);
831 831
        char c;
832 832
        if (line >> std::ws >> c && c != '#') {
833 833
          line.putback(c);
834 834
          return true;
835 835
        }
836 836
      }
837 837
      return false;
838 838
    }
839 839

	
840 840
    bool readSuccess() {
841 841
      return static_cast<bool>(*_is);
842 842
    }
843 843

	
844 844
    void skipSection() {
845 845
      char c;
846 846
      while (readSuccess() && line >> c && c != '@') {
847 847
        readLine();
848 848
      }
849 849
      if (readSuccess()) {
850 850
        line.putback(c);
851 851
      }
852 852
    }
853 853

	
854 854
    void readNodes() {
855 855

	
856 856
      std::vector<int> map_index(_node_maps.size());
857 857
      int map_num, label_index;
858 858

	
859 859
      char c;
860 860
      if (!readLine() || !(line >> c) || c == '@') {
861 861
        if (readSuccess() && line) line.putback(c);
862 862
        if (!_node_maps.empty())
863 863
          throw FormatError("Cannot find map names");
864 864
        return;
865 865
      }
866 866
      line.putback(c);
867 867

	
868 868
      {
869 869
        std::map<std::string, int> maps;
870 870

	
871 871
        std::string map;
872 872
        int index = 0;
873 873
        while (_reader_bits::readToken(line, map)) {
874 874
          if (maps.find(map) != maps.end()) {
875 875
            std::ostringstream msg;
876 876
            msg << "Multiple occurence of node map: " << map;
877 877
            throw FormatError(msg.str());
878 878
          }
879 879
          maps.insert(std::make_pair(map, index));
880 880
          ++index;
881 881
        }
882 882

	
883 883
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
884 884
          std::map<std::string, int>::iterator jt =
885 885
            maps.find(_node_maps[i].first);
886 886
          if (jt == maps.end()) {
887 887
            std::ostringstream msg;
888 888
            msg << "Map not found: " << _node_maps[i].first;
889 889
            throw FormatError(msg.str());
890 890
          }
891 891
          map_index[i] = jt->second;
892 892
        }
893 893

	
894 894
        {
895 895
          std::map<std::string, int>::iterator jt = maps.find("label");
896 896
          if (jt != maps.end()) {
897 897
            label_index = jt->second;
898 898
          } else {
899 899
            label_index = -1;
900 900
          }
901 901
        }
902 902
        map_num = maps.size();
903 903
      }
904 904

	
905 905
      while (readLine() && line >> c && c != '@') {
906 906
        line.putback(c);
907 907

	
908 908
        std::vector<std::string> tokens(map_num);
909 909
        for (int i = 0; i < map_num; ++i) {
910 910
          if (!_reader_bits::readToken(line, tokens[i])) {
911 911
            std::ostringstream msg;
912 912
            msg << "Column not found (" << i + 1 << ")";
913 913
            throw FormatError(msg.str());
914 914
          }
915 915
        }
916 916
        if (line >> std::ws >> c)
917 917
          throw FormatError("Extra character at the end of line");
918 918

	
919 919
        Node n;
920 920
        if (!_use_nodes) {
921 921
          n = _digraph.addNode();
922 922
          if (label_index != -1)
923 923
            _node_index.insert(std::make_pair(tokens[label_index], n));
924 924
        } else {
925 925
          if (label_index == -1)
926 926
            throw FormatError("Label map not found");
927 927
          typename std::map<std::string, Node>::iterator it =
928 928
            _node_index.find(tokens[label_index]);
929 929
          if (it == _node_index.end()) {
930 930
            std::ostringstream msg;
931 931
            msg << "Node with label not found: " << tokens[label_index];
932 932
            throw FormatError(msg.str());
933 933
          }
934 934
          n = it->second;
935 935
        }
936 936

	
937 937
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
938 938
          _node_maps[i].second->set(n, tokens[map_index[i]]);
939 939
        }
940 940

	
941 941
      }
942 942
      if (readSuccess()) {
943 943
        line.putback(c);
944 944
      }
945 945
    }
946 946

	
947 947
    void readArcs() {
948 948

	
949 949
      std::vector<int> map_index(_arc_maps.size());
950 950
      int map_num, label_index;
951 951

	
952 952
      char c;
953 953
      if (!readLine() || !(line >> c) || c == '@') {
954 954
        if (readSuccess() && line) line.putback(c);
955 955
        if (!_arc_maps.empty())
956 956
          throw FormatError("Cannot find map names");
957 957
        return;
958 958
      }
959 959
      line.putback(c);
960 960

	
961 961
      {
962 962
        std::map<std::string, int> maps;
963 963

	
964 964
        std::string map;
965 965
        int index = 0;
966 966
        while (_reader_bits::readToken(line, map)) {
967
          if(map == "-") {
968
              if(index!=0)
969
                throw FormatError("'-' is not allowed as a map name");
970
              else if (line >> std::ws >> c)
971
                throw FormatError("Extra character at the end of line");
972
              else break;
973
            }
967 974
          if (maps.find(map) != maps.end()) {
968 975
            std::ostringstream msg;
969 976
            msg << "Multiple occurence of arc map: " << map;
970 977
            throw FormatError(msg.str());
971 978
          }
972 979
          maps.insert(std::make_pair(map, index));
973 980
          ++index;
974 981
        }
975 982

	
976 983
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
977 984
          std::map<std::string, int>::iterator jt =
978 985
            maps.find(_arc_maps[i].first);
979 986
          if (jt == maps.end()) {
980 987
            std::ostringstream msg;
981 988
            msg << "Map not found: " << _arc_maps[i].first;
982 989
            throw FormatError(msg.str());
983 990
          }
984 991
          map_index[i] = jt->second;
985 992
        }
986 993

	
987 994
        {
988 995
          std::map<std::string, int>::iterator jt = maps.find("label");
989 996
          if (jt != maps.end()) {
990 997
            label_index = jt->second;
991 998
          } else {
992 999
            label_index = -1;
993 1000
          }
994 1001
        }
995 1002
        map_num = maps.size();
996 1003
      }
997 1004

	
998 1005
      while (readLine() && line >> c && c != '@') {
999 1006
        line.putback(c);
1000 1007

	
1001 1008
        std::string source_token;
1002 1009
        std::string target_token;
1003 1010

	
1004 1011
        if (!_reader_bits::readToken(line, source_token))
1005 1012
          throw FormatError("Source not found");
1006 1013

	
1007 1014
        if (!_reader_bits::readToken(line, target_token))
1008 1015
          throw FormatError("Target not found");
1009 1016

	
1010 1017
        std::vector<std::string> tokens(map_num);
1011 1018
        for (int i = 0; i < map_num; ++i) {
1012 1019
          if (!_reader_bits::readToken(line, tokens[i])) {
1013 1020
            std::ostringstream msg;
1014 1021
            msg << "Column not found (" << i + 1 << ")";
1015 1022
            throw FormatError(msg.str());
1016 1023
          }
1017 1024
        }
1018 1025
        if (line >> std::ws >> c)
1019 1026
          throw FormatError("Extra character at the end of line");
1020 1027

	
1021 1028
        Arc a;
1022 1029
        if (!_use_arcs) {
1023 1030

	
1024 1031
          typename NodeIndex::iterator it;
1025 1032

	
1026 1033
          it = _node_index.find(source_token);
1027 1034
          if (it == _node_index.end()) {
1028 1035
            std::ostringstream msg;
1029 1036
            msg << "Item not found: " << source_token;
1030 1037
            throw FormatError(msg.str());
1031 1038
          }
1032 1039
          Node source = it->second;
1033 1040

	
1034 1041
          it = _node_index.find(target_token);
1035 1042
          if (it == _node_index.end()) {
1036 1043
            std::ostringstream msg;
1037 1044
            msg << "Item not found: " << target_token;
1038 1045
            throw FormatError(msg.str());
1039 1046
          }
1040 1047
          Node target = it->second;
1041 1048

	
1042 1049
          a = _digraph.addArc(source, target);
1043 1050
          if (label_index != -1)
1044 1051
            _arc_index.insert(std::make_pair(tokens[label_index], a));
1045 1052
        } else {
1046 1053
          if (label_index == -1)
1047 1054
            throw FormatError("Label map not found");
1048 1055
          typename std::map<std::string, Arc>::iterator it =
1049 1056
            _arc_index.find(tokens[label_index]);
1050 1057
          if (it == _arc_index.end()) {
1051 1058
            std::ostringstream msg;
1052 1059
            msg << "Arc with label not found: " << tokens[label_index];
1053 1060
            throw FormatError(msg.str());
1054 1061
          }
1055 1062
          a = it->second;
1056 1063
        }
1057 1064

	
1058 1065
        for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
1059 1066
          _arc_maps[i].second->set(a, tokens[map_index[i]]);
1060 1067
        }
1061 1068

	
1062 1069
      }
1063 1070
      if (readSuccess()) {
1064 1071
        line.putback(c);
1065 1072
      }
1066 1073
    }
1067 1074

	
1068 1075
    void readAttributes() {
1069 1076

	
1070 1077
      std::set<std::string> read_attr;
1071 1078

	
1072 1079
      char c;
1073 1080
      while (readLine() && line >> c && c != '@') {
1074 1081
        line.putback(c);
1075 1082

	
1076 1083
        std::string attr, token;
1077 1084
        if (!_reader_bits::readToken(line, attr))
1078 1085
          throw FormatError("Attribute name not found");
1079 1086
        if (!_reader_bits::readToken(line, token))
1080 1087
          throw FormatError("Attribute value not found");
1081 1088
        if (line >> c)
1082 1089
          throw FormatError("Extra character at the end of line");
1083 1090

	
1084 1091
        {
1085 1092
          std::set<std::string>::iterator it = read_attr.find(attr);
1086 1093
          if (it != read_attr.end()) {
1087 1094
            std::ostringstream msg;
1088 1095
            msg << "Multiple occurence of attribute: " << attr;
1089 1096
            throw FormatError(msg.str());
1090 1097
          }
1091 1098
          read_attr.insert(attr);
1092 1099
        }
1093 1100

	
1094 1101
        {
1095 1102
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1096 1103
          while (it != _attributes.end() && it->first == attr) {
1097 1104
            it->second->set(token);
1098 1105
            ++it;
1099 1106
          }
1100 1107
        }
1101 1108

	
1102 1109
      }
1103 1110
      if (readSuccess()) {
1104 1111
        line.putback(c);
1105 1112
      }
1106 1113
      for (typename Attributes::iterator it = _attributes.begin();
1107 1114
           it != _attributes.end(); ++it) {
1108 1115
        if (read_attr.find(it->first) == read_attr.end()) {
1109 1116
          std::ostringstream msg;
1110 1117
          msg << "Attribute not found: " << it->first;
1111 1118
          throw FormatError(msg.str());
1112 1119
        }
1113 1120
      }
1114 1121
    }
1115 1122

	
1116 1123
  public:
1117 1124

	
1118 1125
    /// \name Execution of the Reader
1119 1126
    /// @{
1120 1127

	
1121 1128
    /// \brief Start the batch processing
1122 1129
    ///
1123 1130
    /// This function starts the batch processing
1124 1131
    void run() {
1125 1132
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1126 1133

	
1127 1134
      bool nodes_done = _skip_nodes;
1128 1135
      bool arcs_done = _skip_arcs;
1129 1136
      bool attributes_done = false;
1130 1137

	
1131 1138
      line_num = 0;
1132 1139
      readLine();
1133 1140
      skipSection();
1134 1141

	
1135 1142
      while (readSuccess()) {
1136 1143
        try {
1137 1144
          char c;
1138 1145
          std::string section, caption;
1139 1146
          line >> c;
1140 1147
          _reader_bits::readToken(line, section);
1141 1148
          _reader_bits::readToken(line, caption);
1142 1149

	
1143 1150
          if (line >> c)
1144 1151
            throw FormatError("Extra character at the end of line");
1145 1152

	
1146 1153
          if (section == "nodes" && !nodes_done) {
1147 1154
            if (_nodes_caption.empty() || _nodes_caption == caption) {
1148 1155
              readNodes();
1149 1156
              nodes_done = true;
1150 1157
            }
1151 1158
          } else if ((section == "arcs" || section == "edges") &&
1152 1159
                     !arcs_done) {
1153 1160
            if (_arcs_caption.empty() || _arcs_caption == caption) {
1154 1161
              readArcs();
1155 1162
              arcs_done = true;
1156 1163
            }
1157 1164
          } else if (section == "attributes" && !attributes_done) {
1158 1165
            if (_attributes_caption.empty() || _attributes_caption == caption) {
1159 1166
              readAttributes();
1160 1167
              attributes_done = true;
1161 1168
            }
1162 1169
          } else {
1163 1170
            readLine();
1164 1171
            skipSection();
1165 1172
          }
1166 1173
        } catch (FormatError& error) {
1167 1174
          error.line(line_num);
1168 1175
          error.file(_filename);
1169 1176
          throw;
1170 1177
        }
1171 1178
      }
1172 1179

	
1173 1180
      if (!nodes_done) {
1174 1181
        throw FormatError("Section @nodes not found");
1175 1182
      }
1176 1183

	
1177 1184
      if (!arcs_done) {
1178 1185
        throw FormatError("Section @arcs not found");
1179 1186
      }
1180 1187

	
1181 1188
      if (!attributes_done && !_attributes.empty()) {
1182 1189
        throw FormatError("Section @attributes not found");
1183 1190
      }
1184 1191

	
1185 1192
    }
1186 1193

	
1187 1194
    /// @}
1188 1195

	
1189 1196
  };
1190 1197

	
1191 1198
  /// \ingroup lemon_io
1192 1199
  ///
1193 1200
  /// \brief Return a \ref DigraphReader class
1194 1201
  ///
1195 1202
  /// This function just returns a \ref DigraphReader class.
1196 1203
  ///
1197 1204
  /// With this function a digraph can be read from an
1198 1205
  /// \ref lgf-format "LGF" file or input stream with several maps and
1199 1206
  /// attributes. For example, there is network flow problem on a
1200 1207
  /// digraph, i.e. a digraph with a \e capacity map on the arcs and
1201 1208
  /// \e source and \e target nodes. This digraph can be read with the
1202 1209
  /// following code:
1203 1210
  ///
1204 1211
  ///\code
1205 1212
  ///ListDigraph digraph;
1206 1213
  ///ListDigraph::ArcMap<int> cm(digraph);
1207 1214
  ///ListDigraph::Node src, trg;
1208 1215
  ///digraphReader(digraph, std::cin).
1209 1216
  ///  arcMap("capacity", cap).
1210 1217
  ///  node("source", src).
1211 1218
  ///  node("target", trg).
1212 1219
  ///  run();
1213 1220
  ///\endcode
1214 1221
  ///
1215 1222
  /// For a complete documentation, please see the \ref DigraphReader
1216 1223
  /// class documentation.
1217 1224
  /// \warning Don't forget to put the \ref DigraphReader::run() "run()"
1218 1225
  /// to the end of the parameter list.
1219 1226
  /// \relates DigraphReader
1220 1227
  /// \sa digraphReader(TDGR& digraph, const std::string& fn)
1221 1228
  /// \sa digraphReader(TDGR& digraph, const char* fn)
1222 1229
  template <typename TDGR>
... ...
@@ -1581,512 +1588,519 @@
1581 1588
    ///
1582 1589
    /// Set \c \@edges section to be read.
1583 1590
    GraphReader& edges(const std::string& caption) {
1584 1591
      _edges_caption = caption;
1585 1592
      return *this;
1586 1593
    }
1587 1594

	
1588 1595
    /// \brief Set \c \@attributes section to be read
1589 1596
    ///
1590 1597
    /// Set \c \@attributes section to be read.
1591 1598
    GraphReader& attributes(const std::string& caption) {
1592 1599
      _attributes_caption = caption;
1593 1600
      return *this;
1594 1601
    }
1595 1602

	
1596 1603
    /// @}
1597 1604

	
1598 1605
    /// \name Using Previously Constructed Node or Edge Set
1599 1606
    /// @{
1600 1607

	
1601 1608
    /// \brief Use previously constructed node set
1602 1609
    ///
1603 1610
    /// Use previously constructed node set, and specify the node
1604 1611
    /// label map.
1605 1612
    template <typename Map>
1606 1613
    GraphReader& useNodes(const Map& map) {
1607 1614
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1608 1615
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1609 1616
      _use_nodes = true;
1610 1617
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1611 1618
      for (NodeIt n(_graph); n != INVALID; ++n) {
1612 1619
        _node_index.insert(std::make_pair(converter(map[n]), n));
1613 1620
      }
1614 1621
      return *this;
1615 1622
    }
1616 1623

	
1617 1624
    /// \brief Use previously constructed node set
1618 1625
    ///
1619 1626
    /// Use previously constructed node set, and specify the node
1620 1627
    /// label map and a functor which converts the label map values to
1621 1628
    /// \c std::string.
1622 1629
    template <typename Map, typename Converter>
1623 1630
    GraphReader& useNodes(const Map& map,
1624 1631
                            const Converter& converter = Converter()) {
1625 1632
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1626 1633
      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
1627 1634
      _use_nodes = true;
1628 1635
      for (NodeIt n(_graph); n != INVALID; ++n) {
1629 1636
        _node_index.insert(std::make_pair(converter(map[n]), n));
1630 1637
      }
1631 1638
      return *this;
1632 1639
    }
1633 1640

	
1634 1641
    /// \brief Use previously constructed edge set
1635 1642
    ///
1636 1643
    /// Use previously constructed edge set, and specify the edge
1637 1644
    /// label map.
1638 1645
    template <typename Map>
1639 1646
    GraphReader& useEdges(const Map& map) {
1640 1647
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1641 1648
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1642 1649
      _use_edges = true;
1643 1650
      _writer_bits::DefaultConverter<typename Map::Value> converter;
1644 1651
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1645 1652
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1646 1653
      }
1647 1654
      return *this;
1648 1655
    }
1649 1656

	
1650 1657
    /// \brief Use previously constructed edge set
1651 1658
    ///
1652 1659
    /// Use previously constructed edge set, and specify the edge
1653 1660
    /// label map and a functor which converts the label map values to
1654 1661
    /// \c std::string.
1655 1662
    template <typename Map, typename Converter>
1656 1663
    GraphReader& useEdges(const Map& map,
1657 1664
                            const Converter& converter = Converter()) {
1658 1665
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
1659 1666
      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
1660 1667
      _use_edges = true;
1661 1668
      for (EdgeIt a(_graph); a != INVALID; ++a) {
1662 1669
        _edge_index.insert(std::make_pair(converter(map[a]), a));
1663 1670
      }
1664 1671
      return *this;
1665 1672
    }
1666 1673

	
1667 1674
    /// \brief Skip the reading of node section
1668 1675
    ///
1669 1676
    /// Omit the reading of the node section. This implies that each node
1670 1677
    /// map reading rule will be abandoned, and the nodes of the graph
1671 1678
    /// will not be constructed, which usually cause that the edge set
1672 1679
    /// could not be read due to lack of node name
1673 1680
    /// could not be read due to lack of node name resolving.
1674 1681
    /// Therefore \c skipEdges() function should also be used, or
1675 1682
    /// \c useNodes() should be used to specify the label of the nodes.
1676 1683
    GraphReader& skipNodes() {
1677 1684
      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
1678 1685
      _skip_nodes = true;
1679 1686
      return *this;
1680 1687
    }
1681 1688

	
1682 1689
    /// \brief Skip the reading of edge section
1683 1690
    ///
1684 1691
    /// Omit the reading of the edge section. This implies that each edge
1685 1692
    /// map reading rule will be abandoned, and the edges of the graph
1686 1693
    /// will not be constructed.
1687 1694
    GraphReader& skipEdges() {
1688 1695
      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
1689 1696
      _skip_edges = true;
1690 1697
      return *this;
1691 1698
    }
1692 1699

	
1693 1700
    /// @}
1694 1701

	
1695 1702
  private:
1696 1703

	
1697 1704
    bool readLine() {
1698 1705
      std::string str;
1699 1706
      while(++line_num, std::getline(*_is, str)) {
1700 1707
        line.clear(); line.str(str);
1701 1708
        char c;
1702 1709
        if (line >> std::ws >> c && c != '#') {
1703 1710
          line.putback(c);
1704 1711
          return true;
1705 1712
        }
1706 1713
      }
1707 1714
      return false;
1708 1715
    }
1709 1716

	
1710 1717
    bool readSuccess() {
1711 1718
      return static_cast<bool>(*_is);
1712 1719
    }
1713 1720

	
1714 1721
    void skipSection() {
1715 1722
      char c;
1716 1723
      while (readSuccess() && line >> c && c != '@') {
1717 1724
        readLine();
1718 1725
      }
1719 1726
      if (readSuccess()) {
1720 1727
        line.putback(c);
1721 1728
      }
1722 1729
    }
1723 1730

	
1724 1731
    void readNodes() {
1725 1732

	
1726 1733
      std::vector<int> map_index(_node_maps.size());
1727 1734
      int map_num, label_index;
1728 1735

	
1729 1736
      char c;
1730 1737
      if (!readLine() || !(line >> c) || c == '@') {
1731 1738
        if (readSuccess() && line) line.putback(c);
1732 1739
        if (!_node_maps.empty())
1733 1740
          throw FormatError("Cannot find map names");
1734 1741
        return;
1735 1742
      }
1736 1743
      line.putback(c);
1737 1744

	
1738 1745
      {
1739 1746
        std::map<std::string, int> maps;
1740 1747

	
1741 1748
        std::string map;
1742 1749
        int index = 0;
1743 1750
        while (_reader_bits::readToken(line, map)) {
1744 1751
          if (maps.find(map) != maps.end()) {
1745 1752
            std::ostringstream msg;
1746 1753
            msg << "Multiple occurence of node map: " << map;
1747 1754
            throw FormatError(msg.str());
1748 1755
          }
1749 1756
          maps.insert(std::make_pair(map, index));
1750 1757
          ++index;
1751 1758
        }
1752 1759

	
1753 1760
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1754 1761
          std::map<std::string, int>::iterator jt =
1755 1762
            maps.find(_node_maps[i].first);
1756 1763
          if (jt == maps.end()) {
1757 1764
            std::ostringstream msg;
1758 1765
            msg << "Map not found: " << _node_maps[i].first;
1759 1766
            throw FormatError(msg.str());
1760 1767
          }
1761 1768
          map_index[i] = jt->second;
1762 1769
        }
1763 1770

	
1764 1771
        {
1765 1772
          std::map<std::string, int>::iterator jt = maps.find("label");
1766 1773
          if (jt != maps.end()) {
1767 1774
            label_index = jt->second;
1768 1775
          } else {
1769 1776
            label_index = -1;
1770 1777
          }
1771 1778
        }
1772 1779
        map_num = maps.size();
1773 1780
      }
1774 1781

	
1775 1782
      while (readLine() && line >> c && c != '@') {
1776 1783
        line.putback(c);
1777 1784

	
1778 1785
        std::vector<std::string> tokens(map_num);
1779 1786
        for (int i = 0; i < map_num; ++i) {
1780 1787
          if (!_reader_bits::readToken(line, tokens[i])) {
1781 1788
            std::ostringstream msg;
1782 1789
            msg << "Column not found (" << i + 1 << ")";
1783 1790
            throw FormatError(msg.str());
1784 1791
          }
1785 1792
        }
1786 1793
        if (line >> std::ws >> c)
1787 1794
          throw FormatError("Extra character at the end of line");
1788 1795

	
1789 1796
        Node n;
1790 1797
        if (!_use_nodes) {
1791 1798
          n = _graph.addNode();
1792 1799
          if (label_index != -1)
1793 1800
            _node_index.insert(std::make_pair(tokens[label_index], n));
1794 1801
        } else {
1795 1802
          if (label_index == -1)
1796 1803
            throw FormatError("Label map not found");
1797 1804
          typename std::map<std::string, Node>::iterator it =
1798 1805
            _node_index.find(tokens[label_index]);
1799 1806
          if (it == _node_index.end()) {
1800 1807
            std::ostringstream msg;
1801 1808
            msg << "Node with label not found: " << tokens[label_index];
1802 1809
            throw FormatError(msg.str());
1803 1810
          }
1804 1811
          n = it->second;
1805 1812
        }
1806 1813

	
1807 1814
        for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
1808 1815
          _node_maps[i].second->set(n, tokens[map_index[i]]);
1809 1816
        }
1810 1817

	
1811 1818
      }
1812 1819
      if (readSuccess()) {
1813 1820
        line.putback(c);
1814 1821
      }
1815 1822
    }
1816 1823

	
1817 1824
    void readEdges() {
1818 1825

	
1819 1826
      std::vector<int> map_index(_edge_maps.size());
1820 1827
      int map_num, label_index;
1821 1828

	
1822 1829
      char c;
1823 1830
      if (!readLine() || !(line >> c) || c == '@') {
1824 1831
        if (readSuccess() && line) line.putback(c);
1825 1832
        if (!_edge_maps.empty())
1826 1833
          throw FormatError("Cannot find map names");
1827 1834
        return;
1828 1835
      }
1829 1836
      line.putback(c);
1830 1837

	
1831 1838
      {
1832 1839
        std::map<std::string, int> maps;
1833 1840

	
1834 1841
        std::string map;
1835 1842
        int index = 0;
1836 1843
        while (_reader_bits::readToken(line, map)) {
1844
          if(map == "-") {
1845
              if(index!=0)
1846
                throw FormatError("'-' is not allowed as a map name");
1847
              else if (line >> std::ws >> c)
1848
                throw FormatError("Extra character at the end of line");
1849
              else break;
1850
            }
1837 1851
          if (maps.find(map) != maps.end()) {
1838 1852
            std::ostringstream msg;
1839 1853
            msg << "Multiple occurence of edge map: " << map;
1840 1854
            throw FormatError(msg.str());
1841 1855
          }
1842 1856
          maps.insert(std::make_pair(map, index));
1843 1857
          ++index;
1844 1858
        }
1845 1859

	
1846 1860
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1847 1861
          std::map<std::string, int>::iterator jt =
1848 1862
            maps.find(_edge_maps[i].first);
1849 1863
          if (jt == maps.end()) {
1850 1864
            std::ostringstream msg;
1851 1865
            msg << "Map not found: " << _edge_maps[i].first;
1852 1866
            throw FormatError(msg.str());
1853 1867
          }
1854 1868
          map_index[i] = jt->second;
1855 1869
        }
1856 1870

	
1857 1871
        {
1858 1872
          std::map<std::string, int>::iterator jt = maps.find("label");
1859 1873
          if (jt != maps.end()) {
1860 1874
            label_index = jt->second;
1861 1875
          } else {
1862 1876
            label_index = -1;
1863 1877
          }
1864 1878
        }
1865 1879
        map_num = maps.size();
1866 1880
      }
1867 1881

	
1868 1882
      while (readLine() && line >> c && c != '@') {
1869 1883
        line.putback(c);
1870 1884

	
1871 1885
        std::string source_token;
1872 1886
        std::string target_token;
1873 1887

	
1874 1888
        if (!_reader_bits::readToken(line, source_token))
1875 1889
          throw FormatError("Node u not found");
1876 1890

	
1877 1891
        if (!_reader_bits::readToken(line, target_token))
1878 1892
          throw FormatError("Node v not found");
1879 1893

	
1880 1894
        std::vector<std::string> tokens(map_num);
1881 1895
        for (int i = 0; i < map_num; ++i) {
1882 1896
          if (!_reader_bits::readToken(line, tokens[i])) {
1883 1897
            std::ostringstream msg;
1884 1898
            msg << "Column not found (" << i + 1 << ")";
1885 1899
            throw FormatError(msg.str());
1886 1900
          }
1887 1901
        }
1888 1902
        if (line >> std::ws >> c)
1889 1903
          throw FormatError("Extra character at the end of line");
1890 1904

	
1891 1905
        Edge e;
1892 1906
        if (!_use_edges) {
1893 1907

	
1894 1908
          typename NodeIndex::iterator it;
1895 1909

	
1896 1910
          it = _node_index.find(source_token);
1897 1911
          if (it == _node_index.end()) {
1898 1912
            std::ostringstream msg;
1899 1913
            msg << "Item not found: " << source_token;
1900 1914
            throw FormatError(msg.str());
1901 1915
          }
1902 1916
          Node source = it->second;
1903 1917

	
1904 1918
          it = _node_index.find(target_token);
1905 1919
          if (it == _node_index.end()) {
1906 1920
            std::ostringstream msg;
1907 1921
            msg << "Item not found: " << target_token;
1908 1922
            throw FormatError(msg.str());
1909 1923
          }
1910 1924
          Node target = it->second;
1911 1925

	
1912 1926
          e = _graph.addEdge(source, target);
1913 1927
          if (label_index != -1)
1914 1928
            _edge_index.insert(std::make_pair(tokens[label_index], e));
1915 1929
        } else {
1916 1930
          if (label_index == -1)
1917 1931
            throw FormatError("Label map not found");
1918 1932
          typename std::map<std::string, Edge>::iterator it =
1919 1933
            _edge_index.find(tokens[label_index]);
1920 1934
          if (it == _edge_index.end()) {
1921 1935
            std::ostringstream msg;
1922 1936
            msg << "Edge with label not found: " << tokens[label_index];
1923 1937
            throw FormatError(msg.str());
1924 1938
          }
1925 1939
          e = it->second;
1926 1940
        }
1927 1941

	
1928 1942
        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
1929 1943
          _edge_maps[i].second->set(e, tokens[map_index[i]]);
1930 1944
        }
1931 1945

	
1932 1946
      }
1933 1947
      if (readSuccess()) {
1934 1948
        line.putback(c);
1935 1949
      }
1936 1950
    }
1937 1951

	
1938 1952
    void readAttributes() {
1939 1953

	
1940 1954
      std::set<std::string> read_attr;
1941 1955

	
1942 1956
      char c;
1943 1957
      while (readLine() && line >> c && c != '@') {
1944 1958
        line.putback(c);
1945 1959

	
1946 1960
        std::string attr, token;
1947 1961
        if (!_reader_bits::readToken(line, attr))
1948 1962
          throw FormatError("Attribute name not found");
1949 1963
        if (!_reader_bits::readToken(line, token))
1950 1964
          throw FormatError("Attribute value not found");
1951 1965
        if (line >> c)
1952 1966
          throw FormatError("Extra character at the end of line");
1953 1967

	
1954 1968
        {
1955 1969
          std::set<std::string>::iterator it = read_attr.find(attr);
1956 1970
          if (it != read_attr.end()) {
1957 1971
            std::ostringstream msg;
1958 1972
            msg << "Multiple occurence of attribute: " << attr;
1959 1973
            throw FormatError(msg.str());
1960 1974
          }
1961 1975
          read_attr.insert(attr);
1962 1976
        }
1963 1977

	
1964 1978
        {
1965 1979
          typename Attributes::iterator it = _attributes.lower_bound(attr);
1966 1980
          while (it != _attributes.end() && it->first == attr) {
1967 1981
            it->second->set(token);
1968 1982
            ++it;
1969 1983
          }
1970 1984
        }
1971 1985

	
1972 1986
      }
1973 1987
      if (readSuccess()) {
1974 1988
        line.putback(c);
1975 1989
      }
1976 1990
      for (typename Attributes::iterator it = _attributes.begin();
1977 1991
           it != _attributes.end(); ++it) {
1978 1992
        if (read_attr.find(it->first) == read_attr.end()) {
1979 1993
          std::ostringstream msg;
1980 1994
          msg << "Attribute not found: " << it->first;
1981 1995
          throw FormatError(msg.str());
1982 1996
        }
1983 1997
      }
1984 1998
    }
1985 1999

	
1986 2000
  public:
1987 2001

	
1988 2002
    /// \name Execution of the Reader
1989 2003
    /// @{
1990 2004

	
1991 2005
    /// \brief Start the batch processing
1992 2006
    ///
1993 2007
    /// This function starts the batch processing
1994 2008
    void run() {
1995 2009

	
1996 2010
      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
1997 2011

	
1998 2012
      bool nodes_done = _skip_nodes;
1999 2013
      bool edges_done = _skip_edges;
2000 2014
      bool attributes_done = false;
2001 2015

	
2002 2016
      line_num = 0;
2003 2017
      readLine();
2004 2018
      skipSection();
2005 2019

	
2006 2020
      while (readSuccess()) {
2007 2021
        try {
2008 2022
          char c;
2009 2023
          std::string section, caption;
2010 2024
          line >> c;
2011 2025
          _reader_bits::readToken(line, section);
2012 2026
          _reader_bits::readToken(line, caption);
2013 2027

	
2014 2028
          if (line >> c)
2015 2029
            throw FormatError("Extra character at the end of line");
2016 2030

	
2017 2031
          if (section == "nodes" && !nodes_done) {
2018 2032
            if (_nodes_caption.empty() || _nodes_caption == caption) {
2019 2033
              readNodes();
2020 2034
              nodes_done = true;
2021 2035
            }
2022 2036
          } else if ((section == "edges" || section == "arcs") &&
2023 2037
                     !edges_done) {
2024 2038
            if (_edges_caption.empty() || _edges_caption == caption) {
2025 2039
              readEdges();
2026 2040
              edges_done = true;
2027 2041
            }
2028 2042
          } else if (section == "attributes" && !attributes_done) {
2029 2043
            if (_attributes_caption.empty() || _attributes_caption == caption) {
2030 2044
              readAttributes();
2031 2045
              attributes_done = true;
2032 2046
            }
2033 2047
          } else {
2034 2048
            readLine();
2035 2049
            skipSection();
2036 2050
          }
2037 2051
        } catch (FormatError& error) {
2038 2052
          error.line(line_num);
2039 2053
          error.file(_filename);
2040 2054
          throw;
2041 2055
        }
2042 2056
      }
2043 2057

	
2044 2058
      if (!nodes_done) {
2045 2059
        throw FormatError("Section @nodes not found");
2046 2060
      }
2047 2061

	
2048 2062
      if (!edges_done) {
2049 2063
        throw FormatError("Section @edges not found");
2050 2064
      }
2051 2065

	
2052 2066
      if (!attributes_done && !_attributes.empty()) {
2053 2067
        throw FormatError("Section @attributes not found");
2054 2068
      }
2055 2069

	
2056 2070
    }
2057 2071

	
2058 2072
    /// @}
2059 2073

	
2060 2074
  };
2061 2075

	
2062 2076
  /// \ingroup lemon_io
2063 2077
  ///
2064 2078
  /// \brief Return a \ref GraphReader class
2065 2079
  ///
2066 2080
  /// This function just returns a \ref GraphReader class.
2067 2081
  ///
2068 2082
  /// With this function a graph can be read from an
2069 2083
  /// \ref lgf-format "LGF" file or input stream with several maps and
2070 2084
  /// attributes. For example, there is weighted matching problem on a
2071 2085
  /// graph, i.e. a graph with a \e weight map on the edges. This
2072 2086
  /// graph can be read with the following code:
2073 2087
  ///
2074 2088
  ///\code
2075 2089
  ///ListGraph graph;
2076 2090
  ///ListGraph::EdgeMap<int> weight(graph);
2077 2091
  ///graphReader(graph, std::cin).
2078 2092
  ///  edgeMap("weight", weight).
2079 2093
  ///  run();
2080 2094
  ///\endcode
2081 2095
  ///
2082 2096
  /// For a complete documentation, please see the \ref GraphReader
2083 2097
  /// class documentation.
2084 2098
  /// \warning Don't forget to put the \ref GraphReader::run() "run()"
2085 2099
  /// to the end of the parameter list.
2086 2100
  /// \relates GraphReader
2087 2101
  /// \sa graphReader(TGR& graph, const std::string& fn)
2088 2102
  /// \sa graphReader(TGR& graph, const char* fn)
2089 2103
  template <typename TGR>
2090 2104
  GraphReader<TGR> graphReader(TGR& graph, std::istream& is) {
2091 2105
    GraphReader<TGR> tmp(graph, is);
2092 2106
    return tmp;
Ignore white space 512 line context
1 1
INCLUDE_DIRECTORIES(
2 2
  ${PROJECT_SOURCE_DIR}
3 3
  ${PROJECT_BINARY_DIR}
4 4
)
5 5

	
6 6
LINK_DIRECTORIES(
7 7
  ${PROJECT_BINARY_DIR}/lemon
8 8
)
9 9

	
10 10
SET(TEST_WITH_VALGRIND "NO" CACHE STRING
11 11
  "Run the test with valgrind (YES/NO).")
12 12
SET(VALGRIND_FLAGS "" CACHE STRING "Valgrind flags used by the tests.")
13 13

	
14 14
SET(TESTS
15 15
  adaptors_test
16 16
  bellman_ford_test
17 17
  bfs_test
18 18
  circulation_test
19 19
  connectivity_test
20 20
  counter_test
21 21
  dfs_test
22 22
  digraph_test
23 23
  dijkstra_test
24 24
  dim_test
25 25
  edge_set_test
26 26
  error_test
27 27
  euler_test
28 28
  fractional_matching_test
29 29
  gomory_hu_test
30 30
  graph_copy_test
31 31
  graph_test
32 32
  graph_utils_test
33 33
  hao_orlin_test
34 34
  heap_test
35 35
  kruskal_test
36
  lgf_test
36 37
  maps_test
37 38
  matching_test
38 39
  min_cost_arborescence_test
39 40
  min_cost_flow_test
40 41
  min_mean_cycle_test
41 42
  path_test
42 43
  planarity_test
43 44
  preflow_test
44 45
  radix_sort_test
45 46
  random_test
46 47
  suurballe_test
47 48
  time_measure_test
48 49
  unionfind_test
49 50
)
50 51

	
51 52
IF(LEMON_HAVE_LP)
52 53
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
53 54
    ADD_EXECUTABLE(lp_test lp_test.cc)
54 55
  ELSE()
55 56
    ADD_EXECUTABLE(lp_test EXCLUDE_FROM_ALL lp_test.cc)
56 57
  ENDIF()
57 58

	
58 59
  SET(LP_TEST_LIBS lemon)
59 60

	
60 61
  IF(LEMON_HAVE_GLPK)
61 62
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${GLPK_LIBRARIES})
62 63
  ENDIF()
63 64
  IF(LEMON_HAVE_CPLEX)
64 65
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${CPLEX_LIBRARIES})
65 66
  ENDIF()
66 67
  IF(LEMON_HAVE_CLP)
67 68
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${COIN_CLP_LIBRARIES})
68 69
  ENDIF()
69 70

	
70 71
  TARGET_LINK_LIBRARIES(lp_test ${LP_TEST_LIBS})
71 72
  ADD_TEST(lp_test lp_test)
72 73
  ADD_DEPENDENCIES(check lp_test)
73 74

	
74 75
  IF(WIN32 AND LEMON_HAVE_GLPK)
75 76
    GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
76 77
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
77 78
    ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
78 79
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
79 80
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
80 81
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
81 82
    )
82 83
  ENDIF()
83 84

	
84 85
  IF(WIN32 AND LEMON_HAVE_CPLEX)
85 86
    GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
86 87
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
87 88
    ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
88 89
      COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex91.dll ${TARGET_PATH}
89 90
    )
90 91
  ENDIF()
91 92
ENDIF()
92 93

	
93 94
IF(LEMON_HAVE_MIP)
94 95
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
95 96
    ADD_EXECUTABLE(mip_test mip_test.cc)
96 97
  ELSE()
97 98
    ADD_EXECUTABLE(mip_test EXCLUDE_FROM_ALL mip_test.cc)
98 99
  ENDIF()
99 100

	
100 101
  SET(MIP_TEST_LIBS lemon)
101 102

	
102 103
  IF(LEMON_HAVE_GLPK)
103 104
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${GLPK_LIBRARIES})
104 105
  ENDIF()
105 106
  IF(LEMON_HAVE_CPLEX)
106 107
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${CPLEX_LIBRARIES})
107 108
  ENDIF()
108 109
  IF(LEMON_HAVE_CBC)
109 110
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${COIN_CBC_LIBRARIES})
110 111
  ENDIF()
111 112

	
112 113
  TARGET_LINK_LIBRARIES(mip_test ${MIP_TEST_LIBS})
113 114
  ADD_TEST(mip_test mip_test)
114 115
  ADD_DEPENDENCIES(check mip_test)
115 116

	
116 117
  IF(WIN32 AND LEMON_HAVE_GLPK)
117 118
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
118 119
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
119 120
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
120 121
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
121 122
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
122 123
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
123 124
    )
124 125
  ENDIF()
125 126

	
126 127
  IF(WIN32 AND LEMON_HAVE_CPLEX)
127 128
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
128 129
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
129 130
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
130 131
      COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex91.dll ${TARGET_PATH}
131 132
    )
132 133
  ENDIF()
133 134
ENDIF()
134 135

	
135 136
FOREACH(TEST_NAME ${TESTS})
136 137
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
137 138
    ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.cc)
138 139
  ELSE()
139 140
    ADD_EXECUTABLE(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cc)
140 141
  ENDIF()
141 142
  TARGET_LINK_LIBRARIES(${TEST_NAME} lemon)
142 143
    IF(TEST_WITH_VALGRIND)
143 144
      ADD_TEST(${TEST_NAME}
144 145
        valgrind --error-exitcode=1 ${VALGRIND_FLAGS}
145 146
        ${CMAKE_CURRENT_BINARY_DIR}/${TEST_NAME} )
146 147
    ELSE()
147 148
      ADD_TEST(${TEST_NAME} ${TEST_NAME})
148 149
    ENDIF()
149 150
  ADD_DEPENDENCIES(check ${TEST_NAME})
150 151
ENDFOREACH()
Ignore white space 512 line context
1 1
if USE_VALGRIND
2 2
TESTS_ENVIRONMENT=$(top_srcdir)/scripts/valgrind-wrapper.sh
3 3
endif
4 4

	
5 5
EXTRA_DIST += \
6 6
	test/CMakeLists.txt
7 7

	
8 8
noinst_HEADERS += \
9 9
	test/graph_test.h \
10 10
	test/test_tools.h
11 11

	
12 12
check_PROGRAMS += \
13 13
	test/adaptors_test \
14 14
	test/bellman_ford_test \
15 15
	test/bfs_test \
16 16
	test/circulation_test \
17 17
	test/connectivity_test \
18 18
	test/counter_test \
19 19
	test/dfs_test \
20 20
	test/digraph_test \
21 21
	test/dijkstra_test \
22 22
	test/dim_test \
23 23
	test/edge_set_test \
24 24
	test/error_test \
25 25
	test/euler_test \
26 26
	test/fractional_matching_test \
27 27
	test/gomory_hu_test \
28 28
	test/graph_copy_test \
29 29
	test/graph_test \
30 30
	test/graph_utils_test \
31 31
	test/hao_orlin_test \
32 32
	test/heap_test \
33 33
	test/kruskal_test \
34
	test/lgf_test \
34 35
	test/maps_test \
35 36
	test/matching_test \
36 37
	test/min_cost_arborescence_test \
37 38
	test/min_cost_flow_test \
38 39
	test/min_mean_cycle_test \
39 40
	test/path_test \
40 41
	test/planarity_test \
41 42
	test/preflow_test \
42 43
	test/radix_sort_test \
43 44
	test/random_test \
44 45
	test/suurballe_test \
45 46
	test/test_tools_fail \
46 47
	test/test_tools_pass \
47 48
	test/time_measure_test \
48 49
	test/unionfind_test
49 50

	
50 51
test_test_tools_pass_DEPENDENCIES = demo
51 52

	
52 53
if HAVE_LP
53 54
check_PROGRAMS += test/lp_test
54 55
endif HAVE_LP
55 56
if HAVE_MIP
56 57
check_PROGRAMS += test/mip_test
57 58
endif HAVE_MIP
58 59

	
59 60
TESTS += $(check_PROGRAMS)
60 61
XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
61 62

	
62 63
test_adaptors_test_SOURCES = test/adaptors_test.cc
63 64
test_bellman_ford_test_SOURCES = test/bellman_ford_test.cc
64 65
test_bfs_test_SOURCES = test/bfs_test.cc
65 66
test_circulation_test_SOURCES = test/circulation_test.cc
66 67
test_counter_test_SOURCES = test/counter_test.cc
67 68
test_connectivity_test_SOURCES = test/connectivity_test.cc
68 69
test_dfs_test_SOURCES = test/dfs_test.cc
69 70
test_digraph_test_SOURCES = test/digraph_test.cc
70 71
test_dijkstra_test_SOURCES = test/dijkstra_test.cc
71 72
test_dim_test_SOURCES = test/dim_test.cc
72 73
test_edge_set_test_SOURCES = test/edge_set_test.cc
73 74
test_error_test_SOURCES = test/error_test.cc
74 75
test_euler_test_SOURCES = test/euler_test.cc
75 76
test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc
76 77
test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc
77 78
test_graph_copy_test_SOURCES = test/graph_copy_test.cc
78 79
test_graph_test_SOURCES = test/graph_test.cc
79 80
test_graph_utils_test_SOURCES = test/graph_utils_test.cc
81
test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
80 82
test_heap_test_SOURCES = test/heap_test.cc
81 83
test_kruskal_test_SOURCES = test/kruskal_test.cc
82
test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
84
test_lgf_test_SOURCES = test/lgf_test.cc
83 85
test_lp_test_SOURCES = test/lp_test.cc
84 86
test_maps_test_SOURCES = test/maps_test.cc
85 87
test_mip_test_SOURCES = test/mip_test.cc
86 88
test_matching_test_SOURCES = test/matching_test.cc
87 89
test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
88 90
test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
89 91
test_min_mean_cycle_test_SOURCES = test/min_mean_cycle_test.cc
90 92
test_path_test_SOURCES = test/path_test.cc
91 93
test_planarity_test_SOURCES = test/planarity_test.cc
92 94
test_preflow_test_SOURCES = test/preflow_test.cc
93 95
test_radix_sort_test_SOURCES = test/radix_sort_test.cc
94 96
test_suurballe_test_SOURCES = test/suurballe_test.cc
95 97
test_random_test_SOURCES = test/random_test.cc
96 98
test_test_tools_fail_SOURCES = test/test_tools_fail.cc
97 99
test_test_tools_pass_SOURCES = test/test_tools_pass.cc
98 100
test_time_measure_test_SOURCES = test/time_measure_test.cc
99 101
test_unionfind_test_SOURCES = test/unionfind_test.cc
0 comments (0 inline)