diff --git a/doc/lgf.dox b/doc/lgf.dox --- a/doc/lgf.dox +++ b/doc/lgf.dox @@ -63,11 +63,11 @@ 3 (40,10) 10 "Third node" \endcode -The \c \@arcs section is very similar to the \c \@nodes section, -it again starts with a header line describing the names of the maps, -but the \c "label" map is not obligatory here. The following lines -describe the arcs. The first two tokens of each line are -the source and the target node of the arc, respectively, then come the map +The \c \@arcs section is very similar to the \c \@nodes section, it +again starts with a header line describing the names of the maps, but +the \c "label" map is not obligatory here. The following lines +describe the arcs. The first two tokens of each line are the source +and the target node of the arc, respectively, then come the map values. The source and target tokens must be node labels. \code @@ -78,10 +78,21 @@ 2 3 18 \endcode +If there is no map in the \c \@arcs section at all, then it must be +indicated by a sole '-' sign in the first line. + +\code + @arcs + - + 1 2 + 1 3 + 2 3 +\endcode + The \c \@edges is just a synonym of \c \@arcs. The \@arcs section can also store the edge set of an undirected graph. In such case there is a conventional method for store arc maps in the file, if two columns -has the same caption with \c '+' and \c '-' prefix, then these columns +have the same caption with \c '+' and \c '-' prefix, then these columns can be regarded as the values of an arc map. The \c \@attributes section contains key-value pairs, each line diff --git a/lemon/lgf_reader.h b/lemon/lgf_reader.h --- a/lemon/lgf_reader.h +++ b/lemon/lgf_reader.h @@ -2,7 +2,7 @@ * * This file is a part of LEMON, a generic C++ optimization library. * - * Copyright (C) 2003-2010 + * Copyright (C) 2003-2011 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * @@ -964,6 +964,13 @@ std::string map; int index = 0; while (_reader_bits::readToken(line, map)) { + if(map == "-") { + if(index!=0) + throw FormatError("'-' is not allowed as a map name"); + else if (line >> std::ws >> c) + throw FormatError("Extra character at the end of line"); + else break; + } if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of arc map: " << map; @@ -1834,6 +1841,13 @@ std::string map; int index = 0; while (_reader_bits::readToken(line, map)) { + if(map == "-") { + if(index!=0) + throw FormatError("'-' is not allowed as a map name"); + else if (line >> std::ws >> c) + throw FormatError("Extra character at the end of line"); + else break; + } if (maps.find(map) != maps.end()) { std::ostringstream msg; msg << "Multiple occurence of edge map: " << map; diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -33,6 +33,7 @@ hao_orlin_test heap_test kruskal_test + lgf_test maps_test matching_test max_cardinality_search_test diff --git a/test/Makefile.am b/test/Makefile.am --- a/test/Makefile.am +++ b/test/Makefile.am @@ -31,6 +31,7 @@ test/hao_orlin_test \ test/heap_test \ test/kruskal_test \ + test/lgf_test \ test/maps_test \ test/matching_test \ test/max_cardinality_search_test \ @@ -80,9 +81,10 @@ test_graph_copy_test_SOURCES = test/graph_copy_test.cc test_graph_test_SOURCES = test/graph_test.cc test_graph_utils_test_SOURCES = test/graph_utils_test.cc +test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc test_heap_test_SOURCES = test/heap_test.cc test_kruskal_test_SOURCES = test/kruskal_test.cc -test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc +test_lgf_test_SOURCES = test/lgf_test.cc test_lp_test_SOURCES = test/lp_test.cc test_maps_test_SOURCES = test/maps_test.cc test_mip_test_SOURCES = test/mip_test.cc diff --git a/test/lgf_test.cc b/test/lgf_test.cc new file mode 100644 --- /dev/null +++ b/test/lgf_test.cc @@ -0,0 +1,169 @@ +/* -*- mode: C++; indent-tabs-mode: nil; -*- + * + * This file is a part of LEMON, a generic C++ optimization library. + * + * Copyright (C) 2003-2011 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport + * (Egervary Research Group on Combinatorial Optimization, EGRES). + * + * Permission to use, modify and distribute this software is granted + * provided that this copyright notice appears in all copies. For + * precise terms see the accompanying LICENSE file. + * + * This software is provided "AS IS" with no warranty of any kind, + * express or implied, and with no claim as to its suitability for any + * purpose. + * + */ + +#include +#include +#include "test_tools.h" + +using namespace lemon; + +char test_lgf[] = + "@nodes\n" + "label\n" + "0\n" + "1\n" + "@arcs\n" + " label\n" + "0 1 0\n" + "1 0 1\n" + "@attributes\n" + "source 0\n" + "target 1\n"; + +char test_lgf_nomap[] = + "@nodes\n" + "label\n" + "0\n" + "1\n" + "@arcs\n" + " -\n" + "0 1\n"; + +char test_lgf_bad1[] = + "@nodes\n" + "label\n" + "0\n" + "1\n" + "@arcs\n" + " - another\n" + "0 1\n"; + +char test_lgf_bad2[] = + "@nodes\n" + "label\n" + "0\n" + "1\n" + "@arcs\n" + " label -\n" + "0 1\n"; + + +int main() +{ + { + ListDigraph d; + ListDigraph::Node s,t; + ListDigraph::ArcMap label(d); + std::istringstream input(test_lgf); + digraphReader(d, input). + node("source", s). + node("target", t). + arcMap("label", label). + run(); + check(countNodes(d) == 2,"There should be 2 nodes"); + check(countArcs(d) == 2,"There should be 2 arcs"); + } + { + ListGraph g; + ListGraph::Node s,t; + ListGraph::EdgeMap label(g); + std::istringstream input(test_lgf); + graphReader(g, input). + node("source", s). + node("target", t). + edgeMap("label", label). + run(); + check(countNodes(g) == 2,"There should be 2 nodes"); + check(countEdges(g) == 2,"There should be 2 arcs"); + } + + { + ListDigraph d; + std::istringstream input(test_lgf_nomap); + digraphReader(d, input). + run(); + check(countNodes(d) == 2,"There should be 2 nodes"); + check(countArcs(d) == 1,"There should be 1 arc"); + } + { + ListGraph g; + std::istringstream input(test_lgf_nomap); + graphReader(g, input). + run(); + check(countNodes(g) == 2,"There should be 2 nodes"); + check(countEdges(g) == 1,"There should be 1 edge"); + } + + { + ListDigraph d; + std::istringstream input(test_lgf_bad1); + bool ok=false; + try { + digraphReader(d, input). + run(); + } + catch (FormatError& error) + { + ok = true; + } + check(ok,"FormatError exception should have occured"); + } + { + ListGraph g; + std::istringstream input(test_lgf_bad1); + bool ok=false; + try { + graphReader(g, input). + run(); + } + catch (FormatError& error) + { + ok = true; + } + check(ok,"FormatError exception should have occured"); + } + + { + ListDigraph d; + std::istringstream input(test_lgf_bad2); + bool ok=false; + try { + digraphReader(d, input). + run(); + } + catch (FormatError& error) + { + ok = true; + } + check(ok,"FormatError exception should have occured"); + } + { + ListGraph g; + std::istringstream input(test_lgf_bad2); + bool ok=false; + try { + graphReader(g, input). + run(); + } + catch (FormatError& error) + { + ok = true; + } + check(ok,"FormatError exception should have occured"); + } +}