0
80
0
3
3
52
52
4
4
137
137
86
86
44
44
229
229
44
44
109
109
16
16
147
147
36
37
111
111
19
19
251
251
180
180
78
78
48
48
269
269
566
566
38
38
949
949
463
463
292
292
15
15
4
4
43
43
113
113
100
100
58
58
254
254
18
18
17
17
10
10
50
50
24
24
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 demos |
| ... | ... |
@@ -51,53 +51,53 @@ |
| 51 | 51 |
ap.refOption("f", "A switch.", b)
|
| 52 | 52 |
.refOption("nohelp", "", nh)
|
| 53 | 53 |
.refOption("gra", "Choice A", g1)
|
| 54 | 54 |
.refOption("grb", "Choice B", g2)
|
| 55 | 55 |
.refOption("grc", "Choice C", g3);
|
| 56 | 56 |
// Bundle -gr* options into a group |
| 57 | 57 |
ap.optionGroup("gr", "gra")
|
| 58 | 58 |
.optionGroup("gr", "grb")
|
| 59 | 59 |
.optionGroup("gr", "grc");
|
| 60 | 60 |
// Set the group mandatory |
| 61 | 61 |
ap.mandatoryGroup("gr");
|
| 62 | 62 |
// Set the options of the group exclusive (only one option can be given) |
| 63 | 63 |
ap.onlyOneGroup("gr");
|
| 64 | 64 |
// Add non-parsed arguments (e.g. input files) |
| 65 | 65 |
ap.other("infile", "The input file.")
|
| 66 | 66 |
.other("...");
|
| 67 |
|
|
| 67 |
|
|
| 68 | 68 |
// Perform the parsing process |
| 69 | 69 |
// (in case of any error it terminates the program) |
| 70 | 70 |
ap.parse(); |
| 71 | 71 |
|
| 72 | 72 |
// Check each option if it has been given and print its value |
| 73 | 73 |
std::cout << "Parameters of '" << ap.commandName() << "':\n"; |
| 74 | 74 |
|
| 75 | 75 |
std::cout << " Value of -n: " << i << std::endl; |
| 76 | 76 |
if(ap.given("val")) std::cout << " Value of -val: " << d << std::endl;
|
| 77 | 77 |
if(ap.given("val2")) {
|
| 78 | 78 |
d = ap["val2"]; |
| 79 | 79 |
std::cout << " Value of -val2: " << d << std::endl; |
| 80 | 80 |
} |
| 81 | 81 |
if(ap.given("name")) std::cout << " Value of -name: " << s << std::endl;
|
| 82 | 82 |
if(ap.given("f")) std::cout << " -f is given\n";
|
| 83 | 83 |
if(ap.given("nohelp")) std::cout << " Value of -nohelp: " << nh << std::endl;
|
| 84 | 84 |
if(ap.given("gra")) std::cout << " -gra is given\n";
|
| 85 | 85 |
if(ap.given("grb")) std::cout << " -grb is given\n";
|
| 86 | 86 |
if(ap.given("grc")) std::cout << " -grc is given\n";
|
| 87 |
|
|
| 87 |
|
|
| 88 | 88 |
switch(ap.files().size()) {
|
| 89 | 89 |
case 0: |
| 90 | 90 |
std::cout << " No file argument was given.\n"; |
| 91 | 91 |
break; |
| 92 | 92 |
case 1: |
| 93 | 93 |
std::cout << " 1 file argument was given. It is:\n"; |
| 94 | 94 |
break; |
| 95 | 95 |
default: |
| 96 | 96 |
std::cout << " " |
| 97 |
|
|
| 97 |
<< ap.files().size() << " file arguments were given. They are:\n"; |
|
| 98 | 98 |
} |
| 99 | 99 |
for(unsigned int i=0;i<ap.files().size();++i) |
| 100 | 100 |
std::cout << " '" << ap.files()[i] << "'\n"; |
| 101 |
|
|
| 101 |
|
|
| 102 | 102 |
return 0; |
| 103 | 103 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 demos |
| ... | ... |
@@ -36,62 +36,62 @@ |
| 36 | 36 |
#include<lemon/math.h> |
| 37 | 37 |
|
| 38 | 38 |
using namespace std; |
| 39 | 39 |
using namespace lemon; |
| 40 | 40 |
|
| 41 | 41 |
int main() |
| 42 | 42 |
{
|
| 43 | 43 |
Palette palette; |
| 44 | 44 |
Palette paletteW(true); |
| 45 | 45 |
|
| 46 | 46 |
// Create a small digraph |
| 47 | 47 |
ListDigraph g; |
| 48 | 48 |
typedef ListDigraph::Node Node; |
| 49 | 49 |
typedef ListDigraph::NodeIt NodeIt; |
| 50 | 50 |
typedef ListDigraph::Arc Arc; |
| 51 | 51 |
typedef dim2::Point<int> Point; |
| 52 |
|
|
| 52 |
|
|
| 53 | 53 |
Node n1=g.addNode(); |
| 54 | 54 |
Node n2=g.addNode(); |
| 55 | 55 |
Node n3=g.addNode(); |
| 56 | 56 |
Node n4=g.addNode(); |
| 57 | 57 |
Node n5=g.addNode(); |
| 58 | 58 |
|
| 59 | 59 |
ListDigraph::NodeMap<Point> coords(g); |
| 60 | 60 |
ListDigraph::NodeMap<double> sizes(g); |
| 61 | 61 |
ListDigraph::NodeMap<int> colors(g); |
| 62 | 62 |
ListDigraph::NodeMap<int> shapes(g); |
| 63 | 63 |
ListDigraph::ArcMap<int> acolors(g); |
| 64 | 64 |
ListDigraph::ArcMap<int> widths(g); |
| 65 |
|
|
| 65 |
|
|
| 66 | 66 |
coords[n1]=Point(50,50); sizes[n1]=1; colors[n1]=1; shapes[n1]=0; |
| 67 | 67 |
coords[n2]=Point(50,70); sizes[n2]=2; colors[n2]=2; shapes[n2]=2; |
| 68 | 68 |
coords[n3]=Point(70,70); sizes[n3]=1; colors[n3]=3; shapes[n3]=0; |
| 69 | 69 |
coords[n4]=Point(70,50); sizes[n4]=2; colors[n4]=4; shapes[n4]=1; |
| 70 | 70 |
coords[n5]=Point(85,60); sizes[n5]=3; colors[n5]=5; shapes[n5]=2; |
| 71 |
|
|
| 71 |
|
|
| 72 | 72 |
Arc a; |
| 73 | 73 |
|
| 74 | 74 |
a=g.addArc(n1,n2); acolors[a]=0; widths[a]=1; |
| 75 | 75 |
a=g.addArc(n2,n3); acolors[a]=0; widths[a]=1; |
| 76 | 76 |
a=g.addArc(n3,n5); acolors[a]=0; widths[a]=3; |
| 77 | 77 |
a=g.addArc(n5,n4); acolors[a]=0; widths[a]=1; |
| 78 | 78 |
a=g.addArc(n4,n1); acolors[a]=0; widths[a]=1; |
| 79 | 79 |
a=g.addArc(n2,n4); acolors[a]=1; widths[a]=2; |
| 80 | 80 |
a=g.addArc(n3,n4); acolors[a]=2; widths[a]=1; |
| 81 |
|
|
| 81 |
|
|
| 82 | 82 |
IdMap<ListDigraph,Node> id(g); |
| 83 | 83 |
|
| 84 | 84 |
// Create five .eps files showing the digraph with different options |
| 85 | 85 |
cout << "Create 'graph_to_eps_demo_out_1_pure.eps'" << endl; |
| 86 | 86 |
graphToEps(g,"graph_to_eps_demo_out_1_pure.eps"). |
| 87 | 87 |
coords(coords). |
| 88 | 88 |
title("Sample .eps figure").
|
| 89 | 89 |
copyright("(C) 2003-2008 LEMON Project").
|
| 90 | 90 |
run(); |
| 91 | 91 |
|
| 92 | 92 |
cout << "Create 'graph_to_eps_demo_out_2.eps'" << endl; |
| 93 | 93 |
graphToEps(g,"graph_to_eps_demo_out_2.eps"). |
| 94 | 94 |
coords(coords). |
| 95 | 95 |
title("Sample .eps figure").
|
| 96 | 96 |
copyright("(C) 2003-2008 LEMON Project").
|
| 97 | 97 |
absoluteNodeSizes().absoluteArcWidths(). |
| ... | ... |
@@ -169,39 +169,39 @@ |
| 169 | 169 |
absoluteNodeSizes().absoluteArcWidths(). |
| 170 | 170 |
nodeScale(2).nodeSizes(sizes). |
| 171 | 171 |
coords(coords). |
| 172 | 172 |
nodeShapes(shapes). |
| 173 | 173 |
nodeColors(composeMap(palette,colors)). |
| 174 | 174 |
arcColors(composeMap(palette,acolors)). |
| 175 | 175 |
arcWidthScale(.3).arcWidths(widths). |
| 176 | 176 |
nodeTexts(id).nodeTextSize(3). |
| 177 | 177 |
enableParallel().parArcDist(1). |
| 178 | 178 |
drawArrows().arrowWidth(1).arrowLength(1). |
| 179 | 179 |
run(); |
| 180 | 180 |
|
| 181 | 181 |
// Create an .eps file showing the colors of a default Palette |
| 182 | 182 |
ListDigraph h; |
| 183 | 183 |
ListDigraph::NodeMap<int> hcolors(h); |
| 184 | 184 |
ListDigraph::NodeMap<Point> hcoords(h); |
| 185 |
|
|
| 185 |
|
|
| 186 | 186 |
int cols=int(sqrt(double(palette.size()))); |
| 187 | 187 |
for(int i=0;i<int(paletteW.size());i++) {
|
| 188 | 188 |
Node n=h.addNode(); |
| 189 | 189 |
hcoords[n]=Point(1+i%cols,1+i/cols); |
| 190 | 190 |
hcolors[n]=i; |
| 191 | 191 |
} |
| 192 |
|
|
| 192 |
|
|
| 193 | 193 |
cout << "Create 'graph_to_eps_demo_out_6_colors.eps'" << endl; |
| 194 | 194 |
graphToEps(h,"graph_to_eps_demo_out_6_colors.eps"). |
| 195 | 195 |
scale(60). |
| 196 | 196 |
title("Sample .eps figure (Palette demo)").
|
| 197 | 197 |
copyright("(C) 2003-2008 LEMON Project").
|
| 198 | 198 |
coords(hcoords). |
| 199 | 199 |
absoluteNodeSizes().absoluteArcWidths(). |
| 200 | 200 |
nodeScale(.45). |
| 201 | 201 |
distantColorNodeTexts(). |
| 202 | 202 |
nodeTexts(hcolors).nodeTextSize(.6). |
| 203 | 203 |
nodeColors(composeMap(paletteW,hcolors)). |
| 204 | 204 |
run(); |
| 205 |
|
|
| 205 |
|
|
| 206 | 206 |
return 0; |
| 207 | 207 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 demos |
| 20 | 20 |
///\file |
| 21 | 21 |
///\brief Demonstrating graph input and output |
| 22 | 22 |
/// |
| 23 | 23 |
/// This program gives an example of how to read and write a digraph |
| 24 |
/// and additional maps from/to a stream or a file using the |
|
| 24 |
/// and additional maps from/to a stream or a file using the |
|
| 25 | 25 |
/// \ref lgf-format "LGF" format. |
| 26 | 26 |
/// |
| 27 | 27 |
/// The \c "digraph.lgf" file: |
| 28 | 28 |
/// \include digraph.lgf |
| 29 | 29 |
/// |
| 30 | 30 |
/// And the program which reads it and prints the digraph to the |
| 31 | 31 |
/// standard output: |
| 32 | 32 |
/// \include lgf_demo.cc |
| 33 | 33 |
|
| 34 | 34 |
#include <iostream> |
| 35 | 35 |
#include <lemon/smart_graph.h> |
| 36 | 36 |
#include <lemon/lgf_reader.h> |
| 37 | 37 |
#include <lemon/lgf_writer.h> |
| 38 | 38 |
|
| 39 | 39 |
using namespace lemon; |
| 40 | 40 |
|
| 41 | 41 |
int main() {
|
| 42 | 42 |
SmartDigraph g; |
| 43 | 43 |
SmartDigraph::ArcMap<int> cap(g); |
| 44 | 44 |
SmartDigraph::Node s, t; |
| 45 |
|
|
| 45 |
|
|
| 46 | 46 |
try {
|
| 47 | 47 |
digraphReader("digraph.lgf", g). // read the directed graph into g
|
| 48 | 48 |
arcMap("capacity", cap). // read the 'capacity' arc map into cap
|
| 49 | 49 |
node("source", s). // read 'source' node to s
|
| 50 | 50 |
node("target", t). // read 'target' node to t
|
| 51 | 51 |
run(); |
| 52 | 52 |
} catch (DataFormatError& error) { // check if there was any error
|
| 53 | 53 |
std::cerr << "Error: " << error.what() << std::endl; |
| 54 | 54 |
return -1; |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
std::cout << "A digraph is read from 'digraph.lgf'." << std::endl; |
| 58 | 58 |
std::cout << "Number of nodes: " << countNodes(g) << std::endl; |
| 59 | 59 |
std::cout << "Number of arcs: " << countArcs(g) << std::endl; |
| 60 | 60 |
|
| 61 | 61 |
std::cout << "We can write it to the standard output:" << std::endl; |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/*! |
| 20 | 20 |
|
| 21 |
\page coding_style LEMON Coding Style |
|
| 21 |
\page coding_style LEMON Coding Style |
|
| 22 | 22 |
|
| 23 | 23 |
\section naming_conv Naming Conventions |
| 24 | 24 |
|
| 25 | 25 |
In order to make development easier we have made some conventions |
| 26 | 26 |
according to coding style. These include names of types, classes, |
| 27 | 27 |
functions, variables, constants and exceptions. If these conventions |
| 28 | 28 |
are met in one's code then it is easier to read and maintain |
| 29 | 29 |
it. Please comply with these conventions if you want to contribute |
| 30 | 30 |
developing LEMON library. |
| 31 | 31 |
|
| 32 | 32 |
\note When the coding style requires the capitalization of an abbreviation, |
| 33 | 33 |
only the first letter should be upper case. |
| 34 | 34 |
|
| 35 | 35 |
\code |
| 36 | 36 |
XmlReader |
| 37 | 37 |
\endcode |
| ... | ... |
@@ -55,57 +55,57 @@ |
| 55 | 55 |
|
| 56 | 56 |
\code |
| 57 | 57 |
#include <lemon/header_file.h> |
| 58 | 58 |
\endcode |
| 59 | 59 |
|
| 60 | 60 |
The source code files use the same style and they have '.cc' extension. |
| 61 | 61 |
|
| 62 | 62 |
\code |
| 63 | 63 |
source_code.cc |
| 64 | 64 |
\endcode |
| 65 | 65 |
|
| 66 | 66 |
\subsection cs-class Classes and other types |
| 67 | 67 |
|
| 68 | 68 |
The name of a class or any type should look like the following. |
| 69 | 69 |
|
| 70 | 70 |
\code |
| 71 |
AllWordsCapitalizedWithoutUnderscores |
|
| 71 |
AllWordsCapitalizedWithoutUnderscores |
|
| 72 | 72 |
\endcode |
| 73 | 73 |
|
| 74 | 74 |
\subsection cs-func Methods and other functions |
| 75 | 75 |
|
| 76 | 76 |
The name of a function should look like the following. |
| 77 | 77 |
|
| 78 | 78 |
\code |
| 79 |
firstWordLowerCaseRestCapitalizedWithoutUnderscores |
|
| 79 |
firstWordLowerCaseRestCapitalizedWithoutUnderscores |
|
| 80 | 80 |
\endcode |
| 81 | 81 |
|
| 82 | 82 |
\subsection cs-funcs Constants, Macros |
| 83 | 83 |
|
| 84 | 84 |
The names of constants and macros should look like the following. |
| 85 | 85 |
|
| 86 | 86 |
\code |
| 87 |
ALL_UPPER_CASE_WITH_UNDERSCORES |
|
| 87 |
ALL_UPPER_CASE_WITH_UNDERSCORES |
|
| 88 | 88 |
\endcode |
| 89 | 89 |
|
| 90 |
\subsection cs-loc-var Class and instance member variables, auto variables |
|
| 90 |
\subsection cs-loc-var Class and instance member variables, auto variables |
|
| 91 | 91 |
|
| 92 | 92 |
The names of class and instance member variables and auto variables (=variables used locally in methods) should look like the following. |
| 93 | 93 |
|
| 94 | 94 |
\code |
| 95 |
all_lower_case_with_underscores |
|
| 95 |
all_lower_case_with_underscores |
|
| 96 | 96 |
\endcode |
| 97 | 97 |
|
| 98 | 98 |
\subsection pri-loc-var Private member variables |
| 99 | 99 |
|
| 100 | 100 |
Private member variables should start with underscore |
| 101 | 101 |
|
| 102 | 102 |
\code |
| 103 | 103 |
_start_with_underscores |
| 104 | 104 |
\endcode |
| 105 | 105 |
|
| 106 | 106 |
\subsection cs-excep Exceptions |
| 107 | 107 |
|
| 108 | 108 |
When writing exceptions please comply the following naming conventions. |
| 109 | 109 |
|
| 110 | 110 |
\code |
| 111 | 111 |
ClassNameEndsWithException |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/** |
| ... | ... |
@@ -61,19 +61,19 @@ |
| 61 | 61 |
\endcode |
| 62 | 62 |
*/ |
| 63 | 63 |
|
| 64 | 64 |
/** |
| 65 | 65 |
\dir concepts |
| 66 | 66 |
\brief Concept descriptors and checking classes |
| 67 | 67 |
|
| 68 | 68 |
This directory contains the concept descriptors and concept checkers. As a user |
| 69 | 69 |
you typically don't have to deal with these files. |
| 70 | 70 |
*/ |
| 71 | 71 |
|
| 72 | 72 |
/** |
| 73 | 73 |
\dir bits |
| 74 | 74 |
\brief Implementation helper files |
| 75 | 75 |
|
| 76 | 76 |
This directory contains some helper classes to implement graphs, maps and |
| 77 |
some other classes. As a user you typically don't have to deal with these |
|
| 77 |
some other classes. As a user you typically don't have to deal with these |
|
| 78 | 78 |
files. |
| 79 | 79 |
*/ |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/** |
| 20 | 20 |
@defgroup datas Data Structures |
| 21 | 21 |
This group describes the several data structures implemented in LEMON. |
| 22 | 22 |
*/ |
| 23 | 23 |
|
| 24 | 24 |
/** |
| 25 | 25 |
@defgroup graphs Graph Structures |
| 26 | 26 |
@ingroup datas |
| 27 | 27 |
\brief Graph structures implemented in LEMON. |
| 28 | 28 |
|
| 29 |
The implementation of combinatorial algorithms heavily relies on |
|
| 30 |
efficient graph implementations. LEMON offers data structures which are |
|
| 31 |
planned to be easily used in an experimental phase of implementation studies, |
|
| 32 |
and thereafter the program code can be made efficient by small modifications. |
|
| 29 |
The implementation of combinatorial algorithms heavily relies on |
|
| 30 |
efficient graph implementations. LEMON offers data structures which are |
|
| 31 |
planned to be easily used in an experimental phase of implementation studies, |
|
| 32 |
and thereafter the program code can be made efficient by small modifications. |
|
| 33 | 33 |
|
| 34 | 34 |
The most efficient implementation of diverse applications require the |
| 35 | 35 |
usage of different physical graph implementations. These differences |
| 36 | 36 |
appear in the size of graph we require to handle, memory or time usage |
| 37 | 37 |
limitations or in the set of operations through which the graph can be |
| 38 | 38 |
accessed. LEMON provides several physical graph structures to meet |
| 39 | 39 |
the diverging requirements of the possible users. In order to save on |
| 40 | 40 |
running time or on memory usage, some structures may fail to provide |
| 41 | 41 |
some graph features like arc/edge or node deletion. |
| 42 | 42 |
|
| 43 |
Alteration of standard containers need a very limited number of |
|
| 44 |
operations, these together satisfy the everyday requirements. |
|
| 45 |
In the case of graph structures, different operations are needed which do |
|
| 46 |
not alter the physical graph, but gives another view. If some nodes or |
|
| 43 |
Alteration of standard containers need a very limited number of |
|
| 44 |
operations, these together satisfy the everyday requirements. |
|
| 45 |
In the case of graph structures, different operations are needed which do |
|
| 46 |
not alter the physical graph, but gives another view. If some nodes or |
|
| 47 | 47 |
arcs have to be hidden or the reverse oriented graph have to be used, then |
| 48 |
this is the case. It also may happen that in a flow implementation |
|
| 49 |
the residual graph can be accessed by another algorithm, or a node-set |
|
| 50 |
is to be shrunk for another algorithm. |
|
| 51 |
LEMON also provides a variety of graphs for these requirements called |
|
| 52 |
\ref graph_adaptors "graph adaptors". Adaptors cannot be used alone but only |
|
| 53 |
in conjunction with other graph representations. |
|
| 48 |
this is the case. It also may happen that in a flow implementation |
|
| 49 |
the residual graph can be accessed by another algorithm, or a node-set |
|
| 50 |
is to be shrunk for another algorithm. |
|
| 51 |
LEMON also provides a variety of graphs for these requirements called |
|
| 52 |
\ref graph_adaptors "graph adaptors". Adaptors cannot be used alone but only |
|
| 53 |
in conjunction with other graph representations. |
|
| 54 | 54 |
|
| 55 | 55 |
You are free to use the graph structure that fit your requirements |
| 56 | 56 |
the best, most graph algorithms and auxiliary data structures can be used |
| 57 |
with any graph structures. |
|
| 57 |
with any graph structures. |
|
| 58 | 58 |
*/ |
| 59 | 59 |
|
| 60 | 60 |
/** |
| 61 | 61 |
@defgroup semi_adaptors Semi-Adaptor Classes for Graphs |
| 62 | 62 |
@ingroup graphs |
| 63 | 63 |
\brief Graph types between real graphs and graph adaptors. |
| 64 | 64 |
|
| 65 | 65 |
This group describes some graph types between real graphs and graph adaptors. |
| 66 |
These classes wrap graphs to give new functionality as the adaptors do it. |
|
| 66 |
These classes wrap graphs to give new functionality as the adaptors do it. |
|
| 67 | 67 |
On the other hand they are not light-weight structures as the adaptors. |
| 68 | 68 |
*/ |
| 69 | 69 |
|
| 70 | 70 |
/** |
| 71 |
@defgroup maps Maps |
|
| 71 |
@defgroup maps Maps |
|
| 72 | 72 |
@ingroup datas |
| 73 | 73 |
\brief Map structures implemented in LEMON. |
| 74 | 74 |
|
| 75 | 75 |
This group describes the map structures implemented in LEMON. |
| 76 | 76 |
|
| 77 | 77 |
LEMON provides several special purpose maps that e.g. combine |
| 78 | 78 |
new maps from existing ones. |
| 79 | 79 |
*/ |
| 80 | 80 |
|
| 81 | 81 |
/** |
| 82 |
@defgroup graph_maps Graph Maps |
|
| 82 |
@defgroup graph_maps Graph Maps |
|
| 83 | 83 |
@ingroup maps |
| 84 | 84 |
\brief Special graph-related maps. |
| 85 | 85 |
|
| 86 | 86 |
This group describes maps that are specifically designed to assign |
| 87 | 87 |
values to the nodes and arcs of graphs. |
| 88 | 88 |
*/ |
| 89 | 89 |
|
| 90 | 90 |
|
| 91 | 91 |
/** |
| 92 | 92 |
\defgroup map_adaptors Map Adaptors |
| 93 | 93 |
\ingroup maps |
| 94 | 94 |
\brief Tools to create new maps from existing ones |
| 95 | 95 |
|
| 96 | 96 |
This group describes map adaptors that are used to create "implicit" |
| 97 | 97 |
maps from other maps. |
| 98 | 98 |
|
| ... | ... |
@@ -102,70 +102,70 @@ |
| 102 | 102 |
'not' etc.) or e.g. convert a map to another one of different Value type. |
| 103 | 103 |
|
| 104 | 104 |
The typical usage of this classes is passing implicit maps to |
| 105 | 105 |
algorithms. If a function type algorithm is called then the function |
| 106 | 106 |
type map adaptors can be used comfortable. For example let's see the |
| 107 | 107 |
usage of map adaptors with the \c digraphToEps() function. |
| 108 | 108 |
\code |
| 109 | 109 |
Color nodeColor(int deg) {
|
| 110 | 110 |
if (deg >= 2) {
|
| 111 | 111 |
return Color(0.5, 0.0, 0.5); |
| 112 | 112 |
} else if (deg == 1) {
|
| 113 | 113 |
return Color(1.0, 0.5, 1.0); |
| 114 | 114 |
} else {
|
| 115 | 115 |
return Color(0.0, 0.0, 0.0); |
| 116 | 116 |
} |
| 117 | 117 |
} |
| 118 |
|
|
| 118 |
|
|
| 119 | 119 |
Digraph::NodeMap<int> degree_map(graph); |
| 120 |
|
|
| 120 |
|
|
| 121 | 121 |
digraphToEps(graph, "graph.eps") |
| 122 | 122 |
.coords(coords).scaleToA4().undirected() |
| 123 | 123 |
.nodeColors(composeMap(functorToMap(nodeColor), degree_map)) |
| 124 | 124 |
.run(); |
| 125 |
\endcode |
|
| 125 |
\endcode |
|
| 126 | 126 |
The \c functorToMap() function makes an \c int to \c Color map from the |
| 127 | 127 |
\e nodeColor() function. The \c composeMap() compose the \e degree_map |
| 128 | 128 |
and the previously created map. The composed map is a proper function to |
| 129 | 129 |
get the color of each node. |
| 130 | 130 |
|
| 131 | 131 |
The usage with class type algorithms is little bit harder. In this |
| 132 | 132 |
case the function type map adaptors can not be used, because the |
| 133 | 133 |
function map adaptors give back temporary objects. |
| 134 | 134 |
\code |
| 135 | 135 |
Digraph graph; |
| 136 | 136 |
|
| 137 | 137 |
typedef Digraph::ArcMap<double> DoubleArcMap; |
| 138 | 138 |
DoubleArcMap length(graph); |
| 139 | 139 |
DoubleArcMap speed(graph); |
| 140 | 140 |
|
| 141 | 141 |
typedef DivMap<DoubleArcMap, DoubleArcMap> TimeMap; |
| 142 | 142 |
TimeMap time(length, speed); |
| 143 |
|
|
| 143 |
|
|
| 144 | 144 |
Dijkstra<Digraph, TimeMap> dijkstra(graph, time); |
| 145 | 145 |
dijkstra.run(source, target); |
| 146 | 146 |
\endcode |
| 147 | 147 |
We have a length map and a maximum speed map on the arcs of a digraph. |
| 148 | 148 |
The minimum time to pass the arc can be calculated as the division of |
| 149 | 149 |
the two maps which can be done implicitly with the \c DivMap template |
| 150 | 150 |
class. We use the implicit minimum time map as the length map of the |
| 151 | 151 |
\c Dijkstra algorithm. |
| 152 | 152 |
*/ |
| 153 | 153 |
|
| 154 | 154 |
/** |
| 155 |
@defgroup matrices Matrices |
|
| 155 |
@defgroup matrices Matrices |
|
| 156 | 156 |
@ingroup datas |
| 157 | 157 |
\brief Two dimensional data storages implemented in LEMON. |
| 158 | 158 |
|
| 159 | 159 |
This group describes two dimensional data storages implemented in LEMON. |
| 160 | 160 |
*/ |
| 161 | 161 |
|
| 162 | 162 |
/** |
| 163 | 163 |
@defgroup paths Path Structures |
| 164 | 164 |
@ingroup datas |
| 165 | 165 |
\brief Path structures implemented in LEMON. |
| 166 | 166 |
|
| 167 | 167 |
This group describes the path structures implemented in LEMON. |
| 168 | 168 |
|
| 169 | 169 |
LEMON provides flexible data structures to work with paths. |
| 170 | 170 |
All of them have similar interfaces and they can be copied easily with |
| 171 | 171 |
assignment operators and copy constructors. This makes it easy and |
| ... | ... |
@@ -187,105 +187,105 @@ |
| 187 | 187 |
|
| 188 | 188 |
|
| 189 | 189 |
/** |
| 190 | 190 |
@defgroup algs Algorithms |
| 191 | 191 |
\brief This group describes the several algorithms |
| 192 | 192 |
implemented in LEMON. |
| 193 | 193 |
|
| 194 | 194 |
This group describes the several algorithms |
| 195 | 195 |
implemented in LEMON. |
| 196 | 196 |
*/ |
| 197 | 197 |
|
| 198 | 198 |
/** |
| 199 | 199 |
@defgroup search Graph Search |
| 200 | 200 |
@ingroup algs |
| 201 | 201 |
\brief Common graph search algorithms. |
| 202 | 202 |
|
| 203 |
This group describes the common graph search algorithms like |
|
| 203 |
This group describes the common graph search algorithms like |
|
| 204 | 204 |
Breadth-first search (Bfs) and Depth-first search (Dfs). |
| 205 | 205 |
*/ |
| 206 | 206 |
|
| 207 | 207 |
/** |
| 208 | 208 |
@defgroup shortest_path Shortest Path algorithms |
| 209 | 209 |
@ingroup algs |
| 210 | 210 |
\brief Algorithms for finding shortest paths. |
| 211 | 211 |
|
| 212 | 212 |
This group describes the algorithms for finding shortest paths in graphs. |
| 213 | 213 |
*/ |
| 214 | 214 |
|
| 215 |
/** |
|
| 216 |
@defgroup max_flow Maximum Flow algorithms |
|
| 217 |
|
|
| 215 |
/** |
|
| 216 |
@defgroup max_flow Maximum Flow algorithms |
|
| 217 |
@ingroup algs |
|
| 218 | 218 |
\brief Algorithms for finding maximum flows. |
| 219 | 219 |
|
| 220 | 220 |
This group describes the algorithms for finding maximum flows and |
| 221 | 221 |
feasible circulations. |
| 222 | 222 |
|
| 223 | 223 |
The maximum flow problem is to find a flow between a single source and |
| 224 | 224 |
a single target that is maximum. Formally, there is a \f$G=(V,A)\f$ |
| 225 | 225 |
directed graph, an \f$c_a:A\rightarrow\mathbf{R}^+_0\f$ capacity
|
| 226 | 226 |
function and given \f$s, t \in V\f$ source and target node. The |
| 227 | 227 |
maximum flow is the \f$f_a\f$ solution of the next optimization problem: |
| 228 | 228 |
|
| 229 | 229 |
\f[ 0 \le f_a \le c_a \f] |
| 230 | 230 |
\f[ \sum_{v\in\delta^{-}(u)}f_{vu}=\sum_{v\in\delta^{+}(u)}f_{uv} \qquad \forall u \in V \setminus \{s,t\}\f]
|
| 231 | 231 |
\f[ \max \sum_{v\in\delta^{+}(s)}f_{uv} - \sum_{v\in\delta^{-}(s)}f_{vu}\f]
|
| 232 | 232 |
|
| 233 | 233 |
LEMON contains several algorithms for solving maximum flow problems: |
| 234 |
- \ref lemon::EdmondsKarp "Edmonds-Karp" |
|
| 234 |
- \ref lemon::EdmondsKarp "Edmonds-Karp" |
|
| 235 | 235 |
- \ref lemon::Preflow "Goldberg's Preflow algorithm" |
| 236 | 236 |
- \ref lemon::DinitzSleatorTarjan "Dinitz's blocking flow algorithm with dynamic trees" |
| 237 | 237 |
- \ref lemon::GoldbergTarjan "Preflow algorithm with dynamic trees" |
| 238 | 238 |
|
| 239 | 239 |
In most cases the \ref lemon::Preflow "Preflow" algorithm provides the |
| 240 | 240 |
fastest method to compute the maximum flow. All impelementations |
| 241 | 241 |
provides functions to query the minimum cut, which is the dual linear |
| 242 | 242 |
programming problem of the maximum flow. |
| 243 | 243 |
|
| 244 | 244 |
*/ |
| 245 | 245 |
|
| 246 | 246 |
/** |
| 247 | 247 |
@defgroup min_cost_flow Minimum Cost Flow algorithms |
| 248 | 248 |
@ingroup algs |
| 249 | 249 |
|
| 250 | 250 |
\brief Algorithms for finding minimum cost flows and circulations. |
| 251 | 251 |
|
| 252 | 252 |
This group describes the algorithms for finding minimum cost flows and |
| 253 |
circulations. |
|
| 253 |
circulations. |
|
| 254 | 254 |
*/ |
| 255 | 255 |
|
| 256 | 256 |
/** |
| 257 |
@defgroup min_cut Minimum Cut algorithms |
|
| 258 |
@ingroup algs |
|
| 257 |
@defgroup min_cut Minimum Cut algorithms |
|
| 258 |
@ingroup algs |
|
| 259 | 259 |
|
| 260 | 260 |
\brief Algorithms for finding minimum cut in graphs. |
| 261 | 261 |
|
| 262 | 262 |
This group describes the algorithms for finding minimum cut in graphs. |
| 263 | 263 |
|
| 264 | 264 |
The minimum cut problem is to find a non-empty and non-complete |
| 265 | 265 |
\f$X\f$ subset of the vertices with minimum overall capacity on |
| 266 | 266 |
outgoing arcs. Formally, there is \f$G=(V,A)\f$ directed graph, an |
| 267 | 267 |
\f$c_a:A\rightarrow\mathbf{R}^+_0\f$ capacity function. The minimum
|
| 268 | 268 |
cut is the \f$X\f$ solution of the next optimization problem: |
| 269 | 269 |
|
| 270 | 270 |
\f[ \min_{X \subset V, X\not\in \{\emptyset, V\}}\sum_{uv\in A, u\in X, v\not\in X}c_{uv}\f]
|
| 271 | 271 |
|
| 272 | 272 |
LEMON contains several algorithms related to minimum cut problems: |
| 273 | 273 |
|
| 274 | 274 |
- \ref lemon::HaoOrlin "Hao-Orlin algorithm" to calculate minimum cut |
| 275 |
in directed graphs |
|
| 275 |
in directed graphs |
|
| 276 | 276 |
- \ref lemon::NagamochiIbaraki "Nagamochi-Ibaraki algorithm" to |
| 277 | 277 |
calculate minimum cut in undirected graphs |
| 278 | 278 |
- \ref lemon::GomoryHuTree "Gomory-Hu tree computation" to calculate all |
| 279 | 279 |
pairs minimum cut in undirected graphs |
| 280 | 280 |
|
| 281 | 281 |
If you want to find minimum cut just between two distinict nodes, |
| 282 | 282 |
please see the \ref max_flow "Maximum Flow page". |
| 283 | 283 |
|
| 284 | 284 |
*/ |
| 285 | 285 |
|
| 286 | 286 |
/** |
| 287 | 287 |
@defgroup graph_prop Connectivity and other graph properties |
| 288 | 288 |
@ingroup algs |
| 289 | 289 |
\brief Algorithms for discovering the graph properties |
| 290 | 290 |
|
| 291 | 291 |
This group describes the algorithms for discovering the graph properties |
| ... | ... |
@@ -294,58 +294,58 @@ |
| 294 | 294 |
\image html edge_biconnected_components.png |
| 295 | 295 |
\image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth |
| 296 | 296 |
*/ |
| 297 | 297 |
|
| 298 | 298 |
/** |
| 299 | 299 |
@defgroup planar Planarity embedding and drawing |
| 300 | 300 |
@ingroup algs |
| 301 | 301 |
\brief Algorithms for planarity checking, embedding and drawing |
| 302 | 302 |
|
| 303 | 303 |
This group describes the algorithms for planarity checking, embedding and drawing. |
| 304 | 304 |
|
| 305 | 305 |
\image html planar.png |
| 306 | 306 |
\image latex planar.eps "Plane graph" width=\textwidth |
| 307 | 307 |
*/ |
| 308 | 308 |
|
| 309 | 309 |
/** |
| 310 |
@defgroup matching Matching algorithms |
|
| 310 |
@defgroup matching Matching algorithms |
|
| 311 | 311 |
@ingroup algs |
| 312 | 312 |
\brief Algorithms for finding matchings in graphs and bipartite graphs. |
| 313 | 313 |
|
| 314 | 314 |
This group contains algorithm objects and functions to calculate |
| 315 | 315 |
matchings in graphs and bipartite graphs. The general matching problem is |
| 316 | 316 |
finding a subset of the arcs which does not shares common endpoints. |
| 317 |
|
|
| 317 |
|
|
| 318 | 318 |
There are several different algorithms for calculate matchings in |
| 319 | 319 |
graphs. The matching problems in bipartite graphs are generally |
| 320 | 320 |
easier than in general graphs. The goal of the matching optimization |
| 321 | 321 |
can be the finding maximum cardinality, maximum weight or minimum cost |
| 322 | 322 |
matching. The search can be constrained to find perfect or |
| 323 | 323 |
maximum cardinality matching. |
| 324 | 324 |
|
| 325 | 325 |
Lemon contains the next algorithms: |
| 326 |
- \ref lemon::MaxBipartiteMatching "MaxBipartiteMatching" Hopcroft-Karp |
|
| 327 |
augmenting path algorithm for calculate maximum cardinality matching in |
|
| 326 |
- \ref lemon::MaxBipartiteMatching "MaxBipartiteMatching" Hopcroft-Karp |
|
| 327 |
augmenting path algorithm for calculate maximum cardinality matching in |
|
| 328 | 328 |
bipartite graphs |
| 329 |
- \ref lemon::PrBipartiteMatching "PrBipartiteMatching" Push-Relabel |
|
| 330 |
algorithm for calculate maximum cardinality matching in bipartite graphs |
|
| 331 |
- \ref lemon::MaxWeightedBipartiteMatching "MaxWeightedBipartiteMatching" |
|
| 332 |
Successive shortest path algorithm for calculate maximum weighted matching |
|
| 329 |
- \ref lemon::PrBipartiteMatching "PrBipartiteMatching" Push-Relabel |
|
| 330 |
algorithm for calculate maximum cardinality matching in bipartite graphs |
|
| 331 |
- \ref lemon::MaxWeightedBipartiteMatching "MaxWeightedBipartiteMatching" |
|
| 332 |
Successive shortest path algorithm for calculate maximum weighted matching |
|
| 333 | 333 |
and maximum weighted bipartite matching in bipartite graph |
| 334 |
- \ref lemon::MinCostMaxBipartiteMatching "MinCostMaxBipartiteMatching" |
|
| 335 |
Successive shortest path algorithm for calculate minimum cost maximum |
|
| 334 |
- \ref lemon::MinCostMaxBipartiteMatching "MinCostMaxBipartiteMatching" |
|
| 335 |
Successive shortest path algorithm for calculate minimum cost maximum |
|
| 336 | 336 |
matching in bipartite graph |
| 337 | 337 |
- \ref lemon::MaxMatching "MaxMatching" Edmond's blossom shrinking algorithm |
| 338 | 338 |
for calculate maximum cardinality matching in general graph |
| 339 | 339 |
- \ref lemon::MaxWeightedMatching "MaxWeightedMatching" Edmond's blossom |
| 340 | 340 |
shrinking algorithm for calculate maximum weighted matching in general |
| 341 | 341 |
graph |
| 342 | 342 |
- \ref lemon::MaxWeightedPerfectMatching "MaxWeightedPerfectMatching" |
| 343 | 343 |
Edmond's blossom shrinking algorithm for calculate maximum weighted |
| 344 | 344 |
perfect matching in general graph |
| 345 | 345 |
|
| 346 | 346 |
\image html bipartite_matching.png |
| 347 | 347 |
\image latex bipartite_matching.eps "Bipartite Matching" width=\textwidth |
| 348 | 348 |
|
| 349 | 349 |
*/ |
| 350 | 350 |
|
| 351 | 351 |
/** |
| ... | ... |
@@ -383,51 +383,51 @@ |
| 383 | 383 |
This group describes some general optimization frameworks |
| 384 | 384 |
implemented in LEMON. |
| 385 | 385 |
|
| 386 | 386 |
*/ |
| 387 | 387 |
|
| 388 | 388 |
/** |
| 389 | 389 |
@defgroup lp_group Lp and Mip solvers |
| 390 | 390 |
@ingroup gen_opt_group |
| 391 | 391 |
\brief Lp and Mip solver interfaces for LEMON. |
| 392 | 392 |
|
| 393 | 393 |
This group describes Lp and Mip solver interfaces for LEMON. The |
| 394 | 394 |
various LP solvers could be used in the same manner with this |
| 395 | 395 |
interface. |
| 396 | 396 |
|
| 397 | 397 |
*/ |
| 398 | 398 |
|
| 399 |
/** |
|
| 400 |
@defgroup lp_utils Tools for Lp and Mip solvers |
|
| 399 |
/** |
|
| 400 |
@defgroup lp_utils Tools for Lp and Mip solvers |
|
| 401 | 401 |
@ingroup lp_group |
| 402 | 402 |
\brief Helper tools to the Lp and Mip solvers. |
| 403 | 403 |
|
| 404 | 404 |
This group adds some helper tools to general optimization framework |
| 405 | 405 |
implemented in LEMON. |
| 406 | 406 |
*/ |
| 407 | 407 |
|
| 408 | 408 |
/** |
| 409 | 409 |
@defgroup metah Metaheuristics |
| 410 | 410 |
@ingroup gen_opt_group |
| 411 | 411 |
\brief Metaheuristics for LEMON library. |
| 412 | 412 |
|
| 413 | 413 |
This group describes some metaheuristic optimization tools. |
| 414 | 414 |
*/ |
| 415 | 415 |
|
| 416 | 416 |
/** |
| 417 |
@defgroup utils Tools and Utilities |
|
| 417 |
@defgroup utils Tools and Utilities |
|
| 418 | 418 |
\brief Tools and utilities for programming in LEMON |
| 419 | 419 |
|
| 420 | 420 |
Tools and utilities for programming in LEMON. |
| 421 | 421 |
*/ |
| 422 | 422 |
|
| 423 | 423 |
/** |
| 424 | 424 |
@defgroup gutils Basic Graph Utilities |
| 425 | 425 |
@ingroup utils |
| 426 | 426 |
\brief Simple basic graph utilities. |
| 427 | 427 |
|
| 428 | 428 |
This group describes some simple basic graph utilities. |
| 429 | 429 |
*/ |
| 430 | 430 |
|
| 431 | 431 |
/** |
| 432 | 432 |
@defgroup misc Miscellaneous Tools |
| 433 | 433 |
@ingroup utils |
| ... | ... |
@@ -454,64 +454,64 @@ |
| 454 | 454 |
This group describes the tools that makes it easier to create graphs and |
| 455 | 455 |
the maps that dynamically update with the graph changes. |
| 456 | 456 |
*/ |
| 457 | 457 |
|
| 458 | 458 |
/** |
| 459 | 459 |
@defgroup exceptions Exceptions |
| 460 | 460 |
@ingroup utils |
| 461 | 461 |
\brief Exceptions defined in LEMON. |
| 462 | 462 |
|
| 463 | 463 |
This group describes the exceptions defined in LEMON. |
| 464 | 464 |
*/ |
| 465 | 465 |
|
| 466 | 466 |
/** |
| 467 | 467 |
@defgroup io_group Input-Output |
| 468 | 468 |
\brief Graph Input-Output methods |
| 469 | 469 |
|
| 470 |
This group describes the tools for importing and exporting graphs |
|
| 470 |
This group describes the tools for importing and exporting graphs |
|
| 471 | 471 |
and graph related data. Now it supports the LEMON format, the |
| 472 | 472 |
\c DIMACS format and the encapsulated postscript (EPS) format. |
| 473 | 473 |
*/ |
| 474 | 474 |
|
| 475 | 475 |
/** |
| 476 | 476 |
@defgroup lemon_io Lemon Input-Output |
| 477 | 477 |
@ingroup io_group |
| 478 | 478 |
\brief Reading and writing \ref lgf-format "Lemon Graph Format". |
| 479 | 479 |
|
| 480 | 480 |
This group describes methods for reading and writing \ref lgf-format "Lemon Graph Format". |
| 481 | 481 |
*/ |
| 482 | 482 |
|
| 483 | 483 |
/** |
| 484 | 484 |
@defgroup eps_io Postscript exporting |
| 485 | 485 |
@ingroup io_group |
| 486 | 486 |
\brief General \c EPS drawer and graph exporter |
| 487 | 487 |
|
| 488 | 488 |
This group describes general \c EPS drawing methods and special |
| 489 |
graph exporting tools. |
|
| 489 |
graph exporting tools. |
|
| 490 | 490 |
*/ |
| 491 | 491 |
|
| 492 | 492 |
|
| 493 | 493 |
/** |
| 494 | 494 |
@defgroup concept Concepts |
| 495 | 495 |
\brief Skeleton classes and concept checking classes |
| 496 | 496 |
|
| 497 | 497 |
This group describes the data/algorithm skeletons and concept checking |
| 498 | 498 |
classes implemented in LEMON. |
| 499 | 499 |
|
| 500 | 500 |
The purpose of the classes in this group is fourfold. |
| 501 |
|
|
| 501 |
|
|
| 502 | 502 |
- These classes contain the documentations of the concepts. In order |
| 503 | 503 |
to avoid document multiplications, an implementation of a concept |
| 504 | 504 |
simply refers to the corresponding concept class. |
| 505 | 505 |
|
| 506 | 506 |
- These classes declare every functions, <tt>typedef</tt>s etc. an |
| 507 | 507 |
implementation of the concepts should provide, however completely |
| 508 | 508 |
without implementations and real data structures behind the |
| 509 | 509 |
interface. On the other hand they should provide nothing else. All |
| 510 | 510 |
the algorithms working on a data structure meeting a certain concept |
| 511 | 511 |
should compile with these classes. (Though it will not run properly, |
| 512 | 512 |
of course.) In this way it is easily to check if an algorithm |
| 513 | 513 |
doesn't use any extra feature of a certain implementation. |
| 514 | 514 |
|
| 515 | 515 |
- The concept descriptor classes also provide a <em>checker class</em> |
| 516 | 516 |
that makes it possible to check whether a certain implementation of a |
| 517 | 517 |
concept indeed provides all the required features. |
| ... | ... |
@@ -538,22 +538,22 @@ |
| 538 | 538 |
|
| 539 | 539 |
/** |
| 540 | 540 |
\anchor demoprograms |
| 541 | 541 |
|
| 542 | 542 |
@defgroup demos Demo programs |
| 543 | 543 |
|
| 544 | 544 |
Some demo programs are listed here. Their full source codes can be found in |
| 545 | 545 |
the \c demo subdirectory of the source tree. |
| 546 | 546 |
|
| 547 | 547 |
It order to compile them, use <tt>--enable-demo</tt> configure option when |
| 548 | 548 |
build the library. |
| 549 | 549 |
*/ |
| 550 | 550 |
|
| 551 | 551 |
/** |
| 552 | 552 |
@defgroup tools Standalone utility applications |
| 553 | 553 |
|
| 554 |
Some utility applications are listed here. |
|
| 554 |
Some utility applications are listed here. |
|
| 555 | 555 |
|
| 556 | 556 |
The standard compilation procedure (<tt>./configure;make</tt>) will compile |
| 557 |
them, as well. |
|
| 557 |
them, as well. |
|
| 558 | 558 |
*/ |
| 559 | 559 |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 {
|
| ... | ... |
@@ -30,62 +30,62 @@ |
| 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 |
contain whitespaces and escape sequences. |
|
| 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 | 66 |
The \c \@arcs section is very similar to the \c \@nodes section, |
| 67 | 67 |
it again starts with a header line describing the names of the maps, |
| 68 | 68 |
but the \c "label" map is not obligatory here. The following lines |
| 69 | 69 |
describe the arcs. The first two tokens of each line are |
| 70 | 70 |
the source 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 | 81 |
The \c \@edges is just a synonym of \c \@arcs. The @arcs section can |
| 82 | 82 |
also store the edge set of an undirected graph. In such case there is |
| 83 | 83 |
a conventional method for store arc maps in the file, if two columns |
| 84 | 84 |
has the same caption with \c '+' and \c '-' prefix, then these columns |
| 85 | 85 |
can be regarded as the values of an arc map. |
| 86 | 86 |
|
| 87 | 87 |
The \c \@attributes section contains key-value pairs, each line |
| 88 | 88 |
consists of two tokens, an attribute name, and then an attribute |
| 89 | 89 |
value. The value of the attribute could be also a label value of a |
| 90 | 90 |
node or an edge, or even an edge label prefixed with \c '+' or \c '-', |
| 91 | 91 |
which regards to the forward or backward directed arc of the |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/** |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/** |
| ... | ... |
@@ -28,33 +28,33 @@ |
| 28 | 28 |
and <b>O</b>ptimization in <b>N</b>etworks. |
| 29 | 29 |
It is a C++ template |
| 30 | 30 |
library aimed at combinatorial optimization tasks which |
| 31 | 31 |
often involve in working |
| 32 | 32 |
with graphs. |
| 33 | 33 |
|
| 34 | 34 |
<b> |
| 35 | 35 |
LEMON is an <a class="el" href="http://opensource.org/">open source</a> |
| 36 | 36 |
project. |
| 37 | 37 |
You are free to use it in your commercial or |
| 38 | 38 |
non-commercial applications under very permissive |
| 39 | 39 |
\ref license "license terms". |
| 40 | 40 |
</b> |
| 41 | 41 |
|
| 42 | 42 |
\subsection howtoread How to read the documentation |
| 43 | 43 |
|
| 44 |
If you want to get a quick start and see the most important features then |
|
| 44 |
If you want to get a quick start and see the most important features then |
|
| 45 | 45 |
take a look at our \ref quicktour |
| 46 | 46 |
"Quick Tour to LEMON" which will guide you along. |
| 47 | 47 |
|
| 48 |
If you already feel like using our library, see the page that tells you |
|
| 48 |
If you already feel like using our library, see the page that tells you |
|
| 49 | 49 |
\ref getstart "How to start using LEMON". |
| 50 | 50 |
|
| 51 |
If you |
|
| 52 |
want to see how LEMON works, see |
|
| 51 |
If you |
|
| 52 |
want to see how LEMON works, see |
|
| 53 | 53 |
some \ref demoprograms "demo programs"! |
| 54 | 54 |
|
| 55 | 55 |
If you know what you are looking for then try to find it under the |
| 56 | 56 |
<a class="el" href="modules.html">Modules</a> |
| 57 | 57 |
section. |
| 58 | 58 |
|
| 59 | 59 |
|
| 60 | 60 |
*/ |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/// The namespace of LEMON |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TEMPLATE_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/arg_parser.h> |
| ... | ... |
@@ -25,112 +25,112 @@ |
| 25 | 25 |
(static_cast<ArgParser*>(p))->showHelp(); |
| 26 | 26 |
exit(1); |
| 27 | 27 |
} |
| 28 | 28 |
|
| 29 | 29 |
ArgParser::ArgParser(int argc, const char **argv) :_argc(argc), _argv(argv), |
| 30 | 30 |
_command_name(argv[0]) {
|
| 31 | 31 |
funcOption("-help","Print a short help message",_showHelp,this);
|
| 32 | 32 |
synonym("help","-help");
|
| 33 | 33 |
synonym("h","-help");
|
| 34 | 34 |
|
| 35 | 35 |
} |
| 36 | 36 |
|
| 37 | 37 |
ArgParser::~ArgParser() |
| 38 | 38 |
{
|
| 39 | 39 |
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
| 40 | 40 |
if(i->second.self_delete) |
| 41 |
switch(i->second.type) {
|
|
| 42 |
case BOOL: |
|
| 43 |
delete i->second.bool_p; |
|
| 44 |
break; |
|
| 45 |
case STRING: |
|
| 46 |
delete i->second.string_p; |
|
| 47 |
break; |
|
| 48 |
case DOUBLE: |
|
| 49 |
delete i->second.double_p; |
|
| 50 |
break; |
|
| 51 |
case INTEGER: |
|
| 52 |
delete i->second.int_p; |
|
| 53 |
break; |
|
| 54 |
case UNKNOWN: |
|
| 55 |
break; |
|
| 56 |
case FUNC: |
|
| 57 |
break; |
|
| 58 |
} |
|
| 41 |
switch(i->second.type) {
|
|
| 42 |
case BOOL: |
|
| 43 |
delete i->second.bool_p; |
|
| 44 |
break; |
|
| 45 |
case STRING: |
|
| 46 |
delete i->second.string_p; |
|
| 47 |
break; |
|
| 48 |
case DOUBLE: |
|
| 49 |
delete i->second.double_p; |
|
| 50 |
break; |
|
| 51 |
case INTEGER: |
|
| 52 |
delete i->second.int_p; |
|
| 53 |
break; |
|
| 54 |
case UNKNOWN: |
|
| 55 |
break; |
|
| 56 |
case FUNC: |
|
| 57 |
break; |
|
| 58 |
} |
|
| 59 | 59 |
} |
| 60 |
|
|
| 60 |
|
|
| 61 | 61 |
|
| 62 | 62 |
ArgParser &ArgParser::intOption(const std::string &name, |
| 63 |
const std::string &help, |
|
| 64 |
int value, bool obl) |
|
| 63 |
const std::string &help, |
|
| 64 |
int value, bool obl) |
|
| 65 | 65 |
{
|
| 66 | 66 |
ParData p; |
| 67 | 67 |
p.int_p=new int(value); |
| 68 | 68 |
p.self_delete=true; |
| 69 | 69 |
p.help=help; |
| 70 | 70 |
p.type=INTEGER; |
| 71 | 71 |
p.mandatory=obl; |
| 72 | 72 |
_opts[name]=p; |
| 73 | 73 |
return *this; |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 | 76 |
ArgParser &ArgParser::doubleOption(const std::string &name, |
| 77 |
const std::string &help, |
|
| 78 |
double value, bool obl) |
|
| 77 |
const std::string &help, |
|
| 78 |
double value, bool obl) |
|
| 79 | 79 |
{
|
| 80 | 80 |
ParData p; |
| 81 | 81 |
p.double_p=new double(value); |
| 82 | 82 |
p.self_delete=true; |
| 83 | 83 |
p.help=help; |
| 84 | 84 |
p.type=DOUBLE; |
| 85 | 85 |
p.mandatory=obl; |
| 86 | 86 |
_opts[name]=p; |
| 87 | 87 |
return *this; |
| 88 | 88 |
} |
| 89 | 89 |
|
| 90 | 90 |
ArgParser &ArgParser::boolOption(const std::string &name, |
| 91 |
const std::string &help, |
|
| 92 |
bool value, bool obl) |
|
| 91 |
const std::string &help, |
|
| 92 |
bool value, bool obl) |
|
| 93 | 93 |
{
|
| 94 | 94 |
ParData p; |
| 95 | 95 |
p.bool_p=new bool(value); |
| 96 | 96 |
p.self_delete=true; |
| 97 | 97 |
p.help=help; |
| 98 | 98 |
p.type=BOOL; |
| 99 | 99 |
p.mandatory=obl; |
| 100 | 100 |
_opts[name]=p; |
| 101 | 101 |
return *this; |
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
ArgParser &ArgParser::stringOption(const std::string &name, |
| 105 |
const std::string &help, |
|
| 106 |
std::string value, bool obl) |
|
| 105 |
const std::string &help, |
|
| 106 |
std::string value, bool obl) |
|
| 107 | 107 |
{
|
| 108 | 108 |
ParData p; |
| 109 | 109 |
p.string_p=new std::string(value); |
| 110 | 110 |
p.self_delete=true; |
| 111 | 111 |
p.help=help; |
| 112 | 112 |
p.type=STRING; |
| 113 | 113 |
p.mandatory=obl; |
| 114 | 114 |
_opts[name]=p; |
| 115 | 115 |
return *this; |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
ArgParser &ArgParser::refOption(const std::string &name, |
| 119 |
const std::string &help, |
|
| 120 |
int &ref, bool obl) |
|
| 119 |
const std::string &help, |
|
| 120 |
int &ref, bool obl) |
|
| 121 | 121 |
{
|
| 122 | 122 |
ParData p; |
| 123 | 123 |
p.int_p=&ref; |
| 124 | 124 |
p.self_delete=false; |
| 125 | 125 |
p.help=help; |
| 126 | 126 |
p.type=INTEGER; |
| 127 | 127 |
p.mandatory=obl; |
| 128 | 128 |
_opts[name]=p; |
| 129 | 129 |
return *this; |
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
ArgParser &ArgParser::refOption(const std::string &name, |
| 133 | 133 |
const std::string &help, |
| 134 | 134 |
double &ref, bool obl) |
| 135 | 135 |
{
|
| 136 | 136 |
ParData p; |
| ... | ... |
@@ -148,318 +148,318 @@ |
| 148 | 148 |
bool &ref, bool obl) |
| 149 | 149 |
{
|
| 150 | 150 |
ParData p; |
| 151 | 151 |
p.bool_p=&ref; |
| 152 | 152 |
p.self_delete=false; |
| 153 | 153 |
p.help=help; |
| 154 | 154 |
p.type=BOOL; |
| 155 | 155 |
p.mandatory=obl; |
| 156 | 156 |
_opts[name]=p; |
| 157 | 157 |
|
| 158 | 158 |
ref = false; |
| 159 | 159 |
|
| 160 | 160 |
return *this; |
| 161 | 161 |
} |
| 162 | 162 |
|
| 163 | 163 |
ArgParser &ArgParser::refOption(const std::string &name, |
| 164 |
const std::string &help, |
|
| 165 |
std::string &ref, bool obl) |
|
| 164 |
const std::string &help, |
|
| 165 |
std::string &ref, bool obl) |
|
| 166 | 166 |
{
|
| 167 | 167 |
ParData p; |
| 168 | 168 |
p.string_p=&ref; |
| 169 | 169 |
p.self_delete=false; |
| 170 | 170 |
p.help=help; |
| 171 | 171 |
p.type=STRING; |
| 172 | 172 |
p.mandatory=obl; |
| 173 | 173 |
_opts[name]=p; |
| 174 | 174 |
return *this; |
| 175 | 175 |
} |
| 176 | 176 |
|
| 177 | 177 |
ArgParser &ArgParser::funcOption(const std::string &name, |
| 178 |
const std::string &help, |
|
| 179 |
void (*func)(void *),void *data) |
|
| 178 |
const std::string &help, |
|
| 179 |
void (*func)(void *),void *data) |
|
| 180 | 180 |
{
|
| 181 | 181 |
ParData p; |
| 182 | 182 |
p.func_p.p=func; |
| 183 | 183 |
p.func_p.data=data; |
| 184 | 184 |
p.self_delete=false; |
| 185 | 185 |
p.help=help; |
| 186 | 186 |
p.type=FUNC; |
| 187 | 187 |
p.mandatory=false; |
| 188 | 188 |
_opts[name]=p; |
| 189 | 189 |
return *this; |
| 190 | 190 |
} |
| 191 | 191 |
|
| 192 | 192 |
ArgParser &ArgParser::optionGroup(const std::string &group, |
| 193 |
|
|
| 193 |
const std::string &opt) |
|
| 194 | 194 |
{
|
| 195 | 195 |
Opts::iterator i = _opts.find(opt); |
| 196 | 196 |
LEMON_ASSERT(i!=_opts.end(), "Unknown option: '"+opt+"'"); |
| 197 |
LEMON_ASSERT(!(i->second.ingroup), |
|
| 197 |
LEMON_ASSERT(!(i->second.ingroup), |
|
| 198 | 198 |
"Option already in option group: '"+opt+"'"); |
| 199 | 199 |
GroupData &g=_groups[group]; |
| 200 | 200 |
g.opts.push_back(opt); |
| 201 | 201 |
i->second.ingroup=true; |
| 202 | 202 |
return *this; |
| 203 | 203 |
} |
| 204 | 204 |
|
| 205 | 205 |
ArgParser &ArgParser::onlyOneGroup(const std::string &group) |
| 206 | 206 |
{
|
| 207 | 207 |
GroupData &g=_groups[group]; |
| 208 | 208 |
g.only_one=true; |
| 209 | 209 |
return *this; |
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 | 212 |
ArgParser &ArgParser::synonym(const std::string &syn, |
| 213 |
|
|
| 213 |
const std::string &opt) |
|
| 214 | 214 |
{
|
| 215 | 215 |
Opts::iterator o = _opts.find(opt); |
| 216 | 216 |
Opts::iterator s = _opts.find(syn); |
| 217 | 217 |
LEMON_ASSERT(o!=_opts.end(), "Unknown option: '"+opt+"'"); |
| 218 | 218 |
LEMON_ASSERT(s==_opts.end(), "Option already used: '"+syn+"'"); |
| 219 | 219 |
ParData p; |
| 220 | 220 |
p.help=opt; |
| 221 | 221 |
p.mandatory=false; |
| 222 | 222 |
p.syn=true; |
| 223 | 223 |
_opts[syn]=p; |
| 224 | 224 |
o->second.has_syn=true; |
| 225 | 225 |
return *this; |
| 226 | 226 |
} |
| 227 | 227 |
|
| 228 | 228 |
ArgParser &ArgParser::mandatoryGroup(const std::string &group) |
| 229 | 229 |
{
|
| 230 | 230 |
GroupData &g=_groups[group]; |
| 231 | 231 |
g.mandatory=true; |
| 232 | 232 |
return *this; |
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
ArgParser &ArgParser::other(const std::string &name, |
| 236 |
|
|
| 236 |
const std::string &help) |
|
| 237 | 237 |
{
|
| 238 | 238 |
_others_help.push_back(OtherArg(name,help)); |
| 239 | 239 |
return *this; |
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
void ArgParser::show(std::ostream &os,Opts::iterator i) |
| 243 | 243 |
{
|
| 244 | 244 |
os << "-" << i->first; |
| 245 | 245 |
if(i->second.has_syn) |
| 246 | 246 |
for(Opts::iterator j=_opts.begin();j!=_opts.end();++j) |
| 247 |
if(j->second.syn&&j->second.help==i->first) |
|
| 248 |
os << "|-" << j->first; |
|
| 247 |
if(j->second.syn&&j->second.help==i->first) |
|
| 248 |
os << "|-" << j->first; |
|
| 249 | 249 |
switch(i->second.type) {
|
| 250 | 250 |
case STRING: |
| 251 | 251 |
os << " str"; |
| 252 | 252 |
break; |
| 253 | 253 |
case INTEGER: |
| 254 | 254 |
os << " int"; |
| 255 | 255 |
break; |
| 256 | 256 |
case DOUBLE: |
| 257 | 257 |
os << " num"; |
| 258 | 258 |
break; |
| 259 | 259 |
default: |
| 260 | 260 |
break; |
| 261 | 261 |
} |
| 262 | 262 |
} |
| 263 | 263 |
|
| 264 | 264 |
void ArgParser::show(std::ostream &os,Groups::iterator i) |
| 265 | 265 |
{
|
| 266 | 266 |
GroupData::Opts::iterator o=i->second.opts.begin(); |
| 267 | 267 |
while(o!=i->second.opts.end()) {
|
| 268 | 268 |
show(os,_opts.find(*o)); |
| 269 | 269 |
++o; |
| 270 | 270 |
if(o!=i->second.opts.end()) os<<'|'; |
| 271 | 271 |
} |
| 272 | 272 |
} |
| 273 |
|
|
| 273 |
|
|
| 274 | 274 |
void ArgParser::showHelp(Opts::iterator i) |
| 275 | 275 |
{
|
| 276 | 276 |
if(i->second.help.size()==0||i->second.syn) return; |
| 277 | 277 |
std::cerr << " "; |
| 278 | 278 |
show(std::cerr,i); |
| 279 | 279 |
std::cerr << std::endl; |
| 280 | 280 |
std::cerr << " " << i->second.help << std::endl; |
| 281 | 281 |
} |
| 282 | 282 |
void ArgParser::showHelp(std::vector<ArgParser::OtherArg>::iterator i) |
| 283 | 283 |
{
|
| 284 | 284 |
if(i->help.size()==0) return; |
| 285 | 285 |
std::cerr << " " << i->name << std::endl |
| 286 |
|
|
| 286 |
<< " " << i->help << std::endl; |
|
| 287 | 287 |
} |
| 288 |
|
|
| 288 |
|
|
| 289 | 289 |
void ArgParser::shortHelp() |
| 290 | 290 |
{
|
| 291 | 291 |
const unsigned int LINE_LEN=77; |
| 292 | 292 |
const std::string indent(" ");
|
| 293 | 293 |
std::cerr << "Usage:\n " << _command_name; |
| 294 | 294 |
int pos=_command_name.size()+2; |
| 295 | 295 |
for(Groups::iterator g=_groups.begin();g!=_groups.end();++g) {
|
| 296 | 296 |
std::ostringstream cstr; |
| 297 | 297 |
cstr << ' '; |
| 298 | 298 |
if(!g->second.mandatory) cstr << '['; |
| 299 | 299 |
show(cstr,g); |
| 300 | 300 |
if(!g->second.mandatory) cstr << ']'; |
| 301 | 301 |
if(pos+cstr.str().size()>LINE_LEN) {
|
| 302 |
std::cerr << std::endl << indent; |
|
| 303 |
pos=indent.size(); |
|
| 302 |
std::cerr << std::endl << indent; |
|
| 303 |
pos=indent.size(); |
|
| 304 | 304 |
} |
| 305 | 305 |
std::cerr << cstr.str(); |
| 306 | 306 |
pos+=cstr.str().size(); |
| 307 | 307 |
} |
| 308 | 308 |
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
| 309 | 309 |
if(!i->second.ingroup&&!i->second.syn) {
|
| 310 |
std::ostringstream cstr; |
|
| 311 |
cstr << ' '; |
|
| 312 |
if(!i->second.mandatory) cstr << '['; |
|
| 313 |
show(cstr,i); |
|
| 314 |
if(!i->second.mandatory) cstr << ']'; |
|
| 315 |
if(pos+cstr.str().size()>LINE_LEN) {
|
|
| 316 |
std::cerr << std::endl << indent; |
|
| 317 |
pos=indent.size(); |
|
| 318 |
} |
|
| 319 |
std::cerr << cstr.str(); |
|
| 320 |
|
|
| 310 |
std::ostringstream cstr; |
|
| 311 |
cstr << ' '; |
|
| 312 |
if(!i->second.mandatory) cstr << '['; |
|
| 313 |
show(cstr,i); |
|
| 314 |
if(!i->second.mandatory) cstr << ']'; |
|
| 315 |
if(pos+cstr.str().size()>LINE_LEN) {
|
|
| 316 |
std::cerr << std::endl << indent; |
|
| 317 |
pos=indent.size(); |
|
| 318 |
} |
|
| 319 |
std::cerr << cstr.str(); |
|
| 320 |
pos+=cstr.str().size(); |
|
| 321 | 321 |
} |
| 322 | 322 |
for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
| 323 |
|
|
| 323 |
i!=_others_help.end();++i) |
|
| 324 | 324 |
{
|
| 325 |
std::ostringstream cstr; |
|
| 326 |
cstr << ' ' << i->name; |
|
| 327 |
|
|
| 328 |
if(pos+cstr.str().size()>LINE_LEN) {
|
|
| 329 |
std::cerr << std::endl << indent; |
|
| 330 |
pos=indent.size(); |
|
| 331 |
} |
|
| 332 |
std::cerr << cstr.str(); |
|
| 333 |
|
|
| 325 |
std::ostringstream cstr; |
|
| 326 |
cstr << ' ' << i->name; |
|
| 327 |
|
|
| 328 |
if(pos+cstr.str().size()>LINE_LEN) {
|
|
| 329 |
std::cerr << std::endl << indent; |
|
| 330 |
pos=indent.size(); |
|
| 331 |
} |
|
| 332 |
std::cerr << cstr.str(); |
|
| 333 |
pos+=cstr.str().size(); |
|
| 334 | 334 |
} |
| 335 | 335 |
std::cerr << std::endl; |
| 336 | 336 |
} |
| 337 |
|
|
| 337 |
|
|
| 338 | 338 |
void ArgParser::showHelp() |
| 339 | 339 |
{
|
| 340 | 340 |
shortHelp(); |
| 341 | 341 |
std::cerr << "Where:\n"; |
| 342 | 342 |
for(std::vector<OtherArg>::iterator i=_others_help.begin(); |
| 343 |
|
|
| 343 |
i!=_others_help.end();++i) showHelp(i); |
|
| 344 | 344 |
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i); |
| 345 | 345 |
exit(1); |
| 346 | 346 |
} |
| 347 |
|
|
| 348 |
|
|
| 349 |
|
|
| 347 |
|
|
| 348 |
|
|
| 349 |
void ArgParser::unknownOpt(std::string arg) |
|
| 350 | 350 |
{
|
| 351 | 351 |
std::cerr << "\nUnknown option: " << arg << "\n"; |
| 352 | 352 |
std::cerr << "\nType '" << _command_name << |
| 353 | 353 |
" --help' to obtain a short summary on the usage.\n\n"; |
| 354 | 354 |
exit(1); |
| 355 | 355 |
} |
| 356 |
|
|
| 357 |
void ArgParser::requiresValue(std::string arg, OptType t) |
|
| 356 |
|
|
| 357 |
void ArgParser::requiresValue(std::string arg, OptType t) |
|
| 358 | 358 |
{
|
| 359 | 359 |
std::cerr << "Argument '" << arg << "' requires a"; |
| 360 | 360 |
switch(t) {
|
| 361 | 361 |
case STRING: |
| 362 | 362 |
std::cerr << " string"; |
| 363 | 363 |
break; |
| 364 | 364 |
case INTEGER: |
| 365 | 365 |
std::cerr << "n integer"; |
| 366 | 366 |
break; |
| 367 | 367 |
case DOUBLE: |
| 368 | 368 |
std::cerr << " floating point"; |
| 369 | 369 |
break; |
| 370 | 370 |
default: |
| 371 | 371 |
break; |
| 372 | 372 |
} |
| 373 | 373 |
std::cerr << " value\n\n"; |
| 374 | 374 |
showHelp(); |
| 375 | 375 |
} |
| 376 |
|
|
| 376 |
|
|
| 377 | 377 |
|
| 378 | 378 |
void ArgParser::checkMandatories() |
| 379 | 379 |
{
|
| 380 | 380 |
bool ok=true; |
| 381 | 381 |
for(Opts::iterator i=_opts.begin();i!=_opts.end();++i) |
| 382 |
if(i->second.mandatory&&!i->second.set) |
|
| 383 |
{
|
|
| 384 |
if(ok) |
|
| 385 |
std::cerr << _command_name |
|
| 386 |
<< ": The following mandatory arguments are missing.\n"; |
|
| 387 |
ok=false; |
|
| 388 |
showHelp(i); |
|
| 389 |
} |
|
| 382 |
if(i->second.mandatory&&!i->second.set) |
|
| 383 |
{
|
|
| 384 |
if(ok) |
|
| 385 |
std::cerr << _command_name |
|
| 386 |
<< ": The following mandatory arguments are missing.\n"; |
|
| 387 |
ok=false; |
|
| 388 |
showHelp(i); |
|
| 389 |
} |
|
| 390 | 390 |
for(Groups::iterator i=_groups.begin();i!=_groups.end();++i) |
| 391 | 391 |
if(i->second.mandatory||i->second.only_one) |
| 392 |
{
|
|
| 393 |
int set=0; |
|
| 394 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 395 |
o!=i->second.opts.end();++o) |
|
| 396 |
if(_opts.find(*o)->second.set) ++set; |
|
| 397 |
if(i->second.mandatory&&!set) {
|
|
| 398 |
std::cerr << _command_name |
|
| 399 |
<< ": At least one of the following arguments is mandatory.\n"; |
|
| 400 |
ok=false; |
|
| 401 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 402 |
o!=i->second.opts.end();++o) |
|
| 403 |
showHelp(_opts.find(*o)); |
|
| 404 |
} |
|
| 405 |
if(i->second.only_one&&set>1) {
|
|
| 406 |
std::cerr << _command_name |
|
| 407 |
<< ": At most one of the following arguments can be given.\n"; |
|
| 408 |
ok=false; |
|
| 409 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 410 |
o!=i->second.opts.end();++o) |
|
| 411 |
showHelp(_opts.find(*o)); |
|
| 412 |
} |
|
| 413 |
} |
|
| 392 |
{
|
|
| 393 |
int set=0; |
|
| 394 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 395 |
o!=i->second.opts.end();++o) |
|
| 396 |
if(_opts.find(*o)->second.set) ++set; |
|
| 397 |
if(i->second.mandatory&&!set) {
|
|
| 398 |
std::cerr << _command_name |
|
| 399 |
<< ": At least one of the following arguments is mandatory.\n"; |
|
| 400 |
ok=false; |
|
| 401 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 402 |
o!=i->second.opts.end();++o) |
|
| 403 |
showHelp(_opts.find(*o)); |
|
| 404 |
} |
|
| 405 |
if(i->second.only_one&&set>1) {
|
|
| 406 |
std::cerr << _command_name |
|
| 407 |
<< ": At most one of the following arguments can be given.\n"; |
|
| 408 |
ok=false; |
|
| 409 |
for(GroupData::Opts::iterator o=i->second.opts.begin(); |
|
| 410 |
o!=i->second.opts.end();++o) |
|
| 411 |
showHelp(_opts.find(*o)); |
|
| 412 |
} |
|
| 413 |
} |
|
| 414 | 414 |
if(!ok) {
|
| 415 | 415 |
std::cerr << "\nType '" << _command_name << |
| 416 |
|
|
| 416 |
" --help' to obtain a short summary on the usage.\n\n"; |
|
| 417 | 417 |
exit(1); |
| 418 | 418 |
} |
| 419 | 419 |
} |
| 420 | 420 |
|
| 421 | 421 |
ArgParser &ArgParser::parse() |
| 422 | 422 |
{
|
| 423 | 423 |
for(int ar=1; ar<_argc; ++ar) {
|
| 424 | 424 |
std::string arg(_argv[ar]); |
| 425 | 425 |
if (arg[0] != '-' || arg.size() == 1) {
|
| 426 |
|
|
| 426 |
_file_args.push_back(arg); |
|
| 427 | 427 |
} |
| 428 | 428 |
else {
|
| 429 |
Opts::iterator i = _opts.find(arg.substr(1)); |
|
| 430 |
if(i==_opts.end()) unknownOpt(arg); |
|
| 431 |
else {
|
|
| 432 |
if(i->second.syn) i=_opts.find(i->second.help); |
|
| 433 |
ParData &p(i->second); |
|
| 434 |
if (p.type==BOOL) *p.bool_p=true; |
|
| 435 |
else if (p.type==FUNC) p.func_p.p(p.func_p.data); |
|
| 436 |
else if(++ar==_argc) requiresValue(arg, p.type); |
|
| 437 |
else {
|
|
| 438 |
std::string val(_argv[ar]); |
|
| 439 |
std::istringstream vals(val); |
|
| 440 |
switch(p.type) {
|
|
| 441 |
case STRING: |
|
| 442 |
*p.string_p=val; |
|
| 443 |
break; |
|
| 444 |
case INTEGER: |
|
| 445 |
vals >> *p.int_p; |
|
| 446 |
break; |
|
| 447 |
case DOUBLE: |
|
| 448 |
vals >> *p.double_p; |
|
| 449 |
break; |
|
| 450 |
default: |
|
| 451 |
break; |
|
| 452 |
} |
|
| 453 |
if(p.type!=STRING&&(!vals||!vals.eof())) |
|
| 454 |
requiresValue(arg, p.type); |
|
| 455 |
} |
|
| 456 |
p.set = true; |
|
| 457 |
|
|
| 429 |
Opts::iterator i = _opts.find(arg.substr(1)); |
|
| 430 |
if(i==_opts.end()) unknownOpt(arg); |
|
| 431 |
else {
|
|
| 432 |
if(i->second.syn) i=_opts.find(i->second.help); |
|
| 433 |
ParData &p(i->second); |
|
| 434 |
if (p.type==BOOL) *p.bool_p=true; |
|
| 435 |
else if (p.type==FUNC) p.func_p.p(p.func_p.data); |
|
| 436 |
else if(++ar==_argc) requiresValue(arg, p.type); |
|
| 437 |
else {
|
|
| 438 |
std::string val(_argv[ar]); |
|
| 439 |
std::istringstream vals(val); |
|
| 440 |
switch(p.type) {
|
|
| 441 |
case STRING: |
|
| 442 |
*p.string_p=val; |
|
| 443 |
break; |
|
| 444 |
case INTEGER: |
|
| 445 |
vals >> *p.int_p; |
|
| 446 |
break; |
|
| 447 |
case DOUBLE: |
|
| 448 |
vals >> *p.double_p; |
|
| 449 |
break; |
|
| 450 |
default: |
|
| 451 |
break; |
|
| 452 |
} |
|
| 453 |
if(p.type!=STRING&&(!vals||!vals.eof())) |
|
| 454 |
requiresValue(arg, p.type); |
|
| 455 |
} |
|
| 456 |
p.set = true; |
|
| 457 |
} |
|
| 458 | 458 |
} |
| 459 | 459 |
} |
| 460 | 460 |
checkMandatories(); |
| 461 | 461 |
|
| 462 | 462 |
return *this; |
| 463 |
} |
|
| 463 |
} |
|
| 464 | 464 |
|
| 465 | 465 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_ARG_PARSER |
| ... | ... |
@@ -28,355 +28,355 @@ |
| 28 | 28 |
#include <algorithm> |
| 29 | 29 |
#include <lemon/assert.h> |
| 30 | 30 |
|
| 31 | 31 |
///\ingroup misc |
| 32 | 32 |
///\file |
| 33 | 33 |
///\brief A tool to parse command line arguments. |
| 34 | 34 |
|
| 35 | 35 |
namespace lemon {
|
| 36 | 36 |
|
| 37 | 37 |
///Command line arguments parser |
| 38 | 38 |
|
| 39 | 39 |
///\ingroup misc |
| 40 | 40 |
///Command line arguments parser. |
| 41 | 41 |
/// |
| 42 | 42 |
///For a complete example see the \ref arg_parser_demo.cc demo file. |
| 43 | 43 |
class ArgParser {
|
| 44 |
|
|
| 44 |
|
|
| 45 | 45 |
static void _showHelp(void *p); |
| 46 | 46 |
protected: |
| 47 |
|
|
| 47 |
|
|
| 48 | 48 |
int _argc; |
| 49 | 49 |
const char **_argv; |
| 50 |
|
|
| 50 |
|
|
| 51 | 51 |
enum OptType { UNKNOWN=0, BOOL=1, STRING=2, DOUBLE=3, INTEGER=4, FUNC=5 };
|
| 52 |
|
|
| 52 |
|
|
| 53 | 53 |
class ParData {
|
| 54 | 54 |
public: |
| 55 | 55 |
union {
|
| 56 |
bool *bool_p; |
|
| 57 |
int *int_p; |
|
| 58 |
double *double_p; |
|
| 59 |
std::string *string_p; |
|
| 60 |
struct {
|
|
| 61 |
void (*p)(void *); |
|
| 62 |
void *data; |
|
| 63 |
} func_p; |
|
| 64 |
|
|
| 56 |
bool *bool_p; |
|
| 57 |
int *int_p; |
|
| 58 |
double *double_p; |
|
| 59 |
std::string *string_p; |
|
| 60 |
struct {
|
|
| 61 |
void (*p)(void *); |
|
| 62 |
void *data; |
|
| 63 |
} func_p; |
|
| 64 |
|
|
| 65 | 65 |
}; |
| 66 | 66 |
std::string help; |
| 67 | 67 |
bool mandatory; |
| 68 | 68 |
OptType type; |
| 69 | 69 |
bool set; |
| 70 | 70 |
bool ingroup; |
| 71 | 71 |
bool has_syn; |
| 72 | 72 |
bool syn; |
| 73 | 73 |
bool self_delete; |
| 74 | 74 |
ParData() : mandatory(false), type(UNKNOWN), set(false), ingroup(false), |
| 75 |
|
|
| 75 |
has_syn(false), syn(false), self_delete(false) {}
|
|
| 76 | 76 |
}; |
| 77 | 77 |
|
| 78 | 78 |
typedef std::map<std::string,ParData> Opts; |
| 79 | 79 |
Opts _opts; |
| 80 | 80 |
|
| 81 |
class GroupData |
|
| 81 |
class GroupData |
|
| 82 | 82 |
{
|
| 83 | 83 |
public: |
| 84 | 84 |
typedef std::list<std::string> Opts; |
| 85 | 85 |
Opts opts; |
| 86 | 86 |
bool only_one; |
| 87 | 87 |
bool mandatory; |
| 88 | 88 |
GroupData() :only_one(false), mandatory(false) {}
|
| 89 | 89 |
}; |
| 90 |
|
|
| 90 |
|
|
| 91 | 91 |
typedef std::map<std::string,GroupData> Groups; |
| 92 | 92 |
Groups _groups; |
| 93 | 93 |
|
| 94 | 94 |
struct OtherArg |
| 95 | 95 |
{
|
| 96 | 96 |
std::string name; |
| 97 | 97 |
std::string help; |
| 98 | 98 |
OtherArg(std::string n, std::string h) :name(n), help(h) {}
|
| 99 | 99 |
|
| 100 | 100 |
}; |
| 101 |
|
|
| 101 |
|
|
| 102 | 102 |
std::vector<OtherArg> _others_help; |
| 103 | 103 |
std::vector<std::string> _file_args; |
| 104 | 104 |
std::string _command_name; |
| 105 | 105 |
|
| 106 |
|
|
| 106 |
|
|
| 107 | 107 |
private: |
| 108 | 108 |
//Bind a function to an option. |
| 109 | 109 |
|
| 110 | 110 |
//\param name The name of the option. The leading '-' must be omitted. |
| 111 | 111 |
//\param help A help string. |
| 112 | 112 |
//\retval func The function to be called when the option is given. It |
| 113 | 113 |
// must be of type "void f(void *)" |
| 114 | 114 |
//\param data Data to be passed to \c func |
| 115 | 115 |
ArgParser &funcOption(const std::string &name, |
| 116 |
const std::string &help, |
|
| 117 |
void (*func)(void *),void *data); |
|
| 118 |
|
|
| 116 |
const std::string &help, |
|
| 117 |
void (*func)(void *),void *data); |
|
| 118 |
|
|
| 119 | 119 |
public: |
| 120 | 120 |
|
| 121 | 121 |
///Constructor |
| 122 | 122 |
ArgParser(int argc, const char **argv); |
| 123 | 123 |
|
| 124 | 124 |
~ArgParser(); |
| 125 | 125 |
|
| 126 | 126 |
///\name Options |
| 127 | 127 |
/// |
| 128 | 128 |
|
| 129 | 129 |
///@{
|
| 130 | 130 |
|
| 131 | 131 |
///Add a new integer type option |
| 132 | 132 |
|
| 133 | 133 |
///Add a new integer type option. |
| 134 | 134 |
///\param name The name of the option. The leading '-' must be omitted. |
| 135 | 135 |
///\param help A help string. |
| 136 | 136 |
///\param value A default value for the option. |
| 137 | 137 |
///\param obl Indicate if the option is mandatory. |
| 138 | 138 |
ArgParser &intOption(const std::string &name, |
| 139 |
const std::string &help, |
|
| 140 |
int value=0, bool obl=false); |
|
| 139 |
const std::string &help, |
|
| 140 |
int value=0, bool obl=false); |
|
| 141 | 141 |
|
| 142 | 142 |
///Add a new floating point type option |
| 143 | 143 |
|
| 144 | 144 |
///Add a new floating point type option. |
| 145 | 145 |
///\param name The name of the option. The leading '-' must be omitted. |
| 146 | 146 |
///\param help A help string. |
| 147 | 147 |
///\param value A default value for the option. |
| 148 | 148 |
///\param obl Indicate if the option is mandatory. |
| 149 | 149 |
ArgParser &doubleOption(const std::string &name, |
| 150 |
const std::string &help, |
|
| 151 |
double value=0, bool obl=false); |
|
| 150 |
const std::string &help, |
|
| 151 |
double value=0, bool obl=false); |
|
| 152 | 152 |
|
| 153 | 153 |
///Add a new bool type option |
| 154 | 154 |
|
| 155 | 155 |
///Add a new bool type option. |
| 156 | 156 |
///\param name The name of the option. The leading '-' must be omitted. |
| 157 | 157 |
///\param help A help string. |
| 158 | 158 |
///\param value A default value for the option. |
| 159 | 159 |
///\param obl Indicate if the option is mandatory. |
| 160 | 160 |
///\note A mandatory bool obtion is of very little use. |
| 161 | 161 |
ArgParser &boolOption(const std::string &name, |
| 162 |
const std::string &help, |
|
| 163 |
bool value=false, bool obl=false); |
|
| 162 |
const std::string &help, |
|
| 163 |
bool value=false, bool obl=false); |
|
| 164 | 164 |
|
| 165 | 165 |
///Add a new string type option |
| 166 | 166 |
|
| 167 | 167 |
///Add a new string type option. |
| 168 | 168 |
///\param name The name of the option. The leading '-' must be omitted. |
| 169 | 169 |
///\param help A help string. |
| 170 | 170 |
///\param value A default value for the option. |
| 171 | 171 |
///\param obl Indicate if the option is mandatory. |
| 172 | 172 |
ArgParser &stringOption(const std::string &name, |
| 173 |
const std::string &help, |
|
| 174 |
std::string value="", bool obl=false); |
|
| 173 |
const std::string &help, |
|
| 174 |
std::string value="", bool obl=false); |
|
| 175 | 175 |
|
| 176 | 176 |
///Give help string for non-parsed arguments. |
| 177 | 177 |
|
| 178 | 178 |
///With this function you can give help string for non-parsed arguments. |
| 179 | 179 |
///The parameter \c name will be printed in the short usage line, while |
| 180 | 180 |
///\c help gives a more detailed description. |
| 181 | 181 |
ArgParser &other(const std::string &name, |
| 182 |
const std::string &help=""); |
|
| 183 |
|
|
| 182 |
const std::string &help=""); |
|
| 183 |
|
|
| 184 | 184 |
///@} |
| 185 | 185 |
|
| 186 | 186 |
///\name Options with External Storage |
| 187 | 187 |
///Using this functions, the value of the option will be directly written |
| 188 | 188 |
///into a variable once the option appears in the command line. |
| 189 | 189 |
|
| 190 | 190 |
///@{
|
| 191 | 191 |
|
| 192 | 192 |
///Add a new integer type option with a storage reference |
| 193 | 193 |
|
| 194 | 194 |
///Add a new integer type option with a storage reference. |
| 195 | 195 |
///\param name The name of the option. The leading '-' must be omitted. |
| 196 | 196 |
///\param help A help string. |
| 197 | 197 |
///\param obl Indicate if the option is mandatory. |
| 198 | 198 |
///\retval ref The value of the argument will be written to this variable. |
| 199 | 199 |
ArgParser &refOption(const std::string &name, |
| 200 |
const std::string &help, |
|
| 201 |
int &ref, bool obl=false); |
|
| 200 |
const std::string &help, |
|
| 201 |
int &ref, bool obl=false); |
|
| 202 | 202 |
|
| 203 | 203 |
///Add a new floating type option with a storage reference |
| 204 | 204 |
|
| 205 | 205 |
///Add a new floating type option with a storage reference. |
| 206 | 206 |
///\param name The name of the option. The leading '-' must be omitted. |
| 207 | 207 |
///\param help A help string. |
| 208 | 208 |
///\param obl Indicate if the option is mandatory. |
| 209 | 209 |
///\retval ref The value of the argument will be written to this variable. |
| 210 | 210 |
ArgParser &refOption(const std::string &name, |
| 211 |
const std::string &help, |
|
| 212 |
double &ref, bool obl=false); |
|
| 211 |
const std::string &help, |
|
| 212 |
double &ref, bool obl=false); |
|
| 213 | 213 |
|
| 214 | 214 |
///Add a new bool type option with a storage reference |
| 215 | 215 |
|
| 216 | 216 |
///Add a new bool type option with a storage reference. |
| 217 | 217 |
///\param name The name of the option. The leading '-' must be omitted. |
| 218 | 218 |
///\param help A help string. |
| 219 | 219 |
///\param obl Indicate if the option is mandatory. |
| 220 | 220 |
///\retval ref The value of the argument will be written to this variable. |
| 221 | 221 |
///\note A mandatory bool obtion is of very little use. |
| 222 | 222 |
ArgParser &refOption(const std::string &name, |
| 223 |
const std::string &help, |
|
| 224 |
bool &ref, bool obl=false); |
|
| 223 |
const std::string &help, |
|
| 224 |
bool &ref, bool obl=false); |
|
| 225 | 225 |
|
| 226 | 226 |
///Add a new string type option with a storage reference |
| 227 | 227 |
|
| 228 | 228 |
///Add a new string type option with a storage reference. |
| 229 | 229 |
///\param name The name of the option. The leading '-' must be omitted. |
| 230 | 230 |
///\param help A help string. |
| 231 | 231 |
///\param obl Indicate if the option is mandatory. |
| 232 | 232 |
///\retval ref The value of the argument will be written to this variable. |
| 233 | 233 |
ArgParser &refOption(const std::string &name, |
| 234 |
const std::string &help, |
|
| 235 |
std::string &ref, bool obl=false); |
|
| 236 |
|
|
| 234 |
const std::string &help, |
|
| 235 |
std::string &ref, bool obl=false); |
|
| 236 |
|
|
| 237 | 237 |
///@} |
| 238 | 238 |
|
| 239 | 239 |
///\name Option Groups and Synonyms |
| 240 | 240 |
/// |
| 241 |
|
|
| 241 |
|
|
| 242 | 242 |
///@{
|
| 243 | 243 |
|
| 244 | 244 |
///Bundle some options into a group |
| 245 | 245 |
|
| 246 | 246 |
/// You can group some option by calling this function repeatedly for each |
| 247 | 247 |
/// option to be grouped with the same groupname. |
| 248 | 248 |
///\param group The group name. |
| 249 | 249 |
///\param opt The option name. |
| 250 | 250 |
ArgParser &optionGroup(const std::string &group, |
| 251 |
|
|
| 251 |
const std::string &opt); |
|
| 252 | 252 |
|
| 253 | 253 |
///Make the members of a group exclusive |
| 254 | 254 |
|
| 255 | 255 |
///If you call this function for a group, than at most one of them can be |
| 256 | 256 |
///given at the same time. |
| 257 | 257 |
ArgParser &onlyOneGroup(const std::string &group); |
| 258 |
|
|
| 258 |
|
|
| 259 | 259 |
///Make a group mandatory |
| 260 | 260 |
|
| 261 | 261 |
///Using this function, at least one of the members of \c group |
| 262 | 262 |
///must be given. |
| 263 | 263 |
ArgParser &mandatoryGroup(const std::string &group); |
| 264 |
|
|
| 264 |
|
|
| 265 | 265 |
///Create synonym to an option |
| 266 | 266 |
|
| 267 | 267 |
///With this function you can create a synonym \c syn of the |
| 268 | 268 |
///option \c opt. |
| 269 | 269 |
ArgParser &synonym(const std::string &syn, |
| 270 |
const std::string &opt); |
|
| 271 |
|
|
| 270 |
const std::string &opt); |
|
| 271 |
|
|
| 272 | 272 |
///@} |
| 273 | 273 |
|
| 274 | 274 |
void show(std::ostream &os,Opts::iterator i); |
| 275 | 275 |
void show(std::ostream &os,Groups::iterator i); |
| 276 | 276 |
void showHelp(Opts::iterator i); |
| 277 | 277 |
void showHelp(std::vector<OtherArg>::iterator i); |
| 278 | 278 |
void shortHelp(); |
| 279 | 279 |
void showHelp(); |
| 280 | 280 |
|
| 281 | 281 |
void unknownOpt(std::string arg); |
| 282 | 282 |
|
| 283 | 283 |
void requiresValue(std::string arg, OptType t); |
| 284 | 284 |
void checkMandatories(); |
| 285 |
|
|
| 285 |
|
|
| 286 | 286 |
///Start the parsing process |
| 287 | 287 |
ArgParser &parse(); |
| 288 | 288 |
|
| 289 | 289 |
/// Synonym for parse() |
| 290 |
ArgParser &run() |
|
| 290 |
ArgParser &run() |
|
| 291 | 291 |
{
|
| 292 | 292 |
return parse(); |
| 293 | 293 |
} |
| 294 |
|
|
| 294 |
|
|
| 295 | 295 |
///Give back the command name (the 0th argument) |
| 296 | 296 |
const std::string &commandName() { return _command_name; }
|
| 297 | 297 |
|
| 298 | 298 |
///Check if an opion has been given to the command. |
| 299 |
bool given(std::string op) |
|
| 299 |
bool given(std::string op) |
|
| 300 | 300 |
{
|
| 301 | 301 |
Opts::iterator i = _opts.find(op); |
| 302 | 302 |
return i!=_opts.end()?i->second.set:false; |
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 | 305 |
|
| 306 | 306 |
///Magic type for operator[] |
| 307 |
|
|
| 307 |
|
|
| 308 | 308 |
///This is the type of the return value of ArgParser::operator[](). |
| 309 | 309 |
///It automatically converts to \c int, \c double, \c bool or |
| 310 | 310 |
///\c std::string if the type of the option matches, otherwise it |
| 311 | 311 |
///throws an exception (i.e. it performs runtime type checking). |
| 312 |
class RefType |
|
| 312 |
class RefType |
|
| 313 | 313 |
{
|
| 314 | 314 |
ArgParser &_parser; |
| 315 | 315 |
std::string _name; |
| 316 | 316 |
public: |
| 317 | 317 |
///\e |
| 318 | 318 |
RefType(ArgParser &p,const std::string &n) :_parser(p),_name(n) {}
|
| 319 | 319 |
///\e |
| 320 |
operator bool() |
|
| 320 |
operator bool() |
|
| 321 | 321 |
{
|
| 322 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 323 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 324 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 325 |
LEMON_ASSERT(i->second.type==ArgParser::BOOL, |
|
| 326 |
std::string()+"'"+_name+"' is a bool option"); |
|
| 327 |
return *(i->second.bool_p); |
|
| 322 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 323 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 324 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 325 |
LEMON_ASSERT(i->second.type==ArgParser::BOOL, |
|
| 326 |
std::string()+"'"+_name+"' is a bool option"); |
|
| 327 |
return *(i->second.bool_p); |
|
| 328 | 328 |
} |
| 329 | 329 |
///\e |
| 330 | 330 |
operator std::string() |
| 331 | 331 |
{
|
| 332 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 333 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 334 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 335 |
LEMON_ASSERT(i->second.type==ArgParser::STRING, |
|
| 336 |
std::string()+"'"+_name+"' is a string option"); |
|
| 337 |
return *(i->second.string_p); |
|
| 332 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 333 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 334 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 335 |
LEMON_ASSERT(i->second.type==ArgParser::STRING, |
|
| 336 |
std::string()+"'"+_name+"' is a string option"); |
|
| 337 |
return *(i->second.string_p); |
|
| 338 | 338 |
} |
| 339 | 339 |
///\e |
| 340 |
operator double() |
|
| 340 |
operator double() |
|
| 341 | 341 |
{
|
| 342 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 343 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 344 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 345 |
LEMON_ASSERT(i->second.type==ArgParser::DOUBLE || |
|
| 346 |
i->second.type==ArgParser::INTEGER, |
|
| 347 |
std::string()+"'"+_name+"' is a floating point option"); |
|
| 348 |
return i->second.type==ArgParser::DOUBLE ? |
|
| 349 |
*(i->second.double_p) : *(i->second.int_p); |
|
| 342 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 343 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 344 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 345 |
LEMON_ASSERT(i->second.type==ArgParser::DOUBLE || |
|
| 346 |
i->second.type==ArgParser::INTEGER, |
|
| 347 |
std::string()+"'"+_name+"' is a floating point option"); |
|
| 348 |
return i->second.type==ArgParser::DOUBLE ? |
|
| 349 |
*(i->second.double_p) : *(i->second.int_p); |
|
| 350 | 350 |
} |
| 351 | 351 |
///\e |
| 352 |
operator int() |
|
| 352 |
operator int() |
|
| 353 | 353 |
{
|
| 354 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 355 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 356 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 357 |
LEMON_ASSERT(i->second.type==ArgParser::INTEGER, |
|
| 358 |
std::string()+"'"+_name+"' is an integer option"); |
|
| 359 |
return *(i->second.int_p); |
|
| 354 |
Opts::iterator i = _parser._opts.find(_name); |
|
| 355 |
LEMON_ASSERT(i!=_parser._opts.end(), |
|
| 356 |
std::string()+"Unkown option: '"+_name+"'"); |
|
| 357 |
LEMON_ASSERT(i->second.type==ArgParser::INTEGER, |
|
| 358 |
std::string()+"'"+_name+"' is an integer option"); |
|
| 359 |
return *(i->second.int_p); |
|
| 360 | 360 |
} |
| 361 | 361 |
|
| 362 | 362 |
}; |
| 363 | 363 |
|
| 364 | 364 |
///Give back the value of an option |
| 365 |
|
|
| 365 |
|
|
| 366 | 366 |
///Give back the value of an option. |
| 367 | 367 |
///\sa RefType |
| 368 | 368 |
RefType operator[](const std::string &n) |
| 369 | 369 |
{
|
| 370 | 370 |
return RefType(*this, n); |
| 371 |
} |
|
| 371 |
} |
|
| 372 | 372 |
|
| 373 | 373 |
///Give back the non-option type arguments. |
| 374 | 374 |
|
| 375 | 375 |
///Give back a reference to a vector consisting of the program arguments |
| 376 | 376 |
///not starting with a '-' character. |
| 377 | 377 |
std::vector<std::string> &files() { return _file_args; }
|
| 378 |
|
|
| 378 |
|
|
| 379 | 379 |
}; |
| 380 | 380 |
} |
| 381 | 381 |
|
| 382 | 382 |
#endif // LEMON_ARG_PARSER |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_ASSERT_H |
| 20 | 20 |
#define LEMON_ASSERT_H |
| 21 | 21 |
|
| 22 | 22 |
/// \ingroup exceptions |
| 23 | 23 |
/// \file |
| 24 | 24 |
/// \brief Extended assertion handling |
| 25 | 25 |
|
| 26 | 26 |
#include <lemon/error.h> |
| 27 | 27 |
|
| 28 | 28 |
namespace lemon {
|
| 29 | 29 |
|
| 30 | 30 |
inline void assert_fail_log(const char *file, int line, const char *function, |
| 31 |
|
|
| 31 |
const char *message, const char *assertion) |
|
| 32 | 32 |
{
|
| 33 | 33 |
std::cerr << file << ":" << line << ": "; |
| 34 | 34 |
if (function) |
| 35 | 35 |
std::cerr << function << ": "; |
| 36 | 36 |
std::cerr << message; |
| 37 | 37 |
if (assertion) |
| 38 | 38 |
std::cerr << " (assertion '" << assertion << "' failed)"; |
| 39 | 39 |
std::cerr << std::endl; |
| 40 | 40 |
} |
| 41 | 41 |
|
| 42 | 42 |
inline void assert_fail_abort(const char *file, int line, |
| 43 |
const char *function, const char* message, |
|
| 44 |
const char *assertion) |
|
| 43 |
const char *function, const char* message, |
|
| 44 |
const char *assertion) |
|
| 45 | 45 |
{
|
| 46 | 46 |
assert_fail_log(file, line, function, message, assertion); |
| 47 | 47 |
std::abort(); |
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 | 50 |
namespace _assert_bits {
|
| 51 |
|
|
| 52 |
|
|
| 51 |
|
|
| 52 |
|
|
| 53 | 53 |
inline const char* cstringify(const std::string& str) {
|
| 54 | 54 |
return str.c_str(); |
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
inline const char* cstringify(const char* str) {
|
| 58 | 58 |
return str; |
| 59 |
} |
|
| 59 |
} |
|
| 60 | 60 |
} |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
#endif // LEMON_ASSERT_H |
| 64 | 64 |
|
| 65 | 65 |
#undef LEMON_ASSERT |
| 66 | 66 |
#undef LEMON_FIXME |
| 67 | 67 |
#undef LEMON_DEBUG |
| 68 | 68 |
|
| 69 |
#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
|
| 70 |
(defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
|
| 69 |
#if (defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
|
| 70 |
(defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
|
| 71 | 71 |
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) > 1 |
| 72 | 72 |
#error "LEMON assertion system is not set properly" |
| 73 | 73 |
#endif |
| 74 | 74 |
|
| 75 |
#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
|
| 76 |
(defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
|
| 77 |
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ |
|
| 78 |
defined(LEMON_ENABLE_ASSERTS)) && \ |
|
| 79 |
|
|
| 75 |
#if ((defined(LEMON_ASSERT_LOG) ? 1 : 0) + \ |
|
| 76 |
(defined(LEMON_ASSERT_ABORT) ? 1 : 0) + \ |
|
| 77 |
(defined(LEMON_ASSERT_CUSTOM) ? 1 : 0) == 1 || \ |
|
| 78 |
defined(LEMON_ENABLE_ASSERTS)) && \ |
|
| 79 |
(defined(LEMON_DISABLE_ASSERTS) || \ |
|
| 80 | 80 |
defined(NDEBUG)) |
| 81 | 81 |
#error "LEMON assertion system is not set properly" |
| 82 | 82 |
#endif |
| 83 | 83 |
|
| 84 | 84 |
|
| 85 | 85 |
#if defined LEMON_ASSERT_LOG |
| 86 | 86 |
# undef LEMON_ASSERT_HANDLER |
| 87 | 87 |
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_log |
| 88 | 88 |
#elif defined LEMON_ASSERT_ABORT |
| 89 | 89 |
# undef LEMON_ASSERT_HANDLER |
| 90 | 90 |
# define LEMON_ASSERT_HANDLER ::lemon::assert_fail_abort |
| 91 | 91 |
#elif defined LEMON_ASSERT_CUSTOM |
| 92 | 92 |
# undef LEMON_ASSERT_HANDLER |
| 93 | 93 |
# ifndef LEMON_CUSTOM_ASSERT_HANDLER |
| 94 | 94 |
# error "LEMON_CUSTOM_ASSERT_HANDLER is not set" |
| 95 | 95 |
# endif |
| ... | ... |
@@ -123,138 +123,138 @@ |
| 123 | 123 |
/// false, then an assertion is raised. The concrete behaviour depends |
| 124 | 124 |
/// on the settings of the assertion system. \param msg A <tt>const |
| 125 | 125 |
/// char*</tt> parameter, which can be used to provide information |
| 126 | 126 |
/// about the circumstances of the failed assertion. |
| 127 | 127 |
/// |
| 128 | 128 |
/// The assertions are enabled in the default behaviour. |
| 129 | 129 |
/// You can disable them with the following code: |
| 130 | 130 |
/// \code |
| 131 | 131 |
/// #define LEMON_DISABLE_ASSERTS |
| 132 | 132 |
/// \endcode |
| 133 | 133 |
/// or with compilation parameters: |
| 134 | 134 |
/// \code |
| 135 | 135 |
/// g++ -DLEMON_DISABLE_ASSERTS |
| 136 | 136 |
/// make CXXFLAGS='-DLEMON_DISABLE_ASSERTS' |
| 137 | 137 |
/// \endcode |
| 138 | 138 |
/// The checking is also disabled when the standard macro \c NDEBUG is defined. |
| 139 |
/// |
|
| 139 |
/// |
|
| 140 | 140 |
/// The LEMON assertion system has a wide range of customization |
| 141 | 141 |
/// properties. As a default behaviour the failed assertion prints a |
| 142 | 142 |
/// short log message to the standard error and aborts the execution. |
| 143 | 143 |
/// |
| 144 |
/// The following modes can be used in the assertion system: |
|
| 144 |
/// The following modes can be used in the assertion system: |
|
| 145 | 145 |
/// |
| 146 | 146 |
/// - \c LEMON_ASSERT_LOG The failed assertion prints a short log |
| 147 | 147 |
/// message to the standard error and continues the execution. |
| 148 | 148 |
/// - \c LEMON_ASSERT_ABORT This mode is similar to the \c |
| 149 | 149 |
/// LEMON_ASSERT_LOG, but it aborts the program. It is the default |
| 150 | 150 |
/// behaviour. |
| 151 | 151 |
/// - \c LEMON_ASSERT_CUSTOM The user can define own assertion handler |
| 152 | 152 |
/// function. |
| 153 | 153 |
/// \code |
| 154 | 154 |
/// void custom_assert_handler(const char* file, int line, const char* function, |
| 155 | 155 |
/// const char* message, const char* assertion); |
| 156 | 156 |
/// \endcode |
| 157 | 157 |
/// The name of the function should be defined as the \c |
| 158 |
/// LEMON_CUSTOM_ASSERT_HANDLER macro name. |
|
| 158 |
/// LEMON_CUSTOM_ASSERT_HANDLER macro name. |
|
| 159 | 159 |
/// \code |
| 160 | 160 |
/// #define LEMON_CUSTOM_ASSERT_HANDLER custom_assert_handler |
| 161 | 161 |
/// \endcode |
| 162 | 162 |
/// Whenever an assertion is occured, the custom assertion |
| 163 | 163 |
/// handler is called with appropiate parameters. |
| 164 | 164 |
/// |
| 165 | 165 |
/// The assertion mode can also be changed within one compilation unit. |
| 166 | 166 |
/// If the macros are redefined with other settings and the |
| 167 | 167 |
/// \ref lemon/assert.h "assert.h" file is reincluded, then the |
| 168 | 168 |
/// behaviour is changed appropiately to the new settings. |
| 169 |
# define LEMON_ASSERT(exp, msg) \ |
|
| 170 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
| 171 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
| 172 |
LEMON_FUNCTION_NAME, \ |
|
| 173 |
|
|
| 169 |
# define LEMON_ASSERT(exp, msg) \ |
|
| 170 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
| 171 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
|
| 172 |
LEMON_FUNCTION_NAME, \ |
|
| 173 |
::lemon::_assert_bits::cstringify(msg), #exp), 0))) |
|
| 174 | 174 |
|
| 175 | 175 |
/// \ingroup exceptions |
| 176 | 176 |
/// |
| 177 | 177 |
/// \brief Macro for mark not yet implemented features. |
| 178 | 178 |
/// |
| 179 | 179 |
/// Macro for mark not yet implemented features and outstanding bugs. |
| 180 | 180 |
/// It is close to be the shortcut of the following code: |
| 181 | 181 |
/// \code |
| 182 | 182 |
/// LEMON_ASSERT(false, msg); |
| 183 | 183 |
/// \endcode |
| 184 | 184 |
/// |
| 185 |
/// \see LEMON_ASSERT |
|
| 186 |
# define LEMON_FIXME(msg) \ |
|
| 187 |
(LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
|
| 188 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 189 |
|
|
| 185 |
/// \see LEMON_ASSERT |
|
| 186 |
# define LEMON_FIXME(msg) \ |
|
| 187 |
(LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
|
| 188 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 189 |
static_cast<const char*>(0))) |
|
| 190 | 190 |
|
| 191 | 191 |
/// \ingroup exceptions |
| 192 | 192 |
/// |
| 193 | 193 |
/// \brief Macro for internal assertions |
| 194 | 194 |
/// |
| 195 | 195 |
/// Macro for internal assertions, it is used in the library to check |
| 196 | 196 |
/// the consistency of results of algorithms, several pre- and |
| 197 | 197 |
/// postconditions and invariants. The checking is disabled by |
| 198 | 198 |
/// default, but it can be turned on with the macro \c |
| 199 | 199 |
/// LEMON_ENABLE_DEBUG. |
| 200 | 200 |
/// \code |
| 201 | 201 |
/// #define LEMON_ENABLE_DEBUG |
| 202 | 202 |
/// \endcode |
| 203 | 203 |
/// or with compilation parameters: |
| 204 | 204 |
/// \code |
| 205 | 205 |
/// g++ -DLEMON_ENABLE_DEBUG |
| 206 | 206 |
/// make CXXFLAGS='-DLEMON_ENABLE_DEBUG' |
| 207 | 207 |
/// \endcode |
| 208 | 208 |
/// |
| 209 | 209 |
/// This macro works like the \c LEMON_ASSERT macro, therefore the |
| 210 | 210 |
/// current behaviour depends on the settings of \c LEMON_ASSERT |
| 211 | 211 |
/// macro. |
| 212 | 212 |
/// |
| 213 |
/// \see LEMON_ASSERT |
|
| 214 |
# define LEMON_DEBUG(exp, msg) \ |
|
| 215 |
|
|
| 213 |
/// \see LEMON_ASSERT |
|
| 214 |
# define LEMON_DEBUG(exp, msg) \ |
|
| 215 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
| 216 | 216 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
| 217 |
LEMON_FUNCTION_NAME, \ |
|
| 218 |
::lemon::_assert_bits::cstringify(msg), #exp), 0))) |
|
| 217 |
LEMON_FUNCTION_NAME, \ |
|
| 218 |
::lemon::_assert_bits::cstringify(msg), #exp), 0))) |
|
| 219 | 219 |
|
| 220 | 220 |
#else |
| 221 | 221 |
|
| 222 | 222 |
# ifndef LEMON_ASSERT_HANDLER |
| 223 | 223 |
# define LEMON_ASSERT(exp, msg) (static_cast<void>(0)) |
| 224 | 224 |
# define LEMON_FIXME(msg) (static_cast<void>(0)) |
| 225 | 225 |
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0)) |
| 226 | 226 |
# else |
| 227 |
# define LEMON_ASSERT(exp, msg) \ |
|
| 228 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
| 227 |
# define LEMON_ASSERT(exp, msg) \ |
|
| 228 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
|
| 229 | 229 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
| 230 |
LEMON_FUNCTION_NAME, \ |
|
| 231 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 232 |
#exp), 0))) |
|
| 233 |
# define LEMON_FIXME(msg) \ |
|
| 234 |
(LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
|
| 235 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 236 |
|
|
| 230 |
LEMON_FUNCTION_NAME, \ |
|
| 231 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 232 |
#exp), 0))) |
|
| 233 |
# define LEMON_FIXME(msg) \ |
|
| 234 |
(LEMON_ASSERT_HANDLER(__FILE__, __LINE__, LEMON_FUNCTION_NAME, \ |
|
| 235 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 236 |
static_cast<const char*>(0))) |
|
| 237 | 237 |
|
| 238 | 238 |
# if LEMON_ENABLE_DEBUG |
| 239 | 239 |
# define LEMON_DEBUG(exp, msg) |
| 240 | 240 |
(static_cast<void> (!!(exp) ? 0 : ( \ |
| 241 | 241 |
LEMON_ASSERT_HANDLER(__FILE__, __LINE__, \ |
| 242 | 242 |
LEMON_FUNCTION_NAME, \ |
| 243 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 244 |
#exp), 0))) |
|
| 243 |
::lemon::_assert_bits::cstringify(msg), \ |
|
| 244 |
#exp), 0))) |
|
| 245 | 245 |
# else |
| 246 | 246 |
# define LEMON_DEBUG(exp, msg) (static_cast<void>(0)) |
| 247 | 247 |
# endif |
| 248 | 248 |
# endif |
| 249 | 249 |
|
| 250 | 250 |
#endif |
| 251 | 251 |
|
| 252 | 252 |
#ifdef DOXYGEN |
| 253 | 253 |
|
| 254 | 254 |
|
| 255 | 255 |
#else |
| 256 | 256 |
|
| 257 | 257 |
|
| 258 | 258 |
#endif |
| 259 | 259 |
|
| 260 | 260 |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
///\file |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BFS_H |
| 20 | 20 |
#define LEMON_BFS_H |
| 21 | 21 |
|
| 22 | 22 |
///\ingroup search |
| 23 | 23 |
///\file |
| 24 | 24 |
///\brief Bfs algorithm. |
| 25 | 25 |
|
| 26 | 26 |
#include <lemon/list_graph.h> |
| 27 | 27 |
#include <lemon/graph_utils.h> |
| 28 | 28 |
#include <lemon/bits/path_dump.h> |
| 29 | 29 |
#include <lemon/bits/invalid.h> |
| 30 | 30 |
#include <lemon/error.h> |
| 31 | 31 |
#include <lemon/maps.h> |
| 32 | 32 |
|
| 33 | 33 |
namespace lemon {
|
| 34 | 34 |
|
| 35 | 35 |
|
| 36 |
|
|
| 36 |
|
|
| 37 | 37 |
///Default traits class of Bfs class. |
| 38 | 38 |
|
| 39 | 39 |
///Default traits class of Bfs class. |
| 40 | 40 |
///\tparam GR Digraph type. |
| 41 | 41 |
template<class GR> |
| 42 | 42 |
struct BfsDefaultTraits |
| 43 | 43 |
{
|
| 44 |
///The digraph type the algorithm runs on. |
|
| 44 |
///The digraph type the algorithm runs on. |
|
| 45 | 45 |
typedef GR Digraph; |
| 46 | 46 |
///\brief The type of the map that stores the last |
| 47 | 47 |
///arcs of the shortest paths. |
| 48 |
/// |
|
| 48 |
/// |
|
| 49 | 49 |
///The type of the map that stores the last |
| 50 | 50 |
///arcs of the shortest paths. |
| 51 | 51 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 52 | 52 |
/// |
| 53 | 53 |
typedef typename Digraph::template NodeMap<typename GR::Arc> PredMap; |
| 54 | 54 |
///Instantiates a PredMap. |
| 55 |
|
|
| 56 |
///This function instantiates a \ref PredMap. |
|
| 55 |
|
|
| 56 |
///This function instantiates a \ref PredMap. |
|
| 57 | 57 |
///\param G is the digraph, to which we would like to define the PredMap. |
| 58 | 58 |
///\todo The digraph alone may be insufficient to initialize |
| 59 |
static PredMap *createPredMap(const GR &G) |
|
| 59 |
static PredMap *createPredMap(const GR &G) |
|
| 60 | 60 |
{
|
| 61 | 61 |
return new PredMap(G); |
| 62 | 62 |
} |
| 63 | 63 |
///The type of the map that indicates which nodes are processed. |
| 64 |
|
|
| 64 |
|
|
| 65 | 65 |
///The type of the map that indicates which nodes are processed. |
| 66 | 66 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 67 | 67 |
///\todo named parameter to set this type, function to read and write. |
| 68 | 68 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 69 | 69 |
///Instantiates a ProcessedMap. |
| 70 |
|
|
| 71 |
///This function instantiates a \ref ProcessedMap. |
|
| 70 |
|
|
| 71 |
///This function instantiates a \ref ProcessedMap. |
|
| 72 | 72 |
///\param g is the digraph, to which |
| 73 | 73 |
///we would like to define the \ref ProcessedMap |
| 74 | 74 |
#ifdef DOXYGEN |
| 75 | 75 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 76 | 76 |
#else |
| 77 | 77 |
static ProcessedMap *createProcessedMap(const GR &) |
| 78 | 78 |
#endif |
| 79 | 79 |
{
|
| 80 | 80 |
return new ProcessedMap(); |
| 81 | 81 |
} |
| 82 | 82 |
///The type of the map that indicates which nodes are reached. |
| 83 |
|
|
| 83 |
|
|
| 84 | 84 |
///The type of the map that indicates which nodes are reached. |
| 85 | 85 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 86 | 86 |
///\todo named parameter to set this type, function to read and write. |
| 87 | 87 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 88 | 88 |
///Instantiates a ReachedMap. |
| 89 |
|
|
| 90 |
///This function instantiates a \ref ReachedMap. |
|
| 89 |
|
|
| 90 |
///This function instantiates a \ref ReachedMap. |
|
| 91 | 91 |
///\param G is the digraph, to which |
| 92 | 92 |
///we would like to define the \ref ReachedMap. |
| 93 | 93 |
static ReachedMap *createReachedMap(const GR &G) |
| 94 | 94 |
{
|
| 95 | 95 |
return new ReachedMap(G); |
| 96 | 96 |
} |
| 97 | 97 |
///The type of the map that stores the dists of the nodes. |
| 98 |
|
|
| 98 |
|
|
| 99 | 99 |
///The type of the map that stores the dists of the nodes. |
| 100 | 100 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 101 | 101 |
/// |
| 102 | 102 |
typedef typename Digraph::template NodeMap<int> DistMap; |
| 103 | 103 |
///Instantiates a DistMap. |
| 104 |
|
|
| 105 |
///This function instantiates a \ref DistMap. |
|
| 104 |
|
|
| 105 |
///This function instantiates a \ref DistMap. |
|
| 106 | 106 |
///\param G is the digraph, to which we would like to define the \ref DistMap |
| 107 | 107 |
static DistMap *createDistMap(const GR &G) |
| 108 | 108 |
{
|
| 109 | 109 |
return new DistMap(G); |
| 110 | 110 |
} |
| 111 | 111 |
}; |
| 112 |
|
|
| 112 |
|
|
| 113 | 113 |
///%BFS algorithm class. |
| 114 |
|
|
| 114 |
|
|
| 115 | 115 |
///\ingroup search |
| 116 | 116 |
///This class provides an efficient implementation of the %BFS algorithm. |
| 117 | 117 |
/// |
| 118 | 118 |
///\tparam GR The digraph type the algorithm runs on. The default value is |
| 119 | 119 |
///\ref ListDigraph. The value of GR is not used directly by Bfs, it |
| 120 | 120 |
///is only passed to \ref BfsDefaultTraits. |
| 121 | 121 |
///\tparam TR Traits class to set various data types used by the algorithm. |
| 122 | 122 |
///The default traits class is |
| 123 | 123 |
///\ref BfsDefaultTraits "BfsDefaultTraits<GR>". |
| 124 | 124 |
///See \ref BfsDefaultTraits for the documentation of |
| 125 | 125 |
///a Bfs traits class. |
| 126 | 126 |
|
| 127 | 127 |
#ifdef DOXYGEN |
| 128 | 128 |
template <typename GR, |
| 129 |
|
|
| 129 |
typename TR> |
|
| 130 | 130 |
#else |
| 131 | 131 |
template <typename GR=ListDigraph, |
| 132 |
|
|
| 132 |
typename TR=BfsDefaultTraits<GR> > |
|
| 133 | 133 |
#endif |
| 134 | 134 |
class Bfs {
|
| 135 | 135 |
public: |
| 136 | 136 |
/** |
| 137 | 137 |
* \brief \ref Exception for uninitialized parameters. |
| 138 | 138 |
* |
| 139 | 139 |
* This error represents problems in the initialization |
| 140 | 140 |
* of the parameters of the algorithms. |
| 141 | 141 |
*/ |
| 142 | 142 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
| 143 | 143 |
public: |
| 144 | 144 |
virtual const char* what() const throw() {
|
| 145 |
|
|
| 145 |
return "lemon::Bfs::UninitializedParameter"; |
|
| 146 | 146 |
} |
| 147 | 147 |
}; |
| 148 | 148 |
|
| 149 | 149 |
typedef TR Traits; |
| 150 | 150 |
///The type of the underlying digraph. |
| 151 | 151 |
typedef typename TR::Digraph Digraph; |
| 152 |
|
|
| 152 |
|
|
| 153 | 153 |
///\brief The type of the map that stores the last |
| 154 | 154 |
///arcs of the shortest paths. |
| 155 | 155 |
typedef typename TR::PredMap PredMap; |
| 156 | 156 |
///The type of the map indicating which nodes are reached. |
| 157 | 157 |
typedef typename TR::ReachedMap ReachedMap; |
| 158 | 158 |
///The type of the map indicating which nodes are processed. |
| 159 | 159 |
typedef typename TR::ProcessedMap ProcessedMap; |
| 160 | 160 |
///The type of the map that stores the dists of the nodes. |
| 161 | 161 |
typedef typename TR::DistMap DistMap; |
| 162 | 162 |
private: |
| 163 | 163 |
|
| 164 | 164 |
typedef typename Digraph::Node Node; |
| 165 | 165 |
typedef typename Digraph::NodeIt NodeIt; |
| 166 | 166 |
typedef typename Digraph::Arc Arc; |
| 167 | 167 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 168 | 168 |
|
| ... | ... |
@@ -177,526 +177,526 @@ |
| 177 | 177 |
///Indicates if \ref _dist is locally allocated (\c true) or not. |
| 178 | 178 |
bool local_dist; |
| 179 | 179 |
///Pointer to the map of reached status of the nodes. |
| 180 | 180 |
ReachedMap *_reached; |
| 181 | 181 |
///Indicates if \ref _reached is locally allocated (\c true) or not. |
| 182 | 182 |
bool local_reached; |
| 183 | 183 |
///Pointer to the map of processed status of the nodes. |
| 184 | 184 |
ProcessedMap *_processed; |
| 185 | 185 |
///Indicates if \ref _processed is locally allocated (\c true) or not. |
| 186 | 186 |
bool local_processed; |
| 187 | 187 |
|
| 188 | 188 |
std::vector<typename Digraph::Node> _queue; |
| 189 | 189 |
int _queue_head,_queue_tail,_queue_next_dist; |
| 190 | 190 |
int _curr_dist; |
| 191 | 191 |
|
| 192 | 192 |
///Creates the maps if necessary. |
| 193 |
|
|
| 193 |
|
|
| 194 | 194 |
///\todo Better memory allocation (instead of new). |
| 195 |
void create_maps() |
|
| 195 |
void create_maps() |
|
| 196 | 196 |
{
|
| 197 | 197 |
if(!_pred) {
|
| 198 |
local_pred = true; |
|
| 199 |
_pred = Traits::createPredMap(*G); |
|
| 198 |
local_pred = true; |
|
| 199 |
_pred = Traits::createPredMap(*G); |
|
| 200 | 200 |
} |
| 201 | 201 |
if(!_dist) {
|
| 202 |
local_dist = true; |
|
| 203 |
_dist = Traits::createDistMap(*G); |
|
| 202 |
local_dist = true; |
|
| 203 |
_dist = Traits::createDistMap(*G); |
|
| 204 | 204 |
} |
| 205 | 205 |
if(!_reached) {
|
| 206 |
local_reached = true; |
|
| 207 |
_reached = Traits::createReachedMap(*G); |
|
| 206 |
local_reached = true; |
|
| 207 |
_reached = Traits::createReachedMap(*G); |
|
| 208 | 208 |
} |
| 209 | 209 |
if(!_processed) {
|
| 210 |
local_processed = true; |
|
| 211 |
_processed = Traits::createProcessedMap(*G); |
|
| 210 |
local_processed = true; |
|
| 211 |
_processed = Traits::createProcessedMap(*G); |
|
| 212 | 212 |
} |
| 213 | 213 |
} |
| 214 | 214 |
|
| 215 | 215 |
protected: |
| 216 |
|
|
| 216 |
|
|
| 217 | 217 |
Bfs() {}
|
| 218 |
|
|
| 218 |
|
|
| 219 | 219 |
public: |
| 220 |
|
|
| 220 |
|
|
| 221 | 221 |
typedef Bfs Create; |
| 222 | 222 |
|
| 223 | 223 |
///\name Named template parameters |
| 224 | 224 |
|
| 225 | 225 |
///@{
|
| 226 | 226 |
|
| 227 | 227 |
template <class T> |
| 228 | 228 |
struct DefPredMapTraits : public Traits {
|
| 229 | 229 |
typedef T PredMap; |
| 230 |
static PredMap *createPredMap(const Digraph &) |
|
| 230 |
static PredMap *createPredMap(const Digraph &) |
|
| 231 | 231 |
{
|
| 232 |
|
|
| 232 |
throw UninitializedParameter(); |
|
| 233 | 233 |
} |
| 234 | 234 |
}; |
| 235 | 235 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 236 | 236 |
///PredMap type |
| 237 | 237 |
/// |
| 238 | 238 |
///\ref named-templ-param "Named parameter" for setting PredMap type |
| 239 | 239 |
/// |
| 240 | 240 |
template <class T> |
| 241 |
struct DefPredMap : public Bfs< Digraph, DefPredMapTraits<T> > {
|
|
| 241 |
struct DefPredMap : public Bfs< Digraph, DefPredMapTraits<T> > {
|
|
| 242 | 242 |
typedef Bfs< Digraph, DefPredMapTraits<T> > Create; |
| 243 | 243 |
}; |
| 244 |
|
|
| 244 |
|
|
| 245 | 245 |
template <class T> |
| 246 | 246 |
struct DefDistMapTraits : public Traits {
|
| 247 | 247 |
typedef T DistMap; |
| 248 |
static DistMap *createDistMap(const Digraph &) |
|
| 248 |
static DistMap *createDistMap(const Digraph &) |
|
| 249 | 249 |
{
|
| 250 |
|
|
| 250 |
throw UninitializedParameter(); |
|
| 251 | 251 |
} |
| 252 | 252 |
}; |
| 253 | 253 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 254 | 254 |
///DistMap type |
| 255 | 255 |
/// |
| 256 | 256 |
///\ref named-templ-param "Named parameter" for setting DistMap type |
| 257 | 257 |
/// |
| 258 | 258 |
template <class T> |
| 259 |
struct DefDistMap : public Bfs< Digraph, DefDistMapTraits<T> > {
|
|
| 259 |
struct DefDistMap : public Bfs< Digraph, DefDistMapTraits<T> > {
|
|
| 260 | 260 |
typedef Bfs< Digraph, DefDistMapTraits<T> > Create; |
| 261 | 261 |
}; |
| 262 |
|
|
| 262 |
|
|
| 263 | 263 |
template <class T> |
| 264 | 264 |
struct DefReachedMapTraits : public Traits {
|
| 265 | 265 |
typedef T ReachedMap; |
| 266 |
static ReachedMap *createReachedMap(const Digraph &) |
|
| 266 |
static ReachedMap *createReachedMap(const Digraph &) |
|
| 267 | 267 |
{
|
| 268 |
|
|
| 268 |
throw UninitializedParameter(); |
|
| 269 | 269 |
} |
| 270 | 270 |
}; |
| 271 | 271 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 272 | 272 |
///ReachedMap type |
| 273 | 273 |
/// |
| 274 | 274 |
///\ref named-templ-param "Named parameter" for setting ReachedMap type |
| 275 | 275 |
/// |
| 276 | 276 |
template <class T> |
| 277 |
struct DefReachedMap : public Bfs< Digraph, DefReachedMapTraits<T> > {
|
|
| 277 |
struct DefReachedMap : public Bfs< Digraph, DefReachedMapTraits<T> > {
|
|
| 278 | 278 |
typedef Bfs< Digraph, DefReachedMapTraits<T> > Create; |
| 279 | 279 |
}; |
| 280 |
|
|
| 280 |
|
|
| 281 | 281 |
template <class T> |
| 282 | 282 |
struct DefProcessedMapTraits : public Traits {
|
| 283 | 283 |
typedef T ProcessedMap; |
| 284 |
static ProcessedMap *createProcessedMap(const Digraph &) |
|
| 284 |
static ProcessedMap *createProcessedMap(const Digraph &) |
|
| 285 | 285 |
{
|
| 286 |
|
|
| 286 |
throw UninitializedParameter(); |
|
| 287 | 287 |
} |
| 288 | 288 |
}; |
| 289 | 289 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 290 | 290 |
///ProcessedMap type |
| 291 | 291 |
/// |
| 292 | 292 |
///\ref named-templ-param "Named parameter" for setting ProcessedMap type |
| 293 | 293 |
/// |
| 294 | 294 |
template <class T> |
| 295 | 295 |
struct DefProcessedMap : public Bfs< Digraph, DefProcessedMapTraits<T> > {
|
| 296 | 296 |
typedef Bfs< Digraph, DefProcessedMapTraits<T> > Create; |
| 297 | 297 |
}; |
| 298 |
|
|
| 298 |
|
|
| 299 | 299 |
struct DefDigraphProcessedMapTraits : public Traits {
|
| 300 | 300 |
typedef typename Digraph::template NodeMap<bool> ProcessedMap; |
| 301 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 301 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 302 | 302 |
{
|
| 303 |
|
|
| 303 |
return new ProcessedMap(G); |
|
| 304 | 304 |
} |
| 305 | 305 |
}; |
| 306 | 306 |
///\brief \ref named-templ-param "Named parameter" |
| 307 | 307 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 308 | 308 |
/// |
| 309 | 309 |
///\ref named-templ-param "Named parameter" |
| 310 | 310 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 311 | 311 |
///If you don't set it explicitly, it will be automatically allocated. |
| 312 | 312 |
template <class T> |
| 313 | 313 |
struct DefProcessedMapToBeDefaultMap : |
| 314 |
public Bfs< Digraph, DefDigraphProcessedMapTraits> {
|
|
| 314 |
public Bfs< Digraph, DefDigraphProcessedMapTraits> {
|
|
| 315 | 315 |
typedef Bfs< Digraph, DefDigraphProcessedMapTraits> Create; |
| 316 | 316 |
}; |
| 317 |
|
|
| 317 |
|
|
| 318 | 318 |
///@} |
| 319 | 319 |
|
| 320 |
public: |
|
| 321 |
|
|
| 320 |
public: |
|
| 321 |
|
|
| 322 | 322 |
///Constructor. |
| 323 |
|
|
| 323 |
|
|
| 324 | 324 |
///\param _G the digraph the algorithm will run on. |
| 325 | 325 |
/// |
| 326 | 326 |
Bfs(const Digraph& _G) : |
| 327 | 327 |
G(&_G), |
| 328 | 328 |
_pred(NULL), local_pred(false), |
| 329 | 329 |
_dist(NULL), local_dist(false), |
| 330 | 330 |
_reached(NULL), local_reached(false), |
| 331 | 331 |
_processed(NULL), local_processed(false) |
| 332 | 332 |
{ }
|
| 333 |
|
|
| 333 |
|
|
| 334 | 334 |
///Destructor. |
| 335 |
~Bfs() |
|
| 335 |
~Bfs() |
|
| 336 | 336 |
{
|
| 337 | 337 |
if(local_pred) delete _pred; |
| 338 | 338 |
if(local_dist) delete _dist; |
| 339 | 339 |
if(local_reached) delete _reached; |
| 340 | 340 |
if(local_processed) delete _processed; |
| 341 | 341 |
} |
| 342 | 342 |
|
| 343 | 343 |
///Sets the map storing the predecessor arcs. |
| 344 | 344 |
|
| 345 | 345 |
///Sets the map storing the predecessor arcs. |
| 346 | 346 |
///If you don't use this function before calling \ref run(), |
| 347 | 347 |
///it will allocate one. The destructor deallocates this |
| 348 | 348 |
///automatically allocated map, of course. |
| 349 | 349 |
///\return <tt> (*this) </tt> |
| 350 |
Bfs &predMap(PredMap &m) |
|
| 350 |
Bfs &predMap(PredMap &m) |
|
| 351 | 351 |
{
|
| 352 | 352 |
if(local_pred) {
|
| 353 |
delete _pred; |
|
| 354 |
local_pred=false; |
|
| 353 |
delete _pred; |
|
| 354 |
local_pred=false; |
|
| 355 | 355 |
} |
| 356 | 356 |
_pred = &m; |
| 357 | 357 |
return *this; |
| 358 | 358 |
} |
| 359 | 359 |
|
| 360 | 360 |
///Sets the map indicating the reached nodes. |
| 361 | 361 |
|
| 362 | 362 |
///Sets the map indicating the reached nodes. |
| 363 | 363 |
///If you don't use this function before calling \ref run(), |
| 364 | 364 |
///it will allocate one. The destructor deallocates this |
| 365 | 365 |
///automatically allocated map, of course. |
| 366 | 366 |
///\return <tt> (*this) </tt> |
| 367 |
Bfs &reachedMap(ReachedMap &m) |
|
| 367 |
Bfs &reachedMap(ReachedMap &m) |
|
| 368 | 368 |
{
|
| 369 | 369 |
if(local_reached) {
|
| 370 |
delete _reached; |
|
| 371 |
local_reached=false; |
|
| 370 |
delete _reached; |
|
| 371 |
local_reached=false; |
|
| 372 | 372 |
} |
| 373 | 373 |
_reached = &m; |
| 374 | 374 |
return *this; |
| 375 | 375 |
} |
| 376 | 376 |
|
| 377 | 377 |
///Sets the map indicating the processed nodes. |
| 378 | 378 |
|
| 379 | 379 |
///Sets the map indicating the processed nodes. |
| 380 | 380 |
///If you don't use this function before calling \ref run(), |
| 381 | 381 |
///it will allocate one. The destructor deallocates this |
| 382 | 382 |
///automatically allocated map, of course. |
| 383 | 383 |
///\return <tt> (*this) </tt> |
| 384 |
Bfs &processedMap(ProcessedMap &m) |
|
| 384 |
Bfs &processedMap(ProcessedMap &m) |
|
| 385 | 385 |
{
|
| 386 | 386 |
if(local_processed) {
|
| 387 |
delete _processed; |
|
| 388 |
local_processed=false; |
|
| 387 |
delete _processed; |
|
| 388 |
local_processed=false; |
|
| 389 | 389 |
} |
| 390 | 390 |
_processed = &m; |
| 391 | 391 |
return *this; |
| 392 | 392 |
} |
| 393 | 393 |
|
| 394 | 394 |
///Sets the map storing the distances calculated by the algorithm. |
| 395 | 395 |
|
| 396 | 396 |
///Sets the map storing the distances calculated by the algorithm. |
| 397 | 397 |
///If you don't use this function before calling \ref run(), |
| 398 | 398 |
///it will allocate one. The destructor deallocates this |
| 399 | 399 |
///automatically allocated map, of course. |
| 400 | 400 |
///\return <tt> (*this) </tt> |
| 401 |
Bfs &distMap(DistMap &m) |
|
| 401 |
Bfs &distMap(DistMap &m) |
|
| 402 | 402 |
{
|
| 403 | 403 |
if(local_dist) {
|
| 404 |
delete _dist; |
|
| 405 |
local_dist=false; |
|
| 404 |
delete _dist; |
|
| 405 |
local_dist=false; |
|
| 406 | 406 |
} |
| 407 | 407 |
_dist = &m; |
| 408 | 408 |
return *this; |
| 409 | 409 |
} |
| 410 | 410 |
|
| 411 | 411 |
public: |
| 412 | 412 |
///\name Execution control |
| 413 | 413 |
///The simplest way to execute the algorithm is to use |
| 414 | 414 |
///one of the member functions called \c run(...). |
| 415 | 415 |
///\n |
| 416 | 416 |
///If you need more control on the execution, |
| 417 | 417 |
///first you must call \ref init(), then you can add several source nodes |
| 418 | 418 |
///with \ref addSource(). |
| 419 | 419 |
///Finally \ref start() will perform the actual path |
| 420 | 420 |
///computation. |
| 421 | 421 |
|
| 422 | 422 |
///@{
|
| 423 | 423 |
|
| 424 | 424 |
///\brief Initializes the internal data structures. |
| 425 | 425 |
/// |
| 426 | 426 |
///Initializes the internal data structures. |
| 427 | 427 |
/// |
| 428 | 428 |
void init() |
| 429 | 429 |
{
|
| 430 | 430 |
create_maps(); |
| 431 | 431 |
_queue.resize(countNodes(*G)); |
| 432 | 432 |
_queue_head=_queue_tail=0; |
| 433 | 433 |
_curr_dist=1; |
| 434 | 434 |
for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
|
| 435 |
_pred->set(u,INVALID); |
|
| 436 |
_reached->set(u,false); |
|
| 437 |
|
|
| 435 |
_pred->set(u,INVALID); |
|
| 436 |
_reached->set(u,false); |
|
| 437 |
_processed->set(u,false); |
|
| 438 | 438 |
} |
| 439 | 439 |
} |
| 440 |
|
|
| 440 |
|
|
| 441 | 441 |
///Adds a new source node. |
| 442 | 442 |
|
| 443 | 443 |
///Adds a new source node to the set of nodes to be processed. |
| 444 | 444 |
/// |
| 445 | 445 |
void addSource(Node s) |
| 446 | 446 |
{
|
| 447 | 447 |
if(!(*_reached)[s]) |
| 448 |
{
|
|
| 449 |
_reached->set(s,true); |
|
| 450 |
_pred->set(s,INVALID); |
|
| 451 |
_dist->set(s,0); |
|
| 452 |
_queue[_queue_head++]=s; |
|
| 453 |
_queue_next_dist=_queue_head; |
|
| 454 |
|
|
| 448 |
{
|
|
| 449 |
_reached->set(s,true); |
|
| 450 |
_pred->set(s,INVALID); |
|
| 451 |
_dist->set(s,0); |
|
| 452 |
_queue[_queue_head++]=s; |
|
| 453 |
_queue_next_dist=_queue_head; |
|
| 454 |
} |
|
| 455 | 455 |
} |
| 456 |
|
|
| 456 |
|
|
| 457 | 457 |
///Processes the next node. |
| 458 | 458 |
|
| 459 | 459 |
///Processes the next node. |
| 460 | 460 |
/// |
| 461 | 461 |
///\return The processed node. |
| 462 | 462 |
/// |
| 463 | 463 |
///\warning The queue must not be empty! |
| 464 | 464 |
Node processNextNode() |
| 465 | 465 |
{
|
| 466 | 466 |
if(_queue_tail==_queue_next_dist) {
|
| 467 |
_curr_dist++; |
|
| 468 |
_queue_next_dist=_queue_head; |
|
| 467 |
_curr_dist++; |
|
| 468 |
_queue_next_dist=_queue_head; |
|
| 469 | 469 |
} |
| 470 | 470 |
Node n=_queue[_queue_tail++]; |
| 471 | 471 |
_processed->set(n,true); |
| 472 | 472 |
Node m; |
| 473 | 473 |
for(OutArcIt e(*G,n);e!=INVALID;++e) |
| 474 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 475 |
_queue[_queue_head++]=m; |
|
| 476 |
_reached->set(m,true); |
|
| 477 |
_pred->set(m,e); |
|
| 478 |
_dist->set(m,_curr_dist); |
|
| 479 |
} |
|
| 474 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 475 |
_queue[_queue_head++]=m; |
|
| 476 |
_reached->set(m,true); |
|
| 477 |
_pred->set(m,e); |
|
| 478 |
_dist->set(m,_curr_dist); |
|
| 479 |
} |
|
| 480 | 480 |
return n; |
| 481 | 481 |
} |
| 482 | 482 |
|
| 483 | 483 |
///Processes the next node. |
| 484 | 484 |
|
| 485 | 485 |
///Processes the next node. And checks that the given target node |
| 486 | 486 |
///is reached. If the target node is reachable from the processed |
| 487 | 487 |
///node then the reached parameter will be set true. The reached |
| 488 | 488 |
///parameter should be initially false. |
| 489 | 489 |
/// |
| 490 | 490 |
///\param target The target node. |
| 491 | 491 |
///\retval reach Indicates that the target node is reached. |
| 492 | 492 |
///\return The processed node. |
| 493 | 493 |
/// |
| 494 | 494 |
///\warning The queue must not be empty! |
| 495 | 495 |
Node processNextNode(Node target, bool& reach) |
| 496 | 496 |
{
|
| 497 | 497 |
if(_queue_tail==_queue_next_dist) {
|
| 498 |
_curr_dist++; |
|
| 499 |
_queue_next_dist=_queue_head; |
|
| 498 |
_curr_dist++; |
|
| 499 |
_queue_next_dist=_queue_head; |
|
| 500 | 500 |
} |
| 501 | 501 |
Node n=_queue[_queue_tail++]; |
| 502 | 502 |
_processed->set(n,true); |
| 503 | 503 |
Node m; |
| 504 | 504 |
for(OutArcIt e(*G,n);e!=INVALID;++e) |
| 505 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 506 |
_queue[_queue_head++]=m; |
|
| 507 |
_reached->set(m,true); |
|
| 508 |
_pred->set(m,e); |
|
| 509 |
|
|
| 505 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 506 |
_queue[_queue_head++]=m; |
|
| 507 |
_reached->set(m,true); |
|
| 508 |
_pred->set(m,e); |
|
| 509 |
_dist->set(m,_curr_dist); |
|
| 510 | 510 |
reach = reach || (target == m); |
| 511 |
|
|
| 511 |
} |
|
| 512 | 512 |
return n; |
| 513 | 513 |
} |
| 514 | 514 |
|
| 515 | 515 |
///Processes the next node. |
| 516 | 516 |
|
| 517 | 517 |
///Processes the next node. And checks that at least one of |
| 518 | 518 |
///reached node has true value in the \c nm node map. If one node |
| 519 | 519 |
///with true value is reachable from the processed node then the |
| 520 | 520 |
///rnode parameter will be set to the first of such nodes. |
| 521 | 521 |
/// |
| 522 | 522 |
///\param nm The node map of possible targets. |
| 523 | 523 |
///\retval rnode The reached target node. |
| 524 | 524 |
///\return The processed node. |
| 525 | 525 |
/// |
| 526 | 526 |
///\warning The queue must not be empty! |
| 527 | 527 |
template<class NM> |
| 528 | 528 |
Node processNextNode(const NM& nm, Node& rnode) |
| 529 | 529 |
{
|
| 530 | 530 |
if(_queue_tail==_queue_next_dist) {
|
| 531 |
_curr_dist++; |
|
| 532 |
_queue_next_dist=_queue_head; |
|
| 531 |
_curr_dist++; |
|
| 532 |
_queue_next_dist=_queue_head; |
|
| 533 | 533 |
} |
| 534 | 534 |
Node n=_queue[_queue_tail++]; |
| 535 | 535 |
_processed->set(n,true); |
| 536 | 536 |
Node m; |
| 537 | 537 |
for(OutArcIt e(*G,n);e!=INVALID;++e) |
| 538 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 539 |
_queue[_queue_head++]=m; |
|
| 540 |
_reached->set(m,true); |
|
| 541 |
_pred->set(m,e); |
|
| 542 |
_dist->set(m,_curr_dist); |
|
| 543 |
if (nm[m] && rnode == INVALID) rnode = m; |
|
| 544 |
|
|
| 538 |
if(!(*_reached)[m=G->target(e)]) {
|
|
| 539 |
_queue[_queue_head++]=m; |
|
| 540 |
_reached->set(m,true); |
|
| 541 |
_pred->set(m,e); |
|
| 542 |
_dist->set(m,_curr_dist); |
|
| 543 |
if (nm[m] && rnode == INVALID) rnode = m; |
|
| 544 |
} |
|
| 545 | 545 |
return n; |
| 546 | 546 |
} |
| 547 |
|
|
| 547 |
|
|
| 548 | 548 |
///Next node to be processed. |
| 549 | 549 |
|
| 550 | 550 |
///Next node to be processed. |
| 551 | 551 |
/// |
| 552 | 552 |
///\return The next node to be processed or INVALID if the queue is |
| 553 | 553 |
/// empty. |
| 554 | 554 |
Node nextNode() |
| 555 |
{
|
|
| 555 |
{
|
|
| 556 | 556 |
return _queue_tail<_queue_head?_queue[_queue_tail]:INVALID; |
| 557 | 557 |
} |
| 558 |
|
|
| 558 |
|
|
| 559 | 559 |
///\brief Returns \c false if there are nodes |
| 560 | 560 |
///to be processed in the queue |
| 561 | 561 |
/// |
| 562 | 562 |
///Returns \c false if there are nodes |
| 563 | 563 |
///to be processed in the queue |
| 564 | 564 |
bool emptyQueue() { return _queue_tail==_queue_head; }
|
| 565 | 565 |
///Returns the number of the nodes to be processed. |
| 566 |
|
|
| 566 |
|
|
| 567 | 567 |
///Returns the number of the nodes to be processed in the queue. |
| 568 | 568 |
int queueSize() { return _queue_head-_queue_tail; }
|
| 569 |
|
|
| 569 |
|
|
| 570 | 570 |
///Executes the algorithm. |
| 571 | 571 |
|
| 572 | 572 |
///Executes the algorithm. |
| 573 | 573 |
/// |
| 574 | 574 |
///\pre init() must be called and at least one node should be added |
| 575 | 575 |
///with addSource() before using this function. |
| 576 | 576 |
/// |
| 577 | 577 |
///This method runs the %BFS algorithm from the root node(s) |
| 578 | 578 |
///in order to |
| 579 | 579 |
///compute the |
| 580 | 580 |
///shortest path to each node. The algorithm computes |
| 581 | 581 |
///- The shortest path tree. |
| 582 | 582 |
///- The distance of each node from the root(s). |
| 583 | 583 |
void start() |
| 584 | 584 |
{
|
| 585 | 585 |
while ( !emptyQueue() ) processNextNode(); |
| 586 | 586 |
} |
| 587 |
|
|
| 587 |
|
|
| 588 | 588 |
///Executes the algorithm until \c dest is reached. |
| 589 | 589 |
|
| 590 | 590 |
///Executes the algorithm until \c dest is reached. |
| 591 | 591 |
/// |
| 592 | 592 |
///\pre init() must be called and at least one node should be added |
| 593 | 593 |
///with addSource() before using this function. |
| 594 | 594 |
/// |
| 595 | 595 |
///This method runs the %BFS algorithm from the root node(s) |
| 596 | 596 |
///in order to compute the shortest path to \c dest. |
| 597 | 597 |
///The algorithm computes |
| 598 | 598 |
///- The shortest path to \c dest. |
| 599 | 599 |
///- The distance of \c dest from the root(s). |
| 600 | 600 |
void start(Node dest) |
| 601 | 601 |
{
|
| 602 | 602 |
bool reach = false; |
| 603 | 603 |
while ( !emptyQueue() && !reach ) processNextNode(dest, reach); |
| 604 | 604 |
} |
| 605 |
|
|
| 605 |
|
|
| 606 | 606 |
///Executes the algorithm until a condition is met. |
| 607 | 607 |
|
| 608 | 608 |
///Executes the algorithm until a condition is met. |
| 609 | 609 |
/// |
| 610 | 610 |
///\pre init() must be called and at least one node should be added |
| 611 | 611 |
///with addSource() before using this function. |
| 612 | 612 |
/// |
| 613 | 613 |
///\param nm must be a bool (or convertible) node map. The |
| 614 | 614 |
///algorithm will stop when it reaches a node \c v with |
| 615 | 615 |
/// <tt>nm[v]</tt> true. |
| 616 | 616 |
/// |
| 617 | 617 |
///\return The reached node \c v with <tt>nm[v]</tt> true or |
| 618 | 618 |
///\c INVALID if no such node was found. |
| 619 | 619 |
template<class NM> |
| 620 | 620 |
Node start(const NM &nm) |
| 621 | 621 |
{
|
| 622 | 622 |
Node rnode = INVALID; |
| 623 | 623 |
while ( !emptyQueue() && rnode == INVALID ) {
|
| 624 |
|
|
| 624 |
processNextNode(nm, rnode); |
|
| 625 | 625 |
} |
| 626 | 626 |
return rnode; |
| 627 | 627 |
} |
| 628 |
|
|
| 628 |
|
|
| 629 | 629 |
///Runs %BFS algorithm from node \c s. |
| 630 |
|
|
| 630 |
|
|
| 631 | 631 |
///This method runs the %BFS algorithm from a root node \c s |
| 632 | 632 |
///in order to |
| 633 | 633 |
///compute the |
| 634 | 634 |
///shortest path to each node. The algorithm computes |
| 635 | 635 |
///- The shortest path tree. |
| 636 | 636 |
///- The distance of each node from the root. |
| 637 | 637 |
/// |
| 638 | 638 |
///\note b.run(s) is just a shortcut of the following code. |
| 639 | 639 |
///\code |
| 640 | 640 |
/// b.init(); |
| 641 | 641 |
/// b.addSource(s); |
| 642 | 642 |
/// b.start(); |
| 643 | 643 |
///\endcode |
| 644 | 644 |
void run(Node s) {
|
| 645 | 645 |
init(); |
| 646 | 646 |
addSource(s); |
| 647 | 647 |
start(); |
| 648 | 648 |
} |
| 649 |
|
|
| 649 |
|
|
| 650 | 650 |
///Finds the shortest path between \c s and \c t. |
| 651 |
|
|
| 651 |
|
|
| 652 | 652 |
///Finds the shortest path between \c s and \c t. |
| 653 | 653 |
/// |
| 654 | 654 |
///\return The length of the shortest s---t path if there exists one, |
| 655 | 655 |
///0 otherwise. |
| 656 | 656 |
///\note Apart from the return value, b.run(s) is |
| 657 | 657 |
///just a shortcut of the following code. |
| 658 | 658 |
///\code |
| 659 | 659 |
/// b.init(); |
| 660 | 660 |
/// b.addSource(s); |
| 661 | 661 |
/// b.start(t); |
| 662 | 662 |
///\endcode |
| 663 | 663 |
int run(Node s,Node t) {
|
| 664 | 664 |
init(); |
| 665 | 665 |
addSource(s); |
| 666 | 666 |
start(t); |
| 667 | 667 |
return reached(t) ? _curr_dist : 0; |
| 668 | 668 |
} |
| 669 |
|
|
| 669 |
|
|
| 670 | 670 |
///@} |
| 671 | 671 |
|
| 672 | 672 |
///\name Query Functions |
| 673 | 673 |
///The result of the %BFS algorithm can be obtained using these |
| 674 | 674 |
///functions.\n |
| 675 | 675 |
///Before the use of these functions, |
| 676 | 676 |
///either run() or start() must be calleb. |
| 677 |
|
|
| 677 |
|
|
| 678 | 678 |
///@{
|
| 679 | 679 |
|
| 680 | 680 |
typedef PredMapPath<Digraph, PredMap> Path; |
| 681 | 681 |
|
| 682 | 682 |
///Gives back the shortest path. |
| 683 |
|
|
| 683 |
|
|
| 684 | 684 |
///Gives back the shortest path. |
| 685 | 685 |
///\pre The \c t should be reachable from the source. |
| 686 |
Path path(Node t) |
|
| 686 |
Path path(Node t) |
|
| 687 | 687 |
{
|
| 688 | 688 |
return Path(*G, *_pred, t); |
| 689 | 689 |
} |
| 690 | 690 |
|
| 691 | 691 |
///The distance of a node from the root(s). |
| 692 | 692 |
|
| 693 | 693 |
///Returns the distance of a node from the root(s). |
| 694 | 694 |
///\pre \ref run() must be called before using this function. |
| 695 | 695 |
///\warning If node \c v in unreachable from the root(s) the return value |
| 696 | 696 |
///of this function is undefined. |
| 697 | 697 |
int dist(Node v) const { return (*_dist)[v]; }
|
| 698 | 698 |
|
| 699 | 699 |
///Returns the 'previous arc' of the shortest path tree. |
| 700 | 700 |
|
| 701 | 701 |
///For a node \c v it returns the 'previous arc' |
| 702 | 702 |
///of the shortest path tree, |
| ... | ... |
@@ -709,197 +709,197 @@ |
| 709 | 709 |
///this function. |
| 710 | 710 |
Arc predArc(Node v) const { return (*_pred)[v];}
|
| 711 | 711 |
|
| 712 | 712 |
///Returns the 'previous node' of the shortest path tree. |
| 713 | 713 |
|
| 714 | 714 |
///For a node \c v it returns the 'previous node' |
| 715 | 715 |
///of the shortest path tree, |
| 716 | 716 |
///i.e. it returns the last but one node from a shortest path from the |
| 717 | 717 |
///root(a) to \c /v. |
| 718 | 718 |
///It is INVALID if \c v is unreachable from the root(s) or |
| 719 | 719 |
///if \c v itself a root. |
| 720 | 720 |
///The shortest path tree used here is equal to the shortest path |
| 721 | 721 |
///tree used in \ref predArc(). |
| 722 | 722 |
///\pre Either \ref run() or \ref start() must be called before |
| 723 | 723 |
///using this function. |
| 724 | 724 |
Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
|
| 725 |
G->source((*_pred)[v]); } |
|
| 726 |
|
|
| 725 |
G->source((*_pred)[v]); } |
|
| 726 |
|
|
| 727 | 727 |
///Returns a reference to the NodeMap of distances. |
| 728 | 728 |
|
| 729 | 729 |
///Returns a reference to the NodeMap of distances. |
| 730 | 730 |
///\pre Either \ref run() or \ref init() must |
| 731 | 731 |
///be called before using this function. |
| 732 | 732 |
const DistMap &distMap() const { return *_dist;}
|
| 733 |
|
|
| 733 |
|
|
| 734 | 734 |
///Returns a reference to the shortest path tree map. |
| 735 | 735 |
|
| 736 | 736 |
///Returns a reference to the NodeMap of the arcs of the |
| 737 | 737 |
///shortest path tree. |
| 738 | 738 |
///\pre Either \ref run() or \ref init() |
| 739 | 739 |
///must be called before using this function. |
| 740 | 740 |
const PredMap &predMap() const { return *_pred;}
|
| 741 |
|
|
| 741 |
|
|
| 742 | 742 |
///Checks if a node is reachable from the root. |
| 743 | 743 |
|
| 744 | 744 |
///Returns \c true if \c v is reachable from the root. |
| 745 | 745 |
///\warning The source nodes are indicated as unreached. |
| 746 | 746 |
///\pre Either \ref run() or \ref start() |
| 747 | 747 |
///must be called before using this function. |
| 748 | 748 |
/// |
| 749 | 749 |
bool reached(Node v) { return (*_reached)[v]; }
|
| 750 |
|
|
| 750 |
|
|
| 751 | 751 |
///@} |
| 752 | 752 |
}; |
| 753 | 753 |
|
| 754 | 754 |
///Default traits class of Bfs function. |
| 755 | 755 |
|
| 756 | 756 |
///Default traits class of Bfs function. |
| 757 | 757 |
///\tparam GR Digraph type. |
| 758 | 758 |
template<class GR> |
| 759 | 759 |
struct BfsWizardDefaultTraits |
| 760 | 760 |
{
|
| 761 |
///The digraph type the algorithm runs on. |
|
| 761 |
///The digraph type the algorithm runs on. |
|
| 762 | 762 |
typedef GR Digraph; |
| 763 | 763 |
///\brief The type of the map that stores the last |
| 764 | 764 |
///arcs of the shortest paths. |
| 765 |
/// |
|
| 765 |
/// |
|
| 766 | 766 |
///The type of the map that stores the last |
| 767 | 767 |
///arcs of the shortest paths. |
| 768 | 768 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 769 | 769 |
/// |
| 770 | 770 |
typedef NullMap<typename Digraph::Node,typename GR::Arc> PredMap; |
| 771 | 771 |
///Instantiates a PredMap. |
| 772 |
|
|
| 773 |
///This function instantiates a \ref PredMap. |
|
| 772 |
|
|
| 773 |
///This function instantiates a \ref PredMap. |
|
| 774 | 774 |
///\param g is the digraph, to which we would like to define the PredMap. |
| 775 | 775 |
///\todo The digraph alone may be insufficient to initialize |
| 776 | 776 |
#ifdef DOXYGEN |
| 777 |
static PredMap *createPredMap(const GR &g) |
|
| 777 |
static PredMap *createPredMap(const GR &g) |
|
| 778 | 778 |
#else |
| 779 |
static PredMap *createPredMap(const GR &) |
|
| 779 |
static PredMap *createPredMap(const GR &) |
|
| 780 | 780 |
#endif |
| 781 | 781 |
{
|
| 782 | 782 |
return new PredMap(); |
| 783 | 783 |
} |
| 784 | 784 |
|
| 785 | 785 |
///The type of the map that indicates which nodes are processed. |
| 786 |
|
|
| 786 |
|
|
| 787 | 787 |
///The type of the map that indicates which nodes are processed. |
| 788 | 788 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 789 | 789 |
///\todo named parameter to set this type, function to read and write. |
| 790 | 790 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 791 | 791 |
///Instantiates a ProcessedMap. |
| 792 |
|
|
| 793 |
///This function instantiates a \ref ProcessedMap. |
|
| 792 |
|
|
| 793 |
///This function instantiates a \ref ProcessedMap. |
|
| 794 | 794 |
///\param g is the digraph, to which |
| 795 | 795 |
///we would like to define the \ref ProcessedMap |
| 796 | 796 |
#ifdef DOXYGEN |
| 797 | 797 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 798 | 798 |
#else |
| 799 | 799 |
static ProcessedMap *createProcessedMap(const GR &) |
| 800 | 800 |
#endif |
| 801 | 801 |
{
|
| 802 | 802 |
return new ProcessedMap(); |
| 803 | 803 |
} |
| 804 | 804 |
///The type of the map that indicates which nodes are reached. |
| 805 |
|
|
| 805 |
|
|
| 806 | 806 |
///The type of the map that indicates which nodes are reached. |
| 807 | 807 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 808 | 808 |
///\todo named parameter to set this type, function to read and write. |
| 809 | 809 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 810 | 810 |
///Instantiates a ReachedMap. |
| 811 |
|
|
| 812 |
///This function instantiates a \ref ReachedMap. |
|
| 811 |
|
|
| 812 |
///This function instantiates a \ref ReachedMap. |
|
| 813 | 813 |
///\param G is the digraph, to which |
| 814 | 814 |
///we would like to define the \ref ReachedMap. |
| 815 | 815 |
static ReachedMap *createReachedMap(const GR &G) |
| 816 | 816 |
{
|
| 817 | 817 |
return new ReachedMap(G); |
| 818 | 818 |
} |
| 819 | 819 |
///The type of the map that stores the dists of the nodes. |
| 820 |
|
|
| 820 |
|
|
| 821 | 821 |
///The type of the map that stores the dists of the nodes. |
| 822 | 822 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 823 | 823 |
/// |
| 824 | 824 |
typedef NullMap<typename Digraph::Node,int> DistMap; |
| 825 | 825 |
///Instantiates a DistMap. |
| 826 |
|
|
| 827 |
///This function instantiates a \ref DistMap. |
|
| 826 |
|
|
| 827 |
///This function instantiates a \ref DistMap. |
|
| 828 | 828 |
///\param g is the digraph, to which we would like to define the \ref DistMap |
| 829 | 829 |
#ifdef DOXYGEN |
| 830 | 830 |
static DistMap *createDistMap(const GR &g) |
| 831 | 831 |
#else |
| 832 | 832 |
static DistMap *createDistMap(const GR &) |
| 833 | 833 |
#endif |
| 834 | 834 |
{
|
| 835 | 835 |
return new DistMap(); |
| 836 | 836 |
} |
| 837 | 837 |
}; |
| 838 |
|
|
| 838 |
|
|
| 839 | 839 |
/// Default traits used by \ref BfsWizard |
| 840 | 840 |
|
| 841 | 841 |
/// To make it easier to use Bfs algorithm |
| 842 | 842 |
///we have created a wizard class. |
| 843 | 843 |
/// This \ref BfsWizard class needs default traits, |
| 844 | 844 |
///as well as the \ref Bfs class. |
| 845 | 845 |
/// The \ref BfsWizardBase is a class to be the default traits of the |
| 846 | 846 |
/// \ref BfsWizard class. |
| 847 | 847 |
template<class GR> |
| 848 | 848 |
class BfsWizardBase : public BfsWizardDefaultTraits<GR> |
| 849 | 849 |
{
|
| 850 | 850 |
|
| 851 | 851 |
typedef BfsWizardDefaultTraits<GR> Base; |
| 852 | 852 |
protected: |
| 853 | 853 |
/// Type of the nodes in the digraph. |
| 854 | 854 |
typedef typename Base::Digraph::Node Node; |
| 855 | 855 |
|
| 856 | 856 |
/// Pointer to the underlying digraph. |
| 857 | 857 |
void *_g; |
| 858 | 858 |
///Pointer to the map of reached nodes. |
| 859 | 859 |
void *_reached; |
| 860 | 860 |
///Pointer to the map of processed nodes. |
| 861 | 861 |
void *_processed; |
| 862 | 862 |
///Pointer to the map of predecessors arcs. |
| 863 | 863 |
void *_pred; |
| 864 | 864 |
///Pointer to the map of distances. |
| 865 | 865 |
void *_dist; |
| 866 | 866 |
///Pointer to the source node. |
| 867 | 867 |
Node _source; |
| 868 |
|
|
| 868 |
|
|
| 869 | 869 |
public: |
| 870 | 870 |
/// Constructor. |
| 871 |
|
|
| 871 |
|
|
| 872 | 872 |
/// This constructor does not require parameters, therefore it initiates |
| 873 | 873 |
/// all of the attributes to default values (0, INVALID). |
| 874 | 874 |
BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), |
| 875 |
|
|
| 875 |
_dist(0), _source(INVALID) {}
|
|
| 876 | 876 |
|
| 877 | 877 |
/// Constructor. |
| 878 |
|
|
| 878 |
|
|
| 879 | 879 |
/// This constructor requires some parameters, |
| 880 | 880 |
/// listed in the parameters list. |
| 881 | 881 |
/// Others are initiated to 0. |
| 882 | 882 |
/// \param g is the initial value of \ref _g |
| 883 | 883 |
/// \param s is the initial value of \ref _source |
| 884 | 884 |
BfsWizardBase(const GR &g, Node s=INVALID) : |
| 885 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 885 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 886 | 886 |
_reached(0), _processed(0), _pred(0), _dist(0), _source(s) {}
|
| 887 | 887 |
|
| 888 | 888 |
}; |
| 889 |
|
|
| 889 |
|
|
| 890 | 890 |
/// A class to make the usage of Bfs algorithm easier |
| 891 | 891 |
|
| 892 | 892 |
/// This class is created to make it easier to use Bfs algorithm. |
| 893 | 893 |
/// It uses the functions and features of the plain \ref Bfs, |
| 894 | 894 |
/// but it is much simpler to use it. |
| 895 | 895 |
/// |
| 896 | 896 |
/// Simplicity means that the way to change the types defined |
| 897 | 897 |
/// in the traits class is based on functions that returns the new class |
| 898 | 898 |
/// and not on templatable built-in classes. |
| 899 | 899 |
/// When using the plain \ref Bfs |
| 900 | 900 |
/// the new class with the modified type comes from |
| 901 | 901 |
/// the original class by using the :: |
| 902 | 902 |
/// operator. In the case of \ref BfsWizard only |
| 903 | 903 |
/// a function have to be called and it will |
| 904 | 904 |
/// return the needed class. |
| 905 | 905 |
/// |
| ... | ... |
@@ -908,341 +908,341 @@ |
| 908 | 908 |
/// method of it. |
| 909 | 909 |
template<class TR> |
| 910 | 910 |
class BfsWizard : public TR |
| 911 | 911 |
{
|
| 912 | 912 |
typedef TR Base; |
| 913 | 913 |
|
| 914 | 914 |
///The type of the underlying digraph. |
| 915 | 915 |
typedef typename TR::Digraph Digraph; |
| 916 | 916 |
//\e |
| 917 | 917 |
typedef typename Digraph::Node Node; |
| 918 | 918 |
//\e |
| 919 | 919 |
typedef typename Digraph::NodeIt NodeIt; |
| 920 | 920 |
//\e |
| 921 | 921 |
typedef typename Digraph::Arc Arc; |
| 922 | 922 |
//\e |
| 923 | 923 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 924 |
|
|
| 924 |
|
|
| 925 | 925 |
///\brief The type of the map that stores |
| 926 | 926 |
///the reached nodes |
| 927 | 927 |
typedef typename TR::ReachedMap ReachedMap; |
| 928 | 928 |
///\brief The type of the map that stores |
| 929 | 929 |
///the processed nodes |
| 930 | 930 |
typedef typename TR::ProcessedMap ProcessedMap; |
| 931 | 931 |
///\brief The type of the map that stores the last |
| 932 | 932 |
///arcs of the shortest paths. |
| 933 | 933 |
typedef typename TR::PredMap PredMap; |
| 934 | 934 |
///The type of the map that stores the dists of the nodes. |
| 935 | 935 |
typedef typename TR::DistMap DistMap; |
| 936 | 936 |
|
| 937 | 937 |
public: |
| 938 | 938 |
/// Constructor. |
| 939 | 939 |
BfsWizard() : TR() {}
|
| 940 | 940 |
|
| 941 | 941 |
/// Constructor that requires parameters. |
| 942 | 942 |
|
| 943 | 943 |
/// Constructor that requires parameters. |
| 944 | 944 |
/// These parameters will be the default values for the traits class. |
| 945 | 945 |
BfsWizard(const Digraph &g, Node s=INVALID) : |
| 946 | 946 |
TR(g,s) {}
|
| 947 | 947 |
|
| 948 | 948 |
///Copy constructor |
| 949 | 949 |
BfsWizard(const TR &b) : TR(b) {}
|
| 950 | 950 |
|
| 951 | 951 |
~BfsWizard() {}
|
| 952 | 952 |
|
| 953 | 953 |
///Runs Bfs algorithm from a given node. |
| 954 |
|
|
| 954 |
|
|
| 955 | 955 |
///Runs Bfs algorithm from a given node. |
| 956 | 956 |
///The node can be given by the \ref source function. |
| 957 | 957 |
void run() |
| 958 | 958 |
{
|
| 959 | 959 |
if(Base::_source==INVALID) throw UninitializedParameter(); |
| 960 | 960 |
Bfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g)); |
| 961 | 961 |
if(Base::_reached) |
| 962 |
alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached)); |
|
| 963 |
if(Base::_processed) |
|
| 962 |
alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached)); |
|
| 963 |
if(Base::_processed) |
|
| 964 | 964 |
alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed)); |
| 965 |
if(Base::_pred) |
|
| 965 |
if(Base::_pred) |
|
| 966 | 966 |
alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred)); |
| 967 |
if(Base::_dist) |
|
| 967 |
if(Base::_dist) |
|
| 968 | 968 |
alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist)); |
| 969 | 969 |
alg.run(Base::_source); |
| 970 | 970 |
} |
| 971 | 971 |
|
| 972 | 972 |
///Runs Bfs algorithm from the given node. |
| 973 | 973 |
|
| 974 | 974 |
///Runs Bfs algorithm from the given node. |
| 975 | 975 |
///\param s is the given source. |
| 976 | 976 |
void run(Node s) |
| 977 | 977 |
{
|
| 978 | 978 |
Base::_source=s; |
| 979 | 979 |
run(); |
| 980 | 980 |
} |
| 981 | 981 |
|
| 982 | 982 |
template<class T> |
| 983 | 983 |
struct DefPredMapBase : public Base {
|
| 984 | 984 |
typedef T PredMap; |
| 985 | 985 |
static PredMap *createPredMap(const Digraph &) { return 0; };
|
| 986 | 986 |
DefPredMapBase(const TR &b) : TR(b) {}
|
| 987 | 987 |
}; |
| 988 |
|
|
| 988 |
|
|
| 989 | 989 |
///\brief \ref named-templ-param "Named parameter" |
| 990 | 990 |
///function for setting PredMap |
| 991 | 991 |
/// |
| 992 | 992 |
/// \ref named-templ-param "Named parameter" |
| 993 | 993 |
///function for setting PredMap |
| 994 | 994 |
/// |
| 995 | 995 |
template<class T> |
| 996 |
BfsWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 996 |
BfsWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 997 | 997 |
{
|
| 998 | 998 |
Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 999 | 999 |
return BfsWizard<DefPredMapBase<T> >(*this); |
| 1000 | 1000 |
} |
| 1001 |
|
|
| 1002 |
|
|
| 1001 |
|
|
| 1002 |
|
|
| 1003 | 1003 |
template<class T> |
| 1004 | 1004 |
struct DefReachedMapBase : public Base {
|
| 1005 | 1005 |
typedef T ReachedMap; |
| 1006 | 1006 |
static ReachedMap *createReachedMap(const Digraph &) { return 0; };
|
| 1007 | 1007 |
DefReachedMapBase(const TR &b) : TR(b) {}
|
| 1008 | 1008 |
}; |
| 1009 |
|
|
| 1009 |
|
|
| 1010 | 1010 |
///\brief \ref named-templ-param "Named parameter" |
| 1011 | 1011 |
///function for setting ReachedMap |
| 1012 | 1012 |
/// |
| 1013 | 1013 |
/// \ref named-templ-param "Named parameter" |
| 1014 | 1014 |
///function for setting ReachedMap |
| 1015 | 1015 |
/// |
| 1016 | 1016 |
template<class T> |
| 1017 |
BfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) |
|
| 1017 |
BfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) |
|
| 1018 | 1018 |
{
|
| 1019 | 1019 |
Base::_reached=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1020 | 1020 |
return BfsWizard<DefReachedMapBase<T> >(*this); |
| 1021 | 1021 |
} |
| 1022 |
|
|
| 1022 |
|
|
| 1023 | 1023 |
|
| 1024 | 1024 |
template<class T> |
| 1025 | 1025 |
struct DefProcessedMapBase : public Base {
|
| 1026 | 1026 |
typedef T ProcessedMap; |
| 1027 | 1027 |
static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
|
| 1028 | 1028 |
DefProcessedMapBase(const TR &b) : TR(b) {}
|
| 1029 | 1029 |
}; |
| 1030 |
|
|
| 1030 |
|
|
| 1031 | 1031 |
///\brief \ref named-templ-param "Named parameter" |
| 1032 | 1032 |
///function for setting ProcessedMap |
| 1033 | 1033 |
/// |
| 1034 | 1034 |
/// \ref named-templ-param "Named parameter" |
| 1035 | 1035 |
///function for setting ProcessedMap |
| 1036 | 1036 |
/// |
| 1037 | 1037 |
template<class T> |
| 1038 |
BfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) |
|
| 1038 |
BfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) |
|
| 1039 | 1039 |
{
|
| 1040 | 1040 |
Base::_processed=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1041 | 1041 |
return BfsWizard<DefProcessedMapBase<T> >(*this); |
| 1042 | 1042 |
} |
| 1043 |
|
|
| 1044 |
|
|
| 1043 |
|
|
| 1044 |
|
|
| 1045 | 1045 |
template<class T> |
| 1046 | 1046 |
struct DefDistMapBase : public Base {
|
| 1047 | 1047 |
typedef T DistMap; |
| 1048 | 1048 |
static DistMap *createDistMap(const Digraph &) { return 0; };
|
| 1049 | 1049 |
DefDistMapBase(const TR &b) : TR(b) {}
|
| 1050 | 1050 |
}; |
| 1051 |
|
|
| 1051 |
|
|
| 1052 | 1052 |
///\brief \ref named-templ-param "Named parameter" |
| 1053 | 1053 |
///function for setting DistMap type |
| 1054 | 1054 |
/// |
| 1055 | 1055 |
/// \ref named-templ-param "Named parameter" |
| 1056 | 1056 |
///function for setting DistMap type |
| 1057 | 1057 |
/// |
| 1058 | 1058 |
template<class T> |
| 1059 |
BfsWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1059 |
BfsWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1060 | 1060 |
{
|
| 1061 | 1061 |
Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1062 | 1062 |
return BfsWizard<DefDistMapBase<T> >(*this); |
| 1063 | 1063 |
} |
| 1064 |
|
|
| 1064 |
|
|
| 1065 | 1065 |
/// Sets the source node, from which the Bfs algorithm runs. |
| 1066 | 1066 |
|
| 1067 | 1067 |
/// Sets the source node, from which the Bfs algorithm runs. |
| 1068 | 1068 |
/// \param s is the source node. |
| 1069 |
BfsWizard<TR> &source(Node s) |
|
| 1069 |
BfsWizard<TR> &source(Node s) |
|
| 1070 | 1070 |
{
|
| 1071 | 1071 |
Base::_source=s; |
| 1072 | 1072 |
return *this; |
| 1073 | 1073 |
} |
| 1074 |
|
|
| 1074 |
|
|
| 1075 | 1075 |
}; |
| 1076 |
|
|
| 1076 |
|
|
| 1077 | 1077 |
///Function type interface for Bfs algorithm. |
| 1078 | 1078 |
|
| 1079 | 1079 |
/// \ingroup search |
| 1080 | 1080 |
///Function type interface for Bfs algorithm. |
| 1081 | 1081 |
/// |
| 1082 | 1082 |
///This function also has several |
| 1083 | 1083 |
///\ref named-templ-func-param "named parameters", |
| 1084 | 1084 |
///they are declared as the members of class \ref BfsWizard. |
| 1085 | 1085 |
///The following |
| 1086 | 1086 |
///example shows how to use these parameters. |
| 1087 | 1087 |
///\code |
| 1088 | 1088 |
/// bfs(g,source).predMap(preds).run(); |
| 1089 | 1089 |
///\endcode |
| 1090 | 1090 |
///\warning Don't forget to put the \ref BfsWizard::run() "run()" |
| 1091 | 1091 |
///to the end of the parameter list. |
| 1092 | 1092 |
///\sa BfsWizard |
| 1093 | 1093 |
///\sa Bfs |
| 1094 | 1094 |
template<class GR> |
| 1095 | 1095 |
BfsWizard<BfsWizardBase<GR> > |
| 1096 | 1096 |
bfs(const GR &g,typename GR::Node s=INVALID) |
| 1097 | 1097 |
{
|
| 1098 | 1098 |
return BfsWizard<BfsWizardBase<GR> >(g,s); |
| 1099 | 1099 |
} |
| 1100 | 1100 |
|
| 1101 | 1101 |
#ifdef DOXYGEN |
| 1102 | 1102 |
/// \brief Visitor class for bfs. |
| 1103 |
/// |
|
| 1103 |
/// |
|
| 1104 | 1104 |
/// This class defines the interface of the BfsVisit events, and |
| 1105 | 1105 |
/// it could be the base of a real Visitor class. |
| 1106 | 1106 |
template <typename _Digraph> |
| 1107 | 1107 |
struct BfsVisitor {
|
| 1108 | 1108 |
typedef _Digraph Digraph; |
| 1109 | 1109 |
typedef typename Digraph::Arc Arc; |
| 1110 | 1110 |
typedef typename Digraph::Node Node; |
| 1111 | 1111 |
/// \brief Called when the arc reach a node. |
| 1112 |
/// |
|
| 1112 |
/// |
|
| 1113 | 1113 |
/// It is called when the bfs find an arc which target is not |
| 1114 | 1114 |
/// reached yet. |
| 1115 | 1115 |
void discover(const Arc& arc) {}
|
| 1116 | 1116 |
/// \brief Called when the node reached first time. |
| 1117 |
/// |
|
| 1117 |
/// |
|
| 1118 | 1118 |
/// It is Called when the node reached first time. |
| 1119 | 1119 |
void reach(const Node& node) {}
|
| 1120 |
/// \brief Called when the arc examined but target of the arc |
|
| 1120 |
/// \brief Called when the arc examined but target of the arc |
|
| 1121 | 1121 |
/// already discovered. |
| 1122 |
/// |
|
| 1123 |
/// It called when the arc examined but the target of the arc |
|
| 1122 |
/// |
|
| 1123 |
/// It called when the arc examined but the target of the arc |
|
| 1124 | 1124 |
/// already discovered. |
| 1125 | 1125 |
void examine(const Arc& arc) {}
|
| 1126 | 1126 |
/// \brief Called for the source node of the bfs. |
| 1127 |
/// |
|
| 1127 |
/// |
|
| 1128 | 1128 |
/// It is called for the source node of the bfs. |
| 1129 | 1129 |
void start(const Node& node) {}
|
| 1130 | 1130 |
/// \brief Called when the node processed. |
| 1131 |
/// |
|
| 1131 |
/// |
|
| 1132 | 1132 |
/// It is Called when the node processed. |
| 1133 | 1133 |
void process(const Node& node) {}
|
| 1134 | 1134 |
}; |
| 1135 | 1135 |
#else |
| 1136 | 1136 |
template <typename _Digraph> |
| 1137 | 1137 |
struct BfsVisitor {
|
| 1138 | 1138 |
typedef _Digraph Digraph; |
| 1139 | 1139 |
typedef typename Digraph::Arc Arc; |
| 1140 | 1140 |
typedef typename Digraph::Node Node; |
| 1141 | 1141 |
void discover(const Arc&) {}
|
| 1142 | 1142 |
void reach(const Node&) {}
|
| 1143 | 1143 |
void examine(const Arc&) {}
|
| 1144 | 1144 |
void start(const Node&) {}
|
| 1145 | 1145 |
void process(const Node&) {}
|
| 1146 | 1146 |
|
| 1147 | 1147 |
template <typename _Visitor> |
| 1148 | 1148 |
struct Constraints {
|
| 1149 | 1149 |
void constraints() {
|
| 1150 |
Arc arc; |
|
| 1151 |
Node node; |
|
| 1152 |
visitor.discover(arc); |
|
| 1153 |
visitor.reach(node); |
|
| 1154 |
visitor.examine(arc); |
|
| 1155 |
visitor.start(node); |
|
| 1150 |
Arc arc; |
|
| 1151 |
Node node; |
|
| 1152 |
visitor.discover(arc); |
|
| 1153 |
visitor.reach(node); |
|
| 1154 |
visitor.examine(arc); |
|
| 1155 |
visitor.start(node); |
|
| 1156 | 1156 |
visitor.process(node); |
| 1157 | 1157 |
} |
| 1158 | 1158 |
_Visitor& visitor; |
| 1159 | 1159 |
}; |
| 1160 | 1160 |
}; |
| 1161 | 1161 |
#endif |
| 1162 | 1162 |
|
| 1163 | 1163 |
/// \brief Default traits class of BfsVisit class. |
| 1164 | 1164 |
/// |
| 1165 | 1165 |
/// Default traits class of BfsVisit class. |
| 1166 | 1166 |
/// \tparam _Digraph Digraph type. |
| 1167 | 1167 |
template<class _Digraph> |
| 1168 | 1168 |
struct BfsVisitDefaultTraits {
|
| 1169 | 1169 |
|
| 1170 |
/// \brief The digraph type the algorithm runs on. |
|
| 1170 |
/// \brief The digraph type the algorithm runs on. |
|
| 1171 | 1171 |
typedef _Digraph Digraph; |
| 1172 | 1172 |
|
| 1173 | 1173 |
/// \brief The type of the map that indicates which nodes are reached. |
| 1174 |
/// |
|
| 1174 |
/// |
|
| 1175 | 1175 |
/// The type of the map that indicates which nodes are reached. |
| 1176 | 1176 |
/// It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 1177 | 1177 |
/// \todo named parameter to set this type, function to read and write. |
| 1178 | 1178 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 1179 | 1179 |
|
| 1180 | 1180 |
/// \brief Instantiates a ReachedMap. |
| 1181 | 1181 |
/// |
| 1182 |
/// This function instantiates a \ref ReachedMap. |
|
| 1182 |
/// This function instantiates a \ref ReachedMap. |
|
| 1183 | 1183 |
/// \param digraph is the digraph, to which |
| 1184 | 1184 |
/// we would like to define the \ref ReachedMap. |
| 1185 | 1185 |
static ReachedMap *createReachedMap(const Digraph &digraph) {
|
| 1186 | 1186 |
return new ReachedMap(digraph); |
| 1187 | 1187 |
} |
| 1188 | 1188 |
|
| 1189 | 1189 |
}; |
| 1190 | 1190 |
|
| 1191 | 1191 |
/// \ingroup search |
| 1192 |
/// |
|
| 1192 |
/// |
|
| 1193 | 1193 |
/// \brief %BFS Visit algorithm class. |
| 1194 |
/// |
|
| 1194 |
/// |
|
| 1195 | 1195 |
/// This class provides an efficient implementation of the %BFS algorithm |
| 1196 | 1196 |
/// with visitor interface. |
| 1197 | 1197 |
/// |
| 1198 | 1198 |
/// The %BfsVisit class provides an alternative interface to the Bfs |
| 1199 | 1199 |
/// class. It works with callback mechanism, the BfsVisit object calls |
| 1200 |
/// on every bfs event the \c Visitor class member functions. |
|
| 1200 |
/// on every bfs event the \c Visitor class member functions. |
|
| 1201 | 1201 |
/// |
| 1202 | 1202 |
/// \tparam _Digraph The digraph type the algorithm runs on. The default value is |
| 1203 | 1203 |
/// \ref ListDigraph. The value of _Digraph is not used directly by Bfs, it |
| 1204 | 1204 |
/// is only passed to \ref BfsDefaultTraits. |
| 1205 |
/// \tparam _Visitor The Visitor object for the algorithm. The |
|
| 1205 |
/// \tparam _Visitor The Visitor object for the algorithm. The |
|
| 1206 | 1206 |
/// \ref BfsVisitor "BfsVisitor<_Digraph>" is an empty Visitor which |
| 1207 | 1207 |
/// does not observe the Bfs events. If you want to observe the bfs |
| 1208 | 1208 |
/// events you should implement your own Visitor class. |
| 1209 |
/// \tparam _Traits Traits class to set various data types used by the |
|
| 1209 |
/// \tparam _Traits Traits class to set various data types used by the |
|
| 1210 | 1210 |
/// algorithm. The default traits class is |
| 1211 | 1211 |
/// \ref BfsVisitDefaultTraits "BfsVisitDefaultTraits<_Digraph>". |
| 1212 | 1212 |
/// See \ref BfsVisitDefaultTraits for the documentation of |
| 1213 | 1213 |
/// a Bfs visit traits class. |
| 1214 | 1214 |
#ifdef DOXYGEN |
| 1215 | 1215 |
template <typename _Digraph, typename _Visitor, typename _Traits> |
| 1216 | 1216 |
#else |
| 1217 | 1217 |
template <typename _Digraph = ListDigraph, |
| 1218 |
typename _Visitor = BfsVisitor<_Digraph>, |
|
| 1219 |
typename _Traits = BfsDefaultTraits<_Digraph> > |
|
| 1218 |
typename _Visitor = BfsVisitor<_Digraph>, |
|
| 1219 |
typename _Traits = BfsDefaultTraits<_Digraph> > |
|
| 1220 | 1220 |
#endif |
| 1221 | 1221 |
class BfsVisit {
|
| 1222 | 1222 |
public: |
| 1223 |
|
|
| 1223 |
|
|
| 1224 | 1224 |
/// \brief \ref Exception for uninitialized parameters. |
| 1225 | 1225 |
/// |
| 1226 | 1226 |
/// This error represents problems in the initialization |
| 1227 | 1227 |
/// of the parameters of the algorithms. |
| 1228 | 1228 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
| 1229 | 1229 |
public: |
| 1230 |
virtual const char* what() const throw() |
|
| 1230 |
virtual const char* what() const throw() |
|
| 1231 | 1231 |
{
|
| 1232 |
|
|
| 1232 |
return "lemon::BfsVisit::UninitializedParameter"; |
|
| 1233 | 1233 |
} |
| 1234 | 1234 |
}; |
| 1235 | 1235 |
|
| 1236 | 1236 |
typedef _Traits Traits; |
| 1237 | 1237 |
|
| 1238 | 1238 |
typedef typename Traits::Digraph Digraph; |
| 1239 | 1239 |
|
| 1240 | 1240 |
typedef _Visitor Visitor; |
| 1241 | 1241 |
|
| 1242 | 1242 |
///The type of the map indicating which nodes are reached. |
| 1243 | 1243 |
typedef typename Traits::ReachedMap ReachedMap; |
| 1244 | 1244 |
|
| 1245 | 1245 |
private: |
| 1246 | 1246 |
|
| 1247 | 1247 |
typedef typename Digraph::Node Node; |
| 1248 | 1248 |
typedef typename Digraph::NodeIt NodeIt; |
| ... | ... |
@@ -1253,147 +1253,147 @@ |
| 1253 | 1253 |
const Digraph *_digraph; |
| 1254 | 1254 |
/// Pointer to the visitor object. |
| 1255 | 1255 |
Visitor *_visitor; |
| 1256 | 1256 |
///Pointer to the map of reached status of the nodes. |
| 1257 | 1257 |
ReachedMap *_reached; |
| 1258 | 1258 |
///Indicates if \ref _reached is locally allocated (\c true) or not. |
| 1259 | 1259 |
bool local_reached; |
| 1260 | 1260 |
|
| 1261 | 1261 |
std::vector<typename Digraph::Node> _list; |
| 1262 | 1262 |
int _list_front, _list_back; |
| 1263 | 1263 |
|
| 1264 | 1264 |
/// \brief Creates the maps if necessary. |
| 1265 | 1265 |
/// |
| 1266 | 1266 |
/// Creates the maps if necessary. |
| 1267 | 1267 |
void create_maps() {
|
| 1268 | 1268 |
if(!_reached) {
|
| 1269 |
local_reached = true; |
|
| 1270 |
_reached = Traits::createReachedMap(*_digraph); |
|
| 1269 |
local_reached = true; |
|
| 1270 |
_reached = Traits::createReachedMap(*_digraph); |
|
| 1271 | 1271 |
} |
| 1272 | 1272 |
} |
| 1273 | 1273 |
|
| 1274 | 1274 |
protected: |
| 1275 | 1275 |
|
| 1276 | 1276 |
BfsVisit() {}
|
| 1277 |
|
|
| 1277 |
|
|
| 1278 | 1278 |
public: |
| 1279 | 1279 |
|
| 1280 | 1280 |
typedef BfsVisit Create; |
| 1281 | 1281 |
|
| 1282 | 1282 |
/// \name Named template parameters |
| 1283 | 1283 |
|
| 1284 | 1284 |
///@{
|
| 1285 | 1285 |
template <class T> |
| 1286 | 1286 |
struct DefReachedMapTraits : public Traits {
|
| 1287 | 1287 |
typedef T ReachedMap; |
| 1288 | 1288 |
static ReachedMap *createReachedMap(const Digraph &digraph) {
|
| 1289 |
|
|
| 1289 |
throw UninitializedParameter(); |
|
| 1290 | 1290 |
} |
| 1291 | 1291 |
}; |
| 1292 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 1292 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 1293 | 1293 |
/// ReachedMap type |
| 1294 | 1294 |
/// |
| 1295 | 1295 |
/// \ref named-templ-param "Named parameter" for setting ReachedMap type |
| 1296 | 1296 |
template <class T> |
| 1297 | 1297 |
struct DefReachedMap : public BfsVisit< Digraph, Visitor, |
| 1298 |
|
|
| 1298 |
DefReachedMapTraits<T> > {
|
|
| 1299 | 1299 |
typedef BfsVisit< Digraph, Visitor, DefReachedMapTraits<T> > Create; |
| 1300 | 1300 |
}; |
| 1301 | 1301 |
///@} |
| 1302 | 1302 |
|
| 1303 |
public: |
|
| 1304 |
|
|
| 1303 |
public: |
|
| 1304 |
|
|
| 1305 | 1305 |
/// \brief Constructor. |
| 1306 | 1306 |
/// |
| 1307 | 1307 |
/// Constructor. |
| 1308 | 1308 |
/// |
| 1309 | 1309 |
/// \param digraph the digraph the algorithm will run on. |
| 1310 | 1310 |
/// \param visitor The visitor of the algorithm. |
| 1311 | 1311 |
/// |
| 1312 |
BfsVisit(const Digraph& digraph, Visitor& visitor) |
|
| 1312 |
BfsVisit(const Digraph& digraph, Visitor& visitor) |
|
| 1313 | 1313 |
: _digraph(&digraph), _visitor(&visitor), |
| 1314 |
_reached(0), local_reached(false) {}
|
|
| 1315 |
|
|
| 1314 |
_reached(0), local_reached(false) {}
|
|
| 1315 |
|
|
| 1316 | 1316 |
/// \brief Destructor. |
| 1317 | 1317 |
/// |
| 1318 | 1318 |
/// Destructor. |
| 1319 | 1319 |
~BfsVisit() {
|
| 1320 | 1320 |
if(local_reached) delete _reached; |
| 1321 | 1321 |
} |
| 1322 | 1322 |
|
| 1323 | 1323 |
/// \brief Sets the map indicating if a node is reached. |
| 1324 | 1324 |
/// |
| 1325 | 1325 |
/// Sets the map indicating if a node is reached. |
| 1326 | 1326 |
/// If you don't use this function before calling \ref run(), |
| 1327 | 1327 |
/// it will allocate one. The destuctor deallocates this |
| 1328 | 1328 |
/// automatically allocated map, of course. |
| 1329 | 1329 |
/// \return <tt> (*this) </tt> |
| 1330 | 1330 |
BfsVisit &reachedMap(ReachedMap &m) {
|
| 1331 | 1331 |
if(local_reached) {
|
| 1332 |
delete _reached; |
|
| 1333 |
local_reached = false; |
|
| 1332 |
delete _reached; |
|
| 1333 |
local_reached = false; |
|
| 1334 | 1334 |
} |
| 1335 | 1335 |
_reached = &m; |
| 1336 | 1336 |
return *this; |
| 1337 | 1337 |
} |
| 1338 | 1338 |
|
| 1339 | 1339 |
public: |
| 1340 | 1340 |
/// \name Execution control |
| 1341 | 1341 |
/// The simplest way to execute the algorithm is to use |
| 1342 | 1342 |
/// one of the member functions called \c run(...). |
| 1343 | 1343 |
/// \n |
| 1344 | 1344 |
/// If you need more control on the execution, |
| 1345 | 1345 |
/// first you must call \ref init(), then you can adda source node |
| 1346 | 1346 |
/// with \ref addSource(). |
| 1347 | 1347 |
/// Finally \ref start() will perform the actual path |
| 1348 | 1348 |
/// computation. |
| 1349 | 1349 |
|
| 1350 | 1350 |
/// @{
|
| 1351 | 1351 |
/// \brief Initializes the internal data structures. |
| 1352 | 1352 |
/// |
| 1353 | 1353 |
/// Initializes the internal data structures. |
| 1354 | 1354 |
/// |
| 1355 | 1355 |
void init() {
|
| 1356 | 1356 |
create_maps(); |
| 1357 | 1357 |
_list.resize(countNodes(*_digraph)); |
| 1358 | 1358 |
_list_front = _list_back = -1; |
| 1359 | 1359 |
for (NodeIt u(*_digraph) ; u != INVALID ; ++u) {
|
| 1360 |
|
|
| 1360 |
_reached->set(u, false); |
|
| 1361 | 1361 |
} |
| 1362 | 1362 |
} |
| 1363 |
|
|
| 1363 |
|
|
| 1364 | 1364 |
/// \brief Adds a new source node. |
| 1365 | 1365 |
/// |
| 1366 | 1366 |
/// Adds a new source node to the set of nodes to be processed. |
| 1367 | 1367 |
void addSource(Node s) {
|
| 1368 | 1368 |
if(!(*_reached)[s]) {
|
| 1369 |
_reached->set(s,true); |
|
| 1370 |
_visitor->start(s); |
|
| 1371 |
|
|
| 1369 |
_reached->set(s,true); |
|
| 1370 |
_visitor->start(s); |
|
| 1371 |
_visitor->reach(s); |
|
| 1372 | 1372 |
_list[++_list_back] = s; |
| 1373 |
|
|
| 1373 |
} |
|
| 1374 | 1374 |
} |
| 1375 |
|
|
| 1375 |
|
|
| 1376 | 1376 |
/// \brief Processes the next node. |
| 1377 | 1377 |
/// |
| 1378 | 1378 |
/// Processes the next node. |
| 1379 | 1379 |
/// |
| 1380 | 1380 |
/// \return The processed node. |
| 1381 | 1381 |
/// |
| 1382 | 1382 |
/// \pre The queue must not be empty! |
| 1383 |
Node processNextNode() {
|
|
| 1383 |
Node processNextNode() {
|
|
| 1384 | 1384 |
Node n = _list[++_list_front]; |
| 1385 | 1385 |
_visitor->process(n); |
| 1386 | 1386 |
Arc e; |
| 1387 | 1387 |
for (_digraph->firstOut(e, n); e != INVALID; _digraph->nextOut(e)) {
|
| 1388 | 1388 |
Node m = _digraph->target(e); |
| 1389 | 1389 |
if (!(*_reached)[m]) {
|
| 1390 | 1390 |
_visitor->discover(e); |
| 1391 | 1391 |
_visitor->reach(m); |
| 1392 | 1392 |
_reached->set(m, true); |
| 1393 | 1393 |
_list[++_list_back] = m; |
| 1394 | 1394 |
} else {
|
| 1395 | 1395 |
_visitor->examine(e); |
| 1396 | 1396 |
} |
| 1397 | 1397 |
} |
| 1398 | 1398 |
return n; |
| 1399 | 1399 |
} |
| ... | ... |
@@ -1454,108 +1454,108 @@ |
| 1454 | 1454 |
_reached->set(m, true); |
| 1455 | 1455 |
_list[++_list_back] = m; |
| 1456 | 1456 |
if (nm[m] && rnode == INVALID) rnode = m; |
| 1457 | 1457 |
} else {
|
| 1458 | 1458 |
_visitor->examine(e); |
| 1459 | 1459 |
} |
| 1460 | 1460 |
} |
| 1461 | 1461 |
return n; |
| 1462 | 1462 |
} |
| 1463 | 1463 |
|
| 1464 | 1464 |
/// \brief Next node to be processed. |
| 1465 | 1465 |
/// |
| 1466 | 1466 |
/// Next node to be processed. |
| 1467 | 1467 |
/// |
| 1468 | 1468 |
/// \return The next node to be processed or INVALID if the stack is |
| 1469 | 1469 |
/// empty. |
| 1470 |
Node nextNode() {
|
|
| 1470 |
Node nextNode() {
|
|
| 1471 | 1471 |
return _list_front != _list_back ? _list[_list_front + 1] : INVALID; |
| 1472 | 1472 |
} |
| 1473 | 1473 |
|
| 1474 | 1474 |
/// \brief Returns \c false if there are nodes |
| 1475 | 1475 |
/// to be processed in the queue |
| 1476 | 1476 |
/// |
| 1477 | 1477 |
/// Returns \c false if there are nodes |
| 1478 | 1478 |
/// to be processed in the queue |
| 1479 | 1479 |
bool emptyQueue() { return _list_front == _list_back; }
|
| 1480 | 1480 |
|
| 1481 | 1481 |
/// \brief Returns the number of the nodes to be processed. |
| 1482 | 1482 |
/// |
| 1483 | 1483 |
/// Returns the number of the nodes to be processed in the queue. |
| 1484 | 1484 |
int queueSize() { return _list_back - _list_front; }
|
| 1485 |
|
|
| 1485 |
|
|
| 1486 | 1486 |
/// \brief Executes the algorithm. |
| 1487 | 1487 |
/// |
| 1488 | 1488 |
/// Executes the algorithm. |
| 1489 | 1489 |
/// |
| 1490 | 1490 |
/// \pre init() must be called and at least one node should be added |
| 1491 | 1491 |
/// with addSource() before using this function. |
| 1492 | 1492 |
void start() {
|
| 1493 | 1493 |
while ( !emptyQueue() ) processNextNode(); |
| 1494 | 1494 |
} |
| 1495 |
|
|
| 1495 |
|
|
| 1496 | 1496 |
/// \brief Executes the algorithm until \c dest is reached. |
| 1497 | 1497 |
/// |
| 1498 | 1498 |
/// Executes the algorithm until \c dest is reached. |
| 1499 | 1499 |
/// |
| 1500 | 1500 |
/// \pre init() must be called and at least one node should be added |
| 1501 | 1501 |
/// with addSource() before using this function. |
| 1502 | 1502 |
void start(Node dest) {
|
| 1503 | 1503 |
bool reach = false; |
| 1504 | 1504 |
while ( !emptyQueue() && !reach ) processNextNode(dest, reach); |
| 1505 | 1505 |
} |
| 1506 |
|
|
| 1506 |
|
|
| 1507 | 1507 |
/// \brief Executes the algorithm until a condition is met. |
| 1508 | 1508 |
/// |
| 1509 | 1509 |
/// Executes the algorithm until a condition is met. |
| 1510 | 1510 |
/// |
| 1511 | 1511 |
/// \pre init() must be called and at least one node should be added |
| 1512 | 1512 |
/// with addSource() before using this function. |
| 1513 | 1513 |
/// |
| 1514 | 1514 |
///\param nm must be a bool (or convertible) node map. The |
| 1515 | 1515 |
///algorithm will stop when it reaches a node \c v with |
| 1516 | 1516 |
/// <tt>nm[v]</tt> true. |
| 1517 | 1517 |
/// |
| 1518 | 1518 |
///\return The reached node \c v with <tt>nm[v]</tt> true or |
| 1519 | 1519 |
///\c INVALID if no such node was found. |
| 1520 | 1520 |
template <typename NM> |
| 1521 | 1521 |
Node start(const NM &nm) {
|
| 1522 | 1522 |
Node rnode = INVALID; |
| 1523 | 1523 |
while ( !emptyQueue() && rnode == INVALID ) {
|
| 1524 |
|
|
| 1524 |
processNextNode(nm, rnode); |
|
| 1525 | 1525 |
} |
| 1526 | 1526 |
return rnode; |
| 1527 | 1527 |
} |
| 1528 | 1528 |
|
| 1529 | 1529 |
/// \brief Runs %BFSVisit algorithm from node \c s. |
| 1530 | 1530 |
/// |
| 1531 | 1531 |
/// This method runs the %BFS algorithm from a root node \c s. |
| 1532 | 1532 |
/// \note b.run(s) is just a shortcut of the following code. |
| 1533 | 1533 |
///\code |
| 1534 | 1534 |
/// b.init(); |
| 1535 | 1535 |
/// b.addSource(s); |
| 1536 | 1536 |
/// b.start(); |
| 1537 | 1537 |
///\endcode |
| 1538 | 1538 |
void run(Node s) {
|
| 1539 | 1539 |
init(); |
| 1540 | 1540 |
addSource(s); |
| 1541 | 1541 |
start(); |
| 1542 | 1542 |
} |
| 1543 | 1543 |
|
| 1544 | 1544 |
/// \brief Runs %BFSVisit algorithm to visit all nodes in the digraph. |
| 1545 |
/// |
|
| 1545 |
/// |
|
| 1546 | 1546 |
/// This method runs the %BFS algorithm in order to |
| 1547 | 1547 |
/// compute the %BFS path to each node. The algorithm computes |
| 1548 | 1548 |
/// - The %BFS tree. |
| 1549 | 1549 |
/// - The distance of each node from the root in the %BFS tree. |
| 1550 | 1550 |
/// |
| 1551 | 1551 |
///\note b.run() is just a shortcut of the following code. |
| 1552 | 1552 |
///\code |
| 1553 | 1553 |
/// b.init(); |
| 1554 | 1554 |
/// for (NodeIt it(digraph); it != INVALID; ++it) {
|
| 1555 | 1555 |
/// if (!b.reached(it)) {
|
| 1556 | 1556 |
/// b.addSource(it); |
| 1557 | 1557 |
/// b.start(); |
| 1558 | 1558 |
/// } |
| 1559 | 1559 |
/// } |
| 1560 | 1560 |
///\endcode |
| 1561 | 1561 |
void run() {
|
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BIN_HEAP_H |
| ... | ... |
@@ -35,33 +35,33 @@ |
| 35 | 35 |
/// |
| 36 | 36 |
///This class implements the \e binary \e heap data structure. A \e heap |
| 37 | 37 |
///is a data structure for storing items with specified values called \e |
| 38 | 38 |
///priorities in such a way that finding the item with minimum priority is |
| 39 | 39 |
///efficient. \c Compare specifies the ordering of the priorities. In a heap |
| 40 | 40 |
///one can change the priority of an item, add or erase an item, etc. |
| 41 | 41 |
/// |
| 42 | 42 |
///\tparam _Prio Type of the priority of the items. |
| 43 | 43 |
///\tparam _ItemIntMap A read and writable Item int map, used internally |
| 44 | 44 |
///to handle the cross references. |
| 45 | 45 |
///\tparam _Compare A class for the ordering of the priorities. The |
| 46 | 46 |
///default is \c std::less<_Prio>. |
| 47 | 47 |
/// |
| 48 | 48 |
///\sa FibHeap |
| 49 | 49 |
///\sa Dijkstra |
| 50 | 50 |
template <typename _Prio, typename _ItemIntMap, |
| 51 |
|
|
| 51 |
typename _Compare = std::less<_Prio> > |
|
| 52 | 52 |
class BinHeap {
|
| 53 | 53 |
|
| 54 | 54 |
public: |
| 55 | 55 |
///\e |
| 56 | 56 |
typedef _ItemIntMap ItemIntMap; |
| 57 | 57 |
///\e |
| 58 | 58 |
typedef _Prio Prio; |
| 59 | 59 |
///\e |
| 60 | 60 |
typedef typename ItemIntMap::Key Item; |
| 61 | 61 |
///\e |
| 62 | 62 |
typedef std::pair<Item,Prio> Pair; |
| 63 | 63 |
///\e |
| 64 | 64 |
typedef _Compare Compare; |
| 65 | 65 |
|
| 66 | 66 |
/// \brief Type to represent the items states. |
| 67 | 67 |
/// |
| ... | ... |
@@ -77,270 +77,270 @@ |
| 77 | 77 |
POST_HEAP = -2 |
| 78 | 78 |
}; |
| 79 | 79 |
|
| 80 | 80 |
private: |
| 81 | 81 |
std::vector<Pair> data; |
| 82 | 82 |
Compare comp; |
| 83 | 83 |
ItemIntMap &iim; |
| 84 | 84 |
|
| 85 | 85 |
public: |
| 86 | 86 |
/// \brief The constructor. |
| 87 | 87 |
/// |
| 88 | 88 |
/// The constructor. |
| 89 | 89 |
/// \param _iim should be given to the constructor, since it is used |
| 90 | 90 |
/// internally to handle the cross references. The value of the map |
| 91 | 91 |
/// should be PRE_HEAP (-1) for each element. |
| 92 | 92 |
explicit BinHeap(ItemIntMap &_iim) : iim(_iim) {}
|
| 93 |
|
|
| 93 |
|
|
| 94 | 94 |
/// \brief The constructor. |
| 95 | 95 |
/// |
| 96 | 96 |
/// The constructor. |
| 97 | 97 |
/// \param _iim should be given to the constructor, since it is used |
| 98 | 98 |
/// internally to handle the cross references. The value of the map |
| 99 | 99 |
/// should be PRE_HEAP (-1) for each element. |
| 100 | 100 |
/// |
| 101 | 101 |
/// \param _comp The comparator function object. |
| 102 |
BinHeap(ItemIntMap &_iim, const Compare &_comp) |
|
| 102 |
BinHeap(ItemIntMap &_iim, const Compare &_comp) |
|
| 103 | 103 |
: iim(_iim), comp(_comp) {}
|
| 104 | 104 |
|
| 105 | 105 |
|
| 106 | 106 |
/// The number of items stored in the heap. |
| 107 | 107 |
/// |
| 108 | 108 |
/// \brief Returns the number of items stored in the heap. |
| 109 | 109 |
int size() const { return data.size(); }
|
| 110 |
|
|
| 110 |
|
|
| 111 | 111 |
/// \brief Checks if the heap stores no items. |
| 112 | 112 |
/// |
| 113 | 113 |
/// Returns \c true if and only if the heap stores no items. |
| 114 | 114 |
bool empty() const { return data.empty(); }
|
| 115 | 115 |
|
| 116 | 116 |
/// \brief Make empty this heap. |
| 117 |
/// |
|
| 117 |
/// |
|
| 118 | 118 |
/// Make empty this heap. It does not change the cross reference map. |
| 119 | 119 |
/// If you want to reuse what is not surely empty you should first clear |
| 120 | 120 |
/// the heap and after that you should set the cross reference map for |
| 121 | 121 |
/// each item to \c PRE_HEAP. |
| 122 |
void clear() {
|
|
| 123 |
data.clear(); |
|
| 122 |
void clear() {
|
|
| 123 |
data.clear(); |
|
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 | 126 |
private: |
| 127 | 127 |
static int parent(int i) { return (i-1)/2; }
|
| 128 | 128 |
|
| 129 | 129 |
static int second_child(int i) { return 2*i+2; }
|
| 130 | 130 |
bool less(const Pair &p1, const Pair &p2) const {
|
| 131 | 131 |
return comp(p1.second, p2.second); |
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 | 134 |
int bubble_up(int hole, Pair p) {
|
| 135 | 135 |
int par = parent(hole); |
| 136 | 136 |
while( hole>0 && less(p,data[par]) ) {
|
| 137 |
move(data[par],hole); |
|
| 138 |
hole = par; |
|
| 139 |
|
|
| 137 |
move(data[par],hole); |
|
| 138 |
hole = par; |
|
| 139 |
par = parent(hole); |
|
| 140 | 140 |
} |
| 141 | 141 |
move(p, hole); |
| 142 | 142 |
return hole; |
| 143 | 143 |
} |
| 144 | 144 |
|
| 145 | 145 |
int bubble_down(int hole, Pair p, int length) {
|
| 146 | 146 |
int child = second_child(hole); |
| 147 | 147 |
while(child < length) {
|
| 148 |
if( less(data[child-1], data[child]) ) {
|
|
| 149 |
--child; |
|
| 150 |
} |
|
| 151 |
if( !less(data[child], p) ) |
|
| 152 |
goto ok; |
|
| 153 |
move(data[child], hole); |
|
| 154 |
hole = child; |
|
| 155 |
child = second_child(hole); |
|
| 148 |
if( less(data[child-1], data[child]) ) {
|
|
| 149 |
--child; |
|
| 150 |
} |
|
| 151 |
if( !less(data[child], p) ) |
|
| 152 |
goto ok; |
|
| 153 |
move(data[child], hole); |
|
| 154 |
hole = child; |
|
| 155 |
child = second_child(hole); |
|
| 156 | 156 |
} |
| 157 | 157 |
child--; |
| 158 | 158 |
if( child<length && less(data[child], p) ) {
|
| 159 |
move(data[child], hole); |
|
| 160 |
hole=child; |
|
| 159 |
move(data[child], hole); |
|
| 160 |
hole=child; |
|
| 161 | 161 |
} |
| 162 | 162 |
ok: |
| 163 | 163 |
move(p, hole); |
| 164 | 164 |
return hole; |
| 165 | 165 |
} |
| 166 | 166 |
|
| 167 | 167 |
void move(const Pair &p, int i) {
|
| 168 | 168 |
data[i] = p; |
| 169 | 169 |
iim.set(p.first, i); |
| 170 | 170 |
} |
| 171 | 171 |
|
| 172 | 172 |
public: |
| 173 | 173 |
/// \brief Insert a pair of item and priority into the heap. |
| 174 | 174 |
/// |
| 175 | 175 |
/// Adds \c p.first to the heap with priority \c p.second. |
| 176 | 176 |
/// \param p The pair to insert. |
| 177 | 177 |
void push(const Pair &p) {
|
| 178 | 178 |
int n = data.size(); |
| 179 | 179 |
data.resize(n+1); |
| 180 | 180 |
bubble_up(n, p); |
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 | 183 |
/// \brief Insert an item into the heap with the given heap. |
| 184 |
/// |
|
| 185 |
/// Adds \c i to the heap with priority \c p. |
|
| 184 |
/// |
|
| 185 |
/// Adds \c i to the heap with priority \c p. |
|
| 186 | 186 |
/// \param i The item to insert. |
| 187 | 187 |
/// \param p The priority of the item. |
| 188 | 188 |
void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
|
| 189 | 189 |
|
| 190 | 190 |
/// \brief Returns the item with minimum priority relative to \c Compare. |
| 191 | 191 |
/// |
| 192 | 192 |
/// This method returns the item with minimum priority relative to \c |
| 193 |
/// Compare. |
|
| 194 |
/// \pre The heap must be nonempty. |
|
| 193 |
/// Compare. |
|
| 194 |
/// \pre The heap must be nonempty. |
|
| 195 | 195 |
Item top() const {
|
| 196 | 196 |
return data[0].first; |
| 197 | 197 |
} |
| 198 | 198 |
|
| 199 | 199 |
/// \brief Returns the minimum priority relative to \c Compare. |
| 200 | 200 |
/// |
| 201 | 201 |
/// It returns the minimum priority relative to \c Compare. |
| 202 | 202 |
/// \pre The heap must be nonempty. |
| 203 | 203 |
Prio prio() const {
|
| 204 | 204 |
return data[0].second; |
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 | 207 |
/// \brief Deletes the item with minimum priority relative to \c Compare. |
| 208 | 208 |
/// |
| 209 | 209 |
/// This method deletes the item with minimum priority relative to \c |
| 210 |
/// Compare from the heap. |
|
| 211 |
/// \pre The heap must be non-empty. |
|
| 210 |
/// Compare from the heap. |
|
| 211 |
/// \pre The heap must be non-empty. |
|
| 212 | 212 |
void pop() {
|
| 213 | 213 |
int n = data.size()-1; |
| 214 | 214 |
iim.set(data[0].first, POST_HEAP); |
| 215 | 215 |
if (n > 0) {
|
| 216 |
|
|
| 216 |
bubble_down(0, data[n], n); |
|
| 217 | 217 |
} |
| 218 | 218 |
data.pop_back(); |
| 219 | 219 |
} |
| 220 | 220 |
|
| 221 | 221 |
/// \brief Deletes \c i from the heap. |
| 222 | 222 |
/// |
| 223 | 223 |
/// This method deletes item \c i from the heap. |
| 224 | 224 |
/// \param i The item to erase. |
| 225 | 225 |
/// \pre The item should be in the heap. |
| 226 | 226 |
void erase(const Item &i) {
|
| 227 | 227 |
int h = iim[i]; |
| 228 | 228 |
int n = data.size()-1; |
| 229 | 229 |
iim.set(data[h].first, POST_HEAP); |
| 230 | 230 |
if( h < n ) {
|
| 231 |
if ( bubble_up(h, data[n]) == h) {
|
|
| 232 |
bubble_down(h, data[n], n); |
|
| 233 |
|
|
| 231 |
if ( bubble_up(h, data[n]) == h) {
|
|
| 232 |
bubble_down(h, data[n], n); |
|
| 233 |
} |
|
| 234 | 234 |
} |
| 235 | 235 |
data.pop_back(); |
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 |
|
|
| 238 |
|
|
| 239 | 239 |
/// \brief Returns the priority of \c i. |
| 240 | 240 |
/// |
| 241 |
/// This function returns the priority of item \c i. |
|
| 241 |
/// This function returns the priority of item \c i. |
|
| 242 | 242 |
/// \pre \c i must be in the heap. |
| 243 | 243 |
/// \param i The item. |
| 244 | 244 |
Prio operator[](const Item &i) const {
|
| 245 | 245 |
int idx = iim[i]; |
| 246 | 246 |
return data[idx].second; |
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 |
/// \brief \c i gets to the heap with priority \c p independently |
|
| 249 |
/// \brief \c i gets to the heap with priority \c p independently |
|
| 250 | 250 |
/// if \c i was already there. |
| 251 | 251 |
/// |
| 252 | 252 |
/// This method calls \ref push(\c i, \c p) if \c i is not stored |
| 253 | 253 |
/// in the heap and sets the priority of \c i to \c p otherwise. |
| 254 | 254 |
/// \param i The item. |
| 255 | 255 |
/// \param p The priority. |
| 256 | 256 |
void set(const Item &i, const Prio &p) {
|
| 257 | 257 |
int idx = iim[i]; |
| 258 | 258 |
if( idx < 0 ) {
|
| 259 |
|
|
| 259 |
push(i,p); |
|
| 260 | 260 |
} |
| 261 | 261 |
else if( comp(p, data[idx].second) ) {
|
| 262 |
|
|
| 262 |
bubble_up(idx, Pair(i,p)); |
|
| 263 | 263 |
} |
| 264 | 264 |
else {
|
| 265 |
|
|
| 265 |
bubble_down(idx, Pair(i,p), data.size()); |
|
| 266 | 266 |
} |
| 267 | 267 |
} |
| 268 | 268 |
|
| 269 | 269 |
/// \brief Decreases the priority of \c i to \c p. |
| 270 | 270 |
/// |
| 271 | 271 |
/// This method decreases the priority of item \c i to \c p. |
| 272 | 272 |
/// \pre \c i must be stored in the heap with priority at least \c |
| 273 | 273 |
/// p relative to \c Compare. |
| 274 | 274 |
/// \param i The item. |
| 275 | 275 |
/// \param p The priority. |
| 276 | 276 |
void decrease(const Item &i, const Prio &p) {
|
| 277 | 277 |
int idx = iim[i]; |
| 278 | 278 |
bubble_up(idx, Pair(i,p)); |
| 279 | 279 |
} |
| 280 |
|
|
| 280 |
|
|
| 281 | 281 |
/// \brief Increases the priority of \c i to \c p. |
| 282 | 282 |
/// |
| 283 |
/// This method sets the priority of item \c i to \c p. |
|
| 283 |
/// This method sets the priority of item \c i to \c p. |
|
| 284 | 284 |
/// \pre \c i must be stored in the heap with priority at most \c |
| 285 | 285 |
/// p relative to \c Compare. |
| 286 | 286 |
/// \param i The item. |
| 287 | 287 |
/// \param p The priority. |
| 288 | 288 |
void increase(const Item &i, const Prio &p) {
|
| 289 | 289 |
int idx = iim[i]; |
| 290 | 290 |
bubble_down(idx, Pair(i,p), data.size()); |
| 291 | 291 |
} |
| 292 | 292 |
|
| 293 |
/// \brief Returns if \c item is in, has already been in, or has |
|
| 293 |
/// \brief Returns if \c item is in, has already been in, or has |
|
| 294 | 294 |
/// never been in the heap. |
| 295 | 295 |
/// |
| 296 | 296 |
/// This method returns PRE_HEAP if \c item has never been in the |
| 297 | 297 |
/// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP |
| 298 | 298 |
/// otherwise. In the latter case it is possible that \c item will |
| 299 | 299 |
/// get back to the heap again. |
| 300 | 300 |
/// \param i The item. |
| 301 | 301 |
State state(const Item &i) const {
|
| 302 | 302 |
int s = iim[i]; |
| 303 | 303 |
if( s>=0 ) |
| 304 |
|
|
| 304 |
s=0; |
|
| 305 | 305 |
return State(s); |
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
/// \brief Sets the state of the \c item in the heap. |
| 309 | 309 |
/// |
| 310 | 310 |
/// Sets the state of the \c item in the heap. It can be used to |
| 311 | 311 |
/// manually clear the heap when it is important to achive the |
| 312 | 312 |
/// better time complexity. |
| 313 | 313 |
/// \param i The item. |
| 314 |
/// \param st The state. It should not be \c IN_HEAP. |
|
| 314 |
/// \param st The state. It should not be \c IN_HEAP. |
|
| 315 | 315 |
void state(const Item& i, State st) {
|
| 316 | 316 |
switch (st) {
|
| 317 | 317 |
case POST_HEAP: |
| 318 | 318 |
case PRE_HEAP: |
| 319 | 319 |
if (state(i) == IN_HEAP) {
|
| 320 | 320 |
erase(i); |
| 321 | 321 |
} |
| 322 | 322 |
iim[i] = st; |
| 323 | 323 |
break; |
| 324 | 324 |
case IN_HEAP: |
| 325 | 325 |
break; |
| 326 | 326 |
} |
| 327 | 327 |
} |
| 328 | 328 |
|
| 329 | 329 |
/// \brief Replaces an item in the heap. |
| 330 | 330 |
/// |
| 331 | 331 |
/// The \c i item is replaced with \c j item. The \c i item should |
| 332 | 332 |
/// be in the heap, while the \c j should be out of the heap. The |
| 333 | 333 |
/// \c i item will out of the heap and \c j will be in the heap |
| 334 | 334 |
/// with the same prioriority as prevoiusly the \c i item. |
| 335 | 335 |
void replace(const Item& i, const Item& j) {
|
| 336 | 336 |
int idx = iim[i]; |
| 337 | 337 |
iim.set(i, iim[j]); |
| 338 | 338 |
iim.set(j, idx); |
| 339 | 339 |
data[idx].first = j; |
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
}; // class BinHeap |
| 343 |
|
|
| 343 |
|
|
| 344 | 344 |
} // namespace lemon |
| 345 | 345 |
|
| 346 | 346 |
#endif // LEMON_BIN_HEAP_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_ALTERATION_NOTIFIER_H |
| 20 | 20 |
#define LEMON_BITS_ALTERATION_NOTIFIER_H |
| 21 | 21 |
|
| 22 | 22 |
#include <vector> |
| 23 | 23 |
#include <list> |
| 24 | 24 |
|
| 25 | 25 |
#include <lemon/bits/utility.h> |
| 26 | 26 |
|
| 27 | 27 |
///\ingroup graphbits |
| 28 | 28 |
///\file |
| 29 | 29 |
///\brief Observer notifier for graph alteration observers. |
| 30 | 30 |
|
| 31 | 31 |
namespace lemon {
|
| 32 | 32 |
|
| 33 | 33 |
/// \ingroup graphbits |
| 34 | 34 |
/// |
| 35 |
/// \brief Notifier class to notify observes about alterations in |
|
| 35 |
/// \brief Notifier class to notify observes about alterations in |
|
| 36 | 36 |
/// a container. |
| 37 | 37 |
/// |
| 38 | 38 |
/// The simple graph's can be refered as two containers, one node container |
| 39 | 39 |
/// and one edge container. But they are not standard containers they |
| 40 | 40 |
/// does not store values directly they are just key continars for more |
| 41 | 41 |
/// value containers which are the node and edge maps. |
| 42 | 42 |
/// |
| 43 | 43 |
/// The graph's node and edge sets can be changed as we add or erase |
| 44 | 44 |
/// nodes and edges in the graph. Lemon would like to handle easily |
| 45 | 45 |
/// that the node and edge maps should contain values for all nodes or |
| 46 | 46 |
/// edges. If we want to check on every indicing if the map contains |
| 47 | 47 |
/// the current indicing key that cause a drawback in the performance |
| 48 | 48 |
/// in the library. We use another solution we notify all maps about |
| 49 | 49 |
/// an alteration in the graph, which cause only drawback on the |
| 50 | 50 |
/// alteration of the graph. |
| 51 | 51 |
/// |
| 52 |
/// This class provides an interface to the container. The \e first() and \e |
|
| 52 |
/// This class provides an interface to the container. The \e first() and \e |
|
| 53 | 53 |
/// next() member functions make possible to iterate on the keys of the |
| 54 | 54 |
/// container. The \e id() function returns an integer id for each key. |
| 55 | 55 |
/// The \e maxId() function gives back an upper bound of the ids. |
| 56 | 56 |
/// |
| 57 | 57 |
/// For the proper functonality of this class, we should notify it |
| 58 | 58 |
/// about each alteration in the container. The alterations have four type |
| 59 | 59 |
/// as \e add(), \e erase(), \e build() and \e clear(). The \e add() and |
| 60 | 60 |
/// \e erase() signals that only one or few items added or erased to or |
| 61 | 61 |
/// from the graph. If all items are erased from the graph or from an empty |
| 62 | 62 |
/// graph a new graph is builded then it can be signaled with the |
| 63 |
/// clear() and build() members. Important rule that if we erase items |
|
| 63 |
/// clear() and build() members. Important rule that if we erase items |
|
| 64 | 64 |
/// from graph we should first signal the alteration and after that erase |
| 65 | 65 |
/// them from the container, on the other way on item addition we should |
| 66 | 66 |
/// first extend the container and just after that signal the alteration. |
| 67 | 67 |
/// |
| 68 | 68 |
/// The alteration can be observed with a class inherited from the |
| 69 | 69 |
/// \e ObserverBase nested class. The signals can be handled with |
| 70 | 70 |
/// overriding the virtual functions defined in the base class. The |
| 71 |
/// observer base can be attached to the notifier with the |
|
| 71 |
/// observer base can be attached to the notifier with the |
|
| 72 | 72 |
/// \e attach() member and can be detached with detach() function. The |
| 73 | 73 |
/// alteration handlers should not call any function which signals |
| 74 | 74 |
/// an other alteration in the same notifier and should not |
| 75 | 75 |
/// detach any observer from the notifier. |
| 76 | 76 |
/// |
| 77 | 77 |
/// Alteration observers try to be exception safe. If an \e add() or |
| 78 | 78 |
/// a \e clear() function throws an exception then the remaining |
| 79 | 79 |
/// observeres will not be notified and the fulfilled additions will |
| 80 | 80 |
/// be rolled back by calling the \e erase() or \e clear() |
| 81 | 81 |
/// functions. Thence the \e erase() and \e clear() should not throw |
| 82 |
/// exception. Actullay, it can be throw only |
|
| 82 |
/// exception. Actullay, it can be throw only |
|
| 83 | 83 |
/// \ref AlterationObserver::ImmediateDetach ImmediateDetach |
| 84 | 84 |
/// exception which detach the observer from the notifier. |
| 85 | 85 |
/// |
| 86 | 86 |
/// There are some place when the alteration observing is not completly |
| 87 | 87 |
/// reliable. If we want to carry out the node degree in the graph |
| 88 |
/// as in the \ref InDegMap and we use the reverseEdge that cause |
|
| 88 |
/// as in the \ref InDegMap and we use the reverseEdge that cause |
|
| 89 | 89 |
/// unreliable functionality. Because the alteration observing signals |
| 90 | 90 |
/// only erasing and adding but not the reversing it will stores bad |
| 91 | 91 |
/// degrees. The sub graph adaptors cannot signal the alterations because |
| 92 | 92 |
/// just a setting in the filter map can modify the graph and this cannot |
| 93 | 93 |
/// be watched in any way. |
| 94 | 94 |
/// |
| 95 | 95 |
/// \param _Container The container which is observed. |
| 96 | 96 |
/// \param _Item The item type which is obserbved. |
| 97 | 97 |
|
| 98 | 98 |
template <typename _Container, typename _Item> |
| 99 | 99 |
class AlterationNotifier {
|
| 100 | 100 |
public: |
| 101 | 101 |
|
| 102 | 102 |
typedef True Notifier; |
| 103 | 103 |
|
| 104 | 104 |
typedef _Container Container; |
| 105 | 105 |
typedef _Item Item; |
| 106 | 106 |
|
| 107 |
/// \brief Exception which can be called from \e clear() and |
|
| 107 |
/// \brief Exception which can be called from \e clear() and |
|
| 108 | 108 |
/// \e erase(). |
| 109 | 109 |
/// |
| 110 | 110 |
/// From the \e clear() and \e erase() function only this |
| 111 | 111 |
/// exception is allowed to throw. The exception immediatly |
| 112 | 112 |
/// detaches the current observer from the notifier. Because the |
| 113 | 113 |
/// \e clear() and \e erase() should not throw other exceptions |
| 114 | 114 |
/// it can be used to invalidate the observer. |
| 115 | 115 |
struct ImmediateDetach {};
|
| 116 | 116 |
|
| 117 | 117 |
/// \brief ObserverBase is the base class for the observers. |
| 118 | 118 |
/// |
| 119 | 119 |
/// ObserverBase is the abstract base class for the observers. |
| 120 | 120 |
/// It will be notified about an item was inserted into or |
| 121 | 121 |
/// erased from the graph. |
| 122 | 122 |
/// |
| 123 | 123 |
/// The observer interface contains some pure virtual functions |
| 124 | 124 |
/// to override. The add() and erase() functions are |
| 125 | 125 |
/// to notify the oberver when one item is added or |
| 126 | 126 |
/// erased. |
| 127 | 127 |
/// |
| 128 | 128 |
/// The build() and clear() members are to notify the observer |
| 129 | 129 |
/// about the container is built from an empty container or |
| 130 |
/// is cleared to an empty container. |
|
| 130 |
/// is cleared to an empty container. |
|
| 131 | 131 |
|
| 132 | 132 |
class ObserverBase {
|
| 133 | 133 |
protected: |
| 134 | 134 |
typedef AlterationNotifier Notifier; |
| 135 | 135 |
|
| 136 | 136 |
friend class AlterationNotifier; |
| 137 | 137 |
|
| 138 | 138 |
/// \brief Default constructor. |
| 139 | 139 |
/// |
| 140 | 140 |
/// Default constructor for ObserverBase. |
| 141 |
/// |
|
| 141 |
/// |
|
| 142 | 142 |
ObserverBase() : _notifier(0) {}
|
| 143 | 143 |
|
| 144 | 144 |
/// \brief Constructor which attach the observer into notifier. |
| 145 | 145 |
/// |
| 146 | 146 |
/// Constructor which attach the observer into notifier. |
| 147 | 147 |
ObserverBase(AlterationNotifier& nf) {
|
| 148 | 148 |
attach(nf); |
| 149 | 149 |
} |
| 150 | 150 |
|
| 151 | 151 |
/// \brief Constructor which attach the obserever to the same notifier. |
| 152 | 152 |
/// |
| 153 | 153 |
/// Constructor which attach the obserever to the same notifier as |
| 154 |
/// the other observer is attached to. |
|
| 154 |
/// the other observer is attached to. |
|
| 155 | 155 |
ObserverBase(const ObserverBase& copy) {
|
| 156 |
|
|
| 156 |
if (copy.attached()) {
|
|
| 157 | 157 |
attach(*copy.notifier()); |
| 158 |
|
|
| 158 |
} |
|
| 159 | 159 |
} |
| 160 |
|
|
| 160 |
|
|
| 161 | 161 |
/// \brief Destructor |
| 162 | 162 |
virtual ~ObserverBase() {
|
| 163 | 163 |
if (attached()) {
|
| 164 | 164 |
detach(); |
| 165 | 165 |
} |
| 166 | 166 |
} |
| 167 | 167 |
|
| 168 | 168 |
/// \brief Attaches the observer into an AlterationNotifier. |
| 169 | 169 |
/// |
| 170 | 170 |
/// This member attaches the observer into an AlterationNotifier. |
| 171 | 171 |
/// |
| 172 | 172 |
void attach(AlterationNotifier& nf) {
|
| 173 |
|
|
| 173 |
nf.attach(*this); |
|
| 174 | 174 |
} |
| 175 |
|
|
| 175 |
|
|
| 176 | 176 |
/// \brief Detaches the observer into an AlterationNotifier. |
| 177 | 177 |
/// |
| 178 | 178 |
/// This member detaches the observer from an AlterationNotifier. |
| 179 | 179 |
/// |
| 180 | 180 |
void detach() {
|
| 181 | 181 |
_notifier->detach(*this); |
| 182 | 182 |
} |
| 183 |
|
|
| 184 |
/// \brief Gives back a pointer to the notifier which the map |
|
| 183 |
|
|
| 184 |
/// \brief Gives back a pointer to the notifier which the map |
|
| 185 | 185 |
/// attached into. |
| 186 | 186 |
/// |
| 187 | 187 |
/// This function gives back a pointer to the notifier which the map |
| 188 | 188 |
/// attached into. |
| 189 | 189 |
/// |
| 190 | 190 |
Notifier* notifier() const { return const_cast<Notifier*>(_notifier); }
|
| 191 |
|
|
| 191 |
|
|
| 192 | 192 |
/// Gives back true when the observer is attached into a notifier. |
| 193 | 193 |
bool attached() const { return _notifier != 0; }
|
| 194 | 194 |
|
| 195 | 195 |
private: |
| 196 | 196 |
|
| 197 | 197 |
ObserverBase& operator=(const ObserverBase& copy); |
| 198 | 198 |
|
| 199 | 199 |
protected: |
| 200 |
|
|
| 200 |
|
|
| 201 | 201 |
Notifier* _notifier; |
| 202 | 202 |
typename std::list<ObserverBase*>::iterator _index; |
| 203 | 203 |
|
| 204 | 204 |
/// \brief The member function to notificate the observer about an |
| 205 | 205 |
/// item is added to the container. |
| 206 | 206 |
/// |
| 207 | 207 |
/// The add() member function notificates the observer about an item |
| 208 | 208 |
/// is added to the container. It have to be overrided in the |
| 209 | 209 |
/// subclasses. |
| 210 | 210 |
virtual void add(const Item&) = 0; |
| 211 | 211 |
|
| 212 |
/// \brief The member function to notificate the observer about |
|
| 212 |
/// \brief The member function to notificate the observer about |
|
| 213 | 213 |
/// more item is added to the container. |
| 214 | 214 |
/// |
| 215 | 215 |
/// The add() member function notificates the observer about more item |
| 216 | 216 |
/// is added to the container. It have to be overrided in the |
| 217 | 217 |
/// subclasses. |
| 218 | 218 |
virtual void add(const std::vector<Item>& items) = 0; |
| 219 | 219 |
|
| 220 | 220 |
/// \brief The member function to notificate the observer about an |
| 221 | 221 |
/// item is erased from the container. |
| 222 | 222 |
/// |
| 223 | 223 |
/// The erase() member function notificates the observer about an |
| 224 | 224 |
/// item is erased from the container. It have to be overrided in |
| 225 |
/// the subclasses. |
|
| 225 |
/// the subclasses. |
|
| 226 | 226 |
virtual void erase(const Item&) = 0; |
| 227 | 227 |
|
| 228 |
/// \brief The member function to notificate the observer about |
|
| 228 |
/// \brief The member function to notificate the observer about |
|
| 229 | 229 |
/// more item is erased from the container. |
| 230 | 230 |
/// |
| 231 | 231 |
/// The erase() member function notificates the observer about more item |
| 232 | 232 |
/// is erased from the container. It have to be overrided in the |
| 233 | 233 |
/// subclasses. |
| 234 | 234 |
virtual void erase(const std::vector<Item>& items) = 0; |
| 235 | 235 |
|
| 236 | 236 |
/// \brief The member function to notificate the observer about the |
| 237 | 237 |
/// container is built. |
| 238 | 238 |
/// |
| 239 | 239 |
/// The build() member function notificates the observer about the |
| 240 | 240 |
/// container is built from an empty container. It have to be |
| 241 | 241 |
/// overrided in the subclasses. |
| 242 | 242 |
|
| 243 | 243 |
virtual void build() = 0; |
| 244 | 244 |
|
| 245 | 245 |
/// \brief The member function to notificate the observer about all |
| 246 | 246 |
/// items are erased from the container. |
| 247 | 247 |
/// |
| 248 | 248 |
/// The clear() member function notificates the observer about all |
| 249 | 249 |
/// items are erased from the container. It have to be overrided in |
| 250 |
/// the subclasses. |
|
| 250 |
/// the subclasses. |
|
| 251 | 251 |
virtual void clear() = 0; |
| 252 | 252 |
|
| 253 | 253 |
}; |
| 254 |
|
|
| 254 |
|
|
| 255 | 255 |
protected: |
| 256 | 256 |
|
| 257 | 257 |
const Container* container; |
| 258 | 258 |
|
| 259 |
typedef std::list<ObserverBase*> Observers; |
|
| 259 |
typedef std::list<ObserverBase*> Observers; |
|
| 260 | 260 |
Observers _observers; |
| 261 | 261 |
|
| 262 |
|
|
| 262 |
|
|
| 263 | 263 |
public: |
| 264 | 264 |
|
| 265 | 265 |
/// \brief Default constructor. |
| 266 | 266 |
/// |
| 267 |
/// The default constructor of the AlterationNotifier. |
|
| 267 |
/// The default constructor of the AlterationNotifier. |
|
| 268 | 268 |
/// It creates an empty notifier. |
| 269 |
AlterationNotifier() |
|
| 269 |
AlterationNotifier() |
|
| 270 | 270 |
: container(0) {}
|
| 271 | 271 |
|
| 272 | 272 |
/// \brief Constructor. |
| 273 | 273 |
/// |
| 274 | 274 |
/// Constructor with the observed container parameter. |
| 275 |
AlterationNotifier(const Container& _container) |
|
| 275 |
AlterationNotifier(const Container& _container) |
|
| 276 | 276 |
: container(&_container) {}
|
| 277 | 277 |
|
| 278 |
/// \brief Copy Constructor of the AlterationNotifier. |
|
| 278 |
/// \brief Copy Constructor of the AlterationNotifier. |
|
| 279 | 279 |
/// |
| 280 |
/// Copy constructor of the AlterationNotifier. |
|
| 280 |
/// Copy constructor of the AlterationNotifier. |
|
| 281 | 281 |
/// It creates only an empty notifier because the copiable |
| 282 | 282 |
/// notifier's observers have to be registered still into that notifier. |
| 283 |
AlterationNotifier(const AlterationNotifier& _notifier) |
|
| 283 |
AlterationNotifier(const AlterationNotifier& _notifier) |
|
| 284 | 284 |
: container(_notifier.container) {}
|
| 285 | 285 |
|
| 286 | 286 |
/// \brief Destructor. |
| 287 |
/// |
|
| 287 |
/// |
|
| 288 | 288 |
/// Destructor of the AlterationNotifier. |
| 289 | 289 |
/// |
| 290 | 290 |
~AlterationNotifier() {
|
| 291 | 291 |
typename Observers::iterator it; |
| 292 | 292 |
for (it = _observers.begin(); it != _observers.end(); ++it) {
|
| 293 |
|
|
| 293 |
(*it)->_notifier = 0; |
|
| 294 | 294 |
} |
| 295 | 295 |
} |
| 296 | 296 |
|
| 297 | 297 |
/// \brief Sets the container. |
| 298 | 298 |
/// |
| 299 | 299 |
/// Sets the container. |
| 300 | 300 |
void setContainer(const Container& _container) {
|
| 301 | 301 |
container = &_container; |
| 302 | 302 |
} |
| 303 | 303 |
|
| 304 | 304 |
protected: |
| 305 | 305 |
|
| 306 | 306 |
AlterationNotifier& operator=(const AlterationNotifier&); |
| 307 | 307 |
|
| 308 | 308 |
public: |
| 309 | 309 |
|
| ... | ... |
@@ -325,151 +325,151 @@ |
| 325 | 325 |
container->next(item); |
| 326 | 326 |
} |
| 327 | 327 |
|
| 328 | 328 |
/// \brief Returns the id of the item. |
| 329 | 329 |
/// |
| 330 | 330 |
/// Returns the id of the item provided by the container. |
| 331 | 331 |
int id(const Item& item) const {
|
| 332 | 332 |
return container->id(item); |
| 333 | 333 |
} |
| 334 | 334 |
|
| 335 | 335 |
/// \brief Returns the maximum id of the container. |
| 336 | 336 |
/// |
| 337 | 337 |
/// Returns the maximum id of the container. |
| 338 | 338 |
int maxId() const {
|
| 339 | 339 |
return container->maxId(Item()); |
| 340 | 340 |
} |
| 341 |
|
|
| 341 |
|
|
| 342 | 342 |
protected: |
| 343 | 343 |
|
| 344 | 344 |
void attach(ObserverBase& observer) {
|
| 345 | 345 |
observer._index = _observers.insert(_observers.begin(), &observer); |
| 346 | 346 |
observer._notifier = this; |
| 347 |
} |
|
| 347 |
} |
|
| 348 | 348 |
|
| 349 | 349 |
void detach(ObserverBase& observer) {
|
| 350 | 350 |
_observers.erase(observer._index); |
| 351 | 351 |
observer._index = _observers.end(); |
| 352 | 352 |
observer._notifier = 0; |
| 353 | 353 |
} |
| 354 | 354 |
|
| 355 | 355 |
public: |
| 356 |
|
|
| 357 |
/// \brief Notifies all the registed observers about an item added to |
|
| 356 |
|
|
| 357 |
/// \brief Notifies all the registed observers about an item added to |
|
| 358 | 358 |
/// the container. |
| 359 | 359 |
/// |
| 360 |
/// It notifies all the registed observers about an item added to |
|
| 360 |
/// It notifies all the registed observers about an item added to |
|
| 361 | 361 |
/// the container. |
| 362 |
/// |
|
| 362 |
/// |
|
| 363 | 363 |
void add(const Item& item) {
|
| 364 | 364 |
typename Observers::reverse_iterator it; |
| 365 | 365 |
try {
|
| 366 | 366 |
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
|
| 367 | 367 |
(*it)->add(item); |
| 368 | 368 |
} |
| 369 | 369 |
} catch (...) {
|
| 370 | 370 |
typename Observers::iterator jt; |
| 371 | 371 |
for (jt = it.base(); jt != _observers.end(); ++jt) {
|
| 372 | 372 |
(*jt)->erase(item); |
| 373 | 373 |
} |
| 374 | 374 |
throw; |
| 375 | 375 |
} |
| 376 |
} |
|
| 376 |
} |
|
| 377 | 377 |
|
| 378 |
/// \brief Notifies all the registed observers about more item added to |
|
| 378 |
/// \brief Notifies all the registed observers about more item added to |
|
| 379 | 379 |
/// the container. |
| 380 | 380 |
/// |
| 381 |
/// It notifies all the registed observers about more item added to |
|
| 381 |
/// It notifies all the registed observers about more item added to |
|
| 382 | 382 |
/// the container. |
| 383 |
/// |
|
| 383 |
/// |
|
| 384 | 384 |
void add(const std::vector<Item>& items) {
|
| 385 | 385 |
typename Observers::reverse_iterator it; |
| 386 | 386 |
try {
|
| 387 | 387 |
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
|
| 388 | 388 |
(*it)->add(items); |
| 389 | 389 |
} |
| 390 | 390 |
} catch (...) {
|
| 391 | 391 |
typename Observers::iterator jt; |
| 392 | 392 |
for (jt = it.base(); jt != _observers.end(); ++jt) {
|
| 393 | 393 |
(*jt)->erase(items); |
| 394 | 394 |
} |
| 395 | 395 |
throw; |
| 396 | 396 |
} |
| 397 |
} |
|
| 397 |
} |
|
| 398 | 398 |
|
| 399 |
/// \brief Notifies all the registed observers about an item erased from |
|
| 399 |
/// \brief Notifies all the registed observers about an item erased from |
|
| 400 | 400 |
/// the container. |
| 401 |
/// |
|
| 402 |
/// It notifies all the registed observers about an item erased from |
|
| 401 |
/// |
|
| 402 |
/// It notifies all the registed observers about an item erased from |
|
| 403 | 403 |
/// the container. |
| 404 |
/// |
|
| 404 |
/// |
|
| 405 | 405 |
void erase(const Item& item) throw() {
|
| 406 | 406 |
typename Observers::iterator it = _observers.begin(); |
| 407 | 407 |
while (it != _observers.end()) {
|
| 408 | 408 |
try {
|
| 409 | 409 |
(*it)->erase(item); |
| 410 | 410 |
++it; |
| 411 | 411 |
} catch (const ImmediateDetach&) {
|
| 412 | 412 |
it = _observers.erase(it); |
| 413 | 413 |
(*it)->_index = _observers.end(); |
| 414 | 414 |
(*it)->_notifier = 0; |
| 415 | 415 |
} |
| 416 | 416 |
} |
| 417 | 417 |
} |
| 418 | 418 |
|
| 419 |
/// \brief Notifies all the registed observers about more item erased |
|
| 419 |
/// \brief Notifies all the registed observers about more item erased |
|
| 420 | 420 |
/// from the container. |
| 421 |
/// |
|
| 422 |
/// It notifies all the registed observers about more item erased from |
|
| 421 |
/// |
|
| 422 |
/// It notifies all the registed observers about more item erased from |
|
| 423 | 423 |
/// the container. |
| 424 |
/// |
|
| 424 |
/// |
|
| 425 | 425 |
void erase(const std::vector<Item>& items) {
|
| 426 | 426 |
typename Observers::iterator it = _observers.begin(); |
| 427 | 427 |
while (it != _observers.end()) {
|
| 428 | 428 |
try {
|
| 429 | 429 |
(*it)->erase(items); |
| 430 | 430 |
++it; |
| 431 | 431 |
} catch (const ImmediateDetach&) {
|
| 432 | 432 |
it = _observers.erase(it); |
| 433 | 433 |
(*it)->_index = _observers.end(); |
| 434 | 434 |
(*it)->_notifier = 0; |
| 435 | 435 |
} |
| 436 | 436 |
} |
| 437 | 437 |
} |
| 438 | 438 |
|
| 439 |
/// \brief Notifies all the registed observers about the container is |
|
| 439 |
/// \brief Notifies all the registed observers about the container is |
|
| 440 | 440 |
/// built. |
| 441 |
/// |
|
| 441 |
/// |
|
| 442 | 442 |
/// Notifies all the registed observers about the container is built |
| 443 | 443 |
/// from an empty container. |
| 444 | 444 |
void build() {
|
| 445 | 445 |
typename Observers::reverse_iterator it; |
| 446 | 446 |
try {
|
| 447 | 447 |
for (it = _observers.rbegin(); it != _observers.rend(); ++it) {
|
| 448 | 448 |
(*it)->build(); |
| 449 | 449 |
} |
| 450 | 450 |
} catch (...) {
|
| 451 | 451 |
typename Observers::iterator jt; |
| 452 | 452 |
for (jt = it.base(); jt != _observers.end(); ++jt) {
|
| 453 | 453 |
(*jt)->clear(); |
| 454 | 454 |
} |
| 455 | 455 |
throw; |
| 456 | 456 |
} |
| 457 | 457 |
} |
| 458 | 458 |
|
| 459 |
/// \brief Notifies all the registed observers about all items are |
|
| 459 |
/// \brief Notifies all the registed observers about all items are |
|
| 460 | 460 |
/// erased. |
| 461 | 461 |
/// |
| 462 | 462 |
/// Notifies all the registed observers about all items are erased |
| 463 | 463 |
/// from the container. |
| 464 | 464 |
void clear() {
|
| 465 | 465 |
typename Observers::iterator it = _observers.begin(); |
| 466 | 466 |
while (it != _observers.end()) {
|
| 467 | 467 |
try {
|
| 468 | 468 |
(*it)->clear(); |
| 469 | 469 |
++it; |
| 470 | 470 |
} catch (const ImmediateDetach&) {
|
| 471 | 471 |
it = _observers.erase(it); |
| 472 | 472 |
(*it)->_index = _observers.end(); |
| 473 | 473 |
(*it)->_notifier = 0; |
| 474 | 474 |
} |
| 475 | 475 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_ARRAY_MAP_H |
| ... | ... |
@@ -25,322 +25,322 @@ |
| 25 | 25 |
#include <lemon/bits/alteration_notifier.h> |
| 26 | 26 |
#include <lemon/concept_check.h> |
| 27 | 27 |
#include <lemon/concepts/maps.h> |
| 28 | 28 |
|
| 29 | 29 |
/// \ingroup graphbits |
| 30 | 30 |
/// \file |
| 31 | 31 |
/// \brief Graph map based on the array storage. |
| 32 | 32 |
|
| 33 | 33 |
namespace lemon {
|
| 34 | 34 |
|
| 35 | 35 |
/// \ingroup graphbits |
| 36 | 36 |
/// |
| 37 | 37 |
/// \brief Graph map based on the array storage. |
| 38 | 38 |
/// |
| 39 | 39 |
/// The ArrayMap template class is graph map structure what |
| 40 | 40 |
/// automatically updates the map when a key is added to or erased from |
| 41 |
/// the map. This map uses the allocators to implement |
|
| 41 |
/// the map. This map uses the allocators to implement |
|
| 42 | 42 |
/// the container functionality. |
| 43 | 43 |
/// |
| 44 | 44 |
/// The template parameters are the Graph the current Item type and |
| 45 | 45 |
/// the Value type of the map. |
| 46 | 46 |
template <typename _Graph, typename _Item, typename _Value> |
| 47 |
class ArrayMap |
|
| 47 |
class ArrayMap |
|
| 48 | 48 |
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
|
| 49 | 49 |
public: |
| 50 |
/// The graph type of the maps. |
|
| 50 |
/// The graph type of the maps. |
|
| 51 | 51 |
typedef _Graph Graph; |
| 52 | 52 |
/// The item type of the map. |
| 53 | 53 |
typedef _Item Item; |
| 54 | 54 |
/// The reference map tag. |
| 55 | 55 |
typedef True ReferenceMapTag; |
| 56 | 56 |
|
| 57 | 57 |
/// The key type of the maps. |
| 58 | 58 |
typedef _Item Key; |
| 59 | 59 |
/// The value type of the map. |
| 60 | 60 |
typedef _Value Value; |
| 61 | 61 |
|
| 62 | 62 |
/// The const reference type of the map. |
| 63 | 63 |
typedef const _Value& ConstReference; |
| 64 | 64 |
/// The reference type of the map. |
| 65 | 65 |
typedef _Value& Reference; |
| 66 | 66 |
|
| 67 | 67 |
/// The notifier type. |
| 68 | 68 |
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier; |
| 69 | 69 |
|
| 70 | 70 |
/// The MapBase of the Map which imlements the core regisitry function. |
| 71 | 71 |
typedef typename Notifier::ObserverBase Parent; |
| 72 |
|
|
| 72 |
|
|
| 73 | 73 |
private: |
| 74 | 74 |
typedef std::allocator<Value> Allocator; |
| 75 | 75 |
|
| 76 | 76 |
public: |
| 77 | 77 |
|
| 78 | 78 |
/// \brief Graph initialized map constructor. |
| 79 | 79 |
/// |
| 80 | 80 |
/// Graph initialized map constructor. |
| 81 | 81 |
explicit ArrayMap(const Graph& graph) {
|
| 82 | 82 |
Parent::attach(graph.notifier(Item())); |
| 83 | 83 |
allocate_memory(); |
| 84 | 84 |
Notifier* nf = Parent::notifier(); |
| 85 | 85 |
Item it; |
| 86 | 86 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 87 |
int id = nf->id(it);; |
|
| 88 |
allocator.construct(&(values[id]), Value()); |
|
| 89 |
|
|
| 87 |
int id = nf->id(it);; |
|
| 88 |
allocator.construct(&(values[id]), Value()); |
|
| 89 |
} |
|
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 |
/// \brief Constructor to use default value to initialize the map. |
|
| 92 |
/// \brief Constructor to use default value to initialize the map. |
|
| 93 | 93 |
/// |
| 94 |
/// It constructs a map and initialize all of the the map. |
|
| 94 |
/// It constructs a map and initialize all of the the map. |
|
| 95 | 95 |
ArrayMap(const Graph& graph, const Value& value) {
|
| 96 | 96 |
Parent::attach(graph.notifier(Item())); |
| 97 | 97 |
allocate_memory(); |
| 98 | 98 |
Notifier* nf = Parent::notifier(); |
| 99 | 99 |
Item it; |
| 100 | 100 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 101 |
int id = nf->id(it);; |
|
| 102 |
allocator.construct(&(values[id]), value); |
|
| 103 |
|
|
| 101 |
int id = nf->id(it);; |
|
| 102 |
allocator.construct(&(values[id]), value); |
|
| 103 |
} |
|
| 104 | 104 |
} |
| 105 | 105 |
|
| 106 | 106 |
/// \brief Constructor to copy a map of the same map type. |
| 107 | 107 |
/// |
| 108 |
/// Constructor to copy a map of the same map type. |
|
| 108 |
/// Constructor to copy a map of the same map type. |
|
| 109 | 109 |
ArrayMap(const ArrayMap& copy) : Parent() {
|
| 110 | 110 |
if (copy.attached()) {
|
| 111 |
|
|
| 111 |
attach(*copy.notifier()); |
|
| 112 | 112 |
} |
| 113 | 113 |
capacity = copy.capacity; |
| 114 | 114 |
if (capacity == 0) return; |
| 115 | 115 |
values = allocator.allocate(capacity); |
| 116 | 116 |
Notifier* nf = Parent::notifier(); |
| 117 | 117 |
Item it; |
| 118 | 118 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 119 |
int id = nf->id(it);; |
|
| 120 |
allocator.construct(&(values[id]), copy.values[id]); |
|
| 119 |
int id = nf->id(it);; |
|
| 120 |
allocator.construct(&(values[id]), copy.values[id]); |
|
| 121 | 121 |
} |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 | 124 |
/// \brief Assign operator. |
| 125 | 125 |
/// |
| 126 | 126 |
/// This operator assigns for each item in the map the |
| 127 |
/// value mapped to the same item in the copied map. |
|
| 127 |
/// value mapped to the same item in the copied map. |
|
| 128 | 128 |
/// The parameter map should be indiced with the same |
| 129 | 129 |
/// itemset because this assign operator does not change |
| 130 |
/// the container of the map. |
|
| 130 |
/// the container of the map. |
|
| 131 | 131 |
ArrayMap& operator=(const ArrayMap& cmap) {
|
| 132 | 132 |
return operator=<ArrayMap>(cmap); |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 | 135 |
|
| 136 | 136 |
/// \brief Template assign operator. |
| 137 | 137 |
/// |
| 138 | 138 |
/// The given parameter should be conform to the ReadMap |
| 139 | 139 |
/// concecpt and could be indiced by the current item set of |
| 140 | 140 |
/// the NodeMap. In this case the value for each item |
| 141 |
/// is assigned by the value of the given ReadMap. |
|
| 141 |
/// is assigned by the value of the given ReadMap. |
|
| 142 | 142 |
template <typename CMap> |
| 143 | 143 |
ArrayMap& operator=(const CMap& cmap) {
|
| 144 | 144 |
checkConcept<concepts::ReadMap<Key, _Value>, CMap>(); |
| 145 | 145 |
const typename Parent::Notifier* nf = Parent::notifier(); |
| 146 | 146 |
Item it; |
| 147 | 147 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 148 | 148 |
set(it, cmap[it]); |
| 149 | 149 |
} |
| 150 | 150 |
return *this; |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 | 153 |
/// \brief The destructor of the map. |
| 154 |
/// |
|
| 154 |
/// |
|
| 155 | 155 |
/// The destructor of the map. |
| 156 |
virtual ~ArrayMap() {
|
|
| 156 |
virtual ~ArrayMap() {
|
|
| 157 | 157 |
if (attached()) {
|
| 158 |
clear(); |
|
| 159 |
detach(); |
|
| 158 |
clear(); |
|
| 159 |
detach(); |
|
| 160 | 160 |
} |
| 161 | 161 |
} |
| 162 |
|
|
| 162 |
|
|
| 163 | 163 |
protected: |
| 164 | 164 |
|
| 165 | 165 |
using Parent::attach; |
| 166 | 166 |
using Parent::detach; |
| 167 | 167 |
using Parent::attached; |
| 168 | 168 |
|
| 169 | 169 |
public: |
| 170 | 170 |
|
| 171 |
/// \brief The subscript operator. |
|
| 171 |
/// \brief The subscript operator. |
|
| 172 | 172 |
/// |
| 173 | 173 |
/// The subscript operator. The map can be subscripted by the |
| 174 |
/// actual keys of the graph. |
|
| 174 |
/// actual keys of the graph. |
|
| 175 | 175 |
Value& operator[](const Key& key) {
|
| 176 | 176 |
int id = Parent::notifier()->id(key); |
| 177 | 177 |
return values[id]; |
| 178 |
} |
|
| 179 |
|
|
| 178 |
} |
|
| 179 |
|
|
| 180 | 180 |
/// \brief The const subscript operator. |
| 181 | 181 |
/// |
| 182 | 182 |
/// The const subscript operator. The map can be subscripted by the |
| 183 |
/// actual keys of the graph. |
|
| 183 |
/// actual keys of the graph. |
|
| 184 | 184 |
const Value& operator[](const Key& key) const {
|
| 185 | 185 |
int id = Parent::notifier()->id(key); |
| 186 | 186 |
return values[id]; |
| 187 | 187 |
} |
| 188 | 188 |
|
| 189 | 189 |
/// \brief Setter function of the map. |
| 190 |
/// |
|
| 190 |
/// |
|
| 191 | 191 |
/// Setter function of the map. Equivalent with map[key] = val. |
| 192 | 192 |
/// This is a compatibility feature with the not dereferable maps. |
| 193 | 193 |
void set(const Key& key, const Value& val) {
|
| 194 | 194 |
(*this)[key] = val; |
| 195 | 195 |
} |
| 196 | 196 |
|
| 197 | 197 |
protected: |
| 198 | 198 |
|
| 199 | 199 |
/// \brief Adds a new key to the map. |
| 200 |
/// |
|
| 200 |
/// |
|
| 201 | 201 |
/// It adds a new key to the map. It called by the observer notifier |
| 202 |
/// and it overrides the add() member function of the observer base. |
|
| 202 |
/// and it overrides the add() member function of the observer base. |
|
| 203 | 203 |
virtual void add(const Key& key) {
|
| 204 | 204 |
Notifier* nf = Parent::notifier(); |
| 205 | 205 |
int id = nf->id(key); |
| 206 | 206 |
if (id >= capacity) {
|
| 207 |
int new_capacity = (capacity == 0 ? 1 : capacity); |
|
| 208 |
while (new_capacity <= id) {
|
|
| 209 |
new_capacity <<= 1; |
|
| 210 |
} |
|
| 211 |
Value* new_values = allocator.allocate(new_capacity); |
|
| 212 |
Item it; |
|
| 213 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 214 |
int jd = nf->id(it);; |
|
| 215 |
if (id != jd) {
|
|
| 216 |
allocator.construct(&(new_values[jd]), values[jd]); |
|
| 217 |
allocator.destroy(&(values[jd])); |
|
| 218 |
} |
|
| 219 |
} |
|
| 220 |
if (capacity != 0) allocator.deallocate(values, capacity); |
|
| 221 |
values = new_values; |
|
| 222 |
capacity = new_capacity; |
|
| 207 |
int new_capacity = (capacity == 0 ? 1 : capacity); |
|
| 208 |
while (new_capacity <= id) {
|
|
| 209 |
new_capacity <<= 1; |
|
| 210 |
} |
|
| 211 |
Value* new_values = allocator.allocate(new_capacity); |
|
| 212 |
Item it; |
|
| 213 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 214 |
int jd = nf->id(it);; |
|
| 215 |
if (id != jd) {
|
|
| 216 |
allocator.construct(&(new_values[jd]), values[jd]); |
|
| 217 |
allocator.destroy(&(values[jd])); |
|
| 218 |
} |
|
| 219 |
} |
|
| 220 |
if (capacity != 0) allocator.deallocate(values, capacity); |
|
| 221 |
values = new_values; |
|
| 222 |
capacity = new_capacity; |
|
| 223 | 223 |
} |
| 224 | 224 |
allocator.construct(&(values[id]), Value()); |
| 225 | 225 |
} |
| 226 | 226 |
|
| 227 | 227 |
/// \brief Adds more new keys to the map. |
| 228 |
/// |
|
| 228 |
/// |
|
| 229 | 229 |
/// It adds more new keys to the map. It called by the observer notifier |
| 230 |
/// and it overrides the add() member function of the observer base. |
|
| 230 |
/// and it overrides the add() member function of the observer base. |
|
| 231 | 231 |
virtual void add(const std::vector<Key>& keys) {
|
| 232 | 232 |
Notifier* nf = Parent::notifier(); |
| 233 | 233 |
int max_id = -1; |
| 234 | 234 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 235 |
int id = nf->id(keys[i]); |
|
| 236 |
if (id > max_id) {
|
|
| 237 |
max_id = id; |
|
| 238 |
} |
|
| 235 |
int id = nf->id(keys[i]); |
|
| 236 |
if (id > max_id) {
|
|
| 237 |
max_id = id; |
|
| 238 |
} |
|
| 239 | 239 |
} |
| 240 | 240 |
if (max_id >= capacity) {
|
| 241 |
int new_capacity = (capacity == 0 ? 1 : capacity); |
|
| 242 |
while (new_capacity <= max_id) {
|
|
| 243 |
new_capacity <<= 1; |
|
| 244 |
} |
|
| 245 |
Value* new_values = allocator.allocate(new_capacity); |
|
| 246 |
Item it; |
|
| 247 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 248 |
int id = nf->id(it); |
|
| 249 |
bool found = false; |
|
| 250 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 251 |
int jd = nf->id(keys[i]); |
|
| 252 |
if (id == jd) {
|
|
| 253 |
found = true; |
|
| 254 |
break; |
|
| 255 |
} |
|
| 256 |
} |
|
| 257 |
if (found) continue; |
|
| 258 |
allocator.construct(&(new_values[id]), values[id]); |
|
| 259 |
allocator.destroy(&(values[id])); |
|
| 260 |
} |
|
| 261 |
if (capacity != 0) allocator.deallocate(values, capacity); |
|
| 262 |
values = new_values; |
|
| 263 |
|
|
| 241 |
int new_capacity = (capacity == 0 ? 1 : capacity); |
|
| 242 |
while (new_capacity <= max_id) {
|
|
| 243 |
new_capacity <<= 1; |
|
| 244 |
} |
|
| 245 |
Value* new_values = allocator.allocate(new_capacity); |
|
| 246 |
Item it; |
|
| 247 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 248 |
int id = nf->id(it); |
|
| 249 |
bool found = false; |
|
| 250 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 251 |
int jd = nf->id(keys[i]); |
|
| 252 |
if (id == jd) {
|
|
| 253 |
found = true; |
|
| 254 |
break; |
|
| 255 |
} |
|
| 256 |
} |
|
| 257 |
if (found) continue; |
|
| 258 |
allocator.construct(&(new_values[id]), values[id]); |
|
| 259 |
allocator.destroy(&(values[id])); |
|
| 260 |
} |
|
| 261 |
if (capacity != 0) allocator.deallocate(values, capacity); |
|
| 262 |
values = new_values; |
|
| 263 |
capacity = new_capacity; |
|
| 264 | 264 |
} |
| 265 | 265 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 266 |
int id = nf->id(keys[i]); |
|
| 267 |
allocator.construct(&(values[id]), Value()); |
|
| 266 |
int id = nf->id(keys[i]); |
|
| 267 |
allocator.construct(&(values[id]), Value()); |
|
| 268 | 268 |
} |
| 269 | 269 |
} |
| 270 |
|
|
| 270 |
|
|
| 271 | 271 |
/// \brief Erase a key from the map. |
| 272 | 272 |
/// |
| 273 | 273 |
/// Erase a key from the map. It called by the observer notifier |
| 274 |
/// and it overrides the erase() member function of the observer base. |
|
| 274 |
/// and it overrides the erase() member function of the observer base. |
|
| 275 | 275 |
virtual void erase(const Key& key) {
|
| 276 | 276 |
int id = Parent::notifier()->id(key); |
| 277 | 277 |
allocator.destroy(&(values[id])); |
| 278 | 278 |
} |
| 279 | 279 |
|
| 280 | 280 |
/// \brief Erase more keys from the map. |
| 281 | 281 |
/// |
| 282 | 282 |
/// Erase more keys from the map. It called by the observer notifier |
| 283 |
/// and it overrides the erase() member function of the observer base. |
|
| 283 |
/// and it overrides the erase() member function of the observer base. |
|
| 284 | 284 |
virtual void erase(const std::vector<Key>& keys) {
|
| 285 | 285 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 286 |
int id = Parent::notifier()->id(keys[i]); |
|
| 287 |
allocator.destroy(&(values[id])); |
|
| 286 |
int id = Parent::notifier()->id(keys[i]); |
|
| 287 |
allocator.destroy(&(values[id])); |
|
| 288 | 288 |
} |
| 289 | 289 |
} |
| 290 | 290 |
|
| 291 | 291 |
/// \brief Buildes the map. |
| 292 |
/// |
|
| 292 |
/// |
|
| 293 | 293 |
/// It buildes the map. It called by the observer notifier |
| 294 |
/// and it overrides the build() member function of the observer base. |
|
| 294 |
/// and it overrides the build() member function of the observer base. |
|
| 295 | 295 |
virtual void build() {
|
| 296 | 296 |
Notifier* nf = Parent::notifier(); |
| 297 | 297 |
allocate_memory(); |
| 298 | 298 |
Item it; |
| 299 | 299 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 300 |
int id = nf->id(it);; |
|
| 301 |
allocator.construct(&(values[id]), Value()); |
|
| 302 |
|
|
| 300 |
int id = nf->id(it);; |
|
| 301 |
allocator.construct(&(values[id]), Value()); |
|
| 302 |
} |
|
| 303 | 303 |
} |
| 304 | 304 |
|
| 305 | 305 |
/// \brief Clear the map. |
| 306 | 306 |
/// |
| 307 | 307 |
/// It erase all items from the map. It called by the observer notifier |
| 308 |
/// and it overrides the clear() member function of the observer base. |
|
| 309 |
virtual void clear() {
|
|
| 308 |
/// and it overrides the clear() member function of the observer base. |
|
| 309 |
virtual void clear() {
|
|
| 310 | 310 |
Notifier* nf = Parent::notifier(); |
| 311 | 311 |
if (capacity != 0) {
|
| 312 |
Item it; |
|
| 313 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 314 |
int id = nf->id(it); |
|
| 315 |
allocator.destroy(&(values[id])); |
|
| 316 |
} |
|
| 317 |
allocator.deallocate(values, capacity); |
|
| 318 |
|
|
| 312 |
Item it; |
|
| 313 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 314 |
int id = nf->id(it); |
|
| 315 |
allocator.destroy(&(values[id])); |
|
| 316 |
} |
|
| 317 |
allocator.deallocate(values, capacity); |
|
| 318 |
capacity = 0; |
|
| 319 | 319 |
} |
| 320 | 320 |
} |
| 321 | 321 |
|
| 322 | 322 |
private: |
| 323 |
|
|
| 323 |
|
|
| 324 | 324 |
void allocate_memory() {
|
| 325 | 325 |
int max_id = Parent::notifier()->maxId(); |
| 326 | 326 |
if (max_id == -1) {
|
| 327 |
capacity = 0; |
|
| 328 |
values = 0; |
|
| 329 |
|
|
| 327 |
capacity = 0; |
|
| 328 |
values = 0; |
|
| 329 |
return; |
|
| 330 | 330 |
} |
| 331 | 331 |
capacity = 1; |
| 332 | 332 |
while (capacity <= max_id) {
|
| 333 |
|
|
| 333 |
capacity <<= 1; |
|
| 334 | 334 |
} |
| 335 |
values = allocator.allocate(capacity); |
|
| 336 |
} |
|
| 335 |
values = allocator.allocate(capacity); |
|
| 336 |
} |
|
| 337 | 337 |
|
| 338 | 338 |
int capacity; |
| 339 | 339 |
Value* values; |
| 340 | 340 |
Allocator allocator; |
| 341 | 341 |
|
| 342 |
}; |
|
| 342 |
}; |
|
| 343 | 343 |
|
| 344 | 344 |
} |
| 345 | 345 |
|
| 346 |
#endif |
|
| 346 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_BASE_EXTENDER_H |
| ... | ... |
@@ -50,40 +50,40 @@ |
| 50 | 50 |
class Arc : public Edge {
|
| 51 | 51 |
friend class UndirDigraphExtender; |
| 52 | 52 |
|
| 53 | 53 |
protected: |
| 54 | 54 |
bool forward; |
| 55 | 55 |
|
| 56 | 56 |
Arc(const Edge &ue, bool _forward) : |
| 57 | 57 |
Edge(ue), forward(_forward) {}
|
| 58 | 58 |
|
| 59 | 59 |
public: |
| 60 | 60 |
Arc() {}
|
| 61 | 61 |
|
| 62 | 62 |
/// Invalid arc constructor |
| 63 | 63 |
Arc(Invalid i) : Edge(i), forward(true) {}
|
| 64 | 64 |
|
| 65 | 65 |
bool operator==(const Arc &that) const {
|
| 66 |
|
|
| 66 |
return forward==that.forward && Edge(*this)==Edge(that); |
|
| 67 | 67 |
} |
| 68 | 68 |
bool operator!=(const Arc &that) const {
|
| 69 |
|
|
| 69 |
return forward!=that.forward || Edge(*this)!=Edge(that); |
|
| 70 | 70 |
} |
| 71 | 71 |
bool operator<(const Arc &that) const {
|
| 72 |
return forward<that.forward || |
|
| 73 |
(!(that.forward<forward) && Edge(*this)<Edge(that)); |
|
| 72 |
return forward<that.forward || |
|
| 73 |
(!(that.forward<forward) && Edge(*this)<Edge(that)); |
|
| 74 | 74 |
} |
| 75 | 75 |
}; |
| 76 | 76 |
|
| 77 | 77 |
|
| 78 | 78 |
|
| 79 | 79 |
using Parent::source; |
| 80 | 80 |
|
| 81 | 81 |
/// Source of the given Arc. |
| 82 | 82 |
Node source(const Arc &e) const {
|
| 83 | 83 |
return e.forward ? Parent::source(e) : Parent::target(e); |
| 84 | 84 |
} |
| 85 | 85 |
|
| 86 | 86 |
using Parent::target; |
| 87 | 87 |
|
| 88 | 88 |
/// Target of the given Arc. |
| 89 | 89 |
Node target(const Arc &e) const {
|
| ... | ... |
@@ -104,105 +104,105 @@ |
| 104 | 104 |
/// |
| 105 | 105 |
/// \todo reference to the corresponding point of the undirected digraph |
| 106 | 106 |
/// concept. "What does the direction of an edge mean?" |
| 107 | 107 |
static bool direction(const Arc &e) { return e.forward; }
|
| 108 | 108 |
|
| 109 | 109 |
|
| 110 | 110 |
using Parent::first; |
| 111 | 111 |
using Parent::next; |
| 112 | 112 |
|
| 113 | 113 |
void first(Arc &e) const {
|
| 114 | 114 |
Parent::first(e); |
| 115 | 115 |
e.forward=true; |
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
void next(Arc &e) const {
|
| 119 | 119 |
if( e.forward ) {
|
| 120 |
|
|
| 120 |
e.forward = false; |
|
| 121 | 121 |
} |
| 122 | 122 |
else {
|
| 123 |
Parent::next(e); |
|
| 124 |
e.forward = true; |
|
| 123 |
Parent::next(e); |
|
| 124 |
e.forward = true; |
|
| 125 | 125 |
} |
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
void firstOut(Arc &e, const Node &n) const {
|
| 129 | 129 |
Parent::firstIn(e,n); |
| 130 | 130 |
if( Edge(e) != INVALID ) {
|
| 131 |
|
|
| 131 |
e.forward = false; |
|
| 132 | 132 |
} |
| 133 | 133 |
else {
|
| 134 |
Parent::firstOut(e,n); |
|
| 135 |
e.forward = true; |
|
| 134 |
Parent::firstOut(e,n); |
|
| 135 |
e.forward = true; |
|
| 136 | 136 |
} |
| 137 | 137 |
} |
| 138 | 138 |
void nextOut(Arc &e) const {
|
| 139 | 139 |
if( ! e.forward ) {
|
| 140 |
Node n = Parent::target(e); |
|
| 141 |
Parent::nextIn(e); |
|
| 142 |
if( Edge(e) == INVALID ) {
|
|
| 143 |
Parent::firstOut(e, n); |
|
| 144 |
e.forward = true; |
|
| 145 |
} |
|
| 140 |
Node n = Parent::target(e); |
|
| 141 |
Parent::nextIn(e); |
|
| 142 |
if( Edge(e) == INVALID ) {
|
|
| 143 |
Parent::firstOut(e, n); |
|
| 144 |
e.forward = true; |
|
| 145 |
} |
|
| 146 | 146 |
} |
| 147 | 147 |
else {
|
| 148 |
|
|
| 148 |
Parent::nextOut(e); |
|
| 149 | 149 |
} |
| 150 | 150 |
} |
| 151 | 151 |
|
| 152 | 152 |
void firstIn(Arc &e, const Node &n) const {
|
| 153 | 153 |
Parent::firstOut(e,n); |
| 154 | 154 |
if( Edge(e) != INVALID ) {
|
| 155 |
|
|
| 155 |
e.forward = false; |
|
| 156 | 156 |
} |
| 157 | 157 |
else {
|
| 158 |
Parent::firstIn(e,n); |
|
| 159 |
e.forward = true; |
|
| 158 |
Parent::firstIn(e,n); |
|
| 159 |
e.forward = true; |
|
| 160 | 160 |
} |
| 161 | 161 |
} |
| 162 | 162 |
void nextIn(Arc &e) const {
|
| 163 | 163 |
if( ! e.forward ) {
|
| 164 |
Node n = Parent::source(e); |
|
| 165 |
Parent::nextOut(e); |
|
| 166 |
if( Edge(e) == INVALID ) {
|
|
| 167 |
Parent::firstIn(e, n); |
|
| 168 |
e.forward = true; |
|
| 169 |
} |
|
| 164 |
Node n = Parent::source(e); |
|
| 165 |
Parent::nextOut(e); |
|
| 166 |
if( Edge(e) == INVALID ) {
|
|
| 167 |
Parent::firstIn(e, n); |
|
| 168 |
e.forward = true; |
|
| 169 |
} |
|
| 170 | 170 |
} |
| 171 | 171 |
else {
|
| 172 |
|
|
| 172 |
Parent::nextIn(e); |
|
| 173 | 173 |
} |
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
void firstInc(Edge &e, bool &d, const Node &n) const {
|
| 177 | 177 |
d = true; |
| 178 | 178 |
Parent::firstOut(e, n); |
| 179 | 179 |
if (e != INVALID) return; |
| 180 | 180 |
d = false; |
| 181 | 181 |
Parent::firstIn(e, n); |
| 182 | 182 |
} |
| 183 | 183 |
|
| 184 | 184 |
void nextInc(Edge &e, bool &d) const {
|
| 185 | 185 |
if (d) {
|
| 186 |
Node s = Parent::source(e); |
|
| 187 |
Parent::nextOut(e); |
|
| 188 |
if (e != INVALID) return; |
|
| 189 |
d = false; |
|
| 190 |
|
|
| 186 |
Node s = Parent::source(e); |
|
| 187 |
Parent::nextOut(e); |
|
| 188 |
if (e != INVALID) return; |
|
| 189 |
d = false; |
|
| 190 |
Parent::firstIn(e, s); |
|
| 191 | 191 |
} else {
|
| 192 |
|
|
| 192 |
Parent::nextIn(e); |
|
| 193 | 193 |
} |
| 194 | 194 |
} |
| 195 | 195 |
|
| 196 | 196 |
Node nodeFromId(int ix) const {
|
| 197 | 197 |
return Parent::nodeFromId(ix); |
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 | 200 |
Arc arcFromId(int ix) const {
|
| 201 | 201 |
return direct(Parent::arcFromId(ix >> 1), bool(ix & 1)); |
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
Edge edgeFromId(int ix) const {
|
| 205 | 205 |
return Parent::arcFromId(ix); |
| 206 | 206 |
} |
| 207 | 207 |
|
| 208 | 208 |
int id(const Node &n) const {
|
| ... | ... |
@@ -227,255 +227,255 @@ |
| 227 | 227 |
|
| 228 | 228 |
int maxEdgeId() const {
|
| 229 | 229 |
return Parent::maxArcId(); |
| 230 | 230 |
} |
| 231 | 231 |
|
| 232 | 232 |
|
| 233 | 233 |
int arcNum() const {
|
| 234 | 234 |
return 2 * Parent::arcNum(); |
| 235 | 235 |
} |
| 236 | 236 |
|
| 237 | 237 |
int edgeNum() const {
|
| 238 | 238 |
return Parent::arcNum(); |
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 | 241 |
Arc findArc(Node s, Node t, Arc p = INVALID) const {
|
| 242 | 242 |
if (p == INVALID) {
|
| 243 |
Edge arc = Parent::findArc(s, t); |
|
| 244 |
if (arc != INVALID) return direct(arc, true); |
|
| 245 |
arc = Parent::findArc(t, s); |
|
| 246 |
if (arc != INVALID) return direct(arc, false); |
|
| 243 |
Edge arc = Parent::findArc(s, t); |
|
| 244 |
if (arc != INVALID) return direct(arc, true); |
|
| 245 |
arc = Parent::findArc(t, s); |
|
| 246 |
if (arc != INVALID) return direct(arc, false); |
|
| 247 | 247 |
} else if (direction(p)) {
|
| 248 |
Edge arc = Parent::findArc(s, t, p); |
|
| 249 |
if (arc != INVALID) return direct(arc, true); |
|
| 250 |
arc = Parent::findArc(t, s); |
|
| 251 |
if (arc != INVALID) return direct(arc, false); |
|
| 248 |
Edge arc = Parent::findArc(s, t, p); |
|
| 249 |
if (arc != INVALID) return direct(arc, true); |
|
| 250 |
arc = Parent::findArc(t, s); |
|
| 251 |
if (arc != INVALID) return direct(arc, false); |
|
| 252 | 252 |
} else {
|
| 253 |
Edge arc = Parent::findArc(t, s, p); |
|
| 254 |
if (arc != INVALID) return direct(arc, false); |
|
| 253 |
Edge arc = Parent::findArc(t, s, p); |
|
| 254 |
if (arc != INVALID) return direct(arc, false); |
|
| 255 | 255 |
} |
| 256 | 256 |
return INVALID; |
| 257 | 257 |
} |
| 258 | 258 |
|
| 259 | 259 |
Edge findEdge(Node s, Node t, Edge p = INVALID) const {
|
| 260 | 260 |
if (s != t) {
|
| 261 | 261 |
if (p == INVALID) {
|
| 262 | 262 |
Edge arc = Parent::findArc(s, t); |
| 263 | 263 |
if (arc != INVALID) return arc; |
| 264 | 264 |
arc = Parent::findArc(t, s); |
| 265 | 265 |
if (arc != INVALID) return arc; |
| 266 | 266 |
} else if (Parent::s(p) == s) {
|
| 267 | 267 |
Edge arc = Parent::findArc(s, t, p); |
| 268 | 268 |
if (arc != INVALID) return arc; |
| 269 | 269 |
arc = Parent::findArc(t, s); |
| 270 |
if (arc != INVALID) return arc; |
|
| 270 |
if (arc != INVALID) return arc; |
|
| 271 | 271 |
} else {
|
| 272 | 272 |
Edge arc = Parent::findArc(t, s, p); |
| 273 |
if (arc != INVALID) return arc; |
|
| 273 |
if (arc != INVALID) return arc; |
|
| 274 | 274 |
} |
| 275 | 275 |
} else {
|
| 276 | 276 |
return Parent::findArc(s, t, p); |
| 277 | 277 |
} |
| 278 | 278 |
return INVALID; |
| 279 | 279 |
} |
| 280 | 280 |
}; |
| 281 | 281 |
|
| 282 | 282 |
template <typename Base> |
| 283 | 283 |
class BidirBpGraphExtender : public Base {
|
| 284 | 284 |
public: |
| 285 | 285 |
typedef Base Parent; |
| 286 | 286 |
typedef BidirBpGraphExtender Digraph; |
| 287 | 287 |
|
| 288 | 288 |
typedef typename Parent::Node Node; |
| 289 | 289 |
typedef typename Parent::Edge Edge; |
| 290 | 290 |
|
| 291 | 291 |
|
| 292 | 292 |
using Parent::first; |
| 293 | 293 |
using Parent::next; |
| 294 | 294 |
|
| 295 | 295 |
using Parent::id; |
| 296 | 296 |
|
| 297 | 297 |
class Red : public Node {
|
| 298 | 298 |
friend class BidirBpGraphExtender; |
| 299 | 299 |
public: |
| 300 | 300 |
Red() {}
|
| 301 | 301 |
Red(const Node& node) : Node(node) {
|
| 302 |
LEMON_ASSERT(Parent::red(node) || node == INVALID, |
|
| 303 |
typename Parent::NodeSetError()); |
|
| 302 |
LEMON_ASSERT(Parent::red(node) || node == INVALID, |
|
| 303 |
typename Parent::NodeSetError()); |
|
| 304 | 304 |
} |
| 305 | 305 |
Red& operator=(const Node& node) {
|
| 306 |
LEMON_ASSERT(Parent::red(node) || node == INVALID, |
|
| 307 |
typename Parent::NodeSetError()); |
|
| 306 |
LEMON_ASSERT(Parent::red(node) || node == INVALID, |
|
| 307 |
typename Parent::NodeSetError()); |
|
| 308 | 308 |
Node::operator=(node); |
| 309 | 309 |
return *this; |
| 310 | 310 |
} |
| 311 | 311 |
Red(Invalid) : Node(INVALID) {}
|
| 312 | 312 |
Red& operator=(Invalid) {
|
| 313 | 313 |
Node::operator=(INVALID); |
| 314 | 314 |
return *this; |
| 315 | 315 |
} |
| 316 | 316 |
}; |
| 317 | 317 |
|
| 318 | 318 |
void first(Red& node) const {
|
| 319 | 319 |
Parent::firstRed(static_cast<Node&>(node)); |
| 320 | 320 |
} |
| 321 | 321 |
void next(Red& node) const {
|
| 322 | 322 |
Parent::nextRed(static_cast<Node&>(node)); |
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 | 325 |
int id(const Red& node) const {
|
| 326 | 326 |
return Parent::redId(node); |
| 327 | 327 |
} |
| 328 | 328 |
|
| 329 | 329 |
class Blue : public Node {
|
| 330 | 330 |
friend class BidirBpGraphExtender; |
| 331 | 331 |
public: |
| 332 | 332 |
Blue() {}
|
| 333 | 333 |
Blue(const Node& node) : Node(node) {
|
| 334 |
LEMON_ASSERT(Parent::blue(node) || node == INVALID, |
|
| 335 |
typename Parent::NodeSetError()); |
|
| 334 |
LEMON_ASSERT(Parent::blue(node) || node == INVALID, |
|
| 335 |
typename Parent::NodeSetError()); |
|
| 336 | 336 |
} |
| 337 | 337 |
Blue& operator=(const Node& node) {
|
| 338 |
LEMON_ASSERT(Parent::blue(node) || node == INVALID, |
|
| 339 |
typename Parent::NodeSetError()); |
|
| 338 |
LEMON_ASSERT(Parent::blue(node) || node == INVALID, |
|
| 339 |
typename Parent::NodeSetError()); |
|
| 340 | 340 |
Node::operator=(node); |
| 341 | 341 |
return *this; |
| 342 | 342 |
} |
| 343 | 343 |
Blue(Invalid) : Node(INVALID) {}
|
| 344 | 344 |
Blue& operator=(Invalid) {
|
| 345 | 345 |
Node::operator=(INVALID); |
| 346 | 346 |
return *this; |
| 347 | 347 |
} |
| 348 | 348 |
}; |
| 349 | 349 |
|
| 350 | 350 |
void first(Blue& node) const {
|
| 351 | 351 |
Parent::firstBlue(static_cast<Node&>(node)); |
| 352 | 352 |
} |
| 353 | 353 |
void next(Blue& node) const {
|
| 354 | 354 |
Parent::nextBlue(static_cast<Node&>(node)); |
| 355 | 355 |
} |
| 356 |
|
|
| 356 |
|
|
| 357 | 357 |
int id(const Blue& node) const {
|
| 358 | 358 |
return Parent::redId(node); |
| 359 | 359 |
} |
| 360 | 360 |
|
| 361 | 361 |
Node source(const Edge& arc) const {
|
| 362 | 362 |
return red(arc); |
| 363 | 363 |
} |
| 364 | 364 |
Node target(const Edge& arc) const {
|
| 365 | 365 |
return blue(arc); |
| 366 | 366 |
} |
| 367 | 367 |
|
| 368 | 368 |
void firstInc(Edge& arc, bool& dir, const Node& node) const {
|
| 369 | 369 |
if (Parent::red(node)) {
|
| 370 |
Parent::firstFromRed(arc, node); |
|
| 371 |
dir = true; |
|
| 370 |
Parent::firstFromRed(arc, node); |
|
| 371 |
dir = true; |
|
| 372 | 372 |
} else {
|
| 373 |
Parent::firstFromBlue(arc, node); |
|
| 374 |
dir = static_cast<Edge&>(arc) == INVALID; |
|
| 373 |
Parent::firstFromBlue(arc, node); |
|
| 374 |
dir = static_cast<Edge&>(arc) == INVALID; |
|
| 375 | 375 |
} |
| 376 | 376 |
} |
| 377 | 377 |
void nextInc(Edge& arc, bool& dir) const {
|
| 378 | 378 |
if (dir) {
|
| 379 |
|
|
| 379 |
Parent::nextFromRed(arc); |
|
| 380 | 380 |
} else {
|
| 381 |
Parent::nextFromBlue(arc); |
|
| 382 |
if (arc == INVALID) dir = true; |
|
| 381 |
Parent::nextFromBlue(arc); |
|
| 382 |
if (arc == INVALID) dir = true; |
|
| 383 | 383 |
} |
| 384 | 384 |
} |
| 385 | 385 |
|
| 386 | 386 |
class Arc : public Edge {
|
| 387 | 387 |
friend class BidirBpGraphExtender; |
| 388 | 388 |
protected: |
| 389 | 389 |
bool forward; |
| 390 | 390 |
|
| 391 | 391 |
Arc(const Edge& arc, bool _forward) |
| 392 |
|
|
| 392 |
: Edge(arc), forward(_forward) {}
|
|
| 393 | 393 |
|
| 394 | 394 |
public: |
| 395 | 395 |
Arc() {}
|
| 396 | 396 |
Arc (Invalid) : Edge(INVALID), forward(true) {}
|
| 397 | 397 |
bool operator==(const Arc& i) const {
|
| 398 |
|
|
| 398 |
return Edge::operator==(i) && forward == i.forward; |
|
| 399 | 399 |
} |
| 400 | 400 |
bool operator!=(const Arc& i) const {
|
| 401 |
|
|
| 401 |
return Edge::operator!=(i) || forward != i.forward; |
|
| 402 | 402 |
} |
| 403 | 403 |
bool operator<(const Arc& i) const {
|
| 404 |
return Edge::operator<(i) || |
|
| 405 |
(!(i.forward<forward) && Edge(*this)<Edge(i)); |
|
| 404 |
return Edge::operator<(i) || |
|
| 405 |
(!(i.forward<forward) && Edge(*this)<Edge(i)); |
|
| 406 | 406 |
} |
| 407 | 407 |
}; |
| 408 | 408 |
|
| 409 | 409 |
void first(Arc& arc) const {
|
| 410 | 410 |
Parent::first(static_cast<Edge&>(arc)); |
| 411 | 411 |
arc.forward = true; |
| 412 | 412 |
} |
| 413 | 413 |
|
| 414 | 414 |
void next(Arc& arc) const {
|
| 415 | 415 |
if (!arc.forward) {
|
| 416 |
|
|
| 416 |
Parent::next(static_cast<Edge&>(arc)); |
|
| 417 | 417 |
} |
| 418 | 418 |
arc.forward = !arc.forward; |
| 419 | 419 |
} |
| 420 | 420 |
|
| 421 | 421 |
void firstOut(Arc& arc, const Node& node) const {
|
| 422 | 422 |
if (Parent::red(node)) {
|
| 423 |
Parent::firstFromRed(arc, node); |
|
| 424 |
arc.forward = true; |
|
| 423 |
Parent::firstFromRed(arc, node); |
|
| 424 |
arc.forward = true; |
|
| 425 | 425 |
} else {
|
| 426 |
Parent::firstFromBlue(arc, node); |
|
| 427 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 426 |
Parent::firstFromBlue(arc, node); |
|
| 427 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 428 | 428 |
} |
| 429 | 429 |
} |
| 430 | 430 |
void nextOut(Arc& arc) const {
|
| 431 | 431 |
if (arc.forward) {
|
| 432 |
|
|
| 432 |
Parent::nextFromRed(arc); |
|
| 433 | 433 |
} else {
|
| 434 |
|
|
| 434 |
Parent::nextFromBlue(arc); |
|
| 435 | 435 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
| 436 | 436 |
} |
| 437 | 437 |
} |
| 438 | 438 |
|
| 439 | 439 |
void firstIn(Arc& arc, const Node& node) const {
|
| 440 | 440 |
if (Parent::blue(node)) {
|
| 441 |
Parent::firstFromBlue(arc, node); |
|
| 442 |
arc.forward = true; |
|
| 441 |
Parent::firstFromBlue(arc, node); |
|
| 442 |
arc.forward = true; |
|
| 443 | 443 |
} else {
|
| 444 |
Parent::firstFromRed(arc, node); |
|
| 445 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 444 |
Parent::firstFromRed(arc, node); |
|
| 445 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 446 | 446 |
} |
| 447 | 447 |
} |
| 448 | 448 |
void nextIn(Arc& arc) const {
|
| 449 | 449 |
if (arc.forward) {
|
| 450 |
|
|
| 450 |
Parent::nextFromBlue(arc); |
|
| 451 | 451 |
} else {
|
| 452 |
Parent::nextFromRed(arc); |
|
| 453 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 452 |
Parent::nextFromRed(arc); |
|
| 453 |
arc.forward = static_cast<Edge&>(arc) == INVALID; |
|
| 454 | 454 |
} |
| 455 | 455 |
} |
| 456 | 456 |
|
| 457 | 457 |
Node source(const Arc& arc) const {
|
| 458 | 458 |
return arc.forward ? Parent::red(arc) : Parent::blue(arc); |
| 459 | 459 |
} |
| 460 | 460 |
Node target(const Arc& arc) const {
|
| 461 | 461 |
return arc.forward ? Parent::blue(arc) : Parent::red(arc); |
| 462 | 462 |
} |
| 463 | 463 |
|
| 464 | 464 |
int id(const Arc& arc) const {
|
| 465 |
return (Parent::id(static_cast<const Edge&>(arc)) << 1) + |
|
| 465 |
return (Parent::id(static_cast<const Edge&>(arc)) << 1) + |
|
| 466 | 466 |
(arc.forward ? 0 : 1); |
| 467 | 467 |
} |
| 468 | 468 |
Arc arcFromId(int ix) const {
|
| 469 | 469 |
return Arc(Parent::fromEdgeId(ix >> 1), (ix & 1) == 0); |
| 470 | 470 |
} |
| 471 | 471 |
int maxArcId() const {
|
| 472 | 472 |
return (Parent::maxEdgeId() << 1) + 1; |
| 473 | 473 |
} |
| 474 | 474 |
|
| 475 | 475 |
bool direction(const Arc& arc) const {
|
| 476 | 476 |
return arc.forward; |
| 477 | 477 |
} |
| 478 | 478 |
|
| 479 | 479 |
Arc direct(const Edge& arc, bool dir) const {
|
| 480 | 480 |
return Arc(arc, dir); |
| 481 | 481 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BEZIER_H |
| ... | ... |
@@ -31,144 +31,144 @@ |
| 31 | 31 |
namespace dim2 {
|
| 32 | 32 |
|
| 33 | 33 |
class BezierBase {
|
| 34 | 34 |
public: |
| 35 | 35 |
typedef lemon::dim2::Point<double> Point; |
| 36 | 36 |
protected: |
| 37 | 37 |
static Point conv(Point x,Point y,double t) {return (1-t)*x+t*y;}
|
| 38 | 38 |
}; |
| 39 | 39 |
|
| 40 | 40 |
class Bezier1 : public BezierBase |
| 41 | 41 |
{
|
| 42 | 42 |
public: |
| 43 | 43 |
Point p1,p2; |
| 44 | 44 |
|
| 45 | 45 |
Bezier1() {}
|
| 46 | 46 |
Bezier1(Point _p1, Point _p2) :p1(_p1), p2(_p2) {}
|
| 47 |
|
|
| 47 |
|
|
| 48 | 48 |
Point operator()(double t) const |
| 49 | 49 |
{
|
| 50 | 50 |
// return conv(conv(p1,p2,t),conv(p2,p3,t),t); |
| 51 | 51 |
return conv(p1,p2,t); |
| 52 | 52 |
} |
| 53 | 53 |
Bezier1 before(double t) const |
| 54 | 54 |
{
|
| 55 | 55 |
return Bezier1(p1,conv(p1,p2,t)); |
| 56 | 56 |
} |
| 57 |
|
|
| 57 |
|
|
| 58 | 58 |
Bezier1 after(double t) const |
| 59 | 59 |
{
|
| 60 | 60 |
return Bezier1(conv(p1,p2,t),p2); |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
Bezier1 revert() const { return Bezier1(p2,p1);}
|
| 64 | 64 |
Bezier1 operator()(double a,double b) const { return before(b).after(a/b); }
|
| 65 | 65 |
Point grad() const { return p2-p1; }
|
| 66 | 66 |
Point norm() const { return rot90(p2-p1); }
|
| 67 | 67 |
Point grad(double) const { return grad(); }
|
| 68 | 68 |
Point norm(double t) const { return rot90(grad(t)); }
|
| 69 | 69 |
}; |
| 70 | 70 |
|
| 71 | 71 |
class Bezier2 : public BezierBase |
| 72 | 72 |
{
|
| 73 | 73 |
public: |
| 74 | 74 |
Point p1,p2,p3; |
| 75 | 75 |
|
| 76 | 76 |
Bezier2() {}
|
| 77 | 77 |
Bezier2(Point _p1, Point _p2, Point _p3) :p1(_p1), p2(_p2), p3(_p3) {}
|
| 78 | 78 |
Bezier2(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,.5)), p3(b.p2) {}
|
| 79 | 79 |
Point operator()(double t) const |
| 80 | 80 |
{
|
| 81 | 81 |
// return conv(conv(p1,p2,t),conv(p2,p3,t),t); |
| 82 | 82 |
return ((1-t)*(1-t))*p1+(2*(1-t)*t)*p2+(t*t)*p3; |
| 83 | 83 |
} |
| 84 | 84 |
Bezier2 before(double t) const |
| 85 | 85 |
{
|
| 86 | 86 |
Point q(conv(p1,p2,t)); |
| 87 | 87 |
Point r(conv(p2,p3,t)); |
| 88 | 88 |
return Bezier2(p1,q,conv(q,r,t)); |
| 89 | 89 |
} |
| 90 |
|
|
| 90 |
|
|
| 91 | 91 |
Bezier2 after(double t) const |
| 92 | 92 |
{
|
| 93 | 93 |
Point q(conv(p1,p2,t)); |
| 94 | 94 |
Point r(conv(p2,p3,t)); |
| 95 | 95 |
return Bezier2(conv(q,r,t),r,p3); |
| 96 | 96 |
} |
| 97 | 97 |
Bezier2 revert() const { return Bezier2(p3,p2,p1);}
|
| 98 | 98 |
Bezier2 operator()(double a,double b) const { return before(b).after(a/b); }
|
| 99 | 99 |
Bezier1 grad() const { return Bezier1(2.0*(p2-p1),2.0*(p3-p2)); }
|
| 100 | 100 |
Bezier1 norm() const { return Bezier1(2.0*rot90(p2-p1),2.0*rot90(p3-p2)); }
|
| 101 | 101 |
Point grad(double t) const { return grad()(t); }
|
| 102 | 102 |
Point norm(double t) const { return rot90(grad(t)); }
|
| 103 | 103 |
}; |
| 104 | 104 |
|
| 105 | 105 |
class Bezier3 : public BezierBase |
| 106 | 106 |
{
|
| 107 | 107 |
public: |
| 108 | 108 |
Point p1,p2,p3,p4; |
| 109 | 109 |
|
| 110 | 110 |
Bezier3() {}
|
| 111 | 111 |
Bezier3(Point _p1, Point _p2, Point _p3, Point _p4) |
| 112 | 112 |
: p1(_p1), p2(_p2), p3(_p3), p4(_p4) {}
|
| 113 |
Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), |
|
| 114 |
p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
|
|
| 113 |
Bezier3(const Bezier1 &b) : p1(b.p1), p2(conv(b.p1,b.p2,1.0/3.0)), |
|
| 114 |
p3(conv(b.p1,b.p2,2.0/3.0)), p4(b.p2) {}
|
|
| 115 | 115 |
Bezier3(const Bezier2 &b) : p1(b.p1), p2(conv(b.p1,b.p2,2.0/3.0)), |
| 116 |
p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
|
|
| 117 |
|
|
| 118 |
|
|
| 116 |
p3(conv(b.p2,b.p3,1.0/3.0)), p4(b.p3) {}
|
|
| 117 |
|
|
| 118 |
Point operator()(double t) const |
|
| 119 | 119 |
{
|
| 120 | 120 |
// return Bezier2(conv(p1,p2,t),conv(p2,p3,t),conv(p3,p4,t))(t); |
| 121 | 121 |
return ((1-t)*(1-t)*(1-t))*p1+(3*t*(1-t)*(1-t))*p2+ |
| 122 |
|
|
| 122 |
(3*t*t*(1-t))*p3+(t*t*t)*p4; |
|
| 123 | 123 |
} |
| 124 | 124 |
Bezier3 before(double t) const |
| 125 | 125 |
{
|
| 126 | 126 |
Point p(conv(p1,p2,t)); |
| 127 | 127 |
Point q(conv(p2,p3,t)); |
| 128 | 128 |
Point r(conv(p3,p4,t)); |
| 129 | 129 |
Point a(conv(p,q,t)); |
| 130 | 130 |
Point b(conv(q,r,t)); |
| 131 | 131 |
Point c(conv(a,b,t)); |
| 132 | 132 |
return Bezier3(p1,p,a,c); |
| 133 | 133 |
} |
| 134 |
|
|
| 134 |
|
|
| 135 | 135 |
Bezier3 after(double t) const |
| 136 | 136 |
{
|
| 137 | 137 |
Point p(conv(p1,p2,t)); |
| 138 | 138 |
Point q(conv(p2,p3,t)); |
| 139 | 139 |
Point r(conv(p3,p4,t)); |
| 140 | 140 |
Point a(conv(p,q,t)); |
| 141 | 141 |
Point b(conv(q,r,t)); |
| 142 | 142 |
Point c(conv(a,b,t)); |
| 143 | 143 |
return Bezier3(c,b,r,p4); |
| 144 | 144 |
} |
| 145 | 145 |
Bezier3 revert() const { return Bezier3(p4,p3,p2,p1);}
|
| 146 | 146 |
Bezier3 operator()(double a,double b) const { return before(b).after(a/b); }
|
| 147 | 147 |
Bezier2 grad() const { return Bezier2(3.0*(p2-p1),3.0*(p3-p2),3.0*(p4-p3)); }
|
| 148 | 148 |
Bezier2 norm() const { return Bezier2(3.0*rot90(p2-p1),
|
| 149 |
3.0*rot90(p3-p2), |
|
| 150 |
3.0*rot90(p4-p3)); } |
|
| 149 |
3.0*rot90(p3-p2), |
|
| 150 |
3.0*rot90(p4-p3)); } |
|
| 151 | 151 |
Point grad(double t) const { return grad()(t); }
|
| 152 | 152 |
Point norm(double t) const { return rot90(grad(t)); }
|
| 153 | 153 |
|
| 154 | 154 |
template<class R,class F,class S,class D> |
| 155 |
R recSplit(F &_f,const S &_s,D _d) const |
|
| 155 |
R recSplit(F &_f,const S &_s,D _d) const |
|
| 156 | 156 |
{
|
| 157 | 157 |
const Point a=(p1+p2)/2; |
| 158 | 158 |
const Point b=(p2+p3)/2; |
| 159 | 159 |
const Point c=(p3+p4)/2; |
| 160 | 160 |
const Point d=(a+b)/2; |
| 161 | 161 |
const Point e=(b+c)/2; |
| 162 | 162 |
const Point f=(d+e)/2; |
| 163 | 163 |
R f1=_f(Bezier3(p1,a,d,e),_d); |
| 164 | 164 |
R f2=_f(Bezier3(e,d,c,p4),_d); |
| 165 | 165 |
return _s(f1,f2); |
| 166 | 166 |
} |
| 167 |
|
|
| 167 |
|
|
| 168 | 168 |
}; |
| 169 | 169 |
|
| 170 | 170 |
|
| 171 | 171 |
} //END OF NAMESPACE dim2 |
| 172 | 172 |
} //END OF NAMESPACE lemon |
| 173 | 173 |
|
| 174 | 174 |
#endif // LEMON_BEZIER_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_DEFAULT_MAP_H |
| 20 | 20 |
#define LEMON_BITS_DEFAULT_MAP_H |
| 21 | 21 |
|
| 22 | 22 |
|
| 23 | 23 |
#include <lemon/bits/array_map.h> |
| 24 | 24 |
#include <lemon/bits/vector_map.h> |
| 25 | 25 |
//#include <lemon/bits/debug_map.h> |
| 26 | 26 |
|
| 27 | 27 |
///\ingroup graphbits |
| 28 | 28 |
///\file |
| 29 | 29 |
///\brief Graph maps that construct and destruct their elements dynamically. |
| 30 | 30 |
|
| 31 | 31 |
namespace lemon {
|
| 32 |
|
|
| 33 |
|
|
| 32 |
|
|
| 33 |
|
|
| 34 | 34 |
//#ifndef LEMON_USE_DEBUG_MAP |
| 35 | 35 |
|
| 36 | 36 |
template <typename _Graph, typename _Item, typename _Value> |
| 37 | 37 |
struct DefaultMapSelector {
|
| 38 | 38 |
typedef ArrayMap<_Graph, _Item, _Value> Map; |
| 39 | 39 |
}; |
| 40 | 40 |
|
| 41 | 41 |
// bool |
| 42 | 42 |
template <typename _Graph, typename _Item> |
| 43 | 43 |
struct DefaultMapSelector<_Graph, _Item, bool> {
|
| 44 | 44 |
typedef VectorMap<_Graph, _Item, bool> Map; |
| 45 | 45 |
}; |
| 46 | 46 |
|
| 47 | 47 |
// char |
| 48 | 48 |
template <typename _Graph, typename _Item> |
| 49 | 49 |
struct DefaultMapSelector<_Graph, _Item, char> {
|
| ... | ... |
@@ -127,54 +127,54 @@ |
| 127 | 127 |
}; |
| 128 | 128 |
|
| 129 | 129 |
|
| 130 | 130 |
// long double |
| 131 | 131 |
template <typename _Graph, typename _Item> |
| 132 | 132 |
struct DefaultMapSelector<_Graph, _Item, long double> {
|
| 133 | 133 |
typedef VectorMap<_Graph, _Item, long double> Map; |
| 134 | 134 |
}; |
| 135 | 135 |
|
| 136 | 136 |
|
| 137 | 137 |
// pointer |
| 138 | 138 |
template <typename _Graph, typename _Item, typename _Ptr> |
| 139 | 139 |
struct DefaultMapSelector<_Graph, _Item, _Ptr*> {
|
| 140 | 140 |
typedef VectorMap<_Graph, _Item, _Ptr*> Map; |
| 141 | 141 |
}; |
| 142 | 142 |
|
| 143 |
// #else |
|
| 143 |
// #else |
|
| 144 | 144 |
|
| 145 | 145 |
// template <typename _Graph, typename _Item, typename _Value> |
| 146 | 146 |
// struct DefaultMapSelector {
|
| 147 | 147 |
// typedef DebugMap<_Graph, _Item, _Value> Map; |
| 148 | 148 |
// }; |
| 149 | 149 |
|
| 150 |
// #endif |
|
| 150 |
// #endif |
|
| 151 | 151 |
|
| 152 | 152 |
/// \e |
| 153 | 153 |
template <typename _Graph, typename _Item, typename _Value> |
| 154 |
class DefaultMap |
|
| 154 |
class DefaultMap |
|
| 155 | 155 |
: public DefaultMapSelector<_Graph, _Item, _Value>::Map {
|
| 156 | 156 |
public: |
| 157 | 157 |
typedef typename DefaultMapSelector<_Graph, _Item, _Value>::Map Parent; |
| 158 | 158 |
typedef DefaultMap<_Graph, _Item, _Value> Map; |
| 159 |
|
|
| 159 |
|
|
| 160 | 160 |
typedef typename Parent::Graph Graph; |
| 161 | 161 |
typedef typename Parent::Value Value; |
| 162 | 162 |
|
| 163 | 163 |
explicit DefaultMap(const Graph& graph) : Parent(graph) {}
|
| 164 |
DefaultMap(const Graph& graph, const Value& value) |
|
| 164 |
DefaultMap(const Graph& graph, const Value& value) |
|
| 165 | 165 |
: Parent(graph, value) {}
|
| 166 | 166 |
|
| 167 | 167 |
DefaultMap& operator=(const DefaultMap& cmap) {
|
| 168 | 168 |
return operator=<DefaultMap>(cmap); |
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 | 171 |
template <typename CMap> |
| 172 | 172 |
DefaultMap& operator=(const CMap& cmap) {
|
| 173 | 173 |
Parent::operator=(cmap); |
| 174 | 174 |
return *this; |
| 175 | 175 |
} |
| 176 | 176 |
|
| 177 | 177 |
}; |
| 178 | 178 |
|
| 179 | 179 |
} |
| 180 | 180 |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_GRAPH_EXTENDER_H |
| ... | ... |
@@ -53,517 +53,517 @@ |
| 53 | 53 |
} |
| 54 | 54 |
|
| 55 | 55 |
int maxId(Arc) const {
|
| 56 | 56 |
return Parent::maxArcId(); |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 | 59 |
Node fromId(int id, Node) const {
|
| 60 | 60 |
return Parent::nodeFromId(id); |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 | 63 |
Arc fromId(int id, Arc) const {
|
| 64 | 64 |
return Parent::arcFromId(id); |
| 65 | 65 |
} |
| 66 | 66 |
|
| 67 | 67 |
Node oppositeNode(const Node &node, const Arc &arc) const {
|
| 68 | 68 |
if (node == Parent::source(arc)) |
| 69 |
|
|
| 69 |
return Parent::target(arc); |
|
| 70 | 70 |
else if(node == Parent::target(arc)) |
| 71 |
|
|
| 71 |
return Parent::source(arc); |
|
| 72 | 72 |
else |
| 73 |
|
|
| 73 |
return INVALID; |
|
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 | 76 |
// Alterable extension |
| 77 | 77 |
|
| 78 | 78 |
typedef AlterationNotifier<DigraphExtender, Node> NodeNotifier; |
| 79 | 79 |
typedef AlterationNotifier<DigraphExtender, Arc> ArcNotifier; |
| 80 | 80 |
|
| 81 | 81 |
|
| 82 | 82 |
protected: |
| 83 | 83 |
|
| 84 | 84 |
mutable NodeNotifier node_notifier; |
| 85 | 85 |
mutable ArcNotifier arc_notifier; |
| 86 | 86 |
|
| 87 | 87 |
public: |
| 88 | 88 |
|
| 89 | 89 |
NodeNotifier& notifier(Node) const {
|
| 90 | 90 |
return node_notifier; |
| 91 | 91 |
} |
| 92 |
|
|
| 92 |
|
|
| 93 | 93 |
ArcNotifier& notifier(Arc) const {
|
| 94 | 94 |
return arc_notifier; |
| 95 | 95 |
} |
| 96 | 96 |
|
| 97 |
class NodeIt : public Node {
|
|
| 97 |
class NodeIt : public Node {
|
|
| 98 | 98 |
const Digraph* _digraph; |
| 99 | 99 |
public: |
| 100 | 100 |
|
| 101 | 101 |
NodeIt() {}
|
| 102 | 102 |
|
| 103 | 103 |
NodeIt(Invalid i) : Node(i) { }
|
| 104 | 104 |
|
| 105 | 105 |
explicit NodeIt(const Digraph& digraph) : _digraph(&digraph) {
|
| 106 |
|
|
| 106 |
_digraph->first(static_cast<Node&>(*this)); |
|
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 |
NodeIt(const Digraph& digraph, const Node& node) |
|
| 110 |
: Node(node), _digraph(&digraph) {}
|
|
| 109 |
NodeIt(const Digraph& digraph, const Node& node) |
|
| 110 |
: Node(node), _digraph(&digraph) {}
|
|
| 111 | 111 |
|
| 112 |
NodeIt& operator++() {
|
|
| 113 |
_digraph->next(*this); |
|
| 114 |
|
|
| 112 |
NodeIt& operator++() {
|
|
| 113 |
_digraph->next(*this); |
|
| 114 |
return *this; |
|
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 | 117 |
}; |
| 118 | 118 |
|
| 119 | 119 |
|
| 120 |
class ArcIt : public Arc {
|
|
| 120 |
class ArcIt : public Arc {
|
|
| 121 | 121 |
const Digraph* _digraph; |
| 122 | 122 |
public: |
| 123 | 123 |
|
| 124 | 124 |
ArcIt() { }
|
| 125 | 125 |
|
| 126 | 126 |
ArcIt(Invalid i) : Arc(i) { }
|
| 127 | 127 |
|
| 128 | 128 |
explicit ArcIt(const Digraph& digraph) : _digraph(&digraph) {
|
| 129 |
|
|
| 129 |
_digraph->first(static_cast<Arc&>(*this)); |
|
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 |
ArcIt(const Digraph& digraph, const Arc& arc) : |
|
| 133 |
Arc(arc), _digraph(&digraph) { }
|
|
| 132 |
ArcIt(const Digraph& digraph, const Arc& arc) : |
|
| 133 |
Arc(arc), _digraph(&digraph) { }
|
|
| 134 | 134 |
|
| 135 |
ArcIt& operator++() {
|
|
| 136 |
_digraph->next(*this); |
|
| 137 |
|
|
| 135 |
ArcIt& operator++() {
|
|
| 136 |
_digraph->next(*this); |
|
| 137 |
return *this; |
|
| 138 | 138 |
} |
| 139 | 139 |
|
| 140 | 140 |
}; |
| 141 | 141 |
|
| 142 | 142 |
|
| 143 |
class OutArcIt : public Arc {
|
|
| 143 |
class OutArcIt : public Arc {
|
|
| 144 | 144 |
const Digraph* _digraph; |
| 145 | 145 |
public: |
| 146 | 146 |
|
| 147 | 147 |
OutArcIt() { }
|
| 148 | 148 |
|
| 149 | 149 |
OutArcIt(Invalid i) : Arc(i) { }
|
| 150 | 150 |
|
| 151 |
OutArcIt(const Digraph& digraph, const Node& node) |
|
| 152 |
: _digraph(&digraph) {
|
|
| 153 |
|
|
| 151 |
OutArcIt(const Digraph& digraph, const Node& node) |
|
| 152 |
: _digraph(&digraph) {
|
|
| 153 |
_digraph->firstOut(*this, node); |
|
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 |
OutArcIt(const Digraph& digraph, const Arc& arc) |
|
| 157 |
: Arc(arc), _digraph(&digraph) {}
|
|
| 156 |
OutArcIt(const Digraph& digraph, const Arc& arc) |
|
| 157 |
: Arc(arc), _digraph(&digraph) {}
|
|
| 158 | 158 |
|
| 159 |
OutArcIt& operator++() {
|
|
| 160 |
_digraph->nextOut(*this); |
|
| 161 |
|
|
| 159 |
OutArcIt& operator++() {
|
|
| 160 |
_digraph->nextOut(*this); |
|
| 161 |
return *this; |
|
| 162 | 162 |
} |
| 163 | 163 |
|
| 164 | 164 |
}; |
| 165 | 165 |
|
| 166 | 166 |
|
| 167 |
class InArcIt : public Arc {
|
|
| 167 |
class InArcIt : public Arc {
|
|
| 168 | 168 |
const Digraph* _digraph; |
| 169 | 169 |
public: |
| 170 | 170 |
|
| 171 | 171 |
InArcIt() { }
|
| 172 | 172 |
|
| 173 | 173 |
InArcIt(Invalid i) : Arc(i) { }
|
| 174 | 174 |
|
| 175 |
InArcIt(const Digraph& digraph, const Node& node) |
|
| 176 |
: _digraph(&digraph) {
|
|
| 177 |
|
|
| 175 |
InArcIt(const Digraph& digraph, const Node& node) |
|
| 176 |
: _digraph(&digraph) {
|
|
| 177 |
_digraph->firstIn(*this, node); |
|
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 |
InArcIt(const Digraph& digraph, const Arc& arc) : |
|
| 181 |
Arc(arc), _digraph(&digraph) {}
|
|
| 180 |
InArcIt(const Digraph& digraph, const Arc& arc) : |
|
| 181 |
Arc(arc), _digraph(&digraph) {}
|
|
| 182 | 182 |
|
| 183 |
InArcIt& operator++() {
|
|
| 184 |
_digraph->nextIn(*this); |
|
| 185 |
|
|
| 183 |
InArcIt& operator++() {
|
|
| 184 |
_digraph->nextIn(*this); |
|
| 185 |
return *this; |
|
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 | 188 |
}; |
| 189 | 189 |
|
| 190 | 190 |
/// \brief Base node of the iterator |
| 191 | 191 |
/// |
| 192 | 192 |
/// Returns the base node (i.e. the source in this case) of the iterator |
| 193 | 193 |
Node baseNode(const OutArcIt &arc) const {
|
| 194 | 194 |
return Parent::source(arc); |
| 195 | 195 |
} |
| 196 | 196 |
/// \brief Running node of the iterator |
| 197 | 197 |
/// |
| 198 | 198 |
/// Returns the running node (i.e. the target in this case) of the |
| 199 | 199 |
/// iterator |
| 200 | 200 |
Node runningNode(const OutArcIt &arc) const {
|
| 201 | 201 |
return Parent::target(arc); |
| 202 | 202 |
} |
| 203 | 203 |
|
| 204 | 204 |
/// \brief Base node of the iterator |
| 205 | 205 |
/// |
| 206 | 206 |
/// Returns the base node (i.e. the target in this case) of the iterator |
| 207 | 207 |
Node baseNode(const InArcIt &arc) const {
|
| 208 | 208 |
return Parent::target(arc); |
| 209 | 209 |
} |
| 210 | 210 |
/// \brief Running node of the iterator |
| 211 | 211 |
/// |
| 212 | 212 |
/// Returns the running node (i.e. the source in this case) of the |
| 213 | 213 |
/// iterator |
| 214 | 214 |
Node runningNode(const InArcIt &arc) const {
|
| 215 | 215 |
return Parent::source(arc); |
| 216 | 216 |
} |
| 217 | 217 |
|
| 218 |
|
|
| 218 |
|
|
| 219 | 219 |
template <typename _Value> |
| 220 |
class NodeMap |
|
| 220 |
class NodeMap |
|
| 221 | 221 |
: public MapExtender<DefaultMap<Digraph, Node, _Value> > {
|
| 222 | 222 |
public: |
| 223 | 223 |
typedef DigraphExtender Digraph; |
| 224 | 224 |
typedef MapExtender<DefaultMap<Digraph, Node, _Value> > Parent; |
| 225 | 225 |
|
| 226 |
explicit NodeMap(const Digraph& digraph) |
|
| 227 |
: Parent(digraph) {}
|
|
| 228 |
NodeMap(const Digraph& digraph, const _Value& value) |
|
| 229 |
: Parent(digraph, value) {}
|
|
| 226 |
explicit NodeMap(const Digraph& digraph) |
|
| 227 |
: Parent(digraph) {}
|
|
| 228 |
NodeMap(const Digraph& digraph, const _Value& value) |
|
| 229 |
: Parent(digraph, value) {}
|
|
| 230 | 230 |
|
| 231 | 231 |
NodeMap& operator=(const NodeMap& cmap) {
|
| 232 |
|
|
| 232 |
return operator=<NodeMap>(cmap); |
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
template <typename CMap> |
| 236 | 236 |
NodeMap& operator=(const CMap& cmap) {
|
| 237 | 237 |
Parent::operator=(cmap); |
| 238 |
|
|
| 238 |
return *this; |
|
| 239 | 239 |
} |
| 240 | 240 |
|
| 241 | 241 |
}; |
| 242 | 242 |
|
| 243 | 243 |
template <typename _Value> |
| 244 |
class ArcMap |
|
| 244 |
class ArcMap |
|
| 245 | 245 |
: public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
|
| 246 | 246 |
public: |
| 247 | 247 |
typedef DigraphExtender Digraph; |
| 248 | 248 |
typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent; |
| 249 | 249 |
|
| 250 |
explicit ArcMap(const Digraph& digraph) |
|
| 251 |
: Parent(digraph) {}
|
|
| 252 |
ArcMap(const Digraph& digraph, const _Value& value) |
|
| 253 |
: Parent(digraph, value) {}
|
|
| 250 |
explicit ArcMap(const Digraph& digraph) |
|
| 251 |
: Parent(digraph) {}
|
|
| 252 |
ArcMap(const Digraph& digraph, const _Value& value) |
|
| 253 |
: Parent(digraph, value) {}
|
|
| 254 | 254 |
|
| 255 | 255 |
ArcMap& operator=(const ArcMap& cmap) {
|
| 256 |
|
|
| 256 |
return operator=<ArcMap>(cmap); |
|
| 257 | 257 |
} |
| 258 | 258 |
|
| 259 | 259 |
template <typename CMap> |
| 260 | 260 |
ArcMap& operator=(const CMap& cmap) {
|
| 261 | 261 |
Parent::operator=(cmap); |
| 262 |
|
|
| 262 |
return *this; |
|
| 263 | 263 |
} |
| 264 | 264 |
}; |
| 265 | 265 |
|
| 266 | 266 |
|
| 267 | 267 |
Node addNode() {
|
| 268 | 268 |
Node node = Parent::addNode(); |
| 269 | 269 |
notifier(Node()).add(node); |
| 270 | 270 |
return node; |
| 271 | 271 |
} |
| 272 |
|
|
| 272 |
|
|
| 273 | 273 |
Arc addArc(const Node& from, const Node& to) {
|
| 274 | 274 |
Arc arc = Parent::addArc(from, to); |
| 275 | 275 |
notifier(Arc()).add(arc); |
| 276 | 276 |
return arc; |
| 277 | 277 |
} |
| 278 | 278 |
|
| 279 | 279 |
void clear() {
|
| 280 | 280 |
notifier(Arc()).clear(); |
| 281 | 281 |
notifier(Node()).clear(); |
| 282 | 282 |
Parent::clear(); |
| 283 | 283 |
} |
| 284 | 284 |
|
| 285 | 285 |
template <typename Digraph, typename NodeRefMap, typename ArcRefMap> |
| 286 | 286 |
void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
|
| 287 | 287 |
Parent::build(digraph, nodeRef, arcRef); |
| 288 | 288 |
notifier(Node()).build(); |
| 289 | 289 |
notifier(Arc()).build(); |
| 290 | 290 |
} |
| 291 | 291 |
|
| 292 | 292 |
void erase(const Node& node) {
|
| 293 | 293 |
Arc arc; |
| 294 | 294 |
Parent::firstOut(arc, node); |
| 295 | 295 |
while (arc != INVALID ) {
|
| 296 |
erase(arc); |
|
| 297 |
Parent::firstOut(arc, node); |
|
| 298 |
|
|
| 296 |
erase(arc); |
|
| 297 |
Parent::firstOut(arc, node); |
|
| 298 |
} |
|
| 299 | 299 |
|
| 300 | 300 |
Parent::firstIn(arc, node); |
| 301 | 301 |
while (arc != INVALID ) {
|
| 302 |
erase(arc); |
|
| 303 |
Parent::firstIn(arc, node); |
|
| 302 |
erase(arc); |
|
| 303 |
Parent::firstIn(arc, node); |
|
| 304 | 304 |
} |
| 305 | 305 |
|
| 306 | 306 |
notifier(Node()).erase(node); |
| 307 | 307 |
Parent::erase(node); |
| 308 | 308 |
} |
| 309 |
|
|
| 309 |
|
|
| 310 | 310 |
void erase(const Arc& arc) {
|
| 311 | 311 |
notifier(Arc()).erase(arc); |
| 312 | 312 |
Parent::erase(arc); |
| 313 | 313 |
} |
| 314 | 314 |
|
| 315 | 315 |
DigraphExtender() {
|
| 316 | 316 |
node_notifier.setContainer(*this); |
| 317 | 317 |
arc_notifier.setContainer(*this); |
| 318 |
} |
|
| 319 |
|
|
| 318 |
} |
|
| 319 |
|
|
| 320 | 320 |
|
| 321 | 321 |
~DigraphExtender() {
|
| 322 | 322 |
arc_notifier.clear(); |
| 323 | 323 |
node_notifier.clear(); |
| 324 | 324 |
} |
| 325 | 325 |
}; |
| 326 | 326 |
|
| 327 | 327 |
/// \ingroup _graphbits |
| 328 | 328 |
/// |
| 329 | 329 |
/// \brief Extender for the Graphs |
| 330 |
template <typename Base> |
|
| 330 |
template <typename Base> |
|
| 331 | 331 |
class GraphExtender : public Base {
|
| 332 | 332 |
public: |
| 333 |
|
|
| 333 |
|
|
| 334 | 334 |
typedef Base Parent; |
| 335 | 335 |
typedef GraphExtender Graph; |
| 336 | 336 |
|
| 337 | 337 |
typedef True UndirectedTag; |
| 338 | 338 |
|
| 339 | 339 |
typedef typename Parent::Node Node; |
| 340 | 340 |
typedef typename Parent::Arc Arc; |
| 341 | 341 |
typedef typename Parent::Edge Edge; |
| 342 | 342 |
|
| 343 |
// Graph extension |
|
| 343 |
// Graph extension |
|
| 344 | 344 |
|
| 345 | 345 |
int maxId(Node) const {
|
| 346 | 346 |
return Parent::maxNodeId(); |
| 347 | 347 |
} |
| 348 | 348 |
|
| 349 | 349 |
int maxId(Arc) const {
|
| 350 | 350 |
return Parent::maxArcId(); |
| 351 | 351 |
} |
| 352 | 352 |
|
| 353 | 353 |
int maxId(Edge) const {
|
| 354 | 354 |
return Parent::maxEdgeId(); |
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 | 357 |
Node fromId(int id, Node) const {
|
| 358 | 358 |
return Parent::nodeFromId(id); |
| 359 | 359 |
} |
| 360 | 360 |
|
| 361 | 361 |
Arc fromId(int id, Arc) const {
|
| 362 | 362 |
return Parent::arcFromId(id); |
| 363 | 363 |
} |
| 364 | 364 |
|
| 365 | 365 |
Edge fromId(int id, Edge) const {
|
| 366 | 366 |
return Parent::edgeFromId(id); |
| 367 | 367 |
} |
| 368 | 368 |
|
| 369 | 369 |
Node oppositeNode(const Node &n, const Edge &e) const {
|
| 370 | 370 |
if( n == Parent::u(e)) |
| 371 |
|
|
| 371 |
return Parent::v(e); |
|
| 372 | 372 |
else if( n == Parent::v(e)) |
| 373 |
|
|
| 373 |
return Parent::u(e); |
|
| 374 | 374 |
else |
| 375 |
|
|
| 375 |
return INVALID; |
|
| 376 | 376 |
} |
| 377 | 377 |
|
| 378 | 378 |
Arc oppositeArc(const Arc &arc) const {
|
| 379 | 379 |
return Parent::direct(arc, !Parent::direction(arc)); |
| 380 | 380 |
} |
| 381 | 381 |
|
| 382 | 382 |
using Parent::direct; |
| 383 | 383 |
Arc direct(const Edge &edge, const Node &node) const {
|
| 384 | 384 |
return Parent::direct(edge, Parent::u(edge) == node); |
| 385 | 385 |
} |
| 386 | 386 |
|
| 387 | 387 |
// Alterable extension |
| 388 | 388 |
|
| 389 | 389 |
typedef AlterationNotifier<GraphExtender, Node> NodeNotifier; |
| 390 | 390 |
typedef AlterationNotifier<GraphExtender, Arc> ArcNotifier; |
| 391 | 391 |
typedef AlterationNotifier<GraphExtender, Edge> EdgeNotifier; |
| 392 | 392 |
|
| 393 | 393 |
|
| 394 | 394 |
protected: |
| 395 | 395 |
|
| 396 | 396 |
mutable NodeNotifier node_notifier; |
| 397 | 397 |
mutable ArcNotifier arc_notifier; |
| 398 | 398 |
mutable EdgeNotifier edge_notifier; |
| 399 | 399 |
|
| 400 | 400 |
public: |
| 401 | 401 |
|
| 402 | 402 |
NodeNotifier& notifier(Node) const {
|
| 403 | 403 |
return node_notifier; |
| 404 | 404 |
} |
| 405 |
|
|
| 405 |
|
|
| 406 | 406 |
ArcNotifier& notifier(Arc) const {
|
| 407 | 407 |
return arc_notifier; |
| 408 | 408 |
} |
| 409 | 409 |
|
| 410 | 410 |
EdgeNotifier& notifier(Edge) const {
|
| 411 | 411 |
return edge_notifier; |
| 412 | 412 |
} |
| 413 | 413 |
|
| 414 | 414 |
|
| 415 | 415 |
|
| 416 |
class NodeIt : public Node {
|
|
| 416 |
class NodeIt : public Node {
|
|
| 417 | 417 |
const Graph* _graph; |
| 418 | 418 |
public: |
| 419 | 419 |
|
| 420 | 420 |
NodeIt() {}
|
| 421 | 421 |
|
| 422 | 422 |
NodeIt(Invalid i) : Node(i) { }
|
| 423 | 423 |
|
| 424 | 424 |
explicit NodeIt(const Graph& graph) : _graph(&graph) {
|
| 425 |
|
|
| 425 |
_graph->first(static_cast<Node&>(*this)); |
|
| 426 | 426 |
} |
| 427 | 427 |
|
| 428 |
NodeIt(const Graph& graph, const Node& node) |
|
| 429 |
: Node(node), _graph(&graph) {}
|
|
| 428 |
NodeIt(const Graph& graph, const Node& node) |
|
| 429 |
: Node(node), _graph(&graph) {}
|
|
| 430 | 430 |
|
| 431 |
NodeIt& operator++() {
|
|
| 432 |
_graph->next(*this); |
|
| 433 |
|
|
| 431 |
NodeIt& operator++() {
|
|
| 432 |
_graph->next(*this); |
|
| 433 |
return *this; |
|
| 434 | 434 |
} |
| 435 | 435 |
|
| 436 | 436 |
}; |
| 437 | 437 |
|
| 438 | 438 |
|
| 439 |
class ArcIt : public Arc {
|
|
| 439 |
class ArcIt : public Arc {
|
|
| 440 | 440 |
const Graph* _graph; |
| 441 | 441 |
public: |
| 442 | 442 |
|
| 443 | 443 |
ArcIt() { }
|
| 444 | 444 |
|
| 445 | 445 |
ArcIt(Invalid i) : Arc(i) { }
|
| 446 | 446 |
|
| 447 | 447 |
explicit ArcIt(const Graph& graph) : _graph(&graph) {
|
| 448 |
|
|
| 448 |
_graph->first(static_cast<Arc&>(*this)); |
|
| 449 | 449 |
} |
| 450 | 450 |
|
| 451 |
ArcIt(const Graph& graph, const Arc& arc) : |
|
| 452 |
Arc(arc), _graph(&graph) { }
|
|
| 451 |
ArcIt(const Graph& graph, const Arc& arc) : |
|
| 452 |
Arc(arc), _graph(&graph) { }
|
|
| 453 | 453 |
|
| 454 |
ArcIt& operator++() {
|
|
| 455 |
_graph->next(*this); |
|
| 456 |
|
|
| 454 |
ArcIt& operator++() {
|
|
| 455 |
_graph->next(*this); |
|
| 456 |
return *this; |
|
| 457 | 457 |
} |
| 458 | 458 |
|
| 459 | 459 |
}; |
| 460 | 460 |
|
| 461 | 461 |
|
| 462 |
class OutArcIt : public Arc {
|
|
| 462 |
class OutArcIt : public Arc {
|
|
| 463 | 463 |
const Graph* _graph; |
| 464 | 464 |
public: |
| 465 | 465 |
|
| 466 | 466 |
OutArcIt() { }
|
| 467 | 467 |
|
| 468 | 468 |
OutArcIt(Invalid i) : Arc(i) { }
|
| 469 | 469 |
|
| 470 |
OutArcIt(const Graph& graph, const Node& node) |
|
| 471 |
: _graph(&graph) {
|
|
| 472 |
|
|
| 470 |
OutArcIt(const Graph& graph, const Node& node) |
|
| 471 |
: _graph(&graph) {
|
|
| 472 |
_graph->firstOut(*this, node); |
|
| 473 | 473 |
} |
| 474 | 474 |
|
| 475 |
OutArcIt(const Graph& graph, const Arc& arc) |
|
| 476 |
: Arc(arc), _graph(&graph) {}
|
|
| 475 |
OutArcIt(const Graph& graph, const Arc& arc) |
|
| 476 |
: Arc(arc), _graph(&graph) {}
|
|
| 477 | 477 |
|
| 478 |
OutArcIt& operator++() {
|
|
| 479 |
_graph->nextOut(*this); |
|
| 480 |
|
|
| 478 |
OutArcIt& operator++() {
|
|
| 479 |
_graph->nextOut(*this); |
|
| 480 |
return *this; |
|
| 481 | 481 |
} |
| 482 | 482 |
|
| 483 | 483 |
}; |
| 484 | 484 |
|
| 485 | 485 |
|
| 486 |
class InArcIt : public Arc {
|
|
| 486 |
class InArcIt : public Arc {
|
|
| 487 | 487 |
const Graph* _graph; |
| 488 | 488 |
public: |
| 489 | 489 |
|
| 490 | 490 |
InArcIt() { }
|
| 491 | 491 |
|
| 492 | 492 |
InArcIt(Invalid i) : Arc(i) { }
|
| 493 | 493 |
|
| 494 |
InArcIt(const Graph& graph, const Node& node) |
|
| 495 |
: _graph(&graph) {
|
|
| 496 |
|
|
| 494 |
InArcIt(const Graph& graph, const Node& node) |
|
| 495 |
: _graph(&graph) {
|
|
| 496 |
_graph->firstIn(*this, node); |
|
| 497 | 497 |
} |
| 498 | 498 |
|
| 499 |
InArcIt(const Graph& graph, const Arc& arc) : |
|
| 500 |
Arc(arc), _graph(&graph) {}
|
|
| 499 |
InArcIt(const Graph& graph, const Arc& arc) : |
|
| 500 |
Arc(arc), _graph(&graph) {}
|
|
| 501 | 501 |
|
| 502 |
InArcIt& operator++() {
|
|
| 503 |
_graph->nextIn(*this); |
|
| 504 |
|
|
| 502 |
InArcIt& operator++() {
|
|
| 503 |
_graph->nextIn(*this); |
|
| 504 |
return *this; |
|
| 505 | 505 |
} |
| 506 | 506 |
|
| 507 | 507 |
}; |
| 508 | 508 |
|
| 509 | 509 |
|
| 510 |
class EdgeIt : public Parent::Edge {
|
|
| 510 |
class EdgeIt : public Parent::Edge {
|
|
| 511 | 511 |
const Graph* _graph; |
| 512 | 512 |
public: |
| 513 | 513 |
|
| 514 | 514 |
EdgeIt() { }
|
| 515 | 515 |
|
| 516 | 516 |
EdgeIt(Invalid i) : Edge(i) { }
|
| 517 | 517 |
|
| 518 | 518 |
explicit EdgeIt(const Graph& graph) : _graph(&graph) {
|
| 519 |
|
|
| 519 |
_graph->first(static_cast<Edge&>(*this)); |
|
| 520 | 520 |
} |
| 521 | 521 |
|
| 522 |
EdgeIt(const Graph& graph, const Edge& edge) : |
|
| 523 |
Edge(edge), _graph(&graph) { }
|
|
| 522 |
EdgeIt(const Graph& graph, const Edge& edge) : |
|
| 523 |
Edge(edge), _graph(&graph) { }
|
|
| 524 | 524 |
|
| 525 |
EdgeIt& operator++() {
|
|
| 526 |
_graph->next(*this); |
|
| 527 |
|
|
| 525 |
EdgeIt& operator++() {
|
|
| 526 |
_graph->next(*this); |
|
| 527 |
return *this; |
|
| 528 | 528 |
} |
| 529 | 529 |
|
| 530 | 530 |
}; |
| 531 | 531 |
|
| 532 | 532 |
class IncEdgeIt : public Parent::Edge {
|
| 533 | 533 |
friend class GraphExtender; |
| 534 | 534 |
const Graph* _graph; |
| 535 | 535 |
bool _direction; |
| 536 | 536 |
public: |
| 537 | 537 |
|
| 538 | 538 |
IncEdgeIt() { }
|
| 539 | 539 |
|
| 540 | 540 |
IncEdgeIt(Invalid i) : Edge(i), _direction(false) { }
|
| 541 | 541 |
|
| 542 | 542 |
IncEdgeIt(const Graph& graph, const Node &node) : _graph(&graph) {
|
| 543 |
|
|
| 543 |
_graph->firstInc(*this, _direction, node); |
|
| 544 | 544 |
} |
| 545 | 545 |
|
| 546 | 546 |
IncEdgeIt(const Graph& graph, const Edge &edge, const Node &node) |
| 547 |
: _graph(&graph), Edge(edge) {
|
|
| 548 |
_direction = (_graph->source(edge) == node); |
|
| 547 |
: _graph(&graph), Edge(edge) {
|
|
| 548 |
_direction = (_graph->source(edge) == node); |
|
| 549 | 549 |
} |
| 550 | 550 |
|
| 551 | 551 |
IncEdgeIt& operator++() {
|
| 552 |
_graph->nextInc(*this, _direction); |
|
| 553 |
return *this; |
|
| 552 |
_graph->nextInc(*this, _direction); |
|
| 553 |
return *this; |
|
| 554 | 554 |
} |
| 555 | 555 |
}; |
| 556 | 556 |
|
| 557 | 557 |
/// \brief Base node of the iterator |
| 558 | 558 |
/// |
| 559 | 559 |
/// Returns the base node (ie. the source in this case) of the iterator |
| 560 | 560 |
Node baseNode(const OutArcIt &arc) const {
|
| 561 | 561 |
return Parent::source(static_cast<const Arc&>(arc)); |
| 562 | 562 |
} |
| 563 | 563 |
/// \brief Running node of the iterator |
| 564 | 564 |
/// |
| 565 | 565 |
/// Returns the running node (ie. the target in this case) of the |
| 566 | 566 |
/// iterator |
| 567 | 567 |
Node runningNode(const OutArcIt &arc) const {
|
| 568 | 568 |
return Parent::target(static_cast<const Arc&>(arc)); |
| 569 | 569 |
} |
| ... | ... |
@@ -585,166 +585,166 @@ |
| 585 | 585 |
/// Base node of the iterator |
| 586 | 586 |
/// |
| 587 | 587 |
/// Returns the base node of the iterator |
| 588 | 588 |
Node baseNode(const IncEdgeIt &edge) const {
|
| 589 | 589 |
return edge._direction ? u(edge) : v(edge); |
| 590 | 590 |
} |
| 591 | 591 |
/// Running node of the iterator |
| 592 | 592 |
/// |
| 593 | 593 |
/// Returns the running node of the iterator |
| 594 | 594 |
Node runningNode(const IncEdgeIt &edge) const {
|
| 595 | 595 |
return edge._direction ? v(edge) : u(edge); |
| 596 | 596 |
} |
| 597 | 597 |
|
| 598 | 598 |
// Mappable extension |
| 599 | 599 |
|
| 600 | 600 |
template <typename _Value> |
| 601 |
class NodeMap |
|
| 601 |
class NodeMap |
|
| 602 | 602 |
: public MapExtender<DefaultMap<Graph, Node, _Value> > {
|
| 603 | 603 |
public: |
| 604 | 604 |
typedef GraphExtender Graph; |
| 605 | 605 |
typedef MapExtender<DefaultMap<Graph, Node, _Value> > Parent; |
| 606 | 606 |
|
| 607 |
NodeMap(const Graph& graph) |
|
| 608 |
: Parent(graph) {}
|
|
| 609 |
NodeMap(const Graph& graph, const _Value& value) |
|
| 610 |
: Parent(graph, value) {}
|
|
| 607 |
NodeMap(const Graph& graph) |
|
| 608 |
: Parent(graph) {}
|
|
| 609 |
NodeMap(const Graph& graph, const _Value& value) |
|
| 610 |
: Parent(graph, value) {}
|
|
| 611 | 611 |
|
| 612 | 612 |
NodeMap& operator=(const NodeMap& cmap) {
|
| 613 |
|
|
| 613 |
return operator=<NodeMap>(cmap); |
|
| 614 | 614 |
} |
| 615 | 615 |
|
| 616 | 616 |
template <typename CMap> |
| 617 | 617 |
NodeMap& operator=(const CMap& cmap) {
|
| 618 | 618 |
Parent::operator=(cmap); |
| 619 |
|
|
| 619 |
return *this; |
|
| 620 | 620 |
} |
| 621 | 621 |
|
| 622 | 622 |
}; |
| 623 | 623 |
|
| 624 | 624 |
template <typename _Value> |
| 625 |
class ArcMap |
|
| 625 |
class ArcMap |
|
| 626 | 626 |
: public MapExtender<DefaultMap<Graph, Arc, _Value> > {
|
| 627 | 627 |
public: |
| 628 | 628 |
typedef GraphExtender Graph; |
| 629 | 629 |
typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent; |
| 630 | 630 |
|
| 631 |
ArcMap(const Graph& graph) |
|
| 632 |
: Parent(graph) {}
|
|
| 633 |
ArcMap(const Graph& graph, const _Value& value) |
|
| 634 |
: Parent(graph, value) {}
|
|
| 631 |
ArcMap(const Graph& graph) |
|
| 632 |
: Parent(graph) {}
|
|
| 633 |
ArcMap(const Graph& graph, const _Value& value) |
|
| 634 |
: Parent(graph, value) {}
|
|
| 635 | 635 |
|
| 636 | 636 |
ArcMap& operator=(const ArcMap& cmap) {
|
| 637 |
|
|
| 637 |
return operator=<ArcMap>(cmap); |
|
| 638 | 638 |
} |
| 639 | 639 |
|
| 640 | 640 |
template <typename CMap> |
| 641 | 641 |
ArcMap& operator=(const CMap& cmap) {
|
| 642 | 642 |
Parent::operator=(cmap); |
| 643 |
|
|
| 643 |
return *this; |
|
| 644 | 644 |
} |
| 645 | 645 |
}; |
| 646 | 646 |
|
| 647 | 647 |
|
| 648 | 648 |
template <typename _Value> |
| 649 |
class EdgeMap |
|
| 649 |
class EdgeMap |
|
| 650 | 650 |
: public MapExtender<DefaultMap<Graph, Edge, _Value> > {
|
| 651 | 651 |
public: |
| 652 | 652 |
typedef GraphExtender Graph; |
| 653 | 653 |
typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent; |
| 654 | 654 |
|
| 655 |
EdgeMap(const Graph& graph) |
|
| 656 |
: Parent(graph) {}
|
|
| 655 |
EdgeMap(const Graph& graph) |
|
| 656 |
: Parent(graph) {}
|
|
| 657 | 657 |
|
| 658 |
EdgeMap(const Graph& graph, const _Value& value) |
|
| 659 |
: Parent(graph, value) {}
|
|
| 658 |
EdgeMap(const Graph& graph, const _Value& value) |
|
| 659 |
: Parent(graph, value) {}
|
|
| 660 | 660 |
|
| 661 | 661 |
EdgeMap& operator=(const EdgeMap& cmap) {
|
| 662 |
|
|
| 662 |
return operator=<EdgeMap>(cmap); |
|
| 663 | 663 |
} |
| 664 | 664 |
|
| 665 | 665 |
template <typename CMap> |
| 666 | 666 |
EdgeMap& operator=(const CMap& cmap) {
|
| 667 | 667 |
Parent::operator=(cmap); |
| 668 |
|
|
| 668 |
return *this; |
|
| 669 | 669 |
} |
| 670 | 670 |
|
| 671 | 671 |
}; |
| 672 | 672 |
|
| 673 | 673 |
// Alteration extension |
| 674 | 674 |
|
| 675 | 675 |
Node addNode() {
|
| 676 | 676 |
Node node = Parent::addNode(); |
| 677 | 677 |
notifier(Node()).add(node); |
| 678 | 678 |
return node; |
| 679 | 679 |
} |
| 680 | 680 |
|
| 681 | 681 |
Edge addEdge(const Node& from, const Node& to) {
|
| 682 | 682 |
Edge edge = Parent::addEdge(from, to); |
| 683 | 683 |
notifier(Edge()).add(edge); |
| 684 | 684 |
std::vector<Arc> ev; |
| 685 | 685 |
ev.push_back(Parent::direct(edge, true)); |
| 686 |
ev.push_back(Parent::direct(edge, false)); |
|
| 686 |
ev.push_back(Parent::direct(edge, false)); |
|
| 687 | 687 |
notifier(Arc()).add(ev); |
| 688 | 688 |
return edge; |
| 689 | 689 |
} |
| 690 |
|
|
| 690 |
|
|
| 691 | 691 |
void clear() {
|
| 692 | 692 |
notifier(Arc()).clear(); |
| 693 | 693 |
notifier(Edge()).clear(); |
| 694 | 694 |
notifier(Node()).clear(); |
| 695 | 695 |
Parent::clear(); |
| 696 | 696 |
} |
| 697 | 697 |
|
| 698 | 698 |
template <typename Graph, typename NodeRefMap, typename EdgeRefMap> |
| 699 |
void build(const Graph& graph, NodeRefMap& nodeRef, |
|
| 699 |
void build(const Graph& graph, NodeRefMap& nodeRef, |
|
| 700 | 700 |
EdgeRefMap& edgeRef) {
|
| 701 | 701 |
Parent::build(graph, nodeRef, edgeRef); |
| 702 | 702 |
notifier(Node()).build(); |
| 703 | 703 |
notifier(Edge()).build(); |
| 704 | 704 |
notifier(Arc()).build(); |
| 705 | 705 |
} |
| 706 | 706 |
|
| 707 | 707 |
void erase(const Node& node) {
|
| 708 | 708 |
Arc arc; |
| 709 | 709 |
Parent::firstOut(arc, node); |
| 710 | 710 |
while (arc != INVALID ) {
|
| 711 |
erase(arc); |
|
| 712 |
Parent::firstOut(arc, node); |
|
| 713 |
|
|
| 711 |
erase(arc); |
|
| 712 |
Parent::firstOut(arc, node); |
|
| 713 |
} |
|
| 714 | 714 |
|
| 715 | 715 |
Parent::firstIn(arc, node); |
| 716 | 716 |
while (arc != INVALID ) {
|
| 717 |
erase(arc); |
|
| 718 |
Parent::firstIn(arc, node); |
|
| 717 |
erase(arc); |
|
| 718 |
Parent::firstIn(arc, node); |
|
| 719 | 719 |
} |
| 720 | 720 |
|
| 721 | 721 |
notifier(Node()).erase(node); |
| 722 | 722 |
Parent::erase(node); |
| 723 | 723 |
} |
| 724 | 724 |
|
| 725 | 725 |
void erase(const Edge& edge) {
|
| 726 | 726 |
std::vector<Arc> av; |
| 727 | 727 |
av.push_back(Parent::direct(edge, true)); |
| 728 |
av.push_back(Parent::direct(edge, false)); |
|
| 728 |
av.push_back(Parent::direct(edge, false)); |
|
| 729 | 729 |
notifier(Arc()).erase(av); |
| 730 | 730 |
notifier(Edge()).erase(edge); |
| 731 | 731 |
Parent::erase(edge); |
| 732 | 732 |
} |
| 733 | 733 |
|
| 734 | 734 |
GraphExtender() {
|
| 735 |
node_notifier.setContainer(*this); |
|
| 735 |
node_notifier.setContainer(*this); |
|
| 736 | 736 |
arc_notifier.setContainer(*this); |
| 737 | 737 |
edge_notifier.setContainer(*this); |
| 738 |
} |
|
| 738 |
} |
|
| 739 | 739 |
|
| 740 | 740 |
~GraphExtender() {
|
| 741 | 741 |
edge_notifier.clear(); |
| 742 | 742 |
arc_notifier.clear(); |
| 743 |
node_notifier.clear(); |
|
| 744 |
} |
|
| 743 |
node_notifier.clear(); |
|
| 744 |
} |
|
| 745 | 745 |
|
| 746 | 746 |
}; |
| 747 | 747 |
|
| 748 | 748 |
} |
| 749 | 749 |
|
| 750 | 750 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_INVALID_H |
| ... | ... |
@@ -21,35 +21,35 @@ |
| 21 | 21 |
|
| 22 | 22 |
///\file |
| 23 | 23 |
///\brief Definition of INVALID. |
| 24 | 24 |
|
| 25 | 25 |
namespace lemon {
|
| 26 | 26 |
|
| 27 | 27 |
/// \brief Dummy type to make it easier to create invalid iterators. |
| 28 | 28 |
/// |
| 29 | 29 |
/// Dummy type to make it easier to create invalid iterators. |
| 30 | 30 |
/// See \ref INVALID for the usage. |
| 31 | 31 |
struct Invalid {
|
| 32 | 32 |
public: |
| 33 | 33 |
bool operator==(Invalid) { return true; }
|
| 34 | 34 |
bool operator!=(Invalid) { return false; }
|
| 35 | 35 |
bool operator< (Invalid) { return false; }
|
| 36 | 36 |
}; |
| 37 |
|
|
| 37 |
|
|
| 38 | 38 |
/// \brief Invalid iterators. |
| 39 | 39 |
/// |
| 40 | 40 |
/// \ref Invalid is a global type that converts to each iterator |
| 41 | 41 |
/// in such a way that the value of the target iterator will be invalid. |
| 42 | 42 |
|
| 43 | 43 |
//Some people didn't like this: |
| 44 | 44 |
//const Invalid &INVALID = *(Invalid *)0; |
| 45 | 45 |
|
| 46 | 46 |
#ifdef LEMON_ONLY_TEMPLATES |
| 47 | 47 |
const Invalid INVALID = Invalid(); |
| 48 | 48 |
#else |
| 49 | 49 |
extern const Invalid INVALID; |
| 50 | 50 |
#endif |
| 51 | 51 |
|
| 52 | 52 |
} //namespace lemon |
| 53 | 53 |
|
| 54 | 54 |
#endif |
| 55 |
|
|
| 55 |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_MAP_EXTENDER_H |
| 20 | 20 |
#define LEMON_BITS_MAP_EXTENDER_H |
| 21 | 21 |
|
| 22 | 22 |
#include <iterator> |
| 23 | 23 |
|
| 24 | 24 |
#include <lemon/bits/traits.h> |
| 25 | 25 |
|
| 26 | 26 |
#include <lemon/concept_check.h> |
| 27 | 27 |
#include <lemon/concepts/maps.h> |
| 28 | 28 |
|
| 29 | 29 |
///\file |
| 30 | 30 |
///\brief Extenders for iterable maps. |
| 31 | 31 |
|
| 32 | 32 |
namespace lemon {
|
| 33 | 33 |
|
| 34 | 34 |
/// \ingroup graphbits |
| 35 |
/// |
|
| 35 |
/// |
|
| 36 | 36 |
/// \brief Extender for maps |
| 37 | 37 |
template <typename _Map> |
| 38 | 38 |
class MapExtender : public _Map {
|
| 39 | 39 |
public: |
| 40 | 40 |
|
| 41 | 41 |
typedef _Map Parent; |
| 42 | 42 |
typedef MapExtender Map; |
| 43 | 43 |
|
| 44 | 44 |
|
| 45 | 45 |
typedef typename Parent::Graph Graph; |
| 46 | 46 |
typedef typename Parent::Key Item; |
| 47 | 47 |
|
| 48 | 48 |
typedef typename Parent::Key Key; |
| 49 | 49 |
typedef typename Parent::Value Value; |
| 50 | 50 |
|
| 51 | 51 |
class MapIt; |
| 52 | 52 |
class ConstMapIt; |
| 53 | 53 |
|
| 54 | 54 |
friend class MapIt; |
| 55 | 55 |
friend class ConstMapIt; |
| 56 | 56 |
|
| 57 | 57 |
public: |
| 58 | 58 |
|
| 59 |
MapExtender(const Graph& graph) |
|
| 59 |
MapExtender(const Graph& graph) |
|
| 60 | 60 |
: Parent(graph) {}
|
| 61 | 61 |
|
| 62 |
MapExtender(const Graph& graph, const Value& value) |
|
| 62 |
MapExtender(const Graph& graph, const Value& value) |
|
| 63 | 63 |
: Parent(graph, value) {}
|
| 64 | 64 |
|
| 65 | 65 |
MapExtender& operator=(const MapExtender& cmap) {
|
| 66 | 66 |
return operator=<MapExtender>(cmap); |
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 | 69 |
template <typename CMap> |
| 70 | 70 |
MapExtender& operator=(const CMap& cmap) {
|
| 71 | 71 |
Parent::operator=(cmap); |
| 72 | 72 |
return *this; |
| 73 |
} |
|
| 73 |
} |
|
| 74 | 74 |
|
| 75 | 75 |
class MapIt : public Item {
|
| 76 | 76 |
public: |
| 77 |
|
|
| 77 |
|
|
| 78 | 78 |
typedef Item Parent; |
| 79 | 79 |
typedef typename Map::Value Value; |
| 80 |
|
|
| 80 |
|
|
| 81 | 81 |
MapIt() {}
|
| 82 | 82 |
|
| 83 | 83 |
MapIt(Invalid i) : Parent(i) { }
|
| 84 | 84 |
|
| 85 | 85 |
explicit MapIt(Map& _map) : map(_map) {
|
| 86 | 86 |
map.notifier()->first(*this); |
| 87 | 87 |
} |
| 88 | 88 |
|
| 89 |
MapIt(const Map& _map, const Item& item) |
|
| 90 |
: Parent(item), map(_map) {}
|
|
| 89 |
MapIt(const Map& _map, const Item& item) |
|
| 90 |
: Parent(item), map(_map) {}
|
|
| 91 | 91 |
|
| 92 |
MapIt& operator++() {
|
|
| 93 |
map.notifier()->next(*this); |
|
| 94 |
|
|
| 92 |
MapIt& operator++() {
|
|
| 93 |
map.notifier()->next(*this); |
|
| 94 |
return *this; |
|
| 95 | 95 |
} |
| 96 |
|
|
| 96 |
|
|
| 97 | 97 |
typename MapTraits<Map>::ConstReturnValue operator*() const {
|
| 98 |
|
|
| 98 |
return map[*this]; |
|
| 99 | 99 |
} |
| 100 | 100 |
|
| 101 | 101 |
typename MapTraits<Map>::ReturnValue operator*() {
|
| 102 |
|
|
| 102 |
return map[*this]; |
|
| 103 | 103 |
} |
| 104 |
|
|
| 104 |
|
|
| 105 | 105 |
void set(const Value& value) {
|
| 106 |
|
|
| 106 |
map.set(*this, value); |
|
| 107 | 107 |
} |
| 108 |
|
|
| 108 |
|
|
| 109 | 109 |
protected: |
| 110 | 110 |
Map& map; |
| 111 |
|
|
| 111 |
|
|
| 112 | 112 |
}; |
| 113 | 113 |
|
| 114 | 114 |
class ConstMapIt : public Item {
|
| 115 | 115 |
public: |
| 116 | 116 |
|
| 117 | 117 |
typedef Item Parent; |
| 118 | 118 |
|
| 119 | 119 |
typedef typename Map::Value Value; |
| 120 |
|
|
| 120 |
|
|
| 121 | 121 |
ConstMapIt() {}
|
| 122 | 122 |
|
| 123 | 123 |
ConstMapIt(Invalid i) : Parent(i) { }
|
| 124 | 124 |
|
| 125 | 125 |
explicit ConstMapIt(Map& _map) : map(_map) {
|
| 126 | 126 |
map.notifier()->first(*this); |
| 127 | 127 |
} |
| 128 | 128 |
|
| 129 |
ConstMapIt(const Map& _map, const Item& item) |
|
| 130 |
: Parent(item), map(_map) {}
|
|
| 129 |
ConstMapIt(const Map& _map, const Item& item) |
|
| 130 |
: Parent(item), map(_map) {}
|
|
| 131 | 131 |
|
| 132 |
ConstMapIt& operator++() {
|
|
| 133 |
map.notifier()->next(*this); |
|
| 134 |
|
|
| 132 |
ConstMapIt& operator++() {
|
|
| 133 |
map.notifier()->next(*this); |
|
| 134 |
return *this; |
|
| 135 | 135 |
} |
| 136 | 136 |
|
| 137 | 137 |
typename MapTraits<Map>::ConstReturnValue operator*() const {
|
| 138 |
|
|
| 138 |
return map[*this]; |
|
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 | 141 |
protected: |
| 142 | 142 |
const Map& map; |
| 143 | 143 |
}; |
| 144 | 144 |
|
| 145 | 145 |
class ItemIt : public Item {
|
| 146 | 146 |
public: |
| 147 |
|
|
| 147 |
|
|
| 148 | 148 |
typedef Item Parent; |
| 149 |
|
|
| 149 |
|
|
| 150 | 150 |
ItemIt() {}
|
| 151 | 151 |
|
| 152 | 152 |
ItemIt(Invalid i) : Parent(i) { }
|
| 153 | 153 |
|
| 154 | 154 |
explicit ItemIt(Map& _map) : map(_map) {
|
| 155 | 155 |
map.notifier()->first(*this); |
| 156 | 156 |
} |
| 157 | 157 |
|
| 158 |
ItemIt(const Map& _map, const Item& item) |
|
| 159 |
: Parent(item), map(_map) {}
|
|
| 158 |
ItemIt(const Map& _map, const Item& item) |
|
| 159 |
: Parent(item), map(_map) {}
|
|
| 160 | 160 |
|
| 161 |
ItemIt& operator++() {
|
|
| 162 |
map.notifier()->next(*this); |
|
| 163 |
|
|
| 161 |
ItemIt& operator++() {
|
|
| 162 |
map.notifier()->next(*this); |
|
| 163 |
return *this; |
|
| 164 | 164 |
} |
| 165 | 165 |
|
| 166 | 166 |
protected: |
| 167 | 167 |
const Map& map; |
| 168 |
|
|
| 168 |
|
|
| 169 | 169 |
}; |
| 170 | 170 |
}; |
| 171 | 171 |
|
| 172 | 172 |
/// \ingroup graphbits |
| 173 |
/// |
|
| 173 |
/// |
|
| 174 | 174 |
/// \brief Extender for maps which use a subset of the items. |
| 175 | 175 |
template <typename _Graph, typename _Map> |
| 176 | 176 |
class SubMapExtender : public _Map {
|
| 177 | 177 |
public: |
| 178 | 178 |
|
| 179 | 179 |
typedef _Map Parent; |
| 180 | 180 |
typedef SubMapExtender Map; |
| 181 | 181 |
|
| 182 | 182 |
typedef _Graph Graph; |
| 183 | 183 |
|
| 184 | 184 |
typedef typename Parent::Key Item; |
| 185 | 185 |
|
| 186 | 186 |
typedef typename Parent::Key Key; |
| 187 | 187 |
typedef typename Parent::Value Value; |
| 188 | 188 |
|
| 189 | 189 |
class MapIt; |
| 190 | 190 |
class ConstMapIt; |
| 191 | 191 |
|
| 192 | 192 |
friend class MapIt; |
| 193 | 193 |
friend class ConstMapIt; |
| 194 | 194 |
|
| 195 | 195 |
public: |
| 196 | 196 |
|
| 197 |
SubMapExtender(const Graph& _graph) |
|
| 197 |
SubMapExtender(const Graph& _graph) |
|
| 198 | 198 |
: Parent(_graph), graph(_graph) {}
|
| 199 | 199 |
|
| 200 |
SubMapExtender(const Graph& _graph, const Value& _value) |
|
| 200 |
SubMapExtender(const Graph& _graph, const Value& _value) |
|
| 201 | 201 |
: Parent(_graph, _value), graph(_graph) {}
|
| 202 | 202 |
|
| 203 | 203 |
SubMapExtender& operator=(const SubMapExtender& cmap) {
|
| 204 | 204 |
return operator=<MapExtender>(cmap); |
| 205 | 205 |
} |
| 206 | 206 |
|
| 207 | 207 |
template <typename CMap> |
| 208 | 208 |
SubMapExtender& operator=(const CMap& cmap) {
|
| 209 | 209 |
checkConcept<concepts::ReadMap<Key, Value>, CMap>(); |
| 210 | 210 |
Item it; |
| 211 | 211 |
for (graph.first(it); it != INVALID; graph.next(it)) {
|
| 212 | 212 |
Parent::set(it, cmap[it]); |
| 213 | 213 |
} |
| 214 | 214 |
return *this; |
| 215 |
} |
|
| 215 |
} |
|
| 216 | 216 |
|
| 217 | 217 |
class MapIt : public Item {
|
| 218 | 218 |
public: |
| 219 |
|
|
| 219 |
|
|
| 220 | 220 |
typedef Item Parent; |
| 221 | 221 |
typedef typename Map::Value Value; |
| 222 |
|
|
| 222 |
|
|
| 223 | 223 |
MapIt() {}
|
| 224 | 224 |
|
| 225 | 225 |
MapIt(Invalid i) : Parent(i) { }
|
| 226 | 226 |
|
| 227 | 227 |
explicit MapIt(Map& _map) : map(_map) {
|
| 228 | 228 |
map.graph.first(*this); |
| 229 | 229 |
} |
| 230 | 230 |
|
| 231 |
MapIt(const Map& _map, const Item& item) |
|
| 232 |
: Parent(item), map(_map) {}
|
|
| 231 |
MapIt(const Map& _map, const Item& item) |
|
| 232 |
: Parent(item), map(_map) {}
|
|
| 233 | 233 |
|
| 234 |
MapIt& operator++() {
|
|
| 235 |
map.graph.next(*this); |
|
| 236 |
|
|
| 234 |
MapIt& operator++() {
|
|
| 235 |
map.graph.next(*this); |
|
| 236 |
return *this; |
|
| 237 | 237 |
} |
| 238 |
|
|
| 238 |
|
|
| 239 | 239 |
typename MapTraits<Map>::ConstReturnValue operator*() const {
|
| 240 |
|
|
| 240 |
return map[*this]; |
|
| 241 | 241 |
} |
| 242 | 242 |
|
| 243 | 243 |
typename MapTraits<Map>::ReturnValue operator*() {
|
| 244 |
|
|
| 244 |
return map[*this]; |
|
| 245 | 245 |
} |
| 246 |
|
|
| 246 |
|
|
| 247 | 247 |
void set(const Value& value) {
|
| 248 |
|
|
| 248 |
map.set(*this, value); |
|
| 249 | 249 |
} |
| 250 |
|
|
| 250 |
|
|
| 251 | 251 |
protected: |
| 252 | 252 |
Map& map; |
| 253 |
|
|
| 253 |
|
|
| 254 | 254 |
}; |
| 255 | 255 |
|
| 256 | 256 |
class ConstMapIt : public Item {
|
| 257 | 257 |
public: |
| 258 | 258 |
|
| 259 | 259 |
typedef Item Parent; |
| 260 | 260 |
|
| 261 | 261 |
typedef typename Map::Value Value; |
| 262 |
|
|
| 262 |
|
|
| 263 | 263 |
ConstMapIt() {}
|
| 264 | 264 |
|
| 265 | 265 |
ConstMapIt(Invalid i) : Parent(i) { }
|
| 266 | 266 |
|
| 267 | 267 |
explicit ConstMapIt(Map& _map) : map(_map) {
|
| 268 | 268 |
map.graph.first(*this); |
| 269 | 269 |
} |
| 270 | 270 |
|
| 271 |
ConstMapIt(const Map& _map, const Item& item) |
|
| 272 |
: Parent(item), map(_map) {}
|
|
| 271 |
ConstMapIt(const Map& _map, const Item& item) |
|
| 272 |
: Parent(item), map(_map) {}
|
|
| 273 | 273 |
|
| 274 |
ConstMapIt& operator++() {
|
|
| 275 |
map.graph.next(*this); |
|
| 276 |
|
|
| 274 |
ConstMapIt& operator++() {
|
|
| 275 |
map.graph.next(*this); |
|
| 276 |
return *this; |
|
| 277 | 277 |
} |
| 278 | 278 |
|
| 279 | 279 |
typename MapTraits<Map>::ConstReturnValue operator*() const {
|
| 280 |
|
|
| 280 |
return map[*this]; |
|
| 281 | 281 |
} |
| 282 | 282 |
|
| 283 | 283 |
protected: |
| 284 | 284 |
const Map& map; |
| 285 | 285 |
}; |
| 286 | 286 |
|
| 287 | 287 |
class ItemIt : public Item {
|
| 288 | 288 |
public: |
| 289 |
|
|
| 289 |
|
|
| 290 | 290 |
typedef Item Parent; |
| 291 |
|
|
| 291 |
|
|
| 292 | 292 |
ItemIt() {}
|
| 293 | 293 |
|
| 294 | 294 |
ItemIt(Invalid i) : Parent(i) { }
|
| 295 | 295 |
|
| 296 | 296 |
explicit ItemIt(Map& _map) : map(_map) {
|
| 297 | 297 |
map.graph.first(*this); |
| 298 | 298 |
} |
| 299 | 299 |
|
| 300 |
ItemIt(const Map& _map, const Item& item) |
|
| 301 |
: Parent(item), map(_map) {}
|
|
| 300 |
ItemIt(const Map& _map, const Item& item) |
|
| 301 |
: Parent(item), map(_map) {}
|
|
| 302 | 302 |
|
| 303 |
ItemIt& operator++() {
|
|
| 304 |
map.graph.next(*this); |
|
| 305 |
|
|
| 303 |
ItemIt& operator++() {
|
|
| 304 |
map.graph.next(*this); |
|
| 305 |
return *this; |
|
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
protected: |
| 309 | 309 |
const Map& map; |
| 310 |
|
|
| 310 |
|
|
| 311 | 311 |
}; |
| 312 |
|
|
| 312 |
|
|
| 313 | 313 |
private: |
| 314 | 314 |
|
| 315 | 315 |
const Graph& graph; |
| 316 |
|
|
| 316 |
|
|
| 317 | 317 |
}; |
| 318 | 318 |
|
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 | 321 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_PRED_MAP_PATH_H |
| ... | ... |
@@ -40,135 +40,135 @@ |
| 40 | 40 |
typename Digraph::Arc arc; |
| 41 | 41 |
while ((arc = predMap[node]) != INVALID) {
|
| 42 | 42 |
node = digraph.source(arc); |
| 43 | 43 |
++len; |
| 44 | 44 |
} |
| 45 | 45 |
return len; |
| 46 | 46 |
} |
| 47 | 47 |
|
| 48 | 48 |
bool empty() const {
|
| 49 | 49 |
return predMap[target] != INVALID; |
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 | 52 |
class RevArcIt {
|
| 53 | 53 |
public: |
| 54 | 54 |
RevArcIt() {}
|
| 55 | 55 |
RevArcIt(Invalid) : path(0), current(INVALID) {}
|
| 56 |
RevArcIt(const PredMapPath& _path) |
|
| 56 |
RevArcIt(const PredMapPath& _path) |
|
| 57 | 57 |
: path(&_path), current(_path.target) {
|
| 58 | 58 |
if (path->predMap[current] == INVALID) current = INVALID; |
| 59 | 59 |
} |
| 60 | 60 |
|
| 61 | 61 |
operator const typename Digraph::Arc() const {
|
| 62 | 62 |
return path->predMap[current]; |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 | 65 |
RevArcIt& operator++() {
|
| 66 | 66 |
current = path->digraph.source(path->predMap[current]); |
| 67 | 67 |
if (path->predMap[current] == INVALID) current = INVALID; |
| 68 | 68 |
return *this; |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 |
bool operator==(const RevArcIt& e) const {
|
|
| 72 |
return current == e.current; |
|
| 71 |
bool operator==(const RevArcIt& e) const {
|
|
| 72 |
return current == e.current; |
|
| 73 | 73 |
} |
| 74 | 74 |
|
| 75 | 75 |
bool operator!=(const RevArcIt& e) const {
|
| 76 |
return current != e.current; |
|
| 76 |
return current != e.current; |
|
| 77 | 77 |
} |
| 78 | 78 |
|
| 79 |
bool operator<(const RevArcIt& e) const {
|
|
| 80 |
return current < e.current; |
|
| 79 |
bool operator<(const RevArcIt& e) const {
|
|
| 80 |
return current < e.current; |
|
| 81 | 81 |
} |
| 82 |
|
|
| 82 |
|
|
| 83 | 83 |
private: |
| 84 | 84 |
const PredMapPath* path; |
| 85 | 85 |
typename Digraph::Node current; |
| 86 | 86 |
}; |
| 87 | 87 |
|
| 88 | 88 |
private: |
| 89 | 89 |
const Digraph& digraph; |
| 90 | 90 |
const PredMap& predMap; |
| 91 | 91 |
typename Digraph::Node target; |
| 92 | 92 |
}; |
| 93 | 93 |
|
| 94 | 94 |
|
| 95 | 95 |
template <typename _Digraph, typename _PredMatrixMap> |
| 96 | 96 |
class PredMatrixMapPath {
|
| 97 | 97 |
public: |
| 98 | 98 |
typedef True RevPathTag; |
| 99 | 99 |
|
| 100 | 100 |
typedef _Digraph Digraph; |
| 101 | 101 |
typedef typename Digraph::Arc Arc; |
| 102 | 102 |
typedef _PredMatrixMap PredMatrixMap; |
| 103 | 103 |
|
| 104 |
PredMatrixMapPath(const Digraph& _digraph, |
|
| 104 |
PredMatrixMapPath(const Digraph& _digraph, |
|
| 105 | 105 |
const PredMatrixMap& _predMatrixMap, |
| 106 |
typename Digraph::Node _source, |
|
| 106 |
typename Digraph::Node _source, |
|
| 107 | 107 |
typename Digraph::Node _target) |
| 108 |
: digraph(_digraph), predMatrixMap(_predMatrixMap), |
|
| 108 |
: digraph(_digraph), predMatrixMap(_predMatrixMap), |
|
| 109 | 109 |
source(_source), target(_target) {}
|
| 110 | 110 |
|
| 111 | 111 |
int length() const {
|
| 112 | 112 |
int len = 0; |
| 113 | 113 |
typename Digraph::Node node = target; |
| 114 | 114 |
typename Digraph::Arc arc; |
| 115 | 115 |
while ((arc = predMatrixMap(source, node)) != INVALID) {
|
| 116 | 116 |
node = digraph.source(arc); |
| 117 | 117 |
++len; |
| 118 | 118 |
} |
| 119 | 119 |
return len; |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
bool empty() const {
|
| 123 | 123 |
return source != target; |
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 | 126 |
class RevArcIt {
|
| 127 | 127 |
public: |
| 128 | 128 |
RevArcIt() {}
|
| 129 | 129 |
RevArcIt(Invalid) : path(0), current(INVALID) {}
|
| 130 |
RevArcIt(const PredMatrixMapPath& _path) |
|
| 130 |
RevArcIt(const PredMatrixMapPath& _path) |
|
| 131 | 131 |
: path(&_path), current(_path.target) {
|
| 132 |
if (path->predMatrixMap(path->source, current) == INVALID) |
|
| 132 |
if (path->predMatrixMap(path->source, current) == INVALID) |
|
| 133 | 133 |
current = INVALID; |
| 134 | 134 |
} |
| 135 | 135 |
|
| 136 | 136 |
operator const typename Digraph::Arc() const {
|
| 137 | 137 |
return path->predMatrixMap(path->source, current); |
| 138 | 138 |
} |
| 139 | 139 |
|
| 140 | 140 |
RevArcIt& operator++() {
|
| 141 |
current = |
|
| 141 |
current = |
|
| 142 | 142 |
path->digraph.source(path->predMatrixMap(path->source, current)); |
| 143 |
if (path->predMatrixMap(path->source, current) == INVALID) |
|
| 143 |
if (path->predMatrixMap(path->source, current) == INVALID) |
|
| 144 | 144 |
current = INVALID; |
| 145 | 145 |
return *this; |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 |
bool operator==(const RevArcIt& e) const {
|
|
| 149 |
return current == e.current; |
|
| 148 |
bool operator==(const RevArcIt& e) const {
|
|
| 149 |
return current == e.current; |
|
| 150 | 150 |
} |
| 151 | 151 |
|
| 152 | 152 |
bool operator!=(const RevArcIt& e) const {
|
| 153 |
return current != e.current; |
|
| 153 |
return current != e.current; |
|
| 154 | 154 |
} |
| 155 | 155 |
|
| 156 |
bool operator<(const RevArcIt& e) const {
|
|
| 157 |
return current < e.current; |
|
| 156 |
bool operator<(const RevArcIt& e) const {
|
|
| 157 |
return current < e.current; |
|
| 158 | 158 |
} |
| 159 |
|
|
| 159 |
|
|
| 160 | 160 |
private: |
| 161 | 161 |
const PredMatrixMapPath* path; |
| 162 | 162 |
typename Digraph::Node current; |
| 163 | 163 |
}; |
| 164 | 164 |
|
| 165 | 165 |
private: |
| 166 | 166 |
const Digraph& digraph; |
| 167 | 167 |
const PredMatrixMap& predMatrixMap; |
| 168 | 168 |
typename Digraph::Node source; |
| 169 | 169 |
typename Digraph::Node target; |
| 170 | 170 |
}; |
| 171 | 171 |
|
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
#endif |
| 1 |
|
|
| 2 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 3 | 2 |
* |
| 4 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 5 | 4 |
* |
| 6 | 5 |
* Copyright (C) 2003-2008 |
| 7 | 6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport |
| 8 | 7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES). |
| 9 | 8 |
* |
| 10 | 9 |
* Permission to use, modify and distribute this software is granted |
| 11 | 10 |
* provided that this copyright notice appears in all copies. For |
| 12 | 11 |
* precise terms see the accompanying LICENSE file. |
| 13 | 12 |
* |
| 14 | 13 |
* This software is provided "AS IS" with no warranty of any kind, |
| 15 | 14 |
* express or implied, and with no claim as to its suitability for any |
| 16 | 15 |
* purpose. |
| 17 | 16 |
* |
| 18 | 17 |
*/ |
| 19 | 18 |
|
| 20 | 19 |
#ifndef LEMON_BITS_TRAITS_H |
| 21 | 20 |
#define LEMON_BITS_TRAITS_H |
| 22 | 21 |
|
| 23 | 22 |
#include <lemon/bits/utility.h> |
| 24 | 23 |
|
| 25 | 24 |
///\file |
| 26 | 25 |
///\brief Traits for graphs and maps |
| 27 | 26 |
/// |
| 28 | 27 |
|
| 29 | 28 |
namespace lemon {
|
| 30 | 29 |
template <typename _Graph, typename _Item> |
| 31 | 30 |
class ItemSetTraits {};
|
| 32 |
|
|
| 31 |
|
|
| 33 | 32 |
|
| 34 | 33 |
template <typename Graph, typename Enable = void> |
| 35 | 34 |
struct NodeNotifierIndicator {
|
| 36 | 35 |
typedef InvalidType Type; |
| 37 | 36 |
}; |
| 38 | 37 |
template <typename Graph> |
| 39 | 38 |
struct NodeNotifierIndicator< |
| 40 |
Graph, |
|
| 39 |
Graph, |
|
| 41 | 40 |
typename enable_if<typename Graph::NodeNotifier::Notifier, void>::type |
| 42 |
> {
|
|
| 41 |
> {
|
|
| 43 | 42 |
typedef typename Graph::NodeNotifier Type; |
| 44 | 43 |
}; |
| 45 | 44 |
|
| 46 | 45 |
template <typename _Graph> |
| 47 | 46 |
class ItemSetTraits<_Graph, typename _Graph::Node> {
|
| 48 | 47 |
public: |
| 49 |
|
|
| 48 |
|
|
| 50 | 49 |
typedef _Graph Graph; |
| 51 | 50 |
|
| 52 | 51 |
typedef typename Graph::Node Item; |
| 53 | 52 |
typedef typename Graph::NodeIt ItemIt; |
| 54 | 53 |
|
| 55 | 54 |
typedef typename NodeNotifierIndicator<Graph>::Type ItemNotifier; |
| 56 | 55 |
|
| 57 | 56 |
template <typename _Value> |
| 58 | 57 |
class Map : public Graph::template NodeMap<_Value> {
|
| 59 | 58 |
public: |
| 60 |
typedef typename Graph::template NodeMap<_Value> Parent; |
|
| 61 |
typedef typename Graph::template NodeMap<_Value> Type; |
|
| 59 |
typedef typename Graph::template NodeMap<_Value> Parent; |
|
| 60 |
typedef typename Graph::template NodeMap<_Value> Type; |
|
| 62 | 61 |
typedef typename Parent::Value Value; |
| 63 | 62 |
|
| 64 | 63 |
Map(const Graph& _digraph) : Parent(_digraph) {}
|
| 65 |
Map(const Graph& _digraph, const Value& _value) |
|
| 66 |
: Parent(_digraph, _value) {}
|
|
| 64 |
Map(const Graph& _digraph, const Value& _value) |
|
| 65 |
: Parent(_digraph, _value) {}
|
|
| 67 | 66 |
|
| 68 | 67 |
}; |
| 69 | 68 |
|
| 70 | 69 |
}; |
| 71 | 70 |
|
| 72 | 71 |
template <typename Graph, typename Enable = void> |
| 73 | 72 |
struct ArcNotifierIndicator {
|
| 74 | 73 |
typedef InvalidType Type; |
| 75 | 74 |
}; |
| 76 | 75 |
template <typename Graph> |
| 77 | 76 |
struct ArcNotifierIndicator< |
| 78 |
Graph, |
|
| 77 |
Graph, |
|
| 79 | 78 |
typename enable_if<typename Graph::ArcNotifier::Notifier, void>::type |
| 80 |
> {
|
|
| 79 |
> {
|
|
| 81 | 80 |
typedef typename Graph::ArcNotifier Type; |
| 82 | 81 |
}; |
| 83 | 82 |
|
| 84 | 83 |
template <typename _Graph> |
| 85 | 84 |
class ItemSetTraits<_Graph, typename _Graph::Arc> {
|
| 86 | 85 |
public: |
| 87 |
|
|
| 86 |
|
|
| 88 | 87 |
typedef _Graph Graph; |
| 89 | 88 |
|
| 90 | 89 |
typedef typename Graph::Arc Item; |
| 91 | 90 |
typedef typename Graph::ArcIt ItemIt; |
| 92 | 91 |
|
| 93 | 92 |
typedef typename ArcNotifierIndicator<Graph>::Type ItemNotifier; |
| 94 | 93 |
|
| 95 | 94 |
template <typename _Value> |
| 96 | 95 |
class Map : public Graph::template ArcMap<_Value> {
|
| 97 | 96 |
public: |
| 98 |
typedef typename Graph::template ArcMap<_Value> Parent; |
|
| 99 |
typedef typename Graph::template ArcMap<_Value> Type; |
|
| 97 |
typedef typename Graph::template ArcMap<_Value> Parent; |
|
| 98 |
typedef typename Graph::template ArcMap<_Value> Type; |
|
| 100 | 99 |
typedef typename Parent::Value Value; |
| 101 | 100 |
|
| 102 | 101 |
Map(const Graph& _digraph) : Parent(_digraph) {}
|
| 103 |
Map(const Graph& _digraph, const Value& _value) |
|
| 104 |
: Parent(_digraph, _value) {}
|
|
| 102 |
Map(const Graph& _digraph, const Value& _value) |
|
| 103 |
: Parent(_digraph, _value) {}
|
|
| 105 | 104 |
}; |
| 106 | 105 |
|
| 107 | 106 |
}; |
| 108 | 107 |
|
| 109 | 108 |
template <typename Graph, typename Enable = void> |
| 110 | 109 |
struct EdgeNotifierIndicator {
|
| 111 | 110 |
typedef InvalidType Type; |
| 112 | 111 |
}; |
| 113 | 112 |
template <typename Graph> |
| 114 | 113 |
struct EdgeNotifierIndicator< |
| 115 |
Graph, |
|
| 114 |
Graph, |
|
| 116 | 115 |
typename enable_if<typename Graph::EdgeNotifier::Notifier, void>::type |
| 117 |
> {
|
|
| 116 |
> {
|
|
| 118 | 117 |
typedef typename Graph::EdgeNotifier Type; |
| 119 | 118 |
}; |
| 120 | 119 |
|
| 121 | 120 |
template <typename _Graph> |
| 122 | 121 |
class ItemSetTraits<_Graph, typename _Graph::Edge> {
|
| 123 | 122 |
public: |
| 124 |
|
|
| 123 |
|
|
| 125 | 124 |
typedef _Graph Graph; |
| 126 | 125 |
|
| 127 | 126 |
typedef typename Graph::Edge Item; |
| 128 | 127 |
typedef typename Graph::EdgeIt ItemIt; |
| 129 | 128 |
|
| 130 | 129 |
typedef typename EdgeNotifierIndicator<Graph>::Type ItemNotifier; |
| 131 | 130 |
|
| 132 | 131 |
template <typename _Value> |
| 133 | 132 |
class Map : public Graph::template EdgeMap<_Value> {
|
| 134 | 133 |
public: |
| 135 |
typedef typename Graph::template EdgeMap<_Value> Parent; |
|
| 136 |
typedef typename Graph::template EdgeMap<_Value> Type; |
|
| 134 |
typedef typename Graph::template EdgeMap<_Value> Parent; |
|
| 135 |
typedef typename Graph::template EdgeMap<_Value> Type; |
|
| 137 | 136 |
typedef typename Parent::Value Value; |
| 138 | 137 |
|
| 139 | 138 |
Map(const Graph& _digraph) : Parent(_digraph) {}
|
| 140 |
Map(const Graph& _digraph, const Value& _value) |
|
| 141 |
: Parent(_digraph, _value) {}
|
|
| 139 |
Map(const Graph& _digraph, const Value& _value) |
|
| 140 |
: Parent(_digraph, _value) {}
|
|
| 142 | 141 |
}; |
| 143 | 142 |
|
| 144 | 143 |
}; |
| 145 | 144 |
|
| 146 | 145 |
template <typename Map, typename Enable = void> |
| 147 | 146 |
struct MapTraits {
|
| 148 | 147 |
typedef False ReferenceMapTag; |
| 149 | 148 |
|
| 150 | 149 |
typedef typename Map::Key Key; |
| 151 | 150 |
typedef typename Map::Value Value; |
| 152 | 151 |
|
| 153 | 152 |
typedef Value ConstReturnValue; |
| 154 | 153 |
typedef Value ReturnValue; |
| 155 | 154 |
}; |
| 156 | 155 |
|
| 157 | 156 |
template <typename Map> |
| 158 | 157 |
struct MapTraits< |
| 159 |
Map, typename enable_if<typename Map::ReferenceMapTag, void>::type > |
|
| 158 |
Map, typename enable_if<typename Map::ReferenceMapTag, void>::type > |
|
| 160 | 159 |
{
|
| 161 | 160 |
typedef True ReferenceMapTag; |
| 162 |
|
|
| 161 |
|
|
| 163 | 162 |
typedef typename Map::Key Key; |
| 164 | 163 |
typedef typename Map::Value Value; |
| 165 | 164 |
|
| 166 | 165 |
typedef typename Map::ConstReference ConstReturnValue; |
| 167 | 166 |
typedef typename Map::Reference ReturnValue; |
| 168 | 167 |
|
| 169 |
typedef typename Map::ConstReference ConstReference; |
|
| 168 |
typedef typename Map::ConstReference ConstReference; |
|
| 170 | 169 |
typedef typename Map::Reference Reference; |
| 171 | 170 |
}; |
| 172 | 171 |
|
| 173 | 172 |
template <typename MatrixMap, typename Enable = void> |
| 174 | 173 |
struct MatrixMapTraits {
|
| 175 | 174 |
typedef False ReferenceMapTag; |
| 176 | 175 |
|
| 177 | 176 |
typedef typename MatrixMap::FirstKey FirstKey; |
| 178 | 177 |
typedef typename MatrixMap::SecondKey SecondKey; |
| 179 | 178 |
typedef typename MatrixMap::Value Value; |
| 180 | 179 |
|
| 181 | 180 |
typedef Value ConstReturnValue; |
| 182 | 181 |
typedef Value ReturnValue; |
| 183 | 182 |
}; |
| 184 | 183 |
|
| 185 | 184 |
template <typename MatrixMap> |
| 186 | 185 |
struct MatrixMapTraits< |
| 187 |
MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag, |
|
| 188 |
void>::type > |
|
| 186 |
MatrixMap, typename enable_if<typename MatrixMap::ReferenceMapTag, |
|
| 187 |
void>::type > |
|
| 189 | 188 |
{
|
| 190 | 189 |
typedef True ReferenceMapTag; |
| 191 |
|
|
| 190 |
|
|
| 192 | 191 |
typedef typename MatrixMap::FirstKey FirstKey; |
| 193 | 192 |
typedef typename MatrixMap::SecondKey SecondKey; |
| 194 | 193 |
typedef typename MatrixMap::Value Value; |
| 195 | 194 |
|
| 196 | 195 |
typedef typename MatrixMap::ConstReference ConstReturnValue; |
| 197 | 196 |
typedef typename MatrixMap::Reference ReturnValue; |
| 198 | 197 |
|
| 199 |
typedef typename MatrixMap::ConstReference ConstReference; |
|
| 198 |
typedef typename MatrixMap::ConstReference ConstReference; |
|
| 200 | 199 |
typedef typename MatrixMap::Reference Reference; |
| 201 | 200 |
}; |
| 202 | 201 |
|
| 203 | 202 |
// Indicators for the tags |
| 204 | 203 |
|
| 205 | 204 |
template <typename Graph, typename Enable = void> |
| 206 | 205 |
struct NodeNumTagIndicator {
|
| 207 | 206 |
static const bool value = false; |
| 208 | 207 |
}; |
| 209 | 208 |
|
| 210 | 209 |
template <typename Graph> |
| 211 | 210 |
struct NodeNumTagIndicator< |
| 212 |
Graph, |
|
| 211 |
Graph, |
|
| 213 | 212 |
typename enable_if<typename Graph::NodeNumTag, void>::type |
| 214 | 213 |
> {
|
| 215 | 214 |
static const bool value = true; |
| 216 | 215 |
}; |
| 217 | 216 |
|
| 218 | 217 |
template <typename Graph, typename Enable = void> |
| 219 | 218 |
struct EdgeNumTagIndicator {
|
| 220 | 219 |
static const bool value = false; |
| 221 | 220 |
}; |
| 222 | 221 |
|
| 223 | 222 |
template <typename Graph> |
| 224 | 223 |
struct EdgeNumTagIndicator< |
| 225 |
Graph, |
|
| 224 |
Graph, |
|
| 226 | 225 |
typename enable_if<typename Graph::EdgeNumTag, void>::type |
| 227 | 226 |
> {
|
| 228 | 227 |
static const bool value = true; |
| 229 | 228 |
}; |
| 230 | 229 |
|
| 231 | 230 |
template <typename Graph, typename Enable = void> |
| 232 | 231 |
struct FindEdgeTagIndicator {
|
| 233 | 232 |
static const bool value = false; |
| 234 | 233 |
}; |
| 235 | 234 |
|
| 236 | 235 |
template <typename Graph> |
| 237 | 236 |
struct FindEdgeTagIndicator< |
| 238 |
Graph, |
|
| 237 |
Graph, |
|
| 239 | 238 |
typename enable_if<typename Graph::FindEdgeTag, void>::type |
| 240 | 239 |
> {
|
| 241 | 240 |
static const bool value = true; |
| 242 | 241 |
}; |
| 243 | 242 |
|
| 244 | 243 |
template <typename Graph, typename Enable = void> |
| 245 | 244 |
struct UndirectedTagIndicator {
|
| 246 | 245 |
static const bool value = false; |
| 247 | 246 |
}; |
| 248 | 247 |
|
| 249 | 248 |
template <typename Graph> |
| 250 | 249 |
struct UndirectedTagIndicator< |
| 251 |
Graph, |
|
| 250 |
Graph, |
|
| 252 | 251 |
typename enable_if<typename Graph::UndirectedTag, void>::type |
| 253 | 252 |
> {
|
| 254 | 253 |
static const bool value = true; |
| 255 | 254 |
}; |
| 256 | 255 |
|
| 257 | 256 |
template <typename Graph, typename Enable = void> |
| 258 | 257 |
struct BuildTagIndicator {
|
| 259 | 258 |
static const bool value = false; |
| 260 | 259 |
}; |
| 261 | 260 |
|
| 262 | 261 |
template <typename Graph> |
| 263 | 262 |
struct BuildTagIndicator< |
| 264 |
Graph, |
|
| 263 |
Graph, |
|
| 265 | 264 |
typename enable_if<typename Graph::BuildTag, void>::type |
| 266 | 265 |
> {
|
| 267 | 266 |
static const bool value = true; |
| 268 | 267 |
}; |
| 269 | 268 |
|
| 270 | 269 |
} |
| 271 | 270 |
|
| 272 | 271 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
// This file contains a modified version of the enable_if library from BOOST. |
| ... | ... |
@@ -70,71 +70,71 @@ |
| 70 | 70 |
|
| 71 | 71 |
|
| 72 | 72 |
struct InvalidType {
|
| 73 | 73 |
}; |
| 74 | 74 |
|
| 75 | 75 |
template <typename T> |
| 76 | 76 |
struct Wrap {
|
| 77 | 77 |
const T &value; |
| 78 | 78 |
Wrap(const T &t) : value(t) {}
|
| 79 | 79 |
}; |
| 80 | 80 |
|
| 81 | 81 |
/**************** dummy class to avoid ambiguity ****************/ |
| 82 | 82 |
|
| 83 | 83 |
template<int T> struct dummy { dummy(int) {} };
|
| 84 | 84 |
|
| 85 | 85 |
/**************** enable_if from BOOST ****************/ |
| 86 |
|
|
| 86 |
|
|
| 87 | 87 |
template <typename Type, typename T = void> |
| 88 | 88 |
struct exists {
|
| 89 | 89 |
typedef T type; |
| 90 | 90 |
}; |
| 91 | 91 |
|
| 92 |
|
|
| 92 |
|
|
| 93 | 93 |
template <bool B, class T = void> |
| 94 | 94 |
struct enable_if_c {
|
| 95 | 95 |
typedef T type; |
| 96 | 96 |
}; |
| 97 | 97 |
|
| 98 | 98 |
template <class T> |
| 99 | 99 |
struct enable_if_c<false, T> {};
|
| 100 | 100 |
|
| 101 |
template <class Cond, class T = void> |
|
| 101 |
template <class Cond, class T = void> |
|
| 102 | 102 |
struct enable_if : public enable_if_c<Cond::value, T> {};
|
| 103 | 103 |
|
| 104 | 104 |
template <bool B, class T> |
| 105 | 105 |
struct lazy_enable_if_c {
|
| 106 | 106 |
typedef typename T::type type; |
| 107 | 107 |
}; |
| 108 | 108 |
|
| 109 | 109 |
template <class T> |
| 110 | 110 |
struct lazy_enable_if_c<false, T> {};
|
| 111 | 111 |
|
| 112 |
template <class Cond, class T> |
|
| 112 |
template <class Cond, class T> |
|
| 113 | 113 |
struct lazy_enable_if : public lazy_enable_if_c<Cond::value, T> {};
|
| 114 | 114 |
|
| 115 | 115 |
|
| 116 | 116 |
template <bool B, class T = void> |
| 117 | 117 |
struct disable_if_c {
|
| 118 | 118 |
typedef T type; |
| 119 | 119 |
}; |
| 120 | 120 |
|
| 121 | 121 |
template <class T> |
| 122 | 122 |
struct disable_if_c<true, T> {};
|
| 123 | 123 |
|
| 124 |
template <class Cond, class T = void> |
|
| 124 |
template <class Cond, class T = void> |
|
| 125 | 125 |
struct disable_if : public disable_if_c<Cond::value, T> {};
|
| 126 | 126 |
|
| 127 | 127 |
template <bool B, class T> |
| 128 | 128 |
struct lazy_disable_if_c {
|
| 129 | 129 |
typedef typename T::type type; |
| 130 | 130 |
}; |
| 131 | 131 |
|
| 132 | 132 |
template <class T> |
| 133 | 133 |
struct lazy_disable_if_c<true, T> {};
|
| 134 | 134 |
|
| 135 |
template <class Cond, class T> |
|
| 135 |
template <class Cond, class T> |
|
| 136 | 136 |
struct lazy_disable_if : public lazy_disable_if_c<Cond::value, T> {};
|
| 137 | 137 |
|
| 138 | 138 |
} // namespace lemon |
| 139 | 139 |
|
| 140 | 140 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_BITS_VECTOR_MAP_H |
| ... | ... |
@@ -36,42 +36,42 @@ |
| 36 | 36 |
///\brief Vector based graph maps. |
| 37 | 37 |
namespace lemon {
|
| 38 | 38 |
|
| 39 | 39 |
/// \ingroup graphbits |
| 40 | 40 |
/// |
| 41 | 41 |
/// \brief Graph map based on the std::vector storage. |
| 42 | 42 |
/// |
| 43 | 43 |
/// The VectorMap template class is graph map structure what |
| 44 | 44 |
/// automatically updates the map when a key is added to or erased from |
| 45 | 45 |
/// the map. This map type uses the std::vector to store the values. |
| 46 | 46 |
/// |
| 47 | 47 |
/// \tparam _Notifier The AlterationNotifier that will notify this map. |
| 48 | 48 |
/// \tparam _Item The item type of the graph items. |
| 49 | 49 |
/// \tparam _Value The value type of the map. |
| 50 | 50 |
/// \todo Fix the doc: there is _Graph parameter instead of _Notifier. |
| 51 | 51 |
template <typename _Graph, typename _Item, typename _Value> |
| 52 |
class VectorMap |
|
| 52 |
class VectorMap |
|
| 53 | 53 |
: public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
|
| 54 | 54 |
private: |
| 55 |
|
|
| 55 |
|
|
| 56 | 56 |
/// The container type of the map. |
| 57 |
typedef std::vector<_Value> Container; |
|
| 57 |
typedef std::vector<_Value> Container; |
|
| 58 | 58 |
|
| 59 | 59 |
public: |
| 60 | 60 |
|
| 61 |
/// The graph type of the map. |
|
| 61 |
/// The graph type of the map. |
|
| 62 | 62 |
typedef _Graph Graph; |
| 63 | 63 |
/// The item type of the map. |
| 64 | 64 |
typedef _Item Item; |
| 65 | 65 |
/// The reference map tag. |
| 66 | 66 |
typedef True ReferenceMapTag; |
| 67 | 67 |
|
| 68 | 68 |
/// The key type of the map. |
| 69 | 69 |
typedef _Item Key; |
| 70 | 70 |
/// The value type of the map. |
| 71 | 71 |
typedef _Value Value; |
| 72 | 72 |
|
| 73 | 73 |
/// The notifier type. |
| 74 | 74 |
typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier; |
| 75 | 75 |
|
| 76 | 76 |
/// The map type. |
| 77 | 77 |
typedef VectorMap Map; |
| ... | ... |
@@ -80,163 +80,163 @@ |
| 80 | 80 |
|
| 81 | 81 |
/// The reference type of the map; |
| 82 | 82 |
typedef typename Container::reference Reference; |
| 83 | 83 |
/// The const reference type of the map; |
| 84 | 84 |
typedef typename Container::const_reference ConstReference; |
| 85 | 85 |
|
| 86 | 86 |
|
| 87 | 87 |
/// \brief Constructor to attach the new map into the notifier. |
| 88 | 88 |
/// |
| 89 | 89 |
/// It constructs a map and attachs it into the notifier. |
| 90 | 90 |
/// It adds all the items of the graph to the map. |
| 91 | 91 |
VectorMap(const Graph& graph) {
|
| 92 | 92 |
Parent::attach(graph.notifier(Item())); |
| 93 | 93 |
container.resize(Parent::notifier()->maxId() + 1); |
| 94 | 94 |
} |
| 95 | 95 |
|
| 96 |
/// \brief Constructor uses given value to initialize the map. |
|
| 96 |
/// \brief Constructor uses given value to initialize the map. |
|
| 97 | 97 |
/// |
| 98 |
/// It constructs a map uses a given value to initialize the map. |
|
| 98 |
/// It constructs a map uses a given value to initialize the map. |
|
| 99 | 99 |
/// It adds all the items of the graph to the map. |
| 100 | 100 |
VectorMap(const Graph& graph, const Value& value) {
|
| 101 | 101 |
Parent::attach(graph.notifier(Item())); |
| 102 | 102 |
container.resize(Parent::notifier()->maxId() + 1, value); |
| 103 | 103 |
} |
| 104 | 104 |
|
| 105 | 105 |
/// \brief Copy constructor |
| 106 | 106 |
/// |
| 107 | 107 |
/// Copy constructor. |
| 108 | 108 |
VectorMap(const VectorMap& _copy) : Parent() {
|
| 109 | 109 |
if (_copy.attached()) {
|
| 110 |
Parent::attach(*_copy.notifier()); |
|
| 111 |
container = _copy.container; |
|
| 110 |
Parent::attach(*_copy.notifier()); |
|
| 111 |
container = _copy.container; |
|
| 112 | 112 |
} |
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 | 115 |
/// \brief Assign operator. |
| 116 | 116 |
/// |
| 117 | 117 |
/// This operator assigns for each item in the map the |
| 118 |
/// value mapped to the same item in the copied map. |
|
| 118 |
/// value mapped to the same item in the copied map. |
|
| 119 | 119 |
/// The parameter map should be indiced with the same |
| 120 | 120 |
/// itemset because this assign operator does not change |
| 121 |
/// the container of the map. |
|
| 121 |
/// the container of the map. |
|
| 122 | 122 |
VectorMap& operator=(const VectorMap& cmap) {
|
| 123 | 123 |
return operator=<VectorMap>(cmap); |
| 124 | 124 |
} |
| 125 | 125 |
|
| 126 | 126 |
|
| 127 | 127 |
/// \brief Template assign operator. |
| 128 | 128 |
/// |
| 129 | 129 |
/// The given parameter should be conform to the ReadMap |
| 130 | 130 |
/// concecpt and could be indiced by the current item set of |
| 131 | 131 |
/// the NodeMap. In this case the value for each item |
| 132 |
/// is assigned by the value of the given ReadMap. |
|
| 132 |
/// is assigned by the value of the given ReadMap. |
|
| 133 | 133 |
template <typename CMap> |
| 134 | 134 |
VectorMap& operator=(const CMap& cmap) {
|
| 135 | 135 |
checkConcept<concepts::ReadMap<Key, _Value>, CMap>(); |
| 136 | 136 |
const typename Parent::Notifier* nf = Parent::notifier(); |
| 137 | 137 |
Item it; |
| 138 | 138 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 139 | 139 |
set(it, cmap[it]); |
| 140 | 140 |
} |
| 141 | 141 |
return *this; |
| 142 | 142 |
} |
| 143 |
|
|
| 143 |
|
|
| 144 | 144 |
public: |
| 145 | 145 |
|
| 146 | 146 |
/// \brief The subcript operator. |
| 147 | 147 |
/// |
| 148 | 148 |
/// The subscript operator. The map can be subscripted by the |
| 149 |
/// actual items of the graph. |
|
| 149 |
/// actual items of the graph. |
|
| 150 | 150 |
Reference operator[](const Key& key) {
|
| 151 | 151 |
return container[Parent::notifier()->id(key)]; |
| 152 |
} |
|
| 153 |
|
|
| 152 |
} |
|
| 153 |
|
|
| 154 | 154 |
/// \brief The const subcript operator. |
| 155 | 155 |
/// |
| 156 | 156 |
/// The const subscript operator. The map can be subscripted by the |
| 157 |
/// actual items of the graph. |
|
| 157 |
/// actual items of the graph. |
|
| 158 | 158 |
ConstReference operator[](const Key& key) const {
|
| 159 | 159 |
return container[Parent::notifier()->id(key)]; |
| 160 | 160 |
} |
| 161 | 161 |
|
| 162 | 162 |
|
| 163 | 163 |
/// \brief The setter function of the map. |
| 164 | 164 |
/// |
| 165 | 165 |
/// It the same as operator[](key) = value expression. |
| 166 | 166 |
void set(const Key& key, const Value& value) {
|
| 167 | 167 |
(*this)[key] = value; |
| 168 | 168 |
} |
| 169 | 169 |
|
| 170 | 170 |
protected: |
| 171 | 171 |
|
| 172 | 172 |
/// \brief Adds a new key to the map. |
| 173 |
/// |
|
| 173 |
/// |
|
| 174 | 174 |
/// It adds a new key to the map. It called by the observer notifier |
| 175 |
/// and it overrides the add() member function of the observer base. |
|
| 175 |
/// and it overrides the add() member function of the observer base. |
|
| 176 | 176 |
virtual void add(const Key& key) {
|
| 177 | 177 |
int id = Parent::notifier()->id(key); |
| 178 | 178 |
if (id >= int(container.size())) {
|
| 179 |
|
|
| 179 |
container.resize(id + 1); |
|
| 180 | 180 |
} |
| 181 | 181 |
} |
| 182 | 182 |
|
| 183 | 183 |
/// \brief Adds more new keys to the map. |
| 184 |
/// |
|
| 184 |
/// |
|
| 185 | 185 |
/// It adds more new keys to the map. It called by the observer notifier |
| 186 |
/// and it overrides the add() member function of the observer base. |
|
| 186 |
/// and it overrides the add() member function of the observer base. |
|
| 187 | 187 |
virtual void add(const std::vector<Key>& keys) {
|
| 188 | 188 |
int max = container.size() - 1; |
| 189 | 189 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 190 | 190 |
int id = Parent::notifier()->id(keys[i]); |
| 191 | 191 |
if (id >= max) {
|
| 192 | 192 |
max = id; |
| 193 | 193 |
} |
| 194 | 194 |
} |
| 195 | 195 |
container.resize(max + 1); |
| 196 | 196 |
} |
| 197 | 197 |
|
| 198 | 198 |
/// \brief Erase a key from the map. |
| 199 | 199 |
/// |
| 200 | 200 |
/// Erase a key from the map. It called by the observer notifier |
| 201 |
/// and it overrides the erase() member function of the observer base. |
|
| 201 |
/// and it overrides the erase() member function of the observer base. |
|
| 202 | 202 |
virtual void erase(const Key& key) {
|
| 203 | 203 |
container[Parent::notifier()->id(key)] = Value(); |
| 204 | 204 |
} |
| 205 | 205 |
|
| 206 | 206 |
/// \brief Erase more keys from the map. |
| 207 | 207 |
/// |
| 208 | 208 |
/// Erase more keys from the map. It called by the observer notifier |
| 209 |
/// and it overrides the erase() member function of the observer base. |
|
| 209 |
/// and it overrides the erase() member function of the observer base. |
|
| 210 | 210 |
virtual void erase(const std::vector<Key>& keys) {
|
| 211 | 211 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 212 |
|
|
| 212 |
container[Parent::notifier()->id(keys[i])] = Value(); |
|
| 213 | 213 |
} |
| 214 | 214 |
} |
| 215 |
|
|
| 215 |
|
|
| 216 | 216 |
/// \brief Buildes the map. |
| 217 |
/// |
|
| 217 |
/// |
|
| 218 | 218 |
/// It buildes the map. It called by the observer notifier |
| 219 | 219 |
/// and it overrides the build() member function of the observer base. |
| 220 |
virtual void build() {
|
|
| 220 |
virtual void build() {
|
|
| 221 | 221 |
int size = Parent::notifier()->maxId() + 1; |
| 222 | 222 |
container.reserve(size); |
| 223 | 223 |
container.resize(size); |
| 224 | 224 |
} |
| 225 | 225 |
|
| 226 | 226 |
/// \brief Clear the map. |
| 227 | 227 |
/// |
| 228 | 228 |
/// It erase all items from the map. It called by the observer notifier |
| 229 |
/// and it overrides the clear() member function of the observer base. |
|
| 230 |
virtual void clear() {
|
|
| 229 |
/// and it overrides the clear() member function of the observer base. |
|
| 230 |
virtual void clear() {
|
|
| 231 | 231 |
container.clear(); |
| 232 | 232 |
} |
| 233 |
|
|
| 233 |
|
|
| 234 | 234 |
private: |
| 235 |
|
|
| 235 |
|
|
| 236 | 236 |
Container container; |
| 237 | 237 |
|
| 238 | 238 |
}; |
| 239 | 239 |
|
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
///\file |
| 20 | 20 |
///\brief Color constants |
| 21 | 21 |
|
| 22 | 22 |
#include<lemon/color.h> |
| 23 | 23 |
|
| 24 | 24 |
namespace lemon {
|
| 25 | 25 |
|
| 26 | 26 |
const Color WHITE(1,1,1); |
| 27 |
|
|
| 27 |
|
|
| 28 | 28 |
const Color BLACK(0,0,0); |
| 29 | 29 |
const Color RED(1,0,0); |
| 30 | 30 |
const Color GREEN(0,1,0); |
| 31 | 31 |
const Color BLUE(0,0,1); |
| 32 | 32 |
const Color YELLOW(1,1,0); |
| 33 | 33 |
const Color MAGENTA(1,0,1); |
| 34 | 34 |
const Color CYAN(0,1,1); |
| 35 | 35 |
|
| 36 | 36 |
const Color GREY(0,0,0); |
| 37 | 37 |
const Color DARK_RED(.5,0,0); |
| 38 | 38 |
const Color DARK_GREEN(0,.5,0); |
| 39 | 39 |
const Color DARK_BLUE(0,0,.5); |
| 40 | 40 |
const Color DARK_YELLOW(.5,.5,0); |
| 41 | 41 |
const Color DARK_MAGENTA(.5,0,.5); |
| 42 | 42 |
const Color DARK_CYAN(0,.5,.5); |
| 43 |
|
|
| 43 |
|
|
| 44 | 44 |
} //namespace lemon |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_COLOR_H |
| ... | ... |
@@ -49,33 +49,33 @@ |
| 49 | 49 |
double & red() {return _r;}
|
| 50 | 50 |
///Return the red component |
| 51 | 51 |
const double & red() const {return _r;}
|
| 52 | 52 |
///Set the green component |
| 53 | 53 |
double & green() {return _g;}
|
| 54 | 54 |
///Return the green component |
| 55 | 55 |
const double & green() const {return _g;}
|
| 56 | 56 |
///Set the blue component |
| 57 | 57 |
double & blue() {return _b;}
|
| 58 | 58 |
///Return the blue component |
| 59 | 59 |
const double & blue() const {return _b;}
|
| 60 | 60 |
///Set the color components |
| 61 | 61 |
void set(double r,double g,double b) { _r=r;_g=g;_b=b; };
|
| 62 | 62 |
}; |
| 63 | 63 |
|
| 64 | 64 |
/// White color constant |
| 65 |
extern const Color WHITE; |
|
| 65 |
extern const Color WHITE; |
|
| 66 | 66 |
/// Black color constant |
| 67 | 67 |
extern const Color BLACK; |
| 68 | 68 |
/// Red color constant |
| 69 | 69 |
extern const Color RED; |
| 70 | 70 |
/// Green color constant |
| 71 | 71 |
extern const Color GREEN; |
| 72 | 72 |
/// Blue color constant |
| 73 | 73 |
extern const Color BLUE; |
| 74 | 74 |
/// Yellow color constant |
| 75 | 75 |
extern const Color YELLOW; |
| 76 | 76 |
/// Magenta color constant |
| 77 | 77 |
extern const Color MAGENTA; |
| 78 | 78 |
/// Cyan color constant |
| 79 | 79 |
extern const Color CYAN; |
| 80 | 80 |
/// Grey color constant |
| 81 | 81 |
extern const Color GREY; |
| ... | ... |
@@ -117,88 +117,88 @@ |
| 117 | 117 |
///white). If \c num is less then 26/27 then the default color |
| 118 | 118 |
///list is cut. Otherwise the color list is filled repeatedly with |
| 119 | 119 |
///the default color list. (The colors can be changed later on.) |
| 120 | 120 |
Palette(bool have_white=false,int num=-1) |
| 121 | 121 |
{
|
| 122 | 122 |
if (num==0) return; |
| 123 | 123 |
do {
|
| 124 | 124 |
if(have_white) colors.push_back(Color(1,1,1)); |
| 125 | 125 |
|
| 126 | 126 |
colors.push_back(Color(0,0,0)); |
| 127 | 127 |
colors.push_back(Color(1,0,0)); |
| 128 | 128 |
colors.push_back(Color(0,1,0)); |
| 129 | 129 |
colors.push_back(Color(0,0,1)); |
| 130 | 130 |
colors.push_back(Color(1,1,0)); |
| 131 | 131 |
colors.push_back(Color(1,0,1)); |
| 132 | 132 |
colors.push_back(Color(0,1,1)); |
| 133 |
|
|
| 133 |
|
|
| 134 | 134 |
colors.push_back(Color(.5,0,0)); |
| 135 | 135 |
colors.push_back(Color(0,.5,0)); |
| 136 | 136 |
colors.push_back(Color(0,0,.5)); |
| 137 | 137 |
colors.push_back(Color(.5,.5,0)); |
| 138 | 138 |
colors.push_back(Color(.5,0,.5)); |
| 139 | 139 |
colors.push_back(Color(0,.5,.5)); |
| 140 |
|
|
| 140 |
|
|
| 141 | 141 |
colors.push_back(Color(.5,.5,.5)); |
| 142 | 142 |
colors.push_back(Color(1,.5,.5)); |
| 143 | 143 |
colors.push_back(Color(.5,1,.5)); |
| 144 | 144 |
colors.push_back(Color(.5,.5,1)); |
| 145 | 145 |
colors.push_back(Color(1,1,.5)); |
| 146 | 146 |
colors.push_back(Color(1,.5,1)); |
| 147 | 147 |
colors.push_back(Color(.5,1,1)); |
| 148 |
|
|
| 148 |
|
|
| 149 | 149 |
colors.push_back(Color(1,.5,0)); |
| 150 | 150 |
colors.push_back(Color(.5,1,0)); |
| 151 | 151 |
colors.push_back(Color(1,0,.5)); |
| 152 | 152 |
colors.push_back(Color(0,1,.5)); |
| 153 | 153 |
colors.push_back(Color(0,.5,1)); |
| 154 | 154 |
colors.push_back(Color(.5,0,1)); |
| 155 | 155 |
} while(int(colors.size())<num); |
| 156 | 156 |
if(num>=0) colors.resize(num); |
| 157 | 157 |
} |
| 158 | 158 |
///\e |
| 159 | 159 |
Color &operator[](int i) |
| 160 | 160 |
{
|
| 161 | 161 |
return colors[i%colors.size()]; |
| 162 | 162 |
} |
| 163 | 163 |
///\e |
| 164 | 164 |
const Color &operator[](int i) const |
| 165 | 165 |
{
|
| 166 | 166 |
return colors[i%colors.size()]; |
| 167 | 167 |
} |
| 168 | 168 |
///\e |
| 169 | 169 |
void set(int i,const Color &c) |
| 170 | 170 |
{
|
| 171 | 171 |
colors[i%colors.size()]=c; |
| 172 | 172 |
} |
| 173 | 173 |
///Adds a new color to the end of the color list. |
| 174 |
void add(const Color &c) |
|
| 174 |
void add(const Color &c) |
|
| 175 | 175 |
{
|
| 176 | 176 |
colors.push_back(c); |
| 177 | 177 |
} |
| 178 | 178 |
|
| 179 | 179 |
///Sets the number of the existing colors. |
| 180 | 180 |
void resize(int s) { colors.resize(s);}
|
| 181 | 181 |
///Returns the number of the existing colors. |
| 182 | 182 |
int size() const { return int(colors.size());}
|
| 183 | 183 |
}; |
| 184 | 184 |
|
| 185 | 185 |
///Returns a visibly distinct \ref Color |
| 186 | 186 |
|
| 187 | 187 |
///Returns a \ref Color which is as different from the given parameter |
| 188 | 188 |
///as it is possible. |
| 189 |
inline Color distantColor(const Color &c) |
|
| 189 |
inline Color distantColor(const Color &c) |
|
| 190 | 190 |
{
|
| 191 | 191 |
return Color(c.red()<.5?1:0,c.green()<.5?1:0,c.blue()<.5?1:0); |
| 192 | 192 |
} |
| 193 | 193 |
///Returns black for light colors and white for the dark ones. |
| 194 | 194 |
|
| 195 | 195 |
///Returns black for light colors and white for the dark ones. |
| 196 | 196 |
inline Color distantBW(const Color &c){
|
| 197 | 197 |
return (.2125*c.red()+.7154*c.green()+.0721*c.blue())<.5 ? WHITE : BLACK; |
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 | 200 |
/// @} |
| 201 | 201 |
|
| 202 | 202 |
} //END OF NAMESPACE LEMON |
| 203 | 203 |
|
| 204 | 204 |
#endif // LEMON_COLOR_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
// This file contains a modified version of the concept checking |
| ... | ... |
@@ -23,33 +23,33 @@ |
| 23 | 23 |
// (C) Copyright Jeremy Siek 2000. |
| 24 | 24 |
// Distributed under the Boost Software License, Version 1.0. (See |
| 25 | 25 |
// accompanying file LICENSE_1_0.txt or copy at |
| 26 | 26 |
// http://www.boost.org/LICENSE_1_0.txt) |
| 27 | 27 |
// |
| 28 | 28 |
// Revision History: |
| 29 | 29 |
// 05 May 2001: Workarounds for HP aCC from Thomas Matelich. (Jeremy Siek) |
| 30 | 30 |
// 02 April 2001: Removed limits header altogether. (Jeremy Siek) |
| 31 | 31 |
// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock) |
| 32 | 32 |
// |
| 33 | 33 |
|
| 34 | 34 |
// See http://www.boost.org/libs/concept_check for documentation. |
| 35 | 35 |
|
| 36 | 36 |
///\file |
| 37 | 37 |
///\brief Basic utilities for concept checking. |
| 38 | 38 |
/// |
| 39 |
///\todo Are we still using BOOST concept checking utility? |
|
| 39 |
///\todo Are we still using BOOST concept checking utility? |
|
| 40 | 40 |
///Is the BOOST copyright notice necessary? |
| 41 | 41 |
|
| 42 | 42 |
#ifndef LEMON_CONCEPT_CHECK_H |
| 43 | 43 |
#define LEMON_CONCEPT_CHECK_H |
| 44 | 44 |
|
| 45 | 45 |
namespace lemon {
|
| 46 | 46 |
|
| 47 | 47 |
/* |
| 48 | 48 |
"inline" is used for ignore_unused_variable_warning() |
| 49 | 49 |
and function_requires() to make sure there is no |
| 50 | 50 |
overtarget with g++. |
| 51 | 51 |
*/ |
| 52 | 52 |
|
| 53 | 53 |
template <class T> inline void ignore_unused_variable_warning(const T&) { }
|
| 54 | 54 |
|
| 55 | 55 |
///\e |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_CONCEPT_DIGRAPH_H |
| ... | ... |
@@ -33,39 +33,39 @@ |
| 33 | 33 |
namespace concepts {
|
| 34 | 34 |
|
| 35 | 35 |
/// \ingroup graph_concepts |
| 36 | 36 |
/// |
| 37 | 37 |
/// \brief Class describing the concept of directed graphs. |
| 38 | 38 |
/// |
| 39 | 39 |
/// This class describes the \ref concept "concept" of the |
| 40 | 40 |
/// immutable directed digraphs. |
| 41 | 41 |
/// |
| 42 | 42 |
/// Note that actual digraph implementation like @ref ListDigraph or |
| 43 | 43 |
/// @ref SmartDigraph may have several additional functionality. |
| 44 | 44 |
/// |
| 45 | 45 |
/// \sa concept |
| 46 | 46 |
class Digraph {
|
| 47 | 47 |
private: |
| 48 | 48 |
///Digraphs are \e not copy constructible. Use DigraphCopy() instead. |
| 49 |
|
|
| 49 |
|
|
| 50 | 50 |
///Digraphs are \e not copy constructible. Use DigraphCopy() instead. |
| 51 | 51 |
/// |
| 52 | 52 |
Digraph(const Digraph &) {};
|
| 53 | 53 |
///\brief Assignment of \ref Digraph "Digraph"s to another ones are |
| 54 | 54 |
///\e not allowed. Use DigraphCopy() instead. |
| 55 |
|
|
| 55 |
|
|
| 56 | 56 |
///Assignment of \ref Digraph "Digraph"s to another ones are |
| 57 | 57 |
///\e not allowed. Use DigraphCopy() instead. |
| 58 | 58 |
|
| 59 | 59 |
void operator=(const Digraph &) {}
|
| 60 | 60 |
public: |
| 61 | 61 |
///\e |
| 62 | 62 |
|
| 63 | 63 |
/// Defalult constructor. |
| 64 | 64 |
|
| 65 | 65 |
/// Defalult constructor. |
| 66 | 66 |
/// |
| 67 | 67 |
Digraph() { }
|
| 68 | 68 |
/// Class for identifying a node of the digraph |
| 69 | 69 |
|
| 70 | 70 |
/// This class identifies a node of the digraph. It also serves |
| 71 | 71 |
/// as a base class of the node iterators, |
| ... | ... |
@@ -82,95 +82,95 @@ |
| 82 | 82 |
/// Copy constructor. |
| 83 | 83 |
/// |
| 84 | 84 |
Node(const Node&) { }
|
| 85 | 85 |
|
| 86 | 86 |
/// Invalid constructor \& conversion. |
| 87 | 87 |
|
| 88 | 88 |
/// This constructor initializes the iterator to be invalid. |
| 89 | 89 |
/// \sa Invalid for more details. |
| 90 | 90 |
Node(Invalid) { }
|
| 91 | 91 |
/// Equality operator |
| 92 | 92 |
|
| 93 | 93 |
/// Two iterators are equal if and only if they point to the |
| 94 | 94 |
/// same object or both are invalid. |
| 95 | 95 |
bool operator==(Node) const { return true; }
|
| 96 | 96 |
|
| 97 | 97 |
/// Inequality operator |
| 98 |
|
|
| 98 |
|
|
| 99 | 99 |
/// \sa operator==(Node n) |
| 100 | 100 |
/// |
| 101 | 101 |
bool operator!=(Node) const { return true; }
|
| 102 | 102 |
|
| 103 |
/// Artificial ordering operator. |
|
| 104 |
|
|
| 105 |
/// To allow the use of digraph descriptors as key type in std::map or |
|
| 106 |
/// similar associative container we require this. |
|
| 107 |
/// |
|
| 108 |
/// \note This operator only have to define some strict ordering of |
|
| 109 |
/// the items; this order has nothing to do with the iteration |
|
| 110 |
/// ordering of the items. |
|
| 111 |
|
|
| 103 |
/// Artificial ordering operator. |
|
| 104 |
|
|
| 105 |
/// To allow the use of digraph descriptors as key type in std::map or |
|
| 106 |
/// similar associative container we require this. |
|
| 107 |
/// |
|
| 108 |
/// \note This operator only have to define some strict ordering of |
|
| 109 |
/// the items; this order has nothing to do with the iteration |
|
| 110 |
/// ordering of the items. |
|
| 111 |
bool operator<(Node) const { return false; }
|
|
| 112 | 112 |
|
| 113 | 113 |
}; |
| 114 |
|
|
| 114 |
|
|
| 115 | 115 |
/// This iterator goes through each node. |
| 116 | 116 |
|
| 117 | 117 |
/// This iterator goes through each node. |
| 118 | 118 |
/// Its usage is quite simple, for example you can count the number |
| 119 | 119 |
/// of nodes in digraph \c g of type \c Digraph like this: |
| 120 | 120 |
///\code |
| 121 | 121 |
/// int count=0; |
| 122 | 122 |
/// for (Digraph::NodeIt n(g); n!=INVALID; ++n) ++count; |
| 123 | 123 |
///\endcode |
| 124 | 124 |
class NodeIt : public Node {
|
| 125 | 125 |
public: |
| 126 | 126 |
/// Default constructor |
| 127 | 127 |
|
| 128 | 128 |
/// @warning The default constructor sets the iterator |
| 129 | 129 |
/// to an undefined value. |
| 130 | 130 |
NodeIt() { }
|
| 131 | 131 |
/// Copy constructor. |
| 132 |
|
|
| 132 |
|
|
| 133 | 133 |
/// Copy constructor. |
| 134 | 134 |
/// |
| 135 | 135 |
NodeIt(const NodeIt& n) : Node(n) { }
|
| 136 | 136 |
/// Invalid constructor \& conversion. |
| 137 | 137 |
|
| 138 | 138 |
/// Initialize the iterator to be invalid. |
| 139 | 139 |
/// \sa Invalid for more details. |
| 140 | 140 |
NodeIt(Invalid) { }
|
| 141 | 141 |
/// Sets the iterator to the first node. |
| 142 | 142 |
|
| 143 | 143 |
/// Sets the iterator to the first node of \c g. |
| 144 | 144 |
/// |
| 145 | 145 |
NodeIt(const Digraph&) { }
|
| 146 | 146 |
/// Node -> NodeIt conversion. |
| 147 | 147 |
|
| 148 |
/// Sets the iterator to the node of \c the digraph pointed by |
|
| 149 |
/// the trivial iterator. |
|
| 150 |
/// |
|
| 148 |
/// Sets the iterator to the node of \c the digraph pointed by |
|
| 149 |
/// the trivial iterator. |
|
| 150 |
/// This feature necessitates that each time we |
|
| 151 | 151 |
/// iterate the arc-set, the iteration order is the same. |
| 152 | 152 |
NodeIt(const Digraph&, const Node&) { }
|
| 153 | 153 |
/// Next node. |
| 154 | 154 |
|
| 155 | 155 |
/// Assign the iterator to the next node. |
| 156 | 156 |
/// |
| 157 | 157 |
NodeIt& operator++() { return *this; }
|
| 158 | 158 |
}; |
| 159 |
|
|
| 160 |
|
|
| 159 |
|
|
| 160 |
|
|
| 161 | 161 |
/// Class for identifying an arc of the digraph |
| 162 | 162 |
|
| 163 | 163 |
/// This class identifies an arc of the digraph. It also serves |
| 164 | 164 |
/// as a base class of the arc iterators, |
| 165 | 165 |
/// thus they will convert to this type. |
| 166 | 166 |
class Arc {
|
| 167 | 167 |
public: |
| 168 | 168 |
/// Default constructor |
| 169 | 169 |
|
| 170 | 170 |
/// @warning The default constructor sets the iterator |
| 171 | 171 |
/// to an undefined value. |
| 172 | 172 |
Arc() { }
|
| 173 | 173 |
/// Copy constructor. |
| 174 | 174 |
|
| 175 | 175 |
/// Copy constructor. |
| 176 | 176 |
/// |
| ... | ... |
@@ -178,86 +178,86 @@ |
| 178 | 178 |
/// Initialize the iterator to be invalid. |
| 179 | 179 |
|
| 180 | 180 |
/// Initialize the iterator to be invalid. |
| 181 | 181 |
/// |
| 182 | 182 |
Arc(Invalid) { }
|
| 183 | 183 |
/// Equality operator |
| 184 | 184 |
|
| 185 | 185 |
/// Two iterators are equal if and only if they point to the |
| 186 | 186 |
/// same object or both are invalid. |
| 187 | 187 |
bool operator==(Arc) const { return true; }
|
| 188 | 188 |
/// Inequality operator |
| 189 | 189 |
|
| 190 | 190 |
/// \sa operator==(Arc n) |
| 191 | 191 |
/// |
| 192 | 192 |
bool operator!=(Arc) const { return true; }
|
| 193 | 193 |
|
| 194 |
/// Artificial ordering operator. |
|
| 195 |
|
|
| 196 |
/// To allow the use of digraph descriptors as key type in std::map or |
|
| 197 |
/// similar associative container we require this. |
|
| 198 |
/// |
|
| 199 |
/// \note This operator only have to define some strict ordering of |
|
| 200 |
/// the items; this order has nothing to do with the iteration |
|
| 201 |
/// ordering of the items. |
|
| 202 |
|
|
| 194 |
/// Artificial ordering operator. |
|
| 195 |
|
|
| 196 |
/// To allow the use of digraph descriptors as key type in std::map or |
|
| 197 |
/// similar associative container we require this. |
|
| 198 |
/// |
|
| 199 |
/// \note This operator only have to define some strict ordering of |
|
| 200 |
/// the items; this order has nothing to do with the iteration |
|
| 201 |
/// ordering of the items. |
|
| 202 |
bool operator<(Arc) const { return false; }
|
|
| 203 | 203 |
}; |
| 204 |
|
|
| 204 |
|
|
| 205 | 205 |
/// This iterator goes trough the outgoing arcs of a node. |
| 206 | 206 |
|
| 207 | 207 |
/// This iterator goes trough the \e outgoing arcs of a certain node |
| 208 | 208 |
/// of a digraph. |
| 209 | 209 |
/// Its usage is quite simple, for example you can count the number |
| 210 | 210 |
/// of outgoing arcs of a node \c n |
| 211 | 211 |
/// in digraph \c g of type \c Digraph as follows. |
| 212 | 212 |
///\code |
| 213 | 213 |
/// int count=0; |
| 214 | 214 |
/// for (Digraph::OutArcIt e(g, n); e!=INVALID; ++e) ++count; |
| 215 | 215 |
///\endcode |
| 216 |
|
|
| 216 |
|
|
| 217 | 217 |
class OutArcIt : public Arc {
|
| 218 | 218 |
public: |
| 219 | 219 |
/// Default constructor |
| 220 | 220 |
|
| 221 | 221 |
/// @warning The default constructor sets the iterator |
| 222 | 222 |
/// to an undefined value. |
| 223 | 223 |
OutArcIt() { }
|
| 224 | 224 |
/// Copy constructor. |
| 225 | 225 |
|
| 226 | 226 |
/// Copy constructor. |
| 227 | 227 |
/// |
| 228 | 228 |
OutArcIt(const OutArcIt& e) : Arc(e) { }
|
| 229 | 229 |
/// Initialize the iterator to be invalid. |
| 230 | 230 |
|
| 231 | 231 |
/// Initialize the iterator to be invalid. |
| 232 | 232 |
/// |
| 233 | 233 |
OutArcIt(Invalid) { }
|
| 234 | 234 |
/// This constructor sets the iterator to the first outgoing arc. |
| 235 |
|
|
| 235 |
|
|
| 236 | 236 |
/// This constructor sets the iterator to the first outgoing arc of |
| 237 | 237 |
/// the node. |
| 238 | 238 |
OutArcIt(const Digraph&, const Node&) { }
|
| 239 | 239 |
/// Arc -> OutArcIt conversion |
| 240 | 240 |
|
| 241 | 241 |
/// Sets the iterator to the value of the trivial iterator. |
| 242 |
|
|
| 242 |
/// This feature necessitates that each time we |
|
| 243 | 243 |
/// iterate the arc-set, the iteration order is the same. |
| 244 | 244 |
OutArcIt(const Digraph&, const Arc&) { }
|
| 245 | 245 |
///Next outgoing arc |
| 246 |
|
|
| 247 |
/// Assign the iterator to the next |
|
| 246 |
|
|
| 247 |
/// Assign the iterator to the next |
|
| 248 | 248 |
/// outgoing arc of the corresponding node. |
| 249 | 249 |
OutArcIt& operator++() { return *this; }
|
| 250 | 250 |
}; |
| 251 | 251 |
|
| 252 | 252 |
/// This iterator goes trough the incoming arcs of a node. |
| 253 | 253 |
|
| 254 | 254 |
/// This iterator goes trough the \e incoming arcs of a certain node |
| 255 | 255 |
/// of a digraph. |
| 256 | 256 |
/// Its usage is quite simple, for example you can count the number |
| 257 | 257 |
/// of outgoing arcs of a node \c n |
| 258 | 258 |
/// in digraph \c g of type \c Digraph as follows. |
| 259 | 259 |
///\code |
| 260 | 260 |
/// int count=0; |
| 261 | 261 |
/// for(Digraph::InArcIt e(g, n); e!=INVALID; ++e) ++count; |
| 262 | 262 |
///\endcode |
| 263 | 263 |
|
| ... | ... |
@@ -266,40 +266,40 @@ |
| 266 | 266 |
/// Default constructor |
| 267 | 267 |
|
| 268 | 268 |
/// @warning The default constructor sets the iterator |
| 269 | 269 |
/// to an undefined value. |
| 270 | 270 |
InArcIt() { }
|
| 271 | 271 |
/// Copy constructor. |
| 272 | 272 |
|
| 273 | 273 |
/// Copy constructor. |
| 274 | 274 |
/// |
| 275 | 275 |
InArcIt(const InArcIt& e) : Arc(e) { }
|
| 276 | 276 |
/// Initialize the iterator to be invalid. |
| 277 | 277 |
|
| 278 | 278 |
/// Initialize the iterator to be invalid. |
| 279 | 279 |
/// |
| 280 | 280 |
InArcIt(Invalid) { }
|
| 281 | 281 |
/// This constructor sets the iterator to first incoming arc. |
| 282 |
|
|
| 282 |
|
|
| 283 | 283 |
/// This constructor set the iterator to the first incoming arc of |
| 284 | 284 |
/// the node. |
| 285 | 285 |
InArcIt(const Digraph&, const Node&) { }
|
| 286 | 286 |
/// Arc -> InArcIt conversion |
| 287 | 287 |
|
| 288 | 288 |
/// Sets the iterator to the value of the trivial iterator \c e. |
| 289 |
/// This feature necessitates that each time we |
|
| 289 |
/// This feature necessitates that each time we |
|
| 290 | 290 |
/// iterate the arc-set, the iteration order is the same. |
| 291 | 291 |
InArcIt(const Digraph&, const Arc&) { }
|
| 292 | 292 |
/// Next incoming arc |
| 293 | 293 |
|
| 294 | 294 |
/// Assign the iterator to the next inarc of the corresponding node. |
| 295 | 295 |
/// |
| 296 | 296 |
InArcIt& operator++() { return *this; }
|
| 297 | 297 |
}; |
| 298 | 298 |
/// This iterator goes through each arc. |
| 299 | 299 |
|
| 300 | 300 |
/// This iterator goes through each arc of a digraph. |
| 301 | 301 |
/// Its usage is quite simple, for example you can count the number |
| 302 | 302 |
/// of arcs in a digraph \c g of type \c Digraph as follows: |
| 303 | 303 |
///\code |
| 304 | 304 |
/// int count=0; |
| 305 | 305 |
/// for(Digraph::ArcIt e(g); e!=INVALID; ++e) ++count; |
| ... | ... |
@@ -309,178 +309,178 @@ |
| 309 | 309 |
/// Default constructor |
| 310 | 310 |
|
| 311 | 311 |
/// @warning The default constructor sets the iterator |
| 312 | 312 |
/// to an undefined value. |
| 313 | 313 |
ArcIt() { }
|
| 314 | 314 |
/// Copy constructor. |
| 315 | 315 |
|
| 316 | 316 |
/// Copy constructor. |
| 317 | 317 |
/// |
| 318 | 318 |
ArcIt(const ArcIt& e) : Arc(e) { }
|
| 319 | 319 |
/// Initialize the iterator to be invalid. |
| 320 | 320 |
|
| 321 | 321 |
/// Initialize the iterator to be invalid. |
| 322 | 322 |
/// |
| 323 | 323 |
ArcIt(Invalid) { }
|
| 324 | 324 |
/// This constructor sets the iterator to the first arc. |
| 325 |
|
|
| 325 |
|
|
| 326 | 326 |
/// This constructor sets the iterator to the first arc of \c g. |
| 327 | 327 |
///@param g the digraph |
| 328 | 328 |
ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); }
|
| 329 | 329 |
/// Arc -> ArcIt conversion |
| 330 | 330 |
|
| 331 | 331 |
/// Sets the iterator to the value of the trivial iterator \c e. |
| 332 |
/// This feature necessitates that each time we |
|
| 332 |
/// This feature necessitates that each time we |
|
| 333 | 333 |
/// iterate the arc-set, the iteration order is the same. |
| 334 |
ArcIt(const Digraph&, const Arc&) { }
|
|
| 334 |
ArcIt(const Digraph&, const Arc&) { }
|
|
| 335 | 335 |
///Next arc |
| 336 |
|
|
| 336 |
|
|
| 337 | 337 |
/// Assign the iterator to the next arc. |
| 338 | 338 |
ArcIt& operator++() { return *this; }
|
| 339 | 339 |
}; |
| 340 | 340 |
///Gives back the target node of an arc. |
| 341 | 341 |
|
| 342 | 342 |
///Gives back the target node of an arc. |
| 343 | 343 |
/// |
| 344 | 344 |
Node target(Arc) const { return INVALID; }
|
| 345 | 345 |
///Gives back the source node of an arc. |
| 346 | 346 |
|
| 347 | 347 |
///Gives back the source node of an arc. |
| 348 | 348 |
/// |
| 349 | 349 |
Node source(Arc) const { return INVALID; }
|
| 350 | 350 |
|
| 351 | 351 |
/// \brief Returns the ID of the node. |
| 352 |
int id(Node) const { return -1; }
|
|
| 352 |
int id(Node) const { return -1; }
|
|
| 353 | 353 |
|
| 354 | 354 |
/// \brief Returns the ID of the arc. |
| 355 |
int id(Arc) const { return -1; }
|
|
| 355 |
int id(Arc) const { return -1; }
|
|
| 356 | 356 |
|
| 357 | 357 |
/// \brief Returns the node with the given ID. |
| 358 | 358 |
/// |
| 359 | 359 |
/// \pre The argument should be a valid node ID in the graph. |
| 360 |
Node nodeFromId(int) const { return INVALID; }
|
|
| 360 |
Node nodeFromId(int) const { return INVALID; }
|
|
| 361 | 361 |
|
| 362 | 362 |
/// \brief Returns the arc with the given ID. |
| 363 | 363 |
/// |
| 364 | 364 |
/// \pre The argument should be a valid arc ID in the graph. |
| 365 |
Arc arcFromId(int) const { return INVALID; }
|
|
| 365 |
Arc arcFromId(int) const { return INVALID; }
|
|
| 366 | 366 |
|
| 367 | 367 |
/// \brief Returns an upper bound on the node IDs. |
| 368 |
int maxNodeId() const { return -1; }
|
|
| 368 |
int maxNodeId() const { return -1; }
|
|
| 369 | 369 |
|
| 370 | 370 |
/// \brief Returns an upper bound on the arc IDs. |
| 371 |
int maxArcId() const { return -1; }
|
|
| 371 |
int maxArcId() const { return -1; }
|
|
| 372 | 372 |
|
| 373 | 373 |
void first(Node&) const {}
|
| 374 | 374 |
void next(Node&) const {}
|
| 375 | 375 |
|
| 376 | 376 |
void first(Arc&) const {}
|
| 377 | 377 |
void next(Arc&) const {}
|
| 378 | 378 |
|
| 379 | 379 |
|
| 380 | 380 |
void firstIn(Arc&, const Node&) const {}
|
| 381 | 381 |
void nextIn(Arc&) const {}
|
| 382 | 382 |
|
| 383 | 383 |
void firstOut(Arc&, const Node&) const {}
|
| 384 | 384 |
void nextOut(Arc&) const {}
|
| 385 | 385 |
|
| 386 | 386 |
// The second parameter is dummy. |
| 387 | 387 |
Node fromId(int, Node) const { return INVALID; }
|
| 388 | 388 |
// The second parameter is dummy. |
| 389 | 389 |
Arc fromId(int, Arc) const { return INVALID; }
|
| 390 | 390 |
|
| 391 | 391 |
// Dummy parameter. |
| 392 |
int maxId(Node) const { return -1; }
|
|
| 392 |
int maxId(Node) const { return -1; }
|
|
| 393 | 393 |
// Dummy parameter. |
| 394 |
int maxId(Arc) const { return -1; }
|
|
| 394 |
int maxId(Arc) const { return -1; }
|
|
| 395 | 395 |
|
| 396 | 396 |
/// \brief The base node of the iterator. |
| 397 | 397 |
/// |
| 398 | 398 |
/// Gives back the base node of the iterator. |
| 399 | 399 |
/// It is always the target of the pointed arc. |
| 400 | 400 |
Node baseNode(const InArcIt&) const { return INVALID; }
|
| 401 | 401 |
|
| 402 | 402 |
/// \brief The running node of the iterator. |
| 403 | 403 |
/// |
| 404 | 404 |
/// Gives back the running node of the iterator. |
| 405 | 405 |
/// It is always the source of the pointed arc. |
| 406 | 406 |
Node runningNode(const InArcIt&) const { return INVALID; }
|
| 407 | 407 |
|
| 408 | 408 |
/// \brief The base node of the iterator. |
| 409 | 409 |
/// |
| 410 | 410 |
/// Gives back the base node of the iterator. |
| 411 | 411 |
/// It is always the source of the pointed arc. |
| 412 | 412 |
Node baseNode(const OutArcIt&) const { return INVALID; }
|
| 413 | 413 |
|
| 414 | 414 |
/// \brief The running node of the iterator. |
| 415 | 415 |
/// |
| 416 | 416 |
/// Gives back the running node of the iterator. |
| 417 | 417 |
/// It is always the target of the pointed arc. |
| 418 | 418 |
Node runningNode(const OutArcIt&) const { return INVALID; }
|
| 419 | 419 |
|
| 420 | 420 |
/// \brief The opposite node on the given arc. |
| 421 | 421 |
/// |
| 422 | 422 |
/// Gives back the opposite node on the given arc. |
| 423 | 423 |
Node oppositeNode(const Node&, const Arc&) const { return INVALID; }
|
| 424 | 424 |
|
| 425 | 425 |
/// \brief Read write map of the nodes to type \c T. |
| 426 |
/// |
|
| 426 |
/// |
|
| 427 | 427 |
/// ReadWrite map of the nodes to type \c T. |
| 428 | 428 |
/// \sa Reference |
| 429 |
template<class T> |
|
| 429 |
template<class T> |
|
| 430 | 430 |
class NodeMap : public ReadWriteMap< Node, T > {
|
| 431 | 431 |
public: |
| 432 | 432 |
|
| 433 | 433 |
///\e |
| 434 | 434 |
NodeMap(const Digraph&) { }
|
| 435 | 435 |
///\e |
| 436 | 436 |
NodeMap(const Digraph&, T) { }
|
| 437 | 437 |
|
| 438 | 438 |
///Copy constructor |
| 439 | 439 |
NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { }
|
| 440 | 440 |
///Assignment operator |
| 441 | 441 |
template <typename CMap> |
| 442 |
NodeMap& operator=(const CMap&) {
|
|
| 442 |
NodeMap& operator=(const CMap&) {
|
|
| 443 | 443 |
checkConcept<ReadMap<Node, T>, CMap>(); |
| 444 |
return *this; |
|
| 444 |
return *this; |
|
| 445 | 445 |
} |
| 446 | 446 |
}; |
| 447 | 447 |
|
| 448 | 448 |
/// \brief Read write map of the arcs to type \c T. |
| 449 | 449 |
/// |
| 450 | 450 |
/// Reference map of the arcs to type \c T. |
| 451 | 451 |
/// \sa Reference |
| 452 |
template<class T> |
|
| 452 |
template<class T> |
|
| 453 | 453 |
class ArcMap : public ReadWriteMap<Arc,T> {
|
| 454 | 454 |
public: |
| 455 | 455 |
|
| 456 | 456 |
///\e |
| 457 | 457 |
ArcMap(const Digraph&) { }
|
| 458 | 458 |
///\e |
| 459 | 459 |
ArcMap(const Digraph&, T) { }
|
| 460 | 460 |
///Copy constructor |
| 461 | 461 |
ArcMap(const ArcMap& em) : ReadWriteMap<Arc,T>(em) { }
|
| 462 | 462 |
///Assignment operator |
| 463 | 463 |
template <typename CMap> |
| 464 |
ArcMap& operator=(const CMap&) {
|
|
| 464 |
ArcMap& operator=(const CMap&) {
|
|
| 465 | 465 |
checkConcept<ReadMap<Arc, T>, CMap>(); |
| 466 |
return *this; |
|
| 466 |
return *this; |
|
| 467 | 467 |
} |
| 468 | 468 |
}; |
| 469 | 469 |
|
| 470 | 470 |
template <typename _Digraph> |
| 471 | 471 |
struct Constraints {
|
| 472 | 472 |
void constraints() {
|
| 473 | 473 |
checkConcept<IterableDigraphComponent<>, _Digraph>(); |
| 474 |
|
|
| 474 |
checkConcept<IDableDigraphComponent<>, _Digraph>(); |
|
| 475 | 475 |
checkConcept<MappableDigraphComponent<>, _Digraph>(); |
| 476 | 476 |
} |
| 477 | 477 |
}; |
| 478 | 478 |
|
| 479 | 479 |
}; |
| 480 |
|
|
| 481 |
} //namespace concepts |
|
| 480 |
|
|
| 481 |
} //namespace concepts |
|
| 482 | 482 |
} //namespace lemon |
| 483 | 483 |
|
| 484 | 484 |
|
| 485 | 485 |
|
| 486 | 486 |
#endif // LEMON_CONCEPT_DIGRAPH_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 graph_concepts |
| ... | ... |
@@ -52,271 +52,271 @@ |
| 52 | 52 |
/// convertible to Edge or inherited from it so from a directed |
| 53 | 53 |
/// arc we can get the represented edge. |
| 54 | 54 |
/// |
| 55 | 55 |
/// In the sense of the LEMON each edge has a default |
| 56 | 56 |
/// direction (it should be in every computer implementation, |
| 57 | 57 |
/// because the order of edge's nodes defines an |
| 58 | 58 |
/// orientation). With the default orientation we can define that |
| 59 | 59 |
/// the directed arc is forward or backward directed. With the \c |
| 60 | 60 |
/// direction() and \c direct() function we can get the direction |
| 61 | 61 |
/// of the directed arc and we can direct an edge. |
| 62 | 62 |
/// |
| 63 | 63 |
/// The EdgeIt is an iterator for the edges. We can use |
| 64 | 64 |
/// the EdgeMap to map values for the edges. The InArcIt and |
| 65 | 65 |
/// OutArcIt iterates on the same edges but with opposite |
| 66 | 66 |
/// direction. The IncEdgeIt iterates also on the same edges |
| 67 | 67 |
/// as the OutArcIt and InArcIt but it is not convertible to Arc just |
| 68 |
/// to Edge. |
|
| 68 |
/// to Edge. |
|
| 69 | 69 |
class Graph {
|
| 70 | 70 |
public: |
| 71 | 71 |
/// \brief The undirected graph should be tagged by the |
| 72 | 72 |
/// UndirectedTag. |
| 73 | 73 |
/// |
| 74 | 74 |
/// The undirected graph should be tagged by the UndirectedTag. This |
| 75 |
/// tag helps the enable_if technics to make compile time |
|
| 76 |
/// specializations for undirected graphs. |
|
| 75 |
/// tag helps the enable_if technics to make compile time |
|
| 76 |
/// specializations for undirected graphs. |
|
| 77 | 77 |
typedef True UndirectedTag; |
| 78 | 78 |
|
| 79 |
/// \brief The base type of node iterators, |
|
| 79 |
/// \brief The base type of node iterators, |
|
| 80 | 80 |
/// or in other words, the trivial node iterator. |
| 81 | 81 |
/// |
| 82 | 82 |
/// This is the base type of each node iterator, |
| 83 | 83 |
/// thus each kind of node iterator converts to this. |
| 84 |
/// More precisely each kind of node iterator should be inherited |
|
| 84 |
/// More precisely each kind of node iterator should be inherited |
|
| 85 | 85 |
/// from the trivial node iterator. |
| 86 | 86 |
class Node {
|
| 87 | 87 |
public: |
| 88 | 88 |
/// Default constructor |
| 89 | 89 |
|
| 90 | 90 |
/// @warning The default constructor sets the iterator |
| 91 | 91 |
/// to an undefined value. |
| 92 | 92 |
Node() { }
|
| 93 | 93 |
/// Copy constructor. |
| 94 | 94 |
|
| 95 | 95 |
/// Copy constructor. |
| 96 | 96 |
/// |
| 97 | 97 |
Node(const Node&) { }
|
| 98 | 98 |
|
| 99 | 99 |
/// Invalid constructor \& conversion. |
| 100 | 100 |
|
| 101 | 101 |
/// This constructor initializes the iterator to be invalid. |
| 102 | 102 |
/// \sa Invalid for more details. |
| 103 | 103 |
Node(Invalid) { }
|
| 104 | 104 |
/// Equality operator |
| 105 | 105 |
|
| 106 | 106 |
/// Two iterators are equal if and only if they point to the |
| 107 | 107 |
/// same object or both are invalid. |
| 108 | 108 |
bool operator==(Node) const { return true; }
|
| 109 | 109 |
|
| 110 | 110 |
/// Inequality operator |
| 111 |
|
|
| 111 |
|
|
| 112 | 112 |
/// \sa operator==(Node n) |
| 113 | 113 |
/// |
| 114 | 114 |
bool operator!=(Node) const { return true; }
|
| 115 | 115 |
|
| 116 |
/// Artificial ordering operator. |
|
| 117 |
|
|
| 118 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 119 |
/// similar associative container we require this. |
|
| 120 |
/// |
|
| 121 |
/// \note This operator only have to define some strict ordering of |
|
| 122 |
/// the items; this order has nothing to do with the iteration |
|
| 123 |
/// ordering of the items. |
|
| 124 |
|
|
| 116 |
/// Artificial ordering operator. |
|
| 117 |
|
|
| 118 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 119 |
/// similar associative container we require this. |
|
| 120 |
/// |
|
| 121 |
/// \note This operator only have to define some strict ordering of |
|
| 122 |
/// the items; this order has nothing to do with the iteration |
|
| 123 |
/// ordering of the items. |
|
| 124 |
bool operator<(Node) const { return false; }
|
|
| 125 | 125 |
|
| 126 | 126 |
}; |
| 127 |
|
|
| 127 |
|
|
| 128 | 128 |
/// This iterator goes through each node. |
| 129 | 129 |
|
| 130 | 130 |
/// This iterator goes through each node. |
| 131 | 131 |
/// Its usage is quite simple, for example you can count the number |
| 132 | 132 |
/// of nodes in graph \c g of type \c Graph like this: |
| 133 | 133 |
///\code |
| 134 | 134 |
/// int count=0; |
| 135 | 135 |
/// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; |
| 136 | 136 |
///\endcode |
| 137 | 137 |
class NodeIt : public Node {
|
| 138 | 138 |
public: |
| 139 | 139 |
/// Default constructor |
| 140 | 140 |
|
| 141 | 141 |
/// @warning The default constructor sets the iterator |
| 142 | 142 |
/// to an undefined value. |
| 143 | 143 |
NodeIt() { }
|
| 144 | 144 |
/// Copy constructor. |
| 145 |
|
|
| 145 |
|
|
| 146 | 146 |
/// Copy constructor. |
| 147 | 147 |
/// |
| 148 | 148 |
NodeIt(const NodeIt& n) : Node(n) { }
|
| 149 | 149 |
/// Invalid constructor \& conversion. |
| 150 | 150 |
|
| 151 | 151 |
/// Initialize the iterator to be invalid. |
| 152 | 152 |
/// \sa Invalid for more details. |
| 153 | 153 |
NodeIt(Invalid) { }
|
| 154 | 154 |
/// Sets the iterator to the first node. |
| 155 | 155 |
|
| 156 | 156 |
/// Sets the iterator to the first node of \c g. |
| 157 | 157 |
/// |
| 158 | 158 |
NodeIt(const Graph&) { }
|
| 159 | 159 |
/// Node -> NodeIt conversion. |
| 160 | 160 |
|
| 161 |
/// Sets the iterator to the node of \c the graph pointed by |
|
| 162 |
/// the trivial iterator. |
|
| 163 |
/// |
|
| 161 |
/// Sets the iterator to the node of \c the graph pointed by |
|
| 162 |
/// the trivial iterator. |
|
| 163 |
/// This feature necessitates that each time we |
|
| 164 | 164 |
/// iterate the arc-set, the iteration order is the same. |
| 165 | 165 |
NodeIt(const Graph&, const Node&) { }
|
| 166 | 166 |
/// Next node. |
| 167 | 167 |
|
| 168 | 168 |
/// Assign the iterator to the next node. |
| 169 | 169 |
/// |
| 170 | 170 |
NodeIt& operator++() { return *this; }
|
| 171 | 171 |
}; |
| 172 |
|
|
| 173 |
|
|
| 172 |
|
|
| 173 |
|
|
| 174 | 174 |
/// The base type of the edge iterators. |
| 175 | 175 |
|
| 176 | 176 |
/// The base type of the edge iterators. |
| 177 | 177 |
/// |
| 178 | 178 |
class Edge {
|
| 179 | 179 |
public: |
| 180 | 180 |
/// Default constructor |
| 181 | 181 |
|
| 182 | 182 |
/// @warning The default constructor sets the iterator |
| 183 | 183 |
/// to an undefined value. |
| 184 | 184 |
Edge() { }
|
| 185 | 185 |
/// Copy constructor. |
| 186 | 186 |
|
| 187 | 187 |
/// Copy constructor. |
| 188 | 188 |
/// |
| 189 | 189 |
Edge(const Edge&) { }
|
| 190 | 190 |
/// Initialize the iterator to be invalid. |
| 191 | 191 |
|
| 192 | 192 |
/// Initialize the iterator to be invalid. |
| 193 | 193 |
/// |
| 194 | 194 |
Edge(Invalid) { }
|
| 195 | 195 |
/// Equality operator |
| 196 | 196 |
|
| 197 | 197 |
/// Two iterators are equal if and only if they point to the |
| 198 | 198 |
/// same object or both are invalid. |
| 199 | 199 |
bool operator==(Edge) const { return true; }
|
| 200 | 200 |
/// Inequality operator |
| 201 | 201 |
|
| 202 | 202 |
/// \sa operator==(Edge n) |
| 203 | 203 |
/// |
| 204 | 204 |
bool operator!=(Edge) const { return true; }
|
| 205 | 205 |
|
| 206 |
/// Artificial ordering operator. |
|
| 207 |
|
|
| 208 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 209 |
/// similar associative container we require this. |
|
| 210 |
/// |
|
| 211 |
/// \note This operator only have to define some strict ordering of |
|
| 212 |
/// the items; this order has nothing to do with the iteration |
|
| 213 |
/// ordering of the items. |
|
| 214 |
|
|
| 206 |
/// Artificial ordering operator. |
|
| 207 |
|
|
| 208 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 209 |
/// similar associative container we require this. |
|
| 210 |
/// |
|
| 211 |
/// \note This operator only have to define some strict ordering of |
|
| 212 |
/// the items; this order has nothing to do with the iteration |
|
| 213 |
/// ordering of the items. |
|
| 214 |
bool operator<(Edge) const { return false; }
|
|
| 215 | 215 |
}; |
| 216 | 216 |
|
| 217 | 217 |
/// This iterator goes through each edge. |
| 218 | 218 |
|
| 219 | 219 |
/// This iterator goes through each edge of a graph. |
| 220 | 220 |
/// Its usage is quite simple, for example you can count the number |
| 221 | 221 |
/// of edges in a graph \c g of type \c Graph as follows: |
| 222 | 222 |
///\code |
| 223 | 223 |
/// int count=0; |
| 224 | 224 |
/// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; |
| 225 | 225 |
///\endcode |
| 226 | 226 |
class EdgeIt : public Edge {
|
| 227 | 227 |
public: |
| 228 | 228 |
/// Default constructor |
| 229 | 229 |
|
| 230 | 230 |
/// @warning The default constructor sets the iterator |
| 231 | 231 |
/// to an undefined value. |
| 232 | 232 |
EdgeIt() { }
|
| 233 | 233 |
/// Copy constructor. |
| 234 | 234 |
|
| 235 | 235 |
/// Copy constructor. |
| 236 | 236 |
/// |
| 237 | 237 |
EdgeIt(const EdgeIt& e) : Edge(e) { }
|
| 238 | 238 |
/// Initialize the iterator to be invalid. |
| 239 | 239 |
|
| 240 | 240 |
/// Initialize the iterator to be invalid. |
| 241 | 241 |
/// |
| 242 | 242 |
EdgeIt(Invalid) { }
|
| 243 | 243 |
/// This constructor sets the iterator to the first edge. |
| 244 |
|
|
| 244 |
|
|
| 245 | 245 |
/// This constructor sets the iterator to the first edge. |
| 246 | 246 |
EdgeIt(const Graph&) { }
|
| 247 | 247 |
/// Edge -> EdgeIt conversion |
| 248 | 248 |
|
| 249 | 249 |
/// Sets the iterator to the value of the trivial iterator. |
| 250 | 250 |
/// This feature necessitates that each time we |
| 251 |
/// iterate the edge-set, the iteration order is the |
|
| 252 |
/// same. |
|
| 253 |
|
|
| 251 |
/// iterate the edge-set, the iteration order is the |
|
| 252 |
/// same. |
|
| 253 |
EdgeIt(const Graph&, const Edge&) { }
|
|
| 254 | 254 |
/// Next edge |
| 255 |
|
|
| 255 |
|
|
| 256 | 256 |
/// Assign the iterator to the next edge. |
| 257 | 257 |
EdgeIt& operator++() { return *this; }
|
| 258 | 258 |
}; |
| 259 | 259 |
|
| 260 |
/// \brief This iterator goes trough the incident undirected |
|
| 260 |
/// \brief This iterator goes trough the incident undirected |
|
| 261 | 261 |
/// arcs of a node. |
| 262 | 262 |
/// |
| 263 | 263 |
/// This iterator goes trough the incident edges |
| 264 |
/// of a certain node of a graph. You should assume that the |
|
| 264 |
/// of a certain node of a graph. You should assume that the |
|
| 265 | 265 |
/// loop arcs will be iterated twice. |
| 266 |
/// |
|
| 266 |
/// |
|
| 267 | 267 |
/// Its usage is quite simple, for example you can compute the |
| 268 | 268 |
/// degree (i.e. count the number of incident arcs of a node \c n |
| 269 |
/// in graph \c g of type \c Graph as follows. |
|
| 269 |
/// in graph \c g of type \c Graph as follows. |
|
| 270 | 270 |
/// |
| 271 | 271 |
///\code |
| 272 | 272 |
/// int count=0; |
| 273 | 273 |
/// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count; |
| 274 | 274 |
///\endcode |
| 275 | 275 |
class IncEdgeIt : public Edge {
|
| 276 | 276 |
public: |
| 277 | 277 |
/// Default constructor |
| 278 | 278 |
|
| 279 | 279 |
/// @warning The default constructor sets the iterator |
| 280 | 280 |
/// to an undefined value. |
| 281 | 281 |
IncEdgeIt() { }
|
| 282 | 282 |
/// Copy constructor. |
| 283 | 283 |
|
| 284 | 284 |
/// Copy constructor. |
| 285 | 285 |
/// |
| 286 | 286 |
IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
|
| 287 | 287 |
/// Initialize the iterator to be invalid. |
| 288 | 288 |
|
| 289 | 289 |
/// Initialize the iterator to be invalid. |
| 290 | 290 |
/// |
| 291 | 291 |
IncEdgeIt(Invalid) { }
|
| 292 | 292 |
/// This constructor sets the iterator to first incident arc. |
| 293 |
|
|
| 293 |
|
|
| 294 | 294 |
/// This constructor set the iterator to the first incident arc of |
| 295 | 295 |
/// the node. |
| 296 | 296 |
IncEdgeIt(const Graph&, const Node&) { }
|
| 297 | 297 |
/// Edge -> IncEdgeIt conversion |
| 298 | 298 |
|
| 299 | 299 |
/// Sets the iterator to the value of the trivial iterator \c e. |
| 300 |
/// This feature necessitates that each time we |
|
| 300 |
/// This feature necessitates that each time we |
|
| 301 | 301 |
/// iterate the arc-set, the iteration order is the same. |
| 302 | 302 |
IncEdgeIt(const Graph&, const Edge&) { }
|
| 303 | 303 |
/// Next incident arc |
| 304 | 304 |
|
| 305 | 305 |
/// Assign the iterator to the next incident arc |
| 306 |
|
|
| 306 |
/// of the corresponding node. |
|
| 307 | 307 |
IncEdgeIt& operator++() { return *this; }
|
| 308 | 308 |
}; |
| 309 | 309 |
|
| 310 | 310 |
/// The directed arc type. |
| 311 | 311 |
|
| 312 | 312 |
/// The directed arc type. It can be converted to the |
| 313 | 313 |
/// edge or it should be inherited from the undirected |
| 314 | 314 |
/// arc. |
| 315 | 315 |
class Arc : public Edge {
|
| 316 | 316 |
public: |
| 317 | 317 |
/// Default constructor |
| 318 | 318 |
|
| 319 | 319 |
/// @warning The default constructor sets the iterator |
| 320 | 320 |
/// to an undefined value. |
| 321 | 321 |
Arc() { }
|
| 322 | 322 |
/// Copy constructor. |
| ... | ... |
@@ -327,134 +327,134 @@ |
| 327 | 327 |
/// Initialize the iterator to be invalid. |
| 328 | 328 |
|
| 329 | 329 |
/// Initialize the iterator to be invalid. |
| 330 | 330 |
/// |
| 331 | 331 |
Arc(Invalid) { }
|
| 332 | 332 |
/// Equality operator |
| 333 | 333 |
|
| 334 | 334 |
/// Two iterators are equal if and only if they point to the |
| 335 | 335 |
/// same object or both are invalid. |
| 336 | 336 |
bool operator==(Arc) const { return true; }
|
| 337 | 337 |
/// Inequality operator |
| 338 | 338 |
|
| 339 | 339 |
/// \sa operator==(Arc n) |
| 340 | 340 |
/// |
| 341 | 341 |
bool operator!=(Arc) const { return true; }
|
| 342 | 342 |
|
| 343 |
/// Artificial ordering operator. |
|
| 344 |
|
|
| 345 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 346 |
/// similar associative container we require this. |
|
| 347 |
/// |
|
| 348 |
/// \note This operator only have to define some strict ordering of |
|
| 349 |
/// the items; this order has nothing to do with the iteration |
|
| 350 |
/// ordering of the items. |
|
| 351 |
bool operator<(Arc) const { return false; }
|
|
| 352 |
|
|
| 353 |
|
|
| 343 |
/// Artificial ordering operator. |
|
| 344 |
|
|
| 345 |
/// To allow the use of graph descriptors as key type in std::map or |
|
| 346 |
/// similar associative container we require this. |
|
| 347 |
/// |
|
| 348 |
/// \note This operator only have to define some strict ordering of |
|
| 349 |
/// the items; this order has nothing to do with the iteration |
|
| 350 |
/// ordering of the items. |
|
| 351 |
bool operator<(Arc) const { return false; }
|
|
| 352 |
|
|
| 353 |
}; |
|
| 354 | 354 |
/// This iterator goes through each directed arc. |
| 355 | 355 |
|
| 356 | 356 |
/// This iterator goes through each arc of a graph. |
| 357 | 357 |
/// Its usage is quite simple, for example you can count the number |
| 358 | 358 |
/// of arcs in a graph \c g of type \c Graph as follows: |
| 359 | 359 |
///\code |
| 360 | 360 |
/// int count=0; |
| 361 | 361 |
/// for(Graph::ArcIt e(g); e!=INVALID; ++e) ++count; |
| 362 | 362 |
///\endcode |
| 363 | 363 |
class ArcIt : public Arc {
|
| 364 | 364 |
public: |
| 365 | 365 |
/// Default constructor |
| 366 | 366 |
|
| 367 | 367 |
/// @warning The default constructor sets the iterator |
| 368 | 368 |
/// to an undefined value. |
| 369 | 369 |
ArcIt() { }
|
| 370 | 370 |
/// Copy constructor. |
| 371 | 371 |
|
| 372 | 372 |
/// Copy constructor. |
| 373 | 373 |
/// |
| 374 | 374 |
ArcIt(const ArcIt& e) : Arc(e) { }
|
| 375 | 375 |
/// Initialize the iterator to be invalid. |
| 376 | 376 |
|
| 377 | 377 |
/// Initialize the iterator to be invalid. |
| 378 | 378 |
/// |
| 379 | 379 |
ArcIt(Invalid) { }
|
| 380 | 380 |
/// This constructor sets the iterator to the first arc. |
| 381 |
|
|
| 381 |
|
|
| 382 | 382 |
/// This constructor sets the iterator to the first arc of \c g. |
| 383 | 383 |
///@param g the graph |
| 384 | 384 |
ArcIt(const Graph &g) { ignore_unused_variable_warning(g); }
|
| 385 | 385 |
/// Arc -> ArcIt conversion |
| 386 | 386 |
|
| 387 | 387 |
/// Sets the iterator to the value of the trivial iterator \c e. |
| 388 |
/// This feature necessitates that each time we |
|
| 388 |
/// This feature necessitates that each time we |
|
| 389 | 389 |
/// iterate the arc-set, the iteration order is the same. |
| 390 |
ArcIt(const Graph&, const Arc&) { }
|
|
| 390 |
ArcIt(const Graph&, const Arc&) { }
|
|
| 391 | 391 |
///Next arc |
| 392 |
|
|
| 392 |
|
|
| 393 | 393 |
/// Assign the iterator to the next arc. |
| 394 | 394 |
ArcIt& operator++() { return *this; }
|
| 395 | 395 |
}; |
| 396 |
|
|
| 396 |
|
|
| 397 | 397 |
/// This iterator goes trough the outgoing directed arcs of a node. |
| 398 | 398 |
|
| 399 | 399 |
/// This iterator goes trough the \e outgoing arcs of a certain node |
| 400 | 400 |
/// of a graph. |
| 401 | 401 |
/// Its usage is quite simple, for example you can count the number |
| 402 | 402 |
/// of outgoing arcs of a node \c n |
| 403 | 403 |
/// in graph \c g of type \c Graph as follows. |
| 404 | 404 |
///\code |
| 405 | 405 |
/// int count=0; |
| 406 | 406 |
/// for (Graph::OutArcIt e(g, n); e!=INVALID; ++e) ++count; |
| 407 | 407 |
///\endcode |
| 408 |
|
|
| 408 |
|
|
| 409 | 409 |
class OutArcIt : public Arc {
|
| 410 | 410 |
public: |
| 411 | 411 |
/// Default constructor |
| 412 | 412 |
|
| 413 | 413 |
/// @warning The default constructor sets the iterator |
| 414 | 414 |
/// to an undefined value. |
| 415 | 415 |
OutArcIt() { }
|
| 416 | 416 |
/// Copy constructor. |
| 417 | 417 |
|
| 418 | 418 |
/// Copy constructor. |
| 419 | 419 |
/// |
| 420 | 420 |
OutArcIt(const OutArcIt& e) : Arc(e) { }
|
| 421 | 421 |
/// Initialize the iterator to be invalid. |
| 422 | 422 |
|
| 423 | 423 |
/// Initialize the iterator to be invalid. |
| 424 | 424 |
/// |
| 425 | 425 |
OutArcIt(Invalid) { }
|
| 426 | 426 |
/// This constructor sets the iterator to the first outgoing arc. |
| 427 |
|
|
| 427 |
|
|
| 428 | 428 |
/// This constructor sets the iterator to the first outgoing arc of |
| 429 | 429 |
/// the node. |
| 430 | 430 |
///@param n the node |
| 431 | 431 |
///@param g the graph |
| 432 | 432 |
OutArcIt(const Graph& n, const Node& g) {
|
| 433 |
ignore_unused_variable_warning(n); |
|
| 434 |
ignore_unused_variable_warning(g); |
|
| 435 |
|
|
| 433 |
ignore_unused_variable_warning(n); |
|
| 434 |
ignore_unused_variable_warning(g); |
|
| 435 |
} |
|
| 436 | 436 |
/// Arc -> OutArcIt conversion |
| 437 | 437 |
|
| 438 | 438 |
/// Sets the iterator to the value of the trivial iterator. |
| 439 |
|
|
| 439 |
/// This feature necessitates that each time we |
|
| 440 | 440 |
/// iterate the arc-set, the iteration order is the same. |
| 441 | 441 |
OutArcIt(const Graph&, const Arc&) { }
|
| 442 | 442 |
///Next outgoing arc |
| 443 |
|
|
| 444 |
/// Assign the iterator to the next |
|
| 443 |
|
|
| 444 |
/// Assign the iterator to the next |
|
| 445 | 445 |
/// outgoing arc of the corresponding node. |
| 446 | 446 |
OutArcIt& operator++() { return *this; }
|
| 447 | 447 |
}; |
| 448 | 448 |
|
| 449 | 449 |
/// This iterator goes trough the incoming directed arcs of a node. |
| 450 | 450 |
|
| 451 | 451 |
/// This iterator goes trough the \e incoming arcs of a certain node |
| 452 | 452 |
/// of a graph. |
| 453 | 453 |
/// Its usage is quite simple, for example you can count the number |
| 454 | 454 |
/// of outgoing arcs of a node \c n |
| 455 | 455 |
/// in graph \c g of type \c Graph as follows. |
| 456 | 456 |
///\code |
| 457 | 457 |
/// int count=0; |
| 458 | 458 |
/// for(Graph::InArcIt e(g, n); e!=INVALID; ++e) ++count; |
| 459 | 459 |
///\endcode |
| 460 | 460 |
|
| ... | ... |
@@ -463,140 +463,140 @@ |
| 463 | 463 |
/// Default constructor |
| 464 | 464 |
|
| 465 | 465 |
/// @warning The default constructor sets the iterator |
| 466 | 466 |
/// to an undefined value. |
| 467 | 467 |
InArcIt() { }
|
| 468 | 468 |
/// Copy constructor. |
| 469 | 469 |
|
| 470 | 470 |
/// Copy constructor. |
| 471 | 471 |
/// |
| 472 | 472 |
InArcIt(const InArcIt& e) : Arc(e) { }
|
| 473 | 473 |
/// Initialize the iterator to be invalid. |
| 474 | 474 |
|
| 475 | 475 |
/// Initialize the iterator to be invalid. |
| 476 | 476 |
/// |
| 477 | 477 |
InArcIt(Invalid) { }
|
| 478 | 478 |
/// This constructor sets the iterator to first incoming arc. |
| 479 |
|
|
| 479 |
|
|
| 480 | 480 |
/// This constructor set the iterator to the first incoming arc of |
| 481 | 481 |
/// the node. |
| 482 | 482 |
///@param n the node |
| 483 | 483 |
///@param g the graph |
| 484 |
InArcIt(const Graph& g, const Node& n) {
|
|
| 485 |
ignore_unused_variable_warning(n); |
|
| 486 |
ignore_unused_variable_warning(g); |
|
| 487 |
} |
|
| 484 |
InArcIt(const Graph& g, const Node& n) {
|
|
| 485 |
ignore_unused_variable_warning(n); |
|
| 486 |
ignore_unused_variable_warning(g); |
|
| 487 |
} |
|
| 488 | 488 |
/// Arc -> InArcIt conversion |
| 489 | 489 |
|
| 490 | 490 |
/// Sets the iterator to the value of the trivial iterator \c e. |
| 491 |
/// This feature necessitates that each time we |
|
| 491 |
/// This feature necessitates that each time we |
|
| 492 | 492 |
/// iterate the arc-set, the iteration order is the same. |
| 493 | 493 |
InArcIt(const Graph&, const Arc&) { }
|
| 494 | 494 |
/// Next incoming arc |
| 495 | 495 |
|
| 496 | 496 |
/// Assign the iterator to the next inarc of the corresponding node. |
| 497 | 497 |
/// |
| 498 | 498 |
InArcIt& operator++() { return *this; }
|
| 499 | 499 |
}; |
| 500 | 500 |
|
| 501 | 501 |
/// \brief Read write map of the nodes to type \c T. |
| 502 |
/// |
|
| 502 |
/// |
|
| 503 | 503 |
/// ReadWrite map of the nodes to type \c T. |
| 504 | 504 |
/// \sa Reference |
| 505 |
template<class T> |
|
| 505 |
template<class T> |
|
| 506 | 506 |
class NodeMap : public ReadWriteMap< Node, T > |
| 507 | 507 |
{
|
| 508 | 508 |
public: |
| 509 | 509 |
|
| 510 | 510 |
///\e |
| 511 | 511 |
NodeMap(const Graph&) { }
|
| 512 | 512 |
///\e |
| 513 | 513 |
NodeMap(const Graph&, T) { }
|
| 514 | 514 |
|
| 515 | 515 |
///Copy constructor |
| 516 | 516 |
NodeMap(const NodeMap& nm) : ReadWriteMap< Node, T >(nm) { }
|
| 517 | 517 |
///Assignment operator |
| 518 | 518 |
template <typename CMap> |
| 519 |
NodeMap& operator=(const CMap&) {
|
|
| 519 |
NodeMap& operator=(const CMap&) {
|
|
| 520 | 520 |
checkConcept<ReadMap<Node, T>, CMap>(); |
| 521 |
return *this; |
|
| 521 |
return *this; |
|
| 522 | 522 |
} |
| 523 | 523 |
}; |
| 524 | 524 |
|
| 525 | 525 |
/// \brief Read write map of the directed arcs to type \c T. |
| 526 | 526 |
/// |
| 527 | 527 |
/// Reference map of the directed arcs to type \c T. |
| 528 | 528 |
/// \sa Reference |
| 529 |
template<class T> |
|
| 529 |
template<class T> |
|
| 530 | 530 |
class ArcMap : public ReadWriteMap<Arc,T> |
| 531 | 531 |
{
|
| 532 | 532 |
public: |
| 533 | 533 |
|
| 534 | 534 |
///\e |
| 535 | 535 |
ArcMap(const Graph&) { }
|
| 536 | 536 |
///\e |
| 537 | 537 |
ArcMap(const Graph&, T) { }
|
| 538 | 538 |
///Copy constructor |
| 539 | 539 |
ArcMap(const ArcMap& em) : ReadWriteMap<Arc,T>(em) { }
|
| 540 | 540 |
///Assignment operator |
| 541 | 541 |
template <typename CMap> |
| 542 |
ArcMap& operator=(const CMap&) {
|
|
| 542 |
ArcMap& operator=(const CMap&) {
|
|
| 543 | 543 |
checkConcept<ReadMap<Arc, T>, CMap>(); |
| 544 |
return *this; |
|
| 544 |
return *this; |
|
| 545 | 545 |
} |
| 546 | 546 |
}; |
| 547 | 547 |
|
| 548 | 548 |
/// Read write map of the edges to type \c T. |
| 549 | 549 |
|
| 550 | 550 |
/// Reference map of the arcs to type \c T. |
| 551 | 551 |
/// \sa Reference |
| 552 |
template<class T> |
|
| 552 |
template<class T> |
|
| 553 | 553 |
class EdgeMap : public ReadWriteMap<Edge,T> |
| 554 | 554 |
{
|
| 555 | 555 |
public: |
| 556 | 556 |
|
| 557 | 557 |
///\e |
| 558 | 558 |
EdgeMap(const Graph&) { }
|
| 559 | 559 |
///\e |
| 560 | 560 |
EdgeMap(const Graph&, T) { }
|
| 561 | 561 |
///Copy constructor |
| 562 | 562 |
EdgeMap(const EdgeMap& em) : ReadWriteMap<Edge,T>(em) {}
|
| 563 | 563 |
///Assignment operator |
| 564 | 564 |
template <typename CMap> |
| 565 |
EdgeMap& operator=(const CMap&) {
|
|
| 565 |
EdgeMap& operator=(const CMap&) {
|
|
| 566 | 566 |
checkConcept<ReadMap<Edge, T>, CMap>(); |
| 567 |
return *this; |
|
| 567 |
return *this; |
|
| 568 | 568 |
} |
| 569 | 569 |
}; |
| 570 | 570 |
|
| 571 | 571 |
/// \brief Direct the given edge. |
| 572 | 572 |
/// |
| 573 | 573 |
/// Direct the given edge. The returned arc source |
| 574 | 574 |
/// will be the given node. |
| 575 | 575 |
Arc direct(const Edge&, const Node&) const {
|
| 576 |
|
|
| 576 |
return INVALID; |
|
| 577 | 577 |
} |
| 578 | 578 |
|
| 579 | 579 |
/// \brief Direct the given edge. |
| 580 | 580 |
/// |
| 581 | 581 |
/// Direct the given edge. The returned arc |
| 582 | 582 |
/// represents the given edge and the direction comes |
| 583 | 583 |
/// from the bool parameter. The source of the edge and |
| 584 | 584 |
/// the directed arc is the same when the given bool is true. |
| 585 | 585 |
Arc direct(const Edge&, bool) const {
|
| 586 |
|
|
| 586 |
return INVALID; |
|
| 587 | 587 |
} |
| 588 | 588 |
|
| 589 | 589 |
/// \brief Returns true if the arc has default orientation. |
| 590 | 590 |
/// |
| 591 | 591 |
/// Returns whether the given directed arc is same orientation as |
| 592 | 592 |
/// the corresponding edge's default orientation. |
| 593 | 593 |
bool direction(Arc) const { return true; }
|
| 594 | 594 |
|
| 595 | 595 |
/// \brief Returns the opposite directed arc. |
| 596 | 596 |
/// |
| 597 | 597 |
/// Returns the opposite directed arc. |
| 598 | 598 |
Arc oppositeArc(Arc) const { return INVALID; }
|
| 599 | 599 |
|
| 600 | 600 |
/// \brief Opposite node on an arc |
| 601 | 601 |
/// |
| 602 | 602 |
/// \return the opposite of the given Node on the given Edge |
| ... | ... |
@@ -612,138 +612,138 @@ |
| 612 | 612 |
/// which arises this way is called the inherent direction of the |
| 613 | 613 |
/// edge, and is used to define the "default" direction |
| 614 | 614 |
/// of the directed versions of the arcs. |
| 615 | 615 |
/// \sa direction |
| 616 | 616 |
Node u(Edge) const { return INVALID; }
|
| 617 | 617 |
|
| 618 | 618 |
/// \brief Second node of the edge. |
| 619 | 619 |
Node v(Edge) const { return INVALID; }
|
| 620 | 620 |
|
| 621 | 621 |
/// \brief Source node of the directed arc. |
| 622 | 622 |
Node source(Arc) const { return INVALID; }
|
| 623 | 623 |
|
| 624 | 624 |
/// \brief Target node of the directed arc. |
| 625 | 625 |
Node target(Arc) const { return INVALID; }
|
| 626 | 626 |
|
| 627 | 627 |
/// \brief Returns the id of the node. |
| 628 |
int id(Node) const { return -1; }
|
|
| 628 |
int id(Node) const { return -1; }
|
|
| 629 | 629 |
|
| 630 | 630 |
/// \brief Returns the id of the edge. |
| 631 |
int id(Edge) const { return -1; }
|
|
| 631 |
int id(Edge) const { return -1; }
|
|
| 632 | 632 |
|
| 633 | 633 |
/// \brief Returns the id of the arc. |
| 634 |
int id(Arc) const { return -1; }
|
|
| 634 |
int id(Arc) const { return -1; }
|
|
| 635 | 635 |
|
| 636 | 636 |
/// \brief Returns the node with the given id. |
| 637 | 637 |
/// |
| 638 | 638 |
/// \pre The argument should be a valid node id in the graph. |
| 639 |
Node nodeFromId(int) const { return INVALID; }
|
|
| 639 |
Node nodeFromId(int) const { return INVALID; }
|
|
| 640 | 640 |
|
| 641 | 641 |
/// \brief Returns the edge with the given id. |
| 642 | 642 |
/// |
| 643 | 643 |
/// \pre The argument should be a valid edge id in the graph. |
| 644 |
Edge edgeFromId(int) const { return INVALID; }
|
|
| 644 |
Edge edgeFromId(int) const { return INVALID; }
|
|
| 645 | 645 |
|
| 646 | 646 |
/// \brief Returns the arc with the given id. |
| 647 | 647 |
/// |
| 648 | 648 |
/// \pre The argument should be a valid arc id in the graph. |
| 649 |
Arc arcFromId(int) const { return INVALID; }
|
|
| 649 |
Arc arcFromId(int) const { return INVALID; }
|
|
| 650 | 650 |
|
| 651 | 651 |
/// \brief Returns an upper bound on the node IDs. |
| 652 |
int maxNodeId() const { return -1; }
|
|
| 652 |
int maxNodeId() const { return -1; }
|
|
| 653 | 653 |
|
| 654 | 654 |
/// \brief Returns an upper bound on the edge IDs. |
| 655 |
int maxEdgeId() const { return -1; }
|
|
| 655 |
int maxEdgeId() const { return -1; }
|
|
| 656 | 656 |
|
| 657 | 657 |
/// \brief Returns an upper bound on the arc IDs. |
| 658 |
int maxArcId() const { return -1; }
|
|
| 658 |
int maxArcId() const { return -1; }
|
|
| 659 | 659 |
|
| 660 | 660 |
void first(Node&) const {}
|
| 661 | 661 |
void next(Node&) const {}
|
| 662 | 662 |
|
| 663 | 663 |
void first(Edge&) const {}
|
| 664 | 664 |
void next(Edge&) const {}
|
| 665 | 665 |
|
| 666 | 666 |
void first(Arc&) const {}
|
| 667 | 667 |
void next(Arc&) const {}
|
| 668 | 668 |
|
| 669 | 669 |
void firstOut(Arc&, Node) const {}
|
| 670 | 670 |
void nextOut(Arc&) const {}
|
| 671 | 671 |
|
| 672 | 672 |
void firstIn(Arc&, Node) const {}
|
| 673 | 673 |
void nextIn(Arc&) const {}
|
| 674 | 674 |
|
| 675 | 675 |
void firstInc(Edge &, bool &, const Node &) const {}
|
| 676 | 676 |
void nextInc(Edge &, bool &) const {}
|
| 677 | 677 |
|
| 678 | 678 |
// The second parameter is dummy. |
| 679 | 679 |
Node fromId(int, Node) const { return INVALID; }
|
| 680 | 680 |
// The second parameter is dummy. |
| 681 | 681 |
Edge fromId(int, Edge) const { return INVALID; }
|
| 682 | 682 |
// The second parameter is dummy. |
| 683 | 683 |
Arc fromId(int, Arc) const { return INVALID; }
|
| 684 | 684 |
|
| 685 | 685 |
// Dummy parameter. |
| 686 |
int maxId(Node) const { return -1; }
|
|
| 686 |
int maxId(Node) const { return -1; }
|
|
| 687 | 687 |
// Dummy parameter. |
| 688 |
int maxId(Edge) const { return -1; }
|
|
| 688 |
int maxId(Edge) const { return -1; }
|
|
| 689 | 689 |
// Dummy parameter. |
| 690 |
int maxId(Arc) const { return -1; }
|
|
| 690 |
int maxId(Arc) const { return -1; }
|
|
| 691 | 691 |
|
| 692 | 692 |
/// \brief Base node of the iterator |
| 693 | 693 |
/// |
| 694 | 694 |
/// Returns the base node (the source in this case) of the iterator |
| 695 | 695 |
Node baseNode(OutArcIt e) const {
|
| 696 |
|
|
| 696 |
return source(e); |
|
| 697 | 697 |
} |
| 698 | 698 |
/// \brief Running node of the iterator |
| 699 | 699 |
/// |
| 700 | 700 |
/// Returns the running node (the target in this case) of the |
| 701 | 701 |
/// iterator |
| 702 | 702 |
Node runningNode(OutArcIt e) const {
|
| 703 |
|
|
| 703 |
return target(e); |
|
| 704 | 704 |
} |
| 705 | 705 |
|
| 706 | 706 |
/// \brief Base node of the iterator |
| 707 | 707 |
/// |
| 708 | 708 |
/// Returns the base node (the target in this case) of the iterator |
| 709 | 709 |
Node baseNode(InArcIt e) const {
|
| 710 |
|
|
| 710 |
return target(e); |
|
| 711 | 711 |
} |
| 712 | 712 |
/// \brief Running node of the iterator |
| 713 | 713 |
/// |
| 714 | 714 |
/// Returns the running node (the source in this case) of the |
| 715 | 715 |
/// iterator |
| 716 | 716 |
Node runningNode(InArcIt e) const {
|
| 717 |
|
|
| 717 |
return source(e); |
|
| 718 | 718 |
} |
| 719 | 719 |
|
| 720 | 720 |
/// \brief Base node of the iterator |
| 721 | 721 |
/// |
| 722 | 722 |
/// Returns the base node of the iterator |
| 723 | 723 |
Node baseNode(IncEdgeIt) const {
|
| 724 |
|
|
| 724 |
return INVALID; |
|
| 725 | 725 |
} |
| 726 |
|
|
| 726 |
|
|
| 727 | 727 |
/// \brief Running node of the iterator |
| 728 | 728 |
/// |
| 729 | 729 |
/// Returns the running node of the iterator |
| 730 | 730 |
Node runningNode(IncEdgeIt) const {
|
| 731 |
|
|
| 731 |
return INVALID; |
|
| 732 | 732 |
} |
| 733 | 733 |
|
| 734 | 734 |
template <typename _Graph> |
| 735 | 735 |
struct Constraints {
|
| 736 |
void constraints() {
|
|
| 737 |
checkConcept<IterableGraphComponent<>, _Graph>(); |
|
| 738 |
checkConcept<IDableGraphComponent<>, _Graph>(); |
|
| 739 |
checkConcept<MappableGraphComponent<>, _Graph>(); |
|
| 740 |
|
|
| 736 |
void constraints() {
|
|
| 737 |
checkConcept<IterableGraphComponent<>, _Graph>(); |
|
| 738 |
checkConcept<IDableGraphComponent<>, _Graph>(); |
|
| 739 |
checkConcept<MappableGraphComponent<>, _Graph>(); |
|
| 740 |
} |
|
| 741 | 741 |
}; |
| 742 | 742 |
|
| 743 | 743 |
}; |
| 744 | 744 |
|
| 745 | 745 |
} |
| 746 | 746 |
|
| 747 | 747 |
} |
| 748 | 748 |
|
| 749 | 749 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 graph_concepts |
| ... | ... |
@@ -36,628 +36,628 @@ |
| 36 | 36 |
/// |
| 37 | 37 |
/// This class describes the interface of Node and Arc (and Edge |
| 38 | 38 |
/// in undirected graphs) subtypes of graph types. |
| 39 | 39 |
/// |
| 40 | 40 |
/// \note This class is a template class so that we can use it to |
| 41 | 41 |
/// create graph skeleton classes. The reason for this is than Node |
| 42 | 42 |
/// and Arc types should \em not derive from the same base class. |
| 43 | 43 |
/// For Node you should instantiate it with character 'n' and for Arc |
| 44 | 44 |
/// with 'a'. |
| 45 | 45 |
|
| 46 | 46 |
#ifndef DOXYGEN |
| 47 | 47 |
template <char _selector = '0'> |
| 48 | 48 |
#endif |
| 49 | 49 |
class GraphItem {
|
| 50 | 50 |
public: |
| 51 | 51 |
/// \brief Default constructor. |
| 52 |
/// |
|
| 52 |
/// |
|
| 53 | 53 |
/// \warning The default constructor is not required to set |
| 54 | 54 |
/// the item to some well-defined value. So you should consider it |
| 55 | 55 |
/// as uninitialized. |
| 56 | 56 |
GraphItem() {}
|
| 57 | 57 |
/// \brief Copy constructor. |
| 58 | 58 |
/// |
| 59 | 59 |
/// Copy constructor. |
| 60 | 60 |
/// |
| 61 | 61 |
GraphItem(const GraphItem &) {}
|
| 62 | 62 |
/// \brief Invalid constructor \& conversion. |
| 63 | 63 |
/// |
| 64 | 64 |
/// This constructor initializes the item to be invalid. |
| 65 | 65 |
/// \sa Invalid for more details. |
| 66 | 66 |
GraphItem(Invalid) {}
|
| 67 | 67 |
/// \brief Assign operator for nodes. |
| 68 | 68 |
/// |
| 69 |
/// The nodes are assignable. |
|
| 69 |
/// The nodes are assignable. |
|
| 70 | 70 |
/// |
| 71 | 71 |
GraphItem& operator=(GraphItem const&) { return *this; }
|
| 72 | 72 |
/// \brief Equality operator. |
| 73 | 73 |
/// |
| 74 | 74 |
/// Two iterators are equal if and only if they represents the |
| 75 | 75 |
/// same node in the graph or both are invalid. |
| 76 | 76 |
bool operator==(GraphItem) const { return false; }
|
| 77 | 77 |
/// \brief Inequality operator. |
| 78 | 78 |
/// |
| 79 | 79 |
/// \sa operator==(const Node& n) |
| 80 | 80 |
/// |
| 81 | 81 |
bool operator!=(GraphItem) const { return false; }
|
| 82 | 82 |
|
| 83 | 83 |
/// \brief Artificial ordering operator. |
| 84 | 84 |
/// |
| 85 | 85 |
/// To allow the use of graph descriptors as key type in std::map or |
| 86 | 86 |
/// similar associative container we require this. |
| 87 | 87 |
/// |
| 88 | 88 |
/// \note This operator only have to define some strict ordering of |
| 89 | 89 |
/// the items; this order has nothing to do with the iteration |
| 90 | 90 |
/// ordering of the items. |
| 91 | 91 |
bool operator<(GraphItem) const { return false; }
|
| 92 | 92 |
|
| 93 | 93 |
template<typename _GraphItem> |
| 94 | 94 |
struct Constraints {
|
| 95 |
void constraints() {
|
|
| 96 |
_GraphItem i1; |
|
| 97 |
_GraphItem i2 = i1; |
|
| 98 |
_GraphItem i3 = INVALID; |
|
| 99 |
|
|
| 100 |
i1 = i2 = i3; |
|
| 95 |
void constraints() {
|
|
| 96 |
_GraphItem i1; |
|
| 97 |
_GraphItem i2 = i1; |
|
| 98 |
_GraphItem i3 = INVALID; |
|
| 101 | 99 |
|
| 102 |
bool b; |
|
| 103 |
// b = (ia == ib) && (ia != ib) && (ia < ib); |
|
| 104 |
b = (ia == ib) && (ia != ib); |
|
| 105 |
b = (ia == INVALID) && (ib != INVALID); |
|
| 100 |
i1 = i2 = i3; |
|
| 101 |
|
|
| 102 |
bool b; |
|
| 103 |
// b = (ia == ib) && (ia != ib) && (ia < ib); |
|
| 104 |
b = (ia == ib) && (ia != ib); |
|
| 105 |
b = (ia == INVALID) && (ib != INVALID); |
|
| 106 | 106 |
b = (ia < ib); |
| 107 |
|
|
| 107 |
} |
|
| 108 | 108 |
|
| 109 |
const _GraphItem &ia; |
|
| 110 |
const _GraphItem &ib; |
|
| 109 |
const _GraphItem &ia; |
|
| 110 |
const _GraphItem &ib; |
|
| 111 | 111 |
}; |
| 112 | 112 |
}; |
| 113 | 113 |
|
| 114 | 114 |
/// \brief An empty base directed graph class. |
| 115 |
/// |
|
| 115 |
/// |
|
| 116 | 116 |
/// This class provides the minimal set of features needed for a |
| 117 | 117 |
/// directed graph structure. All digraph concepts have to be |
| 118 | 118 |
/// conform to this base directed graph. It just provides types |
| 119 | 119 |
/// for nodes and arcs and functions to get the source and the |
| 120 | 120 |
/// target of the arcs. |
| 121 | 121 |
class BaseDigraphComponent {
|
| 122 | 122 |
public: |
| 123 | 123 |
|
| 124 | 124 |
typedef BaseDigraphComponent Digraph; |
| 125 |
|
|
| 125 |
|
|
| 126 | 126 |
/// \brief Node class of the digraph. |
| 127 | 127 |
/// |
| 128 |
/// This class represents the Nodes of the digraph. |
|
| 128 |
/// This class represents the Nodes of the digraph. |
|
| 129 | 129 |
/// |
| 130 | 130 |
typedef GraphItem<'n'> Node; |
| 131 | 131 |
|
| 132 | 132 |
/// \brief Arc class of the digraph. |
| 133 | 133 |
/// |
| 134 |
/// This class represents the Arcs of the digraph. |
|
| 134 |
/// This class represents the Arcs of the digraph. |
|
| 135 | 135 |
/// |
| 136 | 136 |
typedef GraphItem<'e'> Arc; |
| 137 | 137 |
|
| 138 | 138 |
/// \brief Gives back the target node of an arc. |
| 139 | 139 |
/// |
| 140 | 140 |
/// Gives back the target node of an arc. |
| 141 | 141 |
/// |
| 142 | 142 |
Node target(const Arc&) const { return INVALID;}
|
| 143 | 143 |
|
| 144 | 144 |
/// \brief Gives back the source node of an arc. |
| 145 | 145 |
/// |
| 146 | 146 |
/// Gives back the source node of an arc. |
| 147 | 147 |
/// |
| 148 | 148 |
Node source(const Arc&) const { return INVALID;}
|
| 149 | 149 |
|
| 150 | 150 |
/// \brief Gives back the opposite node on the given arc. |
| 151 | 151 |
/// |
| 152 | 152 |
/// Gives back the opposite node on the given arc. |
| 153 | 153 |
Node oppositeNode(const Node&, const Arc&) const {
|
| 154 | 154 |
return INVALID; |
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
template <typename _Digraph> |
| 158 | 158 |
struct Constraints {
|
| 159 |
typedef typename _Digraph::Node Node; |
|
| 160 |
typedef typename _Digraph::Arc Arc; |
|
| 161 |
|
|
| 162 |
void constraints() {
|
|
| 163 |
checkConcept<GraphItem<'n'>, Node>(); |
|
| 164 |
checkConcept<GraphItem<'a'>, Arc>(); |
|
| 165 |
{
|
|
| 166 |
Node n; |
|
| 167 |
Arc e(INVALID); |
|
| 168 |
n = digraph.source(e); |
|
| 169 |
|
|
| 159 |
typedef typename _Digraph::Node Node; |
|
| 160 |
typedef typename _Digraph::Arc Arc; |
|
| 161 |
|
|
| 162 |
void constraints() {
|
|
| 163 |
checkConcept<GraphItem<'n'>, Node>(); |
|
| 164 |
checkConcept<GraphItem<'a'>, Arc>(); |
|
| 165 |
{
|
|
| 166 |
Node n; |
|
| 167 |
Arc e(INVALID); |
|
| 168 |
n = digraph.source(e); |
|
| 169 |
n = digraph.target(e); |
|
| 170 | 170 |
n = digraph.oppositeNode(n, e); |
| 171 |
} |
|
| 172 |
} |
|
| 173 |
|
|
| 174 |
const _Digraph& digraph; |
|
| 171 |
} |
|
| 172 |
} |
|
| 173 |
|
|
| 174 |
const _Digraph& digraph; |
|
| 175 | 175 |
}; |
| 176 | 176 |
}; |
| 177 | 177 |
|
| 178 | 178 |
/// \brief An empty base undirected graph class. |
| 179 |
/// |
|
| 179 |
/// |
|
| 180 | 180 |
/// This class provides the minimal set of features needed for an |
| 181 | 181 |
/// undirected graph structure. All undirected graph concepts have |
| 182 | 182 |
/// to be conform to this base graph. It just provides types for |
| 183 | 183 |
/// nodes, arcs and edges and functions to get the |
| 184 | 184 |
/// source and the target of the arcs and edges, |
| 185 | 185 |
/// conversion from arcs to edges and function to get |
| 186 | 186 |
/// both direction of the edges. |
| 187 | 187 |
class BaseGraphComponent : public BaseDigraphComponent {
|
| 188 | 188 |
public: |
| 189 | 189 |
typedef BaseDigraphComponent::Node Node; |
| 190 | 190 |
typedef BaseDigraphComponent::Arc Arc; |
| 191 | 191 |
/// \brief Undirected arc class of the graph. |
| 192 | 192 |
/// |
| 193 | 193 |
/// This class represents the edges of the graph. |
| 194 | 194 |
/// The undirected graphs can be used as a directed graph which |
| 195 | 195 |
/// for each arc contains the opposite arc too so the graph is |
| 196 | 196 |
/// bidirected. The edge represents two opposite |
| 197 | 197 |
/// directed arcs. |
| 198 | 198 |
class Edge : public GraphItem<'u'> {
|
| 199 | 199 |
public: |
| 200 | 200 |
typedef GraphItem<'u'> Parent; |
| 201 | 201 |
/// \brief Default constructor. |
| 202 |
/// |
|
| 202 |
/// |
|
| 203 | 203 |
/// \warning The default constructor is not required to set |
| 204 | 204 |
/// the item to some well-defined value. So you should consider it |
| 205 | 205 |
/// as uninitialized. |
| 206 | 206 |
Edge() {}
|
| 207 | 207 |
/// \brief Copy constructor. |
| 208 | 208 |
/// |
| 209 | 209 |
/// Copy constructor. |
| 210 | 210 |
/// |
| 211 | 211 |
Edge(const Edge &) : Parent() {}
|
| 212 | 212 |
/// \brief Invalid constructor \& conversion. |
| 213 | 213 |
/// |
| 214 | 214 |
/// This constructor initializes the item to be invalid. |
| 215 | 215 |
/// \sa Invalid for more details. |
| 216 | 216 |
Edge(Invalid) {}
|
| 217 | 217 |
/// \brief Converter from arc to edge. |
| 218 | 218 |
/// |
| 219 | 219 |
/// Besides the core graph item functionality each arc should |
| 220 |
/// be convertible to the represented edge. |
|
| 220 |
/// be convertible to the represented edge. |
|
| 221 | 221 |
Edge(const Arc&) {}
|
| 222 | 222 |
/// \brief Assign arc to edge. |
| 223 | 223 |
/// |
| 224 | 224 |
/// Besides the core graph item functionality each arc should |
| 225 |
/// be convertible to the represented edge. |
|
| 225 |
/// be convertible to the represented edge. |
|
| 226 | 226 |
Edge& operator=(const Arc&) { return *this; }
|
| 227 | 227 |
}; |
| 228 | 228 |
|
| 229 | 229 |
/// \brief Returns the direction of the arc. |
| 230 | 230 |
/// |
| 231 | 231 |
/// Returns the direction of the arc. Each arc represents an |
| 232 | 232 |
/// edge with a direction. It gives back the |
| 233 | 233 |
/// direction. |
| 234 | 234 |
bool direction(const Arc&) const { return true; }
|
| 235 | 235 |
|
| 236 | 236 |
/// \brief Returns the directed arc. |
| 237 | 237 |
/// |
| 238 | 238 |
/// Returns the directed arc from its direction and the |
| 239 | 239 |
/// represented edge. |
| 240 |
Arc direct(const Edge&, bool) const { return INVALID;}
|
|
| 240 |
Arc direct(const Edge&, bool) const { return INVALID;}
|
|
| 241 | 241 |
|
| 242 | 242 |
/// \brief Returns the directed arc. |
| 243 | 243 |
/// |
| 244 | 244 |
/// Returns the directed arc from its source and the |
| 245 | 245 |
/// represented edge. |
| 246 |
Arc direct(const Edge&, const Node&) const { return INVALID;}
|
|
| 246 |
Arc direct(const Edge&, const Node&) const { return INVALID;}
|
|
| 247 | 247 |
|
| 248 | 248 |
/// \brief Returns the opposite arc. |
| 249 | 249 |
/// |
| 250 | 250 |
/// Returns the opposite arc. It is the arc representing the |
| 251 | 251 |
/// same edge and has opposite direction. |
| 252 | 252 |
Arc oppositeArc(const Arc&) const { return INVALID;}
|
| 253 | 253 |
|
| 254 | 254 |
/// \brief Gives back one ending of an edge. |
| 255 | 255 |
/// |
| 256 | 256 |
/// Gives back one ending of an edge. |
| 257 | 257 |
Node u(const Edge&) const { return INVALID;}
|
| 258 | 258 |
|
| 259 | 259 |
/// \brief Gives back the other ending of an edge. |
| 260 | 260 |
/// |
| 261 | 261 |
/// Gives back the other ending of an edge. |
| 262 | 262 |
Node v(const Edge&) const { return INVALID;}
|
| 263 |
|
|
| 263 |
|
|
| 264 | 264 |
template <typename _Graph> |
| 265 | 265 |
struct Constraints {
|
| 266 |
typedef typename _Graph::Node Node; |
|
| 267 |
typedef typename _Graph::Arc Arc; |
|
| 268 |
typedef typename _Graph::Edge Edge; |
|
| 269 |
|
|
| 270 |
|
|
| 266 |
typedef typename _Graph::Node Node; |
|
| 267 |
typedef typename _Graph::Arc Arc; |
|
| 268 |
typedef typename _Graph::Edge Edge; |
|
| 269 |
|
|
| 270 |
void constraints() {
|
|
| 271 | 271 |
checkConcept<BaseDigraphComponent, _Graph>(); |
| 272 |
checkConcept<GraphItem<'u'>, Edge>(); |
|
| 273 |
{
|
|
| 274 |
Node n; |
|
| 275 |
Edge ue(INVALID); |
|
| 272 |
checkConcept<GraphItem<'u'>, Edge>(); |
|
| 273 |
{
|
|
| 274 |
Node n; |
|
| 275 |
Edge ue(INVALID); |
|
| 276 | 276 |
Arc e; |
| 277 |
n = graph.u(ue); |
|
| 278 |
n = graph.v(ue); |
|
| 277 |
n = graph.u(ue); |
|
| 278 |
n = graph.v(ue); |
|
| 279 | 279 |
e = graph.direct(ue, true); |
| 280 | 280 |
e = graph.direct(ue, n); |
| 281 | 281 |
e = graph.oppositeArc(e); |
| 282 | 282 |
ue = e; |
| 283 | 283 |
bool d = graph.direction(e); |
| 284 | 284 |
ignore_unused_variable_warning(d); |
| 285 |
} |
|
| 286 |
} |
|
| 287 |
|
|
| 288 |
const _Graph& graph; |
|
| 285 |
} |
|
| 286 |
} |
|
| 287 |
|
|
| 288 |
const _Graph& graph; |
|
| 289 | 289 |
}; |
| 290 | 290 |
|
| 291 | 291 |
}; |
| 292 | 292 |
|
| 293 | 293 |
/// \brief An empty idable base digraph class. |
| 294 |
/// |
|
| 294 |
/// |
|
| 295 | 295 |
/// This class provides beside the core digraph features |
| 296 | 296 |
/// core id functions for the digraph structure. |
| 297 | 297 |
/// The most of the base digraphs should be conform to this concept. |
| 298 | 298 |
/// The id's are unique and immutable. |
| 299 | 299 |
template <typename _Base = BaseDigraphComponent> |
| 300 | 300 |
class IDableDigraphComponent : public _Base {
|
| 301 | 301 |
public: |
| 302 | 302 |
|
| 303 | 303 |
typedef _Base Base; |
| 304 | 304 |
typedef typename Base::Node Node; |
| 305 | 305 |
typedef typename Base::Arc Arc; |
| 306 | 306 |
|
| 307 |
/// \brief Gives back an unique integer id for the Node. |
|
| 307 |
/// \brief Gives back an unique integer id for the Node. |
|
| 308 | 308 |
/// |
| 309 |
/// Gives back an unique integer id for the Node. |
|
| 309 |
/// Gives back an unique integer id for the Node. |
|
| 310 | 310 |
/// |
| 311 | 311 |
int id(const Node&) const { return -1;}
|
| 312 | 312 |
|
| 313 | 313 |
/// \brief Gives back the node by the unique id. |
| 314 | 314 |
/// |
| 315 | 315 |
/// Gives back the node by the unique id. |
| 316 | 316 |
/// If the digraph does not contain node with the given id |
| 317 |
/// then the result of the function is undetermined. |
|
| 317 |
/// then the result of the function is undetermined. |
|
| 318 | 318 |
Node nodeFromId(int) const { return INVALID;}
|
| 319 | 319 |
|
| 320 |
/// \brief Gives back an unique integer id for the Arc. |
|
| 320 |
/// \brief Gives back an unique integer id for the Arc. |
|
| 321 | 321 |
/// |
| 322 |
/// Gives back an unique integer id for the Arc. |
|
| 322 |
/// Gives back an unique integer id for the Arc. |
|
| 323 | 323 |
/// |
| 324 | 324 |
int id(const Arc&) const { return -1;}
|
| 325 | 325 |
|
| 326 | 326 |
/// \brief Gives back the arc by the unique id. |
| 327 | 327 |
/// |
| 328 | 328 |
/// Gives back the arc by the unique id. |
| 329 | 329 |
/// If the digraph does not contain arc with the given id |
| 330 |
/// then the result of the function is undetermined. |
|
| 330 |
/// then the result of the function is undetermined. |
|
| 331 | 331 |
Arc arcFromId(int) const { return INVALID;}
|
| 332 | 332 |
|
| 333 | 333 |
/// \brief Gives back an integer greater or equal to the maximum |
| 334 | 334 |
/// Node id. |
| 335 | 335 |
/// |
| 336 | 336 |
/// Gives back an integer greater or equal to the maximum Node |
| 337 | 337 |
/// id. |
| 338 | 338 |
int maxNodeId() const { return -1;}
|
| 339 | 339 |
|
| 340 | 340 |
/// \brief Gives back an integer greater or equal to the maximum |
| 341 | 341 |
/// Arc id. |
| 342 | 342 |
/// |
| 343 | 343 |
/// Gives back an integer greater or equal to the maximum Arc |
| 344 | 344 |
/// id. |
| 345 | 345 |
int maxArcId() const { return -1;}
|
| 346 | 346 |
|
| 347 | 347 |
template <typename _Digraph> |
| 348 | 348 |
struct Constraints {
|
| 349 | 349 |
|
| 350 |
void constraints() {
|
|
| 351 |
checkConcept<Base, _Digraph >(); |
|
| 352 |
typename _Digraph::Node node; |
|
| 353 |
int nid = digraph.id(node); |
|
| 354 |
nid = digraph.id(node); |
|
| 355 |
node = digraph.nodeFromId(nid); |
|
| 356 |
typename _Digraph::Arc arc; |
|
| 357 |
int eid = digraph.id(arc); |
|
| 358 |
eid = digraph.id(arc); |
|
| 359 |
arc = digraph.arcFromId(eid); |
|
| 350 |
void constraints() {
|
|
| 351 |
checkConcept<Base, _Digraph >(); |
|
| 352 |
typename _Digraph::Node node; |
|
| 353 |
int nid = digraph.id(node); |
|
| 354 |
nid = digraph.id(node); |
|
| 355 |
node = digraph.nodeFromId(nid); |
|
| 356 |
typename _Digraph::Arc arc; |
|
| 357 |
int eid = digraph.id(arc); |
|
| 358 |
eid = digraph.id(arc); |
|
| 359 |
arc = digraph.arcFromId(eid); |
|
| 360 | 360 |
|
| 361 |
nid = digraph.maxNodeId(); |
|
| 362 |
ignore_unused_variable_warning(nid); |
|
| 363 |
eid = digraph.maxArcId(); |
|
| 364 |
ignore_unused_variable_warning(eid); |
|
| 365 |
|
|
| 361 |
nid = digraph.maxNodeId(); |
|
| 362 |
ignore_unused_variable_warning(nid); |
|
| 363 |
eid = digraph.maxArcId(); |
|
| 364 |
ignore_unused_variable_warning(eid); |
|
| 365 |
} |
|
| 366 | 366 |
|
| 367 |
|
|
| 367 |
const _Digraph& digraph; |
|
| 368 | 368 |
}; |
| 369 | 369 |
}; |
| 370 | 370 |
|
| 371 | 371 |
/// \brief An empty idable base undirected graph class. |
| 372 |
/// |
|
| 372 |
/// |
|
| 373 | 373 |
/// This class provides beside the core undirected graph features |
| 374 | 374 |
/// core id functions for the undirected graph structure. The |
| 375 | 375 |
/// most of the base undirected graphs should be conform to this |
| 376 | 376 |
/// concept. The id's are unique and immutable. |
| 377 | 377 |
template <typename _Base = BaseGraphComponent> |
| 378 | 378 |
class IDableGraphComponent : public IDableDigraphComponent<_Base> {
|
| 379 | 379 |
public: |
| 380 | 380 |
|
| 381 | 381 |
typedef _Base Base; |
| 382 | 382 |
typedef typename Base::Edge Edge; |
| 383 | 383 |
|
| 384 | 384 |
using IDableDigraphComponent<_Base>::id; |
| 385 | 385 |
|
| 386 |
/// \brief Gives back an unique integer id for the Edge. |
|
| 386 |
/// \brief Gives back an unique integer id for the Edge. |
|
| 387 | 387 |
/// |
| 388 |
/// Gives back an unique integer id for the Edge. |
|
| 388 |
/// Gives back an unique integer id for the Edge. |
|
| 389 | 389 |
/// |
| 390 | 390 |
int id(const Edge&) const { return -1;}
|
| 391 | 391 |
|
| 392 | 392 |
/// \brief Gives back the edge by the unique id. |
| 393 | 393 |
/// |
| 394 | 394 |
/// Gives back the edge by the unique id. If the |
| 395 | 395 |
/// graph does not contain arc with the given id then the |
| 396 | 396 |
/// result of the function is undetermined. |
| 397 | 397 |
Edge edgeFromId(int) const { return INVALID;}
|
| 398 | 398 |
|
| 399 | 399 |
/// \brief Gives back an integer greater or equal to the maximum |
| 400 | 400 |
/// Edge id. |
| 401 | 401 |
/// |
| 402 | 402 |
/// Gives back an integer greater or equal to the maximum Edge |
| 403 | 403 |
/// id. |
| 404 | 404 |
int maxEdgeId() const { return -1;}
|
| 405 | 405 |
|
| 406 | 406 |
template <typename _Graph> |
| 407 | 407 |
struct Constraints {
|
| 408 | 408 |
|
| 409 |
void constraints() {
|
|
| 410 |
checkConcept<Base, _Graph >(); |
|
| 411 |
checkConcept<IDableDigraphComponent<Base>, _Graph >(); |
|
| 412 |
typename _Graph::Edge edge; |
|
| 413 |
int ueid = graph.id(edge); |
|
| 414 |
ueid = graph.id(edge); |
|
| 415 |
edge = graph.edgeFromId(ueid); |
|
| 416 |
ueid = graph.maxEdgeId(); |
|
| 417 |
ignore_unused_variable_warning(ueid); |
|
| 418 |
} |
|
| 409 |
void constraints() {
|
|
| 410 |
checkConcept<Base, _Graph >(); |
|
| 411 |
checkConcept<IDableDigraphComponent<Base>, _Graph >(); |
|
| 412 |
typename _Graph::Edge edge; |
|
| 413 |
int ueid = graph.id(edge); |
|
| 414 |
ueid = graph.id(edge); |
|
| 415 |
edge = graph.edgeFromId(ueid); |
|
| 416 |
ueid = graph.maxEdgeId(); |
|
| 417 |
ignore_unused_variable_warning(ueid); |
|
| 418 |
} |
|
| 419 | 419 |
|
| 420 |
|
|
| 420 |
const _Graph& graph; |
|
| 421 | 421 |
}; |
| 422 | 422 |
}; |
| 423 | 423 |
|
| 424 | 424 |
/// \brief Skeleton class for graph NodeIt and ArcIt |
| 425 | 425 |
/// |
| 426 | 426 |
/// Skeleton class for graph NodeIt and ArcIt. |
| 427 | 427 |
/// |
| 428 | 428 |
template <typename _Graph, typename _Item> |
| 429 | 429 |
class GraphItemIt : public _Item {
|
| 430 | 430 |
public: |
| 431 | 431 |
/// \brief Default constructor. |
| 432 | 432 |
/// |
| 433 | 433 |
/// @warning The default constructor sets the iterator |
| 434 | 434 |
/// to an undefined value. |
| 435 | 435 |
GraphItemIt() {}
|
| 436 | 436 |
/// \brief Copy constructor. |
| 437 | 437 |
/// |
| 438 | 438 |
/// Copy constructor. |
| 439 | 439 |
/// |
| 440 | 440 |
GraphItemIt(const GraphItemIt& ) {}
|
| 441 | 441 |
/// \brief Sets the iterator to the first item. |
| 442 | 442 |
/// |
| 443 | 443 |
/// Sets the iterator to the first item of \c the graph. |
| 444 | 444 |
/// |
| 445 | 445 |
explicit GraphItemIt(const _Graph&) {}
|
| 446 | 446 |
/// \brief Invalid constructor \& conversion. |
| 447 | 447 |
/// |
| 448 | 448 |
/// This constructor initializes the item to be invalid. |
| 449 | 449 |
/// \sa Invalid for more details. |
| 450 | 450 |
GraphItemIt(Invalid) {}
|
| 451 | 451 |
/// \brief Assign operator for items. |
| 452 | 452 |
/// |
| 453 |
/// The items are assignable. |
|
| 453 |
/// The items are assignable. |
|
| 454 | 454 |
/// |
| 455 |
GraphItemIt& operator=(const GraphItemIt&) { return *this; }
|
|
| 455 |
GraphItemIt& operator=(const GraphItemIt&) { return *this; }
|
|
| 456 | 456 |
/// \brief Next item. |
| 457 |
/// |
|
| 457 |
/// |
|
| 458 | 458 |
/// Assign the iterator to the next item. |
| 459 | 459 |
/// |
| 460 | 460 |
GraphItemIt& operator++() { return *this; }
|
| 461 | 461 |
/// \brief Equality operator |
| 462 |
/// |
|
| 462 |
/// |
|
| 463 | 463 |
/// Two iterators are equal if and only if they point to the |
| 464 | 464 |
/// same object or both are invalid. |
| 465 | 465 |
bool operator==(const GraphItemIt&) const { return true;}
|
| 466 | 466 |
/// \brief Inequality operator |
| 467 |
/// |
|
| 467 |
/// |
|
| 468 | 468 |
/// \sa operator==(Node n) |
| 469 | 469 |
/// |
| 470 | 470 |
bool operator!=(const GraphItemIt&) const { return true;}
|
| 471 |
|
|
| 471 |
|
|
| 472 | 472 |
template<typename _GraphItemIt> |
| 473 | 473 |
struct Constraints {
|
| 474 |
void constraints() {
|
|
| 475 |
_GraphItemIt it1(g); |
|
| 476 |
|
|
| 474 |
void constraints() {
|
|
| 475 |
_GraphItemIt it1(g); |
|
| 476 |
_GraphItemIt it2; |
|
| 477 | 477 |
|
| 478 |
it2 = ++it1; |
|
| 479 |
++it2 = it1; |
|
| 480 |
|
|
| 478 |
it2 = ++it1; |
|
| 479 |
++it2 = it1; |
|
| 480 |
++(++it1); |
|
| 481 | 481 |
|
| 482 |
_Item bi = it1; |
|
| 483 |
bi = it2; |
|
| 484 |
} |
|
| 485 |
_Graph& g; |
|
| 482 |
_Item bi = it1; |
|
| 483 |
bi = it2; |
|
| 484 |
} |
|
| 485 |
_Graph& g; |
|
| 486 | 486 |
}; |
| 487 | 487 |
}; |
| 488 | 488 |
|
| 489 | 489 |
/// \brief Skeleton class for graph InArcIt and OutArcIt |
| 490 | 490 |
/// |
| 491 | 491 |
/// \note Because InArcIt and OutArcIt may not inherit from the same |
| 492 |
/// base class, the _selector is a additional template parameter. For |
|
| 493 |
/// InArcIt you should instantiate it with character 'i' and for |
|
| 492 |
/// base class, the _selector is a additional template parameter. For |
|
| 493 |
/// InArcIt you should instantiate it with character 'i' and for |
|
| 494 | 494 |
/// OutArcIt with 'o'. |
| 495 | 495 |
template <typename _Graph, |
| 496 |
typename _Item = typename _Graph::Arc, |
|
| 497 |
typename _Base = typename _Graph::Node, |
|
| 498 |
|
|
| 496 |
typename _Item = typename _Graph::Arc, |
|
| 497 |
typename _Base = typename _Graph::Node, |
|
| 498 |
char _selector = '0'> |
|
| 499 | 499 |
class GraphIncIt : public _Item {
|
| 500 | 500 |
public: |
| 501 | 501 |
/// \brief Default constructor. |
| 502 | 502 |
/// |
| 503 | 503 |
/// @warning The default constructor sets the iterator |
| 504 | 504 |
/// to an undefined value. |
| 505 | 505 |
GraphIncIt() {}
|
| 506 | 506 |
/// \brief Copy constructor. |
| 507 | 507 |
/// |
| 508 | 508 |
/// Copy constructor. |
| 509 | 509 |
/// |
| 510 | 510 |
GraphIncIt(GraphIncIt const& gi) : _Item(gi) {}
|
| 511 |
/// \brief Sets the iterator to the first arc incoming into or outgoing |
|
| 511 |
/// \brief Sets the iterator to the first arc incoming into or outgoing |
|
| 512 | 512 |
/// from the node. |
| 513 | 513 |
/// |
| 514 |
/// Sets the iterator to the first arc incoming into or outgoing |
|
| 514 |
/// Sets the iterator to the first arc incoming into or outgoing |
|
| 515 | 515 |
/// from the node. |
| 516 | 516 |
/// |
| 517 | 517 |
explicit GraphIncIt(const _Graph&, const _Base&) {}
|
| 518 | 518 |
/// \brief Invalid constructor \& conversion. |
| 519 | 519 |
/// |
| 520 | 520 |
/// This constructor initializes the item to be invalid. |
| 521 | 521 |
/// \sa Invalid for more details. |
| 522 | 522 |
GraphIncIt(Invalid) {}
|
| 523 | 523 |
/// \brief Assign operator for iterators. |
| 524 | 524 |
/// |
| 525 |
/// The iterators are assignable. |
|
| 525 |
/// The iterators are assignable. |
|
| 526 | 526 |
/// |
| 527 |
GraphIncIt& operator=(GraphIncIt const&) { return *this; }
|
|
| 527 |
GraphIncIt& operator=(GraphIncIt const&) { return *this; }
|
|
| 528 | 528 |
/// \brief Next item. |
| 529 | 529 |
/// |
| 530 | 530 |
/// Assign the iterator to the next item. |
| 531 | 531 |
/// |
| 532 | 532 |
GraphIncIt& operator++() { return *this; }
|
| 533 | 533 |
|
| 534 | 534 |
/// \brief Equality operator |
| 535 | 535 |
/// |
| 536 | 536 |
/// Two iterators are equal if and only if they point to the |
| 537 | 537 |
/// same object or both are invalid. |
| 538 | 538 |
bool operator==(const GraphIncIt&) const { return true;}
|
| 539 | 539 |
|
| 540 | 540 |
/// \brief Inequality operator |
| 541 | 541 |
/// |
| 542 | 542 |
/// \sa operator==(Node n) |
| 543 | 543 |
/// |
| 544 | 544 |
bool operator!=(const GraphIncIt&) const { return true;}
|
| 545 | 545 |
|
| 546 | 546 |
template <typename _GraphIncIt> |
| 547 | 547 |
struct Constraints {
|
| 548 |
void constraints() {
|
|
| 549 |
checkConcept<GraphItem<_selector>, _GraphIncIt>(); |
|
| 550 |
_GraphIncIt it1(graph, node); |
|
| 551 |
_GraphIncIt it2; |
|
| 548 |
void constraints() {
|
|
| 549 |
checkConcept<GraphItem<_selector>, _GraphIncIt>(); |
|
| 550 |
_GraphIncIt it1(graph, node); |
|
| 551 |
_GraphIncIt it2; |
|
| 552 | 552 |
|
| 553 |
it2 = ++it1; |
|
| 554 |
++it2 = it1; |
|
| 555 |
++(++it1); |
|
| 556 |
_Item e = it1; |
|
| 557 |
|
|
| 553 |
it2 = ++it1; |
|
| 554 |
++it2 = it1; |
|
| 555 |
++(++it1); |
|
| 556 |
_Item e = it1; |
|
| 557 |
e = it2; |
|
| 558 | 558 |
|
| 559 |
|
|
| 559 |
} |
|
| 560 | 560 |
|
| 561 |
_Item arc; |
|
| 562 |
_Base node; |
|
| 563 |
_Graph graph; |
|
| 564 |
_GraphIncIt it; |
|
| 561 |
_Item arc; |
|
| 562 |
_Base node; |
|
| 563 |
_Graph graph; |
|
| 564 |
_GraphIncIt it; |
|
| 565 | 565 |
}; |
| 566 | 566 |
}; |
| 567 | 567 |
|
| 568 | 568 |
|
| 569 | 569 |
/// \brief An empty iterable digraph class. |
| 570 | 570 |
/// |
| 571 | 571 |
/// This class provides beside the core digraph features |
| 572 | 572 |
/// iterator based iterable interface for the digraph structure. |
| 573 | 573 |
/// This concept is part of the Digraph concept. |
| 574 | 574 |
template <typename _Base = BaseDigraphComponent> |
| 575 | 575 |
class IterableDigraphComponent : public _Base {
|
| 576 | 576 |
|
| 577 | 577 |
public: |
| 578 |
|
|
| 578 |
|
|
| 579 | 579 |
typedef _Base Base; |
| 580 | 580 |
typedef typename Base::Node Node; |
| 581 | 581 |
typedef typename Base::Arc Arc; |
| 582 | 582 |
|
| 583 | 583 |
typedef IterableDigraphComponent Digraph; |
| 584 | 584 |
|
| 585 | 585 |
/// \name Base iteration |
| 586 |
/// |
|
| 586 |
/// |
|
| 587 | 587 |
/// This interface provides functions for iteration on digraph items |
| 588 | 588 |
/// |
| 589 |
/// @{
|
|
| 589 |
/// @{
|
|
| 590 | 590 |
|
| 591 | 591 |
/// \brief Gives back the first node in the iterating order. |
| 592 |
/// |
|
| 592 |
/// |
|
| 593 | 593 |
/// Gives back the first node in the iterating order. |
| 594 |
/// |
|
| 594 |
/// |
|
| 595 | 595 |
void first(Node&) const {}
|
| 596 | 596 |
|
| 597 | 597 |
/// \brief Gives back the next node in the iterating order. |
| 598 | 598 |
/// |
| 599 | 599 |
/// Gives back the next node in the iterating order. |
| 600 |
/// |
|
| 600 |
/// |
|
| 601 | 601 |
void next(Node&) const {}
|
| 602 | 602 |
|
| 603 | 603 |
/// \brief Gives back the first arc in the iterating order. |
| 604 | 604 |
/// |
| 605 | 605 |
/// Gives back the first arc in the iterating order. |
| 606 |
/// |
|
| 606 |
/// |
|
| 607 | 607 |
void first(Arc&) const {}
|
| 608 | 608 |
|
| 609 | 609 |
/// \brief Gives back the next arc in the iterating order. |
| 610 | 610 |
/// |
| 611 | 611 |
/// Gives back the next arc in the iterating order. |
| 612 |
/// |
|
| 612 |
/// |
|
| 613 | 613 |
void next(Arc&) const {}
|
| 614 | 614 |
|
| 615 | 615 |
|
| 616 | 616 |
/// \brief Gives back the first of the arcs point to the given |
| 617 | 617 |
/// node. |
| 618 | 618 |
/// |
| 619 | 619 |
/// Gives back the first of the arcs point to the given node. |
| 620 |
/// |
|
| 620 |
/// |
|
| 621 | 621 |
void firstIn(Arc&, const Node&) const {}
|
| 622 | 622 |
|
| 623 | 623 |
/// \brief Gives back the next of the arcs points to the given |
| 624 | 624 |
/// node. |
| 625 | 625 |
/// |
| 626 | 626 |
/// Gives back the next of the arcs points to the given node. |
| 627 | 627 |
/// |
| 628 | 628 |
void nextIn(Arc&) const {}
|
| 629 | 629 |
|
| 630 | 630 |
/// \brief Gives back the first of the arcs start from the |
| 631 | 631 |
/// given node. |
| 632 |
/// |
|
| 632 |
/// |
|
| 633 | 633 |
/// Gives back the first of the arcs start from the given node. |
| 634 |
/// |
|
| 634 |
/// |
|
| 635 | 635 |
void firstOut(Arc&, const Node&) const {}
|
| 636 | 636 |
|
| 637 | 637 |
/// \brief Gives back the next of the arcs start from the given |
| 638 | 638 |
/// node. |
| 639 | 639 |
/// |
| 640 | 640 |
/// Gives back the next of the arcs start from the given node. |
| 641 |
/// |
|
| 641 |
/// |
|
| 642 | 642 |
void nextOut(Arc&) const {}
|
| 643 | 643 |
|
| 644 | 644 |
/// @} |
| 645 | 645 |
|
| 646 | 646 |
/// \name Class based iteration |
| 647 |
/// |
|
| 647 |
/// |
|
| 648 | 648 |
/// This interface provides functions for iteration on digraph items |
| 649 | 649 |
/// |
| 650 | 650 |
/// @{
|
| 651 | 651 |
|
| 652 | 652 |
/// \brief This iterator goes through each node. |
| 653 | 653 |
/// |
| 654 | 654 |
/// This iterator goes through each node. |
| 655 | 655 |
/// |
| 656 | 656 |
typedef GraphItemIt<Digraph, Node> NodeIt; |
| 657 | 657 |
|
| 658 | 658 |
/// \brief This iterator goes through each node. |
| 659 | 659 |
/// |
| 660 | 660 |
/// This iterator goes through each node. |
| 661 | 661 |
/// |
| 662 | 662 |
typedef GraphItemIt<Digraph, Arc> ArcIt; |
| 663 | 663 |
|
| ... | ... |
@@ -686,805 +686,805 @@ |
| 686 | 686 |
Node runningNode(const InArcIt&) const { return INVALID; }
|
| 687 | 687 |
|
| 688 | 688 |
/// \brief The base node of the iterator. |
| 689 | 689 |
/// |
| 690 | 690 |
/// Gives back the base node of the iterator. |
| 691 | 691 |
/// It is always the source of the pointed arc. |
| 692 | 692 |
Node baseNode(const OutArcIt&) const { return INVALID; }
|
| 693 | 693 |
|
| 694 | 694 |
/// \brief The running node of the iterator. |
| 695 | 695 |
/// |
| 696 | 696 |
/// Gives back the running node of the iterator. |
| 697 | 697 |
/// It is always the target of the pointed arc. |
| 698 | 698 |
Node runningNode(const OutArcIt&) const { return INVALID; }
|
| 699 | 699 |
|
| 700 | 700 |
/// @} |
| 701 | 701 |
|
| 702 |
template <typename _Digraph> |
|
| 702 |
template <typename _Digraph> |
|
| 703 | 703 |
struct Constraints {
|
| 704 |
void constraints() {
|
|
| 705 |
checkConcept<Base, _Digraph>(); |
|
| 704 |
void constraints() {
|
|
| 705 |
checkConcept<Base, _Digraph>(); |
|
| 706 | 706 |
|
| 707 | 707 |
{
|
| 708 |
typename _Digraph::Node node(INVALID); |
|
| 708 |
typename _Digraph::Node node(INVALID); |
|
| 709 | 709 |
typename _Digraph::Arc arc(INVALID); |
| 710 | 710 |
{
|
| 711 | 711 |
digraph.first(node); |
| 712 | 712 |
digraph.next(node); |
| 713 | 713 |
} |
| 714 | 714 |
{
|
| 715 | 715 |
digraph.first(arc); |
| 716 | 716 |
digraph.next(arc); |
| 717 | 717 |
} |
| 718 | 718 |
{
|
| 719 | 719 |
digraph.firstIn(arc, node); |
| 720 | 720 |
digraph.nextIn(arc); |
| 721 | 721 |
} |
| 722 | 722 |
{
|
| 723 | 723 |
digraph.firstOut(arc, node); |
| 724 | 724 |
digraph.nextOut(arc); |
| 725 | 725 |
} |
| 726 |
} |
|
| 726 |
} |
|
| 727 | 727 |
|
| 728 | 728 |
{
|
| 729 | 729 |
checkConcept<GraphItemIt<_Digraph, typename _Digraph::Arc>, |
| 730 | 730 |
typename _Digraph::ArcIt >(); |
| 731 | 731 |
checkConcept<GraphItemIt<_Digraph, typename _Digraph::Node>, |
| 732 | 732 |
typename _Digraph::NodeIt >(); |
| 733 |
checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc, |
|
| 733 |
checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc, |
|
| 734 | 734 |
typename _Digraph::Node, 'i'>, typename _Digraph::InArcIt>(); |
| 735 |
checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc, |
|
| 735 |
checkConcept<GraphIncIt<_Digraph, typename _Digraph::Arc, |
|
| 736 | 736 |
typename _Digraph::Node, 'o'>, typename _Digraph::OutArcIt>(); |
| 737 | 737 |
|
| 738 | 738 |
typename _Digraph::Node n; |
| 739 | 739 |
typename _Digraph::InArcIt ieit(INVALID); |
| 740 | 740 |
typename _Digraph::OutArcIt oeit(INVALID); |
| 741 | 741 |
n = digraph.baseNode(ieit); |
| 742 | 742 |
n = digraph.runningNode(ieit); |
| 743 | 743 |
n = digraph.baseNode(oeit); |
| 744 | 744 |
n = digraph.runningNode(oeit); |
| 745 | 745 |
ignore_unused_variable_warning(n); |
| 746 | 746 |
} |
| 747 | 747 |
} |
| 748 |
|
|
| 749 |
const _Digraph& digraph; |
|
| 750 |
|
|
| 748 |
|
|
| 749 |
const _Digraph& digraph; |
|
| 750 |
|
|
| 751 | 751 |
}; |
| 752 | 752 |
}; |
| 753 | 753 |
|
| 754 | 754 |
/// \brief An empty iterable undirected graph class. |
| 755 | 755 |
/// |
| 756 | 756 |
/// This class provides beside the core graph features iterator |
| 757 | 757 |
/// based iterable interface for the undirected graph structure. |
| 758 | 758 |
/// This concept is part of the Graph concept. |
| 759 | 759 |
template <typename _Base = BaseGraphComponent> |
| 760 | 760 |
class IterableGraphComponent : public IterableDigraphComponent<_Base> {
|
| 761 | 761 |
public: |
| 762 | 762 |
|
| 763 | 763 |
typedef _Base Base; |
| 764 | 764 |
typedef typename Base::Node Node; |
| 765 | 765 |
typedef typename Base::Arc Arc; |
| 766 | 766 |
typedef typename Base::Edge Edge; |
| 767 | 767 |
|
| 768 |
|
|
| 768 |
|
|
| 769 | 769 |
typedef IterableGraphComponent Graph; |
| 770 | 770 |
|
| 771 | 771 |
/// \name Base iteration |
| 772 |
/// |
|
| 772 |
/// |
|
| 773 | 773 |
/// This interface provides functions for iteration on graph items |
| 774 |
/// @{
|
|
| 774 |
/// @{
|
|
| 775 | 775 |
|
| 776 | 776 |
using IterableDigraphComponent<_Base>::first; |
| 777 | 777 |
using IterableDigraphComponent<_Base>::next; |
| 778 | 778 |
|
| 779 | 779 |
/// \brief Gives back the first edge in the iterating |
| 780 | 780 |
/// order. |
| 781 | 781 |
/// |
| 782 | 782 |
/// Gives back the first edge in the iterating order. |
| 783 |
/// |
|
| 783 |
/// |
|
| 784 | 784 |
void first(Edge&) const {}
|
| 785 | 785 |
|
| 786 | 786 |
/// \brief Gives back the next edge in the iterating |
| 787 | 787 |
/// order. |
| 788 | 788 |
/// |
| 789 | 789 |
/// Gives back the next edge in the iterating order. |
| 790 |
/// |
|
| 790 |
/// |
|
| 791 | 791 |
void next(Edge&) const {}
|
| 792 | 792 |
|
| 793 | 793 |
|
| 794 | 794 |
/// \brief Gives back the first of the edges from the |
| 795 | 795 |
/// given node. |
| 796 | 796 |
/// |
| 797 | 797 |
/// Gives back the first of the edges from the given |
| 798 | 798 |
/// node. The bool parameter gives back that direction which |
| 799 | 799 |
/// gives a good direction of the edge so the source of the |
| 800 | 800 |
/// directed arc is the given node. |
| 801 | 801 |
void firstInc(Edge&, bool&, const Node&) const {}
|
| 802 | 802 |
|
| 803 | 803 |
/// \brief Gives back the next of the edges from the |
| 804 | 804 |
/// given node. |
| 805 | 805 |
/// |
| 806 | 806 |
/// Gives back the next of the edges from the given |
| 807 | 807 |
/// node. The bool parameter should be used as the \c firstInc() |
| 808 | 808 |
/// use it. |
| 809 | 809 |
void nextInc(Edge&, bool&) const {}
|
| 810 | 810 |
|
| 811 | 811 |
using IterableDigraphComponent<_Base>::baseNode; |
| 812 | 812 |
using IterableDigraphComponent<_Base>::runningNode; |
| 813 | 813 |
|
| 814 | 814 |
/// @} |
| 815 | 815 |
|
| 816 | 816 |
/// \name Class based iteration |
| 817 |
/// |
|
| 817 |
/// |
|
| 818 | 818 |
/// This interface provides functions for iteration on graph items |
| 819 | 819 |
/// |
| 820 | 820 |
/// @{
|
| 821 | 821 |
|
| 822 | 822 |
/// \brief This iterator goes through each node. |
| 823 | 823 |
/// |
| 824 | 824 |
/// This iterator goes through each node. |
| 825 | 825 |
typedef GraphItemIt<Graph, Edge> EdgeIt; |
| 826 | 826 |
/// \brief This iterator goes trough the incident arcs of a |
| 827 | 827 |
/// node. |
| 828 | 828 |
/// |
| 829 | 829 |
/// This iterator goes trough the incident arcs of a certain |
| 830 | 830 |
/// node of a graph. |
| 831 | 831 |
typedef GraphIncIt<Graph, Edge, Node, 'u'> IncEdgeIt; |
| 832 | 832 |
/// \brief The base node of the iterator. |
| 833 | 833 |
/// |
| 834 | 834 |
/// Gives back the base node of the iterator. |
| 835 | 835 |
Node baseNode(const IncEdgeIt&) const { return INVALID; }
|
| 836 | 836 |
|
| 837 | 837 |
/// \brief The running node of the iterator. |
| 838 | 838 |
/// |
| 839 | 839 |
/// Gives back the running node of the iterator. |
| 840 | 840 |
Node runningNode(const IncEdgeIt&) const { return INVALID; }
|
| 841 | 841 |
|
| 842 | 842 |
/// @} |
| 843 | 843 |
|
| 844 |
template <typename _Graph> |
|
| 844 |
template <typename _Graph> |
|
| 845 | 845 |
struct Constraints {
|
| 846 |
void constraints() {
|
|
| 847 |
checkConcept<IterableDigraphComponent<Base>, _Graph>(); |
|
| 846 |
void constraints() {
|
|
| 847 |
checkConcept<IterableDigraphComponent<Base>, _Graph>(); |
|
| 848 | 848 |
|
| 849 | 849 |
{
|
| 850 | 850 |
typename _Graph::Node node(INVALID); |
| 851 | 851 |
typename _Graph::Edge edge(INVALID); |
| 852 | 852 |
bool dir; |
| 853 | 853 |
{
|
| 854 | 854 |
graph.first(edge); |
| 855 | 855 |
graph.next(edge); |
| 856 | 856 |
} |
| 857 | 857 |
{
|
| 858 | 858 |
graph.firstInc(edge, dir, node); |
| 859 | 859 |
graph.nextInc(edge, dir); |
| 860 | 860 |
} |
| 861 |
|
|
| 862 |
} |
|
| 863 |
|
|
| 861 |
|
|
| 862 |
} |
|
| 863 |
|
|
| 864 | 864 |
{
|
| 865 | 865 |
checkConcept<GraphItemIt<_Graph, typename _Graph::Edge>, |
| 866 | 866 |
typename _Graph::EdgeIt >(); |
| 867 |
checkConcept<GraphIncIt<_Graph, typename _Graph::Edge, |
|
| 867 |
checkConcept<GraphIncIt<_Graph, typename _Graph::Edge, |
|
| 868 | 868 |
typename _Graph::Node, 'u'>, typename _Graph::IncEdgeIt>(); |
| 869 |
|
|
| 869 |
|
|
| 870 | 870 |
typename _Graph::Node n; |
| 871 | 871 |
typename _Graph::IncEdgeIt ueit(INVALID); |
| 872 | 872 |
n = graph.baseNode(ueit); |
| 873 | 873 |
n = graph.runningNode(ueit); |
| 874 | 874 |
} |
| 875 | 875 |
} |
| 876 |
|
|
| 877 |
const _Graph& graph; |
|
| 878 |
|
|
| 876 |
|
|
| 877 |
const _Graph& graph; |
|
| 878 |
|
|
| 879 | 879 |
}; |
| 880 | 880 |
}; |
| 881 | 881 |
|
| 882 | 882 |
/// \brief An empty alteration notifier digraph class. |
| 883 |
/// |
|
| 883 |
/// |
|
| 884 | 884 |
/// This class provides beside the core digraph features alteration |
| 885 | 885 |
/// notifier interface for the digraph structure. This implements |
| 886 | 886 |
/// an observer-notifier pattern for each digraph item. More |
| 887 | 887 |
/// obsevers can be registered into the notifier and whenever an |
| 888 | 888 |
/// alteration occured in the digraph all the observers will |
| 889 | 889 |
/// notified about it. |
| 890 | 890 |
template <typename _Base = BaseDigraphComponent> |
| 891 | 891 |
class AlterableDigraphComponent : public _Base {
|
| 892 | 892 |
public: |
| 893 | 893 |
|
| 894 | 894 |
typedef _Base Base; |
| 895 | 895 |
typedef typename Base::Node Node; |
| 896 | 896 |
typedef typename Base::Arc Arc; |
| 897 | 897 |
|
| 898 | 898 |
|
| 899 | 899 |
/// The node observer registry. |
| 900 |
typedef AlterationNotifier<AlterableDigraphComponent, Node> |
|
| 900 |
typedef AlterationNotifier<AlterableDigraphComponent, Node> |
|
| 901 | 901 |
NodeNotifier; |
| 902 | 902 |
/// The arc observer registry. |
| 903 |
typedef AlterationNotifier<AlterableDigraphComponent, Arc> |
|
| 903 |
typedef AlterationNotifier<AlterableDigraphComponent, Arc> |
|
| 904 | 904 |
ArcNotifier; |
| 905 |
|
|
| 905 |
|
|
| 906 | 906 |
/// \brief Gives back the node alteration notifier. |
| 907 | 907 |
/// |
| 908 | 908 |
/// Gives back the node alteration notifier. |
| 909 | 909 |
NodeNotifier& notifier(Node) const {
|
| 910 |
|
|
| 910 |
return NodeNotifier(); |
|
| 911 | 911 |
} |
| 912 |
|
|
| 912 |
|
|
| 913 | 913 |
/// \brief Gives back the arc alteration notifier. |
| 914 | 914 |
/// |
| 915 | 915 |
/// Gives back the arc alteration notifier. |
| 916 | 916 |
ArcNotifier& notifier(Arc) const {
|
| 917 |
|
|
| 917 |
return ArcNotifier(); |
|
| 918 | 918 |
} |
| 919 | 919 |
|
| 920 |
template <typename _Digraph> |
|
| 920 |
template <typename _Digraph> |
|
| 921 | 921 |
struct Constraints {
|
| 922 |
void constraints() {
|
|
| 923 |
checkConcept<Base, _Digraph>(); |
|
| 924 |
|
|
| 922 |
void constraints() {
|
|
| 923 |
checkConcept<Base, _Digraph>(); |
|
| 924 |
typename _Digraph::NodeNotifier& nn |
|
| 925 | 925 |
= digraph.notifier(typename _Digraph::Node()); |
| 926 | 926 |
|
| 927 |
typename _Digraph::ArcNotifier& en |
|
| 927 |
typename _Digraph::ArcNotifier& en |
|
| 928 | 928 |
= digraph.notifier(typename _Digraph::Arc()); |
| 929 |
|
|
| 929 |
|
|
| 930 | 930 |
ignore_unused_variable_warning(nn); |
| 931 | 931 |
ignore_unused_variable_warning(en); |
| 932 |
} |
|
| 933 |
|
|
| 934 |
const _Digraph& digraph; |
|
| 935 |
|
|
| 932 |
} |
|
| 933 |
|
|
| 934 |
const _Digraph& digraph; |
|
| 935 |
|
|
| 936 | 936 |
}; |
| 937 |
|
|
| 937 |
|
|
| 938 | 938 |
}; |
| 939 | 939 |
|
| 940 | 940 |
/// \brief An empty alteration notifier undirected graph class. |
| 941 |
/// |
|
| 941 |
/// |
|
| 942 | 942 |
/// This class provides beside the core graph features alteration |
| 943 | 943 |
/// notifier interface for the graph structure. This implements |
| 944 | 944 |
/// an observer-notifier pattern for each graph item. More |
| 945 | 945 |
/// obsevers can be registered into the notifier and whenever an |
| 946 | 946 |
/// alteration occured in the graph all the observers will |
| 947 | 947 |
/// notified about it. |
| 948 | 948 |
template <typename _Base = BaseGraphComponent> |
| 949 | 949 |
class AlterableGraphComponent : public AlterableDigraphComponent<_Base> {
|
| 950 | 950 |
public: |
| 951 | 951 |
|
| 952 | 952 |
typedef _Base Base; |
| 953 | 953 |
typedef typename Base::Edge Edge; |
| 954 | 954 |
|
| 955 | 955 |
|
| 956 | 956 |
/// The arc observer registry. |
| 957 |
typedef AlterationNotifier<AlterableGraphComponent, Edge> |
|
| 957 |
typedef AlterationNotifier<AlterableGraphComponent, Edge> |
|
| 958 | 958 |
EdgeNotifier; |
| 959 |
|
|
| 959 |
|
|
| 960 | 960 |
/// \brief Gives back the arc alteration notifier. |
| 961 | 961 |
/// |
| 962 | 962 |
/// Gives back the arc alteration notifier. |
| 963 | 963 |
EdgeNotifier& notifier(Edge) const {
|
| 964 |
|
|
| 964 |
return EdgeNotifier(); |
|
| 965 | 965 |
} |
| 966 | 966 |
|
| 967 |
template <typename _Graph> |
|
| 967 |
template <typename _Graph> |
|
| 968 | 968 |
struct Constraints {
|
| 969 |
void constraints() {
|
|
| 970 |
checkConcept<AlterableGraphComponent<Base>, _Graph>(); |
|
| 971 |
|
|
| 969 |
void constraints() {
|
|
| 970 |
checkConcept<AlterableGraphComponent<Base>, _Graph>(); |
|
| 971 |
typename _Graph::EdgeNotifier& uen |
|
| 972 | 972 |
= graph.notifier(typename _Graph::Edge()); |
| 973 | 973 |
ignore_unused_variable_warning(uen); |
| 974 |
} |
|
| 975 |
|
|
| 976 |
const _Graph& graph; |
|
| 977 |
|
|
| 974 |
} |
|
| 975 |
|
|
| 976 |
const _Graph& graph; |
|
| 977 |
|
|
| 978 | 978 |
}; |
| 979 |
|
|
| 979 |
|
|
| 980 | 980 |
}; |
| 981 | 981 |
|
| 982 | 982 |
/// \brief Class describing the concept of graph maps |
| 983 |
/// |
|
| 983 |
/// |
|
| 984 | 984 |
/// This class describes the common interface of the graph maps |
| 985 | 985 |
/// (NodeMap, ArcMap), that is \ref maps-page "maps" which can be used to |
| 986 | 986 |
/// associate data to graph descriptors (nodes or arcs). |
| 987 | 987 |
template <typename _Graph, typename _Item, typename _Value> |
| 988 | 988 |
class GraphMap : public ReadWriteMap<_Item, _Value> {
|
| 989 | 989 |
public: |
| 990 | 990 |
|
| 991 | 991 |
typedef ReadWriteMap<_Item, _Value> Parent; |
| 992 | 992 |
|
| 993 | 993 |
/// The graph type of the map. |
| 994 | 994 |
typedef _Graph Graph; |
| 995 | 995 |
/// The key type of the map. |
| 996 | 996 |
typedef _Item Key; |
| 997 | 997 |
/// The value type of the map. |
| 998 | 998 |
typedef _Value Value; |
| 999 | 999 |
|
| 1000 | 1000 |
/// \brief Construct a new map. |
| 1001 | 1001 |
/// |
| 1002 | 1002 |
/// Construct a new map for the graph. |
| 1003 | 1003 |
explicit GraphMap(const Graph&) {}
|
| 1004 | 1004 |
/// \brief Construct a new map with default value. |
| 1005 | 1005 |
/// |
| 1006 | 1006 |
/// Construct a new map for the graph and initalise the values. |
| 1007 | 1007 |
GraphMap(const Graph&, const Value&) {}
|
| 1008 | 1008 |
/// \brief Copy constructor. |
| 1009 | 1009 |
/// |
| 1010 | 1010 |
/// Copy Constructor. |
| 1011 | 1011 |
GraphMap(const GraphMap&) : Parent() {}
|
| 1012 |
|
|
| 1012 |
|
|
| 1013 | 1013 |
/// \brief Assign operator. |
| 1014 | 1014 |
/// |
| 1015 | 1015 |
/// Assign operator. It does not mofify the underlying graph, |
| 1016 | 1016 |
/// it just iterates on the current item set and set the map |
| 1017 |
/// with the value returned by the assigned map. |
|
| 1017 |
/// with the value returned by the assigned map. |
|
| 1018 | 1018 |
template <typename CMap> |
| 1019 |
GraphMap& operator=(const CMap&) {
|
|
| 1019 |
GraphMap& operator=(const CMap&) {
|
|
| 1020 | 1020 |
checkConcept<ReadMap<Key, Value>, CMap>(); |
| 1021 | 1021 |
return *this; |
| 1022 | 1022 |
} |
| 1023 | 1023 |
|
| 1024 | 1024 |
template<typename _Map> |
| 1025 | 1025 |
struct Constraints {
|
| 1026 |
void constraints() {
|
|
| 1027 |
checkConcept<ReadWriteMap<Key, Value>, _Map >(); |
|
| 1028 |
// Construction with a graph parameter |
|
| 1029 |
_Map a(g); |
|
| 1030 |
// Constructor with a graph and a default value parameter |
|
| 1031 |
_Map a2(g,t); |
|
| 1032 |
// Copy constructor. |
|
| 1033 |
_Map b(c); |
|
| 1034 |
|
|
| 1026 |
void constraints() {
|
|
| 1027 |
checkConcept<ReadWriteMap<Key, Value>, _Map >(); |
|
| 1028 |
// Construction with a graph parameter |
|
| 1029 |
_Map a(g); |
|
| 1030 |
// Constructor with a graph and a default value parameter |
|
| 1031 |
_Map a2(g,t); |
|
| 1032 |
// Copy constructor. |
|
| 1033 |
_Map b(c); |
|
| 1034 |
|
|
| 1035 | 1035 |
ReadMap<Key, Value> cmap; |
| 1036 | 1036 |
b = cmap; |
| 1037 | 1037 |
|
| 1038 |
ignore_unused_variable_warning(a2); |
|
| 1039 |
ignore_unused_variable_warning(b); |
|
| 1040 |
|
|
| 1038 |
ignore_unused_variable_warning(a2); |
|
| 1039 |
ignore_unused_variable_warning(b); |
|
| 1040 |
} |
|
| 1041 | 1041 |
|
| 1042 |
const _Map &c; |
|
| 1043 |
const Graph &g; |
|
| 1044 |
|
|
| 1042 |
const _Map &c; |
|
| 1043 |
const Graph &g; |
|
| 1044 |
const typename GraphMap::Value &t; |
|
| 1045 | 1045 |
}; |
| 1046 | 1046 |
|
| 1047 | 1047 |
}; |
| 1048 | 1048 |
|
| 1049 | 1049 |
/// \brief An empty mappable digraph class. |
| 1050 | 1050 |
/// |
| 1051 | 1051 |
/// This class provides beside the core digraph features |
| 1052 | 1052 |
/// map interface for the digraph structure. |
| 1053 | 1053 |
/// This concept is part of the Digraph concept. |
| 1054 | 1054 |
template <typename _Base = BaseDigraphComponent> |
| 1055 | 1055 |
class MappableDigraphComponent : public _Base {
|
| 1056 | 1056 |
public: |
| 1057 | 1057 |
|
| 1058 | 1058 |
typedef _Base Base; |
| 1059 | 1059 |
typedef typename Base::Node Node; |
| 1060 | 1060 |
typedef typename Base::Arc Arc; |
| 1061 | 1061 |
|
| 1062 | 1062 |
typedef MappableDigraphComponent Digraph; |
| 1063 | 1063 |
|
| 1064 | 1064 |
/// \brief ReadWrite map of the nodes. |
| 1065 | 1065 |
/// |
| 1066 | 1066 |
/// ReadWrite map of the nodes. |
| 1067 | 1067 |
/// |
| 1068 | 1068 |
template <typename _Value> |
| 1069 | 1069 |
class NodeMap : public GraphMap<Digraph, Node, _Value> {
|
| 1070 | 1070 |
public: |
| 1071 | 1071 |
typedef GraphMap<MappableDigraphComponent, Node, _Value> Parent; |
| 1072 | 1072 |
|
| 1073 |
/// \brief Construct a new map. |
|
| 1074 |
/// |
|
| 1075 |
/// Construct a new map for the digraph. |
|
| 1076 |
explicit NodeMap(const MappableDigraphComponent& digraph) |
|
| 1073 |
/// \brief Construct a new map. |
|
| 1074 |
/// |
|
| 1075 |
/// Construct a new map for the digraph. |
|
| 1076 |
explicit NodeMap(const MappableDigraphComponent& digraph) |
|
| 1077 | 1077 |
: Parent(digraph) {}
|
| 1078 | 1078 |
|
| 1079 |
/// \brief Construct a new map with default value. |
|
| 1080 |
/// |
|
| 1081 |
/// Construct a new map for the digraph and initalise the values. |
|
| 1082 |
NodeMap(const MappableDigraphComponent& digraph, const _Value& value) |
|
| 1079 |
/// \brief Construct a new map with default value. |
|
| 1080 |
/// |
|
| 1081 |
/// Construct a new map for the digraph and initalise the values. |
|
| 1082 |
NodeMap(const MappableDigraphComponent& digraph, const _Value& value) |
|
| 1083 | 1083 |
: Parent(digraph, value) {}
|
| 1084 | 1084 |
|
| 1085 |
/// \brief Copy constructor. |
|
| 1086 |
/// |
|
| 1087 |
/// Copy Constructor. |
|
| 1088 |
NodeMap(const NodeMap& nm) : Parent(nm) {}
|
|
| 1085 |
/// \brief Copy constructor. |
|
| 1086 |
/// |
|
| 1087 |
/// Copy Constructor. |
|
| 1088 |
NodeMap(const NodeMap& nm) : Parent(nm) {}
|
|
| 1089 | 1089 |
|
| 1090 |
/// \brief Assign operator. |
|
| 1091 |
/// |
|
| 1092 |
|
|
| 1090 |
/// \brief Assign operator. |
|
| 1091 |
/// |
|
| 1092 |
/// Assign operator. |
|
| 1093 | 1093 |
template <typename CMap> |
| 1094 |
NodeMap& operator=(const CMap&) {
|
|
| 1094 |
NodeMap& operator=(const CMap&) {
|
|
| 1095 | 1095 |
checkConcept<ReadMap<Node, _Value>, CMap>(); |
| 1096 | 1096 |
return *this; |
| 1097 | 1097 |
} |
| 1098 | 1098 |
|
| 1099 | 1099 |
}; |
| 1100 | 1100 |
|
| 1101 | 1101 |
/// \brief ReadWrite map of the arcs. |
| 1102 | 1102 |
/// |
| 1103 | 1103 |
/// ReadWrite map of the arcs. |
| 1104 | 1104 |
/// |
| 1105 | 1105 |
template <typename _Value> |
| 1106 | 1106 |
class ArcMap : public GraphMap<Digraph, Arc, _Value> {
|
| 1107 | 1107 |
public: |
| 1108 | 1108 |
typedef GraphMap<MappableDigraphComponent, Arc, _Value> Parent; |
| 1109 | 1109 |
|
| 1110 |
/// \brief Construct a new map. |
|
| 1111 |
/// |
|
| 1112 |
/// Construct a new map for the digraph. |
|
| 1113 |
explicit ArcMap(const MappableDigraphComponent& digraph) |
|
| 1110 |
/// \brief Construct a new map. |
|
| 1111 |
/// |
|
| 1112 |
/// Construct a new map for the digraph. |
|
| 1113 |
explicit ArcMap(const MappableDigraphComponent& digraph) |
|
| 1114 | 1114 |
: Parent(digraph) {}
|
| 1115 | 1115 |
|
| 1116 |
/// \brief Construct a new map with default value. |
|
| 1117 |
/// |
|
| 1118 |
/// Construct a new map for the digraph and initalise the values. |
|
| 1119 |
ArcMap(const MappableDigraphComponent& digraph, const _Value& value) |
|
| 1116 |
/// \brief Construct a new map with default value. |
|
| 1117 |
/// |
|
| 1118 |
/// Construct a new map for the digraph and initalise the values. |
|
| 1119 |
ArcMap(const MappableDigraphComponent& digraph, const _Value& value) |
|
| 1120 | 1120 |
: Parent(digraph, value) {}
|
| 1121 | 1121 |
|
| 1122 |
/// \brief Copy constructor. |
|
| 1123 |
/// |
|
| 1124 |
/// Copy Constructor. |
|
| 1125 |
ArcMap(const ArcMap& nm) : Parent(nm) {}
|
|
| 1122 |
/// \brief Copy constructor. |
|
| 1123 |
/// |
|
| 1124 |
/// Copy Constructor. |
|
| 1125 |
ArcMap(const ArcMap& nm) : Parent(nm) {}
|
|
| 1126 | 1126 |
|
| 1127 |
/// \brief Assign operator. |
|
| 1128 |
/// |
|
| 1129 |
|
|
| 1127 |
/// \brief Assign operator. |
|
| 1128 |
/// |
|
| 1129 |
/// Assign operator. |
|
| 1130 | 1130 |
template <typename CMap> |
| 1131 |
ArcMap& operator=(const CMap&) {
|
|
| 1131 |
ArcMap& operator=(const CMap&) {
|
|
| 1132 | 1132 |
checkConcept<ReadMap<Arc, _Value>, CMap>(); |
| 1133 | 1133 |
return *this; |
| 1134 | 1134 |
} |
| 1135 | 1135 |
|
| 1136 | 1136 |
}; |
| 1137 | 1137 |
|
| 1138 | 1138 |
|
| 1139 | 1139 |
template <typename _Digraph> |
| 1140 | 1140 |
struct Constraints {
|
| 1141 | 1141 |
|
| 1142 |
struct Dummy {
|
|
| 1143 |
int value; |
|
| 1144 |
Dummy() : value(0) {}
|
|
| 1145 |
Dummy(int _v) : value(_v) {}
|
|
| 1146 |
|
|
| 1142 |
struct Dummy {
|
|
| 1143 |
int value; |
|
| 1144 |
Dummy() : value(0) {}
|
|
| 1145 |
Dummy(int _v) : value(_v) {}
|
|
| 1146 |
}; |
|
| 1147 | 1147 |
|
| 1148 |
void constraints() {
|
|
| 1149 |
checkConcept<Base, _Digraph>(); |
|
| 1150 |
{ // int map test
|
|
| 1151 |
typedef typename _Digraph::template NodeMap<int> IntNodeMap; |
|
| 1152 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, int>, |
|
| 1153 |
IntNodeMap >(); |
|
| 1154 |
} { // bool map test
|
|
| 1155 |
typedef typename _Digraph::template NodeMap<bool> BoolNodeMap; |
|
| 1156 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, bool>, |
|
| 1157 |
BoolNodeMap >(); |
|
| 1158 |
} { // Dummy map test
|
|
| 1159 |
typedef typename _Digraph::template NodeMap<Dummy> DummyNodeMap; |
|
| 1160 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, Dummy>, |
|
| 1161 |
DummyNodeMap >(); |
|
| 1162 |
|
|
| 1148 |
void constraints() {
|
|
| 1149 |
checkConcept<Base, _Digraph>(); |
|
| 1150 |
{ // int map test
|
|
| 1151 |
typedef typename _Digraph::template NodeMap<int> IntNodeMap; |
|
| 1152 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, int>, |
|
| 1153 |
IntNodeMap >(); |
|
| 1154 |
} { // bool map test
|
|
| 1155 |
typedef typename _Digraph::template NodeMap<bool> BoolNodeMap; |
|
| 1156 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, bool>, |
|
| 1157 |
BoolNodeMap >(); |
|
| 1158 |
} { // Dummy map test
|
|
| 1159 |
typedef typename _Digraph::template NodeMap<Dummy> DummyNodeMap; |
|
| 1160 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Node, Dummy>, |
|
| 1161 |
DummyNodeMap >(); |
|
| 1162 |
} |
|
| 1163 | 1163 |
|
| 1164 |
{ // int map test
|
|
| 1165 |
typedef typename _Digraph::template ArcMap<int> IntArcMap; |
|
| 1166 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, int>, |
|
| 1167 |
IntArcMap >(); |
|
| 1168 |
} { // bool map test
|
|
| 1169 |
typedef typename _Digraph::template ArcMap<bool> BoolArcMap; |
|
| 1170 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, bool>, |
|
| 1171 |
BoolArcMap >(); |
|
| 1172 |
} { // Dummy map test
|
|
| 1173 |
typedef typename _Digraph::template ArcMap<Dummy> DummyArcMap; |
|
| 1174 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, Dummy>, |
|
| 1175 |
DummyArcMap >(); |
|
| 1176 |
} |
|
| 1177 |
} |
|
| 1164 |
{ // int map test
|
|
| 1165 |
typedef typename _Digraph::template ArcMap<int> IntArcMap; |
|
| 1166 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, int>, |
|
| 1167 |
IntArcMap >(); |
|
| 1168 |
} { // bool map test
|
|
| 1169 |
typedef typename _Digraph::template ArcMap<bool> BoolArcMap; |
|
| 1170 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, bool>, |
|
| 1171 |
BoolArcMap >(); |
|
| 1172 |
} { // Dummy map test
|
|
| 1173 |
typedef typename _Digraph::template ArcMap<Dummy> DummyArcMap; |
|
| 1174 |
checkConcept<GraphMap<_Digraph, typename _Digraph::Arc, Dummy>, |
|
| 1175 |
DummyArcMap >(); |
|
| 1176 |
} |
|
| 1177 |
} |
|
| 1178 | 1178 |
|
| 1179 |
|
|
| 1179 |
_Digraph& digraph; |
|
| 1180 | 1180 |
}; |
| 1181 | 1181 |
}; |
| 1182 | 1182 |
|
| 1183 | 1183 |
/// \brief An empty mappable base bipartite graph class. |
| 1184 | 1184 |
/// |
| 1185 | 1185 |
/// This class provides beside the core graph features |
| 1186 | 1186 |
/// map interface for the graph structure. |
| 1187 | 1187 |
/// This concept is part of the Graph concept. |
| 1188 | 1188 |
template <typename _Base = BaseGraphComponent> |
| 1189 | 1189 |
class MappableGraphComponent : public MappableDigraphComponent<_Base> {
|
| 1190 | 1190 |
public: |
| 1191 | 1191 |
|
| 1192 | 1192 |
typedef _Base Base; |
| 1193 | 1193 |
typedef typename Base::Edge Edge; |
| 1194 | 1194 |
|
| 1195 | 1195 |
typedef MappableGraphComponent Graph; |
| 1196 | 1196 |
|
| 1197 | 1197 |
/// \brief ReadWrite map of the edges. |
| 1198 | 1198 |
/// |
| 1199 | 1199 |
/// ReadWrite map of the edges. |
| 1200 | 1200 |
/// |
| 1201 | 1201 |
template <typename _Value> |
| 1202 |
class EdgeMap : public GraphMap<Graph, Edge, _Value> {
|
|
| 1202 |
class EdgeMap : public GraphMap<Graph, Edge, _Value> {
|
|
| 1203 | 1203 |
public: |
| 1204 | 1204 |
typedef GraphMap<MappableGraphComponent, Edge, _Value> Parent; |
| 1205 | 1205 |
|
| 1206 |
/// \brief Construct a new map. |
|
| 1207 |
/// |
|
| 1208 |
/// Construct a new map for the graph. |
|
| 1209 |
explicit EdgeMap(const MappableGraphComponent& graph) |
|
| 1206 |
/// \brief Construct a new map. |
|
| 1207 |
/// |
|
| 1208 |
/// Construct a new map for the graph. |
|
| 1209 |
explicit EdgeMap(const MappableGraphComponent& graph) |
|
| 1210 | 1210 |
: Parent(graph) {}
|
| 1211 | 1211 |
|
| 1212 |
/// \brief Construct a new map with default value. |
|
| 1213 |
/// |
|
| 1214 |
/// Construct a new map for the graph and initalise the values. |
|
| 1215 |
EdgeMap(const MappableGraphComponent& graph, const _Value& value) |
|
| 1212 |
/// \brief Construct a new map with default value. |
|
| 1213 |
/// |
|
| 1214 |
/// Construct a new map for the graph and initalise the values. |
|
| 1215 |
EdgeMap(const MappableGraphComponent& graph, const _Value& value) |
|
| 1216 | 1216 |
: Parent(graph, value) {}
|
| 1217 | 1217 |
|
| 1218 |
/// \brief Copy constructor. |
|
| 1219 |
/// |
|
| 1220 |
/// Copy Constructor. |
|
| 1221 |
EdgeMap(const EdgeMap& nm) : Parent(nm) {}
|
|
| 1218 |
/// \brief Copy constructor. |
|
| 1219 |
/// |
|
| 1220 |
/// Copy Constructor. |
|
| 1221 |
EdgeMap(const EdgeMap& nm) : Parent(nm) {}
|
|
| 1222 | 1222 |
|
| 1223 |
/// \brief Assign operator. |
|
| 1224 |
/// |
|
| 1225 |
|
|
| 1223 |
/// \brief Assign operator. |
|
| 1224 |
/// |
|
| 1225 |
/// Assign operator. |
|
| 1226 | 1226 |
template <typename CMap> |
| 1227 |
EdgeMap& operator=(const CMap&) {
|
|
| 1227 |
EdgeMap& operator=(const CMap&) {
|
|
| 1228 | 1228 |
checkConcept<ReadMap<Edge, _Value>, CMap>(); |
| 1229 | 1229 |
return *this; |
| 1230 | 1230 |
} |
| 1231 | 1231 |
|
| 1232 | 1232 |
}; |
| 1233 | 1233 |
|
| 1234 | 1234 |
|
| 1235 | 1235 |
template <typename _Graph> |
| 1236 | 1236 |
struct Constraints {
|
| 1237 | 1237 |
|
| 1238 |
struct Dummy {
|
|
| 1239 |
int value; |
|
| 1240 |
Dummy() : value(0) {}
|
|
| 1241 |
Dummy(int _v) : value(_v) {}
|
|
| 1242 |
|
|
| 1238 |
struct Dummy {
|
|
| 1239 |
int value; |
|
| 1240 |
Dummy() : value(0) {}
|
|
| 1241 |
Dummy(int _v) : value(_v) {}
|
|
| 1242 |
}; |
|
| 1243 | 1243 |
|
| 1244 |
void constraints() {
|
|
| 1245 |
checkConcept<MappableGraphComponent<Base>, _Graph>(); |
|
| 1244 |
void constraints() {
|
|
| 1245 |
checkConcept<MappableGraphComponent<Base>, _Graph>(); |
|
| 1246 | 1246 |
|
| 1247 |
{ // int map test
|
|
| 1248 |
typedef typename _Graph::template EdgeMap<int> IntEdgeMap; |
|
| 1249 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, int>, |
|
| 1250 |
IntEdgeMap >(); |
|
| 1251 |
} { // bool map test
|
|
| 1252 |
typedef typename _Graph::template EdgeMap<bool> BoolEdgeMap; |
|
| 1253 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, bool>, |
|
| 1254 |
BoolEdgeMap >(); |
|
| 1255 |
} { // Dummy map test
|
|
| 1256 |
typedef typename _Graph::template EdgeMap<Dummy> DummyEdgeMap; |
|
| 1257 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, Dummy>, |
|
| 1258 |
DummyEdgeMap >(); |
|
| 1259 |
} |
|
| 1260 |
} |
|
| 1247 |
{ // int map test
|
|
| 1248 |
typedef typename _Graph::template EdgeMap<int> IntEdgeMap; |
|
| 1249 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, int>, |
|
| 1250 |
IntEdgeMap >(); |
|
| 1251 |
} { // bool map test
|
|
| 1252 |
typedef typename _Graph::template EdgeMap<bool> BoolEdgeMap; |
|
| 1253 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, bool>, |
|
| 1254 |
BoolEdgeMap >(); |
|
| 1255 |
} { // Dummy map test
|
|
| 1256 |
typedef typename _Graph::template EdgeMap<Dummy> DummyEdgeMap; |
|
| 1257 |
checkConcept<GraphMap<_Graph, typename _Graph::Edge, Dummy>, |
|
| 1258 |
DummyEdgeMap >(); |
|
| 1259 |
} |
|
| 1260 |
} |
|
| 1261 | 1261 |
|
| 1262 |
|
|
| 1262 |
_Graph& graph; |
|
| 1263 | 1263 |
}; |
| 1264 | 1264 |
}; |
| 1265 | 1265 |
|
| 1266 | 1266 |
/// \brief An empty extendable digraph class. |
| 1267 | 1267 |
/// |
| 1268 | 1268 |
/// This class provides beside the core digraph features digraph |
| 1269 | 1269 |
/// extendable interface for the digraph structure. The main |
| 1270 | 1270 |
/// difference between the base and this interface is that the |
| 1271 | 1271 |
/// digraph alterations should handled already on this level. |
| 1272 | 1272 |
template <typename _Base = BaseDigraphComponent> |
| 1273 | 1273 |
class ExtendableDigraphComponent : public _Base {
|
| 1274 | 1274 |
public: |
| 1275 | 1275 |
typedef _Base Base; |
| 1276 | 1276 |
|
| 1277 | 1277 |
typedef typename _Base::Node Node; |
| 1278 | 1278 |
typedef typename _Base::Arc Arc; |
| 1279 | 1279 |
|
| 1280 | 1280 |
/// \brief Adds a new node to the digraph. |
| 1281 | 1281 |
/// |
| 1282 | 1282 |
/// Adds a new node to the digraph. |
| 1283 | 1283 |
/// |
| 1284 | 1284 |
Node addNode() {
|
| 1285 |
|
|
| 1285 |
return INVALID; |
|
| 1286 | 1286 |
} |
| 1287 |
|
|
| 1287 |
|
|
| 1288 | 1288 |
/// \brief Adds a new arc connects the given two nodes. |
| 1289 | 1289 |
/// |
| 1290 | 1290 |
/// Adds a new arc connects the the given two nodes. |
| 1291 | 1291 |
Arc addArc(const Node&, const Node&) {
|
| 1292 |
|
|
| 1292 |
return INVALID; |
|
| 1293 | 1293 |
} |
| 1294 | 1294 |
|
| 1295 | 1295 |
template <typename _Digraph> |
| 1296 | 1296 |
struct Constraints {
|
| 1297 |
|
|
| 1297 |
void constraints() {
|
|
| 1298 | 1298 |
checkConcept<Base, _Digraph>(); |
| 1299 |
typename _Digraph::Node node_a, node_b; |
|
| 1300 |
node_a = digraph.addNode(); |
|
| 1301 |
node_b = digraph.addNode(); |
|
| 1302 |
typename _Digraph::Arc arc; |
|
| 1303 |
arc = digraph.addArc(node_a, node_b); |
|
| 1304 |
} |
|
| 1299 |
typename _Digraph::Node node_a, node_b; |
|
| 1300 |
node_a = digraph.addNode(); |
|
| 1301 |
node_b = digraph.addNode(); |
|
| 1302 |
typename _Digraph::Arc arc; |
|
| 1303 |
arc = digraph.addArc(node_a, node_b); |
|
| 1304 |
} |
|
| 1305 | 1305 |
|
| 1306 |
|
|
| 1306 |
_Digraph& digraph; |
|
| 1307 | 1307 |
}; |
| 1308 | 1308 |
}; |
| 1309 | 1309 |
|
| 1310 | 1310 |
/// \brief An empty extendable base undirected graph class. |
| 1311 | 1311 |
/// |
| 1312 | 1312 |
/// This class provides beside the core undirected graph features |
| 1313 | 1313 |
/// core undircted graph extend interface for the graph structure. |
| 1314 | 1314 |
/// The main difference between the base and this interface is |
| 1315 | 1315 |
/// that the graph alterations should handled already on this |
| 1316 | 1316 |
/// level. |
| 1317 | 1317 |
template <typename _Base = BaseGraphComponent> |
| 1318 | 1318 |
class ExtendableGraphComponent : public _Base {
|
| 1319 | 1319 |
public: |
| 1320 | 1320 |
|
| 1321 | 1321 |
typedef _Base Base; |
| 1322 | 1322 |
typedef typename _Base::Node Node; |
| 1323 | 1323 |
typedef typename _Base::Edge Edge; |
| 1324 | 1324 |
|
| 1325 | 1325 |
/// \brief Adds a new node to the graph. |
| 1326 | 1326 |
/// |
| 1327 | 1327 |
/// Adds a new node to the graph. |
| 1328 | 1328 |
/// |
| 1329 | 1329 |
Node addNode() {
|
| 1330 |
|
|
| 1330 |
return INVALID; |
|
| 1331 | 1331 |
} |
| 1332 |
|
|
| 1332 |
|
|
| 1333 | 1333 |
/// \brief Adds a new arc connects the given two nodes. |
| 1334 | 1334 |
/// |
| 1335 | 1335 |
/// Adds a new arc connects the the given two nodes. |
| 1336 | 1336 |
Edge addArc(const Node&, const Node&) {
|
| 1337 |
|
|
| 1337 |
return INVALID; |
|
| 1338 | 1338 |
} |
| 1339 | 1339 |
|
| 1340 | 1340 |
template <typename _Graph> |
| 1341 | 1341 |
struct Constraints {
|
| 1342 |
void constraints() {
|
|
| 1343 |
checkConcept<Base, _Graph>(); |
|
| 1344 |
typename _Graph::Node node_a, node_b; |
|
| 1345 |
node_a = graph.addNode(); |
|
| 1346 |
node_b = graph.addNode(); |
|
| 1347 |
typename _Graph::Edge edge; |
|
| 1348 |
edge = graph.addEdge(node_a, node_b); |
|
| 1349 |
} |
|
| 1342 |
void constraints() {
|
|
| 1343 |
checkConcept<Base, _Graph>(); |
|
| 1344 |
typename _Graph::Node node_a, node_b; |
|
| 1345 |
node_a = graph.addNode(); |
|
| 1346 |
node_b = graph.addNode(); |
|
| 1347 |
typename _Graph::Edge edge; |
|
| 1348 |
edge = graph.addEdge(node_a, node_b); |
|
| 1349 |
} |
|
| 1350 | 1350 |
|
| 1351 |
|
|
| 1351 |
_Graph& graph; |
|
| 1352 | 1352 |
}; |
| 1353 | 1353 |
}; |
| 1354 | 1354 |
|
| 1355 | 1355 |
/// \brief An empty erasable digraph class. |
| 1356 |
/// |
|
| 1356 |
/// |
|
| 1357 | 1357 |
/// This class provides beside the core digraph features core erase |
| 1358 | 1358 |
/// functions for the digraph structure. The main difference between |
| 1359 | 1359 |
/// the base and this interface is that the digraph alterations |
| 1360 | 1360 |
/// should handled already on this level. |
| 1361 | 1361 |
template <typename _Base = BaseDigraphComponent> |
| 1362 | 1362 |
class ErasableDigraphComponent : public _Base {
|
| 1363 | 1363 |
public: |
| 1364 | 1364 |
|
| 1365 | 1365 |
typedef _Base Base; |
| 1366 | 1366 |
typedef typename Base::Node Node; |
| 1367 | 1367 |
typedef typename Base::Arc Arc; |
| 1368 | 1368 |
|
| 1369 | 1369 |
/// \brief Erase a node from the digraph. |
| 1370 | 1370 |
/// |
| 1371 |
/// Erase a node from the digraph. This function should |
|
| 1371 |
/// Erase a node from the digraph. This function should |
|
| 1372 | 1372 |
/// erase all arcs connecting to the node. |
| 1373 |
void erase(const Node&) {}
|
|
| 1373 |
void erase(const Node&) {}
|
|
| 1374 | 1374 |
|
| 1375 | 1375 |
/// \brief Erase an arc from the digraph. |
| 1376 | 1376 |
/// |
| 1377 | 1377 |
/// Erase an arc from the digraph. |
| 1378 | 1378 |
/// |
| 1379 | 1379 |
void erase(const Arc&) {}
|
| 1380 | 1380 |
|
| 1381 | 1381 |
template <typename _Digraph> |
| 1382 | 1382 |
struct Constraints {
|
| 1383 |
|
|
| 1383 |
void constraints() {
|
|
| 1384 | 1384 |
checkConcept<Base, _Digraph>(); |
| 1385 |
typename _Digraph::Node node; |
|
| 1386 |
digraph.erase(node); |
|
| 1387 |
typename _Digraph::Arc arc; |
|
| 1388 |
digraph.erase(arc); |
|
| 1389 |
|
|
| 1385 |
typename _Digraph::Node node; |
|
| 1386 |
digraph.erase(node); |
|
| 1387 |
typename _Digraph::Arc arc; |
|
| 1388 |
digraph.erase(arc); |
|
| 1389 |
} |
|
| 1390 | 1390 |
|
| 1391 |
|
|
| 1391 |
_Digraph& digraph; |
|
| 1392 | 1392 |
}; |
| 1393 | 1393 |
}; |
| 1394 | 1394 |
|
| 1395 | 1395 |
/// \brief An empty erasable base undirected graph class. |
| 1396 |
/// |
|
| 1396 |
/// |
|
| 1397 | 1397 |
/// This class provides beside the core undirected graph features |
| 1398 | 1398 |
/// core erase functions for the undirceted graph structure. The |
| 1399 | 1399 |
/// main difference between the base and this interface is that |
| 1400 | 1400 |
/// the graph alterations should handled already on this level. |
| 1401 | 1401 |
template <typename _Base = BaseGraphComponent> |
| 1402 | 1402 |
class ErasableGraphComponent : public _Base {
|
| 1403 | 1403 |
public: |
| 1404 | 1404 |
|
| 1405 | 1405 |
typedef _Base Base; |
| 1406 | 1406 |
typedef typename Base::Node Node; |
| 1407 | 1407 |
typedef typename Base::Edge Edge; |
| 1408 | 1408 |
|
| 1409 | 1409 |
/// \brief Erase a node from the graph. |
| 1410 | 1410 |
/// |
| 1411 | 1411 |
/// Erase a node from the graph. This function should erase |
| 1412 | 1412 |
/// arcs connecting to the node. |
| 1413 |
void erase(const Node&) {}
|
|
| 1413 |
void erase(const Node&) {}
|
|
| 1414 | 1414 |
|
| 1415 | 1415 |
/// \brief Erase an arc from the graph. |
| 1416 | 1416 |
/// |
| 1417 | 1417 |
/// Erase an arc from the graph. |
| 1418 | 1418 |
/// |
| 1419 | 1419 |
void erase(const Edge&) {}
|
| 1420 | 1420 |
|
| 1421 | 1421 |
template <typename _Graph> |
| 1422 | 1422 |
struct Constraints {
|
| 1423 |
|
|
| 1423 |
void constraints() {
|
|
| 1424 | 1424 |
checkConcept<Base, _Graph>(); |
| 1425 |
typename _Graph::Node node; |
|
| 1426 |
graph.erase(node); |
|
| 1427 |
typename _Graph::Edge edge; |
|
| 1428 |
graph.erase(edge); |
|
| 1429 |
|
|
| 1425 |
typename _Graph::Node node; |
|
| 1426 |
graph.erase(node); |
|
| 1427 |
typename _Graph::Edge edge; |
|
| 1428 |
graph.erase(edge); |
|
| 1429 |
} |
|
| 1430 | 1430 |
|
| 1431 |
|
|
| 1431 |
_Graph& graph; |
|
| 1432 | 1432 |
}; |
| 1433 | 1433 |
}; |
| 1434 | 1434 |
|
| 1435 | 1435 |
/// \brief An empty clearable base digraph class. |
| 1436 | 1436 |
/// |
| 1437 | 1437 |
/// This class provides beside the core digraph features core clear |
| 1438 | 1438 |
/// functions for the digraph structure. The main difference between |
| 1439 | 1439 |
/// the base and this interface is that the digraph alterations |
| 1440 | 1440 |
/// should handled already on this level. |
| 1441 | 1441 |
template <typename _Base = BaseDigraphComponent> |
| 1442 | 1442 |
class ClearableDigraphComponent : public _Base {
|
| 1443 | 1443 |
public: |
| 1444 | 1444 |
|
| 1445 | 1445 |
typedef _Base Base; |
| 1446 | 1446 |
|
| 1447 | 1447 |
/// \brief Erase all nodes and arcs from the digraph. |
| 1448 | 1448 |
/// |
| 1449 | 1449 |
/// Erase all nodes and arcs from the digraph. |
| 1450 | 1450 |
/// |
| 1451 |
void clear() {}
|
|
| 1451 |
void clear() {}
|
|
| 1452 | 1452 |
|
| 1453 | 1453 |
template <typename _Digraph> |
| 1454 | 1454 |
struct Constraints {
|
| 1455 |
|
|
| 1455 |
void constraints() {
|
|
| 1456 | 1456 |
checkConcept<Base, _Digraph>(); |
| 1457 |
digraph.clear(); |
|
| 1458 |
} |
|
| 1457 |
digraph.clear(); |
|
| 1458 |
} |
|
| 1459 | 1459 |
|
| 1460 |
|
|
| 1460 |
_Digraph digraph; |
|
| 1461 | 1461 |
}; |
| 1462 | 1462 |
}; |
| 1463 | 1463 |
|
| 1464 | 1464 |
/// \brief An empty clearable base undirected graph class. |
| 1465 | 1465 |
/// |
| 1466 | 1466 |
/// This class provides beside the core undirected graph features |
| 1467 | 1467 |
/// core clear functions for the undirected graph structure. The |
| 1468 | 1468 |
/// main difference between the base and this interface is that |
| 1469 | 1469 |
/// the graph alterations should handled already on this level. |
| 1470 | 1470 |
template <typename _Base = BaseGraphComponent> |
| 1471 | 1471 |
class ClearableGraphComponent : public ClearableDigraphComponent<_Base> {
|
| 1472 | 1472 |
public: |
| 1473 | 1473 |
|
| 1474 | 1474 |
typedef _Base Base; |
| 1475 | 1475 |
|
| 1476 | 1476 |
template <typename _Graph> |
| 1477 | 1477 |
struct Constraints {
|
| 1478 |
|
|
| 1478 |
void constraints() {
|
|
| 1479 | 1479 |
checkConcept<ClearableGraphComponent<Base>, _Graph>(); |
| 1480 |
|
|
| 1480 |
} |
|
| 1481 | 1481 |
|
| 1482 |
|
|
| 1482 |
_Graph graph; |
|
| 1483 | 1483 |
}; |
| 1484 | 1484 |
}; |
| 1485 | 1485 |
|
| 1486 | 1486 |
} |
| 1487 | 1487 |
|
| 1488 | 1488 |
} |
| 1489 | 1489 |
|
| 1490 | 1490 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 concept |
| ... | ... |
@@ -39,114 +39,114 @@ |
| 39 | 39 |
class Heap {
|
| 40 | 40 |
public: |
| 41 | 41 |
|
| 42 | 42 |
/// Type of the items stored in the heap. |
| 43 | 43 |
typedef typename ItemIntMap::Key Item; |
| 44 | 44 |
|
| 45 | 45 |
/// Type of the priorities. |
| 46 | 46 |
typedef Priority Prio; |
| 47 | 47 |
|
| 48 | 48 |
/// \brief Type to represent the states of the items. |
| 49 | 49 |
/// |
| 50 | 50 |
/// Each item has a state associated to it. It can be "in heap", |
| 51 | 51 |
/// "pre heap" or "post heap". The later two are indifferent |
| 52 | 52 |
/// from the point of view of the heap, but may be useful for |
| 53 | 53 |
/// the user. |
| 54 | 54 |
/// |
| 55 |
/// The \c ItemIntMap must be initialized in such a way, that it |
|
| 55 |
/// The \c ItemIntMap must be initialized in such a way, that it |
|
| 56 | 56 |
/// assigns \c PRE_HEAP (<tt>-1</tt>) to every item. |
| 57 | 57 |
enum State {
|
| 58 |
IN_HEAP = 0, |
|
| 59 |
PRE_HEAP = -1, |
|
| 60 |
|
|
| 58 |
IN_HEAP = 0, |
|
| 59 |
PRE_HEAP = -1, |
|
| 60 |
POST_HEAP = -2 |
|
| 61 | 61 |
}; |
| 62 |
|
|
| 62 |
|
|
| 63 | 63 |
/// \brief The constructor. |
| 64 | 64 |
/// |
| 65 | 65 |
/// The constructor. |
| 66 | 66 |
/// \param map A map that assigns \c int values to keys of type |
| 67 | 67 |
/// \c Item. It is used internally by the heap implementations to |
| 68 | 68 |
/// handle the cross references. The assigned value must be |
| 69 | 69 |
/// \c PRE_HEAP (<tt>-1</tt>) for every item. |
| 70 | 70 |
explicit Heap(ItemIntMap &map) {}
|
| 71 | 71 |
|
| 72 | 72 |
/// \brief The number of items stored in the heap. |
| 73 | 73 |
/// |
| 74 | 74 |
/// Returns the number of items stored in the heap. |
| 75 | 75 |
int size() const { return 0; }
|
| 76 | 76 |
|
| 77 | 77 |
/// \brief Checks if the heap is empty. |
| 78 | 78 |
/// |
| 79 | 79 |
/// Returns \c true if the heap is empty. |
| 80 | 80 |
bool empty() const { return false; }
|
| 81 | 81 |
|
| 82 | 82 |
/// \brief Makes the heap empty. |
| 83 | 83 |
/// |
| 84 | 84 |
/// Makes the heap empty. |
| 85 | 85 |
void clear(); |
| 86 | 86 |
|
| 87 | 87 |
/// \brief Inserts an item into the heap with the given priority. |
| 88 |
/// |
|
| 89 |
/// Inserts the given item into the heap with the given priority. |
|
| 88 |
/// |
|
| 89 |
/// Inserts the given item into the heap with the given priority. |
|
| 90 | 90 |
/// \param i The item to insert. |
| 91 | 91 |
/// \param p The priority of the item. |
| 92 | 92 |
void push(const Item &i, const Prio &p) {}
|
| 93 | 93 |
|
| 94 | 94 |
/// \brief Returns the item having minimum priority. |
| 95 | 95 |
/// |
| 96 | 96 |
/// Returns the item having minimum priority. |
| 97 | 97 |
/// \pre The heap must be non-empty. |
| 98 | 98 |
Item top() const {}
|
| 99 | 99 |
|
| 100 | 100 |
/// \brief The minimum priority. |
| 101 | 101 |
/// |
| 102 | 102 |
/// Returns the minimum priority. |
| 103 | 103 |
/// \pre The heap must be non-empty. |
| 104 | 104 |
Prio prio() const {}
|
| 105 | 105 |
|
| 106 | 106 |
/// \brief Removes the item having minimum priority. |
| 107 | 107 |
/// |
| 108 | 108 |
/// Removes the item having minimum priority. |
| 109 | 109 |
/// \pre The heap must be non-empty. |
| 110 | 110 |
void pop() {}
|
| 111 | 111 |
|
| 112 | 112 |
/// \brief Removes an item from the heap. |
| 113 | 113 |
/// |
| 114 | 114 |
/// Removes the given item from the heap if it is already stored. |
| 115 |
/// \param i The item to delete. |
|
| 115 |
/// \param i The item to delete. |
|
| 116 | 116 |
void erase(const Item &i) {}
|
| 117 | 117 |
|
| 118 | 118 |
/// \brief The priority of an item. |
| 119 | 119 |
/// |
| 120 |
/// Returns the priority of the given item. |
|
| 120 |
/// Returns the priority of the given item. |
|
| 121 | 121 |
/// \pre \c i must be in the heap. |
| 122 | 122 |
/// \param i The item. |
| 123 | 123 |
Prio operator[](const Item &i) const {}
|
| 124 | 124 |
|
| 125 | 125 |
/// \brief Sets the priority of an item or inserts it, if it is |
| 126 | 126 |
/// not stored in the heap. |
| 127 | 127 |
/// |
| 128 | 128 |
/// This method sets the priority of the given item if it is |
| 129 | 129 |
/// already stored in the heap. |
| 130 | 130 |
/// Otherwise it inserts the given item with the given priority. |
| 131 | 131 |
/// |
| 132 | 132 |
/// It may throw an \ref UnderflowPriorityException. |
| 133 | 133 |
/// \param i The item. |
| 134 | 134 |
/// \param p The priority. |
| 135 | 135 |
void set(const Item &i, const Prio &p) {}
|
| 136 |
|
|
| 136 |
|
|
| 137 | 137 |
/// \brief Decreases the priority of an item to the given value. |
| 138 | 138 |
/// |
| 139 | 139 |
/// Decreases the priority of an item to the given value. |
| 140 | 140 |
/// \pre \c i must be stored in the heap with priority at least \c p. |
| 141 | 141 |
/// \param i The item. |
| 142 | 142 |
/// \param p The priority. |
| 143 | 143 |
void decrease(const Item &i, const Prio &p) {}
|
| 144 | 144 |
|
| 145 | 145 |
/// \brief Increases the priority of an item to the given value. |
| 146 | 146 |
/// |
| 147 | 147 |
/// Increases the priority of an item to the given value. |
| 148 | 148 |
/// \pre \c i must be stored in the heap with priority at most \c p. |
| 149 | 149 |
/// \param i The item. |
| 150 | 150 |
/// \param p The priority. |
| 151 | 151 |
void increase(const Item &i, const Prio &p) {}
|
| 152 | 152 |
|
| ... | ... |
@@ -161,86 +161,86 @@ |
| 161 | 161 |
/// \param i The item. |
| 162 | 162 |
State state(const Item &i) const {}
|
| 163 | 163 |
|
| 164 | 164 |
/// \brief Sets the state of an item in the heap. |
| 165 | 165 |
/// |
| 166 | 166 |
/// Sets the state of the given item in the heap. It can be used |
| 167 | 167 |
/// to manually clear the heap when it is important to achive the |
| 168 | 168 |
/// better time complexity. |
| 169 | 169 |
/// \param i The item. |
| 170 | 170 |
/// \param st The state. It should not be \c IN_HEAP. |
| 171 | 171 |
void state(const Item& i, State st) {}
|
| 172 | 172 |
|
| 173 | 173 |
|
| 174 | 174 |
template <typename _Heap> |
| 175 | 175 |
struct Constraints {
|
| 176 | 176 |
public: |
| 177 |
void constraints() {
|
|
| 178 |
typedef typename _Heap::Item OwnItem; |
|
| 179 |
typedef typename _Heap::Prio OwnPrio; |
|
| 180 |
typedef typename _Heap::State OwnState; |
|
| 177 |
void constraints() {
|
|
| 178 |
typedef typename _Heap::Item OwnItem; |
|
| 179 |
typedef typename _Heap::Prio OwnPrio; |
|
| 180 |
typedef typename _Heap::State OwnState; |
|
| 181 | 181 |
|
| 182 |
Item item; |
|
| 183 |
Prio prio; |
|
| 184 |
item=Item(); |
|
| 185 |
prio=Prio(); |
|
| 186 |
ignore_unused_variable_warning(item); |
|
| 187 |
ignore_unused_variable_warning(prio); |
|
| 182 |
Item item; |
|
| 183 |
Prio prio; |
|
| 184 |
item=Item(); |
|
| 185 |
prio=Prio(); |
|
| 186 |
ignore_unused_variable_warning(item); |
|
| 187 |
ignore_unused_variable_warning(prio); |
|
| 188 | 188 |
|
| 189 |
OwnItem own_item; |
|
| 190 |
OwnPrio own_prio; |
|
| 191 |
OwnState own_state; |
|
| 192 |
own_item=Item(); |
|
| 193 |
own_prio=Prio(); |
|
| 194 |
ignore_unused_variable_warning(own_item); |
|
| 195 |
ignore_unused_variable_warning(own_prio); |
|
| 196 |
ignore_unused_variable_warning(own_state); |
|
| 189 |
OwnItem own_item; |
|
| 190 |
OwnPrio own_prio; |
|
| 191 |
OwnState own_state; |
|
| 192 |
own_item=Item(); |
|
| 193 |
own_prio=Prio(); |
|
| 194 |
ignore_unused_variable_warning(own_item); |
|
| 195 |
ignore_unused_variable_warning(own_prio); |
|
| 196 |
ignore_unused_variable_warning(own_state); |
|
| 197 | 197 |
|
| 198 |
_Heap heap1(map); |
|
| 199 |
_Heap heap2 = heap1; |
|
| 200 |
ignore_unused_variable_warning(heap1); |
|
| 201 |
ignore_unused_variable_warning(heap2); |
|
| 202 |
|
|
| 203 |
int s = heap.size(); |
|
| 204 |
ignore_unused_variable_warning(s); |
|
| 205 |
bool e = heap.empty(); |
|
| 206 |
|
|
| 198 |
_Heap heap1(map); |
|
| 199 |
_Heap heap2 = heap1; |
|
| 200 |
ignore_unused_variable_warning(heap1); |
|
| 201 |
ignore_unused_variable_warning(heap2); |
|
| 207 | 202 |
|
| 208 |
prio = heap.prio(); |
|
| 209 |
item = heap.top(); |
|
| 210 |
prio = heap[item]; |
|
| 211 |
own_prio = heap.prio(); |
|
| 212 |
own_item = heap.top(); |
|
| 213 |
own_prio = heap[own_item]; |
|
| 203 |
int s = heap.size(); |
|
| 204 |
ignore_unused_variable_warning(s); |
|
| 205 |
bool e = heap.empty(); |
|
| 206 |
ignore_unused_variable_warning(e); |
|
| 214 | 207 |
|
| 215 |
heap.push(item, prio); |
|
| 216 |
heap.push(own_item, own_prio); |
|
| 217 |
|
|
| 208 |
prio = heap.prio(); |
|
| 209 |
item = heap.top(); |
|
| 210 |
prio = heap[item]; |
|
| 211 |
own_prio = heap.prio(); |
|
| 212 |
own_item = heap.top(); |
|
| 213 |
own_prio = heap[own_item]; |
|
| 218 | 214 |
|
| 219 |
heap.set(item, prio); |
|
| 220 |
heap.decrease(item, prio); |
|
| 221 |
heap.increase(item, prio); |
|
| 222 |
heap.set(own_item, own_prio); |
|
| 223 |
heap.decrease(own_item, own_prio); |
|
| 224 |
heap.increase(own_item, own_prio); |
|
| 215 |
heap.push(item, prio); |
|
| 216 |
heap.push(own_item, own_prio); |
|
| 217 |
heap.pop(); |
|
| 225 | 218 |
|
| 226 |
heap.erase(item); |
|
| 227 |
heap.erase(own_item); |
|
| 228 |
|
|
| 219 |
heap.set(item, prio); |
|
| 220 |
heap.decrease(item, prio); |
|
| 221 |
heap.increase(item, prio); |
|
| 222 |
heap.set(own_item, own_prio); |
|
| 223 |
heap.decrease(own_item, own_prio); |
|
| 224 |
heap.increase(own_item, own_prio); |
|
| 229 | 225 |
|
| 230 |
own_state = heap.state(own_item); |
|
| 231 |
heap.state(own_item, own_state); |
|
| 226 |
heap.erase(item); |
|
| 227 |
heap.erase(own_item); |
|
| 228 |
heap.clear(); |
|
| 232 | 229 |
|
| 233 |
own_state = _Heap::PRE_HEAP; |
|
| 234 |
own_state = _Heap::IN_HEAP; |
|
| 235 |
own_state = _Heap::POST_HEAP; |
|
| 236 |
} |
|
| 230 |
own_state = heap.state(own_item); |
|
| 231 |
heap.state(own_item, own_state); |
|
| 237 | 232 |
|
| 238 |
_Heap& heap; |
|
| 239 |
ItemIntMap& map; |
|
| 233 |
own_state = _Heap::PRE_HEAP; |
|
| 234 |
own_state = _Heap::IN_HEAP; |
|
| 235 |
own_state = _Heap::POST_HEAP; |
|
| 236 |
} |
|
| 237 |
|
|
| 238 |
_Heap& heap; |
|
| 239 |
ItemIntMap& map; |
|
| 240 | 240 |
}; |
| 241 | 241 |
}; |
| 242 | 242 |
|
| 243 | 243 |
/// @} |
| 244 | 244 |
} // namespace lemon |
| 245 | 245 |
} |
| 246 | 246 |
#endif // LEMON_CONCEPT_PATH_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_CONCEPT_MAPS_H |
| ... | ... |
@@ -34,179 +34,179 @@ |
| 34 | 34 |
/// @{
|
| 35 | 35 |
|
| 36 | 36 |
/// Readable map concept |
| 37 | 37 |
|
| 38 | 38 |
/// Readable map concept. |
| 39 | 39 |
/// |
| 40 | 40 |
template<typename K, typename T> |
| 41 | 41 |
class ReadMap |
| 42 | 42 |
{
|
| 43 | 43 |
public: |
| 44 | 44 |
/// The key type of the map. |
| 45 | 45 |
typedef K Key; |
| 46 | 46 |
/// The value type of the map. (The type of objects associated with the keys). |
| 47 | 47 |
typedef T Value; |
| 48 | 48 |
|
| 49 | 49 |
/// Returns the value associated with the given key. |
| 50 |
Value operator[](const Key &) const {
|
|
| 50 |
Value operator[](const Key &) const {
|
|
| 51 | 51 |
return *static_cast<Value *>(0); |
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 | 54 |
template<typename _ReadMap> |
| 55 | 55 |
struct Constraints {
|
| 56 |
void constraints() {
|
|
| 57 |
Value val = m[key]; |
|
| 58 |
val = m[key]; |
|
| 59 |
typename _ReadMap::Value own_val = m[own_key]; |
|
| 60 |
|
|
| 56 |
void constraints() {
|
|
| 57 |
Value val = m[key]; |
|
| 58 |
val = m[key]; |
|
| 59 |
typename _ReadMap::Value own_val = m[own_key]; |
|
| 60 |
own_val = m[own_key]; |
|
| 61 | 61 |
|
| 62 |
ignore_unused_variable_warning(key); |
|
| 63 |
ignore_unused_variable_warning(val); |
|
| 64 |
ignore_unused_variable_warning(own_key); |
|
| 65 |
ignore_unused_variable_warning(own_val); |
|
| 66 |
} |
|
| 67 |
const Key& key; |
|
| 68 |
const typename _ReadMap::Key& own_key; |
|
| 69 |
const _ReadMap& m; |
|
| 62 |
ignore_unused_variable_warning(key); |
|
| 63 |
ignore_unused_variable_warning(val); |
|
| 64 |
ignore_unused_variable_warning(own_key); |
|
| 65 |
ignore_unused_variable_warning(own_val); |
|
| 66 |
} |
|
| 67 |
const Key& key; |
|
| 68 |
const typename _ReadMap::Key& own_key; |
|
| 69 |
const _ReadMap& m; |
|
| 70 | 70 |
}; |
| 71 | 71 |
|
| 72 | 72 |
}; |
| 73 | 73 |
|
| 74 | 74 |
|
| 75 | 75 |
/// Writable map concept |
| 76 | 76 |
|
| 77 | 77 |
/// Writable map concept. |
| 78 | 78 |
/// |
| 79 | 79 |
template<typename K, typename T> |
| 80 | 80 |
class WriteMap |
| 81 | 81 |
{
|
| 82 | 82 |
public: |
| 83 | 83 |
/// The key type of the map. |
| 84 | 84 |
typedef K Key; |
| 85 | 85 |
/// The value type of the map. (The type of objects associated with the keys). |
| 86 | 86 |
typedef T Value; |
| 87 | 87 |
|
| 88 | 88 |
/// Sets the value associated with the given key. |
| 89 | 89 |
void set(const Key &, const Value &) {}
|
| 90 | 90 |
|
| 91 | 91 |
/// Default constructor. |
| 92 | 92 |
WriteMap() {}
|
| 93 | 93 |
|
| 94 | 94 |
template <typename _WriteMap> |
| 95 | 95 |
struct Constraints {
|
| 96 |
void constraints() {
|
|
| 97 |
m.set(key, val); |
|
| 98 |
|
|
| 96 |
void constraints() {
|
|
| 97 |
m.set(key, val); |
|
| 98 |
m.set(own_key, own_val); |
|
| 99 | 99 |
|
| 100 |
ignore_unused_variable_warning(key); |
|
| 101 |
ignore_unused_variable_warning(val); |
|
| 102 |
ignore_unused_variable_warning(own_key); |
|
| 103 |
ignore_unused_variable_warning(own_val); |
|
| 104 |
} |
|
| 105 |
const Key& key; |
|
| 106 |
const Value& val; |
|
| 107 |
const typename _WriteMap::Key& own_key; |
|
| 108 |
const typename _WriteMap::Value& own_val; |
|
| 109 |
_WriteMap& m; |
|
| 100 |
ignore_unused_variable_warning(key); |
|
| 101 |
ignore_unused_variable_warning(val); |
|
| 102 |
ignore_unused_variable_warning(own_key); |
|
| 103 |
ignore_unused_variable_warning(own_val); |
|
| 104 |
} |
|
| 105 |
const Key& key; |
|
| 106 |
const Value& val; |
|
| 107 |
const typename _WriteMap::Key& own_key; |
|
| 108 |
const typename _WriteMap::Value& own_val; |
|
| 109 |
_WriteMap& m; |
|
| 110 | 110 |
}; |
| 111 | 111 |
}; |
| 112 | 112 |
|
| 113 | 113 |
/// Read/writable map concept |
| 114 | 114 |
|
| 115 | 115 |
/// Read/writable map concept. |
| 116 | 116 |
/// |
| 117 | 117 |
template<typename K, typename T> |
| 118 | 118 |
class ReadWriteMap : public ReadMap<K,T>, |
| 119 |
|
|
| 119 |
public WriteMap<K,T> |
|
| 120 | 120 |
{
|
| 121 | 121 |
public: |
| 122 | 122 |
/// The key type of the map. |
| 123 | 123 |
typedef K Key; |
| 124 | 124 |
/// The value type of the map. (The type of objects associated with the keys). |
| 125 | 125 |
typedef T Value; |
| 126 | 126 |
|
| 127 | 127 |
/// Returns the value associated with the given key. |
| 128 |
Value operator[](const Key &) const {
|
|
| 128 |
Value operator[](const Key &) const {
|
|
| 129 | 129 |
return *static_cast<Value *>(0); |
| 130 | 130 |
} |
| 131 | 131 |
|
| 132 | 132 |
/// Sets the value associated with the given key. |
| 133 | 133 |
void set(const Key &, const Value &) {}
|
| 134 | 134 |
|
| 135 | 135 |
template<typename _ReadWriteMap> |
| 136 | 136 |
struct Constraints {
|
| 137 |
void constraints() {
|
|
| 138 |
checkConcept<ReadMap<K, T>, _ReadWriteMap >(); |
|
| 139 |
checkConcept<WriteMap<K, T>, _ReadWriteMap >(); |
|
| 140 |
} |
|
| 137 |
void constraints() {
|
|
| 138 |
checkConcept<ReadMap<K, T>, _ReadWriteMap >(); |
|
| 139 |
checkConcept<WriteMap<K, T>, _ReadWriteMap >(); |
|
| 140 |
} |
|
| 141 | 141 |
}; |
| 142 | 142 |
}; |
| 143 | 143 |
|
| 144 | 144 |
|
| 145 | 145 |
/// Dereferable map concept |
| 146 | 146 |
|
| 147 | 147 |
/// Dereferable map concept. |
| 148 | 148 |
/// |
| 149 | 149 |
template<typename K, typename T, typename R, typename CR> |
| 150 | 150 |
class ReferenceMap : public ReadWriteMap<K,T> |
| 151 | 151 |
{
|
| 152 | 152 |
public: |
| 153 | 153 |
/// Tag for reference maps. |
| 154 | 154 |
typedef True ReferenceMapTag; |
| 155 | 155 |
/// The key type of the map. |
| 156 | 156 |
typedef K Key; |
| 157 | 157 |
/// The value type of the map. (The type of objects associated with the keys). |
| 158 | 158 |
typedef T Value; |
| 159 | 159 |
/// The reference type of the map. |
| 160 | 160 |
typedef R Reference; |
| 161 | 161 |
/// The const reference type of the map. |
| 162 | 162 |
typedef CR ConstReference; |
| 163 | 163 |
|
| 164 | 164 |
public: |
| 165 | 165 |
|
| 166 | 166 |
/// Returns a reference to the value associated with the given key. |
| 167 |
Reference operator[](const Key &) {
|
|
| 167 |
Reference operator[](const Key &) {
|
|
| 168 | 168 |
return *static_cast<Value *>(0); |
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 | 171 |
/// Returns a const reference to the value associated with the given key. |
| 172 | 172 |
ConstReference operator[](const Key &) const {
|
| 173 | 173 |
return *static_cast<Value *>(0); |
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
/// Sets the value associated with the given key. |
| 177 | 177 |
void set(const Key &k,const Value &t) { operator[](k)=t; }
|
| 178 | 178 |
|
| 179 | 179 |
template<typename _ReferenceMap> |
| 180 | 180 |
struct Constraints {
|
| 181 |
void constraints() {
|
|
| 182 |
checkConcept<ReadWriteMap<K, T>, _ReferenceMap >(); |
|
| 183 |
ref = m[key]; |
|
| 184 |
m[key] = val; |
|
| 185 |
m[key] = ref; |
|
| 186 |
m[key] = cref; |
|
| 187 |
own_ref = m[own_key]; |
|
| 188 |
m[own_key] = own_val; |
|
| 189 |
m[own_key] = own_ref; |
|
| 190 |
m[own_key] = own_cref; |
|
| 191 |
m[key] = m[own_key]; |
|
| 192 |
m[own_key] = m[key]; |
|
| 193 |
} |
|
| 194 |
const Key& key; |
|
| 195 |
Value& val; |
|
| 196 |
Reference ref; |
|
| 197 |
ConstReference cref; |
|
| 198 |
const typename _ReferenceMap::Key& own_key; |
|
| 199 |
typename _ReferenceMap::Value& own_val; |
|
| 200 |
typename _ReferenceMap::Reference own_ref; |
|
| 201 |
typename _ReferenceMap::ConstReference own_cref; |
|
| 202 |
_ReferenceMap& m; |
|
| 181 |
void constraints() {
|
|
| 182 |
checkConcept<ReadWriteMap<K, T>, _ReferenceMap >(); |
|
| 183 |
ref = m[key]; |
|
| 184 |
m[key] = val; |
|
| 185 |
m[key] = ref; |
|
| 186 |
m[key] = cref; |
|
| 187 |
own_ref = m[own_key]; |
|
| 188 |
m[own_key] = own_val; |
|
| 189 |
m[own_key] = own_ref; |
|
| 190 |
m[own_key] = own_cref; |
|
| 191 |
m[key] = m[own_key]; |
|
| 192 |
m[own_key] = m[key]; |
|
| 193 |
} |
|
| 194 |
const Key& key; |
|
| 195 |
Value& val; |
|
| 196 |
Reference ref; |
|
| 197 |
ConstReference cref; |
|
| 198 |
const typename _ReferenceMap::Key& own_key; |
|
| 199 |
typename _ReferenceMap::Value& own_val; |
|
| 200 |
typename _ReferenceMap::Reference own_ref; |
|
| 201 |
typename _ReferenceMap::ConstReference own_cref; |
|
| 202 |
_ReferenceMap& m; |
|
| 203 | 203 |
}; |
| 204 | 204 |
}; |
| 205 | 205 |
|
| 206 | 206 |
// @} |
| 207 | 207 |
|
| 208 | 208 |
} //namespace concepts |
| 209 | 209 |
|
| 210 | 210 |
} //namespace lemon |
| 211 | 211 |
|
| 212 | 212 |
#endif // LEMON_CONCEPT_MAPS_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 concept |
| ... | ... |
@@ -26,33 +26,33 @@ |
| 26 | 26 |
#define LEMON_CONCEPT_PATH_H |
| 27 | 27 |
|
| 28 | 28 |
#include <lemon/bits/invalid.h> |
| 29 | 29 |
#include <lemon/bits/utility.h> |
| 30 | 30 |
#include <lemon/concept_check.h> |
| 31 | 31 |
|
| 32 | 32 |
namespace lemon {
|
| 33 | 33 |
namespace concepts {
|
| 34 | 34 |
|
| 35 | 35 |
/// \addtogroup concept |
| 36 | 36 |
/// @{
|
| 37 | 37 |
|
| 38 | 38 |
/// \brief A skeleton structure for representing directed paths in |
| 39 | 39 |
/// a digraph. |
| 40 | 40 |
/// |
| 41 | 41 |
/// A skeleton structure for representing directed paths in a |
| 42 |
/// digraph. |
|
| 42 |
/// digraph. |
|
| 43 | 43 |
/// \tparam _Digraph The digraph type in which the path is. |
| 44 | 44 |
/// |
| 45 | 45 |
/// In a sense, the path can be treated as a list of arcs. The |
| 46 | 46 |
/// lemon path type stores just this list. As a consequence it |
| 47 | 47 |
/// cannot enumerate the nodes in the path and the zero length |
| 48 | 48 |
/// paths cannot store the source. |
| 49 | 49 |
/// |
| 50 | 50 |
template <typename _Digraph> |
| 51 | 51 |
class Path {
|
| 52 | 52 |
public: |
| 53 | 53 |
|
| 54 | 54 |
/// Type of the underlying digraph. |
| 55 | 55 |
typedef _Digraph Digraph; |
| 56 | 56 |
/// Arc type of the underlying digraph. |
| 57 | 57 |
typedef typename Digraph::Arc Arc; |
| 58 | 58 |
|
| ... | ... |
@@ -70,51 +70,51 @@ |
| 70 | 70 |
Path& operator=(const CPath& cpath) {}
|
| 71 | 71 |
|
| 72 | 72 |
/// Length of the path ie. the number of arcs in the path. |
| 73 | 73 |
int length() const { return 0;}
|
| 74 | 74 |
|
| 75 | 75 |
/// Returns whether the path is empty. |
| 76 | 76 |
bool empty() const { return true;}
|
| 77 | 77 |
|
| 78 | 78 |
/// Resets the path to an empty path. |
| 79 | 79 |
void clear() {}
|
| 80 | 80 |
|
| 81 | 81 |
/// \brief Lemon style iterator for path arcs |
| 82 | 82 |
/// |
| 83 | 83 |
/// This class is used to iterate on the arcs of the paths. |
| 84 | 84 |
class ArcIt {
|
| 85 | 85 |
public: |
| 86 |
/// Default constructor |
|
| 87 |
ArcIt() {}
|
|
| 88 |
/// Invalid constructor |
|
| 89 |
ArcIt(Invalid) {}
|
|
| 90 |
/// Constructor for first arc |
|
| 91 |
ArcIt(const Path &) {}
|
|
| 86 |
/// Default constructor |
|
| 87 |
ArcIt() {}
|
|
| 88 |
/// Invalid constructor |
|
| 89 |
ArcIt(Invalid) {}
|
|
| 90 |
/// Constructor for first arc |
|
| 91 |
ArcIt(const Path &) {}
|
|
| 92 | 92 |
|
| 93 | 93 |
/// Conversion to Arc |
| 94 |
|
|
| 94 |
operator Arc() const { return INVALID; }
|
|
| 95 | 95 |
|
| 96 |
/// Next arc |
|
| 97 |
ArcIt& operator++() {return *this;}
|
|
| 96 |
/// Next arc |
|
| 97 |
ArcIt& operator++() {return *this;}
|
|
| 98 | 98 |
|
| 99 |
/// Comparison operator |
|
| 100 |
bool operator==(const ArcIt&) const {return true;}
|
|
| 101 |
/// Comparison operator |
|
| 102 |
bool operator!=(const ArcIt&) const {return true;}
|
|
| 103 |
/// Comparison operator |
|
| 104 |
bool operator<(const ArcIt&) const {return false;}
|
|
| 99 |
/// Comparison operator |
|
| 100 |
bool operator==(const ArcIt&) const {return true;}
|
|
| 101 |
/// Comparison operator |
|
| 102 |
bool operator!=(const ArcIt&) const {return true;}
|
|
| 103 |
/// Comparison operator |
|
| 104 |
bool operator<(const ArcIt&) const {return false;}
|
|
| 105 | 105 |
|
| 106 | 106 |
}; |
| 107 | 107 |
|
| 108 | 108 |
template <typename _Path> |
| 109 | 109 |
struct Constraints {
|
| 110 | 110 |
void constraints() {
|
| 111 | 111 |
Path<Digraph> pc; |
| 112 | 112 |
_Path p, pp(pc); |
| 113 | 113 |
int l = p.length(); |
| 114 | 114 |
int e = p.empty(); |
| 115 | 115 |
p.clear(); |
| 116 | 116 |
|
| 117 | 117 |
p = pc; |
| 118 | 118 |
|
| 119 | 119 |
typename _Path::ArcIt id, ii(INVALID), i(p); |
| 120 | 120 |
|
| ... | ... |
@@ -124,180 +124,180 @@ |
| 124 | 124 |
e = (i == ii); |
| 125 | 125 |
e = (i != ii); |
| 126 | 126 |
e = (i < ii); |
| 127 | 127 |
|
| 128 | 128 |
ignore_unused_variable_warning(l); |
| 129 | 129 |
ignore_unused_variable_warning(pp); |
| 130 | 130 |
ignore_unused_variable_warning(e); |
| 131 | 131 |
ignore_unused_variable_warning(id); |
| 132 | 132 |
ignore_unused_variable_warning(ii); |
| 133 | 133 |
ignore_unused_variable_warning(ed); |
| 134 | 134 |
} |
| 135 | 135 |
}; |
| 136 | 136 |
|
| 137 | 137 |
}; |
| 138 | 138 |
|
| 139 | 139 |
namespace _path_bits {
|
| 140 |
|
|
| 140 |
|
|
| 141 | 141 |
template <typename _Digraph, typename _Path, typename RevPathTag = void> |
| 142 | 142 |
struct PathDumperConstraints {
|
| 143 | 143 |
void constraints() {
|
| 144 | 144 |
int l = p.length(); |
| 145 | 145 |
int e = p.empty(); |
| 146 | 146 |
|
| 147 | 147 |
typename _Path::ArcIt id, i(p); |
| 148 | 148 |
|
| 149 | 149 |
++i; |
| 150 | 150 |
typename _Digraph::Arc ed = i; |
| 151 | 151 |
|
| 152 | 152 |
e = (i == INVALID); |
| 153 | 153 |
e = (i != INVALID); |
| 154 | 154 |
|
| 155 | 155 |
ignore_unused_variable_warning(l); |
| 156 | 156 |
ignore_unused_variable_warning(e); |
| 157 | 157 |
ignore_unused_variable_warning(id); |
| 158 | 158 |
ignore_unused_variable_warning(ed); |
| 159 | 159 |
} |
| 160 | 160 |
_Path& p; |
| 161 | 161 |
}; |
| 162 | 162 |
|
| 163 | 163 |
template <typename _Digraph, typename _Path> |
| 164 | 164 |
struct PathDumperConstraints< |
| 165 |
_Digraph, _Path, |
|
| 165 |
_Digraph, _Path, |
|
| 166 | 166 |
typename enable_if<typename _Path::RevPathTag, void>::type |
| 167 | 167 |
> {
|
| 168 | 168 |
void constraints() {
|
| 169 | 169 |
int l = p.length(); |
| 170 | 170 |
int e = p.empty(); |
| 171 | 171 |
|
| 172 | 172 |
typename _Path::RevArcIt id, i(p); |
| 173 | 173 |
|
| 174 | 174 |
++i; |
| 175 | 175 |
typename _Digraph::Arc ed = i; |
| 176 | 176 |
|
| 177 | 177 |
e = (i == INVALID); |
| 178 | 178 |
e = (i != INVALID); |
| 179 | 179 |
|
| 180 | 180 |
ignore_unused_variable_warning(l); |
| 181 | 181 |
ignore_unused_variable_warning(e); |
| 182 | 182 |
ignore_unused_variable_warning(id); |
| 183 | 183 |
ignore_unused_variable_warning(ed); |
| 184 | 184 |
} |
| 185 | 185 |
_Path& p; |
| 186 | 186 |
}; |
| 187 |
|
|
| 187 |
|
|
| 188 | 188 |
} |
| 189 | 189 |
|
| 190 | 190 |
|
| 191 | 191 |
/// \brief A skeleton structure for path dumpers. |
| 192 | 192 |
/// |
| 193 | 193 |
/// A skeleton structure for path dumpers. The path dumpers are |
| 194 | 194 |
/// the generalization of the paths. The path dumpers can |
| 195 | 195 |
/// enumerate the arcs of the path wheter in forward or in |
| 196 | 196 |
/// backward order. In most time these classes are not used |
| 197 | 197 |
/// directly rather it used to assign a dumped class to a real |
| 198 | 198 |
/// path type. |
| 199 | 199 |
/// |
| 200 | 200 |
/// The main purpose of this concept is that the shortest path |
| 201 | 201 |
/// algorithms can enumerate easily the arcs in reverse order. |
| 202 | 202 |
/// If we would like to give back a real path from these |
| 203 | 203 |
/// algorithms then we should create a temporarly path object. In |
| 204 | 204 |
/// Lemon such algorithms gives back a path dumper what can |
| 205 | 205 |
/// assigned to a real path and the dumpers can be implemented as |
| 206 | 206 |
/// an adaptor class to the predecessor map. |
| 207 | 207 |
|
| 208 | 208 |
/// \tparam _Digraph The digraph type in which the path is. |
| 209 | 209 |
/// |
| 210 | 210 |
/// The paths can be constructed from any path type by a |
| 211 | 211 |
/// template constructor or a template assignment operator. |
| 212 |
/// |
|
| 212 |
/// |
|
| 213 | 213 |
template <typename _Digraph> |
| 214 | 214 |
class PathDumper {
|
| 215 | 215 |
public: |
| 216 | 216 |
|
| 217 | 217 |
/// Type of the underlying digraph. |
| 218 | 218 |
typedef _Digraph Digraph; |
| 219 | 219 |
/// Arc type of the underlying digraph. |
| 220 | 220 |
typedef typename Digraph::Arc Arc; |
| 221 | 221 |
|
| 222 | 222 |
/// Length of the path ie. the number of arcs in the path. |
| 223 | 223 |
int length() const { return 0;}
|
| 224 | 224 |
|
| 225 | 225 |
/// Returns whether the path is empty. |
| 226 | 226 |
bool empty() const { return true;}
|
| 227 | 227 |
|
| 228 | 228 |
/// \brief Forward or reverse dumping |
| 229 | 229 |
/// |
| 230 | 230 |
/// If the RevPathTag is defined and true then reverse dumping |
| 231 | 231 |
/// is provided in the path dumper. In this case instead of the |
| 232 | 232 |
/// ArcIt the RevArcIt iterator should be implemented in the |
| 233 | 233 |
/// dumper. |
| 234 | 234 |
typedef False RevPathTag; |
| 235 | 235 |
|
| 236 | 236 |
/// \brief Lemon style iterator for path arcs |
| 237 | 237 |
/// |
| 238 | 238 |
/// This class is used to iterate on the arcs of the paths. |
| 239 | 239 |
class ArcIt {
|
| 240 | 240 |
public: |
| 241 |
/// Default constructor |
|
| 242 |
ArcIt() {}
|
|
| 243 |
/// Invalid constructor |
|
| 244 |
ArcIt(Invalid) {}
|
|
| 245 |
/// Constructor for first arc |
|
| 246 |
ArcIt(const PathDumper&) {}
|
|
| 241 |
/// Default constructor |
|
| 242 |
ArcIt() {}
|
|
| 243 |
/// Invalid constructor |
|
| 244 |
ArcIt(Invalid) {}
|
|
| 245 |
/// Constructor for first arc |
|
| 246 |
ArcIt(const PathDumper&) {}
|
|
| 247 | 247 |
|
| 248 | 248 |
/// Conversion to Arc |
| 249 |
|
|
| 249 |
operator Arc() const { return INVALID; }
|
|
| 250 | 250 |
|
| 251 |
/// Next arc |
|
| 252 |
ArcIt& operator++() {return *this;}
|
|
| 251 |
/// Next arc |
|
| 252 |
ArcIt& operator++() {return *this;}
|
|
| 253 | 253 |
|
| 254 |
/// Comparison operator |
|
| 255 |
bool operator==(const ArcIt&) const {return true;}
|
|
| 256 |
/// Comparison operator |
|
| 257 |
bool operator!=(const ArcIt&) const {return true;}
|
|
| 258 |
/// Comparison operator |
|
| 259 |
bool operator<(const ArcIt&) const {return false;}
|
|
| 254 |
/// Comparison operator |
|
| 255 |
bool operator==(const ArcIt&) const {return true;}
|
|
| 256 |
/// Comparison operator |
|
| 257 |
bool operator!=(const ArcIt&) const {return true;}
|
|
| 258 |
/// Comparison operator |
|
| 259 |
bool operator<(const ArcIt&) const {return false;}
|
|
| 260 | 260 |
|
| 261 | 261 |
}; |
| 262 | 262 |
|
| 263 | 263 |
/// \brief Lemon style iterator for path arcs |
| 264 | 264 |
/// |
| 265 | 265 |
/// This class is used to iterate on the arcs of the paths in |
| 266 | 266 |
/// reverse direction. |
| 267 | 267 |
class RevArcIt {
|
| 268 | 268 |
public: |
| 269 |
/// Default constructor |
|
| 270 |
RevArcIt() {}
|
|
| 271 |
/// Invalid constructor |
|
| 272 |
RevArcIt(Invalid) {}
|
|
| 273 |
/// Constructor for first arc |
|
| 274 |
RevArcIt(const PathDumper &) {}
|
|
| 269 |
/// Default constructor |
|
| 270 |
RevArcIt() {}
|
|
| 271 |
/// Invalid constructor |
|
| 272 |
RevArcIt(Invalid) {}
|
|
| 273 |
/// Constructor for first arc |
|
| 274 |
RevArcIt(const PathDumper &) {}
|
|
| 275 | 275 |
|
| 276 | 276 |
/// Conversion to Arc |
| 277 |
|
|
| 277 |
operator Arc() const { return INVALID; }
|
|
| 278 | 278 |
|
| 279 |
/// Next arc |
|
| 280 |
RevArcIt& operator++() {return *this;}
|
|
| 279 |
/// Next arc |
|
| 280 |
RevArcIt& operator++() {return *this;}
|
|
| 281 | 281 |
|
| 282 |
/// Comparison operator |
|
| 283 |
bool operator==(const RevArcIt&) const {return true;}
|
|
| 284 |
/// Comparison operator |
|
| 285 |
bool operator!=(const RevArcIt&) const {return true;}
|
|
| 286 |
/// Comparison operator |
|
| 287 |
bool operator<(const RevArcIt&) const {return false;}
|
|
| 282 |
/// Comparison operator |
|
| 283 |
bool operator==(const RevArcIt&) const {return true;}
|
|
| 284 |
/// Comparison operator |
|
| 285 |
bool operator!=(const RevArcIt&) const {return true;}
|
|
| 286 |
/// Comparison operator |
|
| 287 |
bool operator<(const RevArcIt&) const {return false;}
|
|
| 288 | 288 |
|
| 289 | 289 |
}; |
| 290 | 290 |
|
| 291 | 291 |
template <typename _Path> |
| 292 | 292 |
struct Constraints {
|
| 293 | 293 |
void constraints() {
|
| 294 | 294 |
function_requires<_path_bits:: |
| 295 | 295 |
PathDumperConstraints<Digraph, _Path> >(); |
| 296 | 296 |
} |
| 297 | 297 |
}; |
| 298 | 298 |
|
| 299 | 299 |
}; |
| 300 | 300 |
|
| 301 | 301 |
|
| 302 | 302 |
///@} |
| 303 | 303 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_COUNTER_H |
| 20 | 20 |
#define LEMON_COUNTER_H |
| 21 | 21 |
|
| 22 | 22 |
#include <string> |
| 23 | 23 |
#include <iostream> |
| 24 | 24 |
|
| 25 | 25 |
///\ingroup timecount |
| 26 | 26 |
///\file |
| 27 | 27 |
///\brief Tools for counting steps and events |
| 28 | 28 |
|
| 29 |
namespace lemon |
|
| 29 |
namespace lemon |
|
| 30 | 30 |
{
|
| 31 | 31 |
|
| 32 | 32 |
template<class P> class _NoSubCounter; |
| 33 | 33 |
|
| 34 | 34 |
template<class P> |
| 35 |
class _SubCounter |
|
| 35 |
class _SubCounter |
|
| 36 | 36 |
{
|
| 37 | 37 |
P &_parent; |
| 38 | 38 |
std::string _title; |
| 39 | 39 |
std::ostream &_os; |
| 40 | 40 |
int count; |
| 41 | 41 |
public: |
| 42 | 42 |
|
| 43 | 43 |
typedef _SubCounter<_SubCounter<P> > SubCounter; |
| 44 | 44 |
typedef _NoSubCounter<_SubCounter<P> > NoSubCounter; |
| 45 | 45 |
|
| 46 | 46 |
_SubCounter(P &parent) |
| 47 | 47 |
: _parent(parent), _title(), _os(std::cerr), count(0) {}
|
| 48 | 48 |
_SubCounter(P &parent,std::string title,std::ostream &os=std::cerr) |
| 49 | 49 |
: _parent(parent), _title(title), _os(os), count(0) {}
|
| 50 | 50 |
_SubCounter(P &parent,const char *title,std::ostream &os=std::cerr) |
| 51 | 51 |
: _parent(parent), _title(title), _os(os), count(0) {}
|
| 52 |
~_SubCounter() {
|
|
| 52 |
~_SubCounter() {
|
|
| 53 | 53 |
_os << _title << count <<std::endl; |
| 54 | 54 |
_parent+=count; |
| 55 | 55 |
} |
| 56 | 56 |
_SubCounter &operator++() { count++; return *this;}
|
| 57 | 57 |
int operator++(int) { return count++; }
|
| 58 | 58 |
_SubCounter &operator--() { count--; return *this;}
|
| 59 | 59 |
int operator--(int) { return count--; }
|
| 60 | 60 |
_SubCounter &operator+=(int c) { count+=c; return *this;}
|
| 61 | 61 |
_SubCounter &operator-=(int c) { count-=c; return *this;}
|
| 62 | 62 |
operator int() {return count;}
|
| 63 | 63 |
}; |
| 64 | 64 |
|
| 65 | 65 |
template<class P> |
| 66 |
class _NoSubCounter |
|
| 66 |
class _NoSubCounter |
|
| 67 | 67 |
{
|
| 68 | 68 |
P &_parent; |
| 69 | 69 |
public: |
| 70 | 70 |
typedef _NoSubCounter<_NoSubCounter<P> > SubCounter; |
| 71 | 71 |
typedef _NoSubCounter<_NoSubCounter<P> > NoSubCounter; |
| 72 |
|
|
| 72 |
|
|
| 73 | 73 |
_NoSubCounter(P &parent) :_parent(parent) {}
|
| 74 |
_NoSubCounter(P &parent,std::string,std::ostream &) |
|
| 74 |
_NoSubCounter(P &parent,std::string,std::ostream &) |
|
| 75 | 75 |
:_parent(parent) {}
|
| 76 |
_NoSubCounter(P &parent,std::string) |
|
| 76 |
_NoSubCounter(P &parent,std::string) |
|
| 77 | 77 |
:_parent(parent) {}
|
| 78 | 78 |
_NoSubCounter(P &parent,const char *,std::ostream &) |
| 79 | 79 |
:_parent(parent) {}
|
| 80 | 80 |
_NoSubCounter(P &parent,const char *) |
| 81 | 81 |
:_parent(parent) {}
|
| 82 | 82 |
~_NoSubCounter() {}
|
| 83 | 83 |
_NoSubCounter &operator++() { ++_parent; return *this;}
|
| 84 | 84 |
int operator++(int) { _parent++; return 0;}
|
| 85 | 85 |
_NoSubCounter &operator--() { --_parent; return *this;}
|
| 86 | 86 |
int operator--(int) { _parent--; return 0;}
|
| 87 | 87 |
_NoSubCounter &operator+=(int c) { _parent+=c; return *this;}
|
| 88 | 88 |
_NoSubCounter &operator-=(int c) { _parent-=c; return *this;}
|
| 89 | 89 |
operator int() {return 0;}
|
| 90 | 90 |
}; |
| 91 | 91 |
|
| 92 | 92 |
|
| 93 | 93 |
/// \addtogroup timecount |
| 94 | 94 |
/// @{
|
| 95 | 95 |
|
| 96 | 96 |
/// A counter class |
| 97 | 97 |
|
| 98 | 98 |
/// This class makes it easier to count certain events (e.g. for debug |
| 99 | 99 |
/// reasons). |
| 100 | 100 |
/// You can increment or decrement the counter using \c operator++, |
| 101 | 101 |
/// \c operator--, \c operator+= and \c operator-=. You can also |
| 102 | 102 |
/// define subcounters for the different phases of the algorithm or |
| 103 | 103 |
/// for different types of operations. |
| 104 | 104 |
/// A report containing the given title and the value of the counter |
| 105 |
/// is automatically printed on destruction. |
|
| 105 |
/// is automatically printed on destruction. |
|
| 106 | 106 |
/// |
| 107 | 107 |
/// The following example shows the usage of counters and subcounters. |
| 108 | 108 |
/// \code |
| 109 | 109 |
/// // Bubble sort |
| 110 | 110 |
/// std::vector<T> v; |
| 111 | 111 |
/// ... |
| 112 | 112 |
/// Counter op("Operations: ");
|
| 113 | 113 |
/// Counter::SubCounter as(op, "Assignments: "); |
| 114 | 114 |
/// Counter::SubCounter co(op, "Comparisons: "); |
| 115 | 115 |
/// for (int i = v.size()-1; i > 0; --i) {
|
| 116 | 116 |
/// for (int j = 0; j < i; ++j) {
|
| 117 | 117 |
/// if (v[j] > v[j+1]) {
|
| 118 | 118 |
/// T tmp = v[j]; |
| 119 | 119 |
/// v[j] = v[j+1]; |
| 120 | 120 |
/// v[j+1] = tmp; |
| 121 | 121 |
/// as += 3; // three assignments |
| 122 | 122 |
/// } |
| 123 | 123 |
/// ++co; // one comparison |
| 124 | 124 |
/// } |
| 125 | 125 |
/// } |
| 126 | 126 |
/// \endcode |
| 127 | 127 |
/// |
| 128 | 128 |
/// This code prints out something like that: |
| 129 | 129 |
/// \code |
| 130 | 130 |
/// Comparisons: 45 |
| 131 | 131 |
/// Assignments: 57 |
| 132 | 132 |
/// Operations: 102 |
| 133 | 133 |
/// \endcode |
| 134 | 134 |
/// |
| 135 | 135 |
/// \sa NoCounter |
| 136 |
class Counter |
|
| 136 |
class Counter |
|
| 137 | 137 |
{
|
| 138 | 138 |
std::string _title; |
| 139 | 139 |
std::ostream &_os; |
| 140 | 140 |
int count; |
| 141 | 141 |
public: |
| 142 | 142 |
|
| 143 | 143 |
/// SubCounter class |
| 144 |
|
|
| 144 |
|
|
| 145 | 145 |
/// This class can be used to setup subcounters for a \ref Counter |
| 146 | 146 |
/// to have finer reports. A subcounter provides exactly the same |
| 147 | 147 |
/// operations as the main \ref Counter, but it also increments and |
| 148 | 148 |
/// decrements the value of its parent. |
| 149 | 149 |
/// Subcounters can also have subcounters. |
| 150 |
/// |
|
| 150 |
/// |
|
| 151 | 151 |
/// The parent counter must be given as the first parameter of the |
| 152 | 152 |
/// constructor. Apart from that a title and an \c ostream object |
| 153 | 153 |
/// can also be given just like for the main \ref Counter. |
| 154 | 154 |
/// |
| 155 | 155 |
/// A report containing the given title and the value of the |
| 156 | 156 |
/// subcounter is automatically printed on destruction. If you |
| 157 | 157 |
/// would like to turn off this report, use \ref NoSubCounter |
| 158 | 158 |
/// instead. |
| 159 |
/// |
|
| 159 |
/// |
|
| 160 | 160 |
/// \sa NoSubCounter |
| 161 | 161 |
typedef _SubCounter<Counter> SubCounter; |
| 162 | 162 |
|
| 163 |
/// SubCounter class without printing report on destruction |
|
| 164 |
|
|
| 163 |
/// SubCounter class without printing report on destruction |
|
| 164 |
|
|
| 165 | 165 |
/// This class can be used to setup subcounters for a \ref Counter. |
| 166 | 166 |
/// It is the same as \ref SubCounter but it does not print report |
| 167 | 167 |
/// on destruction. (It modifies the value of its parent, so 'No' |
| 168 | 168 |
/// only means 'do not print'.) |
| 169 | 169 |
/// |
| 170 | 170 |
/// Replacing \ref SubCounter "SubCounter"s with \ref NoSubCounter |
| 171 |
/// "NoSubCounter"s makes it possible to turn off reporting |
|
| 171 |
/// "NoSubCounter"s makes it possible to turn off reporting |
|
| 172 | 172 |
/// subcounter values without actually removing the definitions |
| 173 | 173 |
/// and the increment or decrement operators. |
| 174 | 174 |
/// |
| 175 | 175 |
/// \sa SubCounter |
| 176 | 176 |
typedef _NoSubCounter<Counter> NoSubCounter; |
| 177 | 177 |
|
| 178 | 178 |
/// Constructor. |
| 179 | 179 |
Counter() : _title(), _os(std::cerr), count(0) {}
|
| 180 | 180 |
/// Constructor. |
| 181 |
Counter(std::string title,std::ostream &os=std::cerr) |
|
| 181 |
Counter(std::string title,std::ostream &os=std::cerr) |
|
| 182 | 182 |
: _title(title), _os(os), count(0) {}
|
| 183 | 183 |
/// Constructor. |
| 184 | 184 |
Counter(const char *title,std::ostream &os=std::cerr) |
| 185 | 185 |
: _title(title), _os(os), count(0) {}
|
| 186 | 186 |
/// Destructor. Prints the given title and the value of the counter. |
| 187 | 187 |
~Counter() {
|
| 188 | 188 |
_os << _title << count <<std::endl; |
| 189 | 189 |
} |
| 190 | 190 |
///\e |
| 191 | 191 |
Counter &operator++() { count++; return *this;}
|
| 192 | 192 |
///\e |
| 193 | 193 |
int operator++(int) { return count++;}
|
| 194 | 194 |
///\e |
| 195 | 195 |
Counter &operator--() { count--; return *this;}
|
| 196 | 196 |
///\e |
| 197 | 197 |
int operator--(int) { return count--;}
|
| 198 | 198 |
///\e |
| 199 | 199 |
Counter &operator+=(int c) { count+=c; return *this;}
|
| 200 | 200 |
///\e |
| 201 | 201 |
Counter &operator-=(int c) { count-=c; return *this;}
|
| 202 | 202 |
/// Resets the counter to the given value. |
| 203 | 203 |
|
| 204 | 204 |
/// Resets the counter to the given value. |
| 205 | 205 |
/// \note This function does not reset the values of |
| 206 | 206 |
/// \ref SubCounter "SubCounter"s but it resets \ref NoSubCounter |
| 207 |
/// "NoSubCounter"s along with the main counter. |
|
| 207 |
/// "NoSubCounter"s along with the main counter. |
|
| 208 | 208 |
void reset(int c=0) {count=c;}
|
| 209 | 209 |
/// Returns the value of the counter. |
| 210 | 210 |
operator int() {return count;}
|
| 211 | 211 |
}; |
| 212 | 212 |
|
| 213 | 213 |
/// 'Do nothing' version of Counter. |
| 214 | 214 |
|
| 215 | 215 |
/// This class can be used in the same way as \ref Counter however it |
| 216 | 216 |
/// does not count at all and does not print report on destruction. |
| 217 | 217 |
/// |
| 218 | 218 |
/// Replacing a \ref Counter with a \ref NoCounter makes it possible |
| 219 | 219 |
/// to turn off all counting and reporting (SubCounters should also |
| 220 | 220 |
/// be replaced with NoSubCounters), so it does not affect the |
| 221 | 221 |
/// efficiency of the program at all. |
| 222 | 222 |
/// |
| 223 | 223 |
/// \sa Counter |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_DFS_H |
| ... | ... |
@@ -21,157 +21,157 @@ |
| 21 | 21 |
|
| 22 | 22 |
///\ingroup search |
| 23 | 23 |
///\file |
| 24 | 24 |
///\brief Dfs algorithm. |
| 25 | 25 |
|
| 26 | 26 |
#include <lemon/list_graph.h> |
| 27 | 27 |
#include <lemon/graph_utils.h> |
| 28 | 28 |
#include <lemon/bits/path_dump.h> |
| 29 | 29 |
#include <lemon/bits/invalid.h> |
| 30 | 30 |
#include <lemon/error.h> |
| 31 | 31 |
#include <lemon/maps.h> |
| 32 | 32 |
|
| 33 | 33 |
#include <lemon/concept_check.h> |
| 34 | 34 |
|
| 35 | 35 |
namespace lemon {
|
| 36 | 36 |
|
| 37 |
|
|
| 37 |
|
|
| 38 | 38 |
///Default traits class of Dfs class. |
| 39 | 39 |
|
| 40 | 40 |
///Default traits class of Dfs class. |
| 41 | 41 |
///\tparam GR Digraph type. |
| 42 | 42 |
template<class GR> |
| 43 | 43 |
struct DfsDefaultTraits |
| 44 | 44 |
{
|
| 45 |
///The digraph type the algorithm runs on. |
|
| 45 |
///The digraph type the algorithm runs on. |
|
| 46 | 46 |
typedef GR Digraph; |
| 47 | 47 |
///\brief The type of the map that stores the last |
| 48 | 48 |
///arcs of the %DFS paths. |
| 49 |
/// |
|
| 49 |
/// |
|
| 50 | 50 |
///The type of the map that stores the last |
| 51 | 51 |
///arcs of the %DFS paths. |
| 52 | 52 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 53 | 53 |
/// |
| 54 | 54 |
typedef typename Digraph::template NodeMap<typename GR::Arc> PredMap; |
| 55 | 55 |
///Instantiates a PredMap. |
| 56 |
|
|
| 57 |
///This function instantiates a \ref PredMap. |
|
| 56 |
|
|
| 57 |
///This function instantiates a \ref PredMap. |
|
| 58 | 58 |
///\param G is the digraph, to which we would like to define the PredMap. |
| 59 | 59 |
///\todo The digraph alone may be insufficient to initialize |
| 60 |
static PredMap *createPredMap(const GR &G) |
|
| 60 |
static PredMap *createPredMap(const GR &G) |
|
| 61 | 61 |
{
|
| 62 | 62 |
return new PredMap(G); |
| 63 | 63 |
} |
| 64 | 64 |
|
| 65 | 65 |
///The type of the map that indicates which nodes are processed. |
| 66 |
|
|
| 66 |
|
|
| 67 | 67 |
///The type of the map that indicates which nodes are processed. |
| 68 | 68 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 69 | 69 |
///\todo named parameter to set this type, function to read and write. |
| 70 | 70 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 71 | 71 |
///Instantiates a ProcessedMap. |
| 72 |
|
|
| 73 |
///This function instantiates a \ref ProcessedMap. |
|
| 72 |
|
|
| 73 |
///This function instantiates a \ref ProcessedMap. |
|
| 74 | 74 |
///\param g is the digraph, to which |
| 75 | 75 |
///we would like to define the \ref ProcessedMap |
| 76 | 76 |
#ifdef DOXYGEN |
| 77 | 77 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 78 | 78 |
#else |
| 79 | 79 |
static ProcessedMap *createProcessedMap(const GR &) |
| 80 | 80 |
#endif |
| 81 | 81 |
{
|
| 82 | 82 |
return new ProcessedMap(); |
| 83 | 83 |
} |
| 84 | 84 |
///The type of the map that indicates which nodes are reached. |
| 85 |
|
|
| 85 |
|
|
| 86 | 86 |
///The type of the map that indicates which nodes are reached. |
| 87 | 87 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 88 | 88 |
///\todo named parameter to set this type, function to read and write. |
| 89 | 89 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 90 | 90 |
///Instantiates a ReachedMap. |
| 91 |
|
|
| 92 |
///This function instantiates a \ref ReachedMap. |
|
| 91 |
|
|
| 92 |
///This function instantiates a \ref ReachedMap. |
|
| 93 | 93 |
///\param G is the digraph, to which |
| 94 | 94 |
///we would like to define the \ref ReachedMap. |
| 95 | 95 |
static ReachedMap *createReachedMap(const GR &G) |
| 96 | 96 |
{
|
| 97 | 97 |
return new ReachedMap(G); |
| 98 | 98 |
} |
| 99 | 99 |
///The type of the map that stores the dists of the nodes. |
| 100 |
|
|
| 100 |
|
|
| 101 | 101 |
///The type of the map that stores the dists of the nodes. |
| 102 | 102 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 103 | 103 |
/// |
| 104 | 104 |
typedef typename Digraph::template NodeMap<int> DistMap; |
| 105 | 105 |
///Instantiates a DistMap. |
| 106 |
|
|
| 107 |
///This function instantiates a \ref DistMap. |
|
| 106 |
|
|
| 107 |
///This function instantiates a \ref DistMap. |
|
| 108 | 108 |
///\param G is the digraph, to which we would like to define the \ref DistMap |
| 109 | 109 |
static DistMap *createDistMap(const GR &G) |
| 110 | 110 |
{
|
| 111 | 111 |
return new DistMap(G); |
| 112 | 112 |
} |
| 113 | 113 |
}; |
| 114 |
|
|
| 114 |
|
|
| 115 | 115 |
///%DFS algorithm class. |
| 116 |
|
|
| 116 |
|
|
| 117 | 117 |
///\ingroup search |
| 118 | 118 |
///This class provides an efficient implementation of the %DFS algorithm. |
| 119 | 119 |
/// |
| 120 | 120 |
///\tparam GR The digraph type the algorithm runs on. The default value is |
| 121 | 121 |
///\ref ListDigraph. The value of GR is not used directly by Dfs, it |
| 122 | 122 |
///is only passed to \ref DfsDefaultTraits. |
| 123 | 123 |
///\tparam TR Traits class to set various data types used by the algorithm. |
| 124 | 124 |
///The default traits class is |
| 125 | 125 |
///\ref DfsDefaultTraits "DfsDefaultTraits<GR>". |
| 126 | 126 |
///See \ref DfsDefaultTraits for the documentation of |
| 127 | 127 |
///a Dfs traits class. |
| 128 | 128 |
#ifdef DOXYGEN |
| 129 | 129 |
template <typename GR, |
| 130 |
|
|
| 130 |
typename TR> |
|
| 131 | 131 |
#else |
| 132 | 132 |
template <typename GR=ListDigraph, |
| 133 |
|
|
| 133 |
typename TR=DfsDefaultTraits<GR> > |
|
| 134 | 134 |
#endif |
| 135 | 135 |
class Dfs {
|
| 136 | 136 |
public: |
| 137 | 137 |
/** |
| 138 | 138 |
* \brief \ref Exception for uninitialized parameters. |
| 139 | 139 |
* |
| 140 | 140 |
* This error represents problems in the initialization |
| 141 | 141 |
* of the parameters of the algorithms. |
| 142 | 142 |
*/ |
| 143 | 143 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
| 144 | 144 |
public: |
| 145 | 145 |
virtual const char* what() const throw() {
|
| 146 |
|
|
| 146 |
return "lemon::Dfs::UninitializedParameter"; |
|
| 147 | 147 |
} |
| 148 | 148 |
}; |
| 149 | 149 |
|
| 150 | 150 |
typedef TR Traits; |
| 151 | 151 |
///The type of the underlying digraph. |
| 152 | 152 |
typedef typename TR::Digraph Digraph; |
| 153 | 153 |
///\e |
| 154 | 154 |
typedef typename Digraph::Node Node; |
| 155 | 155 |
///\e |
| 156 | 156 |
typedef typename Digraph::NodeIt NodeIt; |
| 157 | 157 |
///\e |
| 158 | 158 |
typedef typename Digraph::Arc Arc; |
| 159 | 159 |
///\e |
| 160 | 160 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 161 |
|
|
| 161 |
|
|
| 162 | 162 |
///\brief The type of the map that stores the last |
| 163 | 163 |
///arcs of the %DFS paths. |
| 164 | 164 |
typedef typename TR::PredMap PredMap; |
| 165 | 165 |
///The type of the map indicating which nodes are reached. |
| 166 | 166 |
typedef typename TR::ReachedMap ReachedMap; |
| 167 | 167 |
///The type of the map indicating which nodes are processed. |
| 168 | 168 |
typedef typename TR::ProcessedMap ProcessedMap; |
| 169 | 169 |
///The type of the map that stores the dists of the nodes. |
| 170 | 170 |
typedef typename TR::DistMap DistMap; |
| 171 | 171 |
private: |
| 172 | 172 |
/// Pointer to the underlying digraph. |
| 173 | 173 |
const Digraph *G; |
| 174 | 174 |
///Pointer to the map of predecessors arcs. |
| 175 | 175 |
PredMap *_pred; |
| 176 | 176 |
///Indicates if \ref _pred is locally allocated (\c true) or not. |
| 177 | 177 |
bool local_pred; |
| ... | ... |
@@ -179,710 +179,710 @@ |
| 179 | 179 |
DistMap *_dist; |
| 180 | 180 |
///Indicates if \ref _dist is locally allocated (\c true) or not. |
| 181 | 181 |
bool local_dist; |
| 182 | 182 |
///Pointer to the map of reached status of the nodes. |
| 183 | 183 |
ReachedMap *_reached; |
| 184 | 184 |
///Indicates if \ref _reached is locally allocated (\c true) or not. |
| 185 | 185 |
bool local_reached; |
| 186 | 186 |
///Pointer to the map of processed status of the nodes. |
| 187 | 187 |
ProcessedMap *_processed; |
| 188 | 188 |
///Indicates if \ref _processed is locally allocated (\c true) or not. |
| 189 | 189 |
bool local_processed; |
| 190 | 190 |
|
| 191 | 191 |
std::vector<typename Digraph::OutArcIt> _stack; |
| 192 | 192 |
int _stack_head; |
| 193 | 193 |
|
| 194 | 194 |
///Creates the maps if necessary. |
| 195 |
|
|
| 195 |
|
|
| 196 | 196 |
///\todo Better memory allocation (instead of new). |
| 197 |
void create_maps() |
|
| 197 |
void create_maps() |
|
| 198 | 198 |
{
|
| 199 | 199 |
if(!_pred) {
|
| 200 |
local_pred = true; |
|
| 201 |
_pred = Traits::createPredMap(*G); |
|
| 200 |
local_pred = true; |
|
| 201 |
_pred = Traits::createPredMap(*G); |
|
| 202 | 202 |
} |
| 203 | 203 |
if(!_dist) {
|
| 204 |
local_dist = true; |
|
| 205 |
_dist = Traits::createDistMap(*G); |
|
| 204 |
local_dist = true; |
|
| 205 |
_dist = Traits::createDistMap(*G); |
|
| 206 | 206 |
} |
| 207 | 207 |
if(!_reached) {
|
| 208 |
local_reached = true; |
|
| 209 |
_reached = Traits::createReachedMap(*G); |
|
| 208 |
local_reached = true; |
|
| 209 |
_reached = Traits::createReachedMap(*G); |
|
| 210 | 210 |
} |
| 211 | 211 |
if(!_processed) {
|
| 212 |
local_processed = true; |
|
| 213 |
_processed = Traits::createProcessedMap(*G); |
|
| 212 |
local_processed = true; |
|
| 213 |
_processed = Traits::createProcessedMap(*G); |
|
| 214 | 214 |
} |
| 215 | 215 |
} |
| 216 | 216 |
|
| 217 | 217 |
protected: |
| 218 | 218 |
|
| 219 | 219 |
Dfs() {}
|
| 220 |
|
|
| 220 |
|
|
| 221 | 221 |
public: |
| 222 | 222 |
|
| 223 | 223 |
typedef Dfs Create; |
| 224 | 224 |
|
| 225 | 225 |
///\name Named template parameters |
| 226 | 226 |
|
| 227 | 227 |
///@{
|
| 228 | 228 |
|
| 229 | 229 |
template <class T> |
| 230 | 230 |
struct DefPredMapTraits : public Traits {
|
| 231 | 231 |
typedef T PredMap; |
| 232 |
static PredMap *createPredMap(const Digraph &G) |
|
| 232 |
static PredMap *createPredMap(const Digraph &G) |
|
| 233 | 233 |
{
|
| 234 |
|
|
| 234 |
throw UninitializedParameter(); |
|
| 235 | 235 |
} |
| 236 | 236 |
}; |
| 237 | 237 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 238 | 238 |
///PredMap type |
| 239 | 239 |
/// |
| 240 | 240 |
///\ref named-templ-param "Named parameter" for setting PredMap type |
| 241 | 241 |
/// |
| 242 | 242 |
template <class T> |
| 243 | 243 |
struct DefPredMap : public Dfs<Digraph, DefPredMapTraits<T> > {
|
| 244 | 244 |
typedef Dfs<Digraph, DefPredMapTraits<T> > Create; |
| 245 | 245 |
}; |
| 246 |
|
|
| 247 |
|
|
| 246 |
|
|
| 247 |
|
|
| 248 | 248 |
template <class T> |
| 249 | 249 |
struct DefDistMapTraits : public Traits {
|
| 250 | 250 |
typedef T DistMap; |
| 251 |
static DistMap *createDistMap(const Digraph &) |
|
| 251 |
static DistMap *createDistMap(const Digraph &) |
|
| 252 | 252 |
{
|
| 253 |
|
|
| 253 |
throw UninitializedParameter(); |
|
| 254 | 254 |
} |
| 255 | 255 |
}; |
| 256 | 256 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 257 | 257 |
///DistMap type |
| 258 | 258 |
/// |
| 259 | 259 |
///\ref named-templ-param "Named parameter" for setting DistMap |
| 260 | 260 |
///type |
| 261 | 261 |
template <class T> |
| 262 | 262 |
struct DefDistMap {
|
| 263 | 263 |
typedef Dfs<Digraph, DefDistMapTraits<T> > Create; |
| 264 | 264 |
}; |
| 265 |
|
|
| 265 |
|
|
| 266 | 266 |
template <class T> |
| 267 | 267 |
struct DefReachedMapTraits : public Traits {
|
| 268 | 268 |
typedef T ReachedMap; |
| 269 |
static ReachedMap *createReachedMap(const Digraph &) |
|
| 269 |
static ReachedMap *createReachedMap(const Digraph &) |
|
| 270 | 270 |
{
|
| 271 |
|
|
| 271 |
throw UninitializedParameter(); |
|
| 272 | 272 |
} |
| 273 | 273 |
}; |
| 274 | 274 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 275 | 275 |
///ReachedMap type |
| 276 | 276 |
/// |
| 277 | 277 |
///\ref named-templ-param "Named parameter" for setting ReachedMap type |
| 278 | 278 |
/// |
| 279 | 279 |
template <class T> |
| 280 | 280 |
struct DefReachedMap : public Dfs< Digraph, DefReachedMapTraits<T> > {
|
| 281 | 281 |
typedef Dfs< Digraph, DefReachedMapTraits<T> > Create; |
| 282 | 282 |
}; |
| 283 | 283 |
|
| 284 | 284 |
template <class T> |
| 285 | 285 |
struct DefProcessedMapTraits : public Traits {
|
| 286 | 286 |
typedef T ProcessedMap; |
| 287 |
static ProcessedMap *createProcessedMap(const Digraph &) |
|
| 287 |
static ProcessedMap *createProcessedMap(const Digraph &) |
|
| 288 | 288 |
{
|
| 289 |
|
|
| 289 |
throw UninitializedParameter(); |
|
| 290 | 290 |
} |
| 291 | 291 |
}; |
| 292 | 292 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 293 | 293 |
///ProcessedMap type |
| 294 | 294 |
/// |
| 295 | 295 |
///\ref named-templ-param "Named parameter" for setting ProcessedMap type |
| 296 | 296 |
/// |
| 297 | 297 |
template <class T> |
| 298 |
struct DefProcessedMap : public Dfs< Digraph, DefProcessedMapTraits<T> > {
|
|
| 298 |
struct DefProcessedMap : public Dfs< Digraph, DefProcessedMapTraits<T> > {
|
|
| 299 | 299 |
typedef Dfs< Digraph, DefProcessedMapTraits<T> > Create; |
| 300 | 300 |
}; |
| 301 |
|
|
| 301 |
|
|
| 302 | 302 |
struct DefDigraphProcessedMapTraits : public Traits {
|
| 303 | 303 |
typedef typename Digraph::template NodeMap<bool> ProcessedMap; |
| 304 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 304 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 305 | 305 |
{
|
| 306 |
|
|
| 306 |
return new ProcessedMap(G); |
|
| 307 | 307 |
} |
| 308 | 308 |
}; |
| 309 | 309 |
///\brief \ref named-templ-param "Named parameter" |
| 310 | 310 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 311 | 311 |
/// |
| 312 | 312 |
///\ref named-templ-param "Named parameter" |
| 313 | 313 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 314 | 314 |
///If you don't set it explicitely, it will be automatically allocated. |
| 315 | 315 |
template <class T> |
| 316 | 316 |
class DefProcessedMapToBeDefaultMap : |
| 317 |
public Dfs< Digraph, DefDigraphProcessedMapTraits> {
|
|
| 317 |
public Dfs< Digraph, DefDigraphProcessedMapTraits> {
|
|
| 318 | 318 |
typedef Dfs< Digraph, DefDigraphProcessedMapTraits> Create; |
| 319 | 319 |
}; |
| 320 |
|
|
| 320 |
|
|
| 321 | 321 |
///@} |
| 322 | 322 |
|
| 323 |
public: |
|
| 324 |
|
|
| 323 |
public: |
|
| 324 |
|
|
| 325 | 325 |
///Constructor. |
| 326 |
|
|
| 326 |
|
|
| 327 | 327 |
///\param _G the digraph the algorithm will run on. |
| 328 | 328 |
/// |
| 329 | 329 |
Dfs(const Digraph& _G) : |
| 330 | 330 |
G(&_G), |
| 331 | 331 |
_pred(NULL), local_pred(false), |
| 332 | 332 |
_dist(NULL), local_dist(false), |
| 333 | 333 |
_reached(NULL), local_reached(false), |
| 334 | 334 |
_processed(NULL), local_processed(false) |
| 335 | 335 |
{ }
|
| 336 |
|
|
| 336 |
|
|
| 337 | 337 |
///Destructor. |
| 338 |
~Dfs() |
|
| 338 |
~Dfs() |
|
| 339 | 339 |
{
|
| 340 | 340 |
if(local_pred) delete _pred; |
| 341 | 341 |
if(local_dist) delete _dist; |
| 342 | 342 |
if(local_reached) delete _reached; |
| 343 | 343 |
if(local_processed) delete _processed; |
| 344 | 344 |
} |
| 345 | 345 |
|
| 346 | 346 |
///Sets the map storing the predecessor arcs. |
| 347 | 347 |
|
| 348 | 348 |
///Sets the map storing the predecessor arcs. |
| 349 | 349 |
///If you don't use this function before calling \ref run(), |
| 350 | 350 |
///it will allocate one. The destuctor deallocates this |
| 351 | 351 |
///automatically allocated map, of course. |
| 352 | 352 |
///\return <tt> (*this) </tt> |
| 353 |
Dfs &predMap(PredMap &m) |
|
| 353 |
Dfs &predMap(PredMap &m) |
|
| 354 | 354 |
{
|
| 355 | 355 |
if(local_pred) {
|
| 356 |
delete _pred; |
|
| 357 |
local_pred=false; |
|
| 356 |
delete _pred; |
|
| 357 |
local_pred=false; |
|
| 358 | 358 |
} |
| 359 | 359 |
_pred = &m; |
| 360 | 360 |
return *this; |
| 361 | 361 |
} |
| 362 | 362 |
|
| 363 | 363 |
///Sets the map storing the distances calculated by the algorithm. |
| 364 | 364 |
|
| 365 | 365 |
///Sets the map storing the distances calculated by the algorithm. |
| 366 | 366 |
///If you don't use this function before calling \ref run(), |
| 367 | 367 |
///it will allocate one. The destuctor deallocates this |
| 368 | 368 |
///automatically allocated map, of course. |
| 369 | 369 |
///\return <tt> (*this) </tt> |
| 370 |
Dfs &distMap(DistMap &m) |
|
| 370 |
Dfs &distMap(DistMap &m) |
|
| 371 | 371 |
{
|
| 372 | 372 |
if(local_dist) {
|
| 373 |
delete _dist; |
|
| 374 |
local_dist=false; |
|
| 373 |
delete _dist; |
|
| 374 |
local_dist=false; |
|
| 375 | 375 |
} |
| 376 | 376 |
_dist = &m; |
| 377 | 377 |
return *this; |
| 378 | 378 |
} |
| 379 | 379 |
|
| 380 | 380 |
///Sets the map indicating if a node is reached. |
| 381 | 381 |
|
| 382 | 382 |
///Sets the map indicating if a node is reached. |
| 383 | 383 |
///If you don't use this function before calling \ref run(), |
| 384 | 384 |
///it will allocate one. The destuctor deallocates this |
| 385 | 385 |
///automatically allocated map, of course. |
| 386 | 386 |
///\return <tt> (*this) </tt> |
| 387 |
Dfs &reachedMap(ReachedMap &m) |
|
| 387 |
Dfs &reachedMap(ReachedMap &m) |
|
| 388 | 388 |
{
|
| 389 | 389 |
if(local_reached) {
|
| 390 |
delete _reached; |
|
| 391 |
local_reached=false; |
|
| 390 |
delete _reached; |
|
| 391 |
local_reached=false; |
|
| 392 | 392 |
} |
| 393 | 393 |
_reached = &m; |
| 394 | 394 |
return *this; |
| 395 | 395 |
} |
| 396 | 396 |
|
| 397 | 397 |
///Sets the map indicating if a node is processed. |
| 398 | 398 |
|
| 399 | 399 |
///Sets the map indicating if a node is processed. |
| 400 | 400 |
///If you don't use this function before calling \ref run(), |
| 401 | 401 |
///it will allocate one. The destuctor deallocates this |
| 402 | 402 |
///automatically allocated map, of course. |
| 403 | 403 |
///\return <tt> (*this) </tt> |
| 404 |
Dfs &processedMap(ProcessedMap &m) |
|
| 404 |
Dfs &processedMap(ProcessedMap &m) |
|
| 405 | 405 |
{
|
| 406 | 406 |
if(local_processed) {
|
| 407 |
delete _processed; |
|
| 408 |
local_processed=false; |
|
| 407 |
delete _processed; |
|
| 408 |
local_processed=false; |
|
| 409 | 409 |
} |
| 410 | 410 |
_processed = &m; |
| 411 | 411 |
return *this; |
| 412 | 412 |
} |
| 413 | 413 |
|
| 414 | 414 |
public: |
| 415 | 415 |
///\name Execution control |
| 416 | 416 |
///The simplest way to execute the algorithm is to use |
| 417 | 417 |
///one of the member functions called \c run(...). |
| 418 | 418 |
///\n |
| 419 | 419 |
///If you need more control on the execution, |
| 420 | 420 |
///first you must call \ref init(), then you can add a source node |
| 421 | 421 |
///with \ref addSource(). |
| 422 | 422 |
///Finally \ref start() will perform the actual path |
| 423 | 423 |
///computation. |
| 424 | 424 |
|
| 425 | 425 |
///@{
|
| 426 | 426 |
|
| 427 | 427 |
///Initializes the internal data structures. |
| 428 | 428 |
|
| 429 | 429 |
///Initializes the internal data structures. |
| 430 | 430 |
/// |
| 431 | 431 |
void init() |
| 432 | 432 |
{
|
| 433 | 433 |
create_maps(); |
| 434 | 434 |
_stack.resize(countNodes(*G)); |
| 435 | 435 |
_stack_head=-1; |
| 436 | 436 |
for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
|
| 437 |
_pred->set(u,INVALID); |
|
| 438 |
// _predNode->set(u,INVALID); |
|
| 439 |
_reached->set(u,false); |
|
| 440 |
_processed->set(u,false); |
|
| 437 |
_pred->set(u,INVALID); |
|
| 438 |
// _predNode->set(u,INVALID); |
|
| 439 |
_reached->set(u,false); |
|
| 440 |
_processed->set(u,false); |
|
| 441 | 441 |
} |
| 442 | 442 |
} |
| 443 |
|
|
| 443 |
|
|
| 444 | 444 |
///Adds a new source node. |
| 445 | 445 |
|
| 446 | 446 |
///Adds a new source node to the set of nodes to be processed. |
| 447 | 447 |
/// |
| 448 | 448 |
///\warning dists are wrong (or at least strange) |
| 449 | 449 |
///in case of multiple sources. |
| 450 | 450 |
void addSource(Node s) |
| 451 | 451 |
{
|
| 452 | 452 |
if(!(*_reached)[s]) |
| 453 |
{
|
|
| 454 |
_reached->set(s,true); |
|
| 455 |
_pred->set(s,INVALID); |
|
| 456 |
OutArcIt e(*G,s); |
|
| 457 |
if(e!=INVALID) {
|
|
| 458 |
_stack[++_stack_head]=e; |
|
| 459 |
_dist->set(s,_stack_head); |
|
| 460 |
} |
|
| 461 |
else {
|
|
| 462 |
_processed->set(s,true); |
|
| 463 |
_dist->set(s,0); |
|
| 464 |
} |
|
| 465 |
|
|
| 453 |
{
|
|
| 454 |
_reached->set(s,true); |
|
| 455 |
_pred->set(s,INVALID); |
|
| 456 |
OutArcIt e(*G,s); |
|
| 457 |
if(e!=INVALID) {
|
|
| 458 |
_stack[++_stack_head]=e; |
|
| 459 |
_dist->set(s,_stack_head); |
|
| 460 |
} |
|
| 461 |
else {
|
|
| 462 |
_processed->set(s,true); |
|
| 463 |
_dist->set(s,0); |
|
| 464 |
} |
|
| 465 |
} |
|
| 466 | 466 |
} |
| 467 |
|
|
| 467 |
|
|
| 468 | 468 |
///Processes the next arc. |
| 469 | 469 |
|
| 470 | 470 |
///Processes the next arc. |
| 471 | 471 |
/// |
| 472 | 472 |
///\return The processed arc. |
| 473 | 473 |
/// |
| 474 | 474 |
///\pre The stack must not be empty! |
| 475 | 475 |
Arc processNextArc() |
| 476 |
{
|
|
| 476 |
{
|
|
| 477 | 477 |
Node m; |
| 478 | 478 |
Arc e=_stack[_stack_head]; |
| 479 | 479 |
if(!(*_reached)[m=G->target(e)]) {
|
| 480 |
_pred->set(m,e); |
|
| 481 |
_reached->set(m,true); |
|
| 482 |
++_stack_head; |
|
| 483 |
_stack[_stack_head] = OutArcIt(*G, m); |
|
| 484 |
|
|
| 480 |
_pred->set(m,e); |
|
| 481 |
_reached->set(m,true); |
|
| 482 |
++_stack_head; |
|
| 483 |
_stack[_stack_head] = OutArcIt(*G, m); |
|
| 484 |
_dist->set(m,_stack_head); |
|
| 485 | 485 |
} |
| 486 | 486 |
else {
|
| 487 |
m=G->source(e); |
|
| 488 |
++_stack[_stack_head]; |
|
| 487 |
m=G->source(e); |
|
| 488 |
++_stack[_stack_head]; |
|
| 489 | 489 |
} |
| 490 | 490 |
while(_stack_head>=0 && _stack[_stack_head]==INVALID) {
|
| 491 |
_processed->set(m,true); |
|
| 492 |
--_stack_head; |
|
| 493 |
if(_stack_head>=0) {
|
|
| 494 |
m=G->source(_stack[_stack_head]); |
|
| 495 |
++_stack[_stack_head]; |
|
| 496 |
} |
|
| 491 |
_processed->set(m,true); |
|
| 492 |
--_stack_head; |
|
| 493 |
if(_stack_head>=0) {
|
|
| 494 |
m=G->source(_stack[_stack_head]); |
|
| 495 |
++_stack[_stack_head]; |
|
| 496 |
} |
|
| 497 | 497 |
} |
| 498 | 498 |
return e; |
| 499 | 499 |
} |
| 500 | 500 |
///Next arc to be processed. |
| 501 | 501 |
|
| 502 | 502 |
///Next arc to be processed. |
| 503 | 503 |
/// |
| 504 | 504 |
///\return The next arc to be processed or INVALID if the stack is |
| 505 | 505 |
/// empty. |
| 506 | 506 |
OutArcIt nextArc() |
| 507 |
{
|
|
| 507 |
{
|
|
| 508 | 508 |
return _stack_head>=0?_stack[_stack_head]:INVALID; |
| 509 | 509 |
} |
| 510 | 510 |
|
| 511 | 511 |
///\brief Returns \c false if there are nodes |
| 512 | 512 |
///to be processed in the queue |
| 513 | 513 |
/// |
| 514 | 514 |
///Returns \c false if there are nodes |
| 515 | 515 |
///to be processed in the queue |
| 516 | 516 |
bool emptyQueue() { return _stack_head<0; }
|
| 517 | 517 |
///Returns the number of the nodes to be processed. |
| 518 |
|
|
| 518 |
|
|
| 519 | 519 |
///Returns the number of the nodes to be processed in the queue. |
| 520 | 520 |
int queueSize() { return _stack_head+1; }
|
| 521 |
|
|
| 521 |
|
|
| 522 | 522 |
///Executes the algorithm. |
| 523 | 523 |
|
| 524 | 524 |
///Executes the algorithm. |
| 525 | 525 |
/// |
| 526 | 526 |
///\pre init() must be called and at least one node should be added |
| 527 | 527 |
///with addSource() before using this function. |
| 528 | 528 |
/// |
| 529 | 529 |
///This method runs the %DFS algorithm from the root node(s) |
| 530 | 530 |
///in order to |
| 531 | 531 |
///compute the |
| 532 | 532 |
///%DFS path to each node. The algorithm computes |
| 533 | 533 |
///- The %DFS tree. |
| 534 | 534 |
///- The distance of each node from the root(s) in the %DFS tree. |
| 535 | 535 |
/// |
| 536 | 536 |
void start() |
| 537 | 537 |
{
|
| 538 | 538 |
while ( !emptyQueue() ) processNextArc(); |
| 539 | 539 |
} |
| 540 |
|
|
| 540 |
|
|
| 541 | 541 |
///Executes the algorithm until \c dest is reached. |
| 542 | 542 |
|
| 543 | 543 |
///Executes the algorithm until \c dest is reached. |
| 544 | 544 |
/// |
| 545 | 545 |
///\pre init() must be called and at least one node should be added |
| 546 | 546 |
///with addSource() before using this function. |
| 547 | 547 |
/// |
| 548 | 548 |
///This method runs the %DFS algorithm from the root node(s) |
| 549 | 549 |
///in order to |
| 550 | 550 |
///compute the |
| 551 | 551 |
///%DFS path to \c dest. The algorithm computes |
| 552 | 552 |
///- The %DFS path to \c dest. |
| 553 | 553 |
///- The distance of \c dest from the root(s) in the %DFS tree. |
| 554 | 554 |
/// |
| 555 | 555 |
void start(Node dest) |
| 556 | 556 |
{
|
| 557 |
while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) |
|
| 558 |
processNextArc(); |
|
| 557 |
while ( !emptyQueue() && G->target(_stack[_stack_head])!=dest ) |
|
| 558 |
processNextArc(); |
|
| 559 | 559 |
} |
| 560 |
|
|
| 560 |
|
|
| 561 | 561 |
///Executes the algorithm until a condition is met. |
| 562 | 562 |
|
| 563 | 563 |
///Executes the algorithm until a condition is met. |
| 564 | 564 |
/// |
| 565 | 565 |
///\pre init() must be called and at least one node should be added |
| 566 | 566 |
///with addSource() before using this function. |
| 567 | 567 |
/// |
| 568 | 568 |
///\param em must be a bool (or convertible) arc map. The algorithm |
| 569 | 569 |
///will stop when it reaches an arc \c e with <tt>em[e]</tt> true. |
| 570 | 570 |
/// |
| 571 | 571 |
///\return The reached arc \c e with <tt>em[e]</tt> true or |
| 572 | 572 |
///\c INVALID if no such arc was found. |
| 573 | 573 |
/// |
| 574 | 574 |
///\warning Contrary to \ref Bfs and \ref Dijkstra, \c em is an arc map, |
| 575 | 575 |
///not a node map. |
| 576 | 576 |
template<class EM> |
| 577 | 577 |
Arc start(const EM &em) |
| 578 | 578 |
{
|
| 579 | 579 |
while ( !emptyQueue() && !em[_stack[_stack_head]] ) |
| 580 | 580 |
processNextArc(); |
| 581 | 581 |
return emptyQueue() ? INVALID : _stack[_stack_head]; |
| 582 | 582 |
} |
| 583 | 583 |
|
| 584 | 584 |
///Runs %DFS algorithm to visit all nodes in the digraph. |
| 585 |
|
|
| 585 |
|
|
| 586 | 586 |
///This method runs the %DFS algorithm in order to |
| 587 | 587 |
///compute the |
| 588 | 588 |
///%DFS path to each node. The algorithm computes |
| 589 | 589 |
///- The %DFS tree. |
| 590 | 590 |
///- The distance of each node from the root in the %DFS tree. |
| 591 | 591 |
/// |
| 592 | 592 |
///\note d.run() is just a shortcut of the following code. |
| 593 | 593 |
///\code |
| 594 | 594 |
/// d.init(); |
| 595 | 595 |
/// for (NodeIt it(digraph); it != INVALID; ++it) {
|
| 596 | 596 |
/// if (!d.reached(it)) {
|
| 597 | 597 |
/// d.addSource(it); |
| 598 | 598 |
/// d.start(); |
| 599 | 599 |
/// } |
| 600 | 600 |
/// } |
| 601 | 601 |
///\endcode |
| 602 | 602 |
void run() {
|
| 603 | 603 |
init(); |
| 604 | 604 |
for (NodeIt it(*G); it != INVALID; ++it) {
|
| 605 | 605 |
if (!reached(it)) {
|
| 606 | 606 |
addSource(it); |
| 607 | 607 |
start(); |
| 608 | 608 |
} |
| 609 | 609 |
} |
| 610 | 610 |
} |
| 611 | 611 |
|
| 612 | 612 |
///Runs %DFS algorithm from node \c s. |
| 613 |
|
|
| 613 |
|
|
| 614 | 614 |
///This method runs the %DFS algorithm from a root node \c s |
| 615 | 615 |
///in order to |
| 616 | 616 |
///compute the |
| 617 | 617 |
///%DFS path to each node. The algorithm computes |
| 618 | 618 |
///- The %DFS tree. |
| 619 | 619 |
///- The distance of each node from the root in the %DFS tree. |
| 620 | 620 |
/// |
| 621 | 621 |
///\note d.run(s) is just a shortcut of the following code. |
| 622 | 622 |
///\code |
| 623 | 623 |
/// d.init(); |
| 624 | 624 |
/// d.addSource(s); |
| 625 | 625 |
/// d.start(); |
| 626 | 626 |
///\endcode |
| 627 | 627 |
void run(Node s) {
|
| 628 | 628 |
init(); |
| 629 | 629 |
addSource(s); |
| 630 | 630 |
start(); |
| 631 | 631 |
} |
| 632 |
|
|
| 632 |
|
|
| 633 | 633 |
///Finds the %DFS path between \c s and \c t. |
| 634 |
|
|
| 634 |
|
|
| 635 | 635 |
///Finds the %DFS path between \c s and \c t. |
| 636 | 636 |
/// |
| 637 | 637 |
///\return The length of the %DFS s---t path if there exists one, |
| 638 | 638 |
///0 otherwise. |
| 639 | 639 |
///\note Apart from the return value, d.run(s,t) is |
| 640 | 640 |
///just a shortcut of the following code. |
| 641 | 641 |
///\code |
| 642 | 642 |
/// d.init(); |
| 643 | 643 |
/// d.addSource(s); |
| 644 | 644 |
/// d.start(t); |
| 645 | 645 |
///\endcode |
| 646 | 646 |
int run(Node s,Node t) {
|
| 647 | 647 |
init(); |
| 648 | 648 |
addSource(s); |
| 649 | 649 |
start(t); |
| 650 | 650 |
return reached(t)?_stack_head+1:0; |
| 651 | 651 |
} |
| 652 |
|
|
| 652 |
|
|
| 653 | 653 |
///@} |
| 654 | 654 |
|
| 655 | 655 |
///\name Query Functions |
| 656 | 656 |
///The result of the %DFS algorithm can be obtained using these |
| 657 | 657 |
///functions.\n |
| 658 | 658 |
///Before the use of these functions, |
| 659 | 659 |
///either run() or start() must be called. |
| 660 |
|
|
| 660 |
|
|
| 661 | 661 |
///@{
|
| 662 | 662 |
|
| 663 | 663 |
typedef PredMapPath<Digraph, PredMap> Path; |
| 664 | 664 |
|
| 665 | 665 |
///Gives back the shortest path. |
| 666 |
|
|
| 666 |
|
|
| 667 | 667 |
///Gives back the shortest path. |
| 668 | 668 |
///\pre The \c t should be reachable from the source. |
| 669 |
Path path(Node t) |
|
| 669 |
Path path(Node t) |
|
| 670 | 670 |
{
|
| 671 | 671 |
return Path(*G, *_pred, t); |
| 672 | 672 |
} |
| 673 | 673 |
|
| 674 | 674 |
///The distance of a node from the root(s). |
| 675 | 675 |
|
| 676 | 676 |
///Returns the distance of a node from the root(s). |
| 677 | 677 |
///\pre \ref run() must be called before using this function. |
| 678 |
///\warning If node \c v is unreachable from the root(s) then the return |
|
| 678 |
///\warning If node \c v is unreachable from the root(s) then the return |
|
| 679 | 679 |
///value of this funcion is undefined. |
| 680 | 680 |
int dist(Node v) const { return (*_dist)[v]; }
|
| 681 | 681 |
|
| 682 | 682 |
///Returns the 'previous arc' of the %DFS tree. |
| 683 | 683 |
|
| 684 | 684 |
///For a node \c v it returns the 'previous arc' |
| 685 | 685 |
///of the %DFS path, |
| 686 | 686 |
///i.e. it returns the last arc of a %DFS path from the root(s) to \c |
| 687 | 687 |
///v. It is \ref INVALID |
| 688 | 688 |
///if \c v is unreachable from the root(s) or \c v is a root. The |
| 689 | 689 |
///%DFS tree used here is equal to the %DFS tree used in |
| 690 | 690 |
///\ref predNode(). |
| 691 | 691 |
///\pre Either \ref run() or \ref start() must be called before using |
| 692 | 692 |
///this function. |
| 693 | 693 |
Arc predArc(Node v) const { return (*_pred)[v];}
|
| 694 | 694 |
|
| 695 | 695 |
///Returns the 'previous node' of the %DFS tree. |
| 696 | 696 |
|
| 697 | 697 |
///For a node \c v it returns the 'previous node' |
| 698 | 698 |
///of the %DFS tree, |
| 699 | 699 |
///i.e. it returns the last but one node from a %DFS path from the |
| 700 | 700 |
///root(s) to \c v. |
| 701 | 701 |
///It is INVALID if \c v is unreachable from the root(s) or |
| 702 | 702 |
///if \c v itself a root. |
| 703 | 703 |
///The %DFS tree used here is equal to the %DFS |
| 704 | 704 |
///tree used in \ref predArc(). |
| 705 | 705 |
///\pre Either \ref run() or \ref start() must be called before |
| 706 | 706 |
///using this function. |
| 707 | 707 |
Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
|
| 708 |
G->source((*_pred)[v]); } |
|
| 709 |
|
|
| 708 |
G->source((*_pred)[v]); } |
|
| 709 |
|
|
| 710 | 710 |
///Returns a reference to the NodeMap of distances. |
| 711 | 711 |
|
| 712 | 712 |
///Returns a reference to the NodeMap of distances. |
| 713 | 713 |
///\pre Either \ref run() or \ref init() must |
| 714 | 714 |
///be called before using this function. |
| 715 | 715 |
const DistMap &distMap() const { return *_dist;}
|
| 716 |
|
|
| 716 |
|
|
| 717 | 717 |
///Returns a reference to the %DFS arc-tree map. |
| 718 | 718 |
|
| 719 | 719 |
///Returns a reference to the NodeMap of the arcs of the |
| 720 | 720 |
///%DFS tree. |
| 721 | 721 |
///\pre Either \ref run() or \ref init() |
| 722 | 722 |
///must be called before using this function. |
| 723 | 723 |
const PredMap &predMap() const { return *_pred;}
|
| 724 |
|
|
| 724 |
|
|
| 725 | 725 |
///Checks if a node is reachable from the root. |
| 726 | 726 |
|
| 727 | 727 |
///Returns \c true if \c v is reachable from the root(s). |
| 728 | 728 |
///\warning The source nodes are inditated as unreachable. |
| 729 | 729 |
///\pre Either \ref run() or \ref start() |
| 730 | 730 |
///must be called before using this function. |
| 731 | 731 |
/// |
| 732 | 732 |
bool reached(Node v) { return (*_reached)[v]; }
|
| 733 |
|
|
| 733 |
|
|
| 734 | 734 |
///@} |
| 735 | 735 |
}; |
| 736 | 736 |
|
| 737 | 737 |
///Default traits class of Dfs function. |
| 738 | 738 |
|
| 739 | 739 |
///Default traits class of Dfs function. |
| 740 | 740 |
///\tparam GR Digraph type. |
| 741 | 741 |
template<class GR> |
| 742 | 742 |
struct DfsWizardDefaultTraits |
| 743 | 743 |
{
|
| 744 |
///The digraph type the algorithm runs on. |
|
| 744 |
///The digraph type the algorithm runs on. |
|
| 745 | 745 |
typedef GR Digraph; |
| 746 | 746 |
///\brief The type of the map that stores the last |
| 747 | 747 |
///arcs of the %DFS paths. |
| 748 |
/// |
|
| 748 |
/// |
|
| 749 | 749 |
///The type of the map that stores the last |
| 750 | 750 |
///arcs of the %DFS paths. |
| 751 | 751 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 752 | 752 |
/// |
| 753 | 753 |
typedef NullMap<typename Digraph::Node,typename GR::Arc> PredMap; |
| 754 | 754 |
///Instantiates a PredMap. |
| 755 |
|
|
| 756 |
///This function instantiates a \ref PredMap. |
|
| 755 |
|
|
| 756 |
///This function instantiates a \ref PredMap. |
|
| 757 | 757 |
///\param g is the digraph, to which we would like to define the PredMap. |
| 758 | 758 |
///\todo The digraph alone may be insufficient to initialize |
| 759 | 759 |
#ifdef DOXYGEN |
| 760 |
static PredMap *createPredMap(const GR &g) |
|
| 760 |
static PredMap *createPredMap(const GR &g) |
|
| 761 | 761 |
#else |
| 762 |
static PredMap *createPredMap(const GR &) |
|
| 762 |
static PredMap *createPredMap(const GR &) |
|
| 763 | 763 |
#endif |
| 764 | 764 |
{
|
| 765 | 765 |
return new PredMap(); |
| 766 | 766 |
} |
| 767 | 767 |
|
| 768 | 768 |
///The type of the map that indicates which nodes are processed. |
| 769 |
|
|
| 769 |
|
|
| 770 | 770 |
///The type of the map that indicates which nodes are processed. |
| 771 | 771 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 772 | 772 |
///\todo named parameter to set this type, function to read and write. |
| 773 | 773 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 774 | 774 |
///Instantiates a ProcessedMap. |
| 775 |
|
|
| 776 |
///This function instantiates a \ref ProcessedMap. |
|
| 775 |
|
|
| 776 |
///This function instantiates a \ref ProcessedMap. |
|
| 777 | 777 |
///\param g is the digraph, to which |
| 778 | 778 |
///we would like to define the \ref ProcessedMap |
| 779 | 779 |
#ifdef DOXYGEN |
| 780 | 780 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 781 | 781 |
#else |
| 782 | 782 |
static ProcessedMap *createProcessedMap(const GR &) |
| 783 | 783 |
#endif |
| 784 | 784 |
{
|
| 785 | 785 |
return new ProcessedMap(); |
| 786 | 786 |
} |
| 787 | 787 |
///The type of the map that indicates which nodes are reached. |
| 788 |
|
|
| 788 |
|
|
| 789 | 789 |
///The type of the map that indicates which nodes are reached. |
| 790 | 790 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 791 | 791 |
///\todo named parameter to set this type, function to read and write. |
| 792 | 792 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 793 | 793 |
///Instantiates a ReachedMap. |
| 794 |
|
|
| 795 |
///This function instantiates a \ref ReachedMap. |
|
| 794 |
|
|
| 795 |
///This function instantiates a \ref ReachedMap. |
|
| 796 | 796 |
///\param G is the digraph, to which |
| 797 | 797 |
///we would like to define the \ref ReachedMap. |
| 798 | 798 |
static ReachedMap *createReachedMap(const GR &G) |
| 799 | 799 |
{
|
| 800 | 800 |
return new ReachedMap(G); |
| 801 | 801 |
} |
| 802 | 802 |
///The type of the map that stores the dists of the nodes. |
| 803 |
|
|
| 803 |
|
|
| 804 | 804 |
///The type of the map that stores the dists of the nodes. |
| 805 | 805 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 806 | 806 |
/// |
| 807 | 807 |
typedef NullMap<typename Digraph::Node,int> DistMap; |
| 808 | 808 |
///Instantiates a DistMap. |
| 809 |
|
|
| 810 |
///This function instantiates a \ref DistMap. |
|
| 809 |
|
|
| 810 |
///This function instantiates a \ref DistMap. |
|
| 811 | 811 |
///\param g is the digraph, to which we would like to define the \ref DistMap |
| 812 | 812 |
#ifdef DOXYGEN |
| 813 | 813 |
static DistMap *createDistMap(const GR &g) |
| 814 | 814 |
#else |
| 815 | 815 |
static DistMap *createDistMap(const GR &) |
| 816 | 816 |
#endif |
| 817 | 817 |
{
|
| 818 | 818 |
return new DistMap(); |
| 819 | 819 |
} |
| 820 | 820 |
}; |
| 821 |
|
|
| 821 |
|
|
| 822 | 822 |
/// Default traits used by \ref DfsWizard |
| 823 | 823 |
|
| 824 | 824 |
/// To make it easier to use Dfs algorithm |
| 825 | 825 |
///we have created a wizard class. |
| 826 | 826 |
/// This \ref DfsWizard class needs default traits, |
| 827 | 827 |
///as well as the \ref Dfs class. |
| 828 | 828 |
/// The \ref DfsWizardBase is a class to be the default traits of the |
| 829 | 829 |
/// \ref DfsWizard class. |
| 830 | 830 |
template<class GR> |
| 831 | 831 |
class DfsWizardBase : public DfsWizardDefaultTraits<GR> |
| 832 | 832 |
{
|
| 833 | 833 |
|
| 834 | 834 |
typedef DfsWizardDefaultTraits<GR> Base; |
| 835 | 835 |
protected: |
| 836 | 836 |
/// Type of the nodes in the digraph. |
| 837 | 837 |
typedef typename Base::Digraph::Node Node; |
| 838 | 838 |
|
| 839 | 839 |
/// Pointer to the underlying digraph. |
| 840 | 840 |
void *_g; |
| 841 | 841 |
///Pointer to the map of reached nodes. |
| 842 | 842 |
void *_reached; |
| 843 | 843 |
///Pointer to the map of processed nodes. |
| 844 | 844 |
void *_processed; |
| 845 | 845 |
///Pointer to the map of predecessors arcs. |
| 846 | 846 |
void *_pred; |
| 847 | 847 |
///Pointer to the map of distances. |
| 848 | 848 |
void *_dist; |
| 849 | 849 |
///Pointer to the source node. |
| 850 | 850 |
Node _source; |
| 851 |
|
|
| 851 |
|
|
| 852 | 852 |
public: |
| 853 | 853 |
/// Constructor. |
| 854 |
|
|
| 854 |
|
|
| 855 | 855 |
/// This constructor does not require parameters, therefore it initiates |
| 856 | 856 |
/// all of the attributes to default values (0, INVALID). |
| 857 | 857 |
DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), |
| 858 |
|
|
| 858 |
_dist(0), _source(INVALID) {}
|
|
| 859 | 859 |
|
| 860 | 860 |
/// Constructor. |
| 861 |
|
|
| 861 |
|
|
| 862 | 862 |
/// This constructor requires some parameters, |
| 863 | 863 |
/// listed in the parameters list. |
| 864 | 864 |
/// Others are initiated to 0. |
| 865 | 865 |
/// \param g is the initial value of \ref _g |
| 866 | 866 |
/// \param s is the initial value of \ref _source |
| 867 | 867 |
DfsWizardBase(const GR &g, Node s=INVALID) : |
| 868 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 868 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 869 | 869 |
_reached(0), _processed(0), _pred(0), _dist(0), _source(s) {}
|
| 870 | 870 |
|
| 871 | 871 |
}; |
| 872 |
|
|
| 872 |
|
|
| 873 | 873 |
/// A class to make the usage of the Dfs algorithm easier |
| 874 | 874 |
|
| 875 | 875 |
/// This class is created to make it easier to use the Dfs algorithm. |
| 876 | 876 |
/// It uses the functions and features of the plain \ref Dfs, |
| 877 | 877 |
/// but it is much simpler to use it. |
| 878 | 878 |
/// |
| 879 | 879 |
/// Simplicity means that the way to change the types defined |
| 880 | 880 |
/// in the traits class is based on functions that returns the new class |
| 881 | 881 |
/// and not on templatable built-in classes. |
| 882 | 882 |
/// When using the plain \ref Dfs |
| 883 | 883 |
/// the new class with the modified type comes from |
| 884 | 884 |
/// the original class by using the :: |
| 885 | 885 |
/// operator. In the case of \ref DfsWizard only |
| 886 | 886 |
/// a function have to be called and it will |
| 887 | 887 |
/// return the needed class. |
| 888 | 888 |
/// |
| ... | ... |
@@ -891,354 +891,354 @@ |
| 891 | 891 |
/// method of it. |
| 892 | 892 |
template<class TR> |
| 893 | 893 |
class DfsWizard : public TR |
| 894 | 894 |
{
|
| 895 | 895 |
typedef TR Base; |
| 896 | 896 |
|
| 897 | 897 |
///The type of the underlying digraph. |
| 898 | 898 |
typedef typename TR::Digraph Digraph; |
| 899 | 899 |
//\e |
| 900 | 900 |
typedef typename Digraph::Node Node; |
| 901 | 901 |
//\e |
| 902 | 902 |
typedef typename Digraph::NodeIt NodeIt; |
| 903 | 903 |
//\e |
| 904 | 904 |
typedef typename Digraph::Arc Arc; |
| 905 | 905 |
//\e |
| 906 | 906 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 907 |
|
|
| 907 |
|
|
| 908 | 908 |
///\brief The type of the map that stores |
| 909 | 909 |
///the reached nodes |
| 910 | 910 |
typedef typename TR::ReachedMap ReachedMap; |
| 911 | 911 |
///\brief The type of the map that stores |
| 912 | 912 |
///the processed nodes |
| 913 | 913 |
typedef typename TR::ProcessedMap ProcessedMap; |
| 914 | 914 |
///\brief The type of the map that stores the last |
| 915 | 915 |
///arcs of the %DFS paths. |
| 916 | 916 |
typedef typename TR::PredMap PredMap; |
| 917 | 917 |
///The type of the map that stores the distances of the nodes. |
| 918 | 918 |
typedef typename TR::DistMap DistMap; |
| 919 | 919 |
|
| 920 | 920 |
public: |
| 921 | 921 |
/// Constructor. |
| 922 | 922 |
DfsWizard() : TR() {}
|
| 923 | 923 |
|
| 924 | 924 |
/// Constructor that requires parameters. |
| 925 | 925 |
|
| 926 | 926 |
/// Constructor that requires parameters. |
| 927 | 927 |
/// These parameters will be the default values for the traits class. |
| 928 | 928 |
DfsWizard(const Digraph &g, Node s=INVALID) : |
| 929 | 929 |
TR(g,s) {}
|
| 930 | 930 |
|
| 931 | 931 |
///Copy constructor |
| 932 | 932 |
DfsWizard(const TR &b) : TR(b) {}
|
| 933 | 933 |
|
| 934 | 934 |
~DfsWizard() {}
|
| 935 | 935 |
|
| 936 | 936 |
///Runs Dfs algorithm from a given node. |
| 937 |
|
|
| 937 |
|
|
| 938 | 938 |
///Runs Dfs algorithm from a given node. |
| 939 | 939 |
///The node can be given by the \ref source function. |
| 940 | 940 |
void run() |
| 941 | 941 |
{
|
| 942 | 942 |
if(Base::_source==INVALID) throw UninitializedParameter(); |
| 943 | 943 |
Dfs<Digraph,TR> alg(*reinterpret_cast<const Digraph*>(Base::_g)); |
| 944 |
if(Base::_reached) |
|
| 944 |
if(Base::_reached) |
|
| 945 | 945 |
alg.reachedMap(*reinterpret_cast<ReachedMap*>(Base::_reached)); |
| 946 |
if(Base::_processed) |
|
| 946 |
if(Base::_processed) |
|
| 947 | 947 |
alg.processedMap(*reinterpret_cast<ProcessedMap*>(Base::_processed)); |
| 948 |
if(Base::_pred) |
|
| 948 |
if(Base::_pred) |
|
| 949 | 949 |
alg.predMap(*reinterpret_cast<PredMap*>(Base::_pred)); |
| 950 |
if(Base::_dist) |
|
| 950 |
if(Base::_dist) |
|
| 951 | 951 |
alg.distMap(*reinterpret_cast<DistMap*>(Base::_dist)); |
| 952 | 952 |
alg.run(Base::_source); |
| 953 | 953 |
} |
| 954 | 954 |
|
| 955 | 955 |
///Runs Dfs algorithm from the given node. |
| 956 | 956 |
|
| 957 | 957 |
///Runs Dfs algorithm from the given node. |
| 958 | 958 |
///\param s is the given source. |
| 959 | 959 |
void run(Node s) |
| 960 | 960 |
{
|
| 961 | 961 |
Base::_source=s; |
| 962 | 962 |
run(); |
| 963 | 963 |
} |
| 964 | 964 |
|
| 965 | 965 |
template<class T> |
| 966 | 966 |
struct DefPredMapBase : public Base {
|
| 967 | 967 |
typedef T PredMap; |
| 968 | 968 |
static PredMap *createPredMap(const Digraph &) { return 0; };
|
| 969 | 969 |
DefPredMapBase(const TR &b) : TR(b) {}
|
| 970 | 970 |
}; |
| 971 |
|
|
| 971 |
|
|
| 972 | 972 |
///\brief \ref named-templ-param "Named parameter" |
| 973 | 973 |
///function for setting PredMap type |
| 974 | 974 |
/// |
| 975 | 975 |
/// \ref named-templ-param "Named parameter" |
| 976 | 976 |
///function for setting PredMap type |
| 977 | 977 |
/// |
| 978 | 978 |
template<class T> |
| 979 |
DfsWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 979 |
DfsWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 980 | 980 |
{
|
| 981 | 981 |
Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 982 | 982 |
return DfsWizard<DefPredMapBase<T> >(*this); |
| 983 | 983 |
} |
| 984 |
|
|
| 985 |
|
|
| 984 |
|
|
| 985 |
|
|
| 986 | 986 |
template<class T> |
| 987 | 987 |
struct DefReachedMapBase : public Base {
|
| 988 | 988 |
typedef T ReachedMap; |
| 989 | 989 |
static ReachedMap *createReachedMap(const Digraph &) { return 0; };
|
| 990 | 990 |
DefReachedMapBase(const TR &b) : TR(b) {}
|
| 991 | 991 |
}; |
| 992 |
|
|
| 992 |
|
|
| 993 | 993 |
///\brief \ref named-templ-param "Named parameter" |
| 994 | 994 |
///function for setting ReachedMap |
| 995 | 995 |
/// |
| 996 | 996 |
/// \ref named-templ-param "Named parameter" |
| 997 | 997 |
///function for setting ReachedMap |
| 998 | 998 |
/// |
| 999 | 999 |
template<class T> |
| 1000 |
DfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) |
|
| 1000 |
DfsWizard<DefReachedMapBase<T> > reachedMap(const T &t) |
|
| 1001 | 1001 |
{
|
| 1002 | 1002 |
Base::_reached=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1003 | 1003 |
return DfsWizard<DefReachedMapBase<T> >(*this); |
| 1004 | 1004 |
} |
| 1005 |
|
|
| 1005 |
|
|
| 1006 | 1006 |
|
| 1007 | 1007 |
template<class T> |
| 1008 | 1008 |
struct DefProcessedMapBase : public Base {
|
| 1009 | 1009 |
typedef T ProcessedMap; |
| 1010 | 1010 |
static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
|
| 1011 | 1011 |
DefProcessedMapBase(const TR &b) : TR(b) {}
|
| 1012 | 1012 |
}; |
| 1013 |
|
|
| 1013 |
|
|
| 1014 | 1014 |
///\brief \ref named-templ-param "Named parameter" |
| 1015 | 1015 |
///function for setting ProcessedMap |
| 1016 | 1016 |
/// |
| 1017 | 1017 |
/// \ref named-templ-param "Named parameter" |
| 1018 | 1018 |
///function for setting ProcessedMap |
| 1019 | 1019 |
/// |
| 1020 | 1020 |
template<class T> |
| 1021 |
DfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) |
|
| 1021 |
DfsWizard<DefProcessedMapBase<T> > processedMap(const T &t) |
|
| 1022 | 1022 |
{
|
| 1023 | 1023 |
Base::_processed=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1024 | 1024 |
return DfsWizard<DefProcessedMapBase<T> >(*this); |
| 1025 | 1025 |
} |
| 1026 |
|
|
| 1026 |
|
|
| 1027 | 1027 |
template<class T> |
| 1028 | 1028 |
struct DefDistMapBase : public Base {
|
| 1029 | 1029 |
typedef T DistMap; |
| 1030 | 1030 |
static DistMap *createDistMap(const Digraph &) { return 0; };
|
| 1031 | 1031 |
DefDistMapBase(const TR &b) : TR(b) {}
|
| 1032 | 1032 |
}; |
| 1033 |
|
|
| 1033 |
|
|
| 1034 | 1034 |
///\brief \ref named-templ-param "Named parameter" |
| 1035 | 1035 |
///function for setting DistMap type |
| 1036 | 1036 |
/// |
| 1037 | 1037 |
/// \ref named-templ-param "Named parameter" |
| 1038 | 1038 |
///function for setting DistMap type |
| 1039 | 1039 |
/// |
| 1040 | 1040 |
template<class T> |
| 1041 |
DfsWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1041 |
DfsWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1042 | 1042 |
{
|
| 1043 | 1043 |
Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1044 | 1044 |
return DfsWizard<DefDistMapBase<T> >(*this); |
| 1045 | 1045 |
} |
| 1046 |
|
|
| 1046 |
|
|
| 1047 | 1047 |
/// Sets the source node, from which the Dfs algorithm runs. |
| 1048 | 1048 |
|
| 1049 | 1049 |
/// Sets the source node, from which the Dfs algorithm runs. |
| 1050 | 1050 |
/// \param s is the source node. |
| 1051 |
DfsWizard<TR> &source(Node s) |
|
| 1051 |
DfsWizard<TR> &source(Node s) |
|
| 1052 | 1052 |
{
|
| 1053 | 1053 |
Base::_source=s; |
| 1054 | 1054 |
return *this; |
| 1055 | 1055 |
} |
| 1056 |
|
|
| 1056 |
|
|
| 1057 | 1057 |
}; |
| 1058 |
|
|
| 1058 |
|
|
| 1059 | 1059 |
///Function type interface for Dfs algorithm. |
| 1060 | 1060 |
|
| 1061 | 1061 |
///\ingroup search |
| 1062 | 1062 |
///Function type interface for Dfs algorithm. |
| 1063 | 1063 |
/// |
| 1064 | 1064 |
///This function also has several |
| 1065 | 1065 |
///\ref named-templ-func-param "named parameters", |
| 1066 | 1066 |
///they are declared as the members of class \ref DfsWizard. |
| 1067 | 1067 |
///The following |
| 1068 | 1068 |
///example shows how to use these parameters. |
| 1069 | 1069 |
///\code |
| 1070 | 1070 |
/// dfs(g,source).predMap(preds).run(); |
| 1071 | 1071 |
///\endcode |
| 1072 | 1072 |
///\warning Don't forget to put the \ref DfsWizard::run() "run()" |
| 1073 | 1073 |
///to the end of the parameter list. |
| 1074 | 1074 |
///\sa DfsWizard |
| 1075 | 1075 |
///\sa Dfs |
| 1076 | 1076 |
template<class GR> |
| 1077 | 1077 |
DfsWizard<DfsWizardBase<GR> > |
| 1078 | 1078 |
dfs(const GR &g,typename GR::Node s=INVALID) |
| 1079 | 1079 |
{
|
| 1080 | 1080 |
return DfsWizard<DfsWizardBase<GR> >(g,s); |
| 1081 | 1081 |
} |
| 1082 | 1082 |
|
| 1083 | 1083 |
#ifdef DOXYGEN |
| 1084 | 1084 |
/// \brief Visitor class for dfs. |
| 1085 |
/// |
|
| 1086 |
/// It gives a simple interface for a functional interface for dfs |
|
| 1087 |
/// |
|
| 1085 |
/// |
|
| 1086 |
/// It gives a simple interface for a functional interface for dfs |
|
| 1087 |
/// traversal. The traversal on a linear data structure. |
|
| 1088 | 1088 |
template <typename _Digraph> |
| 1089 | 1089 |
struct DfsVisitor {
|
| 1090 | 1090 |
typedef _Digraph Digraph; |
| 1091 | 1091 |
typedef typename Digraph::Arc Arc; |
| 1092 | 1092 |
typedef typename Digraph::Node Node; |
| 1093 | 1093 |
/// \brief Called when the arc reach a node. |
| 1094 |
/// |
|
| 1094 |
/// |
|
| 1095 | 1095 |
/// It is called when the dfs find an arc which target is not |
| 1096 | 1096 |
/// reached yet. |
| 1097 | 1097 |
void discover(const Arc& arc) {}
|
| 1098 | 1098 |
/// \brief Called when the node reached first time. |
| 1099 |
/// |
|
| 1099 |
/// |
|
| 1100 | 1100 |
/// It is Called when the node reached first time. |
| 1101 | 1101 |
void reach(const Node& node) {}
|
| 1102 | 1102 |
/// \brief Called when we step back on an arc. |
| 1103 |
/// |
|
| 1103 |
/// |
|
| 1104 | 1104 |
/// It is called when the dfs should step back on the arc. |
| 1105 | 1105 |
void backtrack(const Arc& arc) {}
|
| 1106 | 1106 |
/// \brief Called when we step back from the node. |
| 1107 |
/// |
|
| 1107 |
/// |
|
| 1108 | 1108 |
/// It is called when we step back from the node. |
| 1109 | 1109 |
void leave(const Node& node) {}
|
| 1110 |
/// \brief Called when the arc examined but target of the arc |
|
| 1110 |
/// \brief Called when the arc examined but target of the arc |
|
| 1111 | 1111 |
/// already discovered. |
| 1112 |
/// |
|
| 1113 |
/// It called when the arc examined but the target of the arc |
|
| 1112 |
/// |
|
| 1113 |
/// It called when the arc examined but the target of the arc |
|
| 1114 | 1114 |
/// already discovered. |
| 1115 | 1115 |
void examine(const Arc& arc) {}
|
| 1116 | 1116 |
/// \brief Called for the source node of the dfs. |
| 1117 |
/// |
|
| 1117 |
/// |
|
| 1118 | 1118 |
/// It is called for the source node of the dfs. |
| 1119 | 1119 |
void start(const Node& node) {}
|
| 1120 | 1120 |
/// \brief Called when we leave the source node of the dfs. |
| 1121 |
/// |
|
| 1121 |
/// |
|
| 1122 | 1122 |
/// It is called when we leave the source node of the dfs. |
| 1123 | 1123 |
void stop(const Node& node) {}
|
| 1124 | 1124 |
|
| 1125 | 1125 |
}; |
| 1126 | 1126 |
#else |
| 1127 | 1127 |
template <typename _Digraph> |
| 1128 | 1128 |
struct DfsVisitor {
|
| 1129 | 1129 |
typedef _Digraph Digraph; |
| 1130 | 1130 |
typedef typename Digraph::Arc Arc; |
| 1131 | 1131 |
typedef typename Digraph::Node Node; |
| 1132 | 1132 |
void discover(const Arc&) {}
|
| 1133 | 1133 |
void reach(const Node&) {}
|
| 1134 | 1134 |
void backtrack(const Arc&) {}
|
| 1135 | 1135 |
void leave(const Node&) {}
|
| 1136 | 1136 |
void examine(const Arc&) {}
|
| 1137 | 1137 |
void start(const Node&) {}
|
| 1138 | 1138 |
void stop(const Node&) {}
|
| 1139 | 1139 |
|
| 1140 | 1140 |
template <typename _Visitor> |
| 1141 | 1141 |
struct Constraints {
|
| 1142 | 1142 |
void constraints() {
|
| 1143 |
Arc arc; |
|
| 1144 |
Node node; |
|
| 1145 |
visitor.discover(arc); |
|
| 1146 |
visitor.reach(node); |
|
| 1147 |
visitor.backtrack(arc); |
|
| 1148 |
visitor.leave(node); |
|
| 1149 |
visitor.examine(arc); |
|
| 1150 |
visitor.start(node); |
|
| 1151 |
|
|
| 1143 |
Arc arc; |
|
| 1144 |
Node node; |
|
| 1145 |
visitor.discover(arc); |
|
| 1146 |
visitor.reach(node); |
|
| 1147 |
visitor.backtrack(arc); |
|
| 1148 |
visitor.leave(node); |
|
| 1149 |
visitor.examine(arc); |
|
| 1150 |
visitor.start(node); |
|
| 1151 |
visitor.stop(arc); |
|
| 1152 | 1152 |
} |
| 1153 | 1153 |
_Visitor& visitor; |
| 1154 | 1154 |
}; |
| 1155 | 1155 |
}; |
| 1156 | 1156 |
#endif |
| 1157 | 1157 |
|
| 1158 | 1158 |
/// \brief Default traits class of DfsVisit class. |
| 1159 | 1159 |
/// |
| 1160 | 1160 |
/// Default traits class of DfsVisit class. |
| 1161 | 1161 |
/// \tparam _Digraph Digraph type. |
| 1162 | 1162 |
template<class _Digraph> |
| 1163 | 1163 |
struct DfsVisitDefaultTraits {
|
| 1164 | 1164 |
|
| 1165 |
/// \brief The digraph type the algorithm runs on. |
|
| 1165 |
/// \brief The digraph type the algorithm runs on. |
|
| 1166 | 1166 |
typedef _Digraph Digraph; |
| 1167 | 1167 |
|
| 1168 | 1168 |
/// \brief The type of the map that indicates which nodes are reached. |
| 1169 |
/// |
|
| 1169 |
/// |
|
| 1170 | 1170 |
/// The type of the map that indicates which nodes are reached. |
| 1171 | 1171 |
/// It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 1172 | 1172 |
/// \todo named parameter to set this type, function to read and write. |
| 1173 | 1173 |
typedef typename Digraph::template NodeMap<bool> ReachedMap; |
| 1174 | 1174 |
|
| 1175 | 1175 |
/// \brief Instantiates a ReachedMap. |
| 1176 | 1176 |
/// |
| 1177 |
/// This function instantiates a \ref ReachedMap. |
|
| 1177 |
/// This function instantiates a \ref ReachedMap. |
|
| 1178 | 1178 |
/// \param digraph is the digraph, to which |
| 1179 | 1179 |
/// we would like to define the \ref ReachedMap. |
| 1180 | 1180 |
static ReachedMap *createReachedMap(const Digraph &digraph) {
|
| 1181 | 1181 |
return new ReachedMap(digraph); |
| 1182 | 1182 |
} |
| 1183 | 1183 |
|
| 1184 | 1184 |
}; |
| 1185 |
|
|
| 1185 |
|
|
| 1186 | 1186 |
/// %DFS Visit algorithm class. |
| 1187 |
|
|
| 1187 |
|
|
| 1188 | 1188 |
/// \ingroup search |
| 1189 | 1189 |
/// This class provides an efficient implementation of the %DFS algorithm |
| 1190 | 1190 |
/// with visitor interface. |
| 1191 | 1191 |
/// |
| 1192 | 1192 |
/// The %DfsVisit class provides an alternative interface to the Dfs |
| 1193 | 1193 |
/// class. It works with callback mechanism, the DfsVisit object calls |
| 1194 |
/// on every dfs event the \c Visitor class member functions. |
|
| 1194 |
/// on every dfs event the \c Visitor class member functions. |
|
| 1195 | 1195 |
/// |
| 1196 | 1196 |
/// \tparam _Digraph The digraph type the algorithm runs on. The default value is |
| 1197 | 1197 |
/// \ref ListDigraph. The value of _Digraph is not used directly by Dfs, it |
| 1198 | 1198 |
/// is only passed to \ref DfsDefaultTraits. |
| 1199 |
/// \tparam _Visitor The Visitor object for the algorithm. The |
|
| 1199 |
/// \tparam _Visitor The Visitor object for the algorithm. The |
|
| 1200 | 1200 |
/// \ref DfsVisitor "DfsVisitor<_Digraph>" is an empty Visitor which |
| 1201 | 1201 |
/// does not observe the Dfs events. If you want to observe the dfs |
| 1202 | 1202 |
/// events you should implement your own Visitor class. |
| 1203 |
/// \tparam _Traits Traits class to set various data types used by the |
|
| 1203 |
/// \tparam _Traits Traits class to set various data types used by the |
|
| 1204 | 1204 |
/// algorithm. The default traits class is |
| 1205 | 1205 |
/// \ref DfsVisitDefaultTraits "DfsVisitDefaultTraits<_Digraph>". |
| 1206 | 1206 |
/// See \ref DfsVisitDefaultTraits for the documentation of |
| 1207 | 1207 |
/// a Dfs visit traits class. |
| 1208 | 1208 |
/// |
| 1209 | 1209 |
/// \author Jacint Szabo, Alpar Juttner and Balazs Dezso |
| 1210 | 1210 |
#ifdef DOXYGEN |
| 1211 | 1211 |
template <typename _Digraph, typename _Visitor, typename _Traits> |
| 1212 | 1212 |
#else |
| 1213 | 1213 |
template <typename _Digraph = ListDigraph, |
| 1214 |
typename _Visitor = DfsVisitor<_Digraph>, |
|
| 1215 |
typename _Traits = DfsDefaultTraits<_Digraph> > |
|
| 1214 |
typename _Visitor = DfsVisitor<_Digraph>, |
|
| 1215 |
typename _Traits = DfsDefaultTraits<_Digraph> > |
|
| 1216 | 1216 |
#endif |
| 1217 | 1217 |
class DfsVisit {
|
| 1218 | 1218 |
public: |
| 1219 |
|
|
| 1219 |
|
|
| 1220 | 1220 |
/// \brief \ref Exception for uninitialized parameters. |
| 1221 | 1221 |
/// |
| 1222 | 1222 |
/// This error represents problems in the initialization |
| 1223 | 1223 |
/// of the parameters of the algorithms. |
| 1224 | 1224 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
| 1225 | 1225 |
public: |
| 1226 |
virtual const char* what() const throw() |
|
| 1226 |
virtual const char* what() const throw() |
|
| 1227 | 1227 |
{
|
| 1228 |
|
|
| 1228 |
return "lemon::DfsVisit::UninitializedParameter"; |
|
| 1229 | 1229 |
} |
| 1230 | 1230 |
}; |
| 1231 | 1231 |
|
| 1232 | 1232 |
typedef _Traits Traits; |
| 1233 | 1233 |
|
| 1234 | 1234 |
typedef typename Traits::Digraph Digraph; |
| 1235 | 1235 |
|
| 1236 | 1236 |
typedef _Visitor Visitor; |
| 1237 | 1237 |
|
| 1238 | 1238 |
///The type of the map indicating which nodes are reached. |
| 1239 | 1239 |
typedef typename Traits::ReachedMap ReachedMap; |
| 1240 | 1240 |
|
| 1241 | 1241 |
private: |
| 1242 | 1242 |
|
| 1243 | 1243 |
typedef typename Digraph::Node Node; |
| 1244 | 1244 |
typedef typename Digraph::NodeIt NodeIt; |
| ... | ... |
@@ -1249,222 +1249,222 @@ |
| 1249 | 1249 |
const Digraph *_digraph; |
| 1250 | 1250 |
/// Pointer to the visitor object. |
| 1251 | 1251 |
Visitor *_visitor; |
| 1252 | 1252 |
///Pointer to the map of reached status of the nodes. |
| 1253 | 1253 |
ReachedMap *_reached; |
| 1254 | 1254 |
///Indicates if \ref _reached is locally allocated (\c true) or not. |
| 1255 | 1255 |
bool local_reached; |
| 1256 | 1256 |
|
| 1257 | 1257 |
std::vector<typename Digraph::Arc> _stack; |
| 1258 | 1258 |
int _stack_head; |
| 1259 | 1259 |
|
| 1260 | 1260 |
/// \brief Creates the maps if necessary. |
| 1261 | 1261 |
/// |
| 1262 | 1262 |
/// Creates the maps if necessary. |
| 1263 | 1263 |
void create_maps() {
|
| 1264 | 1264 |
if(!_reached) {
|
| 1265 |
local_reached = true; |
|
| 1266 |
_reached = Traits::createReachedMap(*_digraph); |
|
| 1265 |
local_reached = true; |
|
| 1266 |
_reached = Traits::createReachedMap(*_digraph); |
|
| 1267 | 1267 |
} |
| 1268 | 1268 |
} |
| 1269 | 1269 |
|
| 1270 | 1270 |
protected: |
| 1271 | 1271 |
|
| 1272 | 1272 |
DfsVisit() {}
|
| 1273 |
|
|
| 1273 |
|
|
| 1274 | 1274 |
public: |
| 1275 | 1275 |
|
| 1276 | 1276 |
typedef DfsVisit Create; |
| 1277 | 1277 |
|
| 1278 | 1278 |
/// \name Named template parameters |
| 1279 | 1279 |
|
| 1280 | 1280 |
///@{
|
| 1281 | 1281 |
template <class T> |
| 1282 | 1282 |
struct DefReachedMapTraits : public Traits {
|
| 1283 | 1283 |
typedef T ReachedMap; |
| 1284 | 1284 |
static ReachedMap *createReachedMap(const Digraph &digraph) {
|
| 1285 |
|
|
| 1285 |
throw UninitializedParameter(); |
|
| 1286 | 1286 |
} |
| 1287 | 1287 |
}; |
| 1288 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 1288 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 1289 | 1289 |
/// ReachedMap type |
| 1290 | 1290 |
/// |
| 1291 | 1291 |
/// \ref named-templ-param "Named parameter" for setting ReachedMap type |
| 1292 | 1292 |
template <class T> |
| 1293 | 1293 |
struct DefReachedMap : public DfsVisit< Digraph, Visitor, |
| 1294 |
|
|
| 1294 |
DefReachedMapTraits<T> > {
|
|
| 1295 | 1295 |
typedef DfsVisit< Digraph, Visitor, DefReachedMapTraits<T> > Create; |
| 1296 | 1296 |
}; |
| 1297 | 1297 |
///@} |
| 1298 | 1298 |
|
| 1299 |
public: |
|
| 1300 |
|
|
| 1299 |
public: |
|
| 1300 |
|
|
| 1301 | 1301 |
/// \brief Constructor. |
| 1302 | 1302 |
/// |
| 1303 | 1303 |
/// Constructor. |
| 1304 | 1304 |
/// |
| 1305 | 1305 |
/// \param digraph the digraph the algorithm will run on. |
| 1306 | 1306 |
/// \param visitor The visitor of the algorithm. |
| 1307 | 1307 |
/// |
| 1308 |
DfsVisit(const Digraph& digraph, Visitor& visitor) |
|
| 1308 |
DfsVisit(const Digraph& digraph, Visitor& visitor) |
|
| 1309 | 1309 |
: _digraph(&digraph), _visitor(&visitor), |
| 1310 |
_reached(0), local_reached(false) {}
|
|
| 1311 |
|
|
| 1310 |
_reached(0), local_reached(false) {}
|
|
| 1311 |
|
|
| 1312 | 1312 |
/// \brief Destructor. |
| 1313 | 1313 |
/// |
| 1314 | 1314 |
/// Destructor. |
| 1315 | 1315 |
~DfsVisit() {
|
| 1316 | 1316 |
if(local_reached) delete _reached; |
| 1317 | 1317 |
} |
| 1318 | 1318 |
|
| 1319 | 1319 |
/// \brief Sets the map indicating if a node is reached. |
| 1320 | 1320 |
/// |
| 1321 | 1321 |
/// Sets the map indicating if a node is reached. |
| 1322 | 1322 |
/// If you don't use this function before calling \ref run(), |
| 1323 | 1323 |
/// it will allocate one. The destuctor deallocates this |
| 1324 | 1324 |
/// automatically allocated map, of course. |
| 1325 | 1325 |
/// \return <tt> (*this) </tt> |
| 1326 | 1326 |
DfsVisit &reachedMap(ReachedMap &m) {
|
| 1327 | 1327 |
if(local_reached) {
|
| 1328 |
delete _reached; |
|
| 1329 |
local_reached=false; |
|
| 1328 |
delete _reached; |
|
| 1329 |
local_reached=false; |
|
| 1330 | 1330 |
} |
| 1331 | 1331 |
_reached = &m; |
| 1332 | 1332 |
return *this; |
| 1333 | 1333 |
} |
| 1334 | 1334 |
|
| 1335 | 1335 |
public: |
| 1336 | 1336 |
/// \name Execution control |
| 1337 | 1337 |
/// The simplest way to execute the algorithm is to use |
| 1338 | 1338 |
/// one of the member functions called \c run(...). |
| 1339 | 1339 |
/// \n |
| 1340 | 1340 |
/// If you need more control on the execution, |
| 1341 | 1341 |
/// first you must call \ref init(), then you can adda source node |
| 1342 | 1342 |
/// with \ref addSource(). |
| 1343 | 1343 |
/// Finally \ref start() will perform the actual path |
| 1344 | 1344 |
/// computation. |
| 1345 | 1345 |
|
| 1346 | 1346 |
/// @{
|
| 1347 | 1347 |
/// \brief Initializes the internal data structures. |
| 1348 | 1348 |
/// |
| 1349 | 1349 |
/// Initializes the internal data structures. |
| 1350 | 1350 |
/// |
| 1351 | 1351 |
void init() {
|
| 1352 | 1352 |
create_maps(); |
| 1353 | 1353 |
_stack.resize(countNodes(*_digraph)); |
| 1354 | 1354 |
_stack_head = -1; |
| 1355 | 1355 |
for (NodeIt u(*_digraph) ; u != INVALID ; ++u) {
|
| 1356 |
|
|
| 1356 |
_reached->set(u, false); |
|
| 1357 | 1357 |
} |
| 1358 | 1358 |
} |
| 1359 |
|
|
| 1359 |
|
|
| 1360 | 1360 |
/// \brief Adds a new source node. |
| 1361 | 1361 |
/// |
| 1362 | 1362 |
/// Adds a new source node to the set of nodes to be processed. |
| 1363 | 1363 |
void addSource(Node s) {
|
| 1364 | 1364 |
if(!(*_reached)[s]) {
|
| 1365 |
_reached->set(s,true); |
|
| 1366 |
_visitor->start(s); |
|
| 1367 |
_visitor->reach(s); |
|
| 1368 |
Arc e; |
|
| 1369 |
_digraph->firstOut(e, s); |
|
| 1370 |
if (e != INVALID) {
|
|
| 1371 |
_stack[++_stack_head] = e; |
|
| 1372 |
} else {
|
|
| 1373 |
_visitor->leave(s); |
|
| 1374 |
} |
|
| 1375 |
|
|
| 1365 |
_reached->set(s,true); |
|
| 1366 |
_visitor->start(s); |
|
| 1367 |
_visitor->reach(s); |
|
| 1368 |
Arc e; |
|
| 1369 |
_digraph->firstOut(e, s); |
|
| 1370 |
if (e != INVALID) {
|
|
| 1371 |
_stack[++_stack_head] = e; |
|
| 1372 |
} else {
|
|
| 1373 |
_visitor->leave(s); |
|
| 1374 |
} |
|
| 1375 |
} |
|
| 1376 | 1376 |
} |
| 1377 |
|
|
| 1377 |
|
|
| 1378 | 1378 |
/// \brief Processes the next arc. |
| 1379 | 1379 |
/// |
| 1380 | 1380 |
/// Processes the next arc. |
| 1381 | 1381 |
/// |
| 1382 | 1382 |
/// \return The processed arc. |
| 1383 | 1383 |
/// |
| 1384 | 1384 |
/// \pre The stack must not be empty! |
| 1385 |
Arc processNextArc() {
|
|
| 1385 |
Arc processNextArc() {
|
|
| 1386 | 1386 |
Arc e = _stack[_stack_head]; |
| 1387 | 1387 |
Node m = _digraph->target(e); |
| 1388 | 1388 |
if(!(*_reached)[m]) {
|
| 1389 |
_visitor->discover(e); |
|
| 1390 |
_visitor->reach(m); |
|
| 1391 |
_reached->set(m, true); |
|
| 1392 |
_digraph->firstOut(_stack[++_stack_head], m); |
|
| 1389 |
_visitor->discover(e); |
|
| 1390 |
_visitor->reach(m); |
|
| 1391 |
_reached->set(m, true); |
|
| 1392 |
_digraph->firstOut(_stack[++_stack_head], m); |
|
| 1393 | 1393 |
} else {
|
| 1394 |
_visitor->examine(e); |
|
| 1395 |
m = _digraph->source(e); |
|
| 1396 |
|
|
| 1394 |
_visitor->examine(e); |
|
| 1395 |
m = _digraph->source(e); |
|
| 1396 |
_digraph->nextOut(_stack[_stack_head]); |
|
| 1397 | 1397 |
} |
| 1398 | 1398 |
while (_stack_head>=0 && _stack[_stack_head] == INVALID) {
|
| 1399 |
_visitor->leave(m); |
|
| 1400 |
--_stack_head; |
|
| 1401 |
if (_stack_head >= 0) {
|
|
| 1402 |
_visitor->backtrack(_stack[_stack_head]); |
|
| 1403 |
m = _digraph->source(_stack[_stack_head]); |
|
| 1404 |
_digraph->nextOut(_stack[_stack_head]); |
|
| 1405 |
} else {
|
|
| 1406 |
_visitor->stop(m); |
|
| 1407 |
|
|
| 1399 |
_visitor->leave(m); |
|
| 1400 |
--_stack_head; |
|
| 1401 |
if (_stack_head >= 0) {
|
|
| 1402 |
_visitor->backtrack(_stack[_stack_head]); |
|
| 1403 |
m = _digraph->source(_stack[_stack_head]); |
|
| 1404 |
_digraph->nextOut(_stack[_stack_head]); |
|
| 1405 |
} else {
|
|
| 1406 |
_visitor->stop(m); |
|
| 1407 |
} |
|
| 1408 | 1408 |
} |
| 1409 | 1409 |
return e; |
| 1410 | 1410 |
} |
| 1411 | 1411 |
|
| 1412 | 1412 |
/// \brief Next arc to be processed. |
| 1413 | 1413 |
/// |
| 1414 | 1414 |
/// Next arc to be processed. |
| 1415 | 1415 |
/// |
| 1416 | 1416 |
/// \return The next arc to be processed or INVALID if the stack is |
| 1417 | 1417 |
/// empty. |
| 1418 |
Arc nextArc() {
|
|
| 1418 |
Arc nextArc() {
|
|
| 1419 | 1419 |
return _stack_head >= 0 ? _stack[_stack_head] : INVALID; |
| 1420 | 1420 |
} |
| 1421 | 1421 |
|
| 1422 | 1422 |
/// \brief Returns \c false if there are nodes |
| 1423 | 1423 |
/// to be processed in the queue |
| 1424 | 1424 |
/// |
| 1425 | 1425 |
/// Returns \c false if there are nodes |
| 1426 | 1426 |
/// to be processed in the queue |
| 1427 | 1427 |
bool emptyQueue() { return _stack_head < 0; }
|
| 1428 | 1428 |
|
| 1429 | 1429 |
/// \brief Returns the number of the nodes to be processed. |
| 1430 | 1430 |
/// |
| 1431 | 1431 |
/// Returns the number of the nodes to be processed in the queue. |
| 1432 | 1432 |
int queueSize() { return _stack_head + 1; }
|
| 1433 |
|
|
| 1433 |
|
|
| 1434 | 1434 |
/// \brief Executes the algorithm. |
| 1435 | 1435 |
/// |
| 1436 | 1436 |
/// Executes the algorithm. |
| 1437 | 1437 |
/// |
| 1438 | 1438 |
/// \pre init() must be called and at least one node should be added |
| 1439 | 1439 |
/// with addSource() before using this function. |
| 1440 | 1440 |
void start() {
|
| 1441 | 1441 |
while ( !emptyQueue() ) processNextArc(); |
| 1442 | 1442 |
} |
| 1443 |
|
|
| 1443 |
|
|
| 1444 | 1444 |
/// \brief Executes the algorithm until \c dest is reached. |
| 1445 | 1445 |
/// |
| 1446 | 1446 |
/// Executes the algorithm until \c dest is reached. |
| 1447 | 1447 |
/// |
| 1448 | 1448 |
/// \pre init() must be called and at least one node should be added |
| 1449 | 1449 |
/// with addSource() before using this function. |
| 1450 | 1450 |
void start(Node dest) {
|
| 1451 |
while ( !emptyQueue() && _digraph->target(_stack[_stack_head]) != dest ) |
|
| 1452 |
processNextArc(); |
|
| 1451 |
while ( !emptyQueue() && _digraph->target(_stack[_stack_head]) != dest ) |
|
| 1452 |
processNextArc(); |
|
| 1453 | 1453 |
} |
| 1454 |
|
|
| 1454 |
|
|
| 1455 | 1455 |
/// \brief Executes the algorithm until a condition is met. |
| 1456 | 1456 |
/// |
| 1457 | 1457 |
/// Executes the algorithm until a condition is met. |
| 1458 | 1458 |
/// |
| 1459 | 1459 |
/// \pre init() must be called and at least one node should be added |
| 1460 | 1460 |
/// with addSource() before using this function. |
| 1461 | 1461 |
/// |
| 1462 | 1462 |
/// \param em must be a bool (or convertible) arc map. The algorithm |
| 1463 | 1463 |
/// will stop when it reaches an arc \c e with <tt>em[e]</tt> true. |
| 1464 | 1464 |
/// |
| 1465 | 1465 |
///\return The reached arc \c e with <tt>em[e]</tt> true or |
| 1466 | 1466 |
///\c INVALID if no such arc was found. |
| 1467 | 1467 |
/// |
| 1468 | 1468 |
/// \warning Contrary to \ref Bfs and \ref Dijkstra, \c em is an arc map, |
| 1469 | 1469 |
/// not a node map. |
| 1470 | 1470 |
template <typename EM> |
| ... | ... |
@@ -1477,33 +1477,33 @@ |
| 1477 | 1477 |
/// \brief Runs %DFSVisit algorithm from node \c s. |
| 1478 | 1478 |
/// |
| 1479 | 1479 |
/// This method runs the %DFS algorithm from a root node \c s. |
| 1480 | 1480 |
/// \note d.run(s) is just a shortcut of the following code. |
| 1481 | 1481 |
///\code |
| 1482 | 1482 |
/// d.init(); |
| 1483 | 1483 |
/// d.addSource(s); |
| 1484 | 1484 |
/// d.start(); |
| 1485 | 1485 |
///\endcode |
| 1486 | 1486 |
void run(Node s) {
|
| 1487 | 1487 |
init(); |
| 1488 | 1488 |
addSource(s); |
| 1489 | 1489 |
start(); |
| 1490 | 1490 |
} |
| 1491 | 1491 |
|
| 1492 | 1492 |
/// \brief Runs %DFSVisit algorithm to visit all nodes in the digraph. |
| 1493 |
|
|
| 1493 |
|
|
| 1494 | 1494 |
/// This method runs the %DFS algorithm in order to |
| 1495 | 1495 |
/// compute the %DFS path to each node. The algorithm computes |
| 1496 | 1496 |
/// - The %DFS tree. |
| 1497 | 1497 |
/// - The distance of each node from the root in the %DFS tree. |
| 1498 | 1498 |
/// |
| 1499 | 1499 |
///\note d.run() is just a shortcut of the following code. |
| 1500 | 1500 |
///\code |
| 1501 | 1501 |
/// d.init(); |
| 1502 | 1502 |
/// for (NodeIt it(digraph); it != INVALID; ++it) {
|
| 1503 | 1503 |
/// if (!d.reached(it)) {
|
| 1504 | 1504 |
/// d.addSource(it); |
| 1505 | 1505 |
/// d.start(); |
| 1506 | 1506 |
/// } |
| 1507 | 1507 |
/// } |
| 1508 | 1508 |
///\endcode |
| 1509 | 1509 |
void run() {
|
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_DIJKSTRA_H |
| ... | ... |
@@ -21,242 +21,242 @@ |
| 21 | 21 |
|
| 22 | 22 |
///\ingroup shortest_path |
| 23 | 23 |
///\file |
| 24 | 24 |
///\brief Dijkstra algorithm. |
| 25 | 25 |
|
| 26 | 26 |
#include <limits> |
| 27 | 27 |
#include <lemon/list_graph.h> |
| 28 | 28 |
#include <lemon/bin_heap.h> |
| 29 | 29 |
#include <lemon/bits/path_dump.h> |
| 30 | 30 |
#include <lemon/bits/invalid.h> |
| 31 | 31 |
#include <lemon/error.h> |
| 32 | 32 |
#include <lemon/maps.h> |
| 33 | 33 |
|
| 34 | 34 |
namespace lemon {
|
| 35 | 35 |
|
| 36 | 36 |
/// \brief Default OperationTraits for the Dijkstra algorithm class. |
| 37 |
/// |
|
| 37 |
/// |
|
| 38 | 38 |
/// It defines all computational operations and constants which are |
| 39 | 39 |
/// used in the Dijkstra algorithm. |
| 40 | 40 |
template <typename Value> |
| 41 | 41 |
struct DijkstraDefaultOperationTraits {
|
| 42 | 42 |
/// \brief Gives back the zero value of the type. |
| 43 | 43 |
static Value zero() {
|
| 44 | 44 |
return static_cast<Value>(0); |
| 45 | 45 |
} |
| 46 | 46 |
/// \brief Gives back the sum of the given two elements. |
| 47 | 47 |
static Value plus(const Value& left, const Value& right) {
|
| 48 | 48 |
return left + right; |
| 49 | 49 |
} |
| 50 | 50 |
/// \brief Gives back true only if the first value less than the second. |
| 51 | 51 |
static bool less(const Value& left, const Value& right) {
|
| 52 | 52 |
return left < right; |
| 53 | 53 |
} |
| 54 | 54 |
}; |
| 55 | 55 |
|
| 56 | 56 |
/// \brief Widest path OperationTraits for the Dijkstra algorithm class. |
| 57 |
/// |
|
| 57 |
/// |
|
| 58 | 58 |
/// It defines all computational operations and constants which are |
| 59 | 59 |
/// used in the Dijkstra algorithm for widest path computation. |
| 60 | 60 |
template <typename Value> |
| 61 | 61 |
struct DijkstraWidestPathOperationTraits {
|
| 62 | 62 |
/// \brief Gives back the maximum value of the type. |
| 63 | 63 |
static Value zero() {
|
| 64 | 64 |
return std::numeric_limits<Value>::max(); |
| 65 | 65 |
} |
| 66 | 66 |
/// \brief Gives back the minimum of the given two elements. |
| 67 | 67 |
static Value plus(const Value& left, const Value& right) {
|
| 68 | 68 |
return std::min(left, right); |
| 69 | 69 |
} |
| 70 | 70 |
/// \brief Gives back true only if the first value less than the second. |
| 71 | 71 |
static bool less(const Value& left, const Value& right) {
|
| 72 | 72 |
return left < right; |
| 73 | 73 |
} |
| 74 | 74 |
}; |
| 75 |
|
|
| 75 |
|
|
| 76 | 76 |
///Default traits class of Dijkstra class. |
| 77 | 77 |
|
| 78 | 78 |
///Default traits class of Dijkstra class. |
| 79 | 79 |
///\tparam GR Digraph type. |
| 80 | 80 |
///\tparam LM Type of length map. |
| 81 | 81 |
template<class GR, class LM> |
| 82 | 82 |
struct DijkstraDefaultTraits |
| 83 | 83 |
{
|
| 84 |
///The digraph type the algorithm runs on. |
|
| 84 |
///The digraph type the algorithm runs on. |
|
| 85 | 85 |
typedef GR Digraph; |
| 86 | 86 |
///The type of the map that stores the arc lengths. |
| 87 | 87 |
|
| 88 | 88 |
///The type of the map that stores the arc lengths. |
| 89 | 89 |
///It must meet the \ref concepts::ReadMap "ReadMap" concept. |
| 90 | 90 |
typedef LM LengthMap; |
| 91 | 91 |
//The type of the length of the arcs. |
| 92 | 92 |
typedef typename LM::Value Value; |
| 93 | 93 |
/// Operation traits for Dijkstra algorithm. |
| 94 | 94 |
|
| 95 | 95 |
/// It defines the used operation by the algorithm. |
| 96 | 96 |
/// \see DijkstraDefaultOperationTraits |
| 97 | 97 |
typedef DijkstraDefaultOperationTraits<Value> OperationTraits; |
| 98 | 98 |
/// The cross reference type used by heap. |
| 99 | 99 |
|
| 100 | 100 |
|
| 101 | 101 |
/// The cross reference type used by heap. |
| 102 | 102 |
/// Usually it is \c Digraph::NodeMap<int>. |
| 103 | 103 |
typedef typename Digraph::template NodeMap<int> HeapCrossRef; |
| 104 | 104 |
///Instantiates a HeapCrossRef. |
| 105 | 105 |
|
| 106 |
///This function instantiates a \c HeapCrossRef. |
|
| 107 |
/// \param G is the digraph, to which we would like to define the |
|
| 106 |
///This function instantiates a \c HeapCrossRef. |
|
| 107 |
/// \param G is the digraph, to which we would like to define the |
|
| 108 | 108 |
/// HeapCrossRef. |
| 109 |
static HeapCrossRef *createHeapCrossRef(const GR &G) |
|
| 109 |
static HeapCrossRef *createHeapCrossRef(const GR &G) |
|
| 110 | 110 |
{
|
| 111 | 111 |
return new HeapCrossRef(G); |
| 112 | 112 |
} |
| 113 |
|
|
| 113 |
|
|
| 114 | 114 |
///The heap type used by Dijkstra algorithm. |
| 115 | 115 |
|
| 116 | 116 |
///The heap type used by Dijkstra algorithm. |
| 117 | 117 |
/// |
| 118 | 118 |
///\sa BinHeap |
| 119 | 119 |
///\sa Dijkstra |
| 120 | 120 |
typedef BinHeap<typename LM::Value, HeapCrossRef, std::less<Value> > Heap; |
| 121 | 121 |
|
| 122 |
static Heap *createHeap(HeapCrossRef& R) |
|
| 122 |
static Heap *createHeap(HeapCrossRef& R) |
|
| 123 | 123 |
{
|
| 124 | 124 |
return new Heap(R); |
| 125 | 125 |
} |
| 126 | 126 |
|
| 127 | 127 |
///\brief The type of the map that stores the last |
| 128 | 128 |
///arcs of the shortest paths. |
| 129 |
/// |
|
| 129 |
/// |
|
| 130 | 130 |
///The type of the map that stores the last |
| 131 | 131 |
///arcs of the shortest paths. |
| 132 | 132 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 133 | 133 |
/// |
| 134 | 134 |
typedef typename Digraph::template NodeMap<typename GR::Arc> PredMap; |
| 135 | 135 |
///Instantiates a PredMap. |
| 136 |
|
|
| 137 |
///This function instantiates a \c PredMap. |
|
| 136 |
|
|
| 137 |
///This function instantiates a \c PredMap. |
|
| 138 | 138 |
///\param G is the digraph, to which we would like to define the PredMap. |
| 139 | 139 |
///\todo The digraph alone may be insufficient for the initialization |
| 140 |
static PredMap *createPredMap(const GR &G) |
|
| 140 |
static PredMap *createPredMap(const GR &G) |
|
| 141 | 141 |
{
|
| 142 | 142 |
return new PredMap(G); |
| 143 | 143 |
} |
| 144 | 144 |
|
| 145 | 145 |
///The type of the map that stores whether a nodes is processed. |
| 146 |
|
|
| 146 |
|
|
| 147 | 147 |
///The type of the map that stores whether a nodes is processed. |
| 148 | 148 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 149 | 149 |
///By default it is a NullMap. |
| 150 | 150 |
///\todo If it is set to a real map, |
| 151 | 151 |
///Dijkstra::processed() should read this. |
| 152 | 152 |
///\todo named parameter to set this type, function to read and write. |
| 153 | 153 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 154 | 154 |
///Instantiates a ProcessedMap. |
| 155 |
|
|
| 156 |
///This function instantiates a \c ProcessedMap. |
|
| 155 |
|
|
| 156 |
///This function instantiates a \c ProcessedMap. |
|
| 157 | 157 |
///\param g is the digraph, to which |
| 158 | 158 |
///we would like to define the \c ProcessedMap |
| 159 | 159 |
#ifdef DOXYGEN |
| 160 | 160 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 161 | 161 |
#else |
| 162 | 162 |
static ProcessedMap *createProcessedMap(const GR &) |
| 163 | 163 |
#endif |
| 164 | 164 |
{
|
| 165 | 165 |
return new ProcessedMap(); |
| 166 | 166 |
} |
| 167 | 167 |
///The type of the map that stores the dists of the nodes. |
| 168 |
|
|
| 168 |
|
|
| 169 | 169 |
///The type of the map that stores the dists of the nodes. |
| 170 | 170 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 171 | 171 |
/// |
| 172 | 172 |
typedef typename Digraph::template NodeMap<typename LM::Value> DistMap; |
| 173 | 173 |
///Instantiates a DistMap. |
| 174 |
|
|
| 175 |
///This function instantiates a \ref DistMap. |
|
| 174 |
|
|
| 175 |
///This function instantiates a \ref DistMap. |
|
| 176 | 176 |
///\param G is the digraph, to which we would like to define the \ref DistMap |
| 177 | 177 |
static DistMap *createDistMap(const GR &G) |
| 178 | 178 |
{
|
| 179 | 179 |
return new DistMap(G); |
| 180 | 180 |
} |
| 181 | 181 |
}; |
| 182 |
|
|
| 182 |
|
|
| 183 | 183 |
///%Dijkstra algorithm class. |
| 184 |
|
|
| 184 |
|
|
| 185 | 185 |
/// \ingroup shortest_path |
| 186 | 186 |
///This class provides an efficient implementation of %Dijkstra algorithm. |
| 187 | 187 |
///The arc lengths are passed to the algorithm using a |
| 188 | 188 |
///\ref concepts::ReadMap "ReadMap", |
| 189 | 189 |
///so it is easy to change it to any kind of length. |
| 190 | 190 |
/// |
| 191 | 191 |
///The type of the length is determined by the |
| 192 | 192 |
///\ref concepts::ReadMap::Value "Value" of the length map. |
| 193 | 193 |
/// |
| 194 | 194 |
///It is also possible to change the underlying priority heap. |
| 195 | 195 |
/// |
| 196 | 196 |
///\tparam GR The digraph type the algorithm runs on. The default value |
| 197 | 197 |
///is \ref ListDigraph. The value of GR is not used directly by |
| 198 | 198 |
///Dijkstra, it is only passed to \ref DijkstraDefaultTraits. |
| 199 | 199 |
///\tparam LM This read-only ArcMap determines the lengths of the |
| 200 | 200 |
///arcs. It is read once for each arc, so the map may involve in |
| 201 | 201 |
///relatively time consuming process to compute the arc length if |
| 202 | 202 |
///it is necessary. The default map type is \ref |
| 203 | 203 |
///concepts::Digraph::ArcMap "Digraph::ArcMap<int>". The value |
| 204 | 204 |
///of LM is not used directly by Dijkstra, it is only passed to \ref |
| 205 |
///DijkstraDefaultTraits. |
|
| 205 |
///DijkstraDefaultTraits. |
|
| 206 | 206 |
///\tparam TR Traits class to set |
| 207 | 207 |
///various data types used by the algorithm. The default traits |
| 208 | 208 |
///class is \ref DijkstraDefaultTraits |
| 209 | 209 |
///"DijkstraDefaultTraits<GR,LM>". See \ref |
| 210 | 210 |
///DijkstraDefaultTraits for the documentation of a Dijkstra traits |
| 211 | 211 |
///class. |
| 212 | 212 |
|
| 213 | 213 |
#ifdef DOXYGEN |
| 214 | 214 |
template <typename GR, typename LM, typename TR> |
| 215 | 215 |
#else |
| 216 | 216 |
template <typename GR=ListDigraph, |
| 217 |
typename LM=typename GR::template ArcMap<int>, |
|
| 218 |
typename TR=DijkstraDefaultTraits<GR,LM> > |
|
| 217 |
typename LM=typename GR::template ArcMap<int>, |
|
| 218 |
typename TR=DijkstraDefaultTraits<GR,LM> > |
|
| 219 | 219 |
#endif |
| 220 | 220 |
class Dijkstra {
|
| 221 | 221 |
public: |
| 222 | 222 |
/** |
| 223 | 223 |
* \brief \ref Exception for uninitialized parameters. |
| 224 | 224 |
* |
| 225 | 225 |
* This error represents problems in the initialization |
| 226 | 226 |
* of the parameters of the algorithms. |
| 227 | 227 |
*/ |
| 228 | 228 |
class UninitializedParameter : public lemon::UninitializedParameter {
|
| 229 | 229 |
public: |
| 230 | 230 |
virtual const char* what() const throw() {
|
| 231 |
|
|
| 231 |
return "lemon::Dijkstra::UninitializedParameter"; |
|
| 232 | 232 |
} |
| 233 | 233 |
}; |
| 234 | 234 |
|
| 235 | 235 |
typedef TR Traits; |
| 236 | 236 |
///The type of the underlying digraph. |
| 237 | 237 |
typedef typename TR::Digraph Digraph; |
| 238 | 238 |
///\e |
| 239 | 239 |
typedef typename Digraph::Node Node; |
| 240 | 240 |
///\e |
| 241 | 241 |
typedef typename Digraph::NodeIt NodeIt; |
| 242 | 242 |
///\e |
| 243 | 243 |
typedef typename Digraph::Arc Arc; |
| 244 | 244 |
///\e |
| 245 | 245 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 246 |
|
|
| 246 |
|
|
| 247 | 247 |
///The type of the length of the arcs. |
| 248 | 248 |
typedef typename TR::LengthMap::Value Value; |
| 249 | 249 |
///The type of the map that stores the arc lengths. |
| 250 | 250 |
typedef typename TR::LengthMap LengthMap; |
| 251 | 251 |
///\brief The type of the map that stores the last |
| 252 | 252 |
///arcs of the shortest paths. |
| 253 | 253 |
typedef typename TR::PredMap PredMap; |
| 254 | 254 |
///The type of the map indicating if a node is processed. |
| 255 | 255 |
typedef typename TR::ProcessedMap ProcessedMap; |
| 256 | 256 |
///The type of the map that stores the dists of the nodes. |
| 257 | 257 |
typedef typename TR::DistMap DistMap; |
| 258 | 258 |
///The cross reference type used for the current heap. |
| 259 | 259 |
typedef typename TR::HeapCrossRef HeapCrossRef; |
| 260 | 260 |
///The heap type used by the dijkstra algorithm. |
| 261 | 261 |
typedef typename TR::Heap Heap; |
| 262 | 262 |
///The operation traits. |
| ... | ... |
@@ -275,299 +275,299 @@ |
| 275 | 275 |
///Indicates if \ref _dist is locally allocated (\c true) or not. |
| 276 | 276 |
bool local_dist; |
| 277 | 277 |
///Pointer to the map of processed status of the nodes. |
| 278 | 278 |
ProcessedMap *_processed; |
| 279 | 279 |
///Indicates if \ref _processed is locally allocated (\c true) or not. |
| 280 | 280 |
bool local_processed; |
| 281 | 281 |
///Pointer to the heap cross references. |
| 282 | 282 |
HeapCrossRef *_heap_cross_ref; |
| 283 | 283 |
///Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not. |
| 284 | 284 |
bool local_heap_cross_ref; |
| 285 | 285 |
///Pointer to the heap. |
| 286 | 286 |
Heap *_heap; |
| 287 | 287 |
///Indicates if \ref _heap is locally allocated (\c true) or not. |
| 288 | 288 |
bool local_heap; |
| 289 | 289 |
|
| 290 | 290 |
///Creates the maps if necessary. |
| 291 |
|
|
| 291 |
|
|
| 292 | 292 |
///\todo Better memory allocation (instead of new). |
| 293 |
void create_maps() |
|
| 293 |
void create_maps() |
|
| 294 | 294 |
{
|
| 295 | 295 |
if(!_pred) {
|
| 296 |
local_pred = true; |
|
| 297 |
_pred = Traits::createPredMap(*G); |
|
| 296 |
local_pred = true; |
|
| 297 |
_pred = Traits::createPredMap(*G); |
|
| 298 | 298 |
} |
| 299 | 299 |
if(!_dist) {
|
| 300 |
local_dist = true; |
|
| 301 |
_dist = Traits::createDistMap(*G); |
|
| 300 |
local_dist = true; |
|
| 301 |
_dist = Traits::createDistMap(*G); |
|
| 302 | 302 |
} |
| 303 | 303 |
if(!_processed) {
|
| 304 |
local_processed = true; |
|
| 305 |
_processed = Traits::createProcessedMap(*G); |
|
| 304 |
local_processed = true; |
|
| 305 |
_processed = Traits::createProcessedMap(*G); |
|
| 306 | 306 |
} |
| 307 | 307 |
if (!_heap_cross_ref) {
|
| 308 |
local_heap_cross_ref = true; |
|
| 309 |
_heap_cross_ref = Traits::createHeapCrossRef(*G); |
|
| 308 |
local_heap_cross_ref = true; |
|
| 309 |
_heap_cross_ref = Traits::createHeapCrossRef(*G); |
|
| 310 | 310 |
} |
| 311 | 311 |
if (!_heap) {
|
| 312 |
local_heap = true; |
|
| 313 |
_heap = Traits::createHeap(*_heap_cross_ref); |
|
| 312 |
local_heap = true; |
|
| 313 |
_heap = Traits::createHeap(*_heap_cross_ref); |
|
| 314 | 314 |
} |
| 315 | 315 |
} |
| 316 |
|
|
| 316 |
|
|
| 317 | 317 |
public : |
| 318 | 318 |
|
| 319 | 319 |
typedef Dijkstra Create; |
| 320 |
|
|
| 320 |
|
|
| 321 | 321 |
///\name Named template parameters |
| 322 | 322 |
|
| 323 | 323 |
///@{
|
| 324 | 324 |
|
| 325 | 325 |
template <class T> |
| 326 | 326 |
struct DefPredMapTraits : public Traits {
|
| 327 | 327 |
typedef T PredMap; |
| 328 | 328 |
static PredMap *createPredMap(const Digraph &) |
| 329 | 329 |
{
|
| 330 |
|
|
| 330 |
throw UninitializedParameter(); |
|
| 331 | 331 |
} |
| 332 | 332 |
}; |
| 333 | 333 |
///\ref named-templ-param "Named parameter" for setting PredMap type |
| 334 | 334 |
|
| 335 | 335 |
///\ref named-templ-param "Named parameter" for setting PredMap type |
| 336 | 336 |
/// |
| 337 | 337 |
template <class T> |
| 338 |
struct DefPredMap |
|
| 339 |
: public Dijkstra< Digraph, LengthMap, DefPredMapTraits<T> > {
|
|
| 340 |
|
|
| 338 |
struct DefPredMap |
|
| 339 |
: public Dijkstra< Digraph, LengthMap, DefPredMapTraits<T> > {
|
|
| 340 |
typedef Dijkstra< Digraph, LengthMap, DefPredMapTraits<T> > Create; |
|
| 341 | 341 |
}; |
| 342 |
|
|
| 342 |
|
|
| 343 | 343 |
template <class T> |
| 344 | 344 |
struct DefDistMapTraits : public Traits {
|
| 345 | 345 |
typedef T DistMap; |
| 346 | 346 |
static DistMap *createDistMap(const Digraph &) |
| 347 | 347 |
{
|
| 348 |
|
|
| 348 |
throw UninitializedParameter(); |
|
| 349 | 349 |
} |
| 350 | 350 |
}; |
| 351 | 351 |
///\ref named-templ-param "Named parameter" for setting DistMap type |
| 352 | 352 |
|
| 353 | 353 |
///\ref named-templ-param "Named parameter" for setting DistMap type |
| 354 | 354 |
/// |
| 355 | 355 |
template <class T> |
| 356 |
struct DefDistMap |
|
| 357 |
: public Dijkstra< Digraph, LengthMap, DefDistMapTraits<T> > {
|
|
| 356 |
struct DefDistMap |
|
| 357 |
: public Dijkstra< Digraph, LengthMap, DefDistMapTraits<T> > {
|
|
| 358 | 358 |
typedef Dijkstra< Digraph, LengthMap, DefDistMapTraits<T> > Create; |
| 359 | 359 |
}; |
| 360 |
|
|
| 360 |
|
|
| 361 | 361 |
template <class T> |
| 362 | 362 |
struct DefProcessedMapTraits : public Traits {
|
| 363 | 363 |
typedef T ProcessedMap; |
| 364 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 364 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 365 | 365 |
{
|
| 366 |
|
|
| 366 |
throw UninitializedParameter(); |
|
| 367 | 367 |
} |
| 368 | 368 |
}; |
| 369 | 369 |
///\ref named-templ-param "Named parameter" for setting ProcessedMap type |
| 370 | 370 |
|
| 371 | 371 |
///\ref named-templ-param "Named parameter" for setting ProcessedMap type |
| 372 | 372 |
/// |
| 373 | 373 |
template <class T> |
| 374 |
struct DefProcessedMap |
|
| 375 |
: public Dijkstra< Digraph, LengthMap, DefProcessedMapTraits<T> > {
|
|
| 376 |
|
|
| 374 |
struct DefProcessedMap |
|
| 375 |
: public Dijkstra< Digraph, LengthMap, DefProcessedMapTraits<T> > {
|
|
| 376 |
typedef Dijkstra< Digraph, LengthMap, DefProcessedMapTraits<T> > Create; |
|
| 377 | 377 |
}; |
| 378 |
|
|
| 378 |
|
|
| 379 | 379 |
struct DefDigraphProcessedMapTraits : public Traits {
|
| 380 | 380 |
typedef typename Digraph::template NodeMap<bool> ProcessedMap; |
| 381 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 381 |
static ProcessedMap *createProcessedMap(const Digraph &G) |
|
| 382 | 382 |
{
|
| 383 |
|
|
| 383 |
return new ProcessedMap(G); |
|
| 384 | 384 |
} |
| 385 | 385 |
}; |
| 386 | 386 |
///\brief \ref named-templ-param "Named parameter" |
| 387 | 387 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 388 | 388 |
/// |
| 389 | 389 |
///\ref named-templ-param "Named parameter" |
| 390 | 390 |
///for setting the ProcessedMap type to be Digraph::NodeMap<bool>. |
| 391 | 391 |
///If you don't set it explicitely, it will be automatically allocated. |
| 392 | 392 |
template <class T> |
| 393 |
struct DefProcessedMapToBeDefaultMap |
|
| 393 |
struct DefProcessedMapToBeDefaultMap |
|
| 394 | 394 |
: public Dijkstra< Digraph, LengthMap, DefDigraphProcessedMapTraits> {
|
| 395 | 395 |
typedef Dijkstra< Digraph, LengthMap, DefDigraphProcessedMapTraits> Create; |
| 396 | 396 |
}; |
| 397 | 397 |
|
| 398 | 398 |
template <class H, class CR> |
| 399 | 399 |
struct DefHeapTraits : public Traits {
|
| 400 | 400 |
typedef CR HeapCrossRef; |
| 401 | 401 |
typedef H Heap; |
| 402 | 402 |
static HeapCrossRef *createHeapCrossRef(const Digraph &) {
|
| 403 |
|
|
| 403 |
throw UninitializedParameter(); |
|
| 404 | 404 |
} |
| 405 |
static Heap *createHeap(HeapCrossRef &) |
|
| 405 |
static Heap *createHeap(HeapCrossRef &) |
|
| 406 | 406 |
{
|
| 407 |
|
|
| 407 |
throw UninitializedParameter(); |
|
| 408 | 408 |
} |
| 409 | 409 |
}; |
| 410 | 410 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 411 | 411 |
///heap and cross reference type |
| 412 | 412 |
/// |
| 413 |
///\ref named-templ-param "Named parameter" for setting heap and cross |
|
| 413 |
///\ref named-templ-param "Named parameter" for setting heap and cross |
|
| 414 | 414 |
///reference type |
| 415 | 415 |
/// |
| 416 | 416 |
template <class H, class CR = typename Digraph::template NodeMap<int> > |
| 417 | 417 |
struct DefHeap |
| 418 |
: public Dijkstra< Digraph, LengthMap, DefHeapTraits<H, CR> > {
|
|
| 419 |
typedef Dijkstra< Digraph, LengthMap, DefHeapTraits<H, CR> > Create; |
|
| 418 |
: public Dijkstra< Digraph, LengthMap, DefHeapTraits<H, CR> > {
|
|
| 419 |
typedef Dijkstra< Digraph, LengthMap, DefHeapTraits<H, CR> > Create; |
|
| 420 | 420 |
}; |
| 421 | 421 |
|
| 422 | 422 |
template <class H, class CR> |
| 423 | 423 |
struct DefStandardHeapTraits : public Traits {
|
| 424 | 424 |
typedef CR HeapCrossRef; |
| 425 | 425 |
typedef H Heap; |
| 426 | 426 |
static HeapCrossRef *createHeapCrossRef(const Digraph &G) {
|
| 427 |
|
|
| 427 |
return new HeapCrossRef(G); |
|
| 428 | 428 |
} |
| 429 |
static Heap *createHeap(HeapCrossRef &R) |
|
| 429 |
static Heap *createHeap(HeapCrossRef &R) |
|
| 430 | 430 |
{
|
| 431 |
|
|
| 431 |
return new Heap(R); |
|
| 432 | 432 |
} |
| 433 | 433 |
}; |
| 434 | 434 |
///\brief \ref named-templ-param "Named parameter" for setting |
| 435 | 435 |
///heap and cross reference type with automatic allocation |
| 436 | 436 |
/// |
| 437 |
///\ref named-templ-param "Named parameter" for setting heap and cross |
|
| 438 |
///reference type. It can allocate the heap and the cross reference |
|
| 439 |
/// |
|
| 437 |
///\ref named-templ-param "Named parameter" for setting heap and cross |
|
| 438 |
///reference type. It can allocate the heap and the cross reference |
|
| 439 |
///object if the cross reference's constructor waits for the digraph as |
|
| 440 | 440 |
///parameter and the heap's constructor waits for the cross reference. |
| 441 | 441 |
template <class H, class CR = typename Digraph::template NodeMap<int> > |
| 442 | 442 |
struct DefStandardHeap |
| 443 |
: public Dijkstra< Digraph, LengthMap, DefStandardHeapTraits<H, CR> > {
|
|
| 444 |
typedef Dijkstra< Digraph, LengthMap, DefStandardHeapTraits<H, CR> > |
|
| 443 |
: public Dijkstra< Digraph, LengthMap, DefStandardHeapTraits<H, CR> > {
|
|
| 444 |
typedef Dijkstra< Digraph, LengthMap, DefStandardHeapTraits<H, CR> > |
|
| 445 | 445 |
Create; |
| 446 | 446 |
}; |
| 447 | 447 |
|
| 448 | 448 |
template <class T> |
| 449 | 449 |
struct DefOperationTraitsTraits : public Traits {
|
| 450 | 450 |
typedef T OperationTraits; |
| 451 | 451 |
}; |
| 452 |
|
|
| 453 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 452 |
|
|
| 453 |
/// \brief \ref named-templ-param "Named parameter" for setting |
|
| 454 | 454 |
/// OperationTraits type |
| 455 | 455 |
/// |
| 456 | 456 |
/// \ref named-templ-param "Named parameter" for setting OperationTraits |
| 457 | 457 |
/// type |
| 458 | 458 |
template <class T> |
| 459 | 459 |
struct DefOperationTraits |
| 460 | 460 |
: public Dijkstra<Digraph, LengthMap, DefOperationTraitsTraits<T> > {
|
| 461 | 461 |
typedef Dijkstra<Digraph, LengthMap, DefOperationTraitsTraits<T> > |
| 462 | 462 |
Create; |
| 463 | 463 |
}; |
| 464 |
|
|
| 464 |
|
|
| 465 | 465 |
///@} |
| 466 | 466 |
|
| 467 | 467 |
|
| 468 | 468 |
protected: |
| 469 | 469 |
|
| 470 | 470 |
Dijkstra() {}
|
| 471 | 471 |
|
| 472 |
public: |
|
| 473 |
|
|
| 472 |
public: |
|
| 473 |
|
|
| 474 | 474 |
///Constructor. |
| 475 |
|
|
| 475 |
|
|
| 476 | 476 |
///\param _G the digraph the algorithm will run on. |
| 477 | 477 |
///\param _length the length map used by the algorithm. |
| 478 | 478 |
Dijkstra(const Digraph& _G, const LengthMap& _length) : |
| 479 | 479 |
G(&_G), length(&_length), |
| 480 | 480 |
_pred(NULL), local_pred(false), |
| 481 | 481 |
_dist(NULL), local_dist(false), |
| 482 | 482 |
_processed(NULL), local_processed(false), |
| 483 | 483 |
_heap_cross_ref(NULL), local_heap_cross_ref(false), |
| 484 | 484 |
_heap(NULL), local_heap(false) |
| 485 | 485 |
{ }
|
| 486 |
|
|
| 486 |
|
|
| 487 | 487 |
///Destructor. |
| 488 |
~Dijkstra() |
|
| 488 |
~Dijkstra() |
|
| 489 | 489 |
{
|
| 490 | 490 |
if(local_pred) delete _pred; |
| 491 | 491 |
if(local_dist) delete _dist; |
| 492 | 492 |
if(local_processed) delete _processed; |
| 493 | 493 |
if(local_heap_cross_ref) delete _heap_cross_ref; |
| 494 | 494 |
if(local_heap) delete _heap; |
| 495 | 495 |
} |
| 496 | 496 |
|
| 497 | 497 |
///Sets the length map. |
| 498 | 498 |
|
| 499 | 499 |
///Sets the length map. |
| 500 | 500 |
///\return <tt> (*this) </tt> |
| 501 |
Dijkstra &lengthMap(const LengthMap &m) |
|
| 501 |
Dijkstra &lengthMap(const LengthMap &m) |
|
| 502 | 502 |
{
|
| 503 | 503 |
length = &m; |
| 504 | 504 |
return *this; |
| 505 | 505 |
} |
| 506 | 506 |
|
| 507 | 507 |
///Sets the map storing the predecessor arcs. |
| 508 | 508 |
|
| 509 | 509 |
///Sets the map storing the predecessor arcs. |
| 510 | 510 |
///If you don't use this function before calling \ref run(), |
| 511 | 511 |
///it will allocate one. The destuctor deallocates this |
| 512 | 512 |
///automatically allocated map, of course. |
| 513 | 513 |
///\return <tt> (*this) </tt> |
| 514 |
Dijkstra &predMap(PredMap &m) |
|
| 514 |
Dijkstra &predMap(PredMap &m) |
|
| 515 | 515 |
{
|
| 516 | 516 |
if(local_pred) {
|
| 517 |
delete _pred; |
|
| 518 |
local_pred=false; |
|
| 517 |
delete _pred; |
|
| 518 |
local_pred=false; |
|
| 519 | 519 |
} |
| 520 | 520 |
_pred = &m; |
| 521 | 521 |
return *this; |
| 522 | 522 |
} |
| 523 | 523 |
|
| 524 | 524 |
///Sets the map storing the distances calculated by the algorithm. |
| 525 | 525 |
|
| 526 | 526 |
///Sets the map storing the distances calculated by the algorithm. |
| 527 | 527 |
///If you don't use this function before calling \ref run(), |
| 528 | 528 |
///it will allocate one. The destuctor deallocates this |
| 529 | 529 |
///automatically allocated map, of course. |
| 530 | 530 |
///\return <tt> (*this) </tt> |
| 531 |
Dijkstra &distMap(DistMap &m) |
|
| 531 |
Dijkstra &distMap(DistMap &m) |
|
| 532 | 532 |
{
|
| 533 | 533 |
if(local_dist) {
|
| 534 |
delete _dist; |
|
| 535 |
local_dist=false; |
|
| 534 |
delete _dist; |
|
| 535 |
local_dist=false; |
|
| 536 | 536 |
} |
| 537 | 537 |
_dist = &m; |
| 538 | 538 |
return *this; |
| 539 | 539 |
} |
| 540 | 540 |
|
| 541 | 541 |
///Sets the heap and the cross reference used by algorithm. |
| 542 | 542 |
|
| 543 | 543 |
///Sets the heap and the cross reference used by algorithm. |
| 544 | 544 |
///If you don't use this function before calling \ref run(), |
| 545 | 545 |
///it will allocate one. The destuctor deallocates this |
| 546 | 546 |
///automatically allocated heap and cross reference, of course. |
| 547 | 547 |
///\return <tt> (*this) </tt> |
| 548 | 548 |
Dijkstra &heap(Heap& hp, HeapCrossRef &cr) |
| 549 | 549 |
{
|
| 550 | 550 |
if(local_heap_cross_ref) {
|
| 551 |
delete _heap_cross_ref; |
|
| 552 |
local_heap_cross_ref=false; |
|
| 551 |
delete _heap_cross_ref; |
|
| 552 |
local_heap_cross_ref=false; |
|
| 553 | 553 |
} |
| 554 | 554 |
_heap_cross_ref = &cr; |
| 555 | 555 |
if(local_heap) {
|
| 556 |
delete _heap; |
|
| 557 |
local_heap=false; |
|
| 556 |
delete _heap; |
|
| 557 |
local_heap=false; |
|
| 558 | 558 |
} |
| 559 | 559 |
_heap = &hp; |
| 560 | 560 |
return *this; |
| 561 | 561 |
} |
| 562 | 562 |
|
| 563 | 563 |
private: |
| 564 | 564 |
void finalizeNodeData(Node v,Value dst) |
| 565 | 565 |
{
|
| 566 | 566 |
_processed->set(v,true); |
| 567 | 567 |
_dist->set(v, dst); |
| 568 | 568 |
} |
| 569 | 569 |
|
| 570 | 570 |
public: |
| 571 | 571 |
|
| 572 | 572 |
typedef PredMapPath<Digraph, PredMap> Path; |
| 573 | 573 |
|
| ... | ... |
@@ -579,233 +579,233 @@ |
| 579 | 579 |
///first you must call \ref init(), then you can add several source nodes |
| 580 | 580 |
///with \ref addSource(). |
| 581 | 581 |
///Finally \ref start() will perform the actual path |
| 582 | 582 |
///computation. |
| 583 | 583 |
|
| 584 | 584 |
///@{
|
| 585 | 585 |
|
| 586 | 586 |
///Initializes the internal data structures. |
| 587 | 587 |
|
| 588 | 588 |
///Initializes the internal data structures. |
| 589 | 589 |
/// |
| 590 | 590 |
void init() |
| 591 | 591 |
{
|
| 592 | 592 |
create_maps(); |
| 593 | 593 |
_heap->clear(); |
| 594 | 594 |
for ( NodeIt u(*G) ; u!=INVALID ; ++u ) {
|
| 595 |
_pred->set(u,INVALID); |
|
| 596 |
_processed->set(u,false); |
|
| 597 |
|
|
| 595 |
_pred->set(u,INVALID); |
|
| 596 |
_processed->set(u,false); |
|
| 597 |
_heap_cross_ref->set(u,Heap::PRE_HEAP); |
|
| 598 | 598 |
} |
| 599 | 599 |
} |
| 600 |
|
|
| 600 |
|
|
| 601 | 601 |
///Adds a new source node. |
| 602 | 602 |
|
| 603 | 603 |
///Adds a new source node to the priority heap. |
| 604 | 604 |
/// |
| 605 | 605 |
///The optional second parameter is the initial distance of the node. |
| 606 | 606 |
/// |
| 607 | 607 |
///It checks if the node has already been added to the heap and |
| 608 | 608 |
///it is pushed to the heap only if either it was not in the heap |
| 609 | 609 |
///or the shortest path found till then is shorter than \c dst. |
| 610 | 610 |
void addSource(Node s,Value dst=OperationTraits::zero()) |
| 611 | 611 |
{
|
| 612 | 612 |
if(_heap->state(s) != Heap::IN_HEAP) {
|
| 613 |
|
|
| 613 |
_heap->push(s,dst); |
|
| 614 | 614 |
} else if(OperationTraits::less((*_heap)[s], dst)) {
|
| 615 |
_heap->set(s,dst); |
|
| 616 |
_pred->set(s,INVALID); |
|
| 615 |
_heap->set(s,dst); |
|
| 616 |
_pred->set(s,INVALID); |
|
| 617 | 617 |
} |
| 618 | 618 |
} |
| 619 |
|
|
| 619 |
|
|
| 620 | 620 |
///Processes the next node in the priority heap |
| 621 | 621 |
|
| 622 | 622 |
///Processes the next node in the priority heap. |
| 623 | 623 |
/// |
| 624 | 624 |
///\return The processed node. |
| 625 | 625 |
/// |
| 626 | 626 |
///\warning The priority heap must not be empty! |
| 627 | 627 |
Node processNextNode() |
| 628 | 628 |
{
|
| 629 |
Node v=_heap->top(); |
|
| 629 |
Node v=_heap->top(); |
|
| 630 | 630 |
Value oldvalue=_heap->prio(); |
| 631 | 631 |
_heap->pop(); |
| 632 | 632 |
finalizeNodeData(v,oldvalue); |
| 633 |
|
|
| 633 |
|
|
| 634 | 634 |
for(OutArcIt e(*G,v); e!=INVALID; ++e) {
|
| 635 |
Node w=G->target(e); |
|
| 636 |
switch(_heap->state(w)) {
|
|
| 637 |
case Heap::PRE_HEAP: |
|
| 638 |
_heap->push(w,OperationTraits::plus(oldvalue, (*length)[e])); |
|
| 639 |
_pred->set(w,e); |
|
| 640 |
break; |
|
| 641 |
case Heap::IN_HEAP: |
|
| 642 |
{
|
|
| 643 |
Value newvalue = OperationTraits::plus(oldvalue, (*length)[e]); |
|
| 644 |
if ( OperationTraits::less(newvalue, (*_heap)[w]) ) {
|
|
| 645 |
_heap->decrease(w, newvalue); |
|
| 646 |
_pred->set(w,e); |
|
| 647 |
} |
|
| 648 |
} |
|
| 649 |
break; |
|
| 650 |
case Heap::POST_HEAP: |
|
| 651 |
break; |
|
| 652 |
} |
|
| 635 |
Node w=G->target(e); |
|
| 636 |
switch(_heap->state(w)) {
|
|
| 637 |
case Heap::PRE_HEAP: |
|
| 638 |
_heap->push(w,OperationTraits::plus(oldvalue, (*length)[e])); |
|
| 639 |
_pred->set(w,e); |
|
| 640 |
break; |
|
| 641 |
case Heap::IN_HEAP: |
|
| 642 |
{
|
|
| 643 |
Value newvalue = OperationTraits::plus(oldvalue, (*length)[e]); |
|
| 644 |
if ( OperationTraits::less(newvalue, (*_heap)[w]) ) {
|
|
| 645 |
_heap->decrease(w, newvalue); |
|
| 646 |
_pred->set(w,e); |
|
| 647 |
} |
|
| 648 |
} |
|
| 649 |
break; |
|
| 650 |
case Heap::POST_HEAP: |
|
| 651 |
break; |
|
| 652 |
} |
|
| 653 | 653 |
} |
| 654 | 654 |
return v; |
| 655 | 655 |
} |
| 656 | 656 |
|
| 657 | 657 |
///Next node to be processed. |
| 658 |
|
|
| 658 |
|
|
| 659 | 659 |
///Next node to be processed. |
| 660 | 660 |
/// |
| 661 | 661 |
///\return The next node to be processed or INVALID if the priority heap |
| 662 | 662 |
/// is empty. |
| 663 | 663 |
Node nextNode() |
| 664 |
{
|
|
| 664 |
{
|
|
| 665 | 665 |
return !_heap->empty()?_heap->top():INVALID; |
| 666 | 666 |
} |
| 667 |
|
|
| 667 |
|
|
| 668 | 668 |
///\brief Returns \c false if there are nodes |
| 669 | 669 |
///to be processed in the priority heap |
| 670 | 670 |
/// |
| 671 | 671 |
///Returns \c false if there are nodes |
| 672 | 672 |
///to be processed in the priority heap |
| 673 | 673 |
bool emptyQueue() { return _heap->empty(); }
|
| 674 | 674 |
///Returns the number of the nodes to be processed in the priority heap |
| 675 | 675 |
|
| 676 | 676 |
///Returns the number of the nodes to be processed in the priority heap |
| 677 | 677 |
/// |
| 678 | 678 |
int queueSize() { return _heap->size(); }
|
| 679 |
|
|
| 679 |
|
|
| 680 | 680 |
///Executes the algorithm. |
| 681 | 681 |
|
| 682 | 682 |
///Executes the algorithm. |
| 683 | 683 |
/// |
| 684 | 684 |
///\pre init() must be called and at least one node should be added |
| 685 | 685 |
///with addSource() before using this function. |
| 686 | 686 |
/// |
| 687 | 687 |
///This method runs the %Dijkstra algorithm from the root node(s) |
| 688 | 688 |
///in order to |
| 689 | 689 |
///compute the |
| 690 | 690 |
///shortest path to each node. The algorithm computes |
| 691 | 691 |
///- The shortest path tree. |
| 692 | 692 |
///- The distance of each node from the root(s). |
| 693 | 693 |
/// |
| 694 | 694 |
void start() |
| 695 | 695 |
{
|
| 696 | 696 |
while ( !_heap->empty() ) processNextNode(); |
| 697 | 697 |
} |
| 698 |
|
|
| 698 |
|
|
| 699 | 699 |
///Executes the algorithm until \c dest is reached. |
| 700 | 700 |
|
| 701 | 701 |
///Executes the algorithm until \c dest is reached. |
| 702 | 702 |
/// |
| 703 | 703 |
///\pre init() must be called and at least one node should be added |
| 704 | 704 |
///with addSource() before using this function. |
| 705 | 705 |
/// |
| 706 | 706 |
///This method runs the %Dijkstra algorithm from the root node(s) |
| 707 | 707 |
///in order to |
| 708 | 708 |
///compute the |
| 709 | 709 |
///shortest path to \c dest. The algorithm computes |
| 710 | 710 |
///- The shortest path to \c dest. |
| 711 | 711 |
///- The distance of \c dest from the root(s). |
| 712 | 712 |
/// |
| 713 | 713 |
void start(Node dest) |
| 714 | 714 |
{
|
| 715 | 715 |
while ( !_heap->empty() && _heap->top()!=dest ) processNextNode(); |
| 716 | 716 |
if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio()); |
| 717 | 717 |
} |
| 718 |
|
|
| 718 |
|
|
| 719 | 719 |
///Executes the algorithm until a condition is met. |
| 720 | 720 |
|
| 721 | 721 |
///Executes the algorithm until a condition is met. |
| 722 | 722 |
/// |
| 723 | 723 |
///\pre init() must be called and at least one node should be added |
| 724 | 724 |
///with addSource() before using this function. |
| 725 | 725 |
/// |
| 726 | 726 |
///\param nm must be a bool (or convertible) node map. The algorithm |
| 727 | 727 |
///will stop when it reaches a node \c v with <tt>nm[v]</tt> true. |
| 728 | 728 |
/// |
| 729 | 729 |
///\return The reached node \c v with <tt>nm[v]</tt> true or |
| 730 | 730 |
///\c INVALID if no such node was found. |
| 731 | 731 |
template<class NodeBoolMap> |
| 732 | 732 |
Node start(const NodeBoolMap &nm) |
| 733 | 733 |
{
|
| 734 | 734 |
while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode(); |
| 735 | 735 |
if ( _heap->empty() ) return INVALID; |
| 736 | 736 |
finalizeNodeData(_heap->top(),_heap->prio()); |
| 737 | 737 |
return _heap->top(); |
| 738 | 738 |
} |
| 739 |
|
|
| 739 |
|
|
| 740 | 740 |
///Runs %Dijkstra algorithm from node \c s. |
| 741 |
|
|
| 741 |
|
|
| 742 | 742 |
///This method runs the %Dijkstra algorithm from a root node \c s |
| 743 | 743 |
///in order to |
| 744 | 744 |
///compute the |
| 745 | 745 |
///shortest path to each node. The algorithm computes |
| 746 | 746 |
///- The shortest path tree. |
| 747 | 747 |
///- The distance of each node from the root. |
| 748 | 748 |
/// |
| 749 | 749 |
///\note d.run(s) is just a shortcut of the following code. |
| 750 | 750 |
///\code |
| 751 | 751 |
/// d.init(); |
| 752 | 752 |
/// d.addSource(s); |
| 753 | 753 |
/// d.start(); |
| 754 | 754 |
///\endcode |
| 755 | 755 |
void run(Node s) {
|
| 756 | 756 |
init(); |
| 757 | 757 |
addSource(s); |
| 758 | 758 |
start(); |
| 759 | 759 |
} |
| 760 |
|
|
| 760 |
|
|
| 761 | 761 |
///Finds the shortest path between \c s and \c t. |
| 762 |
|
|
| 762 |
|
|
| 763 | 763 |
///Finds the shortest path between \c s and \c t. |
| 764 | 764 |
/// |
| 765 | 765 |
///\return The length of the shortest s---t path if there exists one, |
| 766 | 766 |
///0 otherwise. |
| 767 | 767 |
///\note Apart from the return value, d.run(s) is |
| 768 | 768 |
///just a shortcut of the following code. |
| 769 | 769 |
///\code |
| 770 | 770 |
/// d.init(); |
| 771 | 771 |
/// d.addSource(s); |
| 772 | 772 |
/// d.start(t); |
| 773 | 773 |
///\endcode |
| 774 | 774 |
Value run(Node s,Node t) {
|
| 775 | 775 |
init(); |
| 776 | 776 |
addSource(s); |
| 777 | 777 |
start(t); |
| 778 | 778 |
return (*_pred)[t]==INVALID?OperationTraits::zero():(*_dist)[t]; |
| 779 | 779 |
} |
| 780 |
|
|
| 780 |
|
|
| 781 | 781 |
///@} |
| 782 | 782 |
|
| 783 | 783 |
///\name Query Functions |
| 784 | 784 |
///The result of the %Dijkstra algorithm can be obtained using these |
| 785 | 785 |
///functions.\n |
| 786 | 786 |
///Before the use of these functions, |
| 787 | 787 |
///either run() or start() must be called. |
| 788 |
|
|
| 788 |
|
|
| 789 | 789 |
///@{
|
| 790 | 790 |
|
| 791 | 791 |
///Gives back the shortest path. |
| 792 |
|
|
| 792 |
|
|
| 793 | 793 |
///Gives back the shortest path. |
| 794 | 794 |
///\pre The \c t should be reachable from the source. |
| 795 |
Path path(Node t) |
|
| 795 |
Path path(Node t) |
|
| 796 | 796 |
{
|
| 797 | 797 |
return Path(*G, *_pred, t); |
| 798 | 798 |
} |
| 799 | 799 |
|
| 800 | 800 |
///The distance of a node from the root. |
| 801 | 801 |
|
| 802 | 802 |
///Returns the distance of a node from the root. |
| 803 | 803 |
///\pre \ref run() must be called before using this function. |
| 804 | 804 |
///\warning If node \c v in unreachable from the root the return value |
| 805 | 805 |
///of this funcion is undefined. |
| 806 | 806 |
Value dist(Node v) const { return (*_dist)[v]; }
|
| 807 | 807 |
|
| 808 | 808 |
///The current distance of a node from the root. |
| 809 | 809 |
|
| 810 | 810 |
///Returns the current distance of a node from the root. |
| 811 | 811 |
///It may be decreased in the following processes. |
| ... | ... |
@@ -819,378 +819,378 @@ |
| 819 | 819 |
///v. It is \ref INVALID |
| 820 | 820 |
///if \c v is unreachable from the root or if \c v=s. The |
| 821 | 821 |
///shortest path tree used here is equal to the shortest path tree used in |
| 822 | 822 |
///\ref predNode(). \pre \ref run() must be called before using |
| 823 | 823 |
///this function. |
| 824 | 824 |
Arc predArc(Node v) const { return (*_pred)[v]; }
|
| 825 | 825 |
|
| 826 | 826 |
///Returns the 'previous node' of the shortest path tree. |
| 827 | 827 |
|
| 828 | 828 |
///For a node \c v it returns the 'previous node' of the shortest path tree, |
| 829 | 829 |
///i.e. it returns the last but one node from a shortest path from the |
| 830 | 830 |
///root to \c /v. It is INVALID if \c v is unreachable from the root or if |
| 831 | 831 |
///\c v=s. The shortest path tree used here is equal to the shortest path |
| 832 | 832 |
///tree used in \ref predArc(). \pre \ref run() must be called before |
| 833 | 833 |
///using this function. |
| 834 | 834 |
Node predNode(Node v) const { return (*_pred)[v]==INVALID ? INVALID:
|
| 835 |
G->source((*_pred)[v]); } |
|
| 836 |
|
|
| 835 |
G->source((*_pred)[v]); } |
|
| 836 |
|
|
| 837 | 837 |
///Returns a reference to the NodeMap of distances. |
| 838 | 838 |
|
| 839 | 839 |
///Returns a reference to the NodeMap of distances. \pre \ref run() must |
| 840 | 840 |
///be called before using this function. |
| 841 | 841 |
const DistMap &distMap() const { return *_dist;}
|
| 842 |
|
|
| 842 |
|
|
| 843 | 843 |
///Returns a reference to the shortest path tree map. |
| 844 | 844 |
|
| 845 | 845 |
///Returns a reference to the NodeMap of the arcs of the |
| 846 | 846 |
///shortest path tree. |
| 847 | 847 |
///\pre \ref run() must be called before using this function. |
| 848 | 848 |
const PredMap &predMap() const { return *_pred;}
|
| 849 |
|
|
| 849 |
|
|
| 850 | 850 |
///Checks if a node is reachable from the root. |
| 851 | 851 |
|
| 852 | 852 |
///Returns \c true if \c v is reachable from the root. |
| 853 | 853 |
///\warning The source nodes are inditated as unreached. |
| 854 | 854 |
///\pre \ref run() must be called before using this function. |
| 855 | 855 |
/// |
| 856 | 856 |
bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; }
|
| 857 | 857 |
|
| 858 | 858 |
///Checks if a node is processed. |
| 859 | 859 |
|
| 860 | 860 |
///Returns \c true if \c v is processed, i.e. the shortest |
| 861 | 861 |
///path to \c v has already found. |
| 862 | 862 |
///\pre \ref run() must be called before using this function. |
| 863 | 863 |
/// |
| 864 | 864 |
bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; }
|
| 865 |
|
|
| 865 |
|
|
| 866 | 866 |
///@} |
| 867 | 867 |
}; |
| 868 | 868 |
|
| 869 | 869 |
|
| 870 | 870 |
|
| 871 | 871 |
|
| 872 |
|
|
| 872 |
|
|
| 873 | 873 |
///Default traits class of Dijkstra function. |
| 874 | 874 |
|
| 875 | 875 |
///Default traits class of Dijkstra function. |
| 876 | 876 |
///\tparam GR Digraph type. |
| 877 | 877 |
///\tparam LM Type of length map. |
| 878 | 878 |
template<class GR, class LM> |
| 879 | 879 |
struct DijkstraWizardDefaultTraits |
| 880 | 880 |
{
|
| 881 |
///The digraph type the algorithm runs on. |
|
| 881 |
///The digraph type the algorithm runs on. |
|
| 882 | 882 |
typedef GR Digraph; |
| 883 | 883 |
///The type of the map that stores the arc lengths. |
| 884 | 884 |
|
| 885 | 885 |
///The type of the map that stores the arc lengths. |
| 886 | 886 |
///It must meet the \ref concepts::ReadMap "ReadMap" concept. |
| 887 | 887 |
typedef LM LengthMap; |
| 888 | 888 |
//The type of the length of the arcs. |
| 889 | 889 |
typedef typename LM::Value Value; |
| 890 | 890 |
/// Operation traits for Dijkstra algorithm. |
| 891 | 891 |
|
| 892 | 892 |
/// It defines the used operation by the algorithm. |
| 893 | 893 |
/// \see DijkstraDefaultOperationTraits |
| 894 | 894 |
typedef DijkstraDefaultOperationTraits<Value> OperationTraits; |
| 895 | 895 |
///The heap type used by Dijkstra algorithm. |
| 896 | 896 |
|
| 897 | 897 |
/// The cross reference type used by heap. |
| 898 | 898 |
|
| 899 | 899 |
/// The cross reference type used by heap. |
| 900 | 900 |
/// Usually it is \c Digraph::NodeMap<int>. |
| 901 | 901 |
typedef typename Digraph::template NodeMap<int> HeapCrossRef; |
| 902 | 902 |
///Instantiates a HeapCrossRef. |
| 903 | 903 |
|
| 904 |
///This function instantiates a \ref HeapCrossRef. |
|
| 905 |
/// \param G is the digraph, to which we would like to define the |
|
| 904 |
///This function instantiates a \ref HeapCrossRef. |
|
| 905 |
/// \param G is the digraph, to which we would like to define the |
|
| 906 | 906 |
/// HeapCrossRef. |
| 907 | 907 |
/// \todo The digraph alone may be insufficient for the initialization |
| 908 |
static HeapCrossRef *createHeapCrossRef(const GR &G) |
|
| 908 |
static HeapCrossRef *createHeapCrossRef(const GR &G) |
|
| 909 | 909 |
{
|
| 910 | 910 |
return new HeapCrossRef(G); |
| 911 | 911 |
} |
| 912 |
|
|
| 912 |
|
|
| 913 | 913 |
///The heap type used by Dijkstra algorithm. |
| 914 | 914 |
|
| 915 | 915 |
///The heap type used by Dijkstra algorithm. |
| 916 | 916 |
/// |
| 917 | 917 |
///\sa BinHeap |
| 918 | 918 |
///\sa Dijkstra |
| 919 | 919 |
typedef BinHeap<typename LM::Value, typename GR::template NodeMap<int>, |
| 920 |
|
|
| 920 |
std::less<Value> > Heap; |
|
| 921 | 921 |
|
| 922 |
static Heap *createHeap(HeapCrossRef& R) |
|
| 922 |
static Heap *createHeap(HeapCrossRef& R) |
|
| 923 | 923 |
{
|
| 924 | 924 |
return new Heap(R); |
| 925 | 925 |
} |
| 926 | 926 |
|
| 927 | 927 |
///\brief The type of the map that stores the last |
| 928 | 928 |
///arcs of the shortest paths. |
| 929 |
/// |
|
| 929 |
/// |
|
| 930 | 930 |
///The type of the map that stores the last |
| 931 | 931 |
///arcs of the shortest paths. |
| 932 | 932 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 933 | 933 |
/// |
| 934 | 934 |
typedef NullMap <typename GR::Node,typename GR::Arc> PredMap; |
| 935 | 935 |
///Instantiates a PredMap. |
| 936 |
|
|
| 937 |
///This function instantiates a \ref PredMap. |
|
| 936 |
|
|
| 937 |
///This function instantiates a \ref PredMap. |
|
| 938 | 938 |
///\param g is the digraph, to which we would like to define the PredMap. |
| 939 | 939 |
///\todo The digraph alone may be insufficient for the initialization |
| 940 | 940 |
#ifdef DOXYGEN |
| 941 |
static PredMap *createPredMap(const GR &g) |
|
| 941 |
static PredMap *createPredMap(const GR &g) |
|
| 942 | 942 |
#else |
| 943 |
static PredMap *createPredMap(const GR &) |
|
| 943 |
static PredMap *createPredMap(const GR &) |
|
| 944 | 944 |
#endif |
| 945 | 945 |
{
|
| 946 | 946 |
return new PredMap(); |
| 947 | 947 |
} |
| 948 | 948 |
///The type of the map that stores whether a nodes is processed. |
| 949 |
|
|
| 949 |
|
|
| 950 | 950 |
///The type of the map that stores whether a nodes is processed. |
| 951 | 951 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 952 | 952 |
///By default it is a NullMap. |
| 953 | 953 |
///\todo If it is set to a real map, |
| 954 | 954 |
///Dijkstra::processed() should read this. |
| 955 | 955 |
///\todo named parameter to set this type, function to read and write. |
| 956 | 956 |
typedef NullMap<typename Digraph::Node,bool> ProcessedMap; |
| 957 | 957 |
///Instantiates a ProcessedMap. |
| 958 |
|
|
| 959 |
///This function instantiates a \ref ProcessedMap. |
|
| 958 |
|
|
| 959 |
///This function instantiates a \ref ProcessedMap. |
|
| 960 | 960 |
///\param g is the digraph, to which |
| 961 | 961 |
///we would like to define the \ref ProcessedMap |
| 962 | 962 |
#ifdef DOXYGEN |
| 963 | 963 |
static ProcessedMap *createProcessedMap(const GR &g) |
| 964 | 964 |
#else |
| 965 | 965 |
static ProcessedMap *createProcessedMap(const GR &) |
| 966 | 966 |
#endif |
| 967 | 967 |
{
|
| 968 | 968 |
return new ProcessedMap(); |
| 969 | 969 |
} |
| 970 | 970 |
///The type of the map that stores the dists of the nodes. |
| 971 |
|
|
| 971 |
|
|
| 972 | 972 |
///The type of the map that stores the dists of the nodes. |
| 973 | 973 |
///It must meet the \ref concepts::WriteMap "WriteMap" concept. |
| 974 | 974 |
/// |
| 975 | 975 |
typedef NullMap<typename Digraph::Node,typename LM::Value> DistMap; |
| 976 | 976 |
///Instantiates a DistMap. |
| 977 |
|
|
| 978 |
///This function instantiates a \ref DistMap. |
|
| 977 |
|
|
| 978 |
///This function instantiates a \ref DistMap. |
|
| 979 | 979 |
///\param g is the digraph, to which we would like to define the \ref DistMap |
| 980 | 980 |
#ifdef DOXYGEN |
| 981 | 981 |
static DistMap *createDistMap(const GR &g) |
| 982 | 982 |
#else |
| 983 | 983 |
static DistMap *createDistMap(const GR &) |
| 984 | 984 |
#endif |
| 985 | 985 |
{
|
| 986 | 986 |
return new DistMap(); |
| 987 | 987 |
} |
| 988 | 988 |
}; |
| 989 |
|
|
| 989 |
|
|
| 990 | 990 |
/// Default traits used by \ref DijkstraWizard |
| 991 | 991 |
|
| 992 | 992 |
/// To make it easier to use Dijkstra algorithm |
| 993 | 993 |
///we have created a wizard class. |
| 994 | 994 |
/// This \ref DijkstraWizard class needs default traits, |
| 995 | 995 |
///as well as the \ref Dijkstra class. |
| 996 | 996 |
/// The \ref DijkstraWizardBase is a class to be the default traits of the |
| 997 | 997 |
/// \ref DijkstraWizard class. |
| 998 | 998 |
/// \todo More named parameters are required... |
| 999 | 999 |
template<class GR,class LM> |
| 1000 | 1000 |
class DijkstraWizardBase : public DijkstraWizardDefaultTraits<GR,LM> |
| 1001 | 1001 |
{
|
| 1002 | 1002 |
|
| 1003 | 1003 |
typedef DijkstraWizardDefaultTraits<GR,LM> Base; |
| 1004 | 1004 |
protected: |
| 1005 | 1005 |
/// Type of the nodes in the digraph. |
| 1006 | 1006 |
typedef typename Base::Digraph::Node Node; |
| 1007 | 1007 |
|
| 1008 | 1008 |
/// Pointer to the underlying digraph. |
| 1009 | 1009 |
void *_g; |
| 1010 | 1010 |
/// Pointer to the length map |
| 1011 | 1011 |
void *_length; |
| 1012 | 1012 |
///Pointer to the map of predecessors arcs. |
| 1013 | 1013 |
void *_pred; |
| 1014 | 1014 |
///Pointer to the map of distances. |
| 1015 | 1015 |
void *_dist; |
| 1016 | 1016 |
///Pointer to the source node. |
| 1017 | 1017 |
Node _source; |
| 1018 | 1018 |
|
| 1019 | 1019 |
public: |
| 1020 | 1020 |
/// Constructor. |
| 1021 |
|
|
| 1021 |
|
|
| 1022 | 1022 |
/// This constructor does not require parameters, therefore it initiates |
| 1023 | 1023 |
/// all of the attributes to default values (0, INVALID). |
| 1024 | 1024 |
DijkstraWizardBase() : _g(0), _length(0), _pred(0), |
| 1025 |
|
|
| 1025 |
_dist(0), _source(INVALID) {}
|
|
| 1026 | 1026 |
|
| 1027 | 1027 |
/// Constructor. |
| 1028 |
|
|
| 1028 |
|
|
| 1029 | 1029 |
/// This constructor requires some parameters, |
| 1030 | 1030 |
/// listed in the parameters list. |
| 1031 | 1031 |
/// Others are initiated to 0. |
| 1032 | 1032 |
/// \param g is the initial value of \ref _g |
| 1033 | 1033 |
/// \param l is the initial value of \ref _length |
| 1034 | 1034 |
/// \param s is the initial value of \ref _source |
| 1035 | 1035 |
DijkstraWizardBase(const GR &g,const LM &l, Node s=INVALID) : |
| 1036 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 1037 |
_length(reinterpret_cast<void*>(const_cast<LM*>(&l))), |
|
| 1036 |
_g(reinterpret_cast<void*>(const_cast<GR*>(&g))), |
|
| 1037 |
_length(reinterpret_cast<void*>(const_cast<LM*>(&l))), |
|
| 1038 | 1038 |
_pred(0), _dist(0), _source(s) {}
|
| 1039 | 1039 |
|
| 1040 | 1040 |
}; |
| 1041 |
|
|
| 1041 |
|
|
| 1042 | 1042 |
/// A class to make the usage of Dijkstra algorithm easier |
| 1043 | 1043 |
|
| 1044 | 1044 |
/// This class is created to make it easier to use Dijkstra algorithm. |
| 1045 | 1045 |
/// It uses the functions and features of the plain \ref Dijkstra, |
| 1046 | 1046 |
/// but it is much simpler to use it. |
| 1047 | 1047 |
/// |
| 1048 | 1048 |
/// Simplicity means that the way to change the types defined |
| 1049 | 1049 |
/// in the traits class is based on functions that returns the new class |
| 1050 | 1050 |
/// and not on templatable built-in classes. |
| 1051 | 1051 |
/// When using the plain \ref Dijkstra |
| 1052 | 1052 |
/// the new class with the modified type comes from |
| 1053 | 1053 |
/// the original class by using the :: |
| 1054 | 1054 |
/// operator. In the case of \ref DijkstraWizard only |
| 1055 | 1055 |
/// a function have to be called and it will |
| 1056 | 1056 |
/// return the needed class. |
| 1057 | 1057 |
/// |
| 1058 | 1058 |
/// It does not have own \ref run method. When its \ref run method is called |
| 1059 |
/// it initiates a plain \ref Dijkstra class, and calls the \ref |
|
| 1059 |
/// it initiates a plain \ref Dijkstra class, and calls the \ref |
|
| 1060 | 1060 |
/// Dijkstra::run method of it. |
| 1061 | 1061 |
template<class TR> |
| 1062 | 1062 |
class DijkstraWizard : public TR |
| 1063 | 1063 |
{
|
| 1064 | 1064 |
typedef TR Base; |
| 1065 | 1065 |
|
| 1066 | 1066 |
///The type of the underlying digraph. |
| 1067 | 1067 |
typedef typename TR::Digraph Digraph; |
| 1068 | 1068 |
//\e |
| 1069 | 1069 |
typedef typename Digraph::Node Node; |
| 1070 | 1070 |
//\e |
| 1071 | 1071 |
typedef typename Digraph::NodeIt NodeIt; |
| 1072 | 1072 |
//\e |
| 1073 | 1073 |
typedef typename Digraph::Arc Arc; |
| 1074 | 1074 |
//\e |
| 1075 | 1075 |
typedef typename Digraph::OutArcIt OutArcIt; |
| 1076 |
|
|
| 1076 |
|
|
| 1077 | 1077 |
///The type of the map that stores the arc lengths. |
| 1078 | 1078 |
typedef typename TR::LengthMap LengthMap; |
| 1079 | 1079 |
///The type of the length of the arcs. |
| 1080 | 1080 |
typedef typename LengthMap::Value Value; |
| 1081 | 1081 |
///\brief The type of the map that stores the last |
| 1082 | 1082 |
///arcs of the shortest paths. |
| 1083 | 1083 |
typedef typename TR::PredMap PredMap; |
| 1084 | 1084 |
///The type of the map that stores the dists of the nodes. |
| 1085 | 1085 |
typedef typename TR::DistMap DistMap; |
| 1086 | 1086 |
///The heap type used by the dijkstra algorithm. |
| 1087 | 1087 |
typedef typename TR::Heap Heap; |
| 1088 | 1088 |
public: |
| 1089 | 1089 |
/// Constructor. |
| 1090 | 1090 |
DijkstraWizard() : TR() {}
|
| 1091 | 1091 |
|
| 1092 | 1092 |
/// Constructor that requires parameters. |
| 1093 | 1093 |
|
| 1094 | 1094 |
/// Constructor that requires parameters. |
| 1095 | 1095 |
/// These parameters will be the default values for the traits class. |
| 1096 | 1096 |
DijkstraWizard(const Digraph &g,const LengthMap &l, Node s=INVALID) : |
| 1097 | 1097 |
TR(g,l,s) {}
|
| 1098 | 1098 |
|
| 1099 | 1099 |
///Copy constructor |
| 1100 | 1100 |
DijkstraWizard(const TR &b) : TR(b) {}
|
| 1101 | 1101 |
|
| 1102 | 1102 |
~DijkstraWizard() {}
|
| 1103 | 1103 |
|
| 1104 | 1104 |
///Runs Dijkstra algorithm from a given node. |
| 1105 |
|
|
| 1105 |
|
|
| 1106 | 1106 |
///Runs Dijkstra algorithm from a given node. |
| 1107 | 1107 |
///The node can be given by the \ref source function. |
| 1108 | 1108 |
void run() |
| 1109 | 1109 |
{
|
| 1110 | 1110 |
if(Base::_source==INVALID) throw UninitializedParameter(); |
| 1111 |
Dijkstra<Digraph,LengthMap,TR> |
|
| 1112 |
dij(*reinterpret_cast<const Digraph*>(Base::_g), |
|
| 1111 |
Dijkstra<Digraph,LengthMap,TR> |
|
| 1112 |
dij(*reinterpret_cast<const Digraph*>(Base::_g), |
|
| 1113 | 1113 |
*reinterpret_cast<const LengthMap*>(Base::_length)); |
| 1114 | 1114 |
if(Base::_pred) dij.predMap(*reinterpret_cast<PredMap*>(Base::_pred)); |
| 1115 | 1115 |
if(Base::_dist) dij.distMap(*reinterpret_cast<DistMap*>(Base::_dist)); |
| 1116 | 1116 |
dij.run(Base::_source); |
| 1117 | 1117 |
} |
| 1118 | 1118 |
|
| 1119 | 1119 |
///Runs Dijkstra algorithm from the given node. |
| 1120 | 1120 |
|
| 1121 | 1121 |
///Runs Dijkstra algorithm from the given node. |
| 1122 | 1122 |
///\param s is the given source. |
| 1123 | 1123 |
void run(Node s) |
| 1124 | 1124 |
{
|
| 1125 | 1125 |
Base::_source=s; |
| 1126 | 1126 |
run(); |
| 1127 | 1127 |
} |
| 1128 | 1128 |
|
| 1129 | 1129 |
template<class T> |
| 1130 | 1130 |
struct DefPredMapBase : public Base {
|
| 1131 | 1131 |
typedef T PredMap; |
| 1132 | 1132 |
static PredMap *createPredMap(const Digraph &) { return 0; };
|
| 1133 | 1133 |
DefPredMapBase(const TR &b) : TR(b) {}
|
| 1134 | 1134 |
}; |
| 1135 |
|
|
| 1135 |
|
|
| 1136 | 1136 |
///\brief \ref named-templ-param "Named parameter" |
| 1137 | 1137 |
///function for setting PredMap type |
| 1138 | 1138 |
/// |
| 1139 | 1139 |
/// \ref named-templ-param "Named parameter" |
| 1140 | 1140 |
///function for setting PredMap type |
| 1141 | 1141 |
/// |
| 1142 | 1142 |
template<class T> |
| 1143 |
DijkstraWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 1143 |
DijkstraWizard<DefPredMapBase<T> > predMap(const T &t) |
|
| 1144 | 1144 |
{
|
| 1145 | 1145 |
Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1146 | 1146 |
return DijkstraWizard<DefPredMapBase<T> >(*this); |
| 1147 | 1147 |
} |
| 1148 |
|
|
| 1148 |
|
|
| 1149 | 1149 |
template<class T> |
| 1150 | 1150 |
struct DefDistMapBase : public Base {
|
| 1151 | 1151 |
typedef T DistMap; |
| 1152 | 1152 |
static DistMap *createDistMap(const Digraph &) { return 0; };
|
| 1153 | 1153 |
DefDistMapBase(const TR &b) : TR(b) {}
|
| 1154 | 1154 |
}; |
| 1155 |
|
|
| 1155 |
|
|
| 1156 | 1156 |
///\brief \ref named-templ-param "Named parameter" |
| 1157 | 1157 |
///function for setting DistMap type |
| 1158 | 1158 |
/// |
| 1159 | 1159 |
/// \ref named-templ-param "Named parameter" |
| 1160 | 1160 |
///function for setting DistMap type |
| 1161 | 1161 |
/// |
| 1162 | 1162 |
template<class T> |
| 1163 |
DijkstraWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1163 |
DijkstraWizard<DefDistMapBase<T> > distMap(const T &t) |
|
| 1164 | 1164 |
{
|
| 1165 | 1165 |
Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t)); |
| 1166 | 1166 |
return DijkstraWizard<DefDistMapBase<T> >(*this); |
| 1167 | 1167 |
} |
| 1168 |
|
|
| 1168 |
|
|
| 1169 | 1169 |
/// Sets the source node, from which the Dijkstra algorithm runs. |
| 1170 | 1170 |
|
| 1171 | 1171 |
/// Sets the source node, from which the Dijkstra algorithm runs. |
| 1172 | 1172 |
/// \param s is the source node. |
| 1173 |
DijkstraWizard<TR> &source(Node s) |
|
| 1173 |
DijkstraWizard<TR> &source(Node s) |
|
| 1174 | 1174 |
{
|
| 1175 | 1175 |
Base::_source=s; |
| 1176 | 1176 |
return *this; |
| 1177 | 1177 |
} |
| 1178 |
|
|
| 1178 |
|
|
| 1179 | 1179 |
}; |
| 1180 |
|
|
| 1180 |
|
|
| 1181 | 1181 |
///Function type interface for Dijkstra algorithm. |
| 1182 | 1182 |
|
| 1183 | 1183 |
/// \ingroup shortest_path |
| 1184 | 1184 |
///Function type interface for Dijkstra algorithm. |
| 1185 | 1185 |
/// |
| 1186 | 1186 |
///This function also has several |
| 1187 | 1187 |
///\ref named-templ-func-param "named parameters", |
| 1188 | 1188 |
///they are declared as the members of class \ref DijkstraWizard. |
| 1189 | 1189 |
///The following |
| 1190 | 1190 |
///example shows how to use these parameters. |
| 1191 | 1191 |
///\code |
| 1192 | 1192 |
/// dijkstra(g,length,source).predMap(preds).run(); |
| 1193 | 1193 |
///\endcode |
| 1194 | 1194 |
///\warning Don't forget to put the \ref DijkstraWizard::run() "run()" |
| 1195 | 1195 |
///to the end of the parameter list. |
| 1196 | 1196 |
///\sa DijkstraWizard |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_DIM2_H |
| 20 | 20 |
#define LEMON_DIM2_H |
| 21 | 21 |
|
| 22 | 22 |
#include <iostream> |
| 23 | 23 |
#include <lemon/bits/utility.h> |
| 24 | 24 |
|
| 25 | 25 |
///\ingroup misc |
| 26 | 26 |
///\file |
| 27 |
///\brief A simple two dimensional vector and a bounding box implementation |
|
| 27 |
///\brief A simple two dimensional vector and a bounding box implementation |
|
| 28 | 28 |
/// |
| 29 | 29 |
/// The class \ref lemon::dim2::Point "dim2::Point" implements |
| 30 | 30 |
/// a two dimensional vector with the usual operations. |
| 31 | 31 |
/// |
| 32 | 32 |
/// The class \ref lemon::dim2::BoundingBox "dim2::BoundingBox" |
| 33 | 33 |
/// can be used to determine |
| 34 | 34 |
/// the rectangular bounding box of a set of |
| 35 | 35 |
/// \ref lemon::dim2::Point "dim2::Point"'s. |
| 36 | 36 |
|
| 37 | 37 |
namespace lemon {
|
| 38 | 38 |
|
| 39 | 39 |
///Tools for handling two dimensional coordinates |
| 40 | 40 |
|
| 41 | 41 |
///This namespace is a storage of several |
| 42 | 42 |
///tools for handling two dimensional coordinates |
| 43 | 43 |
namespace dim2 {
|
| ... | ... |
@@ -46,99 +46,99 @@ |
| 46 | 46 |
/// @{
|
| 47 | 47 |
|
| 48 | 48 |
/// A simple two dimensional vector (plainvector) implementation |
| 49 | 49 |
|
| 50 | 50 |
/// A simple two dimensional vector (plainvector) implementation |
| 51 | 51 |
/// with the usual vector operations. |
| 52 | 52 |
template<typename T> |
| 53 | 53 |
class Point {
|
| 54 | 54 |
|
| 55 | 55 |
public: |
| 56 | 56 |
|
| 57 | 57 |
typedef T Value; |
| 58 | 58 |
|
| 59 | 59 |
///First coordinate |
| 60 | 60 |
T x; |
| 61 | 61 |
///Second coordinate |
| 62 |
T y; |
|
| 63 |
|
|
| 62 |
T y; |
|
| 63 |
|
|
| 64 | 64 |
///Default constructor |
| 65 | 65 |
Point() {}
|
| 66 | 66 |
|
| 67 | 67 |
///Construct an instance from coordinates |
| 68 | 68 |
Point(T a, T b) : x(a), y(b) { }
|
| 69 | 69 |
|
| 70 | 70 |
///Returns the dimension of the vector (i.e. returns 2). |
| 71 | 71 |
|
| 72 | 72 |
///The dimension of the vector. |
| 73 |
///This function always returns 2. |
|
| 73 |
///This function always returns 2. |
|
| 74 | 74 |
int size() const { return 2; }
|
| 75 | 75 |
|
| 76 | 76 |
///Subscripting operator |
| 77 | 77 |
|
| 78 | 78 |
///\c p[0] is \c p.x and \c p[1] is \c p.y |
| 79 | 79 |
/// |
| 80 | 80 |
T& operator[](int idx) { return idx == 0 ? x : y; }
|
| 81 | 81 |
|
| 82 | 82 |
///Const subscripting operator |
| 83 | 83 |
|
| 84 | 84 |
///\c p[0] is \c p.x and \c p[1] is \c p.y |
| 85 | 85 |
/// |
| 86 | 86 |
const T& operator[](int idx) const { return idx == 0 ? x : y; }
|
| 87 | 87 |
|
| 88 | 88 |
///Conversion constructor |
| 89 | 89 |
template<class TT> Point(const Point<TT> &p) : x(p.x), y(p.y) {}
|
| 90 | 90 |
|
| 91 | 91 |
///Give back the square of the norm of the vector |
| 92 | 92 |
T normSquare() const {
|
| 93 | 93 |
return x*x+y*y; |
| 94 | 94 |
} |
| 95 |
|
|
| 95 |
|
|
| 96 | 96 |
///Increment the left hand side by \c u |
| 97 | 97 |
Point<T>& operator +=(const Point<T>& u) {
|
| 98 | 98 |
x += u.x; |
| 99 | 99 |
y += u.y; |
| 100 | 100 |
return *this; |
| 101 | 101 |
} |
| 102 |
|
|
| 102 |
|
|
| 103 | 103 |
///Decrement the left hand side by \c u |
| 104 | 104 |
Point<T>& operator -=(const Point<T>& u) {
|
| 105 | 105 |
x -= u.x; |
| 106 | 106 |
y -= u.y; |
| 107 | 107 |
return *this; |
| 108 | 108 |
} |
| 109 | 109 |
|
| 110 | 110 |
///Multiply the left hand side with a scalar |
| 111 | 111 |
Point<T>& operator *=(const T &u) {
|
| 112 | 112 |
x *= u; |
| 113 | 113 |
y *= u; |
| 114 | 114 |
return *this; |
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 | 117 |
///Divide the left hand side by a scalar |
| 118 | 118 |
Point<T>& operator /=(const T &u) {
|
| 119 | 119 |
x /= u; |
| 120 | 120 |
y /= u; |
| 121 | 121 |
return *this; |
| 122 | 122 |
} |
| 123 |
|
|
| 123 |
|
|
| 124 | 124 |
///Return the scalar product of two vectors |
| 125 | 125 |
T operator *(const Point<T>& u) const {
|
| 126 | 126 |
return x*u.x+y*u.y; |
| 127 | 127 |
} |
| 128 |
|
|
| 128 |
|
|
| 129 | 129 |
///Return the sum of two vectors |
| 130 | 130 |
Point<T> operator+(const Point<T> &u) const {
|
| 131 | 131 |
Point<T> b=*this; |
| 132 | 132 |
return b+=u; |
| 133 | 133 |
} |
| 134 | 134 |
|
| 135 | 135 |
///Return the negative of the vector |
| 136 | 136 |
Point<T> operator-() const {
|
| 137 | 137 |
Point<T> b=*this; |
| 138 | 138 |
b.x=-b.x; b.y=-b.y; |
| 139 | 139 |
return b; |
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 | 142 |
///Return the difference of two vectors |
| 143 | 143 |
Point<T> operator-(const Point<T> &u) const {
|
| 144 | 144 |
Point<T> b=*this; |
| ... | ... |
@@ -156,33 +156,33 @@ |
| 156 | 156 |
Point<T> b=*this; |
| 157 | 157 |
return b/=u; |
| 158 | 158 |
} |
| 159 | 159 |
|
| 160 | 160 |
///Test equality |
| 161 | 161 |
bool operator==(const Point<T> &u) const {
|
| 162 | 162 |
return (x==u.x) && (y==u.y); |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 | 165 |
///Test inequality |
| 166 | 166 |
bool operator!=(Point u) const {
|
| 167 | 167 |
return (x!=u.x) || (y!=u.y); |
| 168 | 168 |
} |
| 169 | 169 |
|
| 170 | 170 |
}; |
| 171 | 171 |
|
| 172 |
///Return a Point |
|
| 172 |
///Return a Point |
|
| 173 | 173 |
|
| 174 | 174 |
///Return a Point. |
| 175 | 175 |
///\relates Point |
| 176 | 176 |
template <typename T> |
| 177 | 177 |
inline Point<T> makePoint(const T& x, const T& y) {
|
| 178 | 178 |
return Point<T>(x, y); |
| 179 | 179 |
} |
| 180 | 180 |
|
| 181 | 181 |
///Return a vector multiplied by a scalar |
| 182 | 182 |
|
| 183 | 183 |
///Return a vector multiplied by a scalar. |
| 184 | 184 |
///\relates Point |
| 185 | 185 |
template<typename T> Point<T> operator*(const T &u,const Point<T> &x) {
|
| 186 | 186 |
return x*u; |
| 187 | 187 |
} |
| 188 | 188 |
|
| ... | ... |
@@ -246,461 +246,461 @@ |
| 246 | 246 |
inline Point<T> rot180(const Point<T> &z) |
| 247 | 247 |
{
|
| 248 | 248 |
return Point<T>(-z.x,-z.y); |
| 249 | 249 |
} |
| 250 | 250 |
|
| 251 | 251 |
///Rotate by 270 degrees |
| 252 | 252 |
|
| 253 | 253 |
///Returns the parameter rotated by 90 degrees in negative direction. |
| 254 | 254 |
///\relates Point |
| 255 | 255 |
/// |
| 256 | 256 |
template<typename T> |
| 257 | 257 |
inline Point<T> rot270(const Point<T> &z) |
| 258 | 258 |
{
|
| 259 | 259 |
return Point<T>(z.y,-z.x); |
| 260 | 260 |
} |
| 261 | 261 |
|
| 262 |
|
|
| 262 |
|
|
| 263 | 263 |
|
| 264 | 264 |
/// A class to calculate or store the bounding box of plainvectors. |
| 265 | 265 |
|
| 266 | 266 |
/// A class to calculate or store the bounding box of plainvectors. |
| 267 | 267 |
/// |
| 268 | 268 |
template<typename T> |
| 269 | 269 |
class BoundingBox {
|
| 270 | 270 |
Point<T> bottom_left, top_right; |
| 271 | 271 |
bool _empty; |
| 272 | 272 |
public: |
| 273 |
|
|
| 273 |
|
|
| 274 | 274 |
///Default constructor: creates an empty bounding box |
| 275 | 275 |
BoundingBox() { _empty = true; }
|
| 276 | 276 |
|
| 277 | 277 |
///Construct an instance from one point |
| 278 | 278 |
BoundingBox(Point<T> a) { bottom_left=top_right=a; _empty = false; }
|
| 279 |
|
|
| 279 |
|
|
| 280 | 280 |
///Construct an instance from two points |
| 281 |
|
|
| 281 |
|
|
| 282 | 282 |
///Construct an instance from two points. |
| 283 | 283 |
///\param a The bottom left corner. |
| 284 | 284 |
///\param b The top right corner. |
| 285 | 285 |
///\warning The coordinates of the bottom left corner must be no more |
| 286 | 286 |
///than those of the top right one. |
| 287 | 287 |
BoundingBox(Point<T> a,Point<T> b) |
| 288 | 288 |
{
|
| 289 |
bottom_left=a; |
|
| 290 |
top_right=b; |
|
| 291 |
|
|
| 289 |
bottom_left=a; |
|
| 290 |
top_right=b; |
|
| 291 |
_empty = false; |
|
| 292 | 292 |
} |
| 293 |
|
|
| 293 |
|
|
| 294 | 294 |
///Construct an instance from four numbers |
| 295 | 295 |
|
| 296 | 296 |
///Construct an instance from four numbers. |
| 297 | 297 |
///\param l The left side of the box. |
| 298 | 298 |
///\param b The bottom of the box. |
| 299 | 299 |
///\param r The right side of the box. |
| 300 | 300 |
///\param t The top of the box. |
| 301 | 301 |
///\warning The left side must be no more than the right side and |
| 302 |
///bottom must be no more than the top. |
|
| 302 |
///bottom must be no more than the top. |
|
| 303 | 303 |
BoundingBox(T l,T b,T r,T t) |
| 304 | 304 |
{
|
| 305 |
bottom_left=Point<T>(l,b); |
|
| 306 |
top_right=Point<T>(r,t); |
|
| 307 |
|
|
| 305 |
bottom_left=Point<T>(l,b); |
|
| 306 |
top_right=Point<T>(r,t); |
|
| 307 |
_empty = false; |
|
| 308 | 308 |
} |
| 309 |
|
|
| 309 |
|
|
| 310 | 310 |
///Return \c true if the bounding box is empty. |
| 311 |
|
|
| 311 |
|
|
| 312 | 312 |
///Return \c true if the bounding box is empty (i.e. return \c false |
| 313 | 313 |
///if at least one point was added to the box or the coordinates of |
| 314 | 314 |
///the box were set). |
| 315 | 315 |
/// |
| 316 |
///The coordinates of an empty bounding box are not defined. |
|
| 316 |
///The coordinates of an empty bounding box are not defined. |
|
| 317 | 317 |
bool empty() const {
|
| 318 | 318 |
return _empty; |
| 319 | 319 |
} |
| 320 |
|
|
| 320 |
|
|
| 321 | 321 |
///Make the BoundingBox empty |
| 322 | 322 |
void clear() {
|
| 323 | 323 |
_empty=1; |
| 324 | 324 |
} |
| 325 | 325 |
|
| 326 | 326 |
///Give back the bottom left corner of the box |
| 327 | 327 |
|
| 328 | 328 |
///Give back the bottom left corner of the box. |
| 329 | 329 |
///If the bounding box is empty, then the return value is not defined. |
| 330 | 330 |
Point<T> bottomLeft() const {
|
| 331 | 331 |
return bottom_left; |
| 332 | 332 |
} |
| 333 | 333 |
|
| 334 | 334 |
///Set the bottom left corner of the box |
| 335 | 335 |
|
| 336 | 336 |
///Set the bottom left corner of the box. |
| 337 | 337 |
///It should only be used for non-empty box. |
| 338 | 338 |
void bottomLeft(Point<T> p) {
|
| 339 |
|
|
| 339 |
bottom_left = p; |
|
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
///Give back the top right corner of the box |
| 343 | 343 |
|
| 344 | 344 |
///Give back the top right corner of the box. |
| 345 | 345 |
///If the bounding box is empty, then the return value is not defined. |
| 346 | 346 |
Point<T> topRight() const {
|
| 347 | 347 |
return top_right; |
| 348 | 348 |
} |
| 349 | 349 |
|
| 350 | 350 |
///Set the top right corner of the box |
| 351 | 351 |
|
| 352 | 352 |
///Set the top right corner of the box. |
| 353 | 353 |
///It should only be used for non-empty box. |
| 354 | 354 |
void topRight(Point<T> p) {
|
| 355 |
|
|
| 355 |
top_right = p; |
|
| 356 | 356 |
} |
| 357 | 357 |
|
| 358 | 358 |
///Give back the bottom right corner of the box |
| 359 | 359 |
|
| 360 | 360 |
///Give back the bottom right corner of the box. |
| 361 | 361 |
///If the bounding box is empty, then the return value is not defined. |
| 362 | 362 |
Point<T> bottomRight() const {
|
| 363 | 363 |
return Point<T>(top_right.x,bottom_left.y); |
| 364 | 364 |
} |
| 365 | 365 |
|
| 366 | 366 |
///Set the bottom right corner of the box |
| 367 | 367 |
|
| 368 | 368 |
///Set the bottom right corner of the box. |
| 369 | 369 |
///It should only be used for non-empty box. |
| 370 | 370 |
void bottomRight(Point<T> p) {
|
| 371 |
top_right.x = p.x; |
|
| 372 |
bottom_left.y = p.y; |
|
| 371 |
top_right.x = p.x; |
|
| 372 |
bottom_left.y = p.y; |
|
| 373 | 373 |
} |
| 374 |
|
|
| 374 |
|
|
| 375 | 375 |
///Give back the top left corner of the box |
| 376 | 376 |
|
| 377 | 377 |
///Give back the top left corner of the box. |
| 378 | 378 |
///If the bounding box is empty, then the return value is not defined. |
| 379 | 379 |
Point<T> topLeft() const {
|
| 380 | 380 |
return Point<T>(bottom_left.x,top_right.y); |
| 381 | 381 |
} |
| 382 | 382 |
|
| 383 | 383 |
///Set the top left corner of the box |
| 384 | 384 |
|
| 385 | 385 |
///Set the top left corner of the box. |
| 386 | 386 |
///It should only be used for non-empty box. |
| 387 | 387 |
void topLeft(Point<T> p) {
|
| 388 |
top_right.y = p.y; |
|
| 389 |
bottom_left.x = p.x; |
|
| 388 |
top_right.y = p.y; |
|
| 389 |
bottom_left.x = p.x; |
|
| 390 | 390 |
} |
| 391 | 391 |
|
| 392 | 392 |
///Give back the bottom of the box |
| 393 | 393 |
|
| 394 | 394 |
///Give back the bottom of the box. |
| 395 | 395 |
///If the bounding box is empty, then the return value is not defined. |
| 396 | 396 |
T bottom() const {
|
| 397 | 397 |
return bottom_left.y; |
| 398 | 398 |
} |
| 399 | 399 |
|
| 400 | 400 |
///Set the bottom of the box |
| 401 | 401 |
|
| 402 | 402 |
///Set the bottom of the box. |
| 403 | 403 |
///It should only be used for non-empty box. |
| 404 | 404 |
void bottom(T t) {
|
| 405 |
|
|
| 405 |
bottom_left.y = t; |
|
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 | 408 |
///Give back the top of the box |
| 409 | 409 |
|
| 410 | 410 |
///Give back the top of the box. |
| 411 | 411 |
///If the bounding box is empty, then the return value is not defined. |
| 412 | 412 |
T top() const {
|
| 413 | 413 |
return top_right.y; |
| 414 | 414 |
} |
| 415 | 415 |
|
| 416 | 416 |
///Set the top of the box |
| 417 | 417 |
|
| 418 | 418 |
///Set the top of the box. |
| 419 | 419 |
///It should only be used for non-empty box. |
| 420 | 420 |
void top(T t) {
|
| 421 |
|
|
| 421 |
top_right.y = t; |
|
| 422 | 422 |
} |
| 423 | 423 |
|
| 424 | 424 |
///Give back the left side of the box |
| 425 | 425 |
|
| 426 | 426 |
///Give back the left side of the box. |
| 427 | 427 |
///If the bounding box is empty, then the return value is not defined. |
| 428 | 428 |
T left() const {
|
| 429 | 429 |
return bottom_left.x; |
| 430 | 430 |
} |
| 431 |
|
|
| 431 |
|
|
| 432 | 432 |
///Set the left side of the box |
| 433 | 433 |
|
| 434 | 434 |
///Set the left side of the box. |
| 435 | 435 |
///It should only be used for non-empty box. |
| 436 | 436 |
void left(T t) {
|
| 437 |
|
|
| 437 |
bottom_left.x = t; |
|
| 438 | 438 |
} |
| 439 | 439 |
|
| 440 | 440 |
/// Give back the right side of the box |
| 441 | 441 |
|
| 442 | 442 |
/// Give back the right side of the box. |
| 443 | 443 |
///If the bounding box is empty, then the return value is not defined. |
| 444 | 444 |
T right() const {
|
| 445 | 445 |
return top_right.x; |
| 446 | 446 |
} |
| 447 | 447 |
|
| 448 | 448 |
///Set the right side of the box |
| 449 | 449 |
|
| 450 | 450 |
///Set the right side of the box. |
| 451 | 451 |
///It should only be used for non-empty box. |
| 452 | 452 |
void right(T t) {
|
| 453 |
|
|
| 453 |
top_right.x = t; |
|
| 454 | 454 |
} |
| 455 | 455 |
|
| 456 | 456 |
///Give back the height of the box |
| 457 | 457 |
|
| 458 | 458 |
///Give back the height of the box. |
| 459 | 459 |
///If the bounding box is empty, then the return value is not defined. |
| 460 | 460 |
T height() const {
|
| 461 | 461 |
return top_right.y-bottom_left.y; |
| 462 | 462 |
} |
| 463 | 463 |
|
| 464 | 464 |
///Give back the width of the box |
| 465 | 465 |
|
| 466 | 466 |
///Give back the width of the box. |
| 467 | 467 |
///If the bounding box is empty, then the return value is not defined. |
| 468 | 468 |
T width() const {
|
| 469 | 469 |
return top_right.x-bottom_left.x; |
| 470 | 470 |
} |
| 471 | 471 |
|
| 472 | 472 |
///Checks whether a point is inside a bounding box |
| 473 | 473 |
bool inside(const Point<T>& u) const {
|
| 474 | 474 |
if (_empty) |
| 475 | 475 |
return false; |
| 476 | 476 |
else{
|
| 477 | 477 |
return ((u.x-bottom_left.x)*(top_right.x-u.x) >= 0 && |
| 478 | 478 |
(u.y-bottom_left.y)*(top_right.y-u.y) >= 0 ); |
| 479 | 479 |
} |
| 480 | 480 |
} |
| 481 |
|
|
| 481 |
|
|
| 482 | 482 |
///Increments a bounding box with a point |
| 483 | 483 |
|
| 484 | 484 |
///Increments a bounding box with a point. |
| 485 | 485 |
/// |
| 486 | 486 |
BoundingBox& add(const Point<T>& u){
|
| 487 | 487 |
if (_empty){
|
| 488 | 488 |
bottom_left=top_right=u; |
| 489 | 489 |
_empty = false; |
| 490 | 490 |
} |
| 491 | 491 |
else{
|
| 492 | 492 |
if (bottom_left.x > u.x) bottom_left.x = u.x; |
| 493 | 493 |
if (bottom_left.y > u.y) bottom_left.y = u.y; |
| 494 | 494 |
if (top_right.x < u.x) top_right.x = u.x; |
| 495 | 495 |
if (top_right.y < u.y) top_right.y = u.y; |
| 496 | 496 |
} |
| 497 | 497 |
return *this; |
| 498 | 498 |
} |
| 499 |
|
|
| 499 |
|
|
| 500 | 500 |
///Increments a bounding box to contain another bounding box |
| 501 |
|
|
| 501 |
|
|
| 502 | 502 |
///Increments a bounding box to contain another bounding box. |
| 503 | 503 |
/// |
| 504 | 504 |
BoundingBox& add(const BoundingBox &u){
|
| 505 | 505 |
if ( !u.empty() ){
|
| 506 | 506 |
this->add(u.bottomLeft()); |
| 507 |
|
|
| 507 |
this->add(u.topRight()); |
|
| 508 | 508 |
} |
| 509 | 509 |
return *this; |
| 510 | 510 |
} |
| 511 |
|
|
| 511 |
|
|
| 512 | 512 |
///Intersection of two bounding boxes |
| 513 | 513 |
|
| 514 | 514 |
///Intersection of two bounding boxes. |
| 515 | 515 |
/// |
| 516 | 516 |
BoundingBox operator&(const BoundingBox& u) const {
|
| 517 | 517 |
BoundingBox b; |
| 518 | 518 |
if (this->_empty || u._empty) {
|
| 519 |
b._empty = true; |
|
| 520 |
} else {
|
|
| 521 |
b.bottom_left.x = std::max(this->bottom_left.x,u.bottom_left.x); |
|
| 522 |
b.bottom_left.y = std::max(this->bottom_left.y,u.bottom_left.y); |
|
| 523 |
b.top_right.x = std::min(this->top_right.x,u.top_right.x); |
|
| 524 |
b.top_right.y = std::min(this->top_right.y,u.top_right.y); |
|
| 525 |
b._empty = b.bottom_left.x > b.top_right.x || |
|
| 526 |
b.bottom_left.y > b.top_right.y; |
|
| 527 |
|
|
| 519 |
b._empty = true; |
|
| 520 |
} else {
|
|
| 521 |
b.bottom_left.x = std::max(this->bottom_left.x,u.bottom_left.x); |
|
| 522 |
b.bottom_left.y = std::max(this->bottom_left.y,u.bottom_left.y); |
|
| 523 |
b.top_right.x = std::min(this->top_right.x,u.top_right.x); |
|
| 524 |
b.top_right.y = std::min(this->top_right.y,u.top_right.y); |
|
| 525 |
b._empty = b.bottom_left.x > b.top_right.x || |
|
| 526 |
b.bottom_left.y > b.top_right.y; |
|
| 527 |
} |
|
| 528 | 528 |
return b; |
| 529 | 529 |
} |
| 530 | 530 |
|
| 531 | 531 |
};//class Boundingbox |
| 532 | 532 |
|
| 533 | 533 |
|
| 534 | 534 |
///Map of x-coordinates of a \ref Point "Point"-map |
| 535 | 535 |
|
| 536 | 536 |
///\ingroup maps |
| 537 | 537 |
///Map of x-coordinates of a \ref Point "Point"-map. |
| 538 | 538 |
/// |
| 539 | 539 |
template<class M> |
| 540 |
class XMap |
|
| 540 |
class XMap |
|
| 541 | 541 |
{
|
| 542 | 542 |
M& _map; |
| 543 | 543 |
public: |
| 544 | 544 |
|
| 545 | 545 |
typedef typename M::Value::Value Value; |
| 546 | 546 |
typedef typename M::Key Key; |
| 547 | 547 |
///\e |
| 548 | 548 |
XMap(M& map) : _map(map) {}
|
| 549 | 549 |
Value operator[](Key k) const {return _map[k].x;}
|
| 550 | 550 |
void set(Key k,Value v) {_map.set(k,typename M::Value(v,_map[k].y));}
|
| 551 | 551 |
}; |
| 552 |
|
|
| 552 |
|
|
| 553 | 553 |
///Returns an \ref XMap class |
| 554 | 554 |
|
| 555 | 555 |
///This function just returns an \ref XMap class. |
| 556 | 556 |
/// |
| 557 | 557 |
///\ingroup maps |
| 558 | 558 |
///\relates XMap |
| 559 |
template<class M> |
|
| 560 |
inline XMap<M> xMap(M &m) |
|
| 559 |
template<class M> |
|
| 560 |
inline XMap<M> xMap(M &m) |
|
| 561 | 561 |
{
|
| 562 | 562 |
return XMap<M>(m); |
| 563 | 563 |
} |
| 564 | 564 |
|
| 565 |
template<class M> |
|
| 566 |
inline XMap<M> xMap(const M &m) |
|
| 565 |
template<class M> |
|
| 566 |
inline XMap<M> xMap(const M &m) |
|
| 567 | 567 |
{
|
| 568 | 568 |
return XMap<M>(m); |
| 569 | 569 |
} |
| 570 | 570 |
|
| 571 | 571 |
///Constant (read only) version of \ref XMap |
| 572 | 572 |
|
| 573 | 573 |
///\ingroup maps |
| 574 | 574 |
///Constant (read only) version of \ref XMap |
| 575 | 575 |
/// |
| 576 | 576 |
template<class M> |
| 577 |
class ConstXMap |
|
| 577 |
class ConstXMap |
|
| 578 | 578 |
{
|
| 579 | 579 |
const M& _map; |
| 580 | 580 |
public: |
| 581 | 581 |
|
| 582 | 582 |
typedef typename M::Value::Value Value; |
| 583 | 583 |
typedef typename M::Key Key; |
| 584 | 584 |
///\e |
| 585 | 585 |
ConstXMap(const M &map) : _map(map) {}
|
| 586 | 586 |
Value operator[](Key k) const {return _map[k].x;}
|
| 587 | 587 |
}; |
| 588 |
|
|
| 588 |
|
|
| 589 | 589 |
///Returns a \ref ConstXMap class |
| 590 | 590 |
|
| 591 | 591 |
///This function just returns a \ref ConstXMap class. |
| 592 | 592 |
/// |
| 593 | 593 |
///\ingroup maps |
| 594 | 594 |
///\relates ConstXMap |
| 595 |
template<class M> |
|
| 596 |
inline ConstXMap<M> xMap(const M &m) |
|
| 595 |
template<class M> |
|
| 596 |
inline ConstXMap<M> xMap(const M &m) |
|
| 597 | 597 |
{
|
| 598 | 598 |
return ConstXMap<M>(m); |
| 599 | 599 |
} |
| 600 | 600 |
|
| 601 | 601 |
///Map of y-coordinates of a \ref Point "Point"-map |
| 602 |
|
|
| 602 |
|
|
| 603 | 603 |
///\ingroup maps |
| 604 | 604 |
///Map of y-coordinates of a \ref Point "Point"-map. |
| 605 | 605 |
/// |
| 606 | 606 |
template<class M> |
| 607 |
class YMap |
|
| 607 |
class YMap |
|
| 608 | 608 |
{
|
| 609 | 609 |
M& _map; |
| 610 | 610 |
public: |
| 611 | 611 |
|
| 612 | 612 |
typedef typename M::Value::Value Value; |
| 613 | 613 |
typedef typename M::Key Key; |
| 614 | 614 |
///\e |
| 615 | 615 |
YMap(M& map) : _map(map) {}
|
| 616 | 616 |
Value operator[](Key k) const {return _map[k].y;}
|
| 617 | 617 |
void set(Key k,Value v) {_map.set(k,typename M::Value(_map[k].x,v));}
|
| 618 | 618 |
}; |
| 619 | 619 |
|
| 620 | 620 |
///Returns a \ref YMap class |
| 621 | 621 |
|
| 622 | 622 |
///This function just returns a \ref YMap class. |
| 623 | 623 |
/// |
| 624 | 624 |
///\ingroup maps |
| 625 | 625 |
///\relates YMap |
| 626 |
template<class M> |
|
| 627 |
inline YMap<M> yMap(M &m) |
|
| 626 |
template<class M> |
|
| 627 |
inline YMap<M> yMap(M &m) |
|
| 628 | 628 |
{
|
| 629 | 629 |
return YMap<M>(m); |
| 630 | 630 |
} |
| 631 | 631 |
|
| 632 |
template<class M> |
|
| 633 |
inline YMap<M> yMap(const M &m) |
|
| 632 |
template<class M> |
|
| 633 |
inline YMap<M> yMap(const M &m) |
|
| 634 | 634 |
{
|
| 635 | 635 |
return YMap<M>(m); |
| 636 | 636 |
} |
| 637 | 637 |
|
| 638 | 638 |
///Constant (read only) version of \ref YMap |
| 639 | 639 |
|
| 640 | 640 |
///\ingroup maps |
| 641 | 641 |
///Constant (read only) version of \ref YMap |
| 642 | 642 |
/// |
| 643 | 643 |
template<class M> |
| 644 |
class ConstYMap |
|
| 644 |
class ConstYMap |
|
| 645 | 645 |
{
|
| 646 | 646 |
const M& _map; |
| 647 | 647 |
public: |
| 648 | 648 |
|
| 649 | 649 |
typedef typename M::Value::Value Value; |
| 650 | 650 |
typedef typename M::Key Key; |
| 651 | 651 |
///\e |
| 652 | 652 |
ConstYMap(const M &map) : _map(map) {}
|
| 653 | 653 |
Value operator[](Key k) const {return _map[k].y;}
|
| 654 | 654 |
}; |
| 655 |
|
|
| 655 |
|
|
| 656 | 656 |
///Returns a \ref ConstYMap class |
| 657 | 657 |
|
| 658 | 658 |
///This function just returns a \ref ConstYMap class. |
| 659 | 659 |
/// |
| 660 | 660 |
///\ingroup maps |
| 661 | 661 |
///\relates ConstYMap |
| 662 |
template<class M> |
|
| 663 |
inline ConstYMap<M> yMap(const M &m) |
|
| 662 |
template<class M> |
|
| 663 |
inline ConstYMap<M> yMap(const M &m) |
|
| 664 | 664 |
{
|
| 665 | 665 |
return ConstYMap<M>(m); |
| 666 | 666 |
} |
| 667 | 667 |
|
| 668 | 668 |
|
| 669 | 669 |
///\brief Map of the \ref Point::normSquare() "normSquare()" |
| 670 | 670 |
///of a \ref Point "Point"-map |
| 671 | 671 |
/// |
| 672 | 672 |
///Map of the \ref Point::normSquare() "normSquare()" |
| 673 | 673 |
///of a \ref Point "Point"-map. |
| 674 | 674 |
///\ingroup maps |
| 675 | 675 |
template<class M> |
| 676 |
class NormSquareMap |
|
| 676 |
class NormSquareMap |
|
| 677 | 677 |
{
|
| 678 | 678 |
const M& _map; |
| 679 | 679 |
public: |
| 680 | 680 |
|
| 681 | 681 |
typedef typename M::Value::Value Value; |
| 682 | 682 |
typedef typename M::Key Key; |
| 683 | 683 |
///\e |
| 684 | 684 |
NormSquareMap(const M &map) : _map(map) {}
|
| 685 | 685 |
Value operator[](Key k) const {return _map[k].normSquare();}
|
| 686 | 686 |
}; |
| 687 |
|
|
| 687 |
|
|
| 688 | 688 |
///Returns a \ref NormSquareMap class |
| 689 | 689 |
|
| 690 | 690 |
///This function just returns a \ref NormSquareMap class. |
| 691 | 691 |
/// |
| 692 | 692 |
///\ingroup maps |
| 693 | 693 |
///\relates NormSquareMap |
| 694 |
template<class M> |
|
| 695 |
inline NormSquareMap<M> normSquareMap(const M &m) |
|
| 694 |
template<class M> |
|
| 695 |
inline NormSquareMap<M> normSquareMap(const M &m) |
|
| 696 | 696 |
{
|
| 697 | 697 |
return NormSquareMap<M>(m); |
| 698 | 698 |
} |
| 699 | 699 |
|
| 700 | 700 |
/// @} |
| 701 | 701 |
|
| 702 | 702 |
} //namespce dim2 |
| 703 |
|
|
| 703 |
|
|
| 704 | 704 |
} //namespace lemon |
| 705 | 705 |
|
| 706 | 706 |
#endif //LEMON_DIM2_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_ERROR_H |
| ... | ... |
@@ -32,144 +32,144 @@ |
| 32 | 32 |
|
| 33 | 33 |
namespace lemon {
|
| 34 | 34 |
|
| 35 | 35 |
/// \addtogroup exceptions |
| 36 | 36 |
/// @{
|
| 37 | 37 |
|
| 38 | 38 |
/// \brief Exception safe wrapper class. |
| 39 | 39 |
/// |
| 40 | 40 |
/// Exception safe wrapper class to implement the members of exceptions. |
| 41 | 41 |
template <typename _Type> |
| 42 | 42 |
class ExceptionMember {
|
| 43 | 43 |
public: |
| 44 | 44 |
typedef _Type Type; |
| 45 | 45 |
|
| 46 | 46 |
ExceptionMember() throw() {
|
| 47 | 47 |
try {
|
| 48 |
|
|
| 48 |
ptr.reset(new Type()); |
|
| 49 | 49 |
} catch (...) {}
|
| 50 | 50 |
} |
| 51 | 51 |
|
| 52 | 52 |
ExceptionMember(const Type& type) throw() {
|
| 53 | 53 |
try {
|
| 54 |
ptr.reset(new Type()); |
|
| 55 |
if (ptr.get() == 0) return; |
|
| 56 |
|
|
| 54 |
ptr.reset(new Type()); |
|
| 55 |
if (ptr.get() == 0) return; |
|
| 56 |
*ptr = type; |
|
| 57 | 57 |
} catch (...) {}
|
| 58 | 58 |
} |
| 59 | 59 |
|
| 60 | 60 |
ExceptionMember(const ExceptionMember& copy) throw() {
|
| 61 | 61 |
try {
|
| 62 |
if (!copy.valid()) return; |
|
| 63 |
ptr.reset(new Type()); |
|
| 64 |
if (ptr.get() == 0) return; |
|
| 65 |
*ptr = copy.get(); |
|
| 62 |
if (!copy.valid()) return; |
|
| 63 |
ptr.reset(new Type()); |
|
| 64 |
if (ptr.get() == 0) return; |
|
| 65 |
*ptr = copy.get(); |
|
| 66 | 66 |
} catch (...) {}
|
| 67 | 67 |
} |
| 68 | 68 |
|
| 69 | 69 |
ExceptionMember& operator=(const ExceptionMember& copy) throw() {
|
| 70 | 70 |
if (ptr.get() == 0) return; |
| 71 | 71 |
try {
|
| 72 |
if (!copy.valid()) return; |
|
| 73 |
*ptr = copy.get(); |
|
| 72 |
if (!copy.valid()) return; |
|
| 73 |
*ptr = copy.get(); |
|
| 74 | 74 |
} catch (...) {}
|
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 | 77 |
void set(const Type& type) throw() {
|
| 78 | 78 |
if (ptr.get() == 0) return; |
| 79 | 79 |
try {
|
| 80 |
|
|
| 80 |
*ptr = type; |
|
| 81 | 81 |
} catch (...) {}
|
| 82 | 82 |
} |
| 83 | 83 |
|
| 84 | 84 |
const Type& get() const {
|
| 85 | 85 |
return *ptr; |
| 86 | 86 |
} |
| 87 | 87 |
|
| 88 | 88 |
bool valid() const throw() {
|
| 89 | 89 |
return ptr.get() != 0; |
| 90 | 90 |
} |
| 91 | 91 |
|
| 92 | 92 |
private: |
| 93 | 93 |
std::auto_ptr<_Type> ptr; |
| 94 | 94 |
}; |
| 95 | 95 |
|
| 96 | 96 |
/// Exception-safe convenient error message builder class. |
| 97 | 97 |
|
| 98 | 98 |
/// Helper class which provides a convenient ostream-like (operator << |
| 99 | 99 |
/// based) interface to create a string message. Mostly useful in |
| 100 | 100 |
/// exception classes (therefore the name). |
| 101 | 101 |
class ErrorMessage {
|
| 102 | 102 |
protected: |
| 103 | 103 |
///\e |
| 104 | 104 |
|
| 105 | 105 |
///\todo The good solution is boost::shared_ptr... |
| 106 | 106 |
/// |
| 107 | 107 |
mutable std::auto_ptr<std::ostringstream> buf; |
| 108 | 108 |
|
| 109 | 109 |
///\e |
| 110 | 110 |
bool init() throw() {
|
| 111 | 111 |
try {
|
| 112 |
|
|
| 112 |
buf.reset(new std::ostringstream); |
|
| 113 | 113 |
} |
| 114 | 114 |
catch(...) {
|
| 115 |
|
|
| 115 |
buf.reset(); |
|
| 116 | 116 |
} |
| 117 | 117 |
return buf.get(); |
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 | 120 |
public: |
| 121 | 121 |
|
| 122 | 122 |
///\e |
| 123 | 123 |
ErrorMessage() throw() { init(); }
|
| 124 | 124 |
|
| 125 | 125 |
ErrorMessage(const ErrorMessage& em) throw() : buf(em.buf) { }
|
| 126 | 126 |
|
| 127 | 127 |
///\e |
| 128 | 128 |
ErrorMessage(const char *msg) throw() {
|
| 129 | 129 |
init(); |
| 130 | 130 |
*this << msg; |
| 131 | 131 |
} |
| 132 | 132 |
|
| 133 | 133 |
///\e |
| 134 | 134 |
ErrorMessage(const std::string &msg) throw() {
|
| 135 | 135 |
init(); |
| 136 | 136 |
*this << msg; |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
///\e |
| 140 | 140 |
template <typename T> |
| 141 | 141 |
ErrorMessage& operator<<(const T &t) throw() {
|
| 142 | 142 |
if( ! buf.get() ) return *this; |
| 143 | 143 |
|
| 144 | 144 |
try {
|
| 145 |
|
|
| 145 |
*buf << t; |
|
| 146 | 146 |
} |
| 147 | 147 |
catch(...) {
|
| 148 |
|
|
| 148 |
buf.reset(); |
|
| 149 | 149 |
} |
| 150 | 150 |
return *this; |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 | 153 |
///\e |
| 154 | 154 |
const char* message() throw() {
|
| 155 | 155 |
if( ! buf.get() ) return 0; |
| 156 | 156 |
|
| 157 | 157 |
const char* mes = 0; |
| 158 | 158 |
try {
|
| 159 |
|
|
| 159 |
mes = buf->str().c_str(); |
|
| 160 | 160 |
} |
| 161 | 161 |
catch(...) {}
|
| 162 | 162 |
return mes; |
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 | 165 |
}; |
| 166 | 166 |
|
| 167 | 167 |
/// Generic exception class. |
| 168 | 168 |
|
| 169 | 169 |
/// Base class for exceptions used in LEMON. |
| 170 | 170 |
/// |
| 171 | 171 |
class Exception : public std::exception {
|
| 172 | 172 |
public: |
| 173 | 173 |
///\e |
| 174 | 174 |
Exception() {}
|
| 175 | 175 |
///\e |
| ... | ... |
@@ -241,78 +241,78 @@ |
| 241 | 241 |
ExceptionMember<std::string> _file; |
| 242 | 242 |
int _line; |
| 243 | 243 |
|
| 244 | 244 |
mutable ExceptionMember<std::string> _message_holder; |
| 245 | 245 |
public: |
| 246 | 246 |
|
| 247 | 247 |
DataFormatError(const DataFormatError &dfe) : |
| 248 | 248 |
IoError(dfe), _message(dfe._message), _file(dfe._file), |
| 249 | 249 |
_line(dfe._line) {}
|
| 250 | 250 |
|
| 251 | 251 |
///\e |
| 252 | 252 |
explicit DataFormatError(const char *the_message) |
| 253 | 253 |
: _message(the_message), _line(0) {}
|
| 254 | 254 |
|
| 255 | 255 |
///\e |
| 256 | 256 |
DataFormatError(const std::string &file_name, int line_num, |
| 257 |
|
|
| 257 |
const char *the_message) |
|
| 258 | 258 |
: _message(the_message), _line(line_num) { file(file_name); }
|
| 259 | 259 |
|
| 260 | 260 |
///\e |
| 261 | 261 |
void line(int ln) { _line = ln; }
|
| 262 | 262 |
///\e |
| 263 | 263 |
void message(const std::string& msg) { _message.set(msg); }
|
| 264 | 264 |
///\e |
| 265 | 265 |
void file(const std::string &fl) { _file.set(fl); }
|
| 266 | 266 |
|
| 267 | 267 |
///\e |
| 268 | 268 |
int line() const { return _line; }
|
| 269 | 269 |
///\e |
| 270 | 270 |
const char* message() const {
|
| 271 | 271 |
if (_message.valid() && !_message.get().empty()) {
|
| 272 |
|
|
| 272 |
return _message.get().c_str(); |
|
| 273 | 273 |
} else {
|
| 274 |
|
|
| 274 |
return 0; |
|
| 275 | 275 |
} |
| 276 | 276 |
} |
| 277 | 277 |
|
| 278 | 278 |
/// \brief Returns the filename. |
| 279 | 279 |
/// |
| 280 | 280 |
/// Returns \e null if the filename was not specified. |
| 281 | 281 |
const char* file() const {
|
| 282 | 282 |
if (_file.valid() && !_file.get().empty()) {
|
| 283 |
|
|
| 283 |
return _file.get().c_str(); |
|
| 284 | 284 |
} else {
|
| 285 |
|
|
| 285 |
return 0; |
|
| 286 | 286 |
} |
| 287 | 287 |
} |
| 288 | 288 |
|
| 289 | 289 |
///\e |
| 290 | 290 |
virtual const char* what() const throw() {
|
| 291 | 291 |
try {
|
| 292 |
std::ostringstream ostr; |
|
| 293 |
ostr << "lemon:DataFormatError" << ": "; |
|
| 294 |
if (message()) ostr << message(); |
|
| 295 |
if( file() || line() != 0 ) {
|
|
| 296 |
ostr << " (";
|
|
| 297 |
if( file() ) ostr << "in file '" << file() << "'"; |
|
| 298 |
if( file() && line() != 0 ) ostr << " "; |
|
| 299 |
if( line() != 0 ) ostr << "at line " << line(); |
|
| 300 |
ostr << ")"; |
|
| 301 |
} |
|
| 302 |
|
|
| 292 |
std::ostringstream ostr; |
|
| 293 |
ostr << "lemon:DataFormatError" << ": "; |
|
| 294 |
if (message()) ostr << message(); |
|
| 295 |
if( file() || line() != 0 ) {
|
|
| 296 |
ostr << " (";
|
|
| 297 |
if( file() ) ostr << "in file '" << file() << "'"; |
|
| 298 |
if( file() && line() != 0 ) ostr << " "; |
|
| 299 |
if( line() != 0 ) ostr << "at line " << line(); |
|
| 300 |
ostr << ")"; |
|
| 301 |
} |
|
| 302 |
_message_holder.set(ostr.str()); |
|
| 303 | 303 |
} |
| 304 | 304 |
catch (...) {}
|
| 305 | 305 |
if( _message_holder.valid()) return _message_holder.get().c_str(); |
| 306 | 306 |
return "lemon:DataFormatError"; |
| 307 | 307 |
} |
| 308 | 308 |
|
| 309 | 309 |
virtual ~DataFormatError() throw() {}
|
| 310 | 310 |
}; |
| 311 | 311 |
|
| 312 | 312 |
///\e |
| 313 | 313 |
class FileOpenError : public IoError {
|
| 314 | 314 |
protected: |
| 315 | 315 |
ExceptionMember<std::string> _file; |
| 316 | 316 |
|
| 317 | 317 |
mutable ExceptionMember<std::string> _message_holder; |
| 318 | 318 |
public: |
| ... | ... |
@@ -320,45 +320,45 @@ |
| 320 | 320 |
FileOpenError(const FileOpenError &foe) : |
| 321 | 321 |
IoError(foe), _file(foe._file) {}
|
| 322 | 322 |
|
| 323 | 323 |
///\e |
| 324 | 324 |
explicit FileOpenError(const std::string& fl) |
| 325 | 325 |
: _file(fl) {}
|
| 326 | 326 |
|
| 327 | 327 |
|
| 328 | 328 |
///\e |
| 329 | 329 |
void file(const std::string &fl) { _file.set(fl); }
|
| 330 | 330 |
|
| 331 | 331 |
/// \brief Returns the filename. |
| 332 | 332 |
/// |
| 333 | 333 |
/// Returns \e null if the filename was not specified. |
| 334 | 334 |
const char* file() const {
|
| 335 | 335 |
if (_file.valid() && !_file.get().empty()) {
|
| 336 |
|
|
| 336 |
return _file.get().c_str(); |
|
| 337 | 337 |
} else {
|
| 338 |
|
|
| 338 |
return 0; |
|
| 339 | 339 |
} |
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
///\e |
| 343 | 343 |
virtual const char* what() const throw() {
|
| 344 | 344 |
try {
|
| 345 |
std::ostringstream ostr; |
|
| 346 |
ostr << "lemon::FileOpenError" << ": "; |
|
| 347 |
ostr << "Cannot open file - " << file(); |
|
| 348 |
_message_holder.set(ostr.str()); |
|
| 345 |
std::ostringstream ostr; |
|
| 346 |
ostr << "lemon::FileOpenError" << ": "; |
|
| 347 |
ostr << "Cannot open file - " << file(); |
|
| 348 |
_message_holder.set(ostr.str()); |
|
| 349 | 349 |
} |
| 350 | 350 |
catch (...) {}
|
| 351 | 351 |
if( _message_holder.valid()) return _message_holder.get().c_str(); |
| 352 | 352 |
return "lemon::FileOpenError"; |
| 353 | 353 |
} |
| 354 | 354 |
virtual ~FileOpenError() throw() {}
|
| 355 | 355 |
}; |
| 356 | 356 |
|
| 357 | 357 |
class IoParameterError : public IoError {
|
| 358 | 358 |
protected: |
| 359 | 359 |
ExceptionMember<std::string> _message; |
| 360 | 360 |
ExceptionMember<std::string> _file; |
| 361 | 361 |
|
| 362 | 362 |
mutable ExceptionMember<std::string> _message_holder; |
| 363 | 363 |
public: |
| 364 | 364 |
|
| ... | ... |
@@ -368,53 +368,53 @@ |
| 368 | 368 |
///\e |
| 369 | 369 |
explicit IoParameterError(const char *the_message) |
| 370 | 370 |
: _message(the_message) {}
|
| 371 | 371 |
|
| 372 | 372 |
///\e |
| 373 | 373 |
IoParameterError(const char *file_name, const char *the_message) |
| 374 | 374 |
: _message(the_message), _file(file_name) {}
|
| 375 | 375 |
|
| 376 | 376 |
///\e |
| 377 | 377 |
void message(const std::string& msg) { _message.set(msg); }
|
| 378 | 378 |
///\e |
| 379 | 379 |
void file(const std::string &fl) { _file.set(fl); }
|
| 380 | 380 |
|
| 381 | 381 |
///\e |
| 382 | 382 |
const char* message() const {
|
| 383 | 383 |
if (_message.valid()) {
|
| 384 |
|
|
| 384 |
return _message.get().c_str(); |
|
| 385 | 385 |
} else {
|
| 386 |
|
|
| 386 |
return 0; |
|
| 387 | 387 |
} |
| 388 | 388 |
} |
| 389 | 389 |
|
| 390 | 390 |
/// \brief Returns the filename. |
| 391 | 391 |
/// |
| 392 | 392 |
/// Returns \c 0 if the filename was not specified. |
| 393 | 393 |
const char* file() const {
|
| 394 | 394 |
if (_file.valid()) {
|
| 395 |
|
|
| 395 |
return _file.get().c_str(); |
|
| 396 | 396 |
} else {
|
| 397 |
|
|
| 397 |
return 0; |
|
| 398 | 398 |
} |
| 399 | 399 |
} |
| 400 | 400 |
|
| 401 | 401 |
///\e |
| 402 | 402 |
virtual const char* what() const throw() {
|
| 403 | 403 |
try {
|
| 404 |
std::ostringstream ostr; |
|
| 405 |
if (message()) ostr << message(); |
|
| 406 |
if (file()) ostr << "(when reading file '" << file() << "')"; |
|
| 407 |
_message_holder.set(ostr.str()); |
|
| 404 |
std::ostringstream ostr; |
|
| 405 |
if (message()) ostr << message(); |
|
| 406 |
if (file()) ostr << "(when reading file '" << file() << "')"; |
|
| 407 |
_message_holder.set(ostr.str()); |
|
| 408 | 408 |
} |
| 409 | 409 |
catch (...) {}
|
| 410 | 410 |
if( _message_holder.valid() ) return _message_holder.get().c_str(); |
| 411 | 411 |
return "lemon:IoParameterError"; |
| 412 | 412 |
} |
| 413 | 413 |
virtual ~IoParameterError() throw() {}
|
| 414 | 414 |
}; |
| 415 | 415 |
|
| 416 | 416 |
/// @} |
| 417 | 417 |
|
| 418 | 418 |
} |
| 419 | 419 |
|
| 420 | 420 |
#endif // LEMON_ERROR_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_GRAPH_TO_EPS_H |
| ... | ... |
@@ -47,185 +47,185 @@ |
| 47 | 47 |
///\brief A well configurable tool for visualizing graphs |
| 48 | 48 |
|
| 49 | 49 |
namespace lemon {
|
| 50 | 50 |
|
| 51 | 51 |
namespace _graph_to_eps_bits {
|
| 52 | 52 |
template<class MT> |
| 53 | 53 |
class _NegY {
|
| 54 | 54 |
public: |
| 55 | 55 |
typedef typename MT::Key Key; |
| 56 | 56 |
typedef typename MT::Value Value; |
| 57 | 57 |
const MT ↦ |
| 58 | 58 |
int yscale; |
| 59 | 59 |
_NegY(const MT &m,bool b) : map(m), yscale(1-b*2) {}
|
| 60 | 60 |
Value operator[](Key n) { return Value(map[n].x,map[n].y*yscale);}
|
| 61 | 61 |
}; |
| 62 | 62 |
} |
| 63 |
|
|
| 63 |
|
|
| 64 | 64 |
///Default traits class of \ref GraphToEps |
| 65 | 65 |
|
| 66 | 66 |
///Default traits class of \ref GraphToEps. |
| 67 | 67 |
/// |
| 68 | 68 |
///\c G is the type of the underlying graph. |
| 69 | 69 |
template<class G> |
| 70 | 70 |
struct DefaultGraphToEpsTraits |
| 71 | 71 |
{
|
| 72 | 72 |
typedef G Graph; |
| 73 | 73 |
typedef typename Graph::Node Node; |
| 74 | 74 |
typedef typename Graph::NodeIt NodeIt; |
| 75 | 75 |
typedef typename Graph::Arc Arc; |
| 76 | 76 |
typedef typename Graph::ArcIt ArcIt; |
| 77 | 77 |
typedef typename Graph::InArcIt InArcIt; |
| 78 | 78 |
typedef typename Graph::OutArcIt OutArcIt; |
| 79 |
|
|
| 79 |
|
|
| 80 | 80 |
|
| 81 | 81 |
const Graph &g; |
| 82 | 82 |
|
| 83 | 83 |
std::ostream& os; |
| 84 |
|
|
| 84 |
|
|
| 85 | 85 |
typedef ConstMap<typename Graph::Node,dim2::Point<double> > CoordsMapType; |
| 86 | 86 |
CoordsMapType _coords; |
| 87 | 87 |
ConstMap<typename Graph::Node,double > _nodeSizes; |
| 88 | 88 |
ConstMap<typename Graph::Node,int > _nodeShapes; |
| 89 | 89 |
|
| 90 | 90 |
ConstMap<typename Graph::Node,Color > _nodeColors; |
| 91 | 91 |
ConstMap<typename Graph::Arc,Color > _arcColors; |
| 92 | 92 |
|
| 93 | 93 |
ConstMap<typename Graph::Arc,double > _arcWidths; |
| 94 | 94 |
|
| 95 | 95 |
double _arcWidthScale; |
| 96 |
|
|
| 96 |
|
|
| 97 | 97 |
double _nodeScale; |
| 98 | 98 |
double _xBorder, _yBorder; |
| 99 | 99 |
double _scale; |
| 100 | 100 |
double _nodeBorderQuotient; |
| 101 |
|
|
| 101 |
|
|
| 102 | 102 |
bool _drawArrows; |
| 103 | 103 |
double _arrowLength, _arrowWidth; |
| 104 |
|
|
| 104 |
|
|
| 105 | 105 |
bool _showNodes, _showArcs; |
| 106 | 106 |
|
| 107 | 107 |
bool _enableParallel; |
| 108 | 108 |
double _parArcDist; |
| 109 | 109 |
|
| 110 | 110 |
bool _showNodeText; |
| 111 |
ConstMap<typename Graph::Node,bool > _nodeTexts; |
|
| 111 |
ConstMap<typename Graph::Node,bool > _nodeTexts; |
|
| 112 | 112 |
double _nodeTextSize; |
| 113 | 113 |
|
| 114 | 114 |
bool _showNodePsText; |
| 115 |
ConstMap<typename Graph::Node,bool > _nodePsTexts; |
|
| 115 |
ConstMap<typename Graph::Node,bool > _nodePsTexts; |
|
| 116 | 116 |
char *_nodePsTextsPreamble; |
| 117 |
|
|
| 117 |
|
|
| 118 | 118 |
bool _undirected; |
| 119 | 119 |
|
| 120 | 120 |
bool _pleaseRemoveOsStream; |
| 121 | 121 |
|
| 122 | 122 |
bool _scaleToA4; |
| 123 | 123 |
|
| 124 | 124 |
std::string _title; |
| 125 | 125 |
std::string _copyright; |
| 126 | 126 |
|
| 127 |
enum NodeTextColorType |
|
| 127 |
enum NodeTextColorType |
|
| 128 | 128 |
{ DIST_COL=0, DIST_BW=1, CUST_COL=2, SAME_COL=3 } _nodeTextColorType;
|
| 129 | 129 |
ConstMap<typename Graph::Node,Color > _nodeTextColors; |
| 130 | 130 |
|
| 131 | 131 |
bool _autoNodeScale; |
| 132 | 132 |
bool _autoArcWidthScale; |
| 133 | 133 |
|
| 134 | 134 |
bool _absoluteNodeSizes; |
| 135 | 135 |
bool _absoluteArcWidths; |
| 136 | 136 |
|
| 137 | 137 |
bool _negY; |
| 138 | 138 |
|
| 139 | 139 |
bool _preScale; |
| 140 | 140 |
///Constructor |
| 141 | 141 |
|
| 142 | 142 |
///Constructor |
| 143 | 143 |
///\param _g Reference to the graph to be printed. |
| 144 | 144 |
///\param _os Reference to the output stream. |
| 145 | 145 |
///\param _os Reference to the output stream. By default it is <tt>std::cout</tt>. |
| 146 | 146 |
///\param _pros If it is \c true, then the \c ostream referenced by \c _os |
| 147 | 147 |
///will be explicitly deallocated by the destructor. |
| 148 | 148 |
DefaultGraphToEpsTraits(const G &_g,std::ostream& _os=std::cout, |
| 149 |
|
|
| 149 |
bool _pros=false) : |
|
| 150 | 150 |
g(_g), os(_os), |
| 151 | 151 |
_coords(dim2::Point<double>(1,1)), _nodeSizes(1), _nodeShapes(0), |
| 152 | 152 |
_nodeColors(WHITE), _arcColors(BLACK), |
| 153 | 153 |
_arcWidths(1.0), _arcWidthScale(0.003), |
| 154 | 154 |
_nodeScale(.01), _xBorder(10), _yBorder(10), _scale(1.0), |
| 155 | 155 |
_nodeBorderQuotient(.1), |
| 156 | 156 |
_drawArrows(false), _arrowLength(1), _arrowWidth(0.3), |
| 157 | 157 |
_showNodes(true), _showArcs(true), |
| 158 | 158 |
_enableParallel(false), _parArcDist(1), |
| 159 | 159 |
_showNodeText(false), _nodeTexts(false), _nodeTextSize(1), |
| 160 | 160 |
_showNodePsText(false), _nodePsTexts(false), _nodePsTextsPreamble(0), |
| 161 | 161 |
_undirected(lemon::UndirectedTagIndicator<G>::value), |
| 162 | 162 |
_pleaseRemoveOsStream(_pros), _scaleToA4(false), |
| 163 | 163 |
_nodeTextColorType(SAME_COL), _nodeTextColors(BLACK), |
| 164 | 164 |
_autoNodeScale(false), |
| 165 | 165 |
_autoArcWidthScale(false), |
| 166 | 166 |
_absoluteNodeSizes(false), |
| 167 | 167 |
_absoluteArcWidths(false), |
| 168 | 168 |
_negY(false), |
| 169 | 169 |
_preScale(true) |
| 170 | 170 |
{}
|
| 171 | 171 |
}; |
| 172 | 172 |
|
| 173 | 173 |
///Auxiliary class to implement the named parameters of \ref graphToEps() |
| 174 | 174 |
|
| 175 | 175 |
///Auxiliary class to implement the named parameters of \ref graphToEps(). |
| 176 | 176 |
/// |
| 177 | 177 |
///For detailed examples see the \ref graph_to_eps_demo.cc demo file. |
| 178 |
template<class T> class GraphToEps : public T |
|
| 178 |
template<class T> class GraphToEps : public T |
|
| 179 | 179 |
{
|
| 180 | 180 |
// Can't believe it is required by the C++ standard |
| 181 | 181 |
using T::g; |
| 182 | 182 |
using T::os; |
| 183 | 183 |
|
| 184 | 184 |
using T::_coords; |
| 185 | 185 |
using T::_nodeSizes; |
| 186 | 186 |
using T::_nodeShapes; |
| 187 | 187 |
using T::_nodeColors; |
| 188 | 188 |
using T::_arcColors; |
| 189 | 189 |
using T::_arcWidths; |
| 190 | 190 |
|
| 191 | 191 |
using T::_arcWidthScale; |
| 192 | 192 |
using T::_nodeScale; |
| 193 | 193 |
using T::_xBorder; |
| 194 | 194 |
using T::_yBorder; |
| 195 | 195 |
using T::_scale; |
| 196 | 196 |
using T::_nodeBorderQuotient; |
| 197 |
|
|
| 197 |
|
|
| 198 | 198 |
using T::_drawArrows; |
| 199 | 199 |
using T::_arrowLength; |
| 200 | 200 |
using T::_arrowWidth; |
| 201 |
|
|
| 201 |
|
|
| 202 | 202 |
using T::_showNodes; |
| 203 | 203 |
using T::_showArcs; |
| 204 | 204 |
|
| 205 | 205 |
using T::_enableParallel; |
| 206 | 206 |
using T::_parArcDist; |
| 207 | 207 |
|
| 208 | 208 |
using T::_showNodeText; |
| 209 |
using T::_nodeTexts; |
|
| 209 |
using T::_nodeTexts; |
|
| 210 | 210 |
using T::_nodeTextSize; |
| 211 | 211 |
|
| 212 | 212 |
using T::_showNodePsText; |
| 213 |
using T::_nodePsTexts; |
|
| 213 |
using T::_nodePsTexts; |
|
| 214 | 214 |
using T::_nodePsTextsPreamble; |
| 215 |
|
|
| 215 |
|
|
| 216 | 216 |
using T::_undirected; |
| 217 | 217 |
|
| 218 | 218 |
using T::_pleaseRemoveOsStream; |
| 219 | 219 |
|
| 220 | 220 |
using T::_scaleToA4; |
| 221 | 221 |
|
| 222 | 222 |
using T::_title; |
| 223 | 223 |
using T::_copyright; |
| 224 | 224 |
|
| 225 | 225 |
using T::NodeTextColorType; |
| 226 | 226 |
using T::CUST_COL; |
| 227 | 227 |
using T::DIST_COL; |
| 228 | 228 |
using T::DIST_BW; |
| 229 | 229 |
using T::_nodeTextColorType; |
| 230 | 230 |
using T::_nodeTextColors; |
| 231 | 231 |
|
| ... | ... |
@@ -248,151 +248,151 @@ |
| 248 | 248 |
typedef typename Graph::ArcIt ArcIt; |
| 249 | 249 |
typedef typename Graph::InArcIt InArcIt; |
| 250 | 250 |
typedef typename Graph::OutArcIt OutArcIt; |
| 251 | 251 |
|
| 252 | 252 |
static const int INTERPOL_PREC; |
| 253 | 253 |
static const double A4HEIGHT; |
| 254 | 254 |
static const double A4WIDTH; |
| 255 | 255 |
static const double A4BORDER; |
| 256 | 256 |
|
| 257 | 257 |
bool dontPrint; |
| 258 | 258 |
|
| 259 | 259 |
public: |
| 260 | 260 |
///Node shapes |
| 261 | 261 |
|
| 262 | 262 |
///Node shapes. |
| 263 | 263 |
/// |
| 264 |
enum NodeShapes {
|
|
| 264 |
enum NodeShapes {
|
|
| 265 | 265 |
/// = 0 |
| 266 | 266 |
///\image html nodeshape_0.png |
| 267 | 267 |
///\image latex nodeshape_0.eps "CIRCLE shape (0)" width=2cm |
| 268 |
CIRCLE=0, |
|
| 268 |
CIRCLE=0, |
|
| 269 | 269 |
/// = 1 |
| 270 | 270 |
///\image html nodeshape_1.png |
| 271 | 271 |
///\image latex nodeshape_1.eps "SQUARE shape (1)" width=2cm |
| 272 | 272 |
/// |
| 273 |
SQUARE=1, |
|
| 273 |
SQUARE=1, |
|
| 274 | 274 |
/// = 2 |
| 275 | 275 |
///\image html nodeshape_2.png |
| 276 | 276 |
///\image latex nodeshape_2.eps "DIAMOND shape (2)" width=2cm |
| 277 | 277 |
/// |
| 278 | 278 |
DIAMOND=2, |
| 279 | 279 |
/// = 3 |
| 280 | 280 |
///\image html nodeshape_3.png |
| 281 | 281 |
///\image latex nodeshape_2.eps "MALE shape (4)" width=2cm |
| 282 | 282 |
/// |
| 283 | 283 |
MALE=3, |
| 284 | 284 |
/// = 4 |
| 285 | 285 |
///\image html nodeshape_4.png |
| 286 | 286 |
///\image latex nodeshape_2.eps "FEMALE shape (4)" width=2cm |
| 287 | 287 |
/// |
| 288 | 288 |
FEMALE=4 |
| 289 | 289 |
}; |
| 290 | 290 |
|
| 291 | 291 |
private: |
| 292 | 292 |
class arcLess {
|
| 293 | 293 |
const Graph &g; |
| 294 | 294 |
public: |
| 295 | 295 |
arcLess(const Graph &_g) : g(_g) {}
|
| 296 |
bool operator()(Arc a,Arc b) const |
|
| 296 |
bool operator()(Arc a,Arc b) const |
|
| 297 | 297 |
{
|
| 298 | 298 |
Node ai=std::min(g.source(a),g.target(a)); |
| 299 | 299 |
Node aa=std::max(g.source(a),g.target(a)); |
| 300 | 300 |
Node bi=std::min(g.source(b),g.target(b)); |
| 301 | 301 |
Node ba=std::max(g.source(b),g.target(b)); |
| 302 | 302 |
return ai<bi || |
| 303 |
(ai==bi && (aa < ba || |
|
| 304 |
(aa==ba && ai==g.source(a) && bi==g.target(b)))); |
|
| 303 |
(ai==bi && (aa < ba || |
|
| 304 |
(aa==ba && ai==g.source(a) && bi==g.target(b)))); |
|
| 305 | 305 |
} |
| 306 | 306 |
}; |
| 307 | 307 |
bool isParallel(Arc e,Arc f) const |
| 308 | 308 |
{
|
| 309 | 309 |
return (g.source(e)==g.source(f)&& |
| 310 |
|
|
| 310 |
g.target(e)==g.target(f)) || |
|
| 311 | 311 |
(g.source(e)==g.target(f)&& |
| 312 | 312 |
g.target(e)==g.source(f)); |
| 313 | 313 |
} |
| 314 | 314 |
template<class TT> |
| 315 |
static std::string psOut(const dim2::Point<TT> &p) |
|
| 315 |
static std::string psOut(const dim2::Point<TT> &p) |
|
| 316 | 316 |
{
|
| 317 |
std::ostringstream os; |
|
| 317 |
std::ostringstream os; |
|
| 318 | 318 |
os << p.x << ' ' << p.y; |
| 319 | 319 |
return os.str(); |
| 320 | 320 |
} |
| 321 |
static std::string psOut(const Color &c) |
|
| 321 |
static std::string psOut(const Color &c) |
|
| 322 | 322 |
{
|
| 323 |
std::ostringstream os; |
|
| 323 |
std::ostringstream os; |
|
| 324 | 324 |
os << c.red() << ' ' << c.green() << ' ' << c.blue(); |
| 325 | 325 |
return os.str(); |
| 326 | 326 |
} |
| 327 |
|
|
| 327 |
|
|
| 328 | 328 |
public: |
| 329 | 329 |
GraphToEps(const T &t) : T(t), dontPrint(false) {};
|
| 330 |
|
|
| 330 |
|
|
| 331 | 331 |
template<class X> struct CoordsTraits : public T {
|
| 332 | 332 |
typedef X CoordsMapType; |
| 333 | 333 |
const X &_coords; |
| 334 | 334 |
CoordsTraits(const T &t,const X &x) : T(t), _coords(x) {}
|
| 335 | 335 |
}; |
| 336 | 336 |
///Sets the map of the node coordinates |
| 337 | 337 |
|
| 338 | 338 |
///Sets the map of the node coordinates. |
| 339 | 339 |
///\param x must be a node map with \ref dim2::Point "dim2::Point<double>" or |
| 340 |
///\ref dim2::Point "dim2::Point<int>" values. |
|
| 340 |
///\ref dim2::Point "dim2::Point<int>" values. |
|
| 341 | 341 |
template<class X> GraphToEps<CoordsTraits<X> > coords(const X &x) {
|
| 342 | 342 |
dontPrint=true; |
| 343 | 343 |
return GraphToEps<CoordsTraits<X> >(CoordsTraits<X>(*this,x)); |
| 344 | 344 |
} |
| 345 | 345 |
template<class X> struct NodeSizesTraits : public T {
|
| 346 | 346 |
const X &_nodeSizes; |
| 347 | 347 |
NodeSizesTraits(const T &t,const X &x) : T(t), _nodeSizes(x) {}
|
| 348 | 348 |
}; |
| 349 | 349 |
///Sets the map of the node sizes |
| 350 | 350 |
|
| 351 | 351 |
///Sets the map of the node sizes. |
| 352 |
///\param x must be a node map with \c double (or convertible) values. |
|
| 352 |
///\param x must be a node map with \c double (or convertible) values. |
|
| 353 | 353 |
template<class X> GraphToEps<NodeSizesTraits<X> > nodeSizes(const X &x) |
| 354 | 354 |
{
|
| 355 | 355 |
dontPrint=true; |
| 356 | 356 |
return GraphToEps<NodeSizesTraits<X> >(NodeSizesTraits<X>(*this,x)); |
| 357 | 357 |
} |
| 358 | 358 |
template<class X> struct NodeShapesTraits : public T {
|
| 359 | 359 |
const X &_nodeShapes; |
| 360 | 360 |
NodeShapesTraits(const T &t,const X &x) : T(t), _nodeShapes(x) {}
|
| 361 | 361 |
}; |
| 362 | 362 |
///Sets the map of the node shapes |
| 363 | 363 |
|
| 364 | 364 |
///Sets the map of the node shapes. |
| 365 | 365 |
///The available shape values |
| 366 | 366 |
///can be found in \ref NodeShapes "enum NodeShapes". |
| 367 |
///\param x must be a node map with \c int (or convertible) values. |
|
| 367 |
///\param x must be a node map with \c int (or convertible) values. |
|
| 368 | 368 |
///\sa NodeShapes |
| 369 | 369 |
template<class X> GraphToEps<NodeShapesTraits<X> > nodeShapes(const X &x) |
| 370 | 370 |
{
|
| 371 | 371 |
dontPrint=true; |
| 372 | 372 |
return GraphToEps<NodeShapesTraits<X> >(NodeShapesTraits<X>(*this,x)); |
| 373 | 373 |
} |
| 374 | 374 |
template<class X> struct NodeTextsTraits : public T {
|
| 375 | 375 |
const X &_nodeTexts; |
| 376 | 376 |
NodeTextsTraits(const T &t,const X &x) : T(t), _nodeTexts(x) {}
|
| 377 | 377 |
}; |
| 378 | 378 |
///Sets the text printed on the nodes |
| 379 | 379 |
|
| 380 | 380 |
///Sets the text printed on the nodes. |
| 381 | 381 |
///\param x must be a node map with type that can be pushed to a standard |
| 382 |
///\c ostream. |
|
| 382 |
///\c ostream. |
|
| 383 | 383 |
template<class X> GraphToEps<NodeTextsTraits<X> > nodeTexts(const X &x) |
| 384 | 384 |
{
|
| 385 | 385 |
dontPrint=true; |
| 386 | 386 |
_showNodeText=true; |
| 387 | 387 |
return GraphToEps<NodeTextsTraits<X> >(NodeTextsTraits<X>(*this,x)); |
| 388 | 388 |
} |
| 389 | 389 |
template<class X> struct NodePsTextsTraits : public T {
|
| 390 | 390 |
const X &_nodePsTexts; |
| 391 | 391 |
NodePsTextsTraits(const T &t,const X &x) : T(t), _nodePsTexts(x) {}
|
| 392 | 392 |
}; |
| 393 | 393 |
///Inserts a PostScript block to the nodes |
| 394 | 394 |
|
| 395 | 395 |
///With this command it is possible to insert a verbatim PostScript |
| 396 | 396 |
///block to the nodes. |
| 397 | 397 |
///The PS current point will be moved to the center of the node before |
| 398 | 398 |
///the PostScript block inserted. |
| ... | ... |
@@ -404,93 +404,93 @@ |
| 404 | 404 |
///\c ostream. |
| 405 | 405 |
/// |
| 406 | 406 |
///\sa nodePsTextsPreamble() |
| 407 | 407 |
template<class X> GraphToEps<NodePsTextsTraits<X> > nodePsTexts(const X &x) |
| 408 | 408 |
{
|
| 409 | 409 |
dontPrint=true; |
| 410 | 410 |
_showNodePsText=true; |
| 411 | 411 |
return GraphToEps<NodePsTextsTraits<X> >(NodePsTextsTraits<X>(*this,x)); |
| 412 | 412 |
} |
| 413 | 413 |
template<class X> struct ArcWidthsTraits : public T {
|
| 414 | 414 |
const X &_arcWidths; |
| 415 | 415 |
ArcWidthsTraits(const T &t,const X &x) : T(t), _arcWidths(x) {}
|
| 416 | 416 |
}; |
| 417 | 417 |
///Sets the map of the arc widths |
| 418 | 418 |
|
| 419 | 419 |
///Sets the map of the arc widths. |
| 420 |
///\param x must be an arc map with \c double (or convertible) values. |
|
| 420 |
///\param x must be an arc map with \c double (or convertible) values. |
|
| 421 | 421 |
template<class X> GraphToEps<ArcWidthsTraits<X> > arcWidths(const X &x) |
| 422 | 422 |
{
|
| 423 | 423 |
dontPrint=true; |
| 424 | 424 |
return GraphToEps<ArcWidthsTraits<X> >(ArcWidthsTraits<X>(*this,x)); |
| 425 | 425 |
} |
| 426 | 426 |
|
| 427 | 427 |
template<class X> struct NodeColorsTraits : public T {
|
| 428 | 428 |
const X &_nodeColors; |
| 429 | 429 |
NodeColorsTraits(const T &t,const X &x) : T(t), _nodeColors(x) {}
|
| 430 | 430 |
}; |
| 431 | 431 |
///Sets the map of the node colors |
| 432 | 432 |
|
| 433 | 433 |
///Sets the map of the node colors. |
| 434 | 434 |
///\param x must be a node map with \ref Color values. |
| 435 | 435 |
/// |
| 436 | 436 |
///\sa Palette |
| 437 | 437 |
template<class X> GraphToEps<NodeColorsTraits<X> > |
| 438 | 438 |
nodeColors(const X &x) |
| 439 | 439 |
{
|
| 440 | 440 |
dontPrint=true; |
| 441 | 441 |
return GraphToEps<NodeColorsTraits<X> >(NodeColorsTraits<X>(*this,x)); |
| 442 | 442 |
} |
| 443 | 443 |
template<class X> struct NodeTextColorsTraits : public T {
|
| 444 | 444 |
const X &_nodeTextColors; |
| 445 | 445 |
NodeTextColorsTraits(const T &t,const X &x) : T(t), _nodeTextColors(x) {}
|
| 446 | 446 |
}; |
| 447 | 447 |
///Sets the map of the node text colors |
| 448 | 448 |
|
| 449 | 449 |
///Sets the map of the node text colors. |
| 450 |
///\param x must be a node map with \ref Color values. |
|
| 450 |
///\param x must be a node map with \ref Color values. |
|
| 451 | 451 |
/// |
| 452 | 452 |
///\sa Palette |
| 453 | 453 |
template<class X> GraphToEps<NodeTextColorsTraits<X> > |
| 454 | 454 |
nodeTextColors(const X &x) |
| 455 | 455 |
{
|
| 456 | 456 |
dontPrint=true; |
| 457 | 457 |
_nodeTextColorType=CUST_COL; |
| 458 | 458 |
return GraphToEps<NodeTextColorsTraits<X> > |
| 459 | 459 |
(NodeTextColorsTraits<X>(*this,x)); |
| 460 | 460 |
} |
| 461 | 461 |
template<class X> struct ArcColorsTraits : public T {
|
| 462 | 462 |
const X &_arcColors; |
| 463 | 463 |
ArcColorsTraits(const T &t,const X &x) : T(t), _arcColors(x) {}
|
| 464 | 464 |
}; |
| 465 | 465 |
///Sets the map of the arc colors |
| 466 | 466 |
|
| 467 | 467 |
///Sets the map of the arc colors. |
| 468 |
///\param x must be an arc map with \ref Color values. |
|
| 468 |
///\param x must be an arc map with \ref Color values. |
|
| 469 | 469 |
/// |
| 470 | 470 |
///\sa Palette |
| 471 | 471 |
template<class X> GraphToEps<ArcColorsTraits<X> > |
| 472 | 472 |
arcColors(const X &x) |
| 473 | 473 |
{
|
| 474 | 474 |
dontPrint=true; |
| 475 | 475 |
return GraphToEps<ArcColorsTraits<X> >(ArcColorsTraits<X>(*this,x)); |
| 476 | 476 |
} |
| 477 | 477 |
///Sets a global scale factor for node sizes |
| 478 | 478 |
|
| 479 | 479 |
///Sets a global scale factor for node sizes. |
| 480 |
/// |
|
| 480 |
/// |
|
| 481 | 481 |
/// If nodeSizes() is not given, this function simply sets the node |
| 482 | 482 |
/// sizes to \c d. If nodeSizes() is given, but |
| 483 | 483 |
/// autoNodeScale() is not, then the node size given by |
| 484 | 484 |
/// nodeSizes() will be multiplied by the value \c d. |
| 485 | 485 |
/// If both nodeSizes() and autoNodeScale() are used, then the |
| 486 | 486 |
/// node sizes will be scaled in such a way that the greatest size will be |
| 487 | 487 |
/// equal to \c d. |
| 488 | 488 |
/// \sa nodeSizes() |
| 489 | 489 |
/// \sa autoNodeScale() |
| 490 | 490 |
GraphToEps<T> &nodeScale(double d=.01) {_nodeScale=d;return *this;}
|
| 491 | 491 |
///Turns on/off the automatic node size scaling. |
| 492 | 492 |
|
| 493 | 493 |
///Turns on/off the automatic node size scaling. |
| 494 | 494 |
/// |
| 495 | 495 |
///\sa nodeScale() |
| 496 | 496 |
/// |
| ... | ... |
@@ -555,242 +555,242 @@ |
| 555 | 555 |
_absoluteArcWidths=b;return *this; |
| 556 | 556 |
} |
| 557 | 557 |
///Sets a global scale factor for the whole picture |
| 558 | 558 |
GraphToEps<T> &scale(double d) {_scale=d;return *this;}
|
| 559 | 559 |
///Sets the width of the border around the picture |
| 560 | 560 |
GraphToEps<T> &border(double b=10) {_xBorder=_yBorder=b;return *this;}
|
| 561 | 561 |
///Sets the width of the border around the picture |
| 562 | 562 |
GraphToEps<T> &border(double x, double y) {
|
| 563 | 563 |
_xBorder=x;_yBorder=y;return *this; |
| 564 | 564 |
} |
| 565 | 565 |
///Sets whether to draw arrows |
| 566 | 566 |
GraphToEps<T> &drawArrows(bool b=true) {_drawArrows=b;return *this;}
|
| 567 | 567 |
///Sets the length of the arrowheads |
| 568 | 568 |
GraphToEps<T> &arrowLength(double d=1.0) {_arrowLength*=d;return *this;}
|
| 569 | 569 |
///Sets the width of the arrowheads |
| 570 | 570 |
GraphToEps<T> &arrowWidth(double d=.3) {_arrowWidth*=d;return *this;}
|
| 571 |
|
|
| 571 |
|
|
| 572 | 572 |
///Scales the drawing to fit to A4 page |
| 573 | 573 |
GraphToEps<T> &scaleToA4() {_scaleToA4=true;return *this;}
|
| 574 |
|
|
| 574 |
|
|
| 575 | 575 |
///Enables parallel arcs |
| 576 | 576 |
GraphToEps<T> &enableParallel(bool b=true) {_enableParallel=b;return *this;}
|
| 577 |
|
|
| 577 |
|
|
| 578 | 578 |
///Sets the distance between parallel arcs |
| 579 | 579 |
GraphToEps<T> &parArcDist(double d) {_parArcDist*=d;return *this;}
|
| 580 |
|
|
| 580 |
|
|
| 581 | 581 |
///Hides the arcs |
| 582 | 582 |
GraphToEps<T> &hideArcs(bool b=true) {_showArcs=!b;return *this;}
|
| 583 | 583 |
///Hides the nodes |
| 584 | 584 |
GraphToEps<T> &hideNodes(bool b=true) {_showNodes=!b;return *this;}
|
| 585 |
|
|
| 585 |
|
|
| 586 | 586 |
///Sets the size of the node texts |
| 587 | 587 |
GraphToEps<T> &nodeTextSize(double d) {_nodeTextSize=d;return *this;}
|
| 588 | 588 |
|
| 589 | 589 |
///Sets the color of the node texts to be different from the node color |
| 590 | 590 |
|
| 591 | 591 |
///Sets the color of the node texts to be as different from the node color |
| 592 | 592 |
///as it is possible. |
| 593 | 593 |
GraphToEps<T> &distantColorNodeTexts() |
| 594 | 594 |
{_nodeTextColorType=DIST_COL;return *this;}
|
| 595 | 595 |
///Sets the color of the node texts to be black or white and always visible. |
| 596 | 596 |
|
| 597 | 597 |
///Sets the color of the node texts to be black or white according to |
| 598 | 598 |
///which is more different from the node color. |
| 599 | 599 |
GraphToEps<T> &distantBWNodeTexts() |
| 600 | 600 |
{_nodeTextColorType=DIST_BW;return *this;}
|
| 601 | 601 |
|
| 602 | 602 |
///Gives a preamble block for node Postscript block. |
| 603 |
|
|
| 603 |
|
|
| 604 | 604 |
///Gives a preamble block for node Postscript block. |
| 605 | 605 |
/// |
| 606 | 606 |
///\sa nodePsTexts() |
| 607 | 607 |
GraphToEps<T> & nodePsTextsPreamble(const char *str) {
|
| 608 | 608 |
_nodePsTextsPreamble=str ;return *this; |
| 609 | 609 |
} |
| 610 | 610 |
///Sets whether the graph is undirected |
| 611 | 611 |
|
| 612 | 612 |
///Sets whether the graph is undirected. |
| 613 | 613 |
/// |
| 614 | 614 |
///This setting is the default for undirected graphs. |
| 615 | 615 |
/// |
| 616 | 616 |
///\sa directed() |
| 617 | 617 |
GraphToEps<T> &undirected(bool b=true) {_undirected=b;return *this;}
|
| 618 | 618 |
|
| 619 | 619 |
///Sets whether the graph is directed |
| 620 | 620 |
|
| 621 | 621 |
///Sets whether the graph is directed. |
| 622 | 622 |
///Use it to show the edges as a pair of directed ones. |
| 623 | 623 |
/// |
| 624 | 624 |
///This setting is the default for digraphs. |
| 625 | 625 |
/// |
| 626 | 626 |
///\sa undirected() |
| 627 | 627 |
GraphToEps<T> &directed(bool b=true) {_undirected=!b;return *this;}
|
| 628 |
|
|
| 628 |
|
|
| 629 | 629 |
///Sets the title. |
| 630 | 630 |
|
| 631 | 631 |
///Sets the title of the generated image, |
| 632 | 632 |
///namely it inserts a <tt>%%Title:</tt> DSC field to the header of |
| 633 | 633 |
///the EPS file. |
| 634 | 634 |
GraphToEps<T> &title(const std::string &t) {_title=t;return *this;}
|
| 635 | 635 |
///Sets the copyright statement. |
| 636 | 636 |
|
| 637 | 637 |
///Sets the copyright statement of the generated image, |
| 638 | 638 |
///namely it inserts a <tt>%%Copyright:</tt> DSC field to the header of |
| 639 | 639 |
///the EPS file. |
| 640 | 640 |
GraphToEps<T> ©right(const std::string &t) {_copyright=t;return *this;}
|
| 641 | 641 |
|
| 642 | 642 |
protected: |
| 643 |
bool isInsideNode(dim2::Point<double> p, double r,int t) |
|
| 643 |
bool isInsideNode(dim2::Point<double> p, double r,int t) |
|
| 644 | 644 |
{
|
| 645 | 645 |
switch(t) {
|
| 646 | 646 |
case CIRCLE: |
| 647 | 647 |
case MALE: |
| 648 | 648 |
case FEMALE: |
| 649 | 649 |
return p.normSquare()<=r*r; |
| 650 | 650 |
case SQUARE: |
| 651 | 651 |
return p.x<=r&&p.x>=-r&&p.y<=r&&p.y>=-r; |
| 652 | 652 |
case DIAMOND: |
| 653 | 653 |
return p.x+p.y<=r && p.x-p.y<=r && -p.x+p.y<=r && -p.x-p.y<=r; |
| 654 | 654 |
} |
| 655 | 655 |
return false; |
| 656 | 656 |
} |
| 657 | 657 |
|
| 658 | 658 |
public: |
| 659 | 659 |
~GraphToEps() { }
|
| 660 |
|
|
| 660 |
|
|
| 661 | 661 |
///Draws the graph. |
| 662 | 662 |
|
| 663 | 663 |
///Like other functions using |
| 664 | 664 |
///\ref named-templ-func-param "named template parameters", |
| 665 | 665 |
///this function calls the algorithm itself, i.e. in this case |
| 666 | 666 |
///it draws the graph. |
| 667 | 667 |
void run() {
|
| 668 | 668 |
//\todo better 'epsilon' would be nice here. |
| 669 | 669 |
const double EPSILON=1e-9; |
| 670 | 670 |
if(dontPrint) return; |
| 671 |
|
|
| 671 |
|
|
| 672 | 672 |
_graph_to_eps_bits::_NegY<typename T::CoordsMapType> |
| 673 | 673 |
mycoords(_coords,_negY); |
| 674 | 674 |
|
| 675 | 675 |
os << "%!PS-Adobe-2.0 EPSF-2.0\n"; |
| 676 | 676 |
if(_title.size()>0) os << "%%Title: " << _title << '\n'; |
| 677 | 677 |
if(_copyright.size()>0) os << "%%Copyright: " << _copyright << '\n'; |
| 678 | 678 |
os << "%%Creator: LEMON, graphToEps()\n"; |
| 679 | 679 |
|
| 680 |
{
|
|
| 681 |
#ifndef WIN32 |
|
| 680 |
{
|
|
| 681 |
#ifndef WIN32 |
|
| 682 | 682 |
timeval tv; |
| 683 | 683 |
gettimeofday(&tv, 0); |
| 684 | 684 |
|
| 685 | 685 |
char cbuf[26]; |
| 686 | 686 |
ctime_r(&tv.tv_sec,cbuf); |
| 687 | 687 |
os << "%%CreationDate: " << cbuf; |
| 688 | 688 |
#else |
| 689 | 689 |
SYSTEMTIME time; |
| 690 | 690 |
char buf1[11], buf2[9], buf3[5]; |
| 691 |
|
|
| 691 |
|
|
| 692 | 692 |
GetSystemTime(&time); |
| 693 |
if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 694 |
"ddd MMM dd", buf1, 11) && |
|
| 695 |
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 696 |
"HH':'mm':'ss", buf2, 9) && |
|
| 697 |
GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 698 |
"yyyy", buf3, 5)) {
|
|
| 699 |
os << "%%CreationDate: " << buf1 << ' ' |
|
| 700 |
<< buf2 << ' ' << buf3 << std::endl; |
|
| 701 |
|
|
| 693 |
if (GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 694 |
"ddd MMM dd", buf1, 11) && |
|
| 695 |
GetTimeFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 696 |
"HH':'mm':'ss", buf2, 9) && |
|
| 697 |
GetDateFormat(LOCALE_USER_DEFAULT, 0, &time, |
|
| 698 |
"yyyy", buf3, 5)) {
|
|
| 699 |
os << "%%CreationDate: " << buf1 << ' ' |
|
| 700 |
<< buf2 << ' ' << buf3 << std::endl; |
|
| 701 |
} |
|
| 702 | 702 |
#endif |
| 703 | 703 |
} |
| 704 | 704 |
|
| 705 | 705 |
if (_autoArcWidthScale) {
|
| 706 | 706 |
double max_w=0; |
| 707 | 707 |
for(ArcIt e(g);e!=INVALID;++e) |
| 708 |
|
|
| 708 |
max_w=std::max(double(_arcWidths[e]),max_w); |
|
| 709 | 709 |
//\todo better 'epsilon' would be nice here. |
| 710 | 710 |
if(max_w>EPSILON) {
|
| 711 |
|
|
| 711 |
_arcWidthScale/=max_w; |
|
| 712 | 712 |
} |
| 713 | 713 |
} |
| 714 | 714 |
|
| 715 | 715 |
if (_autoNodeScale) {
|
| 716 | 716 |
double max_s=0; |
| 717 | 717 |
for(NodeIt n(g);n!=INVALID;++n) |
| 718 |
|
|
| 718 |
max_s=std::max(double(_nodeSizes[n]),max_s); |
|
| 719 | 719 |
//\todo better 'epsilon' would be nice here. |
| 720 | 720 |
if(max_s>EPSILON) {
|
| 721 |
|
|
| 721 |
_nodeScale/=max_s; |
|
| 722 | 722 |
} |
| 723 | 723 |
} |
| 724 | 724 |
|
| 725 | 725 |
double diag_len = 1; |
| 726 | 726 |
if(!(_absoluteNodeSizes&&_absoluteArcWidths)) {
|
| 727 | 727 |
dim2::BoundingBox<double> bb; |
| 728 | 728 |
for(NodeIt n(g);n!=INVALID;++n) bb.add(mycoords[n]); |
| 729 | 729 |
if (bb.empty()) {
|
| 730 |
|
|
| 730 |
bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0)); |
|
| 731 | 731 |
} |
| 732 | 732 |
diag_len = std::sqrt((bb.bottomLeft()-bb.topRight()).normSquare()); |
| 733 | 733 |
if(diag_len<EPSILON) diag_len = 1; |
| 734 | 734 |
if(!_absoluteNodeSizes) _nodeScale*=diag_len; |
| 735 | 735 |
if(!_absoluteArcWidths) _arcWidthScale*=diag_len; |
| 736 | 736 |
} |
| 737 |
|
|
| 737 |
|
|
| 738 | 738 |
dim2::BoundingBox<double> bb; |
| 739 | 739 |
for(NodeIt n(g);n!=INVALID;++n) {
|
| 740 | 740 |
double ns=_nodeSizes[n]*_nodeScale; |
| 741 | 741 |
dim2::Point<double> p(ns,ns); |
| 742 | 742 |
switch(_nodeShapes[n]) {
|
| 743 | 743 |
case CIRCLE: |
| 744 | 744 |
case SQUARE: |
| 745 | 745 |
case DIAMOND: |
| 746 |
bb.add(p+mycoords[n]); |
|
| 747 |
bb.add(-p+mycoords[n]); |
|
| 748 |
|
|
| 746 |
bb.add(p+mycoords[n]); |
|
| 747 |
bb.add(-p+mycoords[n]); |
|
| 748 |
break; |
|
| 749 | 749 |
case MALE: |
| 750 |
bb.add(-p+mycoords[n]); |
|
| 751 |
bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]); |
|
| 752 |
|
|
| 750 |
bb.add(-p+mycoords[n]); |
|
| 751 |
bb.add(dim2::Point<double>(1.5*ns,1.5*std::sqrt(3.0)*ns)+mycoords[n]); |
|
| 752 |
break; |
|
| 753 | 753 |
case FEMALE: |
| 754 |
bb.add(p+mycoords[n]); |
|
| 755 |
bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]); |
|
| 756 |
|
|
| 754 |
bb.add(p+mycoords[n]); |
|
| 755 |
bb.add(dim2::Point<double>(-ns,-3.01*ns)+mycoords[n]); |
|
| 756 |
break; |
|
| 757 | 757 |
} |
| 758 | 758 |
} |
| 759 | 759 |
if (bb.empty()) {
|
| 760 | 760 |
bb = dim2::BoundingBox<double>(dim2::Point<double>(0,0)); |
| 761 | 761 |
} |
| 762 |
|
|
| 762 |
|
|
| 763 | 763 |
if(_scaleToA4) |
| 764 | 764 |
os <<"%%BoundingBox: 0 0 596 842\n%%DocumentPaperSizes: a4\n"; |
| 765 | 765 |
else {
|
| 766 | 766 |
if(_preScale) {
|
| 767 |
//Rescale so that BoundingBox won't be neither to big nor too small. |
|
| 768 |
while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10; |
|
| 769 |
|
|
| 767 |
//Rescale so that BoundingBox won't be neither to big nor too small. |
|
| 768 |
while(bb.height()*_scale>1000||bb.width()*_scale>1000) _scale/=10; |
|
| 769 |
while(bb.height()*_scale<100||bb.width()*_scale<100) _scale*=10; |
|
| 770 | 770 |
} |
| 771 |
|
|
| 771 |
|
|
| 772 | 772 |
os << "%%BoundingBox: " |
| 773 |
<< int(floor(bb.left() * _scale - _xBorder)) << ' ' |
|
| 774 |
<< int(floor(bb.bottom() * _scale - _yBorder)) << ' ' |
|
| 775 |
<< int(ceil(bb.right() * _scale + _xBorder)) << ' ' |
|
| 776 |
<< int(ceil(bb.top() * _scale + _yBorder)) << '\n'; |
|
| 773 |
<< int(floor(bb.left() * _scale - _xBorder)) << ' ' |
|
| 774 |
<< int(floor(bb.bottom() * _scale - _yBorder)) << ' ' |
|
| 775 |
<< int(ceil(bb.right() * _scale + _xBorder)) << ' ' |
|
| 776 |
<< int(ceil(bb.top() * _scale + _yBorder)) << '\n'; |
|
| 777 | 777 |
} |
| 778 |
|
|
| 778 |
|
|
| 779 | 779 |
os << "%%EndComments\n"; |
| 780 |
|
|
| 780 |
|
|
| 781 | 781 |
//x1 y1 x2 y2 x3 y3 cr cg cb w |
| 782 | 782 |
os << "/lb { setlinewidth setrgbcolor newpath moveto\n"
|
| 783 | 783 |
<< " 4 2 roll 1 index 1 index curveto stroke } bind def\n"; |
| 784 | 784 |
os << "/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def\n";
|
| 785 | 785 |
//x y r |
| 786 | 786 |
os << "/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def\n";
|
| 787 | 787 |
//x y r |
| 788 | 788 |
os << "/sq { newpath 2 index 1 index add 2 index 2 index add moveto\n"
|
| 789 | 789 |
<< " 2 index 1 index sub 2 index 2 index add lineto\n" |
| 790 | 790 |
<< " 2 index 1 index sub 2 index 2 index sub lineto\n" |
| 791 | 791 |
<< " 2 index 1 index add 2 index 2 index sub lineto\n" |
| 792 | 792 |
<< " closepath pop pop pop} bind def\n"; |
| 793 | 793 |
//x y r |
| 794 | 794 |
os << "/di { newpath 2 index 1 index add 2 index moveto\n"
|
| 795 | 795 |
<< " 2 index 2 index 2 index add lineto\n" |
| 796 | 796 |
<< " 2 index 1 index sub 2 index lineto\n" |
| ... | ... |
@@ -818,303 +818,303 @@ |
| 818 | 818 |
<< " } bind def\n"; |
| 819 | 819 |
os << "/nmale {\n"
|
| 820 | 820 |
<< " 0 0 0 setrgbcolor 3 index " |
| 821 | 821 |
<< _nodeBorderQuotient/(1+_nodeBorderQuotient) |
| 822 | 822 |
<<" 1.5 mul mul setlinewidth\n" |
| 823 | 823 |
<< " newpath 5 index 5 index moveto\n" |
| 824 | 824 |
<< " 5 index 4 index 1 mul 1.5 mul add\n" |
| 825 | 825 |
<< " 5 index 5 index 3 sqrt 1.5 mul mul add\n" |
| 826 | 826 |
<< " 1 index 1 index lineto\n" |
| 827 | 827 |
<< " 1 index 1 index 7 index sub moveto\n" |
| 828 | 828 |
<< " 1 index 1 index lineto\n" |
| 829 | 829 |
<< " exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto\n" |
| 830 | 830 |
<< " stroke\n" |
| 831 | 831 |
<< " 5 index 5 index 5 index c fill\n" |
| 832 | 832 |
<< " setrgbcolor " << 1+_nodeBorderQuotient << " div c fill\n" |
| 833 | 833 |
<< " } bind def\n"; |
| 834 |
|
|
| 834 |
|
|
| 835 | 835 |
|
| 836 | 836 |
os << "/arrl " << _arrowLength << " def\n"; |
| 837 | 837 |
os << "/arrw " << _arrowWidth << " def\n"; |
| 838 | 838 |
// l dx_norm dy_norm |
| 839 | 839 |
os << "/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def\n";
|
| 840 | 840 |
//len w dx_norm dy_norm x1 y1 cr cg cb |
| 841 | 841 |
os << "/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def\n"
|
| 842 | 842 |
<< " /w exch def /len exch def\n" |
| 843 |
// |
|
| 843 |
// << " 0.1 setlinewidth x1 y1 moveto dx len mul dy len mul rlineto stroke" |
|
| 844 | 844 |
<< " newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto\n" |
| 845 | 845 |
<< " len w sub arrl sub dx dy lrl\n" |
| 846 | 846 |
<< " arrw dy dx neg lrl\n" |
| 847 | 847 |
<< " dx arrl w add mul dy w 2 div arrw add mul sub\n" |
| 848 | 848 |
<< " dy arrl w add mul dx w 2 div arrw add mul add rlineto\n" |
| 849 | 849 |
<< " dx arrl w add mul neg dy w 2 div arrw add mul sub\n" |
| 850 | 850 |
<< " dy arrl w add mul neg dx w 2 div arrw add mul add rlineto\n" |
| 851 | 851 |
<< " arrw dy dx neg lrl\n" |
| 852 | 852 |
<< " len w sub arrl sub neg dx dy lrl\n" |
| 853 | 853 |
<< " closepath fill } bind def\n"; |
| 854 | 854 |
os << "/cshow { 2 index 2 index moveto dup stringwidth pop\n"
|
| 855 | 855 |
<< " neg 2 div fosi .35 mul neg rmoveto show pop pop} def\n"; |
| 856 | 856 |
|
| 857 | 857 |
os << "\ngsave\n"; |
| 858 | 858 |
if(_scaleToA4) |
| 859 | 859 |
if(bb.height()>bb.width()) {
|
| 860 |
double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(), |
|
| 861 |
(A4WIDTH-2*A4BORDER)/bb.width()); |
|
| 862 |
os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' ' |
|
| 863 |
<< ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER |
|
| 864 |
<< " translate\n" |
|
| 865 |
<< sc << " dup scale\n" |
|
| 866 |
|
|
| 860 |
double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.height(), |
|
| 861 |
(A4WIDTH-2*A4BORDER)/bb.width()); |
|
| 862 |
os << ((A4WIDTH -2*A4BORDER)-sc*bb.width())/2 + A4BORDER << ' ' |
|
| 863 |
<< ((A4HEIGHT-2*A4BORDER)-sc*bb.height())/2 + A4BORDER |
|
| 864 |
<< " translate\n" |
|
| 865 |
<< sc << " dup scale\n" |
|
| 866 |
<< -bb.left() << ' ' << -bb.bottom() << " translate\n"; |
|
| 867 | 867 |
} |
| 868 | 868 |
else {
|
| 869 |
//\todo Verify centering |
|
| 870 |
double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(), |
|
| 871 |
(A4WIDTH-2*A4BORDER)/bb.height()); |
|
| 872 |
os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' ' |
|
| 873 |
<< ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER |
|
| 874 |
<< " translate\n" |
|
| 875 |
<< sc << " dup scale\n90 rotate\n" |
|
| 876 |
<< -bb.left() << ' ' << -bb.top() << " translate\n"; |
|
| 877 |
|
|
| 869 |
//\todo Verify centering |
|
| 870 |
double sc= std::min((A4HEIGHT-2*A4BORDER)/bb.width(), |
|
| 871 |
(A4WIDTH-2*A4BORDER)/bb.height()); |
|
| 872 |
os << ((A4WIDTH -2*A4BORDER)-sc*bb.height())/2 + A4BORDER << ' ' |
|
| 873 |
<< ((A4HEIGHT-2*A4BORDER)-sc*bb.width())/2 + A4BORDER |
|
| 874 |
<< " translate\n" |
|
| 875 |
<< sc << " dup scale\n90 rotate\n" |
|
| 876 |
<< -bb.left() << ' ' << -bb.top() << " translate\n"; |
|
| 877 |
} |
|
| 878 | 878 |
else if(_scale!=1.0) os << _scale << " dup scale\n"; |
| 879 |
|
|
| 879 |
|
|
| 880 | 880 |
if(_showArcs) {
|
| 881 |
os << "%Arcs:\ngsave\n"; |
|
| 881 |
os << "%Arcs:\ngsave\n"; |
|
| 882 | 882 |
if(_enableParallel) {
|
| 883 |
std::vector<Arc> el; |
|
| 884 |
for(ArcIt e(g);e!=INVALID;++e) |
|
| 885 |
if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 |
|
| 886 |
&&g.source(e)!=g.target(e)) |
|
| 887 |
el.push_back(e); |
|
| 888 |
std::sort(el.begin(),el.end(),arcLess(g)); |
|
| 889 |
|
|
| 890 |
typename std::vector<Arc>::iterator j; |
|
| 891 |
for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
|
|
| 892 |
for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; |
|
| 883 |
std::vector<Arc> el; |
|
| 884 |
for(ArcIt e(g);e!=INVALID;++e) |
|
| 885 |
if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 |
|
| 886 |
&&g.source(e)!=g.target(e)) |
|
| 887 |
el.push_back(e); |
|
| 888 |
std::sort(el.begin(),el.end(),arcLess(g)); |
|
| 893 | 889 |
|
| 894 |
double sw=0; |
|
| 895 |
for(typename std::vector<Arc>::iterator e=i;e!=j;++e) |
|
| 896 |
sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist; |
|
| 897 |
sw-=_parArcDist; |
|
| 898 |
sw/=-2.0; |
|
| 899 |
dim2::Point<double> |
|
| 900 |
dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); |
|
| 901 |
double l=std::sqrt(dvec.normSquare()); |
|
| 902 |
//\todo better 'epsilon' would be nice here. |
|
| 903 |
dim2::Point<double> d(dvec/std::max(l,EPSILON)); |
|
| 904 |
dim2::Point<double> m; |
|
| 905 |
// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0; |
|
| 890 |
typename std::vector<Arc>::iterator j; |
|
| 891 |
for(typename std::vector<Arc>::iterator i=el.begin();i!=el.end();i=j) {
|
|
| 892 |
for(j=i+1;j!=el.end()&&isParallel(*i,*j);++j) ; |
|
| 906 | 893 |
|
| 907 |
// m=dim2::Point<double>(mycoords[g.source(*i)])+ |
|
| 908 |
// dvec*(double(_nodeSizes[g.source(*i)])/ |
|
| 909 |
|
|
| 894 |
double sw=0; |
|
| 895 |
for(typename std::vector<Arc>::iterator e=i;e!=j;++e) |
|
| 896 |
sw+=_arcWidths[*e]*_arcWidthScale+_parArcDist; |
|
| 897 |
sw-=_parArcDist; |
|
| 898 |
sw/=-2.0; |
|
| 899 |
dim2::Point<double> |
|
| 900 |
dvec(mycoords[g.target(*i)]-mycoords[g.source(*i)]); |
|
| 901 |
double l=std::sqrt(dvec.normSquare()); |
|
| 902 |
//\todo better 'epsilon' would be nice here. |
|
| 903 |
dim2::Point<double> d(dvec/std::max(l,EPSILON)); |
|
| 904 |
dim2::Point<double> m; |
|
| 905 |
// m=dim2::Point<double>(mycoords[g.target(*i)]+mycoords[g.source(*i)])/2.0; |
|
| 910 | 906 |
|
| 911 |
m=dim2::Point<double>(mycoords[g.source(*i)])+ |
|
| 912 |
d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0; |
|
| 907 |
// m=dim2::Point<double>(mycoords[g.source(*i)])+ |
|
| 908 |
// dvec*(double(_nodeSizes[g.source(*i)])/ |
|
| 909 |
// (_nodeSizes[g.source(*i)]+_nodeSizes[g.target(*i)])); |
|
| 913 | 910 |
|
| 914 |
for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
|
|
| 915 |
sw+=_arcWidths[*e]*_arcWidthScale/2.0; |
|
| 916 |
dim2::Point<double> mm=m+rot90(d)*sw/.75; |
|
| 917 |
if(_drawArrows) {
|
|
| 918 |
int node_shape; |
|
| 919 |
dim2::Point<double> s=mycoords[g.source(*e)]; |
|
| 920 |
dim2::Point<double> t=mycoords[g.target(*e)]; |
|
| 921 |
double rn=_nodeSizes[g.target(*e)]*_nodeScale; |
|
| 922 |
node_shape=_nodeShapes[g.target(*e)]; |
|
| 923 |
dim2::Bezier3 bez(s,mm,mm,t); |
|
| 924 |
double t1=0,t2=1; |
|
| 925 |
for(int ii=0;ii<INTERPOL_PREC;++ii) |
|
| 926 |
if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2; |
|
| 927 |
else t1=(t1+t2)/2; |
|
| 928 |
dim2::Point<double> apoint=bez((t1+t2)/2); |
|
| 929 |
rn = _arrowLength+_arcWidths[*e]*_arcWidthScale; |
|
| 930 |
rn*=rn; |
|
| 931 |
t2=(t1+t2)/2;t1=0; |
|
| 932 |
for(int ii=0;ii<INTERPOL_PREC;++ii) |
|
| 933 |
if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2; |
|
| 934 |
else t2=(t1+t2)/2; |
|
| 935 |
dim2::Point<double> linend=bez((t1+t2)/2); |
|
| 936 |
bez=bez.before((t1+t2)/2); |
|
| 937 |
// rn=_nodeSizes[g.source(*e)]*_nodeScale; |
|
| 938 |
// node_shape=_nodeShapes[g.source(*e)]; |
|
| 939 |
// t1=0;t2=1; |
|
| 940 |
// for(int i=0;i<INTERPOL_PREC;++i) |
|
| 941 |
// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2; |
|
| 942 |
// else t2=(t1+t2)/2; |
|
| 943 |
// bez=bez.after((t1+t2)/2); |
|
| 944 |
os << _arcWidths[*e]*_arcWidthScale << " setlinewidth " |
|
| 945 |
<< _arcColors[*e].red() << ' ' |
|
| 946 |
<< _arcColors[*e].green() << ' ' |
|
| 947 |
<< _arcColors[*e].blue() << " setrgbcolor newpath\n" |
|
| 948 |
<< bez.p1.x << ' ' << bez.p1.y << " moveto\n" |
|
| 949 |
<< bez.p2.x << ' ' << bez.p2.y << ' ' |
|
| 950 |
<< bez.p3.x << ' ' << bez.p3.y << ' ' |
|
| 951 |
<< bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n"; |
|
| 952 |
dim2::Point<double> dd(rot90(linend-apoint)); |
|
| 953 |
dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/ |
|
| 954 |
std::sqrt(dd.normSquare()); |
|
| 955 |
os << "newpath " << psOut(apoint) << " moveto " |
|
| 956 |
<< psOut(linend+dd) << " lineto " |
|
| 957 |
<< psOut(linend-dd) << " lineto closepath fill\n"; |
|
| 958 |
} |
|
| 959 |
else {
|
|
| 960 |
os << mycoords[g.source(*e)].x << ' ' |
|
| 961 |
<< mycoords[g.source(*e)].y << ' ' |
|
| 962 |
<< mm.x << ' ' << mm.y << ' ' |
|
| 963 |
<< mycoords[g.target(*e)].x << ' ' |
|
| 964 |
<< mycoords[g.target(*e)].y << ' ' |
|
| 965 |
<< _arcColors[*e].red() << ' ' |
|
| 966 |
<< _arcColors[*e].green() << ' ' |
|
| 967 |
<< _arcColors[*e].blue() << ' ' |
|
| 968 |
<< _arcWidths[*e]*_arcWidthScale << " lb\n"; |
|
| 969 |
} |
|
| 970 |
sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist; |
|
| 971 |
} |
|
| 972 |
|
|
| 911 |
m=dim2::Point<double>(mycoords[g.source(*i)])+ |
|
| 912 |
d*(l+_nodeSizes[g.source(*i)]-_nodeSizes[g.target(*i)])/2.0; |
|
| 913 |
|
|
| 914 |
for(typename std::vector<Arc>::iterator e=i;e!=j;++e) {
|
|
| 915 |
sw+=_arcWidths[*e]*_arcWidthScale/2.0; |
|
| 916 |
dim2::Point<double> mm=m+rot90(d)*sw/.75; |
|
| 917 |
if(_drawArrows) {
|
|
| 918 |
int node_shape; |
|
| 919 |
dim2::Point<double> s=mycoords[g.source(*e)]; |
|
| 920 |
dim2::Point<double> t=mycoords[g.target(*e)]; |
|
| 921 |
double rn=_nodeSizes[g.target(*e)]*_nodeScale; |
|
| 922 |
node_shape=_nodeShapes[g.target(*e)]; |
|
| 923 |
dim2::Bezier3 bez(s,mm,mm,t); |
|
| 924 |
double t1=0,t2=1; |
|
| 925 |
for(int ii=0;ii<INTERPOL_PREC;++ii) |
|
| 926 |
if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t2=(t1+t2)/2; |
|
| 927 |
else t1=(t1+t2)/2; |
|
| 928 |
dim2::Point<double> apoint=bez((t1+t2)/2); |
|
| 929 |
rn = _arrowLength+_arcWidths[*e]*_arcWidthScale; |
|
| 930 |
rn*=rn; |
|
| 931 |
t2=(t1+t2)/2;t1=0; |
|
| 932 |
for(int ii=0;ii<INTERPOL_PREC;++ii) |
|
| 933 |
if((bez((t1+t2)/2)-apoint).normSquare()>rn) t1=(t1+t2)/2; |
|
| 934 |
else t2=(t1+t2)/2; |
|
| 935 |
dim2::Point<double> linend=bez((t1+t2)/2); |
|
| 936 |
bez=bez.before((t1+t2)/2); |
|
| 937 |
// rn=_nodeSizes[g.source(*e)]*_nodeScale; |
|
| 938 |
// node_shape=_nodeShapes[g.source(*e)]; |
|
| 939 |
// t1=0;t2=1; |
|
| 940 |
// for(int i=0;i<INTERPOL_PREC;++i) |
|
| 941 |
// if(isInsideNode(bez((t1+t2)/2)-t,rn,node_shape)) t1=(t1+t2)/2; |
|
| 942 |
// else t2=(t1+t2)/2; |
|
| 943 |
// bez=bez.after((t1+t2)/2); |
|
| 944 |
os << _arcWidths[*e]*_arcWidthScale << " setlinewidth " |
|
| 945 |
<< _arcColors[*e].red() << ' ' |
|
| 946 |
<< _arcColors[*e].green() << ' ' |
|
| 947 |
<< _arcColors[*e].blue() << " setrgbcolor newpath\n" |
|
| 948 |
<< bez.p1.x << ' ' << bez.p1.y << " moveto\n" |
|
| 949 |
<< bez.p2.x << ' ' << bez.p2.y << ' ' |
|
| 950 |
<< bez.p3.x << ' ' << bez.p3.y << ' ' |
|
| 951 |
<< bez.p4.x << ' ' << bez.p4.y << " curveto stroke\n"; |
|
| 952 |
dim2::Point<double> dd(rot90(linend-apoint)); |
|
| 953 |
dd*=(.5*_arcWidths[*e]*_arcWidthScale+_arrowWidth)/ |
|
| 954 |
std::sqrt(dd.normSquare()); |
|
| 955 |
os << "newpath " << psOut(apoint) << " moveto " |
|
| 956 |
<< psOut(linend+dd) << " lineto " |
|
| 957 |
<< psOut(linend-dd) << " lineto closepath fill\n"; |
|
| 958 |
} |
|
| 959 |
else {
|
|
| 960 |
os << mycoords[g.source(*e)].x << ' ' |
|
| 961 |
<< mycoords[g.source(*e)].y << ' ' |
|
| 962 |
<< mm.x << ' ' << mm.y << ' ' |
|
| 963 |
<< mycoords[g.target(*e)].x << ' ' |
|
| 964 |
<< mycoords[g.target(*e)].y << ' ' |
|
| 965 |
<< _arcColors[*e].red() << ' ' |
|
| 966 |
<< _arcColors[*e].green() << ' ' |
|
| 967 |
<< _arcColors[*e].blue() << ' ' |
|
| 968 |
<< _arcWidths[*e]*_arcWidthScale << " lb\n"; |
|
| 969 |
} |
|
| 970 |
sw+=_arcWidths[*e]*_arcWidthScale/2.0+_parArcDist; |
|
| 971 |
} |
|
| 972 |
} |
|
| 973 | 973 |
} |
| 974 | 974 |
else for(ArcIt e(g);e!=INVALID;++e) |
| 975 |
if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 |
|
| 976 |
&&g.source(e)!=g.target(e)) {
|
|
| 977 |
if(_drawArrows) {
|
|
| 978 |
dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]); |
|
| 979 |
double rn=_nodeSizes[g.target(e)]*_nodeScale; |
|
| 980 |
int node_shape=_nodeShapes[g.target(e)]; |
|
| 981 |
double t1=0,t2=1; |
|
| 982 |
for(int i=0;i<INTERPOL_PREC;++i) |
|
| 983 |
if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2; |
|
| 984 |
else t2=(t1+t2)/2; |
|
| 985 |
double l=std::sqrt(d.normSquare()); |
|
| 986 |
d/=l; |
|
| 987 |
|
|
| 988 |
os << l*(1-(t1+t2)/2) << ' ' |
|
| 989 |
<< _arcWidths[e]*_arcWidthScale << ' ' |
|
| 990 |
<< d.x << ' ' << d.y << ' ' |
|
| 991 |
<< mycoords[g.source(e)].x << ' ' |
|
| 992 |
<< mycoords[g.source(e)].y << ' ' |
|
| 993 |
<< _arcColors[e].red() << ' ' |
|
| 994 |
<< _arcColors[e].green() << ' ' |
|
| 995 |
<< _arcColors[e].blue() << " arr\n"; |
|
| 996 |
} |
|
| 997 |
else os << mycoords[g.source(e)].x << ' ' |
|
| 998 |
<< mycoords[g.source(e)].y << ' ' |
|
| 999 |
<< mycoords[g.target(e)].x << ' ' |
|
| 1000 |
<< mycoords[g.target(e)].y << ' ' |
|
| 1001 |
<< _arcColors[e].red() << ' ' |
|
| 1002 |
<< _arcColors[e].green() << ' ' |
|
| 1003 |
<< _arcColors[e].blue() << ' ' |
|
| 1004 |
<< _arcWidths[e]*_arcWidthScale << " l\n"; |
|
| 1005 |
|
|
| 975 |
if((!_undirected||g.source(e)<g.target(e))&&_arcWidths[e]>0 |
|
| 976 |
&&g.source(e)!=g.target(e)) {
|
|
| 977 |
if(_drawArrows) {
|
|
| 978 |
dim2::Point<double> d(mycoords[g.target(e)]-mycoords[g.source(e)]); |
|
| 979 |
double rn=_nodeSizes[g.target(e)]*_nodeScale; |
|
| 980 |
int node_shape=_nodeShapes[g.target(e)]; |
|
| 981 |
double t1=0,t2=1; |
|
| 982 |
for(int i=0;i<INTERPOL_PREC;++i) |
|
| 983 |
if(isInsideNode((-(t1+t2)/2)*d,rn,node_shape)) t1=(t1+t2)/2; |
|
| 984 |
else t2=(t1+t2)/2; |
|
| 985 |
double l=std::sqrt(d.normSquare()); |
|
| 986 |
d/=l; |
|
| 987 |
|
|
| 988 |
os << l*(1-(t1+t2)/2) << ' ' |
|
| 989 |
<< _arcWidths[e]*_arcWidthScale << ' ' |
|
| 990 |
<< d.x << ' ' << d.y << ' ' |
|
| 991 |
<< mycoords[g.source(e)].x << ' ' |
|
| 992 |
<< mycoords[g.source(e)].y << ' ' |
|
| 993 |
<< _arcColors[e].red() << ' ' |
|
| 994 |
<< _arcColors[e].green() << ' ' |
|
| 995 |
<< _arcColors[e].blue() << " arr\n"; |
|
| 996 |
} |
|
| 997 |
else os << mycoords[g.source(e)].x << ' ' |
|
| 998 |
<< mycoords[g.source(e)].y << ' ' |
|
| 999 |
<< mycoords[g.target(e)].x << ' ' |
|
| 1000 |
<< mycoords[g.target(e)].y << ' ' |
|
| 1001 |
<< _arcColors[e].red() << ' ' |
|
| 1002 |
<< _arcColors[e].green() << ' ' |
|
| 1003 |
<< _arcColors[e].blue() << ' ' |
|
| 1004 |
<< _arcWidths[e]*_arcWidthScale << " l\n"; |
|
| 1005 |
} |
|
| 1006 | 1006 |
os << "grestore\n"; |
| 1007 | 1007 |
} |
| 1008 | 1008 |
if(_showNodes) {
|
| 1009 | 1009 |
os << "%Nodes:\ngsave\n"; |
| 1010 | 1010 |
for(NodeIt n(g);n!=INVALID;++n) {
|
| 1011 |
os << mycoords[n].x << ' ' << mycoords[n].y << ' ' |
|
| 1012 |
<< _nodeSizes[n]*_nodeScale << ' ' |
|
| 1013 |
<< _nodeColors[n].red() << ' ' |
|
| 1014 |
<< _nodeColors[n].green() << ' ' |
|
| 1015 |
<< _nodeColors[n].blue() << ' '; |
|
| 1016 |
switch(_nodeShapes[n]) {
|
|
| 1017 |
case CIRCLE: |
|
| 1018 |
os<< "nc";break; |
|
| 1019 |
case SQUARE: |
|
| 1020 |
os<< "nsq";break; |
|
| 1021 |
case DIAMOND: |
|
| 1022 |
os<< "ndi";break; |
|
| 1023 |
case MALE: |
|
| 1024 |
os<< "nmale";break; |
|
| 1025 |
case FEMALE: |
|
| 1026 |
os<< "nfemale";break; |
|
| 1027 |
} |
|
| 1028 |
os<<'\n'; |
|
| 1011 |
os << mycoords[n].x << ' ' << mycoords[n].y << ' ' |
|
| 1012 |
<< _nodeSizes[n]*_nodeScale << ' ' |
|
| 1013 |
<< _nodeColors[n].red() << ' ' |
|
| 1014 |
<< _nodeColors[n].green() << ' ' |
|
| 1015 |
<< _nodeColors[n].blue() << ' '; |
|
| 1016 |
switch(_nodeShapes[n]) {
|
|
| 1017 |
case CIRCLE: |
|
| 1018 |
os<< "nc";break; |
|
| 1019 |
case SQUARE: |
|
| 1020 |
os<< "nsq";break; |
|
| 1021 |
case DIAMOND: |
|
| 1022 |
os<< "ndi";break; |
|
| 1023 |
case MALE: |
|
| 1024 |
os<< "nmale";break; |
|
| 1025 |
case FEMALE: |
|
| 1026 |
os<< "nfemale";break; |
|
| 1027 |
} |
|
| 1028 |
os<<'\n'; |
|
| 1029 | 1029 |
} |
| 1030 | 1030 |
os << "grestore\n"; |
| 1031 | 1031 |
} |
| 1032 | 1032 |
if(_showNodeText) {
|
| 1033 | 1033 |
os << "%Node texts:\ngsave\n"; |
| 1034 | 1034 |
os << "/fosi " << _nodeTextSize << " def\n"; |
| 1035 | 1035 |
os << "(Helvetica) findfont fosi scalefont setfont\n"; |
| 1036 | 1036 |
for(NodeIt n(g);n!=INVALID;++n) {
|
| 1037 |
switch(_nodeTextColorType) {
|
|
| 1038 |
case DIST_COL: |
|
| 1039 |
os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n"; |
|
| 1040 |
break; |
|
| 1041 |
case DIST_BW: |
|
| 1042 |
os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n"; |
|
| 1043 |
break; |
|
| 1044 |
case CUST_COL: |
|
| 1045 |
os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n"; |
|
| 1046 |
break; |
|
| 1047 |
default: |
|
| 1048 |
os << "0 0 0 setrgbcolor\n"; |
|
| 1049 |
} |
|
| 1050 |
os << mycoords[n].x << ' ' << mycoords[n].y |
|
| 1051 |
|
|
| 1037 |
switch(_nodeTextColorType) {
|
|
| 1038 |
case DIST_COL: |
|
| 1039 |
os << psOut(distantColor(_nodeColors[n])) << " setrgbcolor\n"; |
|
| 1040 |
break; |
|
| 1041 |
case DIST_BW: |
|
| 1042 |
os << psOut(distantBW(_nodeColors[n])) << " setrgbcolor\n"; |
|
| 1043 |
break; |
|
| 1044 |
case CUST_COL: |
|
| 1045 |
os << psOut(distantColor(_nodeTextColors[n])) << " setrgbcolor\n"; |
|
| 1046 |
break; |
|
| 1047 |
default: |
|
| 1048 |
os << "0 0 0 setrgbcolor\n"; |
|
| 1049 |
} |
|
| 1050 |
os << mycoords[n].x << ' ' << mycoords[n].y |
|
| 1051 |
<< " (" << _nodeTexts[n] << ") cshow\n";
|
|
| 1052 | 1052 |
} |
| 1053 | 1053 |
os << "grestore\n"; |
| 1054 | 1054 |
} |
| 1055 | 1055 |
if(_showNodePsText) {
|
| 1056 | 1056 |
os << "%Node PS blocks:\ngsave\n"; |
| 1057 | 1057 |
for(NodeIt n(g);n!=INVALID;++n) |
| 1058 |
os << mycoords[n].x << ' ' << mycoords[n].y |
|
| 1059 |
<< " moveto\n" << _nodePsTexts[n] << "\n"; |
|
| 1058 |
os << mycoords[n].x << ' ' << mycoords[n].y |
|
| 1059 |
<< " moveto\n" << _nodePsTexts[n] << "\n"; |
|
| 1060 | 1060 |
os << "grestore\n"; |
| 1061 | 1061 |
} |
| 1062 |
|
|
| 1062 |
|
|
| 1063 | 1063 |
os << "grestore\nshowpage\n"; |
| 1064 | 1064 |
|
| 1065 | 1065 |
//CleanUp: |
| 1066 | 1066 |
if(_pleaseRemoveOsStream) {delete &os;}
|
| 1067 | 1067 |
} |
| 1068 | 1068 |
|
| 1069 | 1069 |
///\name Aliases |
| 1070 | 1070 |
///These are just some aliases to other parameter setting functions. |
| 1071 | 1071 |
|
| 1072 | 1072 |
///@{
|
| 1073 | 1073 |
|
| 1074 | 1074 |
///An alias for arcWidths() |
| 1075 | 1075 |
template<class X> GraphToEps<ArcWidthsTraits<X> > edgeWidths(const X &x) |
| 1076 | 1076 |
{
|
| 1077 | 1077 |
return arcWidths(x); |
| 1078 | 1078 |
} |
| 1079 | 1079 |
|
| 1080 | 1080 |
///An alias for arcColors() |
| 1081 | 1081 |
template<class X> GraphToEps<ArcColorsTraits<X> > |
| 1082 | 1082 |
edgeColors(const X &x) |
| 1083 | 1083 |
{
|
| 1084 | 1084 |
return arcColors(x); |
| 1085 | 1085 |
} |
| 1086 | 1086 |
|
| 1087 | 1087 |
///An alias for arcWidthScale() |
| 1088 | 1088 |
GraphToEps<T> &edgeWidthScale(double d) {return arcWidthScale(d);}
|
| 1089 | 1089 |
|
| 1090 | 1090 |
///An alias for autoArcWidthScale() |
| 1091 | 1091 |
GraphToEps<T> &autoEdgeWidthScale(bool b=true) |
| 1092 | 1092 |
{
|
| 1093 | 1093 |
return autoArcWidthScale(b); |
| 1094 | 1094 |
} |
| 1095 |
|
|
| 1095 |
|
|
| 1096 | 1096 |
///An alias for absoluteArcWidths() |
| 1097 | 1097 |
GraphToEps<T> &absoluteEdgeWidths(bool b=true) |
| 1098 | 1098 |
{
|
| 1099 | 1099 |
return absoluteArcWidths(b); |
| 1100 | 1100 |
} |
| 1101 |
|
|
| 1101 |
|
|
| 1102 | 1102 |
///An alias for parArcDist() |
| 1103 | 1103 |
GraphToEps<T> &parEdgeDist(double d) {return parArcDist(d);}
|
| 1104 |
|
|
| 1104 |
|
|
| 1105 | 1105 |
///An alias for hideArcs() |
| 1106 | 1106 |
GraphToEps<T> &hideEdges(bool b=true) {return hideArcs(b);}
|
| 1107 | 1107 |
|
| 1108 | 1108 |
///@} |
| 1109 | 1109 |
}; |
| 1110 | 1110 |
|
| 1111 | 1111 |
template<class T> |
| 1112 | 1112 |
const int GraphToEps<T>::INTERPOL_PREC = 20; |
| 1113 | 1113 |
template<class T> |
| 1114 | 1114 |
const double GraphToEps<T>::A4HEIGHT = 841.8897637795276; |
| 1115 | 1115 |
template<class T> |
| 1116 | 1116 |
const double GraphToEps<T>::A4WIDTH = 595.275590551181; |
| 1117 | 1117 |
template<class T> |
| 1118 | 1118 |
const double GraphToEps<T>::A4BORDER = 15; |
| 1119 | 1119 |
|
| 1120 | 1120 |
|
| ... | ... |
@@ -1130,58 +1130,58 @@ |
| 1130 | 1130 |
///\ref named-templ-func-param "named parameters", |
| 1131 | 1131 |
///they are declared as the members of class \ref GraphToEps. The following |
| 1132 | 1132 |
///example shows how to use these parameters. |
| 1133 | 1133 |
///\code |
| 1134 | 1134 |
/// graphToEps(g,os).scale(10).coords(coords) |
| 1135 | 1135 |
/// .nodeScale(2).nodeSizes(sizes) |
| 1136 | 1136 |
/// .arcWidthScale(.4).run(); |
| 1137 | 1137 |
///\endcode |
| 1138 | 1138 |
/// |
| 1139 | 1139 |
///For more detailed examples see the \ref graph_to_eps_demo.cc demo file. |
| 1140 | 1140 |
/// |
| 1141 | 1141 |
///\warning Don't forget to put the \ref GraphToEps::run() "run()" |
| 1142 | 1142 |
///to the end of the parameter list. |
| 1143 | 1143 |
///\sa GraphToEps |
| 1144 | 1144 |
///\sa graphToEps(G &g, const char *file_name) |
| 1145 | 1145 |
template<class G> |
| 1146 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1146 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1147 | 1147 |
graphToEps(G &g, std::ostream& os=std::cout) |
| 1148 | 1148 |
{
|
| 1149 |
return |
|
| 1149 |
return |
|
| 1150 | 1150 |
GraphToEps<DefaultGraphToEpsTraits<G> >(DefaultGraphToEpsTraits<G>(g,os)); |
| 1151 | 1151 |
} |
| 1152 |
|
|
| 1152 |
|
|
| 1153 | 1153 |
///Generates an EPS file from a graph |
| 1154 | 1154 |
|
| 1155 | 1155 |
///\ingroup eps_io |
| 1156 | 1156 |
///This function does the same as |
| 1157 | 1157 |
///\ref graphToEps(G &g,std::ostream& os) |
| 1158 | 1158 |
///but it writes its output into the file \c file_name |
| 1159 | 1159 |
///instead of a stream. |
| 1160 | 1160 |
///\sa graphToEps(G &g, std::ostream& os) |
| 1161 | 1161 |
template<class G> |
| 1162 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1162 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1163 | 1163 |
graphToEps(G &g,const char *file_name) |
| 1164 | 1164 |
{
|
| 1165 | 1165 |
return GraphToEps<DefaultGraphToEpsTraits<G> > |
| 1166 | 1166 |
(DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name),true)); |
| 1167 | 1167 |
} |
| 1168 | 1168 |
|
| 1169 | 1169 |
///Generates an EPS file from a graph |
| 1170 | 1170 |
|
| 1171 | 1171 |
///\ingroup eps_io |
| 1172 | 1172 |
///This function does the same as |
| 1173 | 1173 |
///\ref graphToEps(G &g,std::ostream& os) |
| 1174 | 1174 |
///but it writes its output into the file \c file_name |
| 1175 | 1175 |
///instead of a stream. |
| 1176 | 1176 |
///\sa graphToEps(G &g, std::ostream& os) |
| 1177 | 1177 |
template<class G> |
| 1178 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1178 |
GraphToEps<DefaultGraphToEpsTraits<G> > |
|
| 1179 | 1179 |
graphToEps(G &g,const std::string& file_name) |
| 1180 | 1180 |
{
|
| 1181 | 1181 |
return GraphToEps<DefaultGraphToEpsTraits<G> > |
| 1182 | 1182 |
(DefaultGraphToEpsTraits<G>(g,*new std::ofstream(file_name.c_str()),true)); |
| 1183 | 1183 |
} |
| 1184 | 1184 |
|
| 1185 | 1185 |
} //END OF NAMESPACE LEMON |
| 1186 | 1186 |
|
| 1187 | 1187 |
#endif // LEMON_GRAPH_TO_EPS_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_GRAPH_UTILS_H |
| ... | ... |
@@ -33,378 +33,378 @@ |
| 33 | 33 |
#include <lemon/bits/alteration_notifier.h> |
| 34 | 34 |
#include <lemon/bits/default_map.h> |
| 35 | 35 |
|
| 36 | 36 |
///\ingroup gutils |
| 37 | 37 |
///\file |
| 38 | 38 |
///\brief Graph utilities. |
| 39 | 39 |
|
| 40 | 40 |
namespace lemon {
|
| 41 | 41 |
|
| 42 | 42 |
/// \addtogroup gutils |
| 43 | 43 |
/// @{
|
| 44 | 44 |
|
| 45 | 45 |
///Creates convenience typedefs for the digraph types and iterators |
| 46 | 46 |
|
| 47 | 47 |
///This \c \#define creates convenience typedefs for the following types |
| 48 | 48 |
///of \c Digraph: \c Node, \c NodeIt, \c Arc, \c ArcIt, \c InArcIt, |
| 49 |
///\c OutArcIt, \c BoolNodeMap, \c IntNodeMap, \c DoubleNodeMap, |
|
| 49 |
///\c OutArcIt, \c BoolNodeMap, \c IntNodeMap, \c DoubleNodeMap, |
|
| 50 | 50 |
///\c BoolArcMap, \c IntArcMap, \c DoubleArcMap. |
| 51 | 51 |
/// |
| 52 | 52 |
///\note If the graph type is a dependent type, ie. the graph type depend |
| 53 | 53 |
///on a template parameter, then use \c TEMPLATE_DIGRAPH_TYPEDEFS() |
| 54 | 54 |
///macro. |
| 55 |
#define DIGRAPH_TYPEDEFS(Digraph) \ |
|
| 56 |
typedef Digraph::Node Node; \ |
|
| 57 |
typedef Digraph::NodeIt NodeIt; \ |
|
| 58 |
typedef Digraph::Arc Arc; \ |
|
| 59 |
typedef Digraph::ArcIt ArcIt; \ |
|
| 60 |
typedef Digraph::InArcIt InArcIt; \ |
|
| 61 |
typedef Digraph::OutArcIt OutArcIt; \ |
|
| 62 |
typedef Digraph::NodeMap<bool> BoolNodeMap; \ |
|
| 63 |
typedef Digraph::NodeMap<int> IntNodeMap; \ |
|
| 64 |
typedef Digraph::NodeMap<double> DoubleNodeMap; \ |
|
| 65 |
typedef Digraph::ArcMap<bool> BoolArcMap; \ |
|
| 66 |
typedef Digraph::ArcMap<int> IntArcMap; \ |
|
| 55 |
#define DIGRAPH_TYPEDEFS(Digraph) \ |
|
| 56 |
typedef Digraph::Node Node; \ |
|
| 57 |
typedef Digraph::NodeIt NodeIt; \ |
|
| 58 |
typedef Digraph::Arc Arc; \ |
|
| 59 |
typedef Digraph::ArcIt ArcIt; \ |
|
| 60 |
typedef Digraph::InArcIt InArcIt; \ |
|
| 61 |
typedef Digraph::OutArcIt OutArcIt; \ |
|
| 62 |
typedef Digraph::NodeMap<bool> BoolNodeMap; \ |
|
| 63 |
typedef Digraph::NodeMap<int> IntNodeMap; \ |
|
| 64 |
typedef Digraph::NodeMap<double> DoubleNodeMap; \ |
|
| 65 |
typedef Digraph::ArcMap<bool> BoolArcMap; \ |
|
| 66 |
typedef Digraph::ArcMap<int> IntArcMap; \ |
|
| 67 | 67 |
typedef Digraph::ArcMap<double> DoubleArcMap |
| 68 | 68 |
|
| 69 | 69 |
///Creates convenience typedefs for the digraph types and iterators |
| 70 | 70 |
|
| 71 | 71 |
///\see DIGRAPH_TYPEDEFS |
| 72 | 72 |
/// |
| 73 | 73 |
///\note Use this macro, if the graph type is a dependent type, |
| 74 | 74 |
///ie. the graph type depend on a template parameter. |
| 75 |
#define TEMPLATE_DIGRAPH_TYPEDEFS(Digraph) \ |
|
| 76 |
typedef typename Digraph::Node Node; \ |
|
| 77 |
typedef typename Digraph::NodeIt NodeIt; \ |
|
| 78 |
typedef typename Digraph::Arc Arc; \ |
|
| 79 |
typedef typename Digraph::ArcIt ArcIt; \ |
|
| 80 |
typedef typename Digraph::InArcIt InArcIt; \ |
|
| 81 |
typedef typename Digraph::OutArcIt OutArcIt; \ |
|
| 82 |
typedef typename Digraph::template NodeMap<bool> BoolNodeMap; \ |
|
| 83 |
typedef typename Digraph::template NodeMap<int> IntNodeMap; \ |
|
| 84 |
typedef typename Digraph::template NodeMap<double> DoubleNodeMap; \ |
|
| 85 |
typedef typename Digraph::template ArcMap<bool> BoolArcMap; \ |
|
| 86 |
typedef typename Digraph::template ArcMap<int> IntArcMap; \ |
|
| 75 |
#define TEMPLATE_DIGRAPH_TYPEDEFS(Digraph) \ |
|
| 76 |
typedef typename Digraph::Node Node; \ |
|
| 77 |
typedef typename Digraph::NodeIt NodeIt; \ |
|
| 78 |
typedef typename Digraph::Arc Arc; \ |
|
| 79 |
typedef typename Digraph::ArcIt ArcIt; \ |
|
| 80 |
typedef typename Digraph::InArcIt InArcIt; \ |
|
| 81 |
typedef typename Digraph::OutArcIt OutArcIt; \ |
|
| 82 |
typedef typename Digraph::template NodeMap<bool> BoolNodeMap; \ |
|
| 83 |
typedef typename Digraph::template NodeMap<int> IntNodeMap; \ |
|
| 84 |
typedef typename Digraph::template NodeMap<double> DoubleNodeMap; \ |
|
| 85 |
typedef typename Digraph::template ArcMap<bool> BoolArcMap; \ |
|
| 86 |
typedef typename Digraph::template ArcMap<int> IntArcMap; \ |
|
| 87 | 87 |
typedef typename Digraph::template ArcMap<double> DoubleArcMap |
| 88 |
|
|
| 88 |
|
|
| 89 | 89 |
///Creates convenience typedefs for the graph types and iterators |
| 90 | 90 |
|
| 91 | 91 |
///This \c \#define creates the same convenience typedefs as defined |
| 92 | 92 |
///by \ref DIGRAPH_TYPEDEFS(Graph) and six more, namely it creates |
| 93 | 93 |
///\c Edge, \c EdgeIt, \c IncEdgeIt, \c BoolEdgeMap, \c IntEdgeMap, |
| 94 | 94 |
///\c DoubleEdgeMap. |
| 95 | 95 |
/// |
| 96 | 96 |
///\note If the graph type is a dependent type, ie. the graph type depend |
| 97 | 97 |
///on a template parameter, then use \c TEMPLATE_DIGRAPH_TYPEDEFS() |
| 98 | 98 |
///macro. |
| 99 |
#define GRAPH_TYPEDEFS(Graph) \ |
|
| 100 |
DIGRAPH_TYPEDEFS(Graph); \ |
|
| 101 |
typedef Graph::Edge Edge; \ |
|
| 102 |
typedef Graph::EdgeIt EdgeIt; \ |
|
| 103 |
typedef Graph::IncEdgeIt IncEdgeIt; \ |
|
| 104 |
typedef Graph::EdgeMap<bool> BoolEdgeMap; \ |
|
| 105 |
|
|
| 99 |
#define GRAPH_TYPEDEFS(Graph) \ |
|
| 100 |
DIGRAPH_TYPEDEFS(Graph); \ |
|
| 101 |
typedef Graph::Edge Edge; \ |
|
| 102 |
typedef Graph::EdgeIt EdgeIt; \ |
|
| 103 |
typedef Graph::IncEdgeIt IncEdgeIt; \ |
|
| 104 |
typedef Graph::EdgeMap<bool> BoolEdgeMap; \ |
|
| 105 |
typedef Graph::EdgeMap<int> IntEdgeMap; \ |
|
| 106 | 106 |
typedef Graph::EdgeMap<double> DoubleEdgeMap |
| 107 | 107 |
|
| 108 | 108 |
///Creates convenience typedefs for the graph types and iterators |
| 109 | 109 |
|
| 110 | 110 |
///\see GRAPH_TYPEDEFS |
| 111 | 111 |
/// |
| 112 | 112 |
///\note Use this macro, if the graph type is a dependent type, |
| 113 | 113 |
///ie. the graph type depend on a template parameter. |
| 114 |
#define TEMPLATE_GRAPH_TYPEDEFS(Graph) \ |
|
| 115 |
TEMPLATE_DIGRAPH_TYPEDEFS(Graph); \ |
|
| 116 |
typedef typename Graph::Edge Edge; \ |
|
| 117 |
typedef typename Graph::EdgeIt EdgeIt; \ |
|
| 118 |
typedef typename Graph::IncEdgeIt IncEdgeIt; \ |
|
| 119 |
typedef typename Graph::template EdgeMap<bool> BoolEdgeMap; \ |
|
| 120 |
|
|
| 114 |
#define TEMPLATE_GRAPH_TYPEDEFS(Graph) \ |
|
| 115 |
TEMPLATE_DIGRAPH_TYPEDEFS(Graph); \ |
|
| 116 |
typedef typename Graph::Edge Edge; \ |
|
| 117 |
typedef typename Graph::EdgeIt EdgeIt; \ |
|
| 118 |
typedef typename Graph::IncEdgeIt IncEdgeIt; \ |
|
| 119 |
typedef typename Graph::template EdgeMap<bool> BoolEdgeMap; \ |
|
| 120 |
typedef typename Graph::template EdgeMap<int> IntEdgeMap; \ |
|
| 121 | 121 |
typedef typename Graph::template EdgeMap<double> DoubleEdgeMap |
| 122 | 122 |
|
| 123 | 123 |
/// \brief Function to count the items in the graph. |
| 124 | 124 |
/// |
| 125 | 125 |
/// This function counts the items (nodes, arcs etc) in the graph. |
| 126 | 126 |
/// The complexity of the function is O(n) because |
| 127 | 127 |
/// it iterates on all of the items. |
| 128 | 128 |
template <typename Graph, typename Item> |
| 129 | 129 |
inline int countItems(const Graph& g) {
|
| 130 | 130 |
typedef typename ItemSetTraits<Graph, Item>::ItemIt ItemIt; |
| 131 | 131 |
int num = 0; |
| 132 | 132 |
for (ItemIt it(g); it != INVALID; ++it) {
|
| 133 | 133 |
++num; |
| 134 | 134 |
} |
| 135 | 135 |
return num; |
| 136 | 136 |
} |
| 137 | 137 |
|
| 138 | 138 |
// Node counting: |
| 139 | 139 |
|
| 140 | 140 |
namespace _graph_utils_bits {
|
| 141 |
|
|
| 141 |
|
|
| 142 | 142 |
template <typename Graph, typename Enable = void> |
| 143 | 143 |
struct CountNodesSelector {
|
| 144 | 144 |
static int count(const Graph &g) {
|
| 145 | 145 |
return countItems<Graph, typename Graph::Node>(g); |
| 146 | 146 |
} |
| 147 | 147 |
}; |
| 148 | 148 |
|
| 149 | 149 |
template <typename Graph> |
| 150 | 150 |
struct CountNodesSelector< |
| 151 |
Graph, typename |
|
| 152 |
enable_if<typename Graph::NodeNumTag, void>::type> |
|
| 151 |
Graph, typename |
|
| 152 |
enable_if<typename Graph::NodeNumTag, void>::type> |
|
| 153 | 153 |
{
|
| 154 | 154 |
static int count(const Graph &g) {
|
| 155 | 155 |
return g.nodeNum(); |
| 156 | 156 |
} |
| 157 |
}; |
|
| 157 |
}; |
|
| 158 | 158 |
} |
| 159 | 159 |
|
| 160 | 160 |
/// \brief Function to count the nodes in the graph. |
| 161 | 161 |
/// |
| 162 | 162 |
/// This function counts the nodes in the graph. |
| 163 | 163 |
/// The complexity of the function is O(n) but for some |
| 164 | 164 |
/// graph structures it is specialized to run in O(1). |
| 165 | 165 |
/// |
| 166 |
/// If the graph contains a \e nodeNum() member function and a |
|
| 166 |
/// If the graph contains a \e nodeNum() member function and a |
|
| 167 | 167 |
/// \e NodeNumTag tag then this function calls directly the member |
| 168 | 168 |
/// function to query the cardinality of the node set. |
| 169 | 169 |
template <typename Graph> |
| 170 | 170 |
inline int countNodes(const Graph& g) {
|
| 171 | 171 |
return _graph_utils_bits::CountNodesSelector<Graph>::count(g); |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
// Arc counting: |
| 175 | 175 |
|
| 176 | 176 |
namespace _graph_utils_bits {
|
| 177 |
|
|
| 177 |
|
|
| 178 | 178 |
template <typename Graph, typename Enable = void> |
| 179 | 179 |
struct CountArcsSelector {
|
| 180 | 180 |
static int count(const Graph &g) {
|
| 181 | 181 |
return countItems<Graph, typename Graph::Arc>(g); |
| 182 | 182 |
} |
| 183 | 183 |
}; |
| 184 | 184 |
|
| 185 | 185 |
template <typename Graph> |
| 186 | 186 |
struct CountArcsSelector< |
| 187 |
Graph, |
|
| 188 |
typename enable_if<typename Graph::ArcNumTag, void>::type> |
|
| 187 |
Graph, |
|
| 188 |
typename enable_if<typename Graph::ArcNumTag, void>::type> |
|
| 189 | 189 |
{
|
| 190 | 190 |
static int count(const Graph &g) {
|
| 191 | 191 |
return g.arcNum(); |
| 192 | 192 |
} |
| 193 |
}; |
|
| 193 |
}; |
|
| 194 | 194 |
} |
| 195 | 195 |
|
| 196 | 196 |
/// \brief Function to count the arcs in the graph. |
| 197 | 197 |
/// |
| 198 | 198 |
/// This function counts the arcs in the graph. |
| 199 | 199 |
/// The complexity of the function is O(e) but for some |
| 200 | 200 |
/// graph structures it is specialized to run in O(1). |
| 201 | 201 |
/// |
| 202 |
/// If the graph contains a \e arcNum() member function and a |
|
| 202 |
/// If the graph contains a \e arcNum() member function and a |
|
| 203 | 203 |
/// \e EdgeNumTag tag then this function calls directly the member |
| 204 | 204 |
/// function to query the cardinality of the arc set. |
| 205 | 205 |
template <typename Graph> |
| 206 | 206 |
inline int countArcs(const Graph& g) {
|
| 207 | 207 |
return _graph_utils_bits::CountArcsSelector<Graph>::count(g); |
| 208 | 208 |
} |
| 209 | 209 |
|
| 210 | 210 |
// Edge counting: |
| 211 | 211 |
namespace _graph_utils_bits {
|
| 212 |
|
|
| 212 |
|
|
| 213 | 213 |
template <typename Graph, typename Enable = void> |
| 214 | 214 |
struct CountEdgesSelector {
|
| 215 | 215 |
static int count(const Graph &g) {
|
| 216 | 216 |
return countItems<Graph, typename Graph::Edge>(g); |
| 217 | 217 |
} |
| 218 | 218 |
}; |
| 219 | 219 |
|
| 220 | 220 |
template <typename Graph> |
| 221 | 221 |
struct CountEdgesSelector< |
| 222 |
Graph, |
|
| 223 |
typename enable_if<typename Graph::EdgeNumTag, void>::type> |
|
| 222 |
Graph, |
|
| 223 |
typename enable_if<typename Graph::EdgeNumTag, void>::type> |
|
| 224 | 224 |
{
|
| 225 | 225 |
static int count(const Graph &g) {
|
| 226 | 226 |
return g.edgeNum(); |
| 227 | 227 |
} |
| 228 |
}; |
|
| 228 |
}; |
|
| 229 | 229 |
} |
| 230 | 230 |
|
| 231 | 231 |
/// \brief Function to count the edges in the graph. |
| 232 | 232 |
/// |
| 233 | 233 |
/// This function counts the edges in the graph. |
| 234 | 234 |
/// The complexity of the function is O(m) but for some |
| 235 | 235 |
/// graph structures it is specialized to run in O(1). |
| 236 | 236 |
/// |
| 237 |
/// If the graph contains a \e edgeNum() member function and a |
|
| 237 |
/// If the graph contains a \e edgeNum() member function and a |
|
| 238 | 238 |
/// \e EdgeNumTag tag then this function calls directly the member |
| 239 | 239 |
/// function to query the cardinality of the edge set. |
| 240 | 240 |
template <typename Graph> |
| 241 | 241 |
inline int countEdges(const Graph& g) {
|
| 242 | 242 |
return _graph_utils_bits::CountEdgesSelector<Graph>::count(g); |
| 243 | 243 |
|
| 244 | 244 |
} |
| 245 | 245 |
|
| 246 | 246 |
|
| 247 | 247 |
template <typename Graph, typename DegIt> |
| 248 | 248 |
inline int countNodeDegree(const Graph& _g, const typename Graph::Node& _n) {
|
| 249 | 249 |
int num = 0; |
| 250 | 250 |
for (DegIt it(_g, _n); it != INVALID; ++it) {
|
| 251 | 251 |
++num; |
| 252 | 252 |
} |
| 253 | 253 |
return num; |
| 254 | 254 |
} |
| 255 | 255 |
|
| 256 | 256 |
/// \brief Function to count the number of the out-arcs from node \c n. |
| 257 | 257 |
/// |
| 258 | 258 |
/// This function counts the number of the out-arcs from node \c n |
| 259 |
/// in the graph. |
|
| 259 |
/// in the graph. |
|
| 260 | 260 |
template <typename Graph> |
| 261 | 261 |
inline int countOutArcs(const Graph& _g, const typename Graph::Node& _n) {
|
| 262 | 262 |
return countNodeDegree<Graph, typename Graph::OutArcIt>(_g, _n); |
| 263 | 263 |
} |
| 264 | 264 |
|
| 265 | 265 |
/// \brief Function to count the number of the in-arcs to node \c n. |
| 266 | 266 |
/// |
| 267 | 267 |
/// This function counts the number of the in-arcs to node \c n |
| 268 |
/// in the graph. |
|
| 268 |
/// in the graph. |
|
| 269 | 269 |
template <typename Graph> |
| 270 | 270 |
inline int countInArcs(const Graph& _g, const typename Graph::Node& _n) {
|
| 271 | 271 |
return countNodeDegree<Graph, typename Graph::InArcIt>(_g, _n); |
| 272 | 272 |
} |
| 273 | 273 |
|
| 274 | 274 |
/// \brief Function to count the number of the inc-edges to node \c n. |
| 275 | 275 |
/// |
| 276 | 276 |
/// This function counts the number of the inc-edges to node \c n |
| 277 |
/// in the graph. |
|
| 277 |
/// in the graph. |
|
| 278 | 278 |
template <typename Graph> |
| 279 | 279 |
inline int countIncEdges(const Graph& _g, const typename Graph::Node& _n) {
|
| 280 | 280 |
return countNodeDegree<Graph, typename Graph::IncEdgeIt>(_g, _n); |
| 281 | 281 |
} |
| 282 | 282 |
|
| 283 | 283 |
namespace _graph_utils_bits {
|
| 284 |
|
|
| 284 |
|
|
| 285 | 285 |
template <typename Graph, typename Enable = void> |
| 286 | 286 |
struct FindArcSelector {
|
| 287 | 287 |
typedef typename Graph::Node Node; |
| 288 | 288 |
typedef typename Graph::Arc Arc; |
| 289 | 289 |
static Arc find(const Graph &g, Node u, Node v, Arc e) {
|
| 290 | 290 |
if (e == INVALID) {
|
| 291 | 291 |
g.firstOut(e, u); |
| 292 | 292 |
} else {
|
| 293 | 293 |
g.nextOut(e); |
| 294 | 294 |
} |
| 295 | 295 |
while (e != INVALID && g.target(e) != v) {
|
| 296 | 296 |
g.nextOut(e); |
| 297 | 297 |
} |
| 298 | 298 |
return e; |
| 299 | 299 |
} |
| 300 | 300 |
}; |
| 301 | 301 |
|
| 302 | 302 |
template <typename Graph> |
| 303 | 303 |
struct FindArcSelector< |
| 304 |
Graph, |
|
| 305 |
typename enable_if<typename Graph::FindEdgeTag, void>::type> |
|
| 304 |
Graph, |
|
| 305 |
typename enable_if<typename Graph::FindEdgeTag, void>::type> |
|
| 306 | 306 |
{
|
| 307 | 307 |
typedef typename Graph::Node Node; |
| 308 | 308 |
typedef typename Graph::Arc Arc; |
| 309 | 309 |
static Arc find(const Graph &g, Node u, Node v, Arc prev) {
|
| 310 | 310 |
return g.findArc(u, v, prev); |
| 311 | 311 |
} |
| 312 |
}; |
|
| 312 |
}; |
|
| 313 | 313 |
} |
| 314 | 314 |
|
| 315 | 315 |
/// \brief Finds an arc between two nodes of a graph. |
| 316 | 316 |
/// |
| 317 | 317 |
/// Finds an arc from node \c u to node \c v in graph \c g. |
| 318 | 318 |
/// |
| 319 | 319 |
/// If \c prev is \ref INVALID (this is the default value), then |
| 320 | 320 |
/// it finds the first arc from \c u to \c v. Otherwise it looks for |
| 321 | 321 |
/// the next arc from \c u to \c v after \c prev. |
| 322 | 322 |
/// \return The found arc or \ref INVALID if there is no such an arc. |
| 323 | 323 |
/// |
| 324 | 324 |
/// Thus you can iterate through each arc from \c u to \c v as it follows. |
| 325 | 325 |
///\code |
| 326 | 326 |
/// for(Arc e=findArc(g,u,v);e!=INVALID;e=findArc(g,u,v,e)) {
|
| 327 | 327 |
/// ... |
| 328 | 328 |
/// } |
| 329 | 329 |
///\endcode |
| 330 | 330 |
/// |
| 331 | 331 |
///\sa ArcLookUp |
| 332 | 332 |
///\sa AllArcLookUp |
| 333 | 333 |
///\sa DynArcLookUp |
| 334 | 334 |
///\sa ConArcIt |
| 335 | 335 |
template <typename Graph> |
| 336 |
inline typename Graph::Arc |
|
| 336 |
inline typename Graph::Arc |
|
| 337 | 337 |
findArc(const Graph &g, typename Graph::Node u, typename Graph::Node v, |
| 338 | 338 |
typename Graph::Arc prev = INVALID) {
|
| 339 | 339 |
return _graph_utils_bits::FindArcSelector<Graph>::find(g, u, v, prev); |
| 340 | 340 |
} |
| 341 | 341 |
|
| 342 | 342 |
/// \brief Iterator for iterating on arcs connected the same nodes. |
| 343 | 343 |
/// |
| 344 |
/// Iterator for iterating on arcs connected the same nodes. It is |
|
| 344 |
/// Iterator for iterating on arcs connected the same nodes. It is |
|
| 345 | 345 |
/// higher level interface for the findArc() function. You can |
| 346 | 346 |
/// use it the following way: |
| 347 | 347 |
///\code |
| 348 | 348 |
/// for (ConArcIt<Graph> it(g, src, trg); it != INVALID; ++it) {
|
| 349 | 349 |
/// ... |
| 350 | 350 |
/// } |
| 351 | 351 |
///\endcode |
| 352 |
/// |
|
| 352 |
/// |
|
| 353 | 353 |
///\sa findArc() |
| 354 | 354 |
///\sa ArcLookUp |
| 355 | 355 |
///\sa AllArcLookUp |
| 356 | 356 |
///\sa DynArcLookUp |
| 357 | 357 |
template <typename _Graph> |
| 358 | 358 |
class ConArcIt : public _Graph::Arc {
|
| 359 | 359 |
public: |
| 360 | 360 |
|
| 361 | 361 |
typedef _Graph Graph; |
| 362 | 362 |
typedef typename Graph::Arc Parent; |
| 363 | 363 |
|
| 364 | 364 |
typedef typename Graph::Arc Arc; |
| 365 | 365 |
typedef typename Graph::Node Node; |
| 366 | 366 |
|
| 367 | 367 |
/// \brief Constructor. |
| 368 | 368 |
/// |
| 369 | 369 |
/// Construct a new ConArcIt iterating on the arcs which |
| 370 | 370 |
/// connects the \c u and \c v node. |
| 371 | 371 |
ConArcIt(const Graph& g, Node u, Node v) : _graph(g) {
|
| 372 | 372 |
Parent::operator=(findArc(_graph, u, v)); |
| 373 | 373 |
} |
| 374 | 374 |
|
| 375 | 375 |
/// \brief Constructor. |
| 376 | 376 |
/// |
| 377 |
/// Construct a new ConArcIt which continues the iterating from |
|
| 377 |
/// Construct a new ConArcIt which continues the iterating from |
|
| 378 | 378 |
/// the \c e arc. |
| 379 | 379 |
ConArcIt(const Graph& g, Arc a) : Parent(a), _graph(g) {}
|
| 380 |
|
|
| 380 |
|
|
| 381 | 381 |
/// \brief Increment operator. |
| 382 | 382 |
/// |
| 383 | 383 |
/// It increments the iterator and gives back the next arc. |
| 384 | 384 |
ConArcIt& operator++() {
|
| 385 |
Parent::operator=(findArc(_graph, _graph.source(*this), |
|
| 386 |
_graph.target(*this), *this)); |
|
| 385 |
Parent::operator=(findArc(_graph, _graph.source(*this), |
|
| 386 |
_graph.target(*this), *this)); |
|
| 387 | 387 |
return *this; |
| 388 | 388 |
} |
| 389 | 389 |
private: |
| 390 | 390 |
const Graph& _graph; |
| 391 | 391 |
}; |
| 392 | 392 |
|
| 393 | 393 |
namespace _graph_utils_bits {
|
| 394 |
|
|
| 394 |
|
|
| 395 | 395 |
template <typename Graph, typename Enable = void> |
| 396 | 396 |
struct FindEdgeSelector {
|
| 397 | 397 |
typedef typename Graph::Node Node; |
| 398 | 398 |
typedef typename Graph::Edge Edge; |
| 399 | 399 |
static Edge find(const Graph &g, Node u, Node v, Edge e) {
|
| 400 | 400 |
bool b; |
| 401 | 401 |
if (u != v) {
|
| 402 | 402 |
if (e == INVALID) {
|
| 403 | 403 |
g.firstInc(e, b, u); |
| 404 | 404 |
} else {
|
| 405 | 405 |
b = g.u(e) == u; |
| 406 | 406 |
g.nextInc(e, b); |
| 407 | 407 |
} |
| 408 | 408 |
while (e != INVALID && (b ? g.v(e) : g.u(e)) != v) {
|
| 409 | 409 |
g.nextInc(e, b); |
| 410 | 410 |
} |
| ... | ... |
@@ -412,245 +412,245 @@ |
| 412 | 412 |
if (e == INVALID) {
|
| 413 | 413 |
g.firstInc(e, b, u); |
| 414 | 414 |
} else {
|
| 415 | 415 |
b = true; |
| 416 | 416 |
g.nextInc(e, b); |
| 417 | 417 |
} |
| 418 | 418 |
while (e != INVALID && (!b || g.v(e) != v)) {
|
| 419 | 419 |
g.nextInc(e, b); |
| 420 | 420 |
} |
| 421 | 421 |
} |
| 422 | 422 |
return e; |
| 423 | 423 |
} |
| 424 | 424 |
}; |
| 425 | 425 |
|
| 426 | 426 |
template <typename Graph> |
| 427 | 427 |
struct FindEdgeSelector< |
| 428 |
Graph, |
|
| 429 |
typename enable_if<typename Graph::FindEdgeTag, void>::type> |
|
| 428 |
Graph, |
|
| 429 |
typename enable_if<typename Graph::FindEdgeTag, void>::type> |
|
| 430 | 430 |
{
|
| 431 | 431 |
typedef typename Graph::Node Node; |
| 432 | 432 |
typedef typename Graph::Edge Edge; |
| 433 | 433 |
static Edge find(const Graph &g, Node u, Node v, Edge prev) {
|
| 434 | 434 |
return g.findEdge(u, v, prev); |
| 435 | 435 |
} |
| 436 |
}; |
|
| 436 |
}; |
|
| 437 | 437 |
} |
| 438 | 438 |
|
| 439 | 439 |
/// \brief Finds an edge between two nodes of a graph. |
| 440 | 440 |
/// |
| 441 | 441 |
/// Finds an edge from node \c u to node \c v in graph \c g. |
| 442 | 442 |
/// If the node \c u and node \c v is equal then each loop edge |
| 443 | 443 |
/// will be enumerated once. |
| 444 | 444 |
/// |
| 445 | 445 |
/// If \c prev is \ref INVALID (this is the default value), then |
| 446 | 446 |
/// it finds the first arc from \c u to \c v. Otherwise it looks for |
| 447 | 447 |
/// the next arc from \c u to \c v after \c prev. |
| 448 | 448 |
/// \return The found arc or \ref INVALID if there is no such an arc. |
| 449 | 449 |
/// |
| 450 | 450 |
/// Thus you can iterate through each arc from \c u to \c v as it follows. |
| 451 | 451 |
///\code |
| 452 |
/// for(Edge e = findEdge(g,u,v); e != INVALID; |
|
| 452 |
/// for(Edge e = findEdge(g,u,v); e != INVALID; |
|
| 453 | 453 |
/// e = findEdge(g,u,v,e)) {
|
| 454 | 454 |
/// ... |
| 455 | 455 |
/// } |
| 456 | 456 |
///\endcode |
| 457 | 457 |
/// |
| 458 | 458 |
///\sa ConEdgeIt |
| 459 | 459 |
|
| 460 | 460 |
template <typename Graph> |
| 461 |
inline typename Graph::Edge |
|
| 461 |
inline typename Graph::Edge |
|
| 462 | 462 |
findEdge(const Graph &g, typename Graph::Node u, typename Graph::Node v, |
| 463 | 463 |
typename Graph::Edge p = INVALID) {
|
| 464 | 464 |
return _graph_utils_bits::FindEdgeSelector<Graph>::find(g, u, v, p); |
| 465 | 465 |
} |
| 466 | 466 |
|
| 467 | 467 |
/// \brief Iterator for iterating on edges connected the same nodes. |
| 468 | 468 |
/// |
| 469 |
/// Iterator for iterating on edges connected the same nodes. It is |
|
| 469 |
/// Iterator for iterating on edges connected the same nodes. It is |
|
| 470 | 470 |
/// higher level interface for the findEdge() function. You can |
| 471 | 471 |
/// use it the following way: |
| 472 | 472 |
///\code |
| 473 | 473 |
/// for (ConEdgeIt<Graph> it(g, src, trg); it != INVALID; ++it) {
|
| 474 | 474 |
/// ... |
| 475 | 475 |
/// } |
| 476 | 476 |
///\endcode |
| 477 | 477 |
/// |
| 478 | 478 |
///\sa findEdge() |
| 479 | 479 |
template <typename _Graph> |
| 480 | 480 |
class ConEdgeIt : public _Graph::Edge {
|
| 481 | 481 |
public: |
| 482 | 482 |
|
| 483 | 483 |
typedef _Graph Graph; |
| 484 | 484 |
typedef typename Graph::Edge Parent; |
| 485 | 485 |
|
| 486 | 486 |
typedef typename Graph::Edge Edge; |
| 487 | 487 |
typedef typename Graph::Node Node; |
| 488 | 488 |
|
| 489 | 489 |
/// \brief Constructor. |
| 490 | 490 |
/// |
| 491 | 491 |
/// Construct a new ConEdgeIt iterating on the edges which |
| 492 | 492 |
/// connects the \c u and \c v node. |
| 493 | 493 |
ConEdgeIt(const Graph& g, Node u, Node v) : _graph(g) {
|
| 494 | 494 |
Parent::operator=(findEdge(_graph, u, v)); |
| 495 | 495 |
} |
| 496 | 496 |
|
| 497 | 497 |
/// \brief Constructor. |
| 498 | 498 |
/// |
| 499 |
/// Construct a new ConEdgeIt which continues the iterating from |
|
| 499 |
/// Construct a new ConEdgeIt which continues the iterating from |
|
| 500 | 500 |
/// the \c e edge. |
| 501 | 501 |
ConEdgeIt(const Graph& g, Edge e) : Parent(e), _graph(g) {}
|
| 502 |
|
|
| 502 |
|
|
| 503 | 503 |
/// \brief Increment operator. |
| 504 | 504 |
/// |
| 505 | 505 |
/// It increments the iterator and gives back the next edge. |
| 506 | 506 |
ConEdgeIt& operator++() {
|
| 507 |
Parent::operator=(findEdge(_graph, _graph.u(*this), |
|
| 508 |
_graph.v(*this), *this)); |
|
| 507 |
Parent::operator=(findEdge(_graph, _graph.u(*this), |
|
| 508 |
_graph.v(*this), *this)); |
|
| 509 | 509 |
return *this; |
| 510 | 510 |
} |
| 511 | 511 |
private: |
| 512 | 512 |
const Graph& _graph; |
| 513 | 513 |
}; |
| 514 | 514 |
|
| 515 | 515 |
namespace _graph_utils_bits {
|
| 516 | 516 |
|
| 517 | 517 |
template <typename Digraph, typename Item, typename RefMap> |
| 518 | 518 |
class MapCopyBase {
|
| 519 | 519 |
public: |
| 520 | 520 |
virtual void copy(const Digraph& from, const RefMap& refMap) = 0; |
| 521 |
|
|
| 521 |
|
|
| 522 | 522 |
virtual ~MapCopyBase() {}
|
| 523 | 523 |
}; |
| 524 | 524 |
|
| 525 |
template <typename Digraph, typename Item, typename RefMap, |
|
| 525 |
template <typename Digraph, typename Item, typename RefMap, |
|
| 526 | 526 |
typename ToMap, typename FromMap> |
| 527 | 527 |
class MapCopy : public MapCopyBase<Digraph, Item, RefMap> {
|
| 528 | 528 |
public: |
| 529 | 529 |
|
| 530 |
MapCopy(ToMap& tmap, const FromMap& map) |
|
| 530 |
MapCopy(ToMap& tmap, const FromMap& map) |
|
| 531 | 531 |
: _tmap(tmap), _map(map) {}
|
| 532 |
|
|
| 532 |
|
|
| 533 | 533 |
virtual void copy(const Digraph& digraph, const RefMap& refMap) {
|
| 534 | 534 |
typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt; |
| 535 | 535 |
for (ItemIt it(digraph); it != INVALID; ++it) {
|
| 536 | 536 |
_tmap.set(refMap[it], _map[it]); |
| 537 | 537 |
} |
| 538 | 538 |
} |
| 539 | 539 |
|
| 540 | 540 |
private: |
| 541 | 541 |
ToMap& _tmap; |
| 542 | 542 |
const FromMap& _map; |
| 543 | 543 |
}; |
| 544 | 544 |
|
| 545 | 545 |
template <typename Digraph, typename Item, typename RefMap, typename It> |
| 546 | 546 |
class ItemCopy : public MapCopyBase<Digraph, Item, RefMap> {
|
| 547 | 547 |
public: |
| 548 | 548 |
|
| 549 | 549 |
ItemCopy(It& it, const Item& item) : _it(it), _item(item) {}
|
| 550 |
|
|
| 550 |
|
|
| 551 | 551 |
virtual void copy(const Digraph&, const RefMap& refMap) {
|
| 552 | 552 |
_it = refMap[_item]; |
| 553 | 553 |
} |
| 554 | 554 |
|
| 555 | 555 |
private: |
| 556 | 556 |
It& _it; |
| 557 | 557 |
Item _item; |
| 558 | 558 |
}; |
| 559 | 559 |
|
| 560 | 560 |
template <typename Digraph, typename Item, typename RefMap, typename Ref> |
| 561 | 561 |
class RefCopy : public MapCopyBase<Digraph, Item, RefMap> {
|
| 562 | 562 |
public: |
| 563 | 563 |
|
| 564 | 564 |
RefCopy(Ref& map) : _map(map) {}
|
| 565 |
|
|
| 565 |
|
|
| 566 | 566 |
virtual void copy(const Digraph& digraph, const RefMap& refMap) {
|
| 567 | 567 |
typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt; |
| 568 | 568 |
for (ItemIt it(digraph); it != INVALID; ++it) {
|
| 569 | 569 |
_map.set(it, refMap[it]); |
| 570 | 570 |
} |
| 571 | 571 |
} |
| 572 | 572 |
|
| 573 | 573 |
private: |
| 574 | 574 |
Ref& _map; |
| 575 | 575 |
}; |
| 576 | 576 |
|
| 577 |
template <typename Digraph, typename Item, typename RefMap, |
|
| 577 |
template <typename Digraph, typename Item, typename RefMap, |
|
| 578 | 578 |
typename CrossRef> |
| 579 | 579 |
class CrossRefCopy : public MapCopyBase<Digraph, Item, RefMap> {
|
| 580 | 580 |
public: |
| 581 | 581 |
|
| 582 | 582 |
CrossRefCopy(CrossRef& cmap) : _cmap(cmap) {}
|
| 583 |
|
|
| 583 |
|
|
| 584 | 584 |
virtual void copy(const Digraph& digraph, const RefMap& refMap) {
|
| 585 | 585 |
typedef typename ItemSetTraits<Digraph, Item>::ItemIt ItemIt; |
| 586 | 586 |
for (ItemIt it(digraph); it != INVALID; ++it) {
|
| 587 | 587 |
_cmap.set(refMap[it], it); |
| 588 | 588 |
} |
| 589 | 589 |
} |
| 590 | 590 |
|
| 591 | 591 |
private: |
| 592 | 592 |
CrossRef& _cmap; |
| 593 | 593 |
}; |
| 594 | 594 |
|
| 595 | 595 |
template <typename Digraph, typename Enable = void> |
| 596 | 596 |
struct DigraphCopySelector {
|
| 597 | 597 |
template <typename From, typename NodeRefMap, typename ArcRefMap> |
| 598 | 598 |
static void copy(Digraph &to, const From& from, |
| 599 | 599 |
NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) {
|
| 600 | 600 |
for (typename From::NodeIt it(from); it != INVALID; ++it) {
|
| 601 | 601 |
nodeRefMap[it] = to.addNode(); |
| 602 | 602 |
} |
| 603 | 603 |
for (typename From::ArcIt it(from); it != INVALID; ++it) {
|
| 604 |
arcRefMap[it] = to.addArc(nodeRefMap[from.source(it)], |
|
| 605 |
nodeRefMap[from.target(it)]); |
|
| 604 |
arcRefMap[it] = to.addArc(nodeRefMap[from.source(it)], |
|
| 605 |
nodeRefMap[from.target(it)]); |
|
| 606 | 606 |
} |
| 607 | 607 |
} |
| 608 | 608 |
}; |
| 609 | 609 |
|
| 610 | 610 |
template <typename Digraph> |
| 611 | 611 |
struct DigraphCopySelector< |
| 612 |
Digraph, |
|
| 613 |
typename enable_if<typename Digraph::BuildTag, void>::type> |
|
| 612 |
Digraph, |
|
| 613 |
typename enable_if<typename Digraph::BuildTag, void>::type> |
|
| 614 | 614 |
{
|
| 615 | 615 |
template <typename From, typename NodeRefMap, typename ArcRefMap> |
| 616 | 616 |
static void copy(Digraph &to, const From& from, |
| 617 | 617 |
NodeRefMap& nodeRefMap, ArcRefMap& arcRefMap) {
|
| 618 | 618 |
to.build(from, nodeRefMap, arcRefMap); |
| 619 | 619 |
} |
| 620 | 620 |
}; |
| 621 | 621 |
|
| 622 | 622 |
template <typename Graph, typename Enable = void> |
| 623 | 623 |
struct GraphCopySelector {
|
| 624 | 624 |
template <typename From, typename NodeRefMap, typename EdgeRefMap> |
| 625 | 625 |
static void copy(Graph &to, const From& from, |
| 626 | 626 |
NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {
|
| 627 | 627 |
for (typename From::NodeIt it(from); it != INVALID; ++it) {
|
| 628 | 628 |
nodeRefMap[it] = to.addNode(); |
| 629 | 629 |
} |
| 630 | 630 |
for (typename From::EdgeIt it(from); it != INVALID; ++it) {
|
| 631 |
edgeRefMap[it] = to.addEdge(nodeRefMap[from.u(it)], |
|
| 632 |
nodeRefMap[from.v(it)]); |
|
| 631 |
edgeRefMap[it] = to.addEdge(nodeRefMap[from.u(it)], |
|
| 632 |
nodeRefMap[from.v(it)]); |
|
| 633 | 633 |
} |
| 634 | 634 |
} |
| 635 | 635 |
}; |
| 636 | 636 |
|
| 637 | 637 |
template <typename Graph> |
| 638 | 638 |
struct GraphCopySelector< |
| 639 |
Graph, |
|
| 640 |
typename enable_if<typename Graph::BuildTag, void>::type> |
|
| 639 |
Graph, |
|
| 640 |
typename enable_if<typename Graph::BuildTag, void>::type> |
|
| 641 | 641 |
{
|
| 642 | 642 |
template <typename From, typename NodeRefMap, typename EdgeRefMap> |
| 643 | 643 |
static void copy(Graph &to, const From& from, |
| 644 | 644 |
NodeRefMap& nodeRefMap, EdgeRefMap& edgeRefMap) {
|
| 645 | 645 |
to.build(from, nodeRefMap, edgeRefMap); |
| 646 | 646 |
} |
| 647 | 647 |
}; |
| 648 | 648 |
|
| 649 | 649 |
} |
| 650 | 650 |
|
| 651 | 651 |
/// \brief Class to copy a digraph. |
| 652 | 652 |
/// |
| 653 | 653 |
/// Class to copy a digraph to another digraph (duplicate a digraph). The |
| 654 | 654 |
/// simplest way of using it is through the \c copyDigraph() function. |
| 655 | 655 |
/// |
| 656 | 656 |
/// This class not just make a copy of a graph, but it can create |
| ... | ... |
@@ -684,192 +684,192 @@ |
| 684 | 684 |
/// dc.run(); |
| 685 | 685 |
///\endcode |
| 686 | 686 |
template <typename To, typename From> |
| 687 | 687 |
class DigraphCopy {
|
| 688 | 688 |
private: |
| 689 | 689 |
|
| 690 | 690 |
typedef typename From::Node Node; |
| 691 | 691 |
typedef typename From::NodeIt NodeIt; |
| 692 | 692 |
typedef typename From::Arc Arc; |
| 693 | 693 |
typedef typename From::ArcIt ArcIt; |
| 694 | 694 |
|
| 695 | 695 |
typedef typename To::Node TNode; |
| 696 | 696 |
typedef typename To::Arc TArc; |
| 697 | 697 |
|
| 698 | 698 |
typedef typename From::template NodeMap<TNode> NodeRefMap; |
| 699 | 699 |
typedef typename From::template ArcMap<TArc> ArcRefMap; |
| 700 |
|
|
| 701 |
|
|
| 702 |
|
|
| 700 |
|
|
| 701 |
|
|
| 702 |
public: |
|
| 703 | 703 |
|
| 704 | 704 |
|
| 705 | 705 |
/// \brief Constructor for the DigraphCopy. |
| 706 | 706 |
/// |
| 707 | 707 |
/// It copies the content of the \c _from digraph into the |
| 708 | 708 |
/// \c _to digraph. |
| 709 |
DigraphCopy(To& to, const From& from) |
|
| 709 |
DigraphCopy(To& to, const From& from) |
|
| 710 | 710 |
: _from(from), _to(to) {}
|
| 711 | 711 |
|
| 712 | 712 |
/// \brief Destructor of the DigraphCopy |
| 713 | 713 |
/// |
| 714 | 714 |
/// Destructor of the DigraphCopy |
| 715 | 715 |
~DigraphCopy() {
|
| 716 | 716 |
for (int i = 0; i < int(_node_maps.size()); ++i) {
|
| 717 | 717 |
delete _node_maps[i]; |
| 718 | 718 |
} |
| 719 | 719 |
for (int i = 0; i < int(_arc_maps.size()); ++i) {
|
| 720 | 720 |
delete _arc_maps[i]; |
| 721 | 721 |
} |
| 722 | 722 |
|
| 723 | 723 |
} |
| 724 | 724 |
|
| 725 | 725 |
/// \brief Copies the node references into the given map. |
| 726 | 726 |
/// |
| 727 | 727 |
/// Copies the node references into the given map. The parameter |
| 728 | 728 |
/// should be a map, which key type is the Node type of the source |
| 729 | 729 |
/// graph, while the value type is the Node type of the |
| 730 | 730 |
/// destination graph. |
| 731 | 731 |
template <typename NodeRef> |
| 732 | 732 |
DigraphCopy& nodeRef(NodeRef& map) {
|
| 733 |
_node_maps.push_back(new _graph_utils_bits::RefCopy<From, Node, |
|
| 734 |
NodeRefMap, NodeRef>(map)); |
|
| 733 |
_node_maps.push_back(new _graph_utils_bits::RefCopy<From, Node, |
|
| 734 |
NodeRefMap, NodeRef>(map)); |
|
| 735 | 735 |
return *this; |
| 736 | 736 |
} |
| 737 | 737 |
|
| 738 | 738 |
/// \brief Copies the node cross references into the given map. |
| 739 | 739 |
/// |
| 740 | 740 |
/// Copies the node cross references (reverse references) into |
| 741 | 741 |
/// the given map. The parameter should be a map, which key type |
| 742 | 742 |
/// is the Node type of the destination graph, while the value type is |
| 743 | 743 |
/// the Node type of the source graph. |
| 744 | 744 |
template <typename NodeCrossRef> |
| 745 | 745 |
DigraphCopy& nodeCrossRef(NodeCrossRef& map) {
|
| 746 | 746 |
_node_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, Node, |
| 747 |
|
|
| 747 |
NodeRefMap, NodeCrossRef>(map)); |
|
| 748 | 748 |
return *this; |
| 749 | 749 |
} |
| 750 | 750 |
|
| 751 | 751 |
/// \brief Make copy of the given map. |
| 752 | 752 |
/// |
| 753 | 753 |
/// Makes copy of the given map for the newly created digraph. |
| 754 | 754 |
/// The new map's key type is the destination graph's node type, |
| 755 | 755 |
/// and the copied map's key type is the source graph's node type. |
| 756 | 756 |
template <typename ToMap, typename FromMap> |
| 757 | 757 |
DigraphCopy& nodeMap(ToMap& tmap, const FromMap& map) {
|
| 758 |
_node_maps.push_back(new _graph_utils_bits::MapCopy<From, Node, |
|
| 759 |
NodeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 758 |
_node_maps.push_back(new _graph_utils_bits::MapCopy<From, Node, |
|
| 759 |
NodeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 760 | 760 |
return *this; |
| 761 | 761 |
} |
| 762 | 762 |
|
| 763 | 763 |
/// \brief Make a copy of the given node. |
| 764 | 764 |
/// |
| 765 | 765 |
/// Make a copy of the given node. |
| 766 | 766 |
DigraphCopy& node(TNode& tnode, const Node& snode) {
|
| 767 |
_node_maps.push_back(new _graph_utils_bits::ItemCopy<From, Node, |
|
| 768 |
NodeRefMap, TNode>(tnode, snode)); |
|
| 767 |
_node_maps.push_back(new _graph_utils_bits::ItemCopy<From, Node, |
|
| 768 |
NodeRefMap, TNode>(tnode, snode)); |
|
| 769 | 769 |
return *this; |
| 770 | 770 |
} |
| 771 | 771 |
|
| 772 | 772 |
/// \brief Copies the arc references into the given map. |
| 773 | 773 |
/// |
| 774 | 774 |
/// Copies the arc references into the given map. |
| 775 | 775 |
template <typename ArcRef> |
| 776 | 776 |
DigraphCopy& arcRef(ArcRef& map) {
|
| 777 |
_arc_maps.push_back(new _graph_utils_bits::RefCopy<From, Arc, |
|
| 778 |
ArcRefMap, ArcRef>(map)); |
|
| 777 |
_arc_maps.push_back(new _graph_utils_bits::RefCopy<From, Arc, |
|
| 778 |
ArcRefMap, ArcRef>(map)); |
|
| 779 | 779 |
return *this; |
| 780 | 780 |
} |
| 781 | 781 |
|
| 782 | 782 |
/// \brief Copies the arc cross references into the given map. |
| 783 | 783 |
/// |
| 784 | 784 |
/// Copies the arc cross references (reverse references) into |
| 785 | 785 |
/// the given map. |
| 786 | 786 |
template <typename ArcCrossRef> |
| 787 | 787 |
DigraphCopy& arcCrossRef(ArcCrossRef& map) {
|
| 788 | 788 |
_arc_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, Arc, |
| 789 |
|
|
| 789 |
ArcRefMap, ArcCrossRef>(map)); |
|
| 790 | 790 |
return *this; |
| 791 | 791 |
} |
| 792 | 792 |
|
| 793 | 793 |
/// \brief Make copy of the given map. |
| 794 | 794 |
/// |
| 795 |
/// Makes copy of the given map for the newly created digraph. |
|
| 795 |
/// Makes copy of the given map for the newly created digraph. |
|
| 796 | 796 |
/// The new map's key type is the to digraph's arc type, |
| 797 | 797 |
/// and the copied map's key type is the from digraph's arc |
| 798 |
/// type. |
|
| 798 |
/// type. |
|
| 799 | 799 |
template <typename ToMap, typename FromMap> |
| 800 | 800 |
DigraphCopy& arcMap(ToMap& tmap, const FromMap& map) {
|
| 801 |
_arc_maps.push_back(new _graph_utils_bits::MapCopy<From, Arc, |
|
| 802 |
ArcRefMap, ToMap, FromMap>(tmap, map)); |
|
| 801 |
_arc_maps.push_back(new _graph_utils_bits::MapCopy<From, Arc, |
|
| 802 |
ArcRefMap, ToMap, FromMap>(tmap, map)); |
|
| 803 | 803 |
return *this; |
| 804 | 804 |
} |
| 805 | 805 |
|
| 806 | 806 |
/// \brief Make a copy of the given arc. |
| 807 | 807 |
/// |
| 808 | 808 |
/// Make a copy of the given arc. |
| 809 | 809 |
DigraphCopy& arc(TArc& tarc, const Arc& sarc) {
|
| 810 |
_arc_maps.push_back(new _graph_utils_bits::ItemCopy<From, Arc, |
|
| 811 |
ArcRefMap, TArc>(tarc, sarc)); |
|
| 810 |
_arc_maps.push_back(new _graph_utils_bits::ItemCopy<From, Arc, |
|
| 811 |
ArcRefMap, TArc>(tarc, sarc)); |
|
| 812 | 812 |
return *this; |
| 813 | 813 |
} |
| 814 | 814 |
|
| 815 | 815 |
/// \brief Executes the copies. |
| 816 | 816 |
/// |
| 817 | 817 |
/// Executes the copies. |
| 818 | 818 |
void run() {
|
| 819 | 819 |
NodeRefMap nodeRefMap(_from); |
| 820 | 820 |
ArcRefMap arcRefMap(_from); |
| 821 | 821 |
_graph_utils_bits::DigraphCopySelector<To>:: |
| 822 | 822 |
copy(_to, _from, nodeRefMap, arcRefMap); |
| 823 | 823 |
for (int i = 0; i < int(_node_maps.size()); ++i) {
|
| 824 | 824 |
_node_maps[i]->copy(_from, nodeRefMap); |
| 825 | 825 |
} |
| 826 | 826 |
for (int i = 0; i < int(_arc_maps.size()); ++i) {
|
| 827 | 827 |
_arc_maps[i]->copy(_from, arcRefMap); |
| 828 |
} |
|
| 828 |
} |
|
| 829 | 829 |
} |
| 830 | 830 |
|
| 831 | 831 |
protected: |
| 832 | 832 |
|
| 833 | 833 |
|
| 834 | 834 |
const From& _from; |
| 835 | 835 |
To& _to; |
| 836 | 836 |
|
| 837 |
std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > |
|
| 837 |
std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > |
|
| 838 | 838 |
_node_maps; |
| 839 | 839 |
|
| 840 |
std::vector<_graph_utils_bits::MapCopyBase<From, Arc, ArcRefMap>* > |
|
| 840 |
std::vector<_graph_utils_bits::MapCopyBase<From, Arc, ArcRefMap>* > |
|
| 841 | 841 |
_arc_maps; |
| 842 | 842 |
|
| 843 | 843 |
}; |
| 844 | 844 |
|
| 845 | 845 |
/// \brief Copy a digraph to another digraph. |
| 846 | 846 |
/// |
| 847 | 847 |
/// Copy a digraph to another digraph. The complete usage of the |
| 848 | 848 |
/// function is detailed in the DigraphCopy class, but a short |
| 849 | 849 |
/// example shows a basic work: |
| 850 | 850 |
///\code |
| 851 | 851 |
/// copyDigraph(trg, src).nodeRef(nr).arcCrossRef(ecr).run(); |
| 852 | 852 |
///\endcode |
| 853 |
/// |
|
| 853 |
/// |
|
| 854 | 854 |
/// After the copy the \c nr map will contain the mapping from the |
| 855 | 855 |
/// nodes of the \c from digraph to the nodes of the \c to digraph and |
| 856 | 856 |
/// \c ecr will contain the mapping from the arcs of the \c to digraph |
| 857 | 857 |
/// to the arcs of the \c from digraph. |
| 858 | 858 |
/// |
| 859 |
/// \see DigraphCopy |
|
| 859 |
/// \see DigraphCopy |
|
| 860 | 860 |
template <typename To, typename From> |
| 861 | 861 |
DigraphCopy<To, From> copyDigraph(To& to, const From& from) {
|
| 862 | 862 |
return DigraphCopy<To, From>(to, from); |
| 863 | 863 |
} |
| 864 | 864 |
|
| 865 | 865 |
/// \brief Class to copy a graph. |
| 866 | 866 |
/// |
| 867 | 867 |
/// Class to copy a graph to another graph (duplicate a graph). The |
| 868 | 868 |
/// simplest way of using it is through the \c copyGraph() function. |
| 869 | 869 |
/// |
| 870 | 870 |
/// This class not just make a copy of a graph, but it can create |
| 871 | 871 |
/// references and cross references between the nodes, edges and arcs of |
| 872 | 872 |
/// the two graphs, it can copy maps for use with the newly created |
| 873 | 873 |
/// graph and copy nodes, edges and arcs. |
| 874 | 874 |
/// |
| 875 | 875 |
/// To make a copy from a graph, first an instance of GraphCopy |
| ... | ... |
@@ -904,262 +904,262 @@ |
| 904 | 904 |
typedef typename From::Node Node; |
| 905 | 905 |
typedef typename From::NodeIt NodeIt; |
| 906 | 906 |
typedef typename From::Arc Arc; |
| 907 | 907 |
typedef typename From::ArcIt ArcIt; |
| 908 | 908 |
typedef typename From::Edge Edge; |
| 909 | 909 |
typedef typename From::EdgeIt EdgeIt; |
| 910 | 910 |
|
| 911 | 911 |
typedef typename To::Node TNode; |
| 912 | 912 |
typedef typename To::Arc TArc; |
| 913 | 913 |
typedef typename To::Edge TEdge; |
| 914 | 914 |
|
| 915 | 915 |
typedef typename From::template NodeMap<TNode> NodeRefMap; |
| 916 | 916 |
typedef typename From::template EdgeMap<TEdge> EdgeRefMap; |
| 917 | 917 |
|
| 918 | 918 |
struct ArcRefMap {
|
| 919 | 919 |
ArcRefMap(const To& to, const From& from, |
| 920 |
const EdgeRefMap& edge_ref, const NodeRefMap& node_ref) |
|
| 921 |
: _to(to), _from(from), |
|
| 920 |
const EdgeRefMap& edge_ref, const NodeRefMap& node_ref) |
|
| 921 |
: _to(to), _from(from), |
|
| 922 | 922 |
_edge_ref(edge_ref), _node_ref(node_ref) {}
|
| 923 | 923 |
|
| 924 | 924 |
typedef typename From::Arc Key; |
| 925 | 925 |
typedef typename To::Arc Value; |
| 926 | 926 |
|
| 927 | 927 |
Value operator[](const Key& key) const {
|
| 928 | 928 |
bool forward = _from.u(key) != _from.v(key) ? |
| 929 |
_node_ref[_from.source(key)] == |
|
| 930 |
_to.source(_to.direct(_edge_ref[key], true)) : |
|
| 931 |
_from.direction(key); |
|
| 932 |
return _to.direct(_edge_ref[key], forward); |
|
| 929 |
_node_ref[_from.source(key)] == |
|
| 930 |
_to.source(_to.direct(_edge_ref[key], true)) : |
|
| 931 |
_from.direction(key); |
|
| 932 |
return _to.direct(_edge_ref[key], forward); |
|
| 933 | 933 |
} |
| 934 |
|
|
| 934 |
|
|
| 935 | 935 |
const To& _to; |
| 936 | 936 |
const From& _from; |
| 937 | 937 |
const EdgeRefMap& _edge_ref; |
| 938 | 938 |
const NodeRefMap& _node_ref; |
| 939 | 939 |
}; |
| 940 | 940 |
|
| 941 |
|
|
| 942 |
public: |
|
| 941 |
|
|
| 942 |
public: |
|
| 943 | 943 |
|
| 944 | 944 |
|
| 945 | 945 |
/// \brief Constructor for the GraphCopy. |
| 946 | 946 |
/// |
| 947 | 947 |
/// It copies the content of the \c _from graph into the |
| 948 | 948 |
/// \c _to graph. |
| 949 |
GraphCopy(To& to, const From& from) |
|
| 949 |
GraphCopy(To& to, const From& from) |
|
| 950 | 950 |
: _from(from), _to(to) {}
|
| 951 | 951 |
|
| 952 | 952 |
/// \brief Destructor of the GraphCopy |
| 953 | 953 |
/// |
| 954 | 954 |
/// Destructor of the GraphCopy |
| 955 | 955 |
~GraphCopy() {
|
| 956 | 956 |
for (int i = 0; i < int(_node_maps.size()); ++i) {
|
| 957 | 957 |
delete _node_maps[i]; |
| 958 | 958 |
} |
| 959 | 959 |
for (int i = 0; i < int(_arc_maps.size()); ++i) {
|
| 960 | 960 |
delete _arc_maps[i]; |
| 961 | 961 |
} |
| 962 | 962 |
for (int i = 0; i < int(_edge_maps.size()); ++i) {
|
| 963 | 963 |
delete _edge_maps[i]; |
| 964 | 964 |
} |
| 965 | 965 |
|
| 966 | 966 |
} |
| 967 | 967 |
|
| 968 | 968 |
/// \brief Copies the node references into the given map. |
| 969 | 969 |
/// |
| 970 | 970 |
/// Copies the node references into the given map. |
| 971 | 971 |
template <typename NodeRef> |
| 972 | 972 |
GraphCopy& nodeRef(NodeRef& map) {
|
| 973 |
_node_maps.push_back(new _graph_utils_bits::RefCopy<From, Node, |
|
| 974 |
NodeRefMap, NodeRef>(map)); |
|
| 973 |
_node_maps.push_back(new _graph_utils_bits::RefCopy<From, Node, |
|
| 974 |
NodeRefMap, NodeRef>(map)); |
|
| 975 | 975 |
return *this; |
| 976 | 976 |
} |
| 977 | 977 |
|
| 978 | 978 |
/// \brief Copies the node cross references into the given map. |
| 979 | 979 |
/// |
| 980 | 980 |
/// Copies the node cross references (reverse references) into |
| 981 | 981 |
/// the given map. |
| 982 | 982 |
template <typename NodeCrossRef> |
| 983 | 983 |
GraphCopy& nodeCrossRef(NodeCrossRef& map) {
|
| 984 | 984 |
_node_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, Node, |
| 985 |
|
|
| 985 |
NodeRefMap, NodeCrossRef>(map)); |
|
| 986 | 986 |
return *this; |
| 987 | 987 |
} |
| 988 | 988 |
|
| 989 | 989 |
/// \brief Make copy of the given map. |
| 990 | 990 |
/// |
| 991 |
/// Makes copy of the given map for the newly created graph. |
|
| 991 |
/// Makes copy of the given map for the newly created graph. |
|
| 992 | 992 |
/// The new map's key type is the to graph's node type, |
| 993 | 993 |
/// and the copied map's key type is the from graph's node |
| 994 |
/// type. |
|
| 994 |
/// type. |
|
| 995 | 995 |
template <typename ToMap, typename FromMap> |
| 996 | 996 |
GraphCopy& nodeMap(ToMap& tmap, const FromMap& map) {
|
| 997 |
_node_maps.push_back(new _graph_utils_bits::MapCopy<From, Node, |
|
| 998 |
NodeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 997 |
_node_maps.push_back(new _graph_utils_bits::MapCopy<From, Node, |
|
| 998 |
NodeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 999 | 999 |
return *this; |
| 1000 | 1000 |
} |
| 1001 | 1001 |
|
| 1002 | 1002 |
/// \brief Make a copy of the given node. |
| 1003 | 1003 |
/// |
| 1004 | 1004 |
/// Make a copy of the given node. |
| 1005 | 1005 |
GraphCopy& node(TNode& tnode, const Node& snode) {
|
| 1006 |
_node_maps.push_back(new _graph_utils_bits::ItemCopy<From, Node, |
|
| 1007 |
NodeRefMap, TNode>(tnode, snode)); |
|
| 1006 |
_node_maps.push_back(new _graph_utils_bits::ItemCopy<From, Node, |
|
| 1007 |
NodeRefMap, TNode>(tnode, snode)); |
|
| 1008 | 1008 |
return *this; |
| 1009 | 1009 |
} |
| 1010 | 1010 |
|
| 1011 | 1011 |
/// \brief Copies the arc references into the given map. |
| 1012 | 1012 |
/// |
| 1013 | 1013 |
/// Copies the arc references into the given map. |
| 1014 | 1014 |
template <typename ArcRef> |
| 1015 | 1015 |
GraphCopy& arcRef(ArcRef& map) {
|
| 1016 |
_arc_maps.push_back(new _graph_utils_bits::RefCopy<From, Arc, |
|
| 1017 |
ArcRefMap, ArcRef>(map)); |
|
| 1016 |
_arc_maps.push_back(new _graph_utils_bits::RefCopy<From, Arc, |
|
| 1017 |
ArcRefMap, ArcRef>(map)); |
|
| 1018 | 1018 |
return *this; |
| 1019 | 1019 |
} |
| 1020 | 1020 |
|
| 1021 | 1021 |
/// \brief Copies the arc cross references into the given map. |
| 1022 | 1022 |
/// |
| 1023 | 1023 |
/// Copies the arc cross references (reverse references) into |
| 1024 | 1024 |
/// the given map. |
| 1025 | 1025 |
template <typename ArcCrossRef> |
| 1026 | 1026 |
GraphCopy& arcCrossRef(ArcCrossRef& map) {
|
| 1027 | 1027 |
_arc_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, Arc, |
| 1028 |
|
|
| 1028 |
ArcRefMap, ArcCrossRef>(map)); |
|
| 1029 | 1029 |
return *this; |
| 1030 | 1030 |
} |
| 1031 | 1031 |
|
| 1032 | 1032 |
/// \brief Make copy of the given map. |
| 1033 | 1033 |
/// |
| 1034 |
/// Makes copy of the given map for the newly created graph. |
|
| 1034 |
/// Makes copy of the given map for the newly created graph. |
|
| 1035 | 1035 |
/// The new map's key type is the to graph's arc type, |
| 1036 | 1036 |
/// and the copied map's key type is the from graph's arc |
| 1037 |
/// type. |
|
| 1037 |
/// type. |
|
| 1038 | 1038 |
template <typename ToMap, typename FromMap> |
| 1039 | 1039 |
GraphCopy& arcMap(ToMap& tmap, const FromMap& map) {
|
| 1040 |
_arc_maps.push_back(new _graph_utils_bits::MapCopy<From, Arc, |
|
| 1041 |
ArcRefMap, ToMap, FromMap>(tmap, map)); |
|
| 1040 |
_arc_maps.push_back(new _graph_utils_bits::MapCopy<From, Arc, |
|
| 1041 |
ArcRefMap, ToMap, FromMap>(tmap, map)); |
|
| 1042 | 1042 |
return *this; |
| 1043 | 1043 |
} |
| 1044 | 1044 |
|
| 1045 | 1045 |
/// \brief Make a copy of the given arc. |
| 1046 | 1046 |
/// |
| 1047 | 1047 |
/// Make a copy of the given arc. |
| 1048 | 1048 |
GraphCopy& arc(TArc& tarc, const Arc& sarc) {
|
| 1049 |
_arc_maps.push_back(new _graph_utils_bits::ItemCopy<From, Arc, |
|
| 1050 |
ArcRefMap, TArc>(tarc, sarc)); |
|
| 1049 |
_arc_maps.push_back(new _graph_utils_bits::ItemCopy<From, Arc, |
|
| 1050 |
ArcRefMap, TArc>(tarc, sarc)); |
|
| 1051 | 1051 |
return *this; |
| 1052 | 1052 |
} |
| 1053 | 1053 |
|
| 1054 | 1054 |
/// \brief Copies the edge references into the given map. |
| 1055 | 1055 |
/// |
| 1056 | 1056 |
/// Copies the edge references into the given map. |
| 1057 | 1057 |
template <typename EdgeRef> |
| 1058 | 1058 |
GraphCopy& edgeRef(EdgeRef& map) {
|
| 1059 |
_edge_maps.push_back(new _graph_utils_bits::RefCopy<From, Edge, |
|
| 1060 |
EdgeRefMap, EdgeRef>(map)); |
|
| 1059 |
_edge_maps.push_back(new _graph_utils_bits::RefCopy<From, Edge, |
|
| 1060 |
EdgeRefMap, EdgeRef>(map)); |
|
| 1061 | 1061 |
return *this; |
| 1062 | 1062 |
} |
| 1063 | 1063 |
|
| 1064 | 1064 |
/// \brief Copies the edge cross references into the given map. |
| 1065 | 1065 |
/// |
| 1066 | 1066 |
/// Copies the edge cross references (reverse |
| 1067 | 1067 |
/// references) into the given map. |
| 1068 | 1068 |
template <typename EdgeCrossRef> |
| 1069 | 1069 |
GraphCopy& edgeCrossRef(EdgeCrossRef& map) {
|
| 1070 |
_edge_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, |
|
| 1071 |
Edge, EdgeRefMap, EdgeCrossRef>(map)); |
|
| 1070 |
_edge_maps.push_back(new _graph_utils_bits::CrossRefCopy<From, |
|
| 1071 |
Edge, EdgeRefMap, EdgeCrossRef>(map)); |
|
| 1072 | 1072 |
return *this; |
| 1073 | 1073 |
} |
| 1074 | 1074 |
|
| 1075 | 1075 |
/// \brief Make copy of the given map. |
| 1076 | 1076 |
/// |
| 1077 |
/// Makes copy of the given map for the newly created graph. |
|
| 1077 |
/// Makes copy of the given map for the newly created graph. |
|
| 1078 | 1078 |
/// The new map's key type is the to graph's edge type, |
| 1079 | 1079 |
/// and the copied map's key type is the from graph's edge |
| 1080 |
/// type. |
|
| 1080 |
/// type. |
|
| 1081 | 1081 |
template <typename ToMap, typename FromMap> |
| 1082 | 1082 |
GraphCopy& edgeMap(ToMap& tmap, const FromMap& map) {
|
| 1083 |
_edge_maps.push_back(new _graph_utils_bits::MapCopy<From, Edge, |
|
| 1084 |
EdgeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 1083 |
_edge_maps.push_back(new _graph_utils_bits::MapCopy<From, Edge, |
|
| 1084 |
EdgeRefMap, ToMap, FromMap>(tmap, map)); |
|
| 1085 | 1085 |
return *this; |
| 1086 | 1086 |
} |
| 1087 | 1087 |
|
| 1088 | 1088 |
/// \brief Make a copy of the given edge. |
| 1089 | 1089 |
/// |
| 1090 | 1090 |
/// Make a copy of the given edge. |
| 1091 | 1091 |
GraphCopy& edge(TEdge& tedge, const Edge& sedge) {
|
| 1092 |
_edge_maps.push_back(new _graph_utils_bits::ItemCopy<From, Edge, |
|
| 1093 |
EdgeRefMap, TEdge>(tedge, sedge)); |
|
| 1092 |
_edge_maps.push_back(new _graph_utils_bits::ItemCopy<From, Edge, |
|
| 1093 |
EdgeRefMap, TEdge>(tedge, sedge)); |
|
| 1094 | 1094 |
return *this; |
| 1095 | 1095 |
} |
| 1096 | 1096 |
|
| 1097 | 1097 |
/// \brief Executes the copies. |
| 1098 | 1098 |
/// |
| 1099 | 1099 |
/// Executes the copies. |
| 1100 | 1100 |
void run() {
|
| 1101 | 1101 |
NodeRefMap nodeRefMap(_from); |
| 1102 | 1102 |
EdgeRefMap edgeRefMap(_from); |
| 1103 | 1103 |
ArcRefMap arcRefMap(_to, _from, edgeRefMap, nodeRefMap); |
| 1104 | 1104 |
_graph_utils_bits::GraphCopySelector<To>:: |
| 1105 | 1105 |
copy(_to, _from, nodeRefMap, edgeRefMap); |
| 1106 | 1106 |
for (int i = 0; i < int(_node_maps.size()); ++i) {
|
| 1107 | 1107 |
_node_maps[i]->copy(_from, nodeRefMap); |
| 1108 | 1108 |
} |
| 1109 | 1109 |
for (int i = 0; i < int(_edge_maps.size()); ++i) {
|
| 1110 | 1110 |
_edge_maps[i]->copy(_from, edgeRefMap); |
| 1111 | 1111 |
} |
| 1112 | 1112 |
for (int i = 0; i < int(_arc_maps.size()); ++i) {
|
| 1113 | 1113 |
_arc_maps[i]->copy(_from, arcRefMap); |
| 1114 | 1114 |
} |
| 1115 | 1115 |
} |
| 1116 | 1116 |
|
| 1117 | 1117 |
private: |
| 1118 |
|
|
| 1118 |
|
|
| 1119 | 1119 |
const From& _from; |
| 1120 | 1120 |
To& _to; |
| 1121 | 1121 |
|
| 1122 |
std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > |
|
| 1122 |
std::vector<_graph_utils_bits::MapCopyBase<From, Node, NodeRefMap>* > |
|
| 1123 | 1123 |
_node_maps; |
| 1124 | 1124 |
|
| 1125 |
std::vector<_graph_utils_bits::MapCopyBase<From, Arc, ArcRefMap>* > |
|
| 1125 |
std::vector<_graph_utils_bits::MapCopyBase<From, Arc, ArcRefMap>* > |
|
| 1126 | 1126 |
_arc_maps; |
| 1127 | 1127 |
|
| 1128 |
std::vector<_graph_utils_bits::MapCopyBase<From, Edge, EdgeRefMap>* > |
|
| 1128 |
std::vector<_graph_utils_bits::MapCopyBase<From, Edge, EdgeRefMap>* > |
|
| 1129 | 1129 |
_edge_maps; |
| 1130 | 1130 |
|
| 1131 | 1131 |
}; |
| 1132 | 1132 |
|
| 1133 | 1133 |
/// \brief Copy a graph to another graph. |
| 1134 | 1134 |
/// |
| 1135 | 1135 |
/// Copy a graph to another graph. The complete usage of the |
| 1136 | 1136 |
/// function is detailed in the GraphCopy class, but a short |
| 1137 | 1137 |
/// example shows a basic work: |
| 1138 | 1138 |
///\code |
| 1139 | 1139 |
/// copyGraph(trg, src).nodeRef(nr).arcCrossRef(ecr).run(); |
| 1140 | 1140 |
///\endcode |
| 1141 |
/// |
|
| 1141 |
/// |
|
| 1142 | 1142 |
/// After the copy the \c nr map will contain the mapping from the |
| 1143 | 1143 |
/// nodes of the \c from graph to the nodes of the \c to graph and |
| 1144 | 1144 |
/// \c ecr will contain the mapping from the arcs of the \c to graph |
| 1145 | 1145 |
/// to the arcs of the \c from graph. |
| 1146 | 1146 |
/// |
| 1147 |
/// \see GraphCopy |
|
| 1147 |
/// \see GraphCopy |
|
| 1148 | 1148 |
template <typename To, typename From> |
| 1149 |
GraphCopy<To, From> |
|
| 1149 |
GraphCopy<To, From> |
|
| 1150 | 1150 |
copyGraph(To& to, const From& from) {
|
| 1151 | 1151 |
return GraphCopy<To, From>(to, from); |
| 1152 | 1152 |
} |
| 1153 | 1153 |
|
| 1154 | 1154 |
/// @} |
| 1155 | 1155 |
|
| 1156 | 1156 |
/// \addtogroup graph_maps |
| 1157 | 1157 |
/// @{
|
| 1158 | 1158 |
|
| 1159 | 1159 |
/// Provides an immutable and unique id for each item in the graph. |
| 1160 | 1160 |
|
| 1161 | 1161 |
/// The IdMap class provides a unique and immutable id for each item of the |
| 1162 | 1162 |
/// same type (e.g. node) in the graph. This id is <ul><li>\b unique: |
| 1163 | 1163 |
/// different items (nodes) get different ids <li>\b immutable: the id of an |
| 1164 | 1164 |
/// item (node) does not change (even if you delete other nodes). </ul> |
| 1165 | 1165 |
/// Through this map you get access (i.e. can read) the inner id values of |
| ... | ... |
@@ -1201,354 +1201,354 @@ |
| 1201 | 1201 |
class InverseMap {
|
| 1202 | 1202 |
public: |
| 1203 | 1203 |
|
| 1204 | 1204 |
/// \brief Constructor. |
| 1205 | 1205 |
/// |
| 1206 | 1206 |
/// Constructor for creating an id-to-item map. |
| 1207 | 1207 |
explicit InverseMap(const Graph& graph) : _graph(&graph) {}
|
| 1208 | 1208 |
|
| 1209 | 1209 |
/// \brief Constructor. |
| 1210 | 1210 |
/// |
| 1211 | 1211 |
/// Constructor for creating an id-to-item map. |
| 1212 | 1212 |
explicit InverseMap(const IdMap& map) : _graph(map._graph) {}
|
| 1213 | 1213 |
|
| 1214 | 1214 |
/// \brief Gives back the given item from its id. |
| 1215 | 1215 |
/// |
| 1216 | 1216 |
/// Gives back the given item from its id. |
| 1217 |
/// |
|
| 1217 |
/// |
|
| 1218 | 1218 |
Item operator[](int id) const { return _graph->fromId(id, Item());}
|
| 1219 | 1219 |
|
| 1220 | 1220 |
private: |
| 1221 | 1221 |
const Graph* _graph; |
| 1222 | 1222 |
}; |
| 1223 | 1223 |
|
| 1224 | 1224 |
/// \brief Gives back the inverse of the map. |
| 1225 | 1225 |
/// |
| 1226 | 1226 |
/// Gives back the inverse of the IdMap. |
| 1227 |
InverseMap inverse() const { return InverseMap(*_graph);}
|
|
| 1227 |
InverseMap inverse() const { return InverseMap(*_graph);}
|
|
| 1228 | 1228 |
|
| 1229 | 1229 |
}; |
| 1230 | 1230 |
|
| 1231 |
|
|
| 1231 |
|
|
| 1232 | 1232 |
/// \brief General invertable graph-map type. |
| 1233 | 1233 |
|
| 1234 |
/// This type provides simple invertable graph-maps. |
|
| 1235 |
/// The InvertableMap wraps an arbitrary ReadWriteMap |
|
| 1234 |
/// This type provides simple invertable graph-maps. |
|
| 1235 |
/// The InvertableMap wraps an arbitrary ReadWriteMap |
|
| 1236 | 1236 |
/// and if a key is set to a new value then store it |
| 1237 | 1237 |
/// in the inverse map. |
| 1238 | 1238 |
/// |
| 1239 | 1239 |
/// The values of the map can be accessed |
| 1240 | 1240 |
/// with stl compatible forward iterator. |
| 1241 | 1241 |
/// |
| 1242 | 1242 |
/// \tparam _Graph The graph type. |
| 1243 | 1243 |
/// \tparam _Item The item type of the graph. |
| 1244 | 1244 |
/// \tparam _Value The value type of the map. |
| 1245 | 1245 |
/// |
| 1246 | 1246 |
/// \see IterableValueMap |
| 1247 | 1247 |
template <typename _Graph, typename _Item, typename _Value> |
| 1248 | 1248 |
class InvertableMap : protected DefaultMap<_Graph, _Item, _Value> {
|
| 1249 | 1249 |
private: |
| 1250 |
|
|
| 1250 |
|
|
| 1251 | 1251 |
typedef DefaultMap<_Graph, _Item, _Value> Map; |
| 1252 | 1252 |
typedef _Graph Graph; |
| 1253 | 1253 |
|
| 1254 | 1254 |
typedef std::map<_Value, _Item> Container; |
| 1255 |
Container _inv_map; |
|
| 1255 |
Container _inv_map; |
|
| 1256 | 1256 |
|
| 1257 | 1257 |
public: |
| 1258 |
|
|
| 1258 |
|
|
| 1259 | 1259 |
/// The key type of InvertableMap (Node, Arc, Edge). |
| 1260 | 1260 |
typedef typename Map::Key Key; |
| 1261 | 1261 |
/// The value type of the InvertableMap. |
| 1262 | 1262 |
typedef typename Map::Value Value; |
| 1263 | 1263 |
|
| 1264 | 1264 |
|
| 1265 | 1265 |
|
| 1266 | 1266 |
/// \brief Constructor. |
| 1267 | 1267 |
/// |
| 1268 | 1268 |
/// Construct a new InvertableMap for the graph. |
| 1269 | 1269 |
/// |
| 1270 |
explicit InvertableMap(const Graph& graph) : Map(graph) {}
|
|
| 1270 |
explicit InvertableMap(const Graph& graph) : Map(graph) {}
|
|
| 1271 | 1271 |
|
| 1272 | 1272 |
/// \brief Forward iterator for values. |
| 1273 | 1273 |
/// |
| 1274 | 1274 |
/// This iterator is an stl compatible forward |
| 1275 | 1275 |
/// iterator on the values of the map. The values can |
| 1276 | 1276 |
/// be accessed in the [beginValue, endValue) range. |
| 1277 | 1277 |
/// |
| 1278 |
class ValueIterator |
|
| 1278 |
class ValueIterator |
|
| 1279 | 1279 |
: public std::iterator<std::forward_iterator_tag, Value> {
|
| 1280 | 1280 |
friend class InvertableMap; |
| 1281 | 1281 |
private: |
| 1282 |
ValueIterator(typename Container::const_iterator _it) |
|
| 1282 |
ValueIterator(typename Container::const_iterator _it) |
|
| 1283 | 1283 |
: it(_it) {}
|
| 1284 | 1284 |
public: |
| 1285 |
|
|
| 1285 |
|
|
| 1286 | 1286 |
ValueIterator() {}
|
| 1287 | 1287 |
|
| 1288 | 1288 |
ValueIterator& operator++() { ++it; return *this; }
|
| 1289 |
ValueIterator operator++(int) {
|
|
| 1290 |
ValueIterator tmp(*this); |
|
| 1289 |
ValueIterator operator++(int) {
|
|
| 1290 |
ValueIterator tmp(*this); |
|
| 1291 | 1291 |
operator++(); |
| 1292 |
return tmp; |
|
| 1292 |
return tmp; |
|
| 1293 | 1293 |
} |
| 1294 | 1294 |
|
| 1295 | 1295 |
const Value& operator*() const { return it->first; }
|
| 1296 | 1296 |
const Value* operator->() const { return &(it->first); }
|
| 1297 | 1297 |
|
| 1298 | 1298 |
bool operator==(ValueIterator jt) const { return it == jt.it; }
|
| 1299 | 1299 |
bool operator!=(ValueIterator jt) const { return it != jt.it; }
|
| 1300 |
|
|
| 1300 |
|
|
| 1301 | 1301 |
private: |
| 1302 | 1302 |
typename Container::const_iterator it; |
| 1303 | 1303 |
}; |
| 1304 | 1304 |
|
| 1305 | 1305 |
/// \brief Returns an iterator to the first value. |
| 1306 | 1306 |
/// |
| 1307 |
/// Returns an stl compatible iterator to the |
|
| 1307 |
/// Returns an stl compatible iterator to the |
|
| 1308 | 1308 |
/// first value of the map. The values of the |
| 1309 | 1309 |
/// map can be accessed in the [beginValue, endValue) |
| 1310 | 1310 |
/// range. |
| 1311 | 1311 |
ValueIterator beginValue() const {
|
| 1312 | 1312 |
return ValueIterator(_inv_map.begin()); |
| 1313 | 1313 |
} |
| 1314 | 1314 |
|
| 1315 | 1315 |
/// \brief Returns an iterator after the last value. |
| 1316 | 1316 |
/// |
| 1317 |
/// Returns an stl compatible iterator after the |
|
| 1317 |
/// Returns an stl compatible iterator after the |
|
| 1318 | 1318 |
/// last value of the map. The values of the |
| 1319 | 1319 |
/// map can be accessed in the [beginValue, endValue) |
| 1320 | 1320 |
/// range. |
| 1321 | 1321 |
ValueIterator endValue() const {
|
| 1322 | 1322 |
return ValueIterator(_inv_map.end()); |
| 1323 | 1323 |
} |
| 1324 |
|
|
| 1324 |
|
|
| 1325 | 1325 |
/// \brief The setter function of the map. |
| 1326 | 1326 |
/// |
| 1327 | 1327 |
/// Sets the mapped value. |
| 1328 | 1328 |
void set(const Key& key, const Value& val) {
|
| 1329 | 1329 |
Value oldval = Map::operator[](key); |
| 1330 | 1330 |
typename Container::iterator it = _inv_map.find(oldval); |
| 1331 | 1331 |
if (it != _inv_map.end() && it->second == key) {
|
| 1332 |
_inv_map.erase(it); |
|
| 1333 |
} |
|
| 1332 |
_inv_map.erase(it); |
|
| 1333 |
} |
|
| 1334 | 1334 |
_inv_map.insert(make_pair(val, key)); |
| 1335 | 1335 |
Map::set(key, val); |
| 1336 | 1336 |
} |
| 1337 | 1337 |
|
| 1338 | 1338 |
/// \brief The getter function of the map. |
| 1339 | 1339 |
/// |
| 1340 | 1340 |
/// It gives back the value associated with the key. |
| 1341 |
typename MapTraits<Map>::ConstReturnValue |
|
| 1341 |
typename MapTraits<Map>::ConstReturnValue |
|
| 1342 | 1342 |
operator[](const Key& key) const {
|
| 1343 | 1343 |
return Map::operator[](key); |
| 1344 | 1344 |
} |
| 1345 | 1345 |
|
| 1346 | 1346 |
/// \brief Gives back the item by its value. |
| 1347 | 1347 |
/// |
| 1348 | 1348 |
/// Gives back the item by its value. |
| 1349 | 1349 |
Key operator()(const Value& key) const {
|
| 1350 | 1350 |
typename Container::const_iterator it = _inv_map.find(key); |
| 1351 | 1351 |
return it != _inv_map.end() ? it->second : INVALID; |
| 1352 | 1352 |
} |
| 1353 | 1353 |
|
| 1354 | 1354 |
protected: |
| 1355 | 1355 |
|
| 1356 | 1356 |
/// \brief Erase the key from the map. |
| 1357 | 1357 |
/// |
| 1358 | 1358 |
/// Erase the key to the map. It is called by the |
| 1359 | 1359 |
/// \c AlterationNotifier. |
| 1360 | 1360 |
virtual void erase(const Key& key) {
|
| 1361 | 1361 |
Value val = Map::operator[](key); |
| 1362 | 1362 |
typename Container::iterator it = _inv_map.find(val); |
| 1363 | 1363 |
if (it != _inv_map.end() && it->second == key) {
|
| 1364 |
|
|
| 1364 |
_inv_map.erase(it); |
|
| 1365 | 1365 |
} |
| 1366 | 1366 |
Map::erase(key); |
| 1367 | 1367 |
} |
| 1368 | 1368 |
|
| 1369 | 1369 |
/// \brief Erase more keys from the map. |
| 1370 | 1370 |
/// |
| 1371 | 1371 |
/// Erase more keys from the map. It is called by the |
| 1372 | 1372 |
/// \c AlterationNotifier. |
| 1373 | 1373 |
virtual void erase(const std::vector<Key>& keys) {
|
| 1374 | 1374 |
for (int i = 0; i < int(keys.size()); ++i) {
|
| 1375 |
Value val = Map::operator[](keys[i]); |
|
| 1376 |
typename Container::iterator it = _inv_map.find(val); |
|
| 1377 |
if (it != _inv_map.end() && it->second == keys[i]) {
|
|
| 1378 |
_inv_map.erase(it); |
|
| 1379 |
|
|
| 1375 |
Value val = Map::operator[](keys[i]); |
|
| 1376 |
typename Container::iterator it = _inv_map.find(val); |
|
| 1377 |
if (it != _inv_map.end() && it->second == keys[i]) {
|
|
| 1378 |
_inv_map.erase(it); |
|
| 1379 |
} |
|
| 1380 | 1380 |
} |
| 1381 | 1381 |
Map::erase(keys); |
| 1382 | 1382 |
} |
| 1383 | 1383 |
|
| 1384 | 1384 |
/// \brief Clear the keys from the map and inverse map. |
| 1385 | 1385 |
/// |
| 1386 | 1386 |
/// Clear the keys from the map and inverse map. It is called by the |
| 1387 | 1387 |
/// \c AlterationNotifier. |
| 1388 | 1388 |
virtual void clear() {
|
| 1389 | 1389 |
_inv_map.clear(); |
| 1390 | 1390 |
Map::clear(); |
| 1391 | 1391 |
} |
| 1392 | 1392 |
|
| 1393 | 1393 |
public: |
| 1394 | 1394 |
|
| 1395 | 1395 |
/// \brief The inverse map type. |
| 1396 | 1396 |
/// |
| 1397 | 1397 |
/// The inverse of this map. The subscript operator of the map |
| 1398 |
/// gives back always the item what was last assigned to the value. |
|
| 1398 |
/// gives back always the item what was last assigned to the value. |
|
| 1399 | 1399 |
class InverseMap {
|
| 1400 | 1400 |
public: |
| 1401 | 1401 |
/// \brief Constructor of the InverseMap. |
| 1402 | 1402 |
/// |
| 1403 | 1403 |
/// Constructor of the InverseMap. |
| 1404 |
explicit InverseMap(const InvertableMap& inverted) |
|
| 1404 |
explicit InverseMap(const InvertableMap& inverted) |
|
| 1405 | 1405 |
: _inverted(inverted) {}
|
| 1406 | 1406 |
|
| 1407 | 1407 |
/// The value type of the InverseMap. |
| 1408 | 1408 |
typedef typename InvertableMap::Key Value; |
| 1409 | 1409 |
/// The key type of the InverseMap. |
| 1410 |
typedef typename InvertableMap::Value Key; |
|
| 1411 |
|
|
| 1412 |
|
|
| 1410 |
typedef typename InvertableMap::Value Key; |
|
| 1411 |
|
|
| 1412 |
/// \brief Subscript operator. |
|
| 1413 | 1413 |
/// |
| 1414 |
/// Subscript operator. It gives back always the item |
|
| 1414 |
/// Subscript operator. It gives back always the item |
|
| 1415 | 1415 |
/// what was last assigned to the value. |
| 1416 | 1416 |
Value operator[](const Key& key) const {
|
| 1417 |
|
|
| 1417 |
return _inverted(key); |
|
| 1418 | 1418 |
} |
| 1419 |
|
|
| 1419 |
|
|
| 1420 | 1420 |
private: |
| 1421 | 1421 |
const InvertableMap& _inverted; |
| 1422 | 1422 |
}; |
| 1423 | 1423 |
|
| 1424 | 1424 |
/// \brief It gives back the just readable inverse map. |
| 1425 | 1425 |
/// |
| 1426 | 1426 |
/// It gives back the just readable inverse map. |
| 1427 | 1427 |
InverseMap inverse() const {
|
| 1428 | 1428 |
return InverseMap(*this); |
| 1429 |
} |
|
| 1430 |
|
|
| 1431 |
|
|
| 1432 |
|
|
| 1429 |
} |
|
| 1430 |
|
|
| 1431 |
|
|
| 1432 |
|
|
| 1433 | 1433 |
}; |
| 1434 | 1434 |
|
| 1435 |
/// \brief Provides a mutable, continuous and unique descriptor for each |
|
| 1435 |
/// \brief Provides a mutable, continuous and unique descriptor for each |
|
| 1436 | 1436 |
/// item in the graph. |
| 1437 | 1437 |
/// |
| 1438 | 1438 |
/// The DescriptorMap class provides a unique and continuous (but mutable) |
| 1439 | 1439 |
/// descriptor (id) for each item of the same type (e.g. node) in the |
| 1440 | 1440 |
/// graph. This id is <ul><li>\b unique: different items (nodes) get |
| 1441 | 1441 |
/// different ids <li>\b continuous: the range of the ids is the set of |
| 1442 | 1442 |
/// integers between 0 and \c n-1, where \c n is the number of the items of |
| 1443 | 1443 |
/// this type (e.g. nodes) (so the id of a node can change if you delete an |
| 1444 | 1444 |
/// other node, i.e. this id is mutable). </ul> This map can be inverted |
| 1445 | 1445 |
/// with its member class \c InverseMap, or with the \c operator() member. |
| 1446 | 1446 |
/// |
| 1447 | 1447 |
/// \tparam _Graph The graph class the \c DescriptorMap belongs to. |
| 1448 |
/// \tparam _Item The Item is the Key of the Map. It may be Node, Arc or |
|
| 1448 |
/// \tparam _Item The Item is the Key of the Map. It may be Node, Arc or |
|
| 1449 | 1449 |
/// Edge. |
| 1450 | 1450 |
template <typename _Graph, typename _Item> |
| 1451 | 1451 |
class DescriptorMap : protected DefaultMap<_Graph, _Item, int> {
|
| 1452 | 1452 |
|
| 1453 | 1453 |
typedef _Item Item; |
| 1454 | 1454 |
typedef DefaultMap<_Graph, _Item, int> Map; |
| 1455 | 1455 |
|
| 1456 | 1456 |
public: |
| 1457 | 1457 |
/// The graph class of DescriptorMap. |
| 1458 | 1458 |
typedef _Graph Graph; |
| 1459 | 1459 |
|
| 1460 | 1460 |
/// The key type of DescriptorMap (Node, Arc, Edge). |
| 1461 | 1461 |
typedef typename Map::Key Key; |
| 1462 | 1462 |
/// The value type of DescriptorMap. |
| 1463 | 1463 |
typedef typename Map::Value Value; |
| 1464 | 1464 |
|
| 1465 | 1465 |
/// \brief Constructor. |
| 1466 | 1466 |
/// |
| 1467 | 1467 |
/// Constructor for descriptor map. |
| 1468 | 1468 |
explicit DescriptorMap(const Graph& _graph) : Map(_graph) {
|
| 1469 | 1469 |
Item it; |
| 1470 |
const typename Map::Notifier* nf = Map::notifier(); |
|
| 1470 |
const typename Map::Notifier* nf = Map::notifier(); |
|
| 1471 | 1471 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 1472 |
Map::set(it, _inv_map.size()); |
|
| 1473 |
_inv_map.push_back(it); |
|
| 1474 |
|
|
| 1472 |
Map::set(it, _inv_map.size()); |
|
| 1473 |
_inv_map.push_back(it); |
|
| 1474 |
} |
|
| 1475 | 1475 |
} |
| 1476 | 1476 |
|
| 1477 | 1477 |
protected: |
| 1478 | 1478 |
|
| 1479 | 1479 |
/// \brief Add a new key to the map. |
| 1480 | 1480 |
/// |
| 1481 | 1481 |
/// Add a new key to the map. It is called by the |
| 1482 | 1482 |
/// \c AlterationNotifier. |
| 1483 | 1483 |
virtual void add(const Item& item) {
|
| 1484 | 1484 |
Map::add(item); |
| 1485 | 1485 |
Map::set(item, _inv_map.size()); |
| 1486 | 1486 |
_inv_map.push_back(item); |
| 1487 | 1487 |
} |
| 1488 | 1488 |
|
| 1489 | 1489 |
/// \brief Add more new keys to the map. |
| 1490 | 1490 |
/// |
| 1491 | 1491 |
/// Add more new keys to the map. It is called by the |
| 1492 | 1492 |
/// \c AlterationNotifier. |
| 1493 | 1493 |
virtual void add(const std::vector<Item>& items) {
|
| 1494 | 1494 |
Map::add(items); |
| 1495 | 1495 |
for (int i = 0; i < int(items.size()); ++i) {
|
| 1496 |
Map::set(items[i], _inv_map.size()); |
|
| 1497 |
_inv_map.push_back(items[i]); |
|
| 1496 |
Map::set(items[i], _inv_map.size()); |
|
| 1497 |
_inv_map.push_back(items[i]); |
|
| 1498 | 1498 |
} |
| 1499 | 1499 |
} |
| 1500 | 1500 |
|
| 1501 | 1501 |
/// \brief Erase the key from the map. |
| 1502 | 1502 |
/// |
| 1503 | 1503 |
/// Erase the key from the map. It is called by the |
| 1504 | 1504 |
/// \c AlterationNotifier. |
| 1505 | 1505 |
virtual void erase(const Item& item) {
|
| 1506 | 1506 |
Map::set(_inv_map.back(), Map::operator[](item)); |
| 1507 | 1507 |
_inv_map[Map::operator[](item)] = _inv_map.back(); |
| 1508 | 1508 |
_inv_map.pop_back(); |
| 1509 | 1509 |
Map::erase(item); |
| 1510 | 1510 |
} |
| 1511 | 1511 |
|
| 1512 | 1512 |
/// \brief Erase more keys from the map. |
| 1513 | 1513 |
/// |
| 1514 | 1514 |
/// Erase more keys from the map. It is called by the |
| 1515 | 1515 |
/// \c AlterationNotifier. |
| 1516 | 1516 |
virtual void erase(const std::vector<Item>& items) {
|
| 1517 | 1517 |
for (int i = 0; i < int(items.size()); ++i) {
|
| 1518 |
Map::set(_inv_map.back(), Map::operator[](items[i])); |
|
| 1519 |
_inv_map[Map::operator[](items[i])] = _inv_map.back(); |
|
| 1520 |
|
|
| 1518 |
Map::set(_inv_map.back(), Map::operator[](items[i])); |
|
| 1519 |
_inv_map[Map::operator[](items[i])] = _inv_map.back(); |
|
| 1520 |
_inv_map.pop_back(); |
|
| 1521 | 1521 |
} |
| 1522 | 1522 |
Map::erase(items); |
| 1523 | 1523 |
} |
| 1524 | 1524 |
|
| 1525 | 1525 |
/// \brief Build the unique map. |
| 1526 | 1526 |
/// |
| 1527 | 1527 |
/// Build the unique map. It is called by the |
| 1528 | 1528 |
/// \c AlterationNotifier. |
| 1529 | 1529 |
virtual void build() {
|
| 1530 | 1530 |
Map::build(); |
| 1531 | 1531 |
Item it; |
| 1532 |
const typename Map::Notifier* nf = Map::notifier(); |
|
| 1532 |
const typename Map::Notifier* nf = Map::notifier(); |
|
| 1533 | 1533 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
| 1534 |
Map::set(it, _inv_map.size()); |
|
| 1535 |
_inv_map.push_back(it); |
|
| 1536 |
|
|
| 1534 |
Map::set(it, _inv_map.size()); |
|
| 1535 |
_inv_map.push_back(it); |
|
| 1536 |
} |
|
| 1537 | 1537 |
} |
| 1538 |
|
|
| 1538 |
|
|
| 1539 | 1539 |
/// \brief Clear the keys from the map. |
| 1540 | 1540 |
/// |
| 1541 | 1541 |
/// Clear the keys from the map. It is called by the |
| 1542 | 1542 |
/// \c AlterationNotifier. |
| 1543 | 1543 |
virtual void clear() {
|
| 1544 | 1544 |
_inv_map.clear(); |
| 1545 | 1545 |
Map::clear(); |
| 1546 | 1546 |
} |
| 1547 | 1547 |
|
| 1548 | 1548 |
public: |
| 1549 | 1549 |
|
| 1550 | 1550 |
/// \brief Returns the maximal value plus one. |
| 1551 | 1551 |
/// |
| 1552 | 1552 |
/// Returns the maximal value plus one in the map. |
| 1553 | 1553 |
unsigned int size() const {
|
| 1554 | 1554 |
return _inv_map.size(); |
| ... | ... |
@@ -1566,144 +1566,144 @@ |
| 1566 | 1566 |
_inv_map[pi] = q; |
| 1567 | 1567 |
} |
| 1568 | 1568 |
|
| 1569 | 1569 |
/// \brief Gives back the \e descriptor of the item. |
| 1570 | 1570 |
/// |
| 1571 | 1571 |
/// Gives back the mutable and unique \e descriptor of the map. |
| 1572 | 1572 |
int operator[](const Item& item) const {
|
| 1573 | 1573 |
return Map::operator[](item); |
| 1574 | 1574 |
} |
| 1575 | 1575 |
|
| 1576 | 1576 |
/// \brief Gives back the item by its descriptor. |
| 1577 | 1577 |
/// |
| 1578 | 1578 |
/// Gives back th item by its descriptor. |
| 1579 | 1579 |
Item operator()(int id) const {
|
| 1580 | 1580 |
return _inv_map[id]; |
| 1581 | 1581 |
} |
| 1582 |
|
|
| 1582 |
|
|
| 1583 | 1583 |
private: |
| 1584 | 1584 |
|
| 1585 | 1585 |
typedef std::vector<Item> Container; |
| 1586 | 1586 |
Container _inv_map; |
| 1587 | 1587 |
|
| 1588 | 1588 |
public: |
| 1589 | 1589 |
/// \brief The inverse map type of DescriptorMap. |
| 1590 | 1590 |
/// |
| 1591 | 1591 |
/// The inverse map type of DescriptorMap. |
| 1592 | 1592 |
class InverseMap {
|
| 1593 | 1593 |
public: |
| 1594 | 1594 |
/// \brief Constructor of the InverseMap. |
| 1595 | 1595 |
/// |
| 1596 | 1596 |
/// Constructor of the InverseMap. |
| 1597 |
explicit InverseMap(const DescriptorMap& inverted) |
|
| 1598 |
: _inverted(inverted) {}
|
|
| 1597 |
explicit InverseMap(const DescriptorMap& inverted) |
|
| 1598 |
: _inverted(inverted) {}
|
|
| 1599 | 1599 |
|
| 1600 | 1600 |
|
| 1601 | 1601 |
/// The value type of the InverseMap. |
| 1602 | 1602 |
typedef typename DescriptorMap::Key Value; |
| 1603 | 1603 |
/// The key type of the InverseMap. |
| 1604 |
typedef typename DescriptorMap::Value Key; |
|
| 1605 |
|
|
| 1606 |
|
|
| 1604 |
typedef typename DescriptorMap::Value Key; |
|
| 1605 |
|
|
| 1606 |
/// \brief Subscript operator. |
|
| 1607 | 1607 |
/// |
| 1608 |
/// Subscript operator. It gives back the item |
|
| 1608 |
/// Subscript operator. It gives back the item |
|
| 1609 | 1609 |
/// that the descriptor belongs to currently. |
| 1610 | 1610 |
Value operator[](const Key& key) const {
|
| 1611 |
|
|
| 1611 |
return _inverted(key); |
|
| 1612 | 1612 |
} |
| 1613 | 1613 |
|
| 1614 | 1614 |
/// \brief Size of the map. |
| 1615 | 1615 |
/// |
| 1616 | 1616 |
/// Returns the size of the map. |
| 1617 | 1617 |
unsigned int size() const {
|
| 1618 |
|
|
| 1618 |
return _inverted.size(); |
|
| 1619 | 1619 |
} |
| 1620 |
|
|
| 1620 |
|
|
| 1621 | 1621 |
private: |
| 1622 | 1622 |
const DescriptorMap& _inverted; |
| 1623 | 1623 |
}; |
| 1624 | 1624 |
|
| 1625 | 1625 |
/// \brief Gives back the inverse of the map. |
| 1626 | 1626 |
/// |
| 1627 | 1627 |
/// Gives back the inverse of the map. |
| 1628 | 1628 |
const InverseMap inverse() const {
|
| 1629 | 1629 |
return InverseMap(*this); |
| 1630 | 1630 |
} |
| 1631 | 1631 |
}; |
| 1632 | 1632 |
|
| 1633 | 1633 |
/// \brief Returns the source of the given arc. |
| 1634 | 1634 |
/// |
| 1635 |
/// The SourceMap gives back the source Node of the given arc. |
|
| 1635 |
/// The SourceMap gives back the source Node of the given arc. |
|
| 1636 | 1636 |
/// \see TargetMap |
| 1637 | 1637 |
template <typename Digraph> |
| 1638 | 1638 |
class SourceMap {
|
| 1639 | 1639 |
public: |
| 1640 | 1640 |
|
| 1641 | 1641 |
typedef typename Digraph::Node Value; |
| 1642 | 1642 |
typedef typename Digraph::Arc Key; |
| 1643 | 1643 |
|
| 1644 | 1644 |
/// \brief Constructor |
| 1645 | 1645 |
/// |
| 1646 | 1646 |
/// Constructor |
| 1647 | 1647 |
/// \param _digraph The digraph that the map belongs to. |
| 1648 | 1648 |
explicit SourceMap(const Digraph& digraph) : _digraph(digraph) {}
|
| 1649 | 1649 |
|
| 1650 | 1650 |
/// \brief The subscript operator. |
| 1651 | 1651 |
/// |
| 1652 | 1652 |
/// The subscript operator. |
| 1653 |
/// \param arc The arc |
|
| 1654 |
/// \return The source of the arc |
|
| 1653 |
/// \param arc The arc |
|
| 1654 |
/// \return The source of the arc |
|
| 1655 | 1655 |
Value operator[](const Key& arc) const {
|
| 1656 | 1656 |
return _digraph.source(arc); |
| 1657 | 1657 |
} |
| 1658 | 1658 |
|
| 1659 | 1659 |
private: |
| 1660 | 1660 |
const Digraph& _digraph; |
| 1661 | 1661 |
}; |
| 1662 | 1662 |
|
| 1663 | 1663 |
/// \brief Returns a \ref SourceMap class. |
| 1664 | 1664 |
/// |
| 1665 | 1665 |
/// This function just returns an \ref SourceMap class. |
| 1666 | 1666 |
/// \relates SourceMap |
| 1667 | 1667 |
template <typename Digraph> |
| 1668 | 1668 |
inline SourceMap<Digraph> sourceMap(const Digraph& digraph) {
|
| 1669 | 1669 |
return SourceMap<Digraph>(digraph); |
| 1670 |
} |
|
| 1670 |
} |
|
| 1671 | 1671 |
|
| 1672 | 1672 |
/// \brief Returns the target of the given arc. |
| 1673 | 1673 |
/// |
| 1674 |
/// The TargetMap gives back the target Node of the given arc. |
|
| 1674 |
/// The TargetMap gives back the target Node of the given arc. |
|
| 1675 | 1675 |
/// \see SourceMap |
| 1676 | 1676 |
template <typename Digraph> |
| 1677 | 1677 |
class TargetMap {
|
| 1678 | 1678 |
public: |
| 1679 | 1679 |
|
| 1680 | 1680 |
typedef typename Digraph::Node Value; |
| 1681 | 1681 |
typedef typename Digraph::Arc Key; |
| 1682 | 1682 |
|
| 1683 | 1683 |
/// \brief Constructor |
| 1684 | 1684 |
/// |
| 1685 | 1685 |
/// Constructor |
| 1686 | 1686 |
/// \param _digraph The digraph that the map belongs to. |
| 1687 | 1687 |
explicit TargetMap(const Digraph& digraph) : _digraph(digraph) {}
|
| 1688 | 1688 |
|
| 1689 | 1689 |
/// \brief The subscript operator. |
| 1690 | 1690 |
/// |
| 1691 | 1691 |
/// The subscript operator. |
| 1692 |
/// \param e The arc |
|
| 1693 |
/// \return The target of the arc |
|
| 1692 |
/// \param e The arc |
|
| 1693 |
/// \return The target of the arc |
|
| 1694 | 1694 |
Value operator[](const Key& e) const {
|
| 1695 | 1695 |
return _digraph.target(e); |
| 1696 | 1696 |
} |
| 1697 | 1697 |
|
| 1698 | 1698 |
private: |
| 1699 | 1699 |
const Digraph& _digraph; |
| 1700 | 1700 |
}; |
| 1701 | 1701 |
|
| 1702 | 1702 |
/// \brief Returns a \ref TargetMap class. |
| 1703 | 1703 |
/// |
| 1704 | 1704 |
/// This function just returns a \ref TargetMap class. |
| 1705 | 1705 |
/// \relates TargetMap |
| 1706 | 1706 |
template <typename Digraph> |
| 1707 | 1707 |
inline TargetMap<Digraph> targetMap(const Digraph& digraph) {
|
| 1708 | 1708 |
return TargetMap<Digraph>(digraph); |
| 1709 | 1709 |
} |
| ... | ... |
@@ -1715,34 +1715,34 @@ |
| 1715 | 1715 |
template <typename Graph> |
| 1716 | 1716 |
class ForwardMap {
|
| 1717 | 1717 |
public: |
| 1718 | 1718 |
|
| 1719 | 1719 |
typedef typename Graph::Arc Value; |
| 1720 | 1720 |
typedef typename Graph::Edge Key; |
| 1721 | 1721 |
|
| 1722 | 1722 |
/// \brief Constructor |
| 1723 | 1723 |
/// |
| 1724 | 1724 |
/// Constructor |
| 1725 | 1725 |
/// \param _graph The graph that the map belongs to. |
| 1726 | 1726 |
explicit ForwardMap(const Graph& graph) : _graph(graph) {}
|
| 1727 | 1727 |
|
| 1728 | 1728 |
/// \brief The subscript operator. |
| 1729 | 1729 |
/// |
| 1730 | 1730 |
/// The subscript operator. |
| 1731 |
/// \param key An edge |
|
| 1732 |
/// \return The "forward" directed arc view of edge |
|
| 1731 |
/// \param key An edge |
|
| 1732 |
/// \return The "forward" directed arc view of edge |
|
| 1733 | 1733 |
Value operator[](const Key& key) const {
|
| 1734 | 1734 |
return _graph.direct(key, true); |
| 1735 | 1735 |
} |
| 1736 | 1736 |
|
| 1737 | 1737 |
private: |
| 1738 | 1738 |
const Graph& _graph; |
| 1739 | 1739 |
}; |
| 1740 | 1740 |
|
| 1741 | 1741 |
/// \brief Returns a \ref ForwardMap class. |
| 1742 | 1742 |
/// |
| 1743 | 1743 |
/// This function just returns an \ref ForwardMap class. |
| 1744 | 1744 |
/// \relates ForwardMap |
| 1745 | 1745 |
template <typename Graph> |
| 1746 | 1746 |
inline ForwardMap<Graph> forwardMap(const Graph& graph) {
|
| 1747 | 1747 |
return ForwardMap<Graph>(graph); |
| 1748 | 1748 |
} |
| ... | ... |
@@ -1754,980 +1754,980 @@ |
| 1754 | 1754 |
template <typename Graph> |
| 1755 | 1755 |
class BackwardMap {
|
| 1756 | 1756 |
public: |
| 1757 | 1757 |
|
| 1758 | 1758 |
typedef typename Graph::Arc Value; |
| 1759 | 1759 |
typedef typename Graph::Edge Key; |
| 1760 | 1760 |
|
| 1761 | 1761 |
/// \brief Constructor |
| 1762 | 1762 |
/// |
| 1763 | 1763 |
/// Constructor |
| 1764 | 1764 |
/// \param _graph The graph that the map belongs to. |
| 1765 | 1765 |
explicit BackwardMap(const Graph& graph) : _graph(graph) {}
|
| 1766 | 1766 |
|
| 1767 | 1767 |
/// \brief The subscript operator. |
| 1768 | 1768 |
/// |
| 1769 | 1769 |
/// The subscript operator. |
| 1770 |
/// \param key An edge |
|
| 1771 |
/// \return The "backward" directed arc view of edge |
|
| 1770 |
/// \param key An edge |
|
| 1771 |
/// \return The "backward" directed arc view of edge |
|
| 1772 | 1772 |
Value operator[](const Key& key) const {
|
| 1773 | 1773 |
return _graph.direct(key, false); |
| 1774 | 1774 |
} |
| 1775 | 1775 |
|
| 1776 | 1776 |
private: |
| 1777 | 1777 |
const Graph& _graph; |
| 1778 | 1778 |
}; |
| 1779 | 1779 |
|
| 1780 | 1780 |
/// \brief Returns a \ref BackwardMap class |
| 1781 | 1781 |
|
| 1782 | 1782 |
/// This function just returns a \ref BackwardMap class. |
| 1783 | 1783 |
/// \relates BackwardMap |
| 1784 | 1784 |
template <typename Graph> |
| 1785 | 1785 |
inline BackwardMap<Graph> backwardMap(const Graph& graph) {
|
| 1786 | 1786 |
return BackwardMap<Graph>(graph); |
| 1787 | 1787 |
} |
| 1788 | 1788 |
|
| 1789 | 1789 |
/// \brief Potential difference map |
| 1790 | 1790 |
/// |
| 1791 | 1791 |
/// If there is an potential map on the nodes then we |
| 1792 | 1792 |
/// can get an arc map as we get the substraction of the |
| 1793 | 1793 |
/// values of the target and source. |
| 1794 | 1794 |
template <typename Digraph, typename NodeMap> |
| 1795 | 1795 |
class PotentialDifferenceMap {
|
| 1796 | 1796 |
public: |
| 1797 | 1797 |
typedef typename Digraph::Arc Key; |
| 1798 | 1798 |
typedef typename NodeMap::Value Value; |
| 1799 | 1799 |
|
| 1800 | 1800 |
/// \brief Constructor |
| 1801 | 1801 |
/// |
| 1802 | 1802 |
/// Contructor of the map |
| 1803 |
explicit PotentialDifferenceMap(const Digraph& digraph, |
|
| 1804 |
const NodeMap& potential) |
|
| 1803 |
explicit PotentialDifferenceMap(const Digraph& digraph, |
|
| 1804 |
const NodeMap& potential) |
|
| 1805 | 1805 |
: _digraph(digraph), _potential(potential) {}
|
| 1806 | 1806 |
|
| 1807 | 1807 |
/// \brief Const subscription operator |
| 1808 | 1808 |
/// |
| 1809 | 1809 |
/// Const subscription operator |
| 1810 | 1810 |
Value operator[](const Key& arc) const {
|
| 1811 |
return _potential[_digraph.target(arc)] - |
|
| 1812 |
_potential[_digraph.source(arc)]; |
|
| 1811 |
return _potential[_digraph.target(arc)] - |
|
| 1812 |
_potential[_digraph.source(arc)]; |
|
| 1813 | 1813 |
} |
| 1814 | 1814 |
|
| 1815 | 1815 |
private: |
| 1816 | 1816 |
const Digraph& _digraph; |
| 1817 | 1817 |
const NodeMap& _potential; |
| 1818 | 1818 |
}; |
| 1819 | 1819 |
|
| 1820 | 1820 |
/// \brief Returns a PotentialDifferenceMap. |
| 1821 | 1821 |
/// |
| 1822 | 1822 |
/// This function just returns a PotentialDifferenceMap. |
| 1823 | 1823 |
/// \relates PotentialDifferenceMap |
| 1824 | 1824 |
template <typename Digraph, typename NodeMap> |
| 1825 |
PotentialDifferenceMap<Digraph, NodeMap> |
|
| 1825 |
PotentialDifferenceMap<Digraph, NodeMap> |
|
| 1826 | 1826 |
potentialDifferenceMap(const Digraph& digraph, const NodeMap& potential) {
|
| 1827 | 1827 |
return PotentialDifferenceMap<Digraph, NodeMap>(digraph, potential); |
| 1828 | 1828 |
} |
| 1829 | 1829 |
|
| 1830 | 1830 |
/// \brief Map of the node in-degrees. |
| 1831 | 1831 |
/// |
| 1832 | 1832 |
/// This map returns the in-degree of a node. Once it is constructed, |
| 1833 | 1833 |
/// the degrees are stored in a standard NodeMap, so each query is done |
| 1834 | 1834 |
/// in constant time. On the other hand, the values are updated automatically |
| 1835 | 1835 |
/// whenever the digraph changes. |
| 1836 | 1836 |
/// |
| 1837 | 1837 |
/// \warning Besides addNode() and addArc(), a digraph structure may provide |
| 1838 | 1838 |
/// alternative ways to modify the digraph. The correct behavior of InDegMap |
| 1839 | 1839 |
/// is not guarantied if these additional features are used. For example |
| 1840 | 1840 |
/// the functions \ref ListDigraph::changeSource() "changeSource()", |
| 1841 | 1841 |
/// \ref ListDigraph::changeTarget() "changeTarget()" and |
| 1842 | 1842 |
/// \ref ListDigraph::reverseArc() "reverseArc()" |
| 1843 | 1843 |
/// of \ref ListDigraph will \e not update the degree values correctly. |
| 1844 | 1844 |
/// |
| 1845 | 1845 |
/// \sa OutDegMap |
| 1846 | 1846 |
|
| 1847 | 1847 |
template <typename _Digraph> |
| 1848 |
class InDegMap |
|
| 1848 |
class InDegMap |
|
| 1849 | 1849 |
: protected ItemSetTraits<_Digraph, typename _Digraph::Arc> |
| 1850 | 1850 |
::ItemNotifier::ObserverBase {
|
| 1851 | 1851 |
|
| 1852 | 1852 |
public: |
| 1853 |
|
|
| 1853 |
|
|
| 1854 | 1854 |
typedef _Digraph Digraph; |
| 1855 | 1855 |
typedef int Value; |
| 1856 | 1856 |
typedef typename Digraph::Node Key; |
| 1857 | 1857 |
|
| 1858 | 1858 |
typedef typename ItemSetTraits<Digraph, typename Digraph::Arc> |
| 1859 | 1859 |
::ItemNotifier::ObserverBase Parent; |
| 1860 | 1860 |
|
| 1861 | 1861 |
private: |
| 1862 | 1862 |
|
| 1863 | 1863 |
class AutoNodeMap : public DefaultMap<Digraph, Key, int> {
|
| 1864 | 1864 |
public: |
| 1865 | 1865 |
|
| 1866 | 1866 |
typedef DefaultMap<Digraph, Key, int> Parent; |
| 1867 | 1867 |
|
| 1868 | 1868 |
AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {}
|
| 1869 |
|
|
| 1869 |
|
|
| 1870 | 1870 |
virtual void add(const Key& key) {
|
| 1871 |
Parent::add(key); |
|
| 1872 |
Parent::set(key, 0); |
|
| 1871 |
Parent::add(key); |
|
| 1872 |
Parent::set(key, 0); |
|
| 1873 | 1873 |
} |
| 1874 | 1874 |
|
| 1875 | 1875 |
virtual void add(const std::vector<Key>& keys) {
|
| 1876 |
Parent::add(keys); |
|
| 1877 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 1878 |
Parent::set(keys[i], 0); |
|
| 1879 |
} |
|
| 1876 |
Parent::add(keys); |
|
| 1877 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 1878 |
Parent::set(keys[i], 0); |
|
| 1879 |
} |
|
| 1880 | 1880 |
} |
| 1881 | 1881 |
|
| 1882 | 1882 |
virtual void build() {
|
| 1883 |
Parent::build(); |
|
| 1884 |
Key it; |
|
| 1885 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 1886 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 1887 |
Parent::set(it, 0); |
|
| 1888 |
} |
|
| 1883 |
Parent::build(); |
|
| 1884 |
Key it; |
|
| 1885 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 1886 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 1887 |
Parent::set(it, 0); |
|
| 1888 |
} |
|
| 1889 | 1889 |
} |
| 1890 | 1890 |
}; |
| 1891 | 1891 |
|
| 1892 | 1892 |
public: |
| 1893 | 1893 |
|
| 1894 | 1894 |
/// \brief Constructor. |
| 1895 | 1895 |
/// |
| 1896 | 1896 |
/// Constructor for creating in-degree map. |
| 1897 |
explicit InDegMap(const Digraph& digraph) |
|
| 1897 |
explicit InDegMap(const Digraph& digraph) |
|
| 1898 | 1898 |
: _digraph(digraph), _deg(digraph) {
|
| 1899 | 1899 |
Parent::attach(_digraph.notifier(typename Digraph::Arc())); |
| 1900 |
|
|
| 1900 |
|
|
| 1901 | 1901 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 1902 |
|
|
| 1902 |
_deg[it] = countInArcs(_digraph, it); |
|
| 1903 | 1903 |
} |
| 1904 | 1904 |
} |
| 1905 |
|
|
| 1905 |
|
|
| 1906 | 1906 |
/// Gives back the in-degree of a Node. |
| 1907 | 1907 |
int operator[](const Key& key) const {
|
| 1908 | 1908 |
return _deg[key]; |
| 1909 | 1909 |
} |
| 1910 | 1910 |
|
| 1911 | 1911 |
protected: |
| 1912 |
|
|
| 1912 |
|
|
| 1913 | 1913 |
typedef typename Digraph::Arc Arc; |
| 1914 | 1914 |
|
| 1915 | 1915 |
virtual void add(const Arc& arc) {
|
| 1916 | 1916 |
++_deg[_digraph.target(arc)]; |
| 1917 | 1917 |
} |
| 1918 | 1918 |
|
| 1919 | 1919 |
virtual void add(const std::vector<Arc>& arcs) {
|
| 1920 | 1920 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 1921 | 1921 |
++_deg[_digraph.target(arcs[i])]; |
| 1922 | 1922 |
} |
| 1923 | 1923 |
} |
| 1924 | 1924 |
|
| 1925 | 1925 |
virtual void erase(const Arc& arc) {
|
| 1926 | 1926 |
--_deg[_digraph.target(arc)]; |
| 1927 | 1927 |
} |
| 1928 | 1928 |
|
| 1929 | 1929 |
virtual void erase(const std::vector<Arc>& arcs) {
|
| 1930 | 1930 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 1931 | 1931 |
--_deg[_digraph.target(arcs[i])]; |
| 1932 | 1932 |
} |
| 1933 | 1933 |
} |
| 1934 | 1934 |
|
| 1935 | 1935 |
virtual void build() {
|
| 1936 | 1936 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 1937 |
_deg[it] = countInArcs(_digraph, it); |
|
| 1938 |
} |
|
| 1937 |
_deg[it] = countInArcs(_digraph, it); |
|
| 1938 |
} |
|
| 1939 | 1939 |
} |
| 1940 | 1940 |
|
| 1941 | 1941 |
virtual void clear() {
|
| 1942 | 1942 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 1943 |
|
|
| 1943 |
_deg[it] = 0; |
|
| 1944 | 1944 |
} |
| 1945 | 1945 |
} |
| 1946 | 1946 |
private: |
| 1947 |
|
|
| 1947 |
|
|
| 1948 | 1948 |
const Digraph& _digraph; |
| 1949 | 1949 |
AutoNodeMap _deg; |
| 1950 | 1950 |
}; |
| 1951 | 1951 |
|
| 1952 | 1952 |
/// \brief Map of the node out-degrees. |
| 1953 | 1953 |
/// |
| 1954 | 1954 |
/// This map returns the out-degree of a node. Once it is constructed, |
| 1955 | 1955 |
/// the degrees are stored in a standard NodeMap, so each query is done |
| 1956 | 1956 |
/// in constant time. On the other hand, the values are updated automatically |
| 1957 | 1957 |
/// whenever the digraph changes. |
| 1958 | 1958 |
/// |
| 1959 | 1959 |
/// \warning Besides addNode() and addArc(), a digraph structure may provide |
| 1960 | 1960 |
/// alternative ways to modify the digraph. The correct behavior of OutDegMap |
| 1961 | 1961 |
/// is not guarantied if these additional features are used. For example |
| 1962 | 1962 |
/// the functions \ref ListDigraph::changeSource() "changeSource()", |
| 1963 | 1963 |
/// \ref ListDigraph::changeTarget() "changeTarget()" and |
| 1964 | 1964 |
/// \ref ListDigraph::reverseArc() "reverseArc()" |
| 1965 | 1965 |
/// of \ref ListDigraph will \e not update the degree values correctly. |
| 1966 | 1966 |
/// |
| 1967 | 1967 |
/// \sa InDegMap |
| 1968 | 1968 |
|
| 1969 | 1969 |
template <typename _Digraph> |
| 1970 |
class OutDegMap |
|
| 1970 |
class OutDegMap |
|
| 1971 | 1971 |
: protected ItemSetTraits<_Digraph, typename _Digraph::Arc> |
| 1972 | 1972 |
::ItemNotifier::ObserverBase {
|
| 1973 | 1973 |
|
| 1974 | 1974 |
public: |
| 1975 |
|
|
| 1975 |
|
|
| 1976 | 1976 |
typedef _Digraph Digraph; |
| 1977 | 1977 |
typedef int Value; |
| 1978 | 1978 |
typedef typename Digraph::Node Key; |
| 1979 | 1979 |
|
| 1980 | 1980 |
typedef typename ItemSetTraits<Digraph, typename Digraph::Arc> |
| 1981 | 1981 |
::ItemNotifier::ObserverBase Parent; |
| 1982 | 1982 |
|
| 1983 | 1983 |
private: |
| 1984 | 1984 |
|
| 1985 | 1985 |
class AutoNodeMap : public DefaultMap<Digraph, Key, int> {
|
| 1986 | 1986 |
public: |
| 1987 | 1987 |
|
| 1988 | 1988 |
typedef DefaultMap<Digraph, Key, int> Parent; |
| 1989 | 1989 |
|
| 1990 | 1990 |
AutoNodeMap(const Digraph& digraph) : Parent(digraph, 0) {}
|
| 1991 |
|
|
| 1991 |
|
|
| 1992 | 1992 |
virtual void add(const Key& key) {
|
| 1993 |
Parent::add(key); |
|
| 1994 |
Parent::set(key, 0); |
|
| 1993 |
Parent::add(key); |
|
| 1994 |
Parent::set(key, 0); |
|
| 1995 | 1995 |
} |
| 1996 | 1996 |
virtual void add(const std::vector<Key>& keys) {
|
| 1997 |
Parent::add(keys); |
|
| 1998 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 1999 |
Parent::set(keys[i], 0); |
|
| 2000 |
} |
|
| 1997 |
Parent::add(keys); |
|
| 1998 |
for (int i = 0; i < int(keys.size()); ++i) {
|
|
| 1999 |
Parent::set(keys[i], 0); |
|
| 2000 |
} |
|
| 2001 | 2001 |
} |
| 2002 | 2002 |
virtual void build() {
|
| 2003 |
Parent::build(); |
|
| 2004 |
Key it; |
|
| 2005 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 2006 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 2007 |
Parent::set(it, 0); |
|
| 2008 |
} |
|
| 2003 |
Parent::build(); |
|
| 2004 |
Key it; |
|
| 2005 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 2006 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 2007 |
Parent::set(it, 0); |
|
| 2008 |
} |
|
| 2009 | 2009 |
} |
| 2010 | 2010 |
}; |
| 2011 | 2011 |
|
| 2012 | 2012 |
public: |
| 2013 | 2013 |
|
| 2014 | 2014 |
/// \brief Constructor. |
| 2015 | 2015 |
/// |
| 2016 | 2016 |
/// Constructor for creating out-degree map. |
| 2017 |
explicit OutDegMap(const Digraph& digraph) |
|
| 2017 |
explicit OutDegMap(const Digraph& digraph) |
|
| 2018 | 2018 |
: _digraph(digraph), _deg(digraph) {
|
| 2019 | 2019 |
Parent::attach(_digraph.notifier(typename Digraph::Arc())); |
| 2020 |
|
|
| 2020 |
|
|
| 2021 | 2021 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 2022 |
|
|
| 2022 |
_deg[it] = countOutArcs(_digraph, it); |
|
| 2023 | 2023 |
} |
| 2024 | 2024 |
} |
| 2025 | 2025 |
|
| 2026 | 2026 |
/// Gives back the out-degree of a Node. |
| 2027 | 2027 |
int operator[](const Key& key) const {
|
| 2028 | 2028 |
return _deg[key]; |
| 2029 | 2029 |
} |
| 2030 | 2030 |
|
| 2031 | 2031 |
protected: |
| 2032 |
|
|
| 2032 |
|
|
| 2033 | 2033 |
typedef typename Digraph::Arc Arc; |
| 2034 | 2034 |
|
| 2035 | 2035 |
virtual void add(const Arc& arc) {
|
| 2036 | 2036 |
++_deg[_digraph.source(arc)]; |
| 2037 | 2037 |
} |
| 2038 | 2038 |
|
| 2039 | 2039 |
virtual void add(const std::vector<Arc>& arcs) {
|
| 2040 | 2040 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 2041 | 2041 |
++_deg[_digraph.source(arcs[i])]; |
| 2042 | 2042 |
} |
| 2043 | 2043 |
} |
| 2044 | 2044 |
|
| 2045 | 2045 |
virtual void erase(const Arc& arc) {
|
| 2046 | 2046 |
--_deg[_digraph.source(arc)]; |
| 2047 | 2047 |
} |
| 2048 | 2048 |
|
| 2049 | 2049 |
virtual void erase(const std::vector<Arc>& arcs) {
|
| 2050 | 2050 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 2051 | 2051 |
--_deg[_digraph.source(arcs[i])]; |
| 2052 | 2052 |
} |
| 2053 | 2053 |
} |
| 2054 | 2054 |
|
| 2055 | 2055 |
virtual void build() {
|
| 2056 | 2056 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 2057 |
_deg[it] = countOutArcs(_digraph, it); |
|
| 2058 |
} |
|
| 2057 |
_deg[it] = countOutArcs(_digraph, it); |
|
| 2058 |
} |
|
| 2059 | 2059 |
} |
| 2060 | 2060 |
|
| 2061 | 2061 |
virtual void clear() {
|
| 2062 | 2062 |
for(typename Digraph::NodeIt it(_digraph); it != INVALID; ++it) {
|
| 2063 |
|
|
| 2063 |
_deg[it] = 0; |
|
| 2064 | 2064 |
} |
| 2065 | 2065 |
} |
| 2066 | 2066 |
private: |
| 2067 |
|
|
| 2067 |
|
|
| 2068 | 2068 |
const Digraph& _digraph; |
| 2069 | 2069 |
AutoNodeMap _deg; |
| 2070 | 2070 |
}; |
| 2071 | 2071 |
|
| 2072 | 2072 |
|
| 2073 | 2073 |
///Dynamic arc look up between given endpoints. |
| 2074 |
|
|
| 2074 |
|
|
| 2075 | 2075 |
///\ingroup gutils |
| 2076 | 2076 |
///Using this class, you can find an arc in a digraph from a given |
| 2077 | 2077 |
///source to a given target in amortized time <em>O(log d)</em>, |
| 2078 | 2078 |
///where <em>d</em> is the out-degree of the source node. |
| 2079 | 2079 |
/// |
| 2080 | 2080 |
///It is possible to find \e all parallel arcs between two nodes with |
| 2081 | 2081 |
///the \c findFirst() and \c findNext() members. |
| 2082 | 2082 |
/// |
| 2083 | 2083 |
///See the \ref ArcLookUp and \ref AllArcLookUp classes if your |
| 2084 | 2084 |
///digraph is not changed so frequently. |
| 2085 | 2085 |
/// |
| 2086 | 2086 |
///This class uses a self-adjusting binary search tree, Sleator's |
| 2087 | 2087 |
///and Tarjan's Splay tree for guarantee the logarithmic amortized |
| 2088 | 2088 |
///time bound for arc lookups. This class also guarantees the |
| 2089 | 2089 |
///optimal time bound in a constant factor for any distribution of |
| 2090 | 2090 |
///queries. |
| 2091 | 2091 |
/// |
| 2092 |
///\tparam G The type of the underlying digraph. |
|
| 2092 |
///\tparam G The type of the underlying digraph. |
|
| 2093 | 2093 |
/// |
| 2094 |
///\sa ArcLookUp |
|
| 2095 |
///\sa AllArcLookUp |
|
| 2094 |
///\sa ArcLookUp |
|
| 2095 |
///\sa AllArcLookUp |
|
| 2096 | 2096 |
template<class G> |
| 2097 |
class DynArcLookUp |
|
| 2097 |
class DynArcLookUp |
|
| 2098 | 2098 |
: protected ItemSetTraits<G, typename G::Arc>::ItemNotifier::ObserverBase |
| 2099 | 2099 |
{
|
| 2100 | 2100 |
public: |
| 2101 | 2101 |
typedef typename ItemSetTraits<G, typename G::Arc> |
| 2102 | 2102 |
::ItemNotifier::ObserverBase Parent; |
| 2103 | 2103 |
|
| 2104 | 2104 |
TEMPLATE_DIGRAPH_TYPEDEFS(G); |
| 2105 | 2105 |
typedef G Digraph; |
| 2106 | 2106 |
|
| 2107 | 2107 |
protected: |
| 2108 | 2108 |
|
| 2109 | 2109 |
class AutoNodeMap : public DefaultMap<G, Node, Arc> {
|
| 2110 | 2110 |
public: |
| 2111 | 2111 |
|
| 2112 | 2112 |
typedef DefaultMap<G, Node, Arc> Parent; |
| 2113 | 2113 |
|
| 2114 | 2114 |
AutoNodeMap(const G& digraph) : Parent(digraph, INVALID) {}
|
| 2115 |
|
|
| 2115 |
|
|
| 2116 | 2116 |
virtual void add(const Node& node) {
|
| 2117 |
Parent::add(node); |
|
| 2118 |
Parent::set(node, INVALID); |
|
| 2117 |
Parent::add(node); |
|
| 2118 |
Parent::set(node, INVALID); |
|
| 2119 | 2119 |
} |
| 2120 | 2120 |
|
| 2121 | 2121 |
virtual void add(const std::vector<Node>& nodes) {
|
| 2122 |
Parent::add(nodes); |
|
| 2123 |
for (int i = 0; i < int(nodes.size()); ++i) {
|
|
| 2124 |
Parent::set(nodes[i], INVALID); |
|
| 2125 |
} |
|
| 2122 |
Parent::add(nodes); |
|
| 2123 |
for (int i = 0; i < int(nodes.size()); ++i) {
|
|
| 2124 |
Parent::set(nodes[i], INVALID); |
|
| 2125 |
} |
|
| 2126 | 2126 |
} |
| 2127 | 2127 |
|
| 2128 | 2128 |
virtual void build() {
|
| 2129 |
Parent::build(); |
|
| 2130 |
Node it; |
|
| 2131 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 2132 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 2133 |
Parent::set(it, INVALID); |
|
| 2134 |
} |
|
| 2129 |
Parent::build(); |
|
| 2130 |
Node it; |
|
| 2131 |
typename Parent::Notifier* nf = Parent::notifier(); |
|
| 2132 |
for (nf->first(it); it != INVALID; nf->next(it)) {
|
|
| 2133 |
Parent::set(it, INVALID); |
|
| 2134 |
} |
|
| 2135 | 2135 |
} |
| 2136 | 2136 |
}; |
| 2137 | 2137 |
|
| 2138 | 2138 |
const Digraph &_g; |
| 2139 | 2139 |
AutoNodeMap _head; |
| 2140 | 2140 |
typename Digraph::template ArcMap<Arc> _parent; |
| 2141 | 2141 |
typename Digraph::template ArcMap<Arc> _left; |
| 2142 | 2142 |
typename Digraph::template ArcMap<Arc> _right; |
| 2143 |
|
|
| 2143 |
|
|
| 2144 | 2144 |
class ArcLess {
|
| 2145 | 2145 |
const Digraph &g; |
| 2146 | 2146 |
public: |
| 2147 | 2147 |
ArcLess(const Digraph &_g) : g(_g) {}
|
| 2148 |
bool operator()(Arc a,Arc b) const |
|
| 2148 |
bool operator()(Arc a,Arc b) const |
|
| 2149 | 2149 |
{
|
| 2150 |
|
|
| 2150 |
return g.target(a)<g.target(b); |
|
| 2151 | 2151 |
} |
| 2152 | 2152 |
}; |
| 2153 |
|
|
| 2153 |
|
|
| 2154 | 2154 |
public: |
| 2155 |
|
|
| 2155 |
|
|
| 2156 | 2156 |
///Constructor |
| 2157 | 2157 |
|
| 2158 | 2158 |
///Constructor. |
| 2159 | 2159 |
/// |
| 2160 | 2160 |
///It builds up the search database. |
| 2161 |
DynArcLookUp(const Digraph &g) |
|
| 2162 |
: _g(g),_head(g),_parent(g),_left(g),_right(g) |
|
| 2163 |
|
|
| 2161 |
DynArcLookUp(const Digraph &g) |
|
| 2162 |
: _g(g),_head(g),_parent(g),_left(g),_right(g) |
|
| 2163 |
{
|
|
| 2164 | 2164 |
Parent::attach(_g.notifier(typename Digraph::Arc())); |
| 2165 |
refresh(); |
|
| 2165 |
refresh(); |
|
| 2166 | 2166 |
} |
| 2167 |
|
|
| 2167 |
|
|
| 2168 | 2168 |
protected: |
| 2169 | 2169 |
|
| 2170 | 2170 |
virtual void add(const Arc& arc) {
|
| 2171 | 2171 |
insert(arc); |
| 2172 | 2172 |
} |
| 2173 | 2173 |
|
| 2174 | 2174 |
virtual void add(const std::vector<Arc>& arcs) {
|
| 2175 | 2175 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 2176 |
|
|
| 2176 |
insert(arcs[i]); |
|
| 2177 | 2177 |
} |
| 2178 | 2178 |
} |
| 2179 | 2179 |
|
| 2180 | 2180 |
virtual void erase(const Arc& arc) {
|
| 2181 | 2181 |
remove(arc); |
| 2182 | 2182 |
} |
| 2183 | 2183 |
|
| 2184 | 2184 |
virtual void erase(const std::vector<Arc>& arcs) {
|
| 2185 | 2185 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 2186 |
remove(arcs[i]); |
|
| 2187 |
} |
|
| 2186 |
remove(arcs[i]); |
|
| 2187 |
} |
|
| 2188 | 2188 |
} |
| 2189 | 2189 |
|
| 2190 | 2190 |
virtual void build() {
|
| 2191 | 2191 |
refresh(); |
| 2192 | 2192 |
} |
| 2193 | 2193 |
|
| 2194 | 2194 |
virtual void clear() {
|
| 2195 | 2195 |
for(NodeIt n(_g);n!=INVALID;++n) {
|
| 2196 |
|
|
| 2196 |
_head.set(n, INVALID); |
|
| 2197 | 2197 |
} |
| 2198 | 2198 |
} |
| 2199 | 2199 |
|
| 2200 | 2200 |
void insert(Arc arc) {
|
| 2201 | 2201 |
Node s = _g.source(arc); |
| 2202 | 2202 |
Node t = _g.target(arc); |
| 2203 | 2203 |
_left.set(arc, INVALID); |
| 2204 | 2204 |
_right.set(arc, INVALID); |
| 2205 |
|
|
| 2205 |
|
|
| 2206 | 2206 |
Arc e = _head[s]; |
| 2207 | 2207 |
if (e == INVALID) {
|
| 2208 |
_head.set(s, arc); |
|
| 2209 |
_parent.set(arc, INVALID); |
|
| 2210 |
|
|
| 2208 |
_head.set(s, arc); |
|
| 2209 |
_parent.set(arc, INVALID); |
|
| 2210 |
return; |
|
| 2211 | 2211 |
} |
| 2212 | 2212 |
while (true) {
|
| 2213 |
if (t < _g.target(e)) {
|
|
| 2214 |
if (_left[e] == INVALID) {
|
|
| 2215 |
_left.set(e, arc); |
|
| 2216 |
_parent.set(arc, e); |
|
| 2217 |
splay(arc); |
|
| 2218 |
return; |
|
| 2219 |
} else {
|
|
| 2220 |
e = _left[e]; |
|
| 2221 |
} |
|
| 2222 |
} else {
|
|
| 2223 |
if (_right[e] == INVALID) {
|
|
| 2224 |
_right.set(e, arc); |
|
| 2225 |
_parent.set(arc, e); |
|
| 2226 |
splay(arc); |
|
| 2227 |
return; |
|
| 2228 |
} else {
|
|
| 2229 |
e = _right[e]; |
|
| 2230 |
} |
|
| 2231 |
|
|
| 2213 |
if (t < _g.target(e)) {
|
|
| 2214 |
if (_left[e] == INVALID) {
|
|
| 2215 |
_left.set(e, arc); |
|
| 2216 |
_parent.set(arc, e); |
|
| 2217 |
splay(arc); |
|
| 2218 |
return; |
|
| 2219 |
} else {
|
|
| 2220 |
e = _left[e]; |
|
| 2221 |
} |
|
| 2222 |
} else {
|
|
| 2223 |
if (_right[e] == INVALID) {
|
|
| 2224 |
_right.set(e, arc); |
|
| 2225 |
_parent.set(arc, e); |
|
| 2226 |
splay(arc); |
|
| 2227 |
return; |
|
| 2228 |
} else {
|
|
| 2229 |
e = _right[e]; |
|
| 2230 |
} |
|
| 2231 |
} |
|
| 2232 | 2232 |
} |
| 2233 | 2233 |
} |
| 2234 | 2234 |
|
| 2235 | 2235 |
void remove(Arc arc) {
|
| 2236 | 2236 |
if (_left[arc] == INVALID) {
|
| 2237 |
if (_right[arc] != INVALID) {
|
|
| 2238 |
_parent.set(_right[arc], _parent[arc]); |
|
| 2239 |
} |
|
| 2240 |
if (_parent[arc] != INVALID) {
|
|
| 2241 |
if (_left[_parent[arc]] == arc) {
|
|
| 2242 |
_left.set(_parent[arc], _right[arc]); |
|
| 2243 |
} else {
|
|
| 2244 |
_right.set(_parent[arc], _right[arc]); |
|
| 2245 |
} |
|
| 2246 |
} else {
|
|
| 2247 |
_head.set(_g.source(arc), _right[arc]); |
|
| 2248 |
} |
|
| 2237 |
if (_right[arc] != INVALID) {
|
|
| 2238 |
_parent.set(_right[arc], _parent[arc]); |
|
| 2239 |
} |
|
| 2240 |
if (_parent[arc] != INVALID) {
|
|
| 2241 |
if (_left[_parent[arc]] == arc) {
|
|
| 2242 |
_left.set(_parent[arc], _right[arc]); |
|
| 2243 |
} else {
|
|
| 2244 |
_right.set(_parent[arc], _right[arc]); |
|
| 2245 |
} |
|
| 2246 |
} else {
|
|
| 2247 |
_head.set(_g.source(arc), _right[arc]); |
|
| 2248 |
} |
|
| 2249 | 2249 |
} else if (_right[arc] == INVALID) {
|
| 2250 |
_parent.set(_left[arc], _parent[arc]); |
|
| 2251 |
if (_parent[arc] != INVALID) {
|
|
| 2252 |
if (_left[_parent[arc]] == arc) {
|
|
| 2253 |
_left.set(_parent[arc], _left[arc]); |
|
| 2254 |
} else {
|
|
| 2255 |
_right.set(_parent[arc], _left[arc]); |
|
| 2256 |
} |
|
| 2257 |
} else {
|
|
| 2258 |
_head.set(_g.source(arc), _left[arc]); |
|
| 2259 |
} |
|
| 2250 |
_parent.set(_left[arc], _parent[arc]); |
|
| 2251 |
if (_parent[arc] != INVALID) {
|
|
| 2252 |
if (_left[_parent[arc]] == arc) {
|
|
| 2253 |
_left.set(_parent[arc], _left[arc]); |
|
| 2254 |
} else {
|
|
| 2255 |
_right.set(_parent[arc], _left[arc]); |
|
| 2256 |
} |
|
| 2257 |
} else {
|
|
| 2258 |
_head.set(_g.source(arc), _left[arc]); |
|
| 2259 |
} |
|
| 2260 | 2260 |
} else {
|
| 2261 |
Arc e = _left[arc]; |
|
| 2262 |
if (_right[e] != INVALID) {
|
|
| 2263 |
e = _right[e]; |
|
| 2264 |
while (_right[e] != INVALID) {
|
|
| 2265 |
e = _right[e]; |
|
| 2266 |
} |
|
| 2267 |
Arc s = _parent[e]; |
|
| 2268 |
_right.set(_parent[e], _left[e]); |
|
| 2269 |
if (_left[e] != INVALID) {
|
|
| 2270 |
_parent.set(_left[e], _parent[e]); |
|
| 2271 |
} |
|
| 2272 |
|
|
| 2273 |
_left.set(e, _left[arc]); |
|
| 2274 |
_parent.set(_left[arc], e); |
|
| 2275 |
_right.set(e, _right[arc]); |
|
| 2276 |
_parent.set(_right[arc], e); |
|
| 2277 |
|
|
| 2278 |
_parent.set(e, _parent[arc]); |
|
| 2279 |
if (_parent[arc] != INVALID) {
|
|
| 2280 |
if (_left[_parent[arc]] == arc) {
|
|
| 2281 |
_left.set(_parent[arc], e); |
|
| 2282 |
} else {
|
|
| 2283 |
_right.set(_parent[arc], e); |
|
| 2284 |
} |
|
| 2285 |
} |
|
| 2286 |
splay(s); |
|
| 2287 |
} else {
|
|
| 2288 |
_right.set(e, _right[arc]); |
|
| 2289 |
_parent.set(_right[arc], e); |
|
| 2290 |
|
|
| 2291 |
if (_parent[arc] != INVALID) {
|
|
| 2292 |
if (_left[_parent[arc]] == arc) {
|
|
| 2293 |
_left.set(_parent[arc], e); |
|
| 2294 |
} else {
|
|
| 2295 |
_right.set(_parent[arc], e); |
|
| 2296 |
} |
|
| 2297 |
} else {
|
|
| 2298 |
_head.set(_g.source(arc), e); |
|
| 2299 |
} |
|
| 2300 |
} |
|
| 2261 |
Arc e = _left[arc]; |
|
| 2262 |
if (_right[e] != INVALID) {
|
|
| 2263 |
e = _right[e]; |
|
| 2264 |
while (_right[e] != INVALID) {
|
|
| 2265 |
e = _right[e]; |
|
| 2266 |
} |
|
| 2267 |
Arc s = _parent[e]; |
|
| 2268 |
_right.set(_parent[e], _left[e]); |
|
| 2269 |
if (_left[e] != INVALID) {
|
|
| 2270 |
_parent.set(_left[e], _parent[e]); |
|
| 2271 |
} |
|
| 2272 |
|
|
| 2273 |
_left.set(e, _left[arc]); |
|
| 2274 |
_parent.set(_left[arc], e); |
|
| 2275 |
_right.set(e, _right[arc]); |
|
| 2276 |
_parent.set(_right[arc], e); |
|
| 2277 |
|
|
| 2278 |
_parent.set(e, _parent[arc]); |
|
| 2279 |
if (_parent[arc] != INVALID) {
|
|
| 2280 |
if (_left[_parent[arc]] == arc) {
|
|
| 2281 |
_left.set(_parent[arc], e); |
|
| 2282 |
} else {
|
|
| 2283 |
_right.set(_parent[arc], e); |
|
| 2284 |
} |
|
| 2285 |
} |
|
| 2286 |
splay(s); |
|
| 2287 |
} else {
|
|
| 2288 |
_right.set(e, _right[arc]); |
|
| 2289 |
_parent.set(_right[arc], e); |
|
| 2290 |
|
|
| 2291 |
if (_parent[arc] != INVALID) {
|
|
| 2292 |
if (_left[_parent[arc]] == arc) {
|
|
| 2293 |
_left.set(_parent[arc], e); |
|
| 2294 |
} else {
|
|
| 2295 |
_right.set(_parent[arc], e); |
|
| 2296 |
} |
|
| 2297 |
} else {
|
|
| 2298 |
_head.set(_g.source(arc), e); |
|
| 2299 |
} |
|
| 2300 |
} |
|
| 2301 | 2301 |
} |
| 2302 | 2302 |
} |
| 2303 | 2303 |
|
| 2304 |
Arc refreshRec(std::vector<Arc> &v,int a,int b) |
|
| 2304 |
Arc refreshRec(std::vector<Arc> &v,int a,int b) |
|
| 2305 | 2305 |
{
|
| 2306 | 2306 |
int m=(a+b)/2; |
| 2307 | 2307 |
Arc me=v[m]; |
| 2308 | 2308 |
if (a < m) {
|
| 2309 |
Arc left = refreshRec(v,a,m-1); |
|
| 2310 |
_left.set(me, left); |
|
| 2311 |
|
|
| 2309 |
Arc left = refreshRec(v,a,m-1); |
|
| 2310 |
_left.set(me, left); |
|
| 2311 |
_parent.set(left, me); |
|
| 2312 | 2312 |
} else {
|
| 2313 |
|
|
| 2313 |
_left.set(me, INVALID); |
|
| 2314 | 2314 |
} |
| 2315 | 2315 |
if (m < b) {
|
| 2316 |
Arc right = refreshRec(v,m+1,b); |
|
| 2317 |
_right.set(me, right); |
|
| 2318 |
|
|
| 2316 |
Arc right = refreshRec(v,m+1,b); |
|
| 2317 |
_right.set(me, right); |
|
| 2318 |
_parent.set(right, me); |
|
| 2319 | 2319 |
} else {
|
| 2320 |
|
|
| 2320 |
_right.set(me, INVALID); |
|
| 2321 | 2321 |
} |
| 2322 | 2322 |
return me; |
| 2323 | 2323 |
} |
| 2324 | 2324 |
|
| 2325 | 2325 |
void refresh() {
|
| 2326 | 2326 |
for(NodeIt n(_g);n!=INVALID;++n) {
|
| 2327 |
std::vector<Arc> v; |
|
| 2328 |
for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e); |
|
| 2329 |
if(v.size()) {
|
|
| 2330 |
std::sort(v.begin(),v.end(),ArcLess(_g)); |
|
| 2331 |
Arc head = refreshRec(v,0,v.size()-1); |
|
| 2332 |
_head.set(n, head); |
|
| 2333 |
_parent.set(head, INVALID); |
|
| 2334 |
} |
|
| 2335 |
|
|
| 2327 |
std::vector<Arc> v; |
|
| 2328 |
for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e); |
|
| 2329 |
if(v.size()) {
|
|
| 2330 |
std::sort(v.begin(),v.end(),ArcLess(_g)); |
|
| 2331 |
Arc head = refreshRec(v,0,v.size()-1); |
|
| 2332 |
_head.set(n, head); |
|
| 2333 |
_parent.set(head, INVALID); |
|
| 2334 |
} |
|
| 2335 |
else _head.set(n, INVALID); |
|
| 2336 | 2336 |
} |
| 2337 | 2337 |
} |
| 2338 | 2338 |
|
| 2339 |
void zig(Arc v) {
|
|
| 2339 |
void zig(Arc v) {
|
|
| 2340 | 2340 |
Arc w = _parent[v]; |
| 2341 | 2341 |
_parent.set(v, _parent[w]); |
| 2342 | 2342 |
_parent.set(w, v); |
| 2343 | 2343 |
_left.set(w, _right[v]); |
| 2344 | 2344 |
_right.set(v, w); |
| 2345 | 2345 |
if (_parent[v] != INVALID) {
|
| 2346 |
if (_right[_parent[v]] == w) {
|
|
| 2347 |
_right.set(_parent[v], v); |
|
| 2348 |
} else {
|
|
| 2349 |
_left.set(_parent[v], v); |
|
| 2350 |
|
|
| 2346 |
if (_right[_parent[v]] == w) {
|
|
| 2347 |
_right.set(_parent[v], v); |
|
| 2348 |
} else {
|
|
| 2349 |
_left.set(_parent[v], v); |
|
| 2350 |
} |
|
| 2351 | 2351 |
} |
| 2352 | 2352 |
if (_left[w] != INVALID){
|
| 2353 |
|
|
| 2353 |
_parent.set(_left[w], w); |
|
| 2354 | 2354 |
} |
| 2355 | 2355 |
} |
| 2356 | 2356 |
|
| 2357 |
void zag(Arc v) {
|
|
| 2357 |
void zag(Arc v) {
|
|
| 2358 | 2358 |
Arc w = _parent[v]; |
| 2359 | 2359 |
_parent.set(v, _parent[w]); |
| 2360 | 2360 |
_parent.set(w, v); |
| 2361 | 2361 |
_right.set(w, _left[v]); |
| 2362 | 2362 |
_left.set(v, w); |
| 2363 | 2363 |
if (_parent[v] != INVALID){
|
| 2364 |
if (_left[_parent[v]] == w) {
|
|
| 2365 |
_left.set(_parent[v], v); |
|
| 2366 |
} else {
|
|
| 2367 |
_right.set(_parent[v], v); |
|
| 2368 |
|
|
| 2364 |
if (_left[_parent[v]] == w) {
|
|
| 2365 |
_left.set(_parent[v], v); |
|
| 2366 |
} else {
|
|
| 2367 |
_right.set(_parent[v], v); |
|
| 2368 |
} |
|
| 2369 | 2369 |
} |
| 2370 | 2370 |
if (_right[w] != INVALID){
|
| 2371 |
|
|
| 2371 |
_parent.set(_right[w], w); |
|
| 2372 | 2372 |
} |
| 2373 | 2373 |
} |
| 2374 | 2374 |
|
| 2375 | 2375 |
void splay(Arc v) {
|
| 2376 | 2376 |
while (_parent[v] != INVALID) {
|
| 2377 |
if (v == _left[_parent[v]]) {
|
|
| 2378 |
if (_parent[_parent[v]] == INVALID) {
|
|
| 2379 |
zig(v); |
|
| 2380 |
} else {
|
|
| 2381 |
if (_parent[v] == _left[_parent[_parent[v]]]) {
|
|
| 2382 |
zig(_parent[v]); |
|
| 2383 |
zig(v); |
|
| 2384 |
} else {
|
|
| 2385 |
zig(v); |
|
| 2386 |
zag(v); |
|
| 2387 |
} |
|
| 2388 |
} |
|
| 2389 |
} else {
|
|
| 2390 |
if (_parent[_parent[v]] == INVALID) {
|
|
| 2391 |
zag(v); |
|
| 2392 |
} else {
|
|
| 2393 |
if (_parent[v] == _left[_parent[_parent[v]]]) {
|
|
| 2394 |
zag(v); |
|
| 2395 |
zig(v); |
|
| 2396 |
} else {
|
|
| 2397 |
zag(_parent[v]); |
|
| 2398 |
zag(v); |
|
| 2399 |
} |
|
| 2400 |
} |
|
| 2401 |
|
|
| 2377 |
if (v == _left[_parent[v]]) {
|
|
| 2378 |
if (_parent[_parent[v]] == INVALID) {
|
|
| 2379 |
zig(v); |
|
| 2380 |
} else {
|
|
| 2381 |
if (_parent[v] == _left[_parent[_parent[v]]]) {
|
|
| 2382 |
zig(_parent[v]); |
|
| 2383 |
zig(v); |
|
| 2384 |
} else {
|
|
| 2385 |
zig(v); |
|
| 2386 |
zag(v); |
|
| 2387 |
} |
|
| 2388 |
} |
|
| 2389 |
} else {
|
|
| 2390 |
if (_parent[_parent[v]] == INVALID) {
|
|
| 2391 |
zag(v); |
|
| 2392 |
} else {
|
|
| 2393 |
if (_parent[v] == _left[_parent[_parent[v]]]) {
|
|
| 2394 |
zag(v); |
|
| 2395 |
zig(v); |
|
| 2396 |
} else {
|
|
| 2397 |
zag(_parent[v]); |
|
| 2398 |
zag(v); |
|
| 2399 |
} |
|
| 2400 |
} |
|
| 2401 |
} |
|
| 2402 | 2402 |
} |
| 2403 | 2403 |
_head[_g.source(v)] = v; |
| 2404 | 2404 |
} |
| 2405 | 2405 |
|
| 2406 | 2406 |
|
| 2407 | 2407 |
public: |
| 2408 |
|
|
| 2408 |
|
|
| 2409 | 2409 |
///Find an arc between two nodes. |
| 2410 |
|
|
| 2410 |
|
|
| 2411 | 2411 |
///Find an arc between two nodes in time <em>O(</em>log<em>d)</em>, where |
| 2412 | 2412 |
/// <em>d</em> is the number of outgoing arcs of \c s. |
| 2413 | 2413 |
///\param s The source node |
| 2414 | 2414 |
///\param t The target node |
| 2415 | 2415 |
///\return An arc from \c s to \c t if there exists, |
| 2416 | 2416 |
///\ref INVALID otherwise. |
| 2417 | 2417 |
Arc operator()(Node s, Node t) const |
| 2418 | 2418 |
{
|
| 2419 | 2419 |
Arc a = _head[s]; |
| 2420 | 2420 |
while (true) {
|
| 2421 |
if (_g.target(a) == t) {
|
|
| 2422 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2423 |
return a; |
|
| 2424 |
} else if (t < _g.target(a)) {
|
|
| 2425 |
if (_left[a] == INVALID) {
|
|
| 2426 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2427 |
return INVALID; |
|
| 2428 |
} else {
|
|
| 2429 |
a = _left[a]; |
|
| 2430 |
} |
|
| 2431 |
} else {
|
|
| 2432 |
if (_right[a] == INVALID) {
|
|
| 2433 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2434 |
return INVALID; |
|
| 2435 |
} else {
|
|
| 2436 |
a = _right[a]; |
|
| 2437 |
} |
|
| 2438 |
} |
|
| 2421 |
if (_g.target(a) == t) {
|
|
| 2422 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2423 |
return a; |
|
| 2424 |
} else if (t < _g.target(a)) {
|
|
| 2425 |
if (_left[a] == INVALID) {
|
|
| 2426 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2427 |
return INVALID; |
|
| 2428 |
} else {
|
|
| 2429 |
a = _left[a]; |
|
| 2430 |
} |
|
| 2431 |
} else {
|
|
| 2432 |
if (_right[a] == INVALID) {
|
|
| 2433 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2434 |
return INVALID; |
|
| 2435 |
} else {
|
|
| 2436 |
a = _right[a]; |
|
| 2437 |
} |
|
| 2438 |
} |
|
| 2439 | 2439 |
} |
| 2440 | 2440 |
} |
| 2441 | 2441 |
|
| 2442 | 2442 |
///Find the first arc between two nodes. |
| 2443 |
|
|
| 2443 |
|
|
| 2444 | 2444 |
///Find the first arc between two nodes in time |
| 2445 | 2445 |
/// <em>O(</em>log<em>d)</em>, where <em>d</em> is the number of |
| 2446 |
/// outgoing arcs of \c s. |
|
| 2447 |
///\param s The source node |
|
| 2446 |
/// outgoing arcs of \c s. |
|
| 2447 |
///\param s The source node |
|
| 2448 | 2448 |
///\param t The target node |
| 2449 | 2449 |
///\return An arc from \c s to \c t if there exists, \ref INVALID |
| 2450 | 2450 |
/// otherwise. |
| 2451 | 2451 |
Arc findFirst(Node s, Node t) const |
| 2452 | 2452 |
{
|
| 2453 | 2453 |
Arc a = _head[s]; |
| 2454 | 2454 |
Arc r = INVALID; |
| 2455 | 2455 |
while (true) {
|
| 2456 |
if (_g.target(a) < t) {
|
|
| 2457 |
if (_right[a] == INVALID) {
|
|
| 2458 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2459 |
return r; |
|
| 2460 |
} else {
|
|
| 2461 |
a = _right[a]; |
|
| 2462 |
} |
|
| 2463 |
} else {
|
|
| 2464 |
if (_g.target(a) == t) {
|
|
| 2465 |
r = a; |
|
| 2466 |
} |
|
| 2467 |
if (_left[a] == INVALID) {
|
|
| 2468 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2469 |
return r; |
|
| 2470 |
} else {
|
|
| 2471 |
a = _left[a]; |
|
| 2472 |
} |
|
| 2473 |
} |
|
| 2456 |
if (_g.target(a) < t) {
|
|
| 2457 |
if (_right[a] == INVALID) {
|
|
| 2458 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2459 |
return r; |
|
| 2460 |
} else {
|
|
| 2461 |
a = _right[a]; |
|
| 2462 |
} |
|
| 2463 |
} else {
|
|
| 2464 |
if (_g.target(a) == t) {
|
|
| 2465 |
r = a; |
|
| 2466 |
} |
|
| 2467 |
if (_left[a] == INVALID) {
|
|
| 2468 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2469 |
return r; |
|
| 2470 |
} else {
|
|
| 2471 |
a = _left[a]; |
|
| 2472 |
} |
|
| 2473 |
} |
|
| 2474 | 2474 |
} |
| 2475 | 2475 |
} |
| 2476 | 2476 |
|
| 2477 | 2477 |
///Find the next arc between two nodes. |
| 2478 |
|
|
| 2478 |
|
|
| 2479 | 2479 |
///Find the next arc between two nodes in time |
| 2480 | 2480 |
/// <em>O(</em>log<em>d)</em>, where <em>d</em> is the number of |
| 2481 |
/// outgoing arcs of \c s. |
|
| 2482 |
///\param s The source node |
|
| 2481 |
/// outgoing arcs of \c s. |
|
| 2482 |
///\param s The source node |
|
| 2483 | 2483 |
///\param t The target node |
| 2484 | 2484 |
///\return An arc from \c s to \c t if there exists, \ref INVALID |
| 2485 | 2485 |
/// otherwise. |
| 2486 | 2486 |
|
| 2487 | 2487 |
///\note If \c e is not the result of the previous \c findFirst() |
| 2488 | 2488 |
///operation then the amorized time bound can not be guaranteed. |
| 2489 | 2489 |
#ifdef DOXYGEN |
| 2490 | 2490 |
Arc findNext(Node s, Node t, Arc a) const |
| 2491 | 2491 |
#else |
| 2492 | 2492 |
Arc findNext(Node, Node t, Arc a) const |
| 2493 | 2493 |
#endif |
| 2494 | 2494 |
{
|
| 2495 | 2495 |
if (_right[a] != INVALID) {
|
| 2496 |
a = _right[a]; |
|
| 2497 |
while (_left[a] != INVALID) {
|
|
| 2498 |
a = _left[a]; |
|
| 2499 |
} |
|
| 2500 |
|
|
| 2496 |
a = _right[a]; |
|
| 2497 |
while (_left[a] != INVALID) {
|
|
| 2498 |
a = _left[a]; |
|
| 2499 |
} |
|
| 2500 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2501 | 2501 |
} else {
|
| 2502 |
while (_parent[a] != INVALID && _right[_parent[a]] == a) {
|
|
| 2503 |
a = _parent[a]; |
|
| 2504 |
} |
|
| 2505 |
if (_parent[a] == INVALID) {
|
|
| 2506 |
return INVALID; |
|
| 2507 |
} else {
|
|
| 2508 |
a = _parent[a]; |
|
| 2509 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2510 |
|
|
| 2502 |
while (_parent[a] != INVALID && _right[_parent[a]] == a) {
|
|
| 2503 |
a = _parent[a]; |
|
| 2504 |
} |
|
| 2505 |
if (_parent[a] == INVALID) {
|
|
| 2506 |
return INVALID; |
|
| 2507 |
} else {
|
|
| 2508 |
a = _parent[a]; |
|
| 2509 |
const_cast<DynArcLookUp&>(*this).splay(a); |
|
| 2510 |
} |
|
| 2511 | 2511 |
} |
| 2512 | 2512 |
if (_g.target(a) == t) return a; |
| 2513 |
else return INVALID; |
|
| 2513 |
else return INVALID; |
|
| 2514 | 2514 |
} |
| 2515 | 2515 |
|
| 2516 | 2516 |
}; |
| 2517 | 2517 |
|
| 2518 | 2518 |
///Fast arc look up between given endpoints. |
| 2519 |
|
|
| 2519 |
|
|
| 2520 | 2520 |
///\ingroup gutils |
| 2521 | 2521 |
///Using this class, you can find an arc in a digraph from a given |
| 2522 | 2522 |
///source to a given target in time <em>O(log d)</em>, |
| 2523 | 2523 |
///where <em>d</em> is the out-degree of the source node. |
| 2524 | 2524 |
/// |
| 2525 | 2525 |
///It is not possible to find \e all parallel arcs between two nodes. |
| 2526 | 2526 |
///Use \ref AllArcLookUp for this purpose. |
| 2527 | 2527 |
/// |
| 2528 | 2528 |
///\warning This class is static, so you should refresh() (or at least |
| 2529 | 2529 |
///refresh(Node)) this data structure |
| 2530 | 2530 |
///whenever the digraph changes. This is a time consuming (superlinearly |
| 2531 | 2531 |
///proportional (<em>O(m</em>log<em>m)</em>) to the number of arcs). |
| 2532 | 2532 |
/// |
| 2533 | 2533 |
///\tparam G The type of the underlying digraph. |
| 2534 | 2534 |
/// |
| 2535 | 2535 |
///\sa DynArcLookUp |
| 2536 |
///\sa AllArcLookUp |
|
| 2536 |
///\sa AllArcLookUp |
|
| 2537 | 2537 |
template<class G> |
| 2538 |
class ArcLookUp |
|
| 2538 |
class ArcLookUp |
|
| 2539 | 2539 |
{
|
| 2540 | 2540 |
public: |
| 2541 | 2541 |
TEMPLATE_DIGRAPH_TYPEDEFS(G); |
| 2542 | 2542 |
typedef G Digraph; |
| 2543 | 2543 |
|
| 2544 | 2544 |
protected: |
| 2545 | 2545 |
const Digraph &_g; |
| 2546 | 2546 |
typename Digraph::template NodeMap<Arc> _head; |
| 2547 | 2547 |
typename Digraph::template ArcMap<Arc> _left; |
| 2548 | 2548 |
typename Digraph::template ArcMap<Arc> _right; |
| 2549 |
|
|
| 2549 |
|
|
| 2550 | 2550 |
class ArcLess {
|
| 2551 | 2551 |
const Digraph &g; |
| 2552 | 2552 |
public: |
| 2553 | 2553 |
ArcLess(const Digraph &_g) : g(_g) {}
|
| 2554 |
bool operator()(Arc a,Arc b) const |
|
| 2554 |
bool operator()(Arc a,Arc b) const |
|
| 2555 | 2555 |
{
|
| 2556 |
|
|
| 2556 |
return g.target(a)<g.target(b); |
|
| 2557 | 2557 |
} |
| 2558 | 2558 |
}; |
| 2559 |
|
|
| 2559 |
|
|
| 2560 | 2560 |
public: |
| 2561 |
|
|
| 2561 |
|
|
| 2562 | 2562 |
///Constructor |
| 2563 | 2563 |
|
| 2564 | 2564 |
///Constructor. |
| 2565 | 2565 |
/// |
| 2566 | 2566 |
///It builds up the search database, which remains valid until the digraph |
| 2567 | 2567 |
///changes. |
| 2568 | 2568 |
ArcLookUp(const Digraph &g) :_g(g),_head(g),_left(g),_right(g) {refresh();}
|
| 2569 |
|
|
| 2569 |
|
|
| 2570 | 2570 |
private: |
| 2571 |
Arc refreshRec(std::vector<Arc> &v,int a,int b) |
|
| 2571 |
Arc refreshRec(std::vector<Arc> &v,int a,int b) |
|
| 2572 | 2572 |
{
|
| 2573 | 2573 |
int m=(a+b)/2; |
| 2574 | 2574 |
Arc me=v[m]; |
| 2575 | 2575 |
_left[me] = a<m?refreshRec(v,a,m-1):INVALID; |
| 2576 | 2576 |
_right[me] = m<b?refreshRec(v,m+1,b):INVALID; |
| 2577 | 2577 |
return me; |
| 2578 | 2578 |
} |
| 2579 | 2579 |
public: |
| 2580 | 2580 |
///Refresh the data structure at a node. |
| 2581 | 2581 |
|
| 2582 | 2582 |
///Build up the search database of node \c n. |
| 2583 | 2583 |
/// |
| 2584 | 2584 |
///It runs in time <em>O(d</em>log<em>d)</em>, where <em>d</em> is |
| 2585 | 2585 |
///the number of the outgoing arcs of \c n. |
| 2586 |
void refresh(Node n) |
|
| 2586 |
void refresh(Node n) |
|
| 2587 | 2587 |
{
|
| 2588 | 2588 |
std::vector<Arc> v; |
| 2589 | 2589 |
for(OutArcIt e(_g,n);e!=INVALID;++e) v.push_back(e); |
| 2590 | 2590 |
if(v.size()) {
|
| 2591 |
std::sort(v.begin(),v.end(),ArcLess(_g)); |
|
| 2592 |
_head[n]=refreshRec(v,0,v.size()-1); |
|
| 2591 |
std::sort(v.begin(),v.end(),ArcLess(_g)); |
|
| 2592 |
_head[n]=refreshRec(v,0,v.size()-1); |
|
| 2593 | 2593 |
} |
| 2594 | 2594 |
else _head[n]=INVALID; |
| 2595 | 2595 |
} |
| 2596 | 2596 |
///Refresh the full data structure. |
| 2597 | 2597 |
|
| 2598 | 2598 |
///Build up the full search database. In fact, it simply calls |
| 2599 | 2599 |
///\ref refresh(Node) "refresh(n)" for each node \c n. |
| 2600 | 2600 |
/// |
| 2601 | 2601 |
///It runs in time <em>O(m</em>log<em>D)</em>, where <em>m</em> is |
| 2602 | 2602 |
///the number of the arcs of \c n and <em>D</em> is the maximum |
| 2603 | 2603 |
///out-degree of the digraph. |
| 2604 | 2604 |
|
| 2605 |
void refresh() |
|
| 2605 |
void refresh() |
|
| 2606 | 2606 |
{
|
| 2607 | 2607 |
for(NodeIt n(_g);n!=INVALID;++n) refresh(n); |
| 2608 | 2608 |
} |
| 2609 |
|
|
| 2609 |
|
|
| 2610 | 2610 |
///Find an arc between two nodes. |
| 2611 |
|
|
| 2611 |
|
|
| 2612 | 2612 |
///Find an arc between two nodes in time <em>O(</em>log<em>d)</em>, where |
| 2613 | 2613 |
/// <em>d</em> is the number of outgoing arcs of \c s. |
| 2614 | 2614 |
///\param s The source node |
| 2615 | 2615 |
///\param t The target node |
| 2616 | 2616 |
///\return An arc from \c s to \c t if there exists, |
| 2617 | 2617 |
///\ref INVALID otherwise. |
| 2618 | 2618 |
/// |
| 2619 | 2619 |
///\warning If you change the digraph, refresh() must be called before using |
| 2620 | 2620 |
///this operator. If you change the outgoing arcs of |
| 2621 | 2621 |
///a single node \c n, then |
| 2622 | 2622 |
///\ref refresh(Node) "refresh(n)" is enough. |
| 2623 | 2623 |
/// |
| 2624 | 2624 |
Arc operator()(Node s, Node t) const |
| 2625 | 2625 |
{
|
| 2626 | 2626 |
Arc e; |
| 2627 | 2627 |
for(e=_head[s]; |
| 2628 |
e!=INVALID&&_g.target(e)!=t; |
|
| 2629 |
e = t < _g.target(e)?_left[e]:_right[e]) ; |
|
| 2628 |
e!=INVALID&&_g.target(e)!=t; |
|
| 2629 |
e = t < _g.target(e)?_left[e]:_right[e]) ; |
|
| 2630 | 2630 |
return e; |
| 2631 | 2631 |
} |
| 2632 | 2632 |
|
| 2633 | 2633 |
}; |
| 2634 | 2634 |
|
| 2635 | 2635 |
///Fast look up of all arcs between given endpoints. |
| 2636 |
|
|
| 2636 |
|
|
| 2637 | 2637 |
///\ingroup gutils |
| 2638 | 2638 |
///This class is the same as \ref ArcLookUp, with the addition |
| 2639 | 2639 |
///that it makes it possible to find all arcs between given endpoints. |
| 2640 | 2640 |
/// |
| 2641 | 2641 |
///\warning This class is static, so you should refresh() (or at least |
| 2642 | 2642 |
///refresh(Node)) this data structure |
| 2643 | 2643 |
///whenever the digraph changes. This is a time consuming (superlinearly |
| 2644 | 2644 |
///proportional (<em>O(m</em>log<em>m)</em>) to the number of arcs). |
| 2645 | 2645 |
/// |
| 2646 | 2646 |
///\tparam G The type of the underlying digraph. |
| 2647 | 2647 |
/// |
| 2648 | 2648 |
///\sa DynArcLookUp |
| 2649 |
///\sa ArcLookUp |
|
| 2649 |
///\sa ArcLookUp |
|
| 2650 | 2650 |
template<class G> |
| 2651 | 2651 |
class AllArcLookUp : public ArcLookUp<G> |
| 2652 | 2652 |
{
|
| 2653 | 2653 |
using ArcLookUp<G>::_g; |
| 2654 | 2654 |
using ArcLookUp<G>::_right; |
| 2655 | 2655 |
using ArcLookUp<G>::_left; |
| 2656 | 2656 |
using ArcLookUp<G>::_head; |
| 2657 | 2657 |
|
| 2658 | 2658 |
TEMPLATE_DIGRAPH_TYPEDEFS(G); |
| 2659 | 2659 |
typedef G Digraph; |
| 2660 |
|
|
| 2660 |
|
|
| 2661 | 2661 |
typename Digraph::template ArcMap<Arc> _next; |
| 2662 |
|
|
| 2662 |
|
|
| 2663 | 2663 |
Arc refreshNext(Arc head,Arc next=INVALID) |
| 2664 | 2664 |
{
|
| 2665 | 2665 |
if(head==INVALID) return next; |
| 2666 | 2666 |
else {
|
| 2667 |
next=refreshNext(_right[head],next); |
|
| 2668 |
// _next[head]=next; |
|
| 2669 |
_next[head]=( next!=INVALID && _g.target(next)==_g.target(head)) |
|
| 2670 |
? next : INVALID; |
|
| 2671 |
|
|
| 2667 |
next=refreshNext(_right[head],next); |
|
| 2668 |
// _next[head]=next; |
|
| 2669 |
_next[head]=( next!=INVALID && _g.target(next)==_g.target(head)) |
|
| 2670 |
? next : INVALID; |
|
| 2671 |
return refreshNext(_left[head],head); |
|
| 2672 | 2672 |
} |
| 2673 | 2673 |
} |
| 2674 |
|
|
| 2674 |
|
|
| 2675 | 2675 |
void refreshNext() |
| 2676 | 2676 |
{
|
| 2677 | 2677 |
for(NodeIt n(_g);n!=INVALID;++n) refreshNext(_head[n]); |
| 2678 | 2678 |
} |
| 2679 |
|
|
| 2679 |
|
|
| 2680 | 2680 |
public: |
| 2681 | 2681 |
///Constructor |
| 2682 | 2682 |
|
| 2683 | 2683 |
///Constructor. |
| 2684 | 2684 |
/// |
| 2685 | 2685 |
///It builds up the search database, which remains valid until the digraph |
| 2686 | 2686 |
///changes. |
| 2687 | 2687 |
AllArcLookUp(const Digraph &g) : ArcLookUp<G>(g), _next(g) {refreshNext();}
|
| 2688 | 2688 |
|
| 2689 | 2689 |
///Refresh the data structure at a node. |
| 2690 | 2690 |
|
| 2691 | 2691 |
///Build up the search database of node \c n. |
| 2692 | 2692 |
/// |
| 2693 | 2693 |
///It runs in time <em>O(d</em>log<em>d)</em>, where <em>d</em> is |
| 2694 | 2694 |
///the number of the outgoing arcs of \c n. |
| 2695 |
|
|
| 2696 |
void refresh(Node n) |
|
| 2695 |
|
|
| 2696 |
void refresh(Node n) |
|
| 2697 | 2697 |
{
|
| 2698 | 2698 |
ArcLookUp<G>::refresh(n); |
| 2699 | 2699 |
refreshNext(_head[n]); |
| 2700 | 2700 |
} |
| 2701 |
|
|
| 2701 |
|
|
| 2702 | 2702 |
///Refresh the full data structure. |
| 2703 | 2703 |
|
| 2704 | 2704 |
///Build up the full search database. In fact, it simply calls |
| 2705 | 2705 |
///\ref refresh(Node) "refresh(n)" for each node \c n. |
| 2706 | 2706 |
/// |
| 2707 | 2707 |
///It runs in time <em>O(m</em>log<em>D)</em>, where <em>m</em> is |
| 2708 | 2708 |
///the number of the arcs of \c n and <em>D</em> is the maximum |
| 2709 | 2709 |
///out-degree of the digraph. |
| 2710 | 2710 |
|
| 2711 |
void refresh() |
|
| 2711 |
void refresh() |
|
| 2712 | 2712 |
{
|
| 2713 | 2713 |
for(NodeIt n(_g);n!=INVALID;++n) refresh(_head[n]); |
| 2714 | 2714 |
} |
| 2715 |
|
|
| 2715 |
|
|
| 2716 | 2716 |
///Find an arc between two nodes. |
| 2717 |
|
|
| 2717 |
|
|
| 2718 | 2718 |
///Find an arc between two nodes. |
| 2719 | 2719 |
///\param s The source node |
| 2720 | 2720 |
///\param t The target node |
| 2721 | 2721 |
///\param prev The previous arc between \c s and \c t. It it is INVALID or |
| 2722 | 2722 |
///not given, the operator finds the first appropriate arc. |
| 2723 | 2723 |
///\return An arc from \c s to \c t after \c prev or |
| 2724 | 2724 |
///\ref INVALID if there is no more. |
| 2725 | 2725 |
/// |
| 2726 | 2726 |
///For example, you can count the number of arcs from \c u to \c v in the |
| 2727 | 2727 |
///following way. |
| 2728 | 2728 |
///\code |
| 2729 | 2729 |
///AllArcLookUp<ListDigraph> ae(g); |
| 2730 | 2730 |
///... |
| 2731 | 2731 |
///int n=0; |
| 2732 | 2732 |
///for(Arc e=ae(u,v);e!=INVALID;e=ae(u,v,e)) n++; |
| 2733 | 2733 |
///\endcode |
| ... | ... |
@@ -2737,24 +2737,24 @@ |
| 2737 | 2737 |
///consecutive arcs are found in constant time. |
| 2738 | 2738 |
/// |
| 2739 | 2739 |
///\warning If you change the digraph, refresh() must be called before using |
| 2740 | 2740 |
///this operator. If you change the outgoing arcs of |
| 2741 | 2741 |
///a single node \c n, then |
| 2742 | 2742 |
///\ref refresh(Node) "refresh(n)" is enough. |
| 2743 | 2743 |
/// |
| 2744 | 2744 |
#ifdef DOXYGEN |
| 2745 | 2745 |
Arc operator()(Node s, Node t, Arc prev=INVALID) const {}
|
| 2746 | 2746 |
#else |
| 2747 | 2747 |
using ArcLookUp<G>::operator() ; |
| 2748 | 2748 |
Arc operator()(Node s, Node t, Arc prev) const |
| 2749 | 2749 |
{
|
| 2750 | 2750 |
return prev==INVALID?(*this)(s,t):_next[prev]; |
| 2751 | 2751 |
} |
| 2752 | 2752 |
#endif |
| 2753 |
|
|
| 2753 |
|
|
| 2754 | 2754 |
}; |
| 2755 | 2755 |
|
| 2756 | 2756 |
/// @} |
| 2757 | 2757 |
|
| 2758 | 2758 |
} //END OF NAMESPACE LEMON |
| 2759 | 2759 |
|
| 2760 | 2760 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_KRUSKAL_H |
| ... | ... |
@@ -32,302 +32,302 @@ |
| 32 | 32 |
|
| 33 | 33 |
///\ingroup spantree |
| 34 | 34 |
///\file |
| 35 | 35 |
///\brief Kruskal's algorithm to compute a minimum cost spanning tree |
| 36 | 36 |
/// |
| 37 | 37 |
///Kruskal's algorithm to compute a minimum cost spanning tree. |
| 38 | 38 |
/// |
| 39 | 39 |
|
| 40 | 40 |
namespace lemon {
|
| 41 | 41 |
|
| 42 | 42 |
namespace _kruskal_bits {
|
| 43 | 43 |
|
| 44 | 44 |
// Kruskal for directed graphs. |
| 45 | 45 |
|
| 46 | 46 |
template <typename Digraph, typename In, typename Out> |
| 47 | 47 |
typename disable_if<lemon::UndirectedTagIndicator<Digraph>, |
| 48 |
|
|
| 48 |
typename In::value_type::second_type >::type |
|
| 49 | 49 |
kruskal(const Digraph& digraph, const In& in, Out& out,dummy<0> = 0) {
|
| 50 | 50 |
typedef typename In::value_type::second_type Value; |
| 51 | 51 |
typedef typename Digraph::template NodeMap<int> IndexMap; |
| 52 | 52 |
typedef typename Digraph::Node Node; |
| 53 |
|
|
| 53 |
|
|
| 54 | 54 |
IndexMap index(digraph); |
| 55 | 55 |
UnionFind<IndexMap> uf(index); |
| 56 | 56 |
for (typename Digraph::NodeIt it(digraph); it != INVALID; ++it) {
|
| 57 | 57 |
uf.insert(it); |
| 58 | 58 |
} |
| 59 |
|
|
| 59 |
|
|
| 60 | 60 |
Value tree_value = 0; |
| 61 | 61 |
for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
|
| 62 | 62 |
if (uf.join(digraph.target(it->first),digraph.source(it->first))) {
|
| 63 | 63 |
out.set(it->first, true); |
| 64 | 64 |
tree_value += it->second; |
| 65 | 65 |
} |
| 66 | 66 |
else {
|
| 67 | 67 |
out.set(it->first, false); |
| 68 | 68 |
} |
| 69 | 69 |
} |
| 70 | 70 |
return tree_value; |
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 | 73 |
// Kruskal for undirected graphs. |
| 74 | 74 |
|
| 75 | 75 |
template <typename Graph, typename In, typename Out> |
| 76 | 76 |
typename enable_if<lemon::UndirectedTagIndicator<Graph>, |
| 77 |
|
|
| 77 |
typename In::value_type::second_type >::type |
|
| 78 | 78 |
kruskal(const Graph& graph, const In& in, Out& out,dummy<1> = 1) {
|
| 79 | 79 |
typedef typename In::value_type::second_type Value; |
| 80 | 80 |
typedef typename Graph::template NodeMap<int> IndexMap; |
| 81 | 81 |
typedef typename Graph::Node Node; |
| 82 |
|
|
| 82 |
|
|
| 83 | 83 |
IndexMap index(graph); |
| 84 | 84 |
UnionFind<IndexMap> uf(index); |
| 85 | 85 |
for (typename Graph::NodeIt it(graph); it != INVALID; ++it) {
|
| 86 | 86 |
uf.insert(it); |
| 87 | 87 |
} |
| 88 |
|
|
| 88 |
|
|
| 89 | 89 |
Value tree_value = 0; |
| 90 | 90 |
for (typename In::const_iterator it = in.begin(); it != in.end(); ++it) {
|
| 91 | 91 |
if (uf.join(graph.u(it->first),graph.v(it->first))) {
|
| 92 | 92 |
out.set(it->first, true); |
| 93 | 93 |
tree_value += it->second; |
| 94 | 94 |
} |
| 95 | 95 |
else {
|
| 96 | 96 |
out.set(it->first, false); |
| 97 | 97 |
} |
| 98 | 98 |
} |
| 99 | 99 |
return tree_value; |
| 100 | 100 |
} |
| 101 | 101 |
|
| 102 | 102 |
|
| 103 | 103 |
template <typename Sequence> |
| 104 | 104 |
struct PairComp {
|
| 105 | 105 |
typedef typename Sequence::value_type Value; |
| 106 | 106 |
bool operator()(const Value& left, const Value& right) {
|
| 107 |
|
|
| 107 |
return left.second < right.second; |
|
| 108 | 108 |
} |
| 109 | 109 |
}; |
| 110 | 110 |
|
| 111 | 111 |
template <typename In, typename Enable = void> |
| 112 | 112 |
struct SequenceInputIndicator {
|
| 113 | 113 |
static const bool value = false; |
| 114 | 114 |
}; |
| 115 | 115 |
|
| 116 | 116 |
template <typename In> |
| 117 |
struct SequenceInputIndicator<In, |
|
| 117 |
struct SequenceInputIndicator<In, |
|
| 118 | 118 |
typename exists<typename In::value_type::first_type>::type> {
|
| 119 | 119 |
static const bool value = true; |
| 120 | 120 |
}; |
| 121 | 121 |
|
| 122 | 122 |
template <typename In, typename Enable = void> |
| 123 | 123 |
struct MapInputIndicator {
|
| 124 | 124 |
static const bool value = false; |
| 125 | 125 |
}; |
| 126 | 126 |
|
| 127 | 127 |
template <typename In> |
| 128 |
struct MapInputIndicator<In, |
|
| 128 |
struct MapInputIndicator<In, |
|
| 129 | 129 |
typename exists<typename In::Value>::type> {
|
| 130 | 130 |
static const bool value = true; |
| 131 | 131 |
}; |
| 132 | 132 |
|
| 133 | 133 |
template <typename In, typename Enable = void> |
| 134 | 134 |
struct SequenceOutputIndicator {
|
| 135 | 135 |
static const bool value = false; |
| 136 | 136 |
}; |
| 137 |
|
|
| 137 |
|
|
| 138 | 138 |
template <typename Out> |
| 139 |
struct SequenceOutputIndicator<Out, |
|
| 139 |
struct SequenceOutputIndicator<Out, |
|
| 140 | 140 |
typename exists<typename Out::value_type>::type> {
|
| 141 | 141 |
static const bool value = true; |
| 142 | 142 |
}; |
| 143 | 143 |
|
| 144 | 144 |
template <typename Out, typename Enable = void> |
| 145 | 145 |
struct MapOutputIndicator {
|
| 146 | 146 |
static const bool value = false; |
| 147 | 147 |
}; |
| 148 | 148 |
|
| 149 | 149 |
template <typename Out> |
| 150 |
struct MapOutputIndicator<Out, |
|
| 150 |
struct MapOutputIndicator<Out, |
|
| 151 | 151 |
typename exists<typename Out::Value>::type> {
|
| 152 | 152 |
static const bool value = true; |
| 153 | 153 |
}; |
| 154 | 154 |
|
| 155 | 155 |
template <typename In, typename InEnable = void> |
| 156 | 156 |
struct KruskalValueSelector {};
|
| 157 | 157 |
|
| 158 | 158 |
template <typename In> |
| 159 | 159 |
struct KruskalValueSelector<In, |
| 160 |
typename enable_if<SequenceInputIndicator<In>, void>::type> |
|
| 160 |
typename enable_if<SequenceInputIndicator<In>, void>::type> |
|
| 161 | 161 |
{
|
| 162 | 162 |
typedef typename In::value_type::second_type Value; |
| 163 |
}; |
|
| 163 |
}; |
|
| 164 | 164 |
|
| 165 | 165 |
template <typename In> |
| 166 | 166 |
struct KruskalValueSelector<In, |
| 167 |
typename enable_if<MapInputIndicator<In>, void>::type> |
|
| 167 |
typename enable_if<MapInputIndicator<In>, void>::type> |
|
| 168 | 168 |
{
|
| 169 | 169 |
typedef typename In::Value Value; |
| 170 |
}; |
|
| 171 |
|
|
| 170 |
}; |
|
| 171 |
|
|
| 172 | 172 |
template <typename Graph, typename In, typename Out, |
| 173 | 173 |
typename InEnable = void> |
| 174 | 174 |
struct KruskalInputSelector {};
|
| 175 | 175 |
|
| 176 | 176 |
template <typename Graph, typename In, typename Out, |
| 177 | 177 |
typename InEnable = void> |
| 178 | 178 |
struct KruskalOutputSelector {};
|
| 179 |
|
|
| 179 |
|
|
| 180 | 180 |
template <typename Graph, typename In, typename Out> |
| 181 | 181 |
struct KruskalInputSelector<Graph, In, Out, |
| 182 |
typename enable_if<SequenceInputIndicator<In>, void>::type > |
|
| 182 |
typename enable_if<SequenceInputIndicator<In>, void>::type > |
|
| 183 | 183 |
{
|
| 184 | 184 |
typedef typename In::value_type::second_type Value; |
| 185 | 185 |
|
| 186 | 186 |
static Value kruskal(const Graph& graph, const In& in, Out& out) {
|
| 187 | 187 |
return KruskalOutputSelector<Graph, In, Out>:: |
| 188 | 188 |
kruskal(graph, in, out); |
| 189 | 189 |
} |
| 190 | 190 |
|
| 191 | 191 |
}; |
| 192 | 192 |
|
| 193 | 193 |
template <typename Graph, typename In, typename Out> |
| 194 | 194 |
struct KruskalInputSelector<Graph, In, Out, |
| 195 |
typename enable_if<MapInputIndicator<In>, void>::type > |
|
| 195 |
typename enable_if<MapInputIndicator<In>, void>::type > |
|
| 196 | 196 |
{
|
| 197 | 197 |
typedef typename In::Value Value; |
| 198 | 198 |
static Value kruskal(const Graph& graph, const In& in, Out& out) {
|
| 199 | 199 |
typedef typename In::Key MapArc; |
| 200 | 200 |
typedef typename In::Value Value; |
| 201 | 201 |
typedef typename ItemSetTraits<Graph, MapArc>::ItemIt MapArcIt; |
| 202 | 202 |
typedef std::vector<std::pair<MapArc, Value> > Sequence; |
| 203 | 203 |
Sequence seq; |
| 204 |
|
|
| 204 |
|
|
| 205 | 205 |
for (MapArcIt it(graph); it != INVALID; ++it) {
|
| 206 | 206 |
seq.push_back(std::make_pair(it, in[it])); |
| 207 | 207 |
} |
| 208 | 208 |
|
| 209 | 209 |
std::sort(seq.begin(), seq.end(), PairComp<Sequence>()); |
| 210 | 210 |
return KruskalOutputSelector<Graph, Sequence, Out>:: |
| 211 | 211 |
kruskal(graph, seq, out); |
| 212 | 212 |
} |
| 213 | 213 |
}; |
| 214 | 214 |
|
| 215 | 215 |
template <typename T> |
| 216 | 216 |
struct RemoveConst {
|
| 217 | 217 |
typedef T type; |
| 218 | 218 |
}; |
| 219 | 219 |
|
| 220 | 220 |
template <typename T> |
| 221 | 221 |
struct RemoveConst<const T> {
|
| 222 | 222 |
typedef T type; |
| 223 | 223 |
}; |
| 224 | 224 |
|
| 225 | 225 |
template <typename Graph, typename In, typename Out> |
| 226 | 226 |
struct KruskalOutputSelector<Graph, In, Out, |
| 227 |
typename enable_if<SequenceOutputIndicator<Out>, void>::type > |
|
| 227 |
typename enable_if<SequenceOutputIndicator<Out>, void>::type > |
|
| 228 | 228 |
{
|
| 229 | 229 |
typedef typename In::value_type::second_type Value; |
| 230 | 230 |
|
| 231 | 231 |
static Value kruskal(const Graph& graph, const In& in, Out& out) {
|
| 232 | 232 |
typedef LoggerBoolMap<typename RemoveConst<Out>::type> Map; |
| 233 | 233 |
Map map(out); |
| 234 | 234 |
return _kruskal_bits::kruskal(graph, in, map); |
| 235 | 235 |
} |
| 236 | 236 |
|
| 237 | 237 |
}; |
| 238 | 238 |
|
| 239 | 239 |
template <typename Graph, typename In, typename Out> |
| 240 | 240 |
struct KruskalOutputSelector<Graph, In, Out, |
| 241 |
typename enable_if<MapOutputIndicator<Out>, void>::type > |
|
| 241 |
typename enable_if<MapOutputIndicator<Out>, void>::type > |
|
| 242 | 242 |
{
|
| 243 | 243 |
typedef typename In::value_type::second_type Value; |
| 244 | 244 |
|
| 245 | 245 |
static Value kruskal(const Graph& graph, const In& in, Out& out) {
|
| 246 | 246 |
return _kruskal_bits::kruskal(graph, in, out); |
| 247 | 247 |
} |
| 248 | 248 |
}; |
| 249 | 249 |
|
| 250 | 250 |
} |
| 251 | 251 |
|
| 252 | 252 |
/// \ingroup spantree |
| 253 | 253 |
/// |
| 254 | 254 |
/// \brief Kruskal algorithm to find a minimum cost spanning tree of |
| 255 | 255 |
/// a graph. |
| 256 | 256 |
/// |
| 257 |
/// This function runs Kruskal's algorithm to find a minimum cost |
|
| 257 |
/// This function runs Kruskal's algorithm to find a minimum cost |
|
| 258 | 258 |
/// spanning tree. |
| 259 | 259 |
/// Due to some C++ hacking, it accepts various input and output types. |
| 260 | 260 |
/// |
| 261 | 261 |
/// \param g The graph the algorithm runs on. |
| 262 |
/// It can be either \ref concepts::Digraph "directed" or |
|
| 262 |
/// It can be either \ref concepts::Digraph "directed" or |
|
| 263 | 263 |
/// \ref concepts::Graph "undirected". |
| 264 |
/// If the graph is directed, the algorithm consider it to be |
|
| 264 |
/// If the graph is directed, the algorithm consider it to be |
|
| 265 | 265 |
/// undirected by disregarding the direction of the arcs. |
| 266 | 266 |
/// |
| 267 |
/// \param in This object is used to describe the arc/edge costs. |
|
| 267 |
/// \param in This object is used to describe the arc/edge costs. |
|
| 268 | 268 |
/// It can be one of the following choices. |
| 269 | 269 |
/// - An STL compatible 'Forward Container' with |
| 270 | 270 |
/// <tt>std::pair<GR::Arc,X></tt> or |
| 271 | 271 |
/// <tt>std::pair<GR::Edge,X></tt> as its <tt>value_type</tt>, where |
| 272 | 272 |
/// \c X is the type of the costs. The pairs indicates the arcs/edges |
| 273 | 273 |
/// along with the assigned cost. <em>They must be in a |
| 274 | 274 |
/// cost-ascending order.</em> |
| 275 |
/// - Any readable arc/edge map. The values of the map indicate the |
|
| 275 |
/// - Any readable arc/edge map. The values of the map indicate the |
|
| 276 | 276 |
/// arc/edge costs. |
| 277 | 277 |
/// |
| 278 | 278 |
/// \retval out Here we also have a choice. |
| 279 | 279 |
/// - It can be a writable \c bool arc/edge map. After running the |
| 280 | 280 |
/// algorithm it will contain the found minimum cost spanning |
| 281 | 281 |
/// tree: the value of an arc/edge will be set to \c true if it belongs |
| 282 | 282 |
/// to the tree, otherwise it will be set to \c false. The value of |
| 283 | 283 |
/// each arc/edge will be set exactly once. |
| 284 | 284 |
/// - It can also be an iteraror of an STL Container with |
| 285 | 285 |
/// <tt>GR::Arc</tt> or <tt>GR::Edge</tt> as its |
| 286 | 286 |
/// <tt>value_type</tt>. The algorithm copies the elements of the |
| 287 | 287 |
/// found tree into this sequence. For example, if we know that the |
| 288 | 288 |
/// spanning tree of the graph \c g has say 53 arcs, then we can |
| 289 | 289 |
/// put its arcs into an STL vector \c tree with a code like this. |
| 290 | 290 |
///\code |
| 291 | 291 |
/// std::vector<Arc> tree(53); |
| 292 | 292 |
/// kruskal(g,cost,tree.begin()); |
| 293 | 293 |
///\endcode |
| 294 | 294 |
/// Or if we don't know in advance the size of the tree, we can |
| 295 |
/// write this. |
|
| 295 |
/// write this. |
|
| 296 | 296 |
///\code |
| 297 | 297 |
/// std::vector<Arc> tree; |
| 298 |
/// kruskal(g,cost,std::back_inserter(tree)); |
|
| 298 |
/// kruskal(g,cost,std::back_inserter(tree)); |
|
| 299 | 299 |
///\endcode |
| 300 | 300 |
/// |
| 301 | 301 |
/// \return The total cost of the found spanning tree. |
| 302 | 302 |
/// |
| 303 | 303 |
/// \warning If Kruskal runs on an be consistent of using the same |
| 304 | 304 |
/// Arc type for input and output. |
| 305 | 305 |
/// |
| 306 | 306 |
|
| 307 | 307 |
#ifdef DOXYGEN |
| 308 | 308 |
template <class Graph, class In, class Out> |
| 309 | 309 |
Value kruskal(GR const& g, const In& in, Out& out) |
| 310 |
#else |
|
| 310 |
#else |
|
| 311 | 311 |
template <class Graph, class In, class Out> |
| 312 |
inline typename _kruskal_bits::KruskalValueSelector<In>::Value |
|
| 313 |
kruskal(const Graph& graph, const In& in, Out& out) |
|
| 312 |
inline typename _kruskal_bits::KruskalValueSelector<In>::Value |
|
| 313 |
kruskal(const Graph& graph, const In& in, Out& out) |
|
| 314 | 314 |
#endif |
| 315 | 315 |
{
|
| 316 | 316 |
return _kruskal_bits::KruskalInputSelector<Graph, In, Out>:: |
| 317 | 317 |
kruskal(graph, in, out); |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 |
|
|
| 321 |
|
|
| 320 |
|
|
| 321 |
|
|
| 322 | 322 |
|
| 323 | 323 |
template <class Graph, class In, class Out> |
| 324 | 324 |
inline typename _kruskal_bits::KruskalValueSelector<In>::Value |
| 325 | 325 |
kruskal(const Graph& graph, const In& in, const Out& out) |
| 326 | 326 |
{
|
| 327 | 327 |
return _kruskal_bits::KruskalInputSelector<Graph, In, const Out>:: |
| 328 | 328 |
kruskal(graph, in, out); |
| 329 |
} |
|
| 329 |
} |
|
| 330 | 330 |
|
| 331 | 331 |
} //namespace lemon |
| 332 | 332 |
|
| 333 | 333 |
#endif //LEMON_KRUSKAL_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
| ... | ... |
@@ -33,386 +33,386 @@ |
| 33 | 33 |
|
| 34 | 34 |
#include <lemon/assert.h> |
| 35 | 35 |
#include <lemon/graph_utils.h> |
| 36 | 36 |
|
| 37 | 37 |
#include <lemon/lgf_writer.h> |
| 38 | 38 |
|
| 39 | 39 |
#include <lemon/concept_check.h> |
| 40 | 40 |
#include <lemon/concepts/maps.h> |
| 41 | 41 |
|
| 42 | 42 |
namespace lemon {
|
| 43 | 43 |
|
| 44 | 44 |
namespace _reader_bits {
|
| 45 | 45 |
|
| 46 | 46 |
template <typename Value> |
| 47 | 47 |
struct DefaultConverter {
|
| 48 | 48 |
Value operator()(const std::string& str) {
|
| 49 |
std::istringstream is(str); |
|
| 50 |
Value value; |
|
| 51 |
is >> value; |
|
| 52 |
|
|
| 53 |
char c; |
|
| 54 |
if (is >> std::ws >> c) {
|
|
| 55 |
throw DataFormatError("Remaining characters in token");
|
|
| 56 |
} |
|
| 57 |
|
|
| 49 |
std::istringstream is(str); |
|
| 50 |
Value value; |
|
| 51 |
is >> value; |
|
| 52 |
|
|
| 53 |
char c; |
|
| 54 |
if (is >> std::ws >> c) {
|
|
| 55 |
throw DataFormatError("Remaining characters in token");
|
|
| 56 |
} |
|
| 57 |
return value; |
|
| 58 | 58 |
} |
| 59 | 59 |
}; |
| 60 | 60 |
|
| 61 | 61 |
template <> |
| 62 | 62 |
struct DefaultConverter<std::string> {
|
| 63 | 63 |
std::string operator()(const std::string& str) {
|
| 64 |
|
|
| 64 |
return str; |
|
| 65 | 65 |
} |
| 66 | 66 |
}; |
| 67 | 67 |
|
| 68 |
template <typename _Item> |
|
| 68 |
template <typename _Item> |
|
| 69 | 69 |
class MapStorageBase {
|
| 70 | 70 |
public: |
| 71 | 71 |
typedef _Item Item; |
| 72 | 72 |
|
| 73 | 73 |
public: |
| 74 | 74 |
MapStorageBase() {}
|
| 75 | 75 |
virtual ~MapStorageBase() {}
|
| 76 | 76 |
|
| 77 | 77 |
virtual void set(const Item& item, const std::string& value) = 0; |
| 78 | 78 |
|
| 79 | 79 |
}; |
| 80 | 80 |
|
| 81 |
template <typename _Item, typename _Map, |
|
| 82 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 81 |
template <typename _Item, typename _Map, |
|
| 82 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 83 | 83 |
class MapStorage : public MapStorageBase<_Item> {
|
| 84 | 84 |
public: |
| 85 | 85 |
typedef _Map Map; |
| 86 | 86 |
typedef _Converter Converter; |
| 87 | 87 |
typedef _Item Item; |
| 88 |
|
|
| 88 |
|
|
| 89 | 89 |
private: |
| 90 | 90 |
Map& _map; |
| 91 | 91 |
Converter _converter; |
| 92 | 92 |
|
| 93 | 93 |
public: |
| 94 |
MapStorage(Map& map, const Converter& converter = Converter()) |
|
| 95 |
: _map(map), _converter(converter) {}
|
|
| 94 |
MapStorage(Map& map, const Converter& converter = Converter()) |
|
| 95 |
: _map(map), _converter(converter) {}
|
|
| 96 | 96 |
virtual ~MapStorage() {}
|
| 97 | 97 |
|
| 98 | 98 |
virtual void set(const Item& item ,const std::string& value) {
|
| 99 |
|
|
| 99 |
_map.set(item, _converter(value)); |
|
| 100 | 100 |
} |
| 101 | 101 |
}; |
| 102 | 102 |
|
| 103 |
template <typename _Graph, bool _dir, typename _Map, |
|
| 104 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 103 |
template <typename _Graph, bool _dir, typename _Map, |
|
| 104 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 105 | 105 |
class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
|
| 106 | 106 |
public: |
| 107 | 107 |
typedef _Map Map; |
| 108 | 108 |
typedef _Converter Converter; |
| 109 | 109 |
typedef _Graph Graph; |
| 110 | 110 |
typedef typename Graph::Edge Item; |
| 111 | 111 |
static const bool dir = _dir; |
| 112 |
|
|
| 112 |
|
|
| 113 | 113 |
private: |
| 114 | 114 |
const Graph& _graph; |
| 115 | 115 |
Map& _map; |
| 116 | 116 |
Converter _converter; |
| 117 | 117 |
|
| 118 | 118 |
public: |
| 119 |
GraphArcMapStorage(const Graph& graph, Map& map, |
|
| 120 |
const Converter& converter = Converter()) |
|
| 121 |
|
|
| 119 |
GraphArcMapStorage(const Graph& graph, Map& map, |
|
| 120 |
const Converter& converter = Converter()) |
|
| 121 |
: _graph(graph), _map(map), _converter(converter) {}
|
|
| 122 | 122 |
virtual ~GraphArcMapStorage() {}
|
| 123 | 123 |
|
| 124 | 124 |
virtual void set(const Item& item ,const std::string& value) {
|
| 125 |
|
|
| 125 |
_map.set(_graph.direct(item, dir), _converter(value)); |
|
| 126 | 126 |
} |
| 127 | 127 |
}; |
| 128 | 128 |
|
| 129 | 129 |
class ValueStorageBase {
|
| 130 | 130 |
public: |
| 131 | 131 |
ValueStorageBase() {}
|
| 132 | 132 |
virtual ~ValueStorageBase() {}
|
| 133 | 133 |
|
| 134 | 134 |
virtual void set(const std::string&) = 0; |
| 135 | 135 |
}; |
| 136 | 136 |
|
| 137 | 137 |
template <typename _Value, typename _Converter = DefaultConverter<_Value> > |
| 138 | 138 |
class ValueStorage : public ValueStorageBase {
|
| 139 | 139 |
public: |
| 140 | 140 |
typedef _Value Value; |
| 141 | 141 |
typedef _Converter Converter; |
| 142 | 142 |
|
| 143 | 143 |
private: |
| 144 | 144 |
Value& _value; |
| 145 | 145 |
Converter _converter; |
| 146 | 146 |
|
| 147 | 147 |
public: |
| 148 | 148 |
ValueStorage(Value& value, const Converter& converter = Converter()) |
| 149 |
|
|
| 149 |
: _value(value), _converter(converter) {}
|
|
| 150 | 150 |
|
| 151 | 151 |
virtual void set(const std::string& value) {
|
| 152 |
|
|
| 152 |
_value = _converter(value); |
|
| 153 | 153 |
} |
| 154 | 154 |
}; |
| 155 | 155 |
|
| 156 | 156 |
template <typename Value> |
| 157 | 157 |
struct MapLookUpConverter {
|
| 158 | 158 |
const std::map<std::string, Value>& _map; |
| 159 | 159 |
|
| 160 | 160 |
MapLookUpConverter(const std::map<std::string, Value>& map) |
| 161 | 161 |
: _map(map) {}
|
| 162 | 162 |
|
| 163 | 163 |
Value operator()(const std::string& str) {
|
| 164 | 164 |
typename std::map<std::string, Value>::const_iterator it = |
| 165 | 165 |
_map.find(str); |
| 166 | 166 |
if (it == _map.end()) {
|
| 167 | 167 |
std::ostringstream msg; |
| 168 | 168 |
msg << "Item not found: " << str; |
| 169 | 169 |
throw DataFormatError(msg.str().c_str()); |
| 170 | 170 |
} |
| 171 | 171 |
return it->second; |
| 172 | 172 |
} |
| 173 | 173 |
}; |
| 174 | 174 |
|
| 175 | 175 |
template <typename Graph> |
| 176 | 176 |
struct GraphArcLookUpConverter {
|
| 177 | 177 |
const Graph& _graph; |
| 178 | 178 |
const std::map<std::string, typename Graph::Edge>& _map; |
| 179 |
|
|
| 180 |
GraphArcLookUpConverter(const Graph& graph, |
|
| 181 |
const std::map<std::string, |
|
| 182 |
typename Graph::Edge>& map) |
|
| 183 |
: _graph(graph), _map(map) {}
|
|
| 184 |
|
|
| 179 |
|
|
| 180 |
GraphArcLookUpConverter(const Graph& graph, |
|
| 181 |
const std::map<std::string, |
|
| 182 |
typename Graph::Edge>& map) |
|
| 183 |
: _graph(graph), _map(map) {}
|
|
| 184 |
|
|
| 185 | 185 |
typename Graph::Arc operator()(const std::string& str) {
|
| 186 |
if (str.empty() || (str[0] != '+' && str[0] != '-')) {
|
|
| 187 |
throw DataFormatError("Item must start with '+' or '-'");
|
|
| 188 |
} |
|
| 189 |
typename std::map<std::string, typename Graph::Edge> |
|
| 190 |
::const_iterator it = _map.find(str.substr(1)); |
|
| 191 |
if (it == _map.end()) {
|
|
| 192 |
throw DataFormatError("Item not found");
|
|
| 193 |
} |
|
| 194 |
|
|
| 186 |
if (str.empty() || (str[0] != '+' && str[0] != '-')) {
|
|
| 187 |
throw DataFormatError("Item must start with '+' or '-'");
|
|
| 188 |
} |
|
| 189 |
typename std::map<std::string, typename Graph::Edge> |
|
| 190 |
::const_iterator it = _map.find(str.substr(1)); |
|
| 191 |
if (it == _map.end()) {
|
|
| 192 |
throw DataFormatError("Item not found");
|
|
| 193 |
} |
|
| 194 |
return _graph.direct(it->second, str[0] == '+'); |
|
| 195 | 195 |
} |
| 196 | 196 |
}; |
| 197 | 197 |
|
| 198 | 198 |
inline bool isWhiteSpace(char c) {
|
| 199 |
return c == ' ' || c == '\t' || c == '\v' || |
|
| 200 |
c == '\n' || c == '\r' || c == '\f'; |
|
| 199 |
return c == ' ' || c == '\t' || c == '\v' || |
|
| 200 |
c == '\n' || c == '\r' || c == '\f'; |
|
| 201 | 201 |
} |
| 202 |
|
|
| 202 |
|
|
| 203 | 203 |
inline bool isOct(char c) {
|
| 204 |
return '0' <= c && c <='7'; |
|
| 204 |
return '0' <= c && c <='7'; |
|
| 205 | 205 |
} |
| 206 |
|
|
| 206 |
|
|
| 207 | 207 |
inline int valueOct(char c) {
|
| 208 | 208 |
LEMON_ASSERT(isOct(c), "The character is not octal."); |
| 209 | 209 |
return c - '0'; |
| 210 | 210 |
} |
| 211 | 211 |
|
| 212 | 212 |
inline bool isHex(char c) {
|
| 213 |
return ('0' <= c && c <= '9') ||
|
|
| 214 |
('a' <= c && c <= 'z') ||
|
|
| 215 |
|
|
| 213 |
return ('0' <= c && c <= '9') ||
|
|
| 214 |
('a' <= c && c <= 'z') ||
|
|
| 215 |
('A' <= c && c <= 'Z');
|
|
| 216 | 216 |
} |
| 217 |
|
|
| 217 |
|
|
| 218 | 218 |
inline int valueHex(char c) {
|
| 219 | 219 |
LEMON_ASSERT(isHex(c), "The character is not hexadecimal."); |
| 220 | 220 |
if ('0' <= c && c <= '9') return c - '0';
|
| 221 | 221 |
if ('a' <= c && c <= 'z') return c - 'a' + 10;
|
| 222 | 222 |
return c - 'A' + 10; |
| 223 | 223 |
} |
| 224 | 224 |
|
| 225 | 225 |
inline bool isIdentifierFirstChar(char c) {
|
| 226 | 226 |
return ('a' <= c && c <= 'z') ||
|
| 227 |
|
|
| 227 |
('A' <= c && c <= 'Z') || c == '_';
|
|
| 228 | 228 |
} |
| 229 | 229 |
|
| 230 | 230 |
inline bool isIdentifierChar(char c) {
|
| 231 | 231 |
return isIdentifierFirstChar(c) || |
| 232 |
|
|
| 232 |
('0' <= c && c <= '9');
|
|
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
inline char readEscape(std::istream& is) {
|
| 236 | 236 |
char c; |
| 237 | 237 |
if (!is.get(c)) |
| 238 |
|
|
| 238 |
throw DataFormatError("Escape format error");
|
|
| 239 | 239 |
|
| 240 | 240 |
switch (c) {
|
| 241 | 241 |
case '\\': |
| 242 |
|
|
| 242 |
return '\\'; |
|
| 243 | 243 |
case '\"': |
| 244 |
|
|
| 244 |
return '\"'; |
|
| 245 | 245 |
case '\'': |
| 246 |
|
|
| 246 |
return '\''; |
|
| 247 | 247 |
case '\?': |
| 248 |
|
|
| 248 |
return '\?'; |
|
| 249 | 249 |
case 'a': |
| 250 |
|
|
| 250 |
return '\a'; |
|
| 251 | 251 |
case 'b': |
| 252 |
|
|
| 252 |
return '\b'; |
|
| 253 | 253 |
case 'f': |
| 254 |
|
|
| 254 |
return '\f'; |
|
| 255 | 255 |
case 'n': |
| 256 |
|
|
| 256 |
return '\n'; |
|
| 257 | 257 |
case 'r': |
| 258 |
|
|
| 258 |
return '\r'; |
|
| 259 | 259 |
case 't': |
| 260 |
|
|
| 260 |
return '\t'; |
|
| 261 | 261 |
case 'v': |
| 262 |
|
|
| 262 |
return '\v'; |
|
| 263 | 263 |
case 'x': |
| 264 |
{
|
|
| 265 |
int code; |
|
| 266 |
if (!is.get(c) || !isHex(c)) |
|
| 267 |
throw DataFormatError("Escape format error");
|
|
| 268 |
else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
|
| 269 |
else code = code * 16 + valueHex(c); |
|
| 270 |
return code; |
|
| 271 |
} |
|
| 264 |
{
|
|
| 265 |
int code; |
|
| 266 |
if (!is.get(c) || !isHex(c)) |
|
| 267 |
throw DataFormatError("Escape format error");
|
|
| 268 |
else if (code = valueHex(c), !is.get(c) || !isHex(c)) is.putback(c); |
|
| 269 |
else code = code * 16 + valueHex(c); |
|
| 270 |
return code; |
|
| 271 |
} |
|
| 272 | 272 |
default: |
| 273 |
{
|
|
| 274 |
int code; |
|
| 275 |
if (!isOct(c)) |
|
| 276 |
throw DataFormatError("Escape format error");
|
|
| 277 |
else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
|
| 278 |
is.putback(c); |
|
| 279 |
else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
|
| 280 |
is.putback(c); |
|
| 281 |
else code = code * 8 + valueOct(c); |
|
| 282 |
return code; |
|
| 283 |
} |
|
| 284 |
} |
|
| 273 |
{
|
|
| 274 |
int code; |
|
| 275 |
if (!isOct(c)) |
|
| 276 |
throw DataFormatError("Escape format error");
|
|
| 277 |
else if (code = valueOct(c), !is.get(c) || !isOct(c)) |
|
| 278 |
is.putback(c); |
|
| 279 |
else if (code = code * 8 + valueOct(c), !is.get(c) || !isOct(c)) |
|
| 280 |
is.putback(c); |
|
| 281 |
else code = code * 8 + valueOct(c); |
|
| 282 |
return code; |
|
| 283 |
} |
|
| 284 |
} |
|
| 285 | 285 |
} |
| 286 |
|
|
| 286 |
|
|
| 287 | 287 |
inline std::istream& readToken(std::istream& is, std::string& str) {
|
| 288 | 288 |
std::ostringstream os; |
| 289 | 289 |
|
| 290 | 290 |
char c; |
| 291 | 291 |
is >> std::ws; |
| 292 |
|
|
| 293 |
if (!is.get(c)) |
|
| 294 |
|
|
| 292 |
|
|
| 293 |
if (!is.get(c)) |
|
| 294 |
return is; |
|
| 295 | 295 |
|
| 296 | 296 |
if (c == '\"') {
|
| 297 |
while (is.get(c) && c != '\"') {
|
|
| 298 |
if (c == '\\') |
|
| 299 |
c = readEscape(is); |
|
| 300 |
os << c; |
|
| 301 |
} |
|
| 302 |
if (!is) |
|
| 303 |
|
|
| 297 |
while (is.get(c) && c != '\"') {
|
|
| 298 |
if (c == '\\') |
|
| 299 |
c = readEscape(is); |
|
| 300 |
os << c; |
|
| 301 |
} |
|
| 302 |
if (!is) |
|
| 303 |
throw DataFormatError("Quoted format error");
|
|
| 304 | 304 |
} else {
|
| 305 |
is.putback(c); |
|
| 306 |
while (is.get(c) && !isWhiteSpace(c)) {
|
|
| 307 |
if (c == '\\') |
|
| 308 |
c = readEscape(is); |
|
| 309 |
os << c; |
|
| 310 |
} |
|
| 311 |
if (!is) {
|
|
| 312 |
is.clear(); |
|
| 313 |
} else {
|
|
| 314 |
is.putback(c); |
|
| 315 |
|
|
| 305 |
is.putback(c); |
|
| 306 |
while (is.get(c) && !isWhiteSpace(c)) {
|
|
| 307 |
if (c == '\\') |
|
| 308 |
c = readEscape(is); |
|
| 309 |
os << c; |
|
| 310 |
} |
|
| 311 |
if (!is) {
|
|
| 312 |
is.clear(); |
|
| 313 |
} else {
|
|
| 314 |
is.putback(c); |
|
| 315 |
} |
|
| 316 | 316 |
} |
| 317 | 317 |
str = os.str(); |
| 318 | 318 |
return is; |
| 319 | 319 |
} |
| 320 | 320 |
|
| 321 | 321 |
class Section {
|
| 322 | 322 |
public: |
| 323 | 323 |
virtual ~Section() {}
|
| 324 | 324 |
virtual void process(std::istream& is, int& line_num) = 0; |
| 325 | 325 |
}; |
| 326 | 326 |
|
| 327 | 327 |
template <typename Functor> |
| 328 | 328 |
class LineSection : public Section {
|
| 329 | 329 |
private: |
| 330 | 330 |
|
| 331 | 331 |
Functor _functor; |
| 332 | 332 |
|
| 333 | 333 |
public: |
| 334 |
|
|
| 334 |
|
|
| 335 | 335 |
LineSection(const Functor& functor) : _functor(functor) {}
|
| 336 | 336 |
virtual ~LineSection() {}
|
| 337 | 337 |
|
| 338 | 338 |
virtual void process(std::istream& is, int& line_num) {
|
| 339 |
char c; |
|
| 340 |
std::string line; |
|
| 341 |
while (is.get(c) && c != '@') {
|
|
| 342 |
if (c == '\n') {
|
|
| 343 |
++line_num; |
|
| 344 |
} else if (c == '#') {
|
|
| 345 |
getline(is, line); |
|
| 346 |
++line_num; |
|
| 347 |
} else if (!isWhiteSpace(c)) {
|
|
| 348 |
is.putback(c); |
|
| 349 |
getline(is, line); |
|
| 350 |
_functor(line); |
|
| 351 |
++line_num; |
|
| 352 |
} |
|
| 353 |
} |
|
| 354 |
if (is) is.putback(c); |
|
| 355 |
|
|
| 339 |
char c; |
|
| 340 |
std::string line; |
|
| 341 |
while (is.get(c) && c != '@') {
|
|
| 342 |
if (c == '\n') {
|
|
| 343 |
++line_num; |
|
| 344 |
} else if (c == '#') {
|
|
| 345 |
getline(is, line); |
|
| 346 |
++line_num; |
|
| 347 |
} else if (!isWhiteSpace(c)) {
|
|
| 348 |
is.putback(c); |
|
| 349 |
getline(is, line); |
|
| 350 |
_functor(line); |
|
| 351 |
++line_num; |
|
| 352 |
} |
|
| 353 |
} |
|
| 354 |
if (is) is.putback(c); |
|
| 355 |
else if (is.eof()) is.clear(); |
|
| 356 | 356 |
} |
| 357 | 357 |
}; |
| 358 | 358 |
|
| 359 | 359 |
template <typename Functor> |
| 360 | 360 |
class StreamSection : public Section {
|
| 361 | 361 |
private: |
| 362 | 362 |
|
| 363 | 363 |
Functor _functor; |
| 364 | 364 |
|
| 365 | 365 |
public: |
| 366 |
|
|
| 366 |
|
|
| 367 | 367 |
StreamSection(const Functor& functor) : _functor(functor) {}
|
| 368 |
virtual ~StreamSection() {}
|
|
| 368 |
virtual ~StreamSection() {}
|
|
| 369 | 369 |
|
| 370 | 370 |
virtual void process(std::istream& is, int& line_num) {
|
| 371 |
_functor(is, line_num); |
|
| 372 |
char c; |
|
| 373 |
std::string line; |
|
| 374 |
while (is.get(c) && c != '@') {
|
|
| 375 |
if (c == '\n') {
|
|
| 376 |
++line_num; |
|
| 377 |
} else if (!isWhiteSpace(c)) {
|
|
| 378 |
getline(is, line); |
|
| 379 |
++line_num; |
|
| 380 |
} |
|
| 381 |
} |
|
| 382 |
if (is) is.putback(c); |
|
| 383 |
|
|
| 371 |
_functor(is, line_num); |
|
| 372 |
char c; |
|
| 373 |
std::string line; |
|
| 374 |
while (is.get(c) && c != '@') {
|
|
| 375 |
if (c == '\n') {
|
|
| 376 |
++line_num; |
|
| 377 |
} else if (!isWhiteSpace(c)) {
|
|
| 378 |
getline(is, line); |
|
| 379 |
++line_num; |
|
| 380 |
} |
|
| 381 |
} |
|
| 382 |
if (is) is.putback(c); |
|
| 383 |
else if (is.eof()) is.clear(); |
|
| 384 | 384 |
} |
| 385 | 385 |
}; |
| 386 |
|
|
| 386 |
|
|
| 387 | 387 |
} |
| 388 | 388 |
|
| 389 | 389 |
template <typename Digraph> |
| 390 | 390 |
class DigraphReader; |
| 391 | 391 |
|
| 392 | 392 |
template <typename Digraph> |
| 393 | 393 |
DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph); |
| 394 | 394 |
|
| 395 | 395 |
template <typename Digraph> |
| 396 | 396 |
DigraphReader<Digraph> digraphReader(const std::string& fn, Digraph& digraph); |
| 397 | 397 |
|
| 398 | 398 |
template <typename Digraph> |
| 399 | 399 |
DigraphReader<Digraph> digraphReader(const char *fn, Digraph& digraph); |
| 400 | 400 |
|
| 401 | 401 |
/// \ingroup lemon_io |
| 402 |
/// |
|
| 402 |
/// |
|
| 403 | 403 |
/// \brief \ref lgf-format "LGF" reader for directed graphs |
| 404 | 404 |
/// |
| 405 | 405 |
/// This utility reads an \ref lgf-format "LGF" file. |
| 406 | 406 |
/// |
| 407 | 407 |
/// The reading method does a batch processing. The user creates a |
| 408 | 408 |
/// reader object, then various reading rules can be added to the |
| 409 | 409 |
/// reader, and eventually the reading is executed with the \c run() |
| 410 | 410 |
/// member function. A map reading rule can be added to the reader |
| 411 | 411 |
/// with the \c nodeMap() or \c arcMap() members. An optional |
| 412 | 412 |
/// converter parameter can also be added as a standard functor |
| 413 | 413 |
/// converting from \c std::string to the value type of the map. If it |
| 414 | 414 |
/// is set, it will determine how the tokens in the file should be |
| 415 | 415 |
/// converted to the value type of the map. If the functor is not set, |
| 416 | 416 |
/// then a default conversion will be used. One map can be read into |
| 417 | 417 |
/// multiple map objects at the same time. The \c attribute(), \c |
| 418 | 418 |
/// node() and \c arc() functions are used to add attribute reading |
| ... | ... |
@@ -440,256 +440,256 @@ |
| 440 | 440 |
/// application of these functions is multipass reading, which is |
| 441 | 441 |
/// important if two \c \@arcs sections must be read from the |
| 442 | 442 |
/// file. In this case the first phase would read the node set and one |
| 443 | 443 |
/// of the arc sets, while the second phase would read the second arc |
| 444 | 444 |
/// set into an \e ArcSet class (\c SmartArcSet or \c ListArcSet). |
| 445 | 445 |
/// The previously read label node map should be passed to the \c |
| 446 | 446 |
/// useNodes() functions. Another application of multipass reading when |
| 447 | 447 |
/// paths are given as a node map or an arc map. It is impossible to read this in |
| 448 | 448 |
/// a single pass, because the arcs are not constructed when the node |
| 449 | 449 |
/// maps are read. |
| 450 | 450 |
template <typename _Digraph> |
| 451 | 451 |
class DigraphReader {
|
| 452 | 452 |
public: |
| 453 | 453 |
|
| 454 | 454 |
typedef _Digraph Digraph; |
| 455 | 455 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 456 |
|
|
| 456 |
|
|
| 457 | 457 |
private: |
| 458 | 458 |
|
| 459 | 459 |
|
| 460 | 460 |
std::istream* _is; |
| 461 | 461 |
bool local_is; |
| 462 | 462 |
|
| 463 | 463 |
Digraph& _digraph; |
| 464 | 464 |
|
| 465 | 465 |
std::string _nodes_caption; |
| 466 | 466 |
std::string _arcs_caption; |
| 467 | 467 |
std::string _attributes_caption; |
| 468 | 468 |
|
| 469 | 469 |
typedef std::map<std::string, Node> NodeIndex; |
| 470 | 470 |
NodeIndex _node_index; |
| 471 | 471 |
typedef std::map<std::string, Arc> ArcIndex; |
| 472 | 472 |
ArcIndex _arc_index; |
| 473 |
|
|
| 474 |
typedef std::vector<std::pair<std::string, |
|
| 475 |
_reader_bits::MapStorageBase<Node>*> > NodeMaps; |
|
| 476 |
NodeMaps _node_maps; |
|
| 473 |
|
|
| 474 |
typedef std::vector<std::pair<std::string, |
|
| 475 |
_reader_bits::MapStorageBase<Node>*> > NodeMaps; |
|
| 476 |
NodeMaps _node_maps; |
|
| 477 | 477 |
|
| 478 | 478 |
typedef std::vector<std::pair<std::string, |
| 479 | 479 |
_reader_bits::MapStorageBase<Arc>*> >ArcMaps; |
| 480 | 480 |
ArcMaps _arc_maps; |
| 481 | 481 |
|
| 482 |
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> |
|
| 482 |
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> |
|
| 483 | 483 |
Attributes; |
| 484 | 484 |
Attributes _attributes; |
| 485 | 485 |
|
| 486 | 486 |
bool _use_nodes; |
| 487 | 487 |
bool _use_arcs; |
| 488 | 488 |
|
| 489 | 489 |
bool _skip_nodes; |
| 490 | 490 |
bool _skip_arcs; |
| 491 | 491 |
|
| 492 | 492 |
int line_num; |
| 493 | 493 |
std::istringstream line; |
| 494 | 494 |
|
| 495 | 495 |
public: |
| 496 | 496 |
|
| 497 | 497 |
/// \brief Constructor |
| 498 | 498 |
/// |
| 499 | 499 |
/// Construct a directed graph reader, which reads from the given |
| 500 | 500 |
/// input stream. |
| 501 |
DigraphReader(std::istream& is, Digraph& digraph) |
|
| 501 |
DigraphReader(std::istream& is, Digraph& digraph) |
|
| 502 | 502 |
: _is(&is), local_is(false), _digraph(digraph), |
| 503 |
_use_nodes(false), _use_arcs(false), |
|
| 504 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 503 |
_use_nodes(false), _use_arcs(false), |
|
| 504 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 505 | 505 |
|
| 506 | 506 |
/// \brief Constructor |
| 507 | 507 |
/// |
| 508 | 508 |
/// Construct a directed graph reader, which reads from the given |
| 509 | 509 |
/// file. |
| 510 |
DigraphReader(const std::string& fn, Digraph& digraph) |
|
| 510 |
DigraphReader(const std::string& fn, Digraph& digraph) |
|
| 511 | 511 |
: _is(new std::ifstream(fn.c_str())), local_is(true), _digraph(digraph), |
| 512 |
_use_nodes(false), _use_arcs(false), |
|
| 513 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 514 |
|
|
| 512 |
_use_nodes(false), _use_arcs(false), |
|
| 513 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 514 |
|
|
| 515 | 515 |
/// \brief Constructor |
| 516 | 516 |
/// |
| 517 | 517 |
/// Construct a directed graph reader, which reads from the given |
| 518 | 518 |
/// file. |
| 519 |
DigraphReader(const char* fn, Digraph& digraph) |
|
| 519 |
DigraphReader(const char* fn, Digraph& digraph) |
|
| 520 | 520 |
: _is(new std::ifstream(fn)), local_is(true), _digraph(digraph), |
| 521 |
_use_nodes(false), _use_arcs(false), |
|
| 522 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 521 |
_use_nodes(false), _use_arcs(false), |
|
| 522 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 523 | 523 |
|
| 524 | 524 |
/// \brief Destructor |
| 525 | 525 |
~DigraphReader() {
|
| 526 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 527 |
it != _node_maps.end(); ++it) {
|
|
| 528 |
|
|
| 526 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 527 |
it != _node_maps.end(); ++it) {
|
|
| 528 |
delete it->second; |
|
| 529 | 529 |
} |
| 530 | 530 |
|
| 531 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 532 |
it != _arc_maps.end(); ++it) {
|
|
| 533 |
|
|
| 531 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 532 |
it != _arc_maps.end(); ++it) {
|
|
| 533 |
delete it->second; |
|
| 534 | 534 |
} |
| 535 | 535 |
|
| 536 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 537 |
it != _attributes.end(); ++it) {
|
|
| 538 |
|
|
| 536 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 537 |
it != _attributes.end(); ++it) {
|
|
| 538 |
delete it->second; |
|
| 539 | 539 |
} |
| 540 | 540 |
|
| 541 | 541 |
if (local_is) {
|
| 542 |
|
|
| 542 |
delete _is; |
|
| 543 | 543 |
} |
| 544 | 544 |
|
| 545 | 545 |
} |
| 546 | 546 |
|
| 547 | 547 |
private: |
| 548 | 548 |
|
| 549 |
friend DigraphReader<Digraph> digraphReader<>(std::istream& is, |
|
| 550 |
Digraph& digraph); |
|
| 551 |
friend DigraphReader<Digraph> digraphReader<>(const std::string& fn, |
|
| 552 |
Digraph& digraph); |
|
| 553 |
friend DigraphReader<Digraph> digraphReader<>(const char *fn, |
|
| 554 |
Digraph& digraph); |
|
| 555 |
|
|
| 556 |
DigraphReader(DigraphReader& other) |
|
| 549 |
friend DigraphReader<Digraph> digraphReader<>(std::istream& is, |
|
| 550 |
Digraph& digraph); |
|
| 551 |
friend DigraphReader<Digraph> digraphReader<>(const std::string& fn, |
|
| 552 |
Digraph& digraph); |
|
| 553 |
friend DigraphReader<Digraph> digraphReader<>(const char *fn, |
|
| 554 |
Digraph& digraph); |
|
| 555 |
|
|
| 556 |
DigraphReader(DigraphReader& other) |
|
| 557 | 557 |
: _is(other._is), local_is(other.local_is), _digraph(other._digraph), |
| 558 |
_use_nodes(other._use_nodes), _use_arcs(other._use_arcs), |
|
| 559 |
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
|
|
| 558 |
_use_nodes(other._use_nodes), _use_arcs(other._use_arcs), |
|
| 559 |
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
|
|
| 560 | 560 |
|
| 561 | 561 |
other._is = 0; |
| 562 | 562 |
other.local_is = false; |
| 563 |
|
|
| 563 |
|
|
| 564 | 564 |
_node_index.swap(other._node_index); |
| 565 | 565 |
_arc_index.swap(other._arc_index); |
| 566 | 566 |
|
| 567 | 567 |
_node_maps.swap(other._node_maps); |
| 568 | 568 |
_arc_maps.swap(other._arc_maps); |
| 569 | 569 |
_attributes.swap(other._attributes); |
| 570 | 570 |
|
| 571 | 571 |
_nodes_caption = other._nodes_caption; |
| 572 | 572 |
_arcs_caption = other._arcs_caption; |
| 573 | 573 |
_attributes_caption = other._attributes_caption; |
| 574 | 574 |
|
| 575 | 575 |
} |
| 576 | 576 |
|
| 577 | 577 |
DigraphReader& operator=(const DigraphReader&); |
| 578 | 578 |
|
| 579 | 579 |
public: |
| 580 | 580 |
|
| 581 | 581 |
/// \name Reading rules |
| 582 | 582 |
/// @{
|
| 583 |
|
|
| 583 |
|
|
| 584 | 584 |
/// \brief Node map reading rule |
| 585 | 585 |
/// |
| 586 | 586 |
/// Add a node map reading rule to the reader. |
| 587 | 587 |
template <typename Map> |
| 588 | 588 |
DigraphReader& nodeMap(const std::string& caption, Map& map) {
|
| 589 | 589 |
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
| 590 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 591 |
new _reader_bits::MapStorage<Node, Map>(map); |
|
| 590 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 591 |
new _reader_bits::MapStorage<Node, Map>(map); |
|
| 592 | 592 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 593 | 593 |
return *this; |
| 594 | 594 |
} |
| 595 | 595 |
|
| 596 | 596 |
/// \brief Node map reading rule |
| 597 | 597 |
/// |
| 598 | 598 |
/// Add a node map reading rule with specialized converter to the |
| 599 | 599 |
/// reader. |
| 600 | 600 |
template <typename Map, typename Converter> |
| 601 |
DigraphReader& nodeMap(const std::string& caption, Map& map, |
|
| 602 |
const Converter& converter = Converter()) {
|
|
| 601 |
DigraphReader& nodeMap(const std::string& caption, Map& map, |
|
| 602 |
const Converter& converter = Converter()) {
|
|
| 603 | 603 |
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
| 604 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 605 |
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 604 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 605 |
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 606 | 606 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 607 | 607 |
return *this; |
| 608 | 608 |
} |
| 609 | 609 |
|
| 610 | 610 |
/// \brief Arc map reading rule |
| 611 | 611 |
/// |
| 612 | 612 |
/// Add an arc map reading rule to the reader. |
| 613 | 613 |
template <typename Map> |
| 614 | 614 |
DigraphReader& arcMap(const std::string& caption, Map& map) {
|
| 615 | 615 |
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
| 616 |
_reader_bits::MapStorageBase<Arc>* storage = |
|
| 617 |
new _reader_bits::MapStorage<Arc, Map>(map); |
|
| 616 |
_reader_bits::MapStorageBase<Arc>* storage = |
|
| 617 |
new _reader_bits::MapStorage<Arc, Map>(map); |
|
| 618 | 618 |
_arc_maps.push_back(std::make_pair(caption, storage)); |
| 619 | 619 |
return *this; |
| 620 | 620 |
} |
| 621 | 621 |
|
| 622 | 622 |
/// \brief Arc map reading rule |
| 623 | 623 |
/// |
| 624 | 624 |
/// Add an arc map reading rule with specialized converter to the |
| 625 | 625 |
/// reader. |
| 626 | 626 |
template <typename Map, typename Converter> |
| 627 |
DigraphReader& arcMap(const std::string& caption, Map& map, |
|
| 628 |
const Converter& converter = Converter()) {
|
|
| 627 |
DigraphReader& arcMap(const std::string& caption, Map& map, |
|
| 628 |
const Converter& converter = Converter()) {
|
|
| 629 | 629 |
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
| 630 |
_reader_bits::MapStorageBase<Arc>* storage = |
|
| 631 |
new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter); |
|
| 630 |
_reader_bits::MapStorageBase<Arc>* storage = |
|
| 631 |
new _reader_bits::MapStorage<Arc, Map, Converter>(map, converter); |
|
| 632 | 632 |
_arc_maps.push_back(std::make_pair(caption, storage)); |
| 633 | 633 |
return *this; |
| 634 | 634 |
} |
| 635 | 635 |
|
| 636 | 636 |
/// \brief Attribute reading rule |
| 637 | 637 |
/// |
| 638 | 638 |
/// Add an attribute reading rule to the reader. |
| 639 | 639 |
template <typename Value> |
| 640 | 640 |
DigraphReader& attribute(const std::string& caption, Value& value) {
|
| 641 |
_reader_bits::ValueStorageBase* storage = |
|
| 642 |
new _reader_bits::ValueStorage<Value>(value); |
|
| 641 |
_reader_bits::ValueStorageBase* storage = |
|
| 642 |
new _reader_bits::ValueStorage<Value>(value); |
|
| 643 | 643 |
_attributes.insert(std::make_pair(caption, storage)); |
| 644 | 644 |
return *this; |
| 645 | 645 |
} |
| 646 | 646 |
|
| 647 | 647 |
/// \brief Attribute reading rule |
| 648 | 648 |
/// |
| 649 | 649 |
/// Add an attribute reading rule with specialized converter to the |
| 650 | 650 |
/// reader. |
| 651 | 651 |
template <typename Value, typename Converter> |
| 652 |
DigraphReader& attribute(const std::string& caption, Value& value, |
|
| 653 |
const Converter& converter = Converter()) {
|
|
| 654 |
_reader_bits::ValueStorageBase* storage = |
|
| 655 |
new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 652 |
DigraphReader& attribute(const std::string& caption, Value& value, |
|
| 653 |
const Converter& converter = Converter()) {
|
|
| 654 |
_reader_bits::ValueStorageBase* storage = |
|
| 655 |
new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 656 | 656 |
_attributes.insert(std::make_pair(caption, storage)); |
| 657 | 657 |
return *this; |
| 658 | 658 |
} |
| 659 | 659 |
|
| 660 | 660 |
/// \brief Node reading rule |
| 661 | 661 |
/// |
| 662 | 662 |
/// Add a node reading rule to reader. |
| 663 | 663 |
DigraphReader& node(const std::string& caption, Node& node) {
|
| 664 | 664 |
typedef _reader_bits::MapLookUpConverter<Node> Converter; |
| 665 | 665 |
Converter converter(_node_index); |
| 666 |
_reader_bits::ValueStorageBase* storage = |
|
| 667 |
new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 666 |
_reader_bits::ValueStorageBase* storage = |
|
| 667 |
new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 668 | 668 |
_attributes.insert(std::make_pair(caption, storage)); |
| 669 | 669 |
return *this; |
| 670 | 670 |
} |
| 671 | 671 |
|
| 672 | 672 |
/// \brief Arc reading rule |
| 673 | 673 |
/// |
| 674 | 674 |
/// Add an arc reading rule to reader. |
| 675 | 675 |
DigraphReader& arc(const std::string& caption, Arc& arc) {
|
| 676 | 676 |
typedef _reader_bits::MapLookUpConverter<Arc> Converter; |
| 677 | 677 |
Converter converter(_arc_index); |
| 678 |
_reader_bits::ValueStorageBase* storage = |
|
| 679 |
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 678 |
_reader_bits::ValueStorageBase* storage = |
|
| 679 |
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 680 | 680 |
_attributes.insert(std::make_pair(caption, storage)); |
| 681 | 681 |
return *this; |
| 682 | 682 |
} |
| 683 | 683 |
|
| 684 | 684 |
/// @} |
| 685 | 685 |
|
| 686 | 686 |
/// \name Select section by name |
| 687 | 687 |
/// @{
|
| 688 | 688 |
|
| 689 | 689 |
/// \brief Set \c \@nodes section to be read |
| 690 | 690 |
/// |
| 691 | 691 |
/// Set \c \@nodes section to be read |
| 692 | 692 |
DigraphReader& nodes(const std::string& caption) {
|
| 693 | 693 |
_nodes_caption = caption; |
| 694 | 694 |
return *this; |
| 695 | 695 |
} |
| ... | ... |
@@ -709,814 +709,814 @@ |
| 709 | 709 |
_attributes_caption = caption; |
| 710 | 710 |
return *this; |
| 711 | 711 |
} |
| 712 | 712 |
|
| 713 | 713 |
/// @} |
| 714 | 714 |
|
| 715 | 715 |
/// \name Using previously constructed node or arc set |
| 716 | 716 |
/// @{
|
| 717 | 717 |
|
| 718 | 718 |
/// \brief Use previously constructed node set |
| 719 | 719 |
/// |
| 720 | 720 |
/// Use previously constructed node set, and specify the node |
| 721 | 721 |
/// label map. |
| 722 | 722 |
template <typename Map> |
| 723 | 723 |
DigraphReader& useNodes(const Map& map) {
|
| 724 | 724 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 725 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 725 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 726 | 726 |
_use_nodes = true; |
| 727 | 727 |
_writer_bits::DefaultConverter<typename Map::Value> converter; |
| 728 | 728 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
| 729 |
|
|
| 729 |
_node_index.insert(std::make_pair(converter(map[n]), n)); |
|
| 730 | 730 |
} |
| 731 | 731 |
return *this; |
| 732 | 732 |
} |
| 733 | 733 |
|
| 734 | 734 |
/// \brief Use previously constructed node set |
| 735 | 735 |
/// |
| 736 | 736 |
/// Use previously constructed node set, and specify the node |
| 737 | 737 |
/// label map and a functor which converts the label map values to |
| 738 | 738 |
/// \c std::string. |
| 739 | 739 |
template <typename Map, typename Converter> |
| 740 |
DigraphReader& useNodes(const Map& map, |
|
| 741 |
const Converter& converter = Converter()) {
|
|
| 740 |
DigraphReader& useNodes(const Map& map, |
|
| 741 |
const Converter& converter = Converter()) {
|
|
| 742 | 742 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 743 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 743 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 744 | 744 |
_use_nodes = true; |
| 745 | 745 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
| 746 |
|
|
| 746 |
_node_index.insert(std::make_pair(converter(map[n]), n)); |
|
| 747 | 747 |
} |
| 748 | 748 |
return *this; |
| 749 | 749 |
} |
| 750 | 750 |
|
| 751 | 751 |
/// \brief Use previously constructed arc set |
| 752 | 752 |
/// |
| 753 | 753 |
/// Use previously constructed arc set, and specify the arc |
| 754 | 754 |
/// label map. |
| 755 | 755 |
template <typename Map> |
| 756 | 756 |
DigraphReader& useArcs(const Map& map) {
|
| 757 | 757 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 758 | 758 |
LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); |
| 759 | 759 |
_use_arcs = true; |
| 760 | 760 |
_writer_bits::DefaultConverter<typename Map::Value> converter; |
| 761 | 761 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
| 762 |
|
|
| 762 |
_arc_index.insert(std::make_pair(converter(map[a]), a)); |
|
| 763 | 763 |
} |
| 764 | 764 |
return *this; |
| 765 | 765 |
} |
| 766 | 766 |
|
| 767 | 767 |
/// \brief Use previously constructed arc set |
| 768 | 768 |
/// |
| 769 | 769 |
/// Use previously constructed arc set, and specify the arc |
| 770 | 770 |
/// label map and a functor which converts the label map values to |
| 771 | 771 |
/// \c std::string. |
| 772 | 772 |
template <typename Map, typename Converter> |
| 773 |
DigraphReader& useArcs(const Map& map, |
|
| 774 |
const Converter& converter = Converter()) {
|
|
| 773 |
DigraphReader& useArcs(const Map& map, |
|
| 774 |
const Converter& converter = Converter()) {
|
|
| 775 | 775 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 776 |
LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); |
|
| 776 |
LEMON_ASSERT(!_use_arcs, "Multiple usage of useArcs() member"); |
|
| 777 | 777 |
_use_arcs = true; |
| 778 | 778 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
| 779 |
|
|
| 779 |
_arc_index.insert(std::make_pair(converter(map[a]), a)); |
|
| 780 | 780 |
} |
| 781 | 781 |
return *this; |
| 782 | 782 |
} |
| 783 | 783 |
|
| 784 | 784 |
/// \brief Skips the reading of node section |
| 785 | 785 |
/// |
| 786 | 786 |
/// Omit the reading of the node section. This implies that each node |
| 787 | 787 |
/// map reading rule will be abandoned, and the nodes of the graph |
| 788 | 788 |
/// will not be constructed, which usually cause that the arc set |
| 789 | 789 |
/// could not be read due to lack of node name resolving. |
| 790 | 790 |
/// Therefore \c skipArcs() function should also be used, or |
| 791 | 791 |
/// \c useNodes() should be used to specify the label of the nodes. |
| 792 | 792 |
DigraphReader& skipNodes() {
|
| 793 |
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); |
|
| 793 |
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); |
|
| 794 | 794 |
_skip_nodes = true; |
| 795 | 795 |
return *this; |
| 796 | 796 |
} |
| 797 | 797 |
|
| 798 | 798 |
/// \brief Skips the reading of arc section |
| 799 | 799 |
/// |
| 800 | 800 |
/// Omit the reading of the arc section. This implies that each arc |
| 801 | 801 |
/// map reading rule will be abandoned, and the arcs of the graph |
| 802 | 802 |
/// will not be constructed. |
| 803 | 803 |
DigraphReader& skipArcs() {
|
| 804 |
LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); |
|
| 804 |
LEMON_ASSERT(!_skip_arcs, "Skip arcs already set"); |
|
| 805 | 805 |
_skip_arcs = true; |
| 806 | 806 |
return *this; |
| 807 | 807 |
} |
| 808 | 808 |
|
| 809 | 809 |
/// @} |
| 810 | 810 |
|
| 811 | 811 |
private: |
| 812 | 812 |
|
| 813 | 813 |
bool readLine() {
|
| 814 | 814 |
std::string str; |
| 815 | 815 |
while(++line_num, std::getline(*_is, str)) {
|
| 816 |
line.clear(); line.str(str); |
|
| 817 |
char c; |
|
| 818 |
if (line >> std::ws >> c && c != '#') {
|
|
| 819 |
line.putback(c); |
|
| 820 |
return true; |
|
| 821 |
} |
|
| 816 |
line.clear(); line.str(str); |
|
| 817 |
char c; |
|
| 818 |
if (line >> std::ws >> c && c != '#') {
|
|
| 819 |
line.putback(c); |
|
| 820 |
return true; |
|
| 821 |
} |
|
| 822 | 822 |
} |
| 823 | 823 |
return false; |
| 824 | 824 |
} |
| 825 | 825 |
|
| 826 | 826 |
bool readSuccess() {
|
| 827 | 827 |
return static_cast<bool>(*_is); |
| 828 | 828 |
} |
| 829 |
|
|
| 829 |
|
|
| 830 | 830 |
void skipSection() {
|
| 831 | 831 |
char c; |
| 832 | 832 |
while (readSuccess() && line >> c && c != '@') {
|
| 833 |
|
|
| 833 |
readLine(); |
|
| 834 | 834 |
} |
| 835 | 835 |
line.putback(c); |
| 836 | 836 |
} |
| 837 | 837 |
|
| 838 | 838 |
void readNodes() {
|
| 839 | 839 |
|
| 840 | 840 |
std::vector<int> map_index(_node_maps.size()); |
| 841 | 841 |
int map_num, label_index; |
| 842 | 842 |
|
| 843 | 843 |
char c; |
| 844 | 844 |
if (!readLine() || !(line >> c) || c == '@') {
|
| 845 |
if (readSuccess() && line) line.putback(c); |
|
| 846 |
if (!_node_maps.empty()) |
|
| 847 |
throw DataFormatError("Cannot find map names");
|
|
| 848 |
return; |
|
| 845 |
if (readSuccess() && line) line.putback(c); |
|
| 846 |
if (!_node_maps.empty()) |
|
| 847 |
throw DataFormatError("Cannot find map names");
|
|
| 848 |
return; |
|
| 849 | 849 |
} |
| 850 | 850 |
line.putback(c); |
| 851 | 851 |
|
| 852 | 852 |
{
|
| 853 |
std::map<std::string, int> maps; |
|
| 854 |
|
|
| 855 |
std::string map; |
|
| 856 |
int index = 0; |
|
| 857 |
while (_reader_bits::readToken(line, map)) {
|
|
| 858 |
if (maps.find(map) != maps.end()) {
|
|
| 859 |
std::ostringstream msg; |
|
| 860 |
msg << "Multiple occurence of node map: " << map; |
|
| 861 |
throw DataFormatError(msg.str().c_str()); |
|
| 862 |
} |
|
| 863 |
maps.insert(std::make_pair(map, index)); |
|
| 864 |
++index; |
|
| 865 |
} |
|
| 866 |
|
|
| 867 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 868 |
std::map<std::string, int>::iterator jt = |
|
| 869 |
maps.find(_node_maps[i].first); |
|
| 870 |
if (jt == maps.end()) {
|
|
| 871 |
std::ostringstream msg; |
|
| 872 |
msg << "Map not found in file: " << _node_maps[i].first; |
|
| 873 |
throw DataFormatError(msg.str().c_str()); |
|
| 874 |
} |
|
| 875 |
map_index[i] = jt->second; |
|
| 876 |
} |
|
| 877 |
|
|
| 878 |
{
|
|
| 879 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 880 |
if (jt != maps.end()) {
|
|
| 881 |
label_index = jt->second; |
|
| 882 |
} else {
|
|
| 883 |
label_index = -1; |
|
| 884 |
} |
|
| 885 |
} |
|
| 886 |
map_num = maps.size(); |
|
| 853 |
std::map<std::string, int> maps; |
|
| 854 |
|
|
| 855 |
std::string map; |
|
| 856 |
int index = 0; |
|
| 857 |
while (_reader_bits::readToken(line, map)) {
|
|
| 858 |
if (maps.find(map) != maps.end()) {
|
|
| 859 |
std::ostringstream msg; |
|
| 860 |
msg << "Multiple occurence of node map: " << map; |
|
| 861 |
throw DataFormatError(msg.str().c_str()); |
|
| 862 |
} |
|
| 863 |
maps.insert(std::make_pair(map, index)); |
|
| 864 |
++index; |
|
| 865 |
} |
|
| 866 |
|
|
| 867 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 868 |
std::map<std::string, int>::iterator jt = |
|
| 869 |
maps.find(_node_maps[i].first); |
|
| 870 |
if (jt == maps.end()) {
|
|
| 871 |
std::ostringstream msg; |
|
| 872 |
msg << "Map not found in file: " << _node_maps[i].first; |
|
| 873 |
throw DataFormatError(msg.str().c_str()); |
|
| 874 |
} |
|
| 875 |
map_index[i] = jt->second; |
|
| 876 |
} |
|
| 877 |
|
|
| 878 |
{
|
|
| 879 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 880 |
if (jt != maps.end()) {
|
|
| 881 |
label_index = jt->second; |
|
| 882 |
} else {
|
|
| 883 |
label_index = -1; |
|
| 884 |
} |
|
| 885 |
} |
|
| 886 |
map_num = maps.size(); |
|
| 887 | 887 |
} |
| 888 | 888 |
|
| 889 | 889 |
while (readLine() && line >> c && c != '@') {
|
| 890 |
line.putback(c); |
|
| 891 |
|
|
| 892 |
std::vector<std::string> tokens(map_num); |
|
| 893 |
for (int i = 0; i < map_num; ++i) {
|
|
| 894 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 895 |
std::ostringstream msg; |
|
| 896 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 897 |
throw DataFormatError(msg.str().c_str()); |
|
| 898 |
} |
|
| 899 |
} |
|
| 900 |
if (line >> std::ws >> c) |
|
| 901 |
throw DataFormatError("Extra character on the end of line");
|
|
| 902 |
|
|
| 903 |
Node n; |
|
| 904 |
if (!_use_nodes) {
|
|
| 905 |
n = _digraph.addNode(); |
|
| 906 |
if (label_index != -1) |
|
| 907 |
_node_index.insert(std::make_pair(tokens[label_index], n)); |
|
| 908 |
} else {
|
|
| 909 |
if (label_index == -1) |
|
| 910 |
throw DataFormatError("Label map not found in file");
|
|
| 911 |
typename std::map<std::string, Node>::iterator it = |
|
| 912 |
_node_index.find(tokens[label_index]); |
|
| 913 |
if (it == _node_index.end()) {
|
|
| 914 |
std::ostringstream msg; |
|
| 915 |
msg << "Node with label not found: " << tokens[label_index]; |
|
| 916 |
throw DataFormatError(msg.str().c_str()); |
|
| 917 |
} |
|
| 918 |
n = it->second; |
|
| 919 |
} |
|
| 920 |
|
|
| 921 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 922 |
_node_maps[i].second->set(n, tokens[map_index[i]]); |
|
| 923 |
} |
|
| 890 |
line.putback(c); |
|
| 891 |
|
|
| 892 |
std::vector<std::string> tokens(map_num); |
|
| 893 |
for (int i = 0; i < map_num; ++i) {
|
|
| 894 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 895 |
std::ostringstream msg; |
|
| 896 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 897 |
throw DataFormatError(msg.str().c_str()); |
|
| 898 |
} |
|
| 899 |
} |
|
| 900 |
if (line >> std::ws >> c) |
|
| 901 |
throw DataFormatError("Extra character on the end of line");
|
|
| 902 |
|
|
| 903 |
Node n; |
|
| 904 |
if (!_use_nodes) {
|
|
| 905 |
n = _digraph.addNode(); |
|
| 906 |
if (label_index != -1) |
|
| 907 |
_node_index.insert(std::make_pair(tokens[label_index], n)); |
|
| 908 |
} else {
|
|
| 909 |
if (label_index == -1) |
|
| 910 |
throw DataFormatError("Label map not found in file");
|
|
| 911 |
typename std::map<std::string, Node>::iterator it = |
|
| 912 |
_node_index.find(tokens[label_index]); |
|
| 913 |
if (it == _node_index.end()) {
|
|
| 914 |
std::ostringstream msg; |
|
| 915 |
msg << "Node with label not found: " << tokens[label_index]; |
|
| 916 |
throw DataFormatError(msg.str().c_str()); |
|
| 917 |
} |
|
| 918 |
n = it->second; |
|
| 919 |
} |
|
| 920 |
|
|
| 921 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 922 |
_node_maps[i].second->set(n, tokens[map_index[i]]); |
|
| 923 |
} |
|
| 924 | 924 |
|
| 925 | 925 |
} |
| 926 | 926 |
if (readSuccess()) {
|
| 927 |
|
|
| 927 |
line.putback(c); |
|
| 928 | 928 |
} |
| 929 | 929 |
} |
| 930 | 930 |
|
| 931 | 931 |
void readArcs() {
|
| 932 | 932 |
|
| 933 | 933 |
std::vector<int> map_index(_arc_maps.size()); |
| 934 | 934 |
int map_num, label_index; |
| 935 | 935 |
|
| 936 | 936 |
char c; |
| 937 | 937 |
if (!readLine() || !(line >> c) || c == '@') {
|
| 938 |
if (readSuccess() && line) line.putback(c); |
|
| 939 |
if (!_arc_maps.empty()) |
|
| 940 |
throw DataFormatError("Cannot find map names");
|
|
| 941 |
return; |
|
| 938 |
if (readSuccess() && line) line.putback(c); |
|
| 939 |
if (!_arc_maps.empty()) |
|
| 940 |
throw DataFormatError("Cannot find map names");
|
|
| 941 |
return; |
|
| 942 | 942 |
} |
| 943 | 943 |
line.putback(c); |
| 944 |
|
|
| 944 |
|
|
| 945 | 945 |
{
|
| 946 |
std::map<std::string, int> maps; |
|
| 947 |
|
|
| 948 |
std::string map; |
|
| 949 |
int index = 0; |
|
| 950 |
while (_reader_bits::readToken(line, map)) {
|
|
| 951 |
if (maps.find(map) != maps.end()) {
|
|
| 952 |
std::ostringstream msg; |
|
| 953 |
msg << "Multiple occurence of arc map: " << map; |
|
| 954 |
throw DataFormatError(msg.str().c_str()); |
|
| 955 |
} |
|
| 956 |
maps.insert(std::make_pair(map, index)); |
|
| 957 |
++index; |
|
| 958 |
} |
|
| 959 |
|
|
| 960 |
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
| 961 |
std::map<std::string, int>::iterator jt = |
|
| 962 |
maps.find(_arc_maps[i].first); |
|
| 963 |
if (jt == maps.end()) {
|
|
| 964 |
std::ostringstream msg; |
|
| 965 |
msg << "Map not found in file: " << _arc_maps[i].first; |
|
| 966 |
throw DataFormatError(msg.str().c_str()); |
|
| 967 |
} |
|
| 968 |
map_index[i] = jt->second; |
|
| 969 |
} |
|
| 970 |
|
|
| 971 |
{
|
|
| 972 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 973 |
if (jt != maps.end()) {
|
|
| 974 |
label_index = jt->second; |
|
| 975 |
} else {
|
|
| 976 |
label_index = -1; |
|
| 977 |
} |
|
| 978 |
} |
|
| 979 |
map_num = maps.size(); |
|
| 946 |
std::map<std::string, int> maps; |
|
| 947 |
|
|
| 948 |
std::string map; |
|
| 949 |
int index = 0; |
|
| 950 |
while (_reader_bits::readToken(line, map)) {
|
|
| 951 |
if (maps.find(map) != maps.end()) {
|
|
| 952 |
std::ostringstream msg; |
|
| 953 |
msg << "Multiple occurence of arc map: " << map; |
|
| 954 |
throw DataFormatError(msg.str().c_str()); |
|
| 955 |
} |
|
| 956 |
maps.insert(std::make_pair(map, index)); |
|
| 957 |
++index; |
|
| 958 |
} |
|
| 959 |
|
|
| 960 |
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
| 961 |
std::map<std::string, int>::iterator jt = |
|
| 962 |
maps.find(_arc_maps[i].first); |
|
| 963 |
if (jt == maps.end()) {
|
|
| 964 |
std::ostringstream msg; |
|
| 965 |
msg << "Map not found in file: " << _arc_maps[i].first; |
|
| 966 |
throw DataFormatError(msg.str().c_str()); |
|
| 967 |
} |
|
| 968 |
map_index[i] = jt->second; |
|
| 969 |
} |
|
| 970 |
|
|
| 971 |
{
|
|
| 972 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 973 |
if (jt != maps.end()) {
|
|
| 974 |
label_index = jt->second; |
|
| 975 |
} else {
|
|
| 976 |
label_index = -1; |
|
| 977 |
} |
|
| 978 |
} |
|
| 979 |
map_num = maps.size(); |
|
| 980 | 980 |
} |
| 981 | 981 |
|
| 982 | 982 |
while (readLine() && line >> c && c != '@') {
|
| 983 |
line.putback(c); |
|
| 984 |
|
|
| 985 |
std::string source_token; |
|
| 986 |
std::string target_token; |
|
| 987 |
|
|
| 988 |
if (!_reader_bits::readToken(line, source_token)) |
|
| 989 |
throw DataFormatError("Source not found");
|
|
| 990 |
|
|
| 991 |
if (!_reader_bits::readToken(line, target_token)) |
|
| 992 |
throw DataFormatError("Target not found");
|
|
| 993 |
|
|
| 994 |
std::vector<std::string> tokens(map_num); |
|
| 995 |
for (int i = 0; i < map_num; ++i) {
|
|
| 996 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 997 |
std::ostringstream msg; |
|
| 998 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 999 |
throw DataFormatError(msg.str().c_str()); |
|
| 1000 |
} |
|
| 1001 |
} |
|
| 1002 |
if (line >> std::ws >> c) |
|
| 1003 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1004 |
|
|
| 1005 |
Arc a; |
|
| 1006 |
if (!_use_arcs) {
|
|
| 983 |
line.putback(c); |
|
| 984 |
|
|
| 985 |
std::string source_token; |
|
| 986 |
std::string target_token; |
|
| 987 |
|
|
| 988 |
if (!_reader_bits::readToken(line, source_token)) |
|
| 989 |
throw DataFormatError("Source not found");
|
|
| 990 |
|
|
| 991 |
if (!_reader_bits::readToken(line, target_token)) |
|
| 992 |
throw DataFormatError("Target not found");
|
|
| 993 |
|
|
| 994 |
std::vector<std::string> tokens(map_num); |
|
| 995 |
for (int i = 0; i < map_num; ++i) {
|
|
| 996 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 997 |
std::ostringstream msg; |
|
| 998 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 999 |
throw DataFormatError(msg.str().c_str()); |
|
| 1000 |
} |
|
| 1001 |
} |
|
| 1002 |
if (line >> std::ws >> c) |
|
| 1003 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1004 |
|
|
| 1005 |
Arc a; |
|
| 1006 |
if (!_use_arcs) {
|
|
| 1007 | 1007 |
|
| 1008 | 1008 |
typename NodeIndex::iterator it; |
| 1009 |
|
|
| 1009 |
|
|
| 1010 | 1010 |
it = _node_index.find(source_token); |
| 1011 | 1011 |
if (it == _node_index.end()) {
|
| 1012 | 1012 |
std::ostringstream msg; |
| 1013 | 1013 |
msg << "Item not found: " << source_token; |
| 1014 | 1014 |
throw DataFormatError(msg.str().c_str()); |
| 1015 | 1015 |
} |
| 1016 | 1016 |
Node source = it->second; |
| 1017 | 1017 |
|
| 1018 | 1018 |
it = _node_index.find(target_token); |
| 1019 |
if (it == _node_index.end()) {
|
|
| 1020 |
std::ostringstream msg; |
|
| 1019 |
if (it == _node_index.end()) {
|
|
| 1020 |
std::ostringstream msg; |
|
| 1021 | 1021 |
msg << "Item not found: " << target_token; |
| 1022 | 1022 |
throw DataFormatError(msg.str().c_str()); |
| 1023 |
} |
|
| 1024 |
Node target = it->second; |
|
| 1025 |
|
|
| 1026 |
a = _digraph.addArc(source, target); |
|
| 1027 |
if (label_index != -1) |
|
| 1028 |
_arc_index.insert(std::make_pair(tokens[label_index], a)); |
|
| 1029 |
} else {
|
|
| 1030 |
if (label_index == -1) |
|
| 1031 |
throw DataFormatError("Label map not found in file");
|
|
| 1032 |
typename std::map<std::string, Arc>::iterator it = |
|
| 1033 |
_arc_index.find(tokens[label_index]); |
|
| 1034 |
if (it == _arc_index.end()) {
|
|
| 1035 |
std::ostringstream msg; |
|
| 1036 |
msg << "Arc with label not found: " << tokens[label_index]; |
|
| 1037 |
throw DataFormatError(msg.str().c_str()); |
|
| 1038 |
} |
|
| 1039 |
a = it->second; |
|
| 1040 |
} |
|
| 1041 |
|
|
| 1042 |
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
| 1043 |
_arc_maps[i].second->set(a, tokens[map_index[i]]); |
|
| 1044 |
} |
|
| 1023 |
} |
|
| 1024 |
Node target = it->second; |
|
| 1025 |
|
|
| 1026 |
a = _digraph.addArc(source, target); |
|
| 1027 |
if (label_index != -1) |
|
| 1028 |
_arc_index.insert(std::make_pair(tokens[label_index], a)); |
|
| 1029 |
} else {
|
|
| 1030 |
if (label_index == -1) |
|
| 1031 |
throw DataFormatError("Label map not found in file");
|
|
| 1032 |
typename std::map<std::string, Arc>::iterator it = |
|
| 1033 |
_arc_index.find(tokens[label_index]); |
|
| 1034 |
if (it == _arc_index.end()) {
|
|
| 1035 |
std::ostringstream msg; |
|
| 1036 |
msg << "Arc with label not found: " << tokens[label_index]; |
|
| 1037 |
throw DataFormatError(msg.str().c_str()); |
|
| 1038 |
} |
|
| 1039 |
a = it->second; |
|
| 1040 |
} |
|
| 1041 |
|
|
| 1042 |
for (int i = 0; i < static_cast<int>(_arc_maps.size()); ++i) {
|
|
| 1043 |
_arc_maps[i].second->set(a, tokens[map_index[i]]); |
|
| 1044 |
} |
|
| 1045 | 1045 |
|
| 1046 | 1046 |
} |
| 1047 | 1047 |
if (readSuccess()) {
|
| 1048 |
|
|
| 1048 |
line.putback(c); |
|
| 1049 | 1049 |
} |
| 1050 | 1050 |
} |
| 1051 | 1051 |
|
| 1052 | 1052 |
void readAttributes() {
|
| 1053 | 1053 |
|
| 1054 | 1054 |
std::set<std::string> read_attr; |
| 1055 | 1055 |
|
| 1056 | 1056 |
char c; |
| 1057 | 1057 |
while (readLine() && line >> c && c != '@') {
|
| 1058 |
line.putback(c); |
|
| 1059 |
|
|
| 1060 |
std::string attr, token; |
|
| 1061 |
if (!_reader_bits::readToken(line, attr)) |
|
| 1062 |
throw DataFormatError("Attribute name not found");
|
|
| 1063 |
if (!_reader_bits::readToken(line, token)) |
|
| 1064 |
throw DataFormatError("Attribute value not found");
|
|
| 1065 |
if (line >> c) |
|
| 1066 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1067 |
|
|
| 1068 |
{
|
|
| 1069 |
std::set<std::string>::iterator it = read_attr.find(attr); |
|
| 1070 |
if (it != read_attr.end()) {
|
|
| 1071 |
std::ostringstream msg; |
|
| 1072 |
msg << "Multiple occurence of attribute " << attr; |
|
| 1073 |
throw DataFormatError(msg.str().c_str()); |
|
| 1074 |
} |
|
| 1075 |
read_attr.insert(attr); |
|
| 1076 |
} |
|
| 1077 |
|
|
| 1078 |
{
|
|
| 1079 |
typename Attributes::iterator it = _attributes.lower_bound(attr); |
|
| 1080 |
while (it != _attributes.end() && it->first == attr) {
|
|
| 1081 |
it->second->set(token); |
|
| 1082 |
++it; |
|
| 1083 |
} |
|
| 1084 |
|
|
| 1058 |
line.putback(c); |
|
| 1059 |
|
|
| 1060 |
std::string attr, token; |
|
| 1061 |
if (!_reader_bits::readToken(line, attr)) |
|
| 1062 |
throw DataFormatError("Attribute name not found");
|
|
| 1063 |
if (!_reader_bits::readToken(line, token)) |
|
| 1064 |
throw DataFormatError("Attribute value not found");
|
|
| 1065 |
if (line >> c) |
|
| 1066 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1067 |
|
|
| 1068 |
{
|
|
| 1069 |
std::set<std::string>::iterator it = read_attr.find(attr); |
|
| 1070 |
if (it != read_attr.end()) {
|
|
| 1071 |
std::ostringstream msg; |
|
| 1072 |
msg << "Multiple occurence of attribute " << attr; |
|
| 1073 |
throw DataFormatError(msg.str().c_str()); |
|
| 1074 |
} |
|
| 1075 |
read_attr.insert(attr); |
|
| 1076 |
} |
|
| 1077 |
|
|
| 1078 |
{
|
|
| 1079 |
typename Attributes::iterator it = _attributes.lower_bound(attr); |
|
| 1080 |
while (it != _attributes.end() && it->first == attr) {
|
|
| 1081 |
it->second->set(token); |
|
| 1082 |
++it; |
|
| 1083 |
} |
|
| 1084 |
} |
|
| 1085 | 1085 |
|
| 1086 | 1086 |
} |
| 1087 | 1087 |
if (readSuccess()) {
|
| 1088 |
|
|
| 1088 |
line.putback(c); |
|
| 1089 | 1089 |
} |
| 1090 | 1090 |
for (typename Attributes::iterator it = _attributes.begin(); |
| 1091 |
it != _attributes.end(); ++it) {
|
|
| 1092 |
if (read_attr.find(it->first) == read_attr.end()) {
|
|
| 1093 |
std::ostringstream msg; |
|
| 1094 |
msg << "Attribute not found in file: " << it->first; |
|
| 1095 |
throw DataFormatError(msg.str().c_str()); |
|
| 1096 |
} |
|
| 1091 |
it != _attributes.end(); ++it) {
|
|
| 1092 |
if (read_attr.find(it->first) == read_attr.end()) {
|
|
| 1093 |
std::ostringstream msg; |
|
| 1094 |
msg << "Attribute not found in file: " << it->first; |
|
| 1095 |
throw DataFormatError(msg.str().c_str()); |
|
| 1096 |
} |
|
| 1097 | 1097 |
} |
| 1098 | 1098 |
} |
| 1099 | 1099 |
|
| 1100 | 1100 |
public: |
| 1101 | 1101 |
|
| 1102 |
/// \name Execution of the reader |
|
| 1102 |
/// \name Execution of the reader |
|
| 1103 | 1103 |
/// @{
|
| 1104 | 1104 |
|
| 1105 | 1105 |
/// \brief Start the batch processing |
| 1106 | 1106 |
/// |
| 1107 | 1107 |
/// This function starts the batch processing |
| 1108 | 1108 |
void run() {
|
| 1109 | 1109 |
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
| 1110 | 1110 |
if (!*_is) {
|
| 1111 |
|
|
| 1111 |
throw DataFormatError("Cannot find file");
|
|
| 1112 | 1112 |
} |
| 1113 |
|
|
| 1113 |
|
|
| 1114 | 1114 |
bool nodes_done = _skip_nodes; |
| 1115 | 1115 |
bool arcs_done = _skip_arcs; |
| 1116 | 1116 |
bool attributes_done = false; |
| 1117 | 1117 |
|
| 1118 |
line_num = 0; |
|
| 1118 |
line_num = 0; |
|
| 1119 | 1119 |
readLine(); |
| 1120 | 1120 |
skipSection(); |
| 1121 | 1121 |
|
| 1122 | 1122 |
while (readSuccess()) {
|
| 1123 |
try {
|
|
| 1124 |
char c; |
|
| 1125 |
std::string section, caption; |
|
| 1126 |
line >> c; |
|
| 1127 |
_reader_bits::readToken(line, section); |
|
| 1128 |
_reader_bits::readToken(line, caption); |
|
| 1129 |
|
|
| 1130 |
if (line >> c) |
|
| 1131 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1132 |
|
|
| 1133 |
if (section == "nodes" && !nodes_done) {
|
|
| 1134 |
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
| 1135 |
readNodes(); |
|
| 1136 |
nodes_done = true; |
|
| 1137 |
} |
|
| 1138 |
} else if ((section == "arcs" || section == "edges") && |
|
| 1139 |
!arcs_done) {
|
|
| 1140 |
if (_arcs_caption.empty() || _arcs_caption == caption) {
|
|
| 1141 |
readArcs(); |
|
| 1142 |
arcs_done = true; |
|
| 1143 |
} |
|
| 1144 |
} else if (section == "attributes" && !attributes_done) {
|
|
| 1145 |
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
| 1146 |
readAttributes(); |
|
| 1147 |
attributes_done = true; |
|
| 1148 |
} |
|
| 1149 |
} else {
|
|
| 1150 |
readLine(); |
|
| 1151 |
skipSection(); |
|
| 1152 |
} |
|
| 1153 |
} catch (DataFormatError& error) {
|
|
| 1154 |
error.line(line_num); |
|
| 1155 |
throw; |
|
| 1156 |
} |
|
| 1123 |
try {
|
|
| 1124 |
char c; |
|
| 1125 |
std::string section, caption; |
|
| 1126 |
line >> c; |
|
| 1127 |
_reader_bits::readToken(line, section); |
|
| 1128 |
_reader_bits::readToken(line, caption); |
|
| 1129 |
|
|
| 1130 |
if (line >> c) |
|
| 1131 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1132 |
|
|
| 1133 |
if (section == "nodes" && !nodes_done) {
|
|
| 1134 |
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
| 1135 |
readNodes(); |
|
| 1136 |
nodes_done = true; |
|
| 1137 |
} |
|
| 1138 |
} else if ((section == "arcs" || section == "edges") && |
|
| 1139 |
!arcs_done) {
|
|
| 1140 |
if (_arcs_caption.empty() || _arcs_caption == caption) {
|
|
| 1141 |
readArcs(); |
|
| 1142 |
arcs_done = true; |
|
| 1143 |
} |
|
| 1144 |
} else if (section == "attributes" && !attributes_done) {
|
|
| 1145 |
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
| 1146 |
readAttributes(); |
|
| 1147 |
attributes_done = true; |
|
| 1148 |
} |
|
| 1149 |
} else {
|
|
| 1150 |
readLine(); |
|
| 1151 |
skipSection(); |
|
| 1152 |
} |
|
| 1153 |
} catch (DataFormatError& error) {
|
|
| 1154 |
error.line(line_num); |
|
| 1155 |
throw; |
|
| 1156 |
} |
|
| 1157 | 1157 |
} |
| 1158 | 1158 |
|
| 1159 | 1159 |
if (!nodes_done) {
|
| 1160 |
|
|
| 1160 |
throw DataFormatError("Section @nodes not found");
|
|
| 1161 | 1161 |
} |
| 1162 | 1162 |
|
| 1163 | 1163 |
if (!arcs_done) {
|
| 1164 |
|
|
| 1164 |
throw DataFormatError("Section @arcs not found");
|
|
| 1165 | 1165 |
} |
| 1166 | 1166 |
|
| 1167 | 1167 |
if (!attributes_done && !_attributes.empty()) {
|
| 1168 |
|
|
| 1168 |
throw DataFormatError("Section @attributes not found");
|
|
| 1169 | 1169 |
} |
| 1170 | 1170 |
|
| 1171 | 1171 |
} |
| 1172 | 1172 |
|
| 1173 | 1173 |
/// @} |
| 1174 |
|
|
| 1174 |
|
|
| 1175 | 1175 |
}; |
| 1176 | 1176 |
|
| 1177 | 1177 |
/// \brief Return a \ref DigraphReader class |
| 1178 |
/// |
|
| 1178 |
/// |
|
| 1179 | 1179 |
/// This function just returns a \ref DigraphReader class. |
| 1180 | 1180 |
/// \relates DigraphReader |
| 1181 | 1181 |
template <typename Digraph> |
| 1182 | 1182 |
DigraphReader<Digraph> digraphReader(std::istream& is, Digraph& digraph) {
|
| 1183 | 1183 |
DigraphReader<Digraph> tmp(is, digraph); |
| 1184 | 1184 |
return tmp; |
| 1185 | 1185 |
} |
| 1186 | 1186 |
|
| 1187 | 1187 |
/// \brief Return a \ref DigraphReader class |
| 1188 |
/// |
|
| 1188 |
/// |
|
| 1189 | 1189 |
/// This function just returns a \ref DigraphReader class. |
| 1190 | 1190 |
/// \relates DigraphReader |
| 1191 | 1191 |
template <typename Digraph> |
| 1192 |
DigraphReader<Digraph> digraphReader(const std::string& fn, |
|
| 1193 |
Digraph& digraph) {
|
|
| 1192 |
DigraphReader<Digraph> digraphReader(const std::string& fn, |
|
| 1193 |
Digraph& digraph) {
|
|
| 1194 | 1194 |
DigraphReader<Digraph> tmp(fn, digraph); |
| 1195 | 1195 |
return tmp; |
| 1196 | 1196 |
} |
| 1197 | 1197 |
|
| 1198 | 1198 |
/// \brief Return a \ref DigraphReader class |
| 1199 |
/// |
|
| 1199 |
/// |
|
| 1200 | 1200 |
/// This function just returns a \ref DigraphReader class. |
| 1201 | 1201 |
/// \relates DigraphReader |
| 1202 | 1202 |
template <typename Digraph> |
| 1203 | 1203 |
DigraphReader<Digraph> digraphReader(const char* fn, Digraph& digraph) {
|
| 1204 | 1204 |
DigraphReader<Digraph> tmp(fn, digraph); |
| 1205 | 1205 |
return tmp; |
| 1206 | 1206 |
} |
| 1207 | 1207 |
|
| 1208 | 1208 |
template <typename Graph> |
| 1209 | 1209 |
class GraphReader; |
| 1210 | 1210 |
|
| 1211 | 1211 |
template <typename Graph> |
| 1212 |
GraphReader<Graph> graphReader(std::istream& is, Graph& graph); |
|
| 1212 |
GraphReader<Graph> graphReader(std::istream& is, Graph& graph); |
|
| 1213 | 1213 |
|
| 1214 | 1214 |
template <typename Graph> |
| 1215 |
GraphReader<Graph> graphReader(const std::string& fn, Graph& graph); |
|
| 1215 |
GraphReader<Graph> graphReader(const std::string& fn, Graph& graph); |
|
| 1216 | 1216 |
|
| 1217 | 1217 |
template <typename Graph> |
| 1218 |
GraphReader<Graph> graphReader(const char *fn, Graph& graph); |
|
| 1218 |
GraphReader<Graph> graphReader(const char *fn, Graph& graph); |
|
| 1219 | 1219 |
|
| 1220 | 1220 |
/// \ingroup lemon_io |
| 1221 |
/// |
|
| 1221 |
/// |
|
| 1222 | 1222 |
/// \brief \ref lgf-format "LGF" reader for undirected graphs |
| 1223 | 1223 |
/// |
| 1224 | 1224 |
/// This utility reads an \ref lgf-format "LGF" file. |
| 1225 | 1225 |
/// |
| 1226 | 1226 |
/// It can be used almost the same way as \c DigraphReader. |
| 1227 | 1227 |
/// The only difference is that this class can handle edges and |
| 1228 | 1228 |
/// edge maps as well as arcs and arc maps. |
| 1229 | 1229 |
/// |
| 1230 | 1230 |
/// The columns in the \c \@edges (or \c \@arcs) section are the |
| 1231 | 1231 |
/// edge maps. However, if there are two maps with the same name |
| 1232 | 1232 |
/// prefixed with \c '+' and \c '-', then these can be read into an |
| 1233 | 1233 |
/// arc map. Similarly, an attribute can be read into an arc, if |
| 1234 | 1234 |
/// it's value is an edge label prefixed with \c '+' or \c '-'. |
| 1235 | 1235 |
template <typename _Graph> |
| 1236 | 1236 |
class GraphReader {
|
| 1237 | 1237 |
public: |
| 1238 | 1238 |
|
| 1239 | 1239 |
typedef _Graph Graph; |
| 1240 | 1240 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
| 1241 |
|
|
| 1241 |
|
|
| 1242 | 1242 |
private: |
| 1243 | 1243 |
|
| 1244 | 1244 |
std::istream* _is; |
| 1245 | 1245 |
bool local_is; |
| 1246 | 1246 |
|
| 1247 | 1247 |
Graph& _graph; |
| 1248 | 1248 |
|
| 1249 | 1249 |
std::string _nodes_caption; |
| 1250 | 1250 |
std::string _edges_caption; |
| 1251 | 1251 |
std::string _attributes_caption; |
| 1252 | 1252 |
|
| 1253 | 1253 |
typedef std::map<std::string, Node> NodeIndex; |
| 1254 | 1254 |
NodeIndex _node_index; |
| 1255 | 1255 |
typedef std::map<std::string, Edge> EdgeIndex; |
| 1256 | 1256 |
EdgeIndex _edge_index; |
| 1257 |
|
|
| 1258 |
typedef std::vector<std::pair<std::string, |
|
| 1259 |
_reader_bits::MapStorageBase<Node>*> > NodeMaps; |
|
| 1260 |
NodeMaps _node_maps; |
|
| 1257 |
|
|
| 1258 |
typedef std::vector<std::pair<std::string, |
|
| 1259 |
_reader_bits::MapStorageBase<Node>*> > NodeMaps; |
|
| 1260 |
NodeMaps _node_maps; |
|
| 1261 | 1261 |
|
| 1262 | 1262 |
typedef std::vector<std::pair<std::string, |
| 1263 | 1263 |
_reader_bits::MapStorageBase<Edge>*> > EdgeMaps; |
| 1264 | 1264 |
EdgeMaps _edge_maps; |
| 1265 | 1265 |
|
| 1266 |
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> |
|
| 1266 |
typedef std::multimap<std::string, _reader_bits::ValueStorageBase*> |
|
| 1267 | 1267 |
Attributes; |
| 1268 | 1268 |
Attributes _attributes; |
| 1269 | 1269 |
|
| 1270 | 1270 |
bool _use_nodes; |
| 1271 | 1271 |
bool _use_edges; |
| 1272 | 1272 |
|
| 1273 | 1273 |
bool _skip_nodes; |
| 1274 | 1274 |
bool _skip_edges; |
| 1275 | 1275 |
|
| 1276 | 1276 |
int line_num; |
| 1277 | 1277 |
std::istringstream line; |
| 1278 | 1278 |
|
| 1279 | 1279 |
public: |
| 1280 | 1280 |
|
| 1281 | 1281 |
/// \brief Constructor |
| 1282 | 1282 |
/// |
| 1283 | 1283 |
/// Construct an undirected graph reader, which reads from the given |
| 1284 | 1284 |
/// input stream. |
| 1285 |
GraphReader(std::istream& is, Graph& graph) |
|
| 1285 |
GraphReader(std::istream& is, Graph& graph) |
|
| 1286 | 1286 |
: _is(&is), local_is(false), _graph(graph), |
| 1287 |
_use_nodes(false), _use_edges(false), |
|
| 1288 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1287 |
_use_nodes(false), _use_edges(false), |
|
| 1288 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1289 | 1289 |
|
| 1290 | 1290 |
/// \brief Constructor |
| 1291 | 1291 |
/// |
| 1292 | 1292 |
/// Construct an undirected graph reader, which reads from the given |
| 1293 | 1293 |
/// file. |
| 1294 |
GraphReader(const std::string& fn, Graph& graph) |
|
| 1294 |
GraphReader(const std::string& fn, Graph& graph) |
|
| 1295 | 1295 |
: _is(new std::ifstream(fn.c_str())), local_is(true), _graph(graph), |
| 1296 |
_use_nodes(false), _use_edges(false), |
|
| 1297 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1298 |
|
|
| 1296 |
_use_nodes(false), _use_edges(false), |
|
| 1297 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1298 |
|
|
| 1299 | 1299 |
/// \brief Constructor |
| 1300 | 1300 |
/// |
| 1301 | 1301 |
/// Construct an undirected graph reader, which reads from the given |
| 1302 | 1302 |
/// file. |
| 1303 |
GraphReader(const char* fn, Graph& graph) |
|
| 1303 |
GraphReader(const char* fn, Graph& graph) |
|
| 1304 | 1304 |
: _is(new std::ifstream(fn)), local_is(true), _graph(graph), |
| 1305 |
_use_nodes(false), _use_edges(false), |
|
| 1306 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1305 |
_use_nodes(false), _use_edges(false), |
|
| 1306 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 1307 | 1307 |
|
| 1308 | 1308 |
/// \brief Destructor |
| 1309 | 1309 |
~GraphReader() {
|
| 1310 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 1311 |
it != _node_maps.end(); ++it) {
|
|
| 1312 |
|
|
| 1310 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 1311 |
it != _node_maps.end(); ++it) {
|
|
| 1312 |
delete it->second; |
|
| 1313 | 1313 |
} |
| 1314 | 1314 |
|
| 1315 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 1316 |
it != _edge_maps.end(); ++it) {
|
|
| 1317 |
|
|
| 1315 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 1316 |
it != _edge_maps.end(); ++it) {
|
|
| 1317 |
delete it->second; |
|
| 1318 | 1318 |
} |
| 1319 | 1319 |
|
| 1320 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 1321 |
it != _attributes.end(); ++it) {
|
|
| 1322 |
|
|
| 1320 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 1321 |
it != _attributes.end(); ++it) {
|
|
| 1322 |
delete it->second; |
|
| 1323 | 1323 |
} |
| 1324 | 1324 |
|
| 1325 | 1325 |
if (local_is) {
|
| 1326 |
|
|
| 1326 |
delete _is; |
|
| 1327 | 1327 |
} |
| 1328 | 1328 |
|
| 1329 | 1329 |
} |
| 1330 | 1330 |
|
| 1331 | 1331 |
private: |
| 1332 |
friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph); |
|
| 1333 |
friend GraphReader<Graph> graphReader<>(const std::string& fn, |
|
| 1334 |
Graph& graph); |
|
| 1335 |
friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph); |
|
| 1336 |
|
|
| 1337 |
GraphReader(GraphReader& other) |
|
| 1332 |
friend GraphReader<Graph> graphReader<>(std::istream& is, Graph& graph); |
|
| 1333 |
friend GraphReader<Graph> graphReader<>(const std::string& fn, |
|
| 1334 |
Graph& graph); |
|
| 1335 |
friend GraphReader<Graph> graphReader<>(const char *fn, Graph& graph); |
|
| 1336 |
|
|
| 1337 |
GraphReader(GraphReader& other) |
|
| 1338 | 1338 |
: _is(other._is), local_is(other.local_is), _graph(other._graph), |
| 1339 |
_use_nodes(other._use_nodes), _use_edges(other._use_edges), |
|
| 1340 |
_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
|
|
| 1339 |
_use_nodes(other._use_nodes), _use_edges(other._use_edges), |
|
| 1340 |
_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
|
|
| 1341 | 1341 |
|
| 1342 | 1342 |
other._is = 0; |
| 1343 | 1343 |
other.local_is = false; |
| 1344 |
|
|
| 1344 |
|
|
| 1345 | 1345 |
_node_index.swap(other._node_index); |
| 1346 | 1346 |
_edge_index.swap(other._edge_index); |
| 1347 | 1347 |
|
| 1348 | 1348 |
_node_maps.swap(other._node_maps); |
| 1349 | 1349 |
_edge_maps.swap(other._edge_maps); |
| 1350 | 1350 |
_attributes.swap(other._attributes); |
| 1351 | 1351 |
|
| 1352 | 1352 |
_nodes_caption = other._nodes_caption; |
| 1353 | 1353 |
_edges_caption = other._edges_caption; |
| 1354 | 1354 |
_attributes_caption = other._attributes_caption; |
| 1355 | 1355 |
|
| 1356 | 1356 |
} |
| 1357 | 1357 |
|
| 1358 | 1358 |
GraphReader& operator=(const GraphReader&); |
| 1359 | 1359 |
|
| 1360 | 1360 |
public: |
| 1361 | 1361 |
|
| 1362 | 1362 |
/// \name Reading rules |
| 1363 | 1363 |
/// @{
|
| 1364 |
|
|
| 1364 |
|
|
| 1365 | 1365 |
/// \brief Node map reading rule |
| 1366 | 1366 |
/// |
| 1367 | 1367 |
/// Add a node map reading rule to the reader. |
| 1368 | 1368 |
template <typename Map> |
| 1369 | 1369 |
GraphReader& nodeMap(const std::string& caption, Map& map) {
|
| 1370 | 1370 |
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
| 1371 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 1372 |
new _reader_bits::MapStorage<Node, Map>(map); |
|
| 1371 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 1372 |
new _reader_bits::MapStorage<Node, Map>(map); |
|
| 1373 | 1373 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 1374 | 1374 |
return *this; |
| 1375 | 1375 |
} |
| 1376 | 1376 |
|
| 1377 | 1377 |
/// \brief Node map reading rule |
| 1378 | 1378 |
/// |
| 1379 | 1379 |
/// Add a node map reading rule with specialized converter to the |
| 1380 | 1380 |
/// reader. |
| 1381 | 1381 |
template <typename Map, typename Converter> |
| 1382 |
GraphReader& nodeMap(const std::string& caption, Map& map, |
|
| 1383 |
const Converter& converter = Converter()) {
|
|
| 1382 |
GraphReader& nodeMap(const std::string& caption, Map& map, |
|
| 1383 |
const Converter& converter = Converter()) {
|
|
| 1384 | 1384 |
checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
| 1385 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 1386 |
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 1385 |
_reader_bits::MapStorageBase<Node>* storage = |
|
| 1386 |
new _reader_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 1387 | 1387 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 1388 | 1388 |
return *this; |
| 1389 | 1389 |
} |
| 1390 | 1390 |
|
| 1391 | 1391 |
/// \brief Edge map reading rule |
| 1392 | 1392 |
/// |
| 1393 | 1393 |
/// Add an edge map reading rule to the reader. |
| 1394 | 1394 |
template <typename Map> |
| 1395 | 1395 |
GraphReader& edgeMap(const std::string& caption, Map& map) {
|
| 1396 | 1396 |
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
| 1397 |
_reader_bits::MapStorageBase<Edge>* storage = |
|
| 1398 |
new _reader_bits::MapStorage<Edge, Map>(map); |
|
| 1397 |
_reader_bits::MapStorageBase<Edge>* storage = |
|
| 1398 |
new _reader_bits::MapStorage<Edge, Map>(map); |
|
| 1399 | 1399 |
_edge_maps.push_back(std::make_pair(caption, storage)); |
| 1400 | 1400 |
return *this; |
| 1401 | 1401 |
} |
| 1402 | 1402 |
|
| 1403 | 1403 |
/// \brief Edge map reading rule |
| 1404 | 1404 |
/// |
| 1405 | 1405 |
/// Add an edge map reading rule with specialized converter to the |
| 1406 | 1406 |
/// reader. |
| 1407 | 1407 |
template <typename Map, typename Converter> |
| 1408 |
GraphReader& edgeMap(const std::string& caption, Map& map, |
|
| 1409 |
const Converter& converter = Converter()) {
|
|
| 1408 |
GraphReader& edgeMap(const std::string& caption, Map& map, |
|
| 1409 |
const Converter& converter = Converter()) {
|
|
| 1410 | 1410 |
checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>(); |
| 1411 |
_reader_bits::MapStorageBase<Edge>* storage = |
|
| 1412 |
new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter); |
|
| 1411 |
_reader_bits::MapStorageBase<Edge>* storage = |
|
| 1412 |
new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter); |
|
| 1413 | 1413 |
_edge_maps.push_back(std::make_pair(caption, storage)); |
| 1414 | 1414 |
return *this; |
| 1415 | 1415 |
} |
| 1416 | 1416 |
|
| 1417 | 1417 |
/// \brief Arc map reading rule |
| 1418 | 1418 |
/// |
| 1419 | 1419 |
/// Add an arc map reading rule to the reader. |
| 1420 | 1420 |
template <typename Map> |
| 1421 | 1421 |
GraphReader& arcMap(const std::string& caption, Map& map) {
|
| 1422 | 1422 |
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
| 1423 |
_reader_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1424 |
new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
|
| 1423 |
_reader_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1424 |
new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
|
| 1425 | 1425 |
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
| 1426 |
_reader_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1427 |
new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
|
| 1426 |
_reader_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1427 |
new _reader_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
|
| 1428 | 1428 |
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
| 1429 | 1429 |
return *this; |
| 1430 | 1430 |
} |
| 1431 | 1431 |
|
| 1432 | 1432 |
/// \brief Arc map reading rule |
| 1433 | 1433 |
/// |
| 1434 | 1434 |
/// Add an arc map reading rule with specialized converter to the |
| 1435 | 1435 |
/// reader. |
| 1436 | 1436 |
template <typename Map, typename Converter> |
| 1437 |
GraphReader& arcMap(const std::string& caption, Map& map, |
|
| 1438 |
const Converter& converter = Converter()) {
|
|
| 1437 |
GraphReader& arcMap(const std::string& caption, Map& map, |
|
| 1438 |
const Converter& converter = Converter()) {
|
|
| 1439 | 1439 |
checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>(); |
| 1440 |
_reader_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1441 |
new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
|
| 1442 |
|
|
| 1440 |
_reader_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1441 |
new _reader_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
|
| 1442 |
(_graph, map, converter); |
|
| 1443 | 1443 |
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
| 1444 |
_reader_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1445 |
new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
|
| 1446 |
|
|
| 1444 |
_reader_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1445 |
new _reader_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
|
| 1446 |
(_graph, map, converter); |
|
| 1447 | 1447 |
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
| 1448 | 1448 |
return *this; |
| 1449 | 1449 |
} |
| 1450 | 1450 |
|
| 1451 | 1451 |
/// \brief Attribute reading rule |
| 1452 | 1452 |
/// |
| 1453 | 1453 |
/// Add an attribute reading rule to the reader. |
| 1454 | 1454 |
template <typename Value> |
| 1455 | 1455 |
GraphReader& attribute(const std::string& caption, Value& value) {
|
| 1456 |
_reader_bits::ValueStorageBase* storage = |
|
| 1457 |
new _reader_bits::ValueStorage<Value>(value); |
|
| 1456 |
_reader_bits::ValueStorageBase* storage = |
|
| 1457 |
new _reader_bits::ValueStorage<Value>(value); |
|
| 1458 | 1458 |
_attributes.insert(std::make_pair(caption, storage)); |
| 1459 | 1459 |
return *this; |
| 1460 | 1460 |
} |
| 1461 | 1461 |
|
| 1462 | 1462 |
/// \brief Attribute reading rule |
| 1463 | 1463 |
/// |
| 1464 | 1464 |
/// Add an attribute reading rule with specialized converter to the |
| 1465 | 1465 |
/// reader. |
| 1466 | 1466 |
template <typename Value, typename Converter> |
| 1467 |
GraphReader& attribute(const std::string& caption, Value& value, |
|
| 1468 |
const Converter& converter = Converter()) {
|
|
| 1469 |
_reader_bits::ValueStorageBase* storage = |
|
| 1470 |
new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 1467 |
GraphReader& attribute(const std::string& caption, Value& value, |
|
| 1468 |
const Converter& converter = Converter()) {
|
|
| 1469 |
_reader_bits::ValueStorageBase* storage = |
|
| 1470 |
new _reader_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 1471 | 1471 |
_attributes.insert(std::make_pair(caption, storage)); |
| 1472 | 1472 |
return *this; |
| 1473 | 1473 |
} |
| 1474 | 1474 |
|
| 1475 | 1475 |
/// \brief Node reading rule |
| 1476 | 1476 |
/// |
| 1477 | 1477 |
/// Add a node reading rule to reader. |
| 1478 | 1478 |
GraphReader& node(const std::string& caption, Node& node) {
|
| 1479 | 1479 |
typedef _reader_bits::MapLookUpConverter<Node> Converter; |
| 1480 | 1480 |
Converter converter(_node_index); |
| 1481 |
_reader_bits::ValueStorageBase* storage = |
|
| 1482 |
new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 1481 |
_reader_bits::ValueStorageBase* storage = |
|
| 1482 |
new _reader_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 1483 | 1483 |
_attributes.insert(std::make_pair(caption, storage)); |
| 1484 | 1484 |
return *this; |
| 1485 | 1485 |
} |
| 1486 | 1486 |
|
| 1487 | 1487 |
/// \brief Edge reading rule |
| 1488 | 1488 |
/// |
| 1489 | 1489 |
/// Add an edge reading rule to reader. |
| 1490 | 1490 |
GraphReader& edge(const std::string& caption, Edge& edge) {
|
| 1491 | 1491 |
typedef _reader_bits::MapLookUpConverter<Edge> Converter; |
| 1492 | 1492 |
Converter converter(_edge_index); |
| 1493 |
_reader_bits::ValueStorageBase* storage = |
|
| 1494 |
new _reader_bits::ValueStorage<Edge, Converter>(edge, converter); |
|
| 1493 |
_reader_bits::ValueStorageBase* storage = |
|
| 1494 |
new _reader_bits::ValueStorage<Edge, Converter>(edge, converter); |
|
| 1495 | 1495 |
_attributes.insert(std::make_pair(caption, storage)); |
| 1496 | 1496 |
return *this; |
| 1497 | 1497 |
} |
| 1498 | 1498 |
|
| 1499 | 1499 |
/// \brief Arc reading rule |
| 1500 | 1500 |
/// |
| 1501 | 1501 |
/// Add an arc reading rule to reader. |
| 1502 | 1502 |
GraphReader& arc(const std::string& caption, Arc& arc) {
|
| 1503 | 1503 |
typedef _reader_bits::GraphArcLookUpConverter<Graph> Converter; |
| 1504 | 1504 |
Converter converter(_graph, _edge_index); |
| 1505 |
_reader_bits::ValueStorageBase* storage = |
|
| 1506 |
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 1505 |
_reader_bits::ValueStorageBase* storage = |
|
| 1506 |
new _reader_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 1507 | 1507 |
_attributes.insert(std::make_pair(caption, storage)); |
| 1508 | 1508 |
return *this; |
| 1509 | 1509 |
} |
| 1510 | 1510 |
|
| 1511 | 1511 |
/// @} |
| 1512 | 1512 |
|
| 1513 | 1513 |
/// \name Select section by name |
| 1514 | 1514 |
/// @{
|
| 1515 | 1515 |
|
| 1516 | 1516 |
/// \brief Set \c \@nodes section to be read |
| 1517 | 1517 |
/// |
| 1518 | 1518 |
/// Set \c \@nodes section to be read. |
| 1519 | 1519 |
GraphReader& nodes(const std::string& caption) {
|
| 1520 | 1520 |
_nodes_caption = caption; |
| 1521 | 1521 |
return *this; |
| 1522 | 1522 |
} |
| ... | ... |
@@ -1536,592 +1536,592 @@ |
| 1536 | 1536 |
_attributes_caption = caption; |
| 1537 | 1537 |
return *this; |
| 1538 | 1538 |
} |
| 1539 | 1539 |
|
| 1540 | 1540 |
/// @} |
| 1541 | 1541 |
|
| 1542 | 1542 |
/// \name Using previously constructed node or edge set |
| 1543 | 1543 |
/// @{
|
| 1544 | 1544 |
|
| 1545 | 1545 |
/// \brief Use previously constructed node set |
| 1546 | 1546 |
/// |
| 1547 | 1547 |
/// Use previously constructed node set, and specify the node |
| 1548 | 1548 |
/// label map. |
| 1549 | 1549 |
template <typename Map> |
| 1550 | 1550 |
GraphReader& useNodes(const Map& map) {
|
| 1551 | 1551 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 1552 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 1552 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 1553 | 1553 |
_use_nodes = true; |
| 1554 | 1554 |
_writer_bits::DefaultConverter<typename Map::Value> converter; |
| 1555 | 1555 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
| 1556 |
|
|
| 1556 |
_node_index.insert(std::make_pair(converter(map[n]), n)); |
|
| 1557 | 1557 |
} |
| 1558 | 1558 |
return *this; |
| 1559 | 1559 |
} |
| 1560 | 1560 |
|
| 1561 | 1561 |
/// \brief Use previously constructed node set |
| 1562 | 1562 |
/// |
| 1563 | 1563 |
/// Use previously constructed node set, and specify the node |
| 1564 | 1564 |
/// label map and a functor which converts the label map values to |
| 1565 | 1565 |
/// \c std::string. |
| 1566 | 1566 |
template <typename Map, typename Converter> |
| 1567 |
GraphReader& useNodes(const Map& map, |
|
| 1568 |
const Converter& converter = Converter()) {
|
|
| 1567 |
GraphReader& useNodes(const Map& map, |
|
| 1568 |
const Converter& converter = Converter()) {
|
|
| 1569 | 1569 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 1570 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 1570 |
LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member"); |
|
| 1571 | 1571 |
_use_nodes = true; |
| 1572 | 1572 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
| 1573 |
|
|
| 1573 |
_node_index.insert(std::make_pair(converter(map[n]), n)); |
|
| 1574 | 1574 |
} |
| 1575 | 1575 |
return *this; |
| 1576 | 1576 |
} |
| 1577 | 1577 |
|
| 1578 | 1578 |
/// \brief Use previously constructed edge set |
| 1579 | 1579 |
/// |
| 1580 | 1580 |
/// Use previously constructed edge set, and specify the edge |
| 1581 | 1581 |
/// label map. |
| 1582 | 1582 |
template <typename Map> |
| 1583 | 1583 |
GraphReader& useEdges(const Map& map) {
|
| 1584 | 1584 |
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
| 1585 | 1585 |
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); |
| 1586 | 1586 |
_use_edges = true; |
| 1587 | 1587 |
_writer_bits::DefaultConverter<typename Map::Value> converter; |
| 1588 | 1588 |
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
| 1589 |
|
|
| 1589 |
_edge_index.insert(std::make_pair(converter(map[a]), a)); |
|
| 1590 | 1590 |
} |
| 1591 | 1591 |
return *this; |
| 1592 | 1592 |
} |
| 1593 | 1593 |
|
| 1594 | 1594 |
/// \brief Use previously constructed edge set |
| 1595 | 1595 |
/// |
| 1596 | 1596 |
/// Use previously constructed edge set, and specify the edge |
| 1597 | 1597 |
/// label map and a functor which converts the label map values to |
| 1598 | 1598 |
/// \c std::string. |
| 1599 | 1599 |
template <typename Map, typename Converter> |
| 1600 |
GraphReader& useEdges(const Map& map, |
|
| 1601 |
const Converter& converter = Converter()) {
|
|
| 1600 |
GraphReader& useEdges(const Map& map, |
|
| 1601 |
const Converter& converter = Converter()) {
|
|
| 1602 | 1602 |
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
| 1603 |
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); |
|
| 1603 |
LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member"); |
|
| 1604 | 1604 |
_use_edges = true; |
| 1605 | 1605 |
for (EdgeIt a(_graph); a != INVALID; ++a) {
|
| 1606 |
|
|
| 1606 |
_edge_index.insert(std::make_pair(converter(map[a]), a)); |
|
| 1607 | 1607 |
} |
| 1608 | 1608 |
return *this; |
| 1609 | 1609 |
} |
| 1610 | 1610 |
|
| 1611 | 1611 |
/// \brief Skip the reading of node section |
| 1612 | 1612 |
/// |
| 1613 | 1613 |
/// Omit the reading of the node section. This implies that each node |
| 1614 | 1614 |
/// map reading rule will be abandoned, and the nodes of the graph |
| 1615 | 1615 |
/// will not be constructed, which usually cause that the edge set |
| 1616 | 1616 |
/// could not be read due to lack of node name |
| 1617 | 1617 |
/// could not be read due to lack of node name resolving. |
| 1618 | 1618 |
/// Therefore \c skipEdges() function should also be used, or |
| 1619 | 1619 |
/// \c useNodes() should be used to specify the label of the nodes. |
| 1620 | 1620 |
GraphReader& skipNodes() {
|
| 1621 |
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); |
|
| 1621 |
LEMON_ASSERT(!_skip_nodes, "Skip nodes already set"); |
|
| 1622 | 1622 |
_skip_nodes = true; |
| 1623 | 1623 |
return *this; |
| 1624 | 1624 |
} |
| 1625 | 1625 |
|
| 1626 | 1626 |
/// \brief Skip the reading of edge section |
| 1627 | 1627 |
/// |
| 1628 | 1628 |
/// Omit the reading of the edge section. This implies that each edge |
| 1629 | 1629 |
/// map reading rule will be abandoned, and the edges of the graph |
| 1630 | 1630 |
/// will not be constructed. |
| 1631 | 1631 |
GraphReader& skipEdges() {
|
| 1632 |
LEMON_ASSERT(!_skip_edges, "Skip edges already set"); |
|
| 1632 |
LEMON_ASSERT(!_skip_edges, "Skip edges already set"); |
|
| 1633 | 1633 |
_skip_edges = true; |
| 1634 | 1634 |
return *this; |
| 1635 | 1635 |
} |
| 1636 | 1636 |
|
| 1637 | 1637 |
/// @} |
| 1638 | 1638 |
|
| 1639 | 1639 |
private: |
| 1640 | 1640 |
|
| 1641 | 1641 |
bool readLine() {
|
| 1642 | 1642 |
std::string str; |
| 1643 | 1643 |
while(++line_num, std::getline(*_is, str)) {
|
| 1644 |
line.clear(); line.str(str); |
|
| 1645 |
char c; |
|
| 1646 |
if (line >> std::ws >> c && c != '#') {
|
|
| 1647 |
line.putback(c); |
|
| 1648 |
return true; |
|
| 1649 |
} |
|
| 1644 |
line.clear(); line.str(str); |
|
| 1645 |
char c; |
|
| 1646 |
if (line >> std::ws >> c && c != '#') {
|
|
| 1647 |
line.putback(c); |
|
| 1648 |
return true; |
|
| 1649 |
} |
|
| 1650 | 1650 |
} |
| 1651 | 1651 |
return false; |
| 1652 | 1652 |
} |
| 1653 | 1653 |
|
| 1654 | 1654 |
bool readSuccess() {
|
| 1655 | 1655 |
return static_cast<bool>(*_is); |
| 1656 | 1656 |
} |
| 1657 |
|
|
| 1657 |
|
|
| 1658 | 1658 |
void skipSection() {
|
| 1659 | 1659 |
char c; |
| 1660 | 1660 |
while (readSuccess() && line >> c && c != '@') {
|
| 1661 |
|
|
| 1661 |
readLine(); |
|
| 1662 | 1662 |
} |
| 1663 | 1663 |
line.putback(c); |
| 1664 | 1664 |
} |
| 1665 | 1665 |
|
| 1666 | 1666 |
void readNodes() {
|
| 1667 | 1667 |
|
| 1668 | 1668 |
std::vector<int> map_index(_node_maps.size()); |
| 1669 | 1669 |
int map_num, label_index; |
| 1670 | 1670 |
|
| 1671 | 1671 |
char c; |
| 1672 | 1672 |
if (!readLine() || !(line >> c) || c == '@') {
|
| 1673 |
if (readSuccess() && line) line.putback(c); |
|
| 1674 |
if (!_node_maps.empty()) |
|
| 1675 |
throw DataFormatError("Cannot find map names");
|
|
| 1676 |
return; |
|
| 1673 |
if (readSuccess() && line) line.putback(c); |
|
| 1674 |
if (!_node_maps.empty()) |
|
| 1675 |
throw DataFormatError("Cannot find map names");
|
|
| 1676 |
return; |
|
| 1677 | 1677 |
} |
| 1678 | 1678 |
line.putback(c); |
| 1679 |
|
|
| 1679 |
|
|
| 1680 | 1680 |
{
|
| 1681 |
std::map<std::string, int> maps; |
|
| 1682 |
|
|
| 1683 |
std::string map; |
|
| 1684 |
int index = 0; |
|
| 1685 |
while (_reader_bits::readToken(line, map)) {
|
|
| 1686 |
if (maps.find(map) != maps.end()) {
|
|
| 1687 |
std::ostringstream msg; |
|
| 1688 |
msg << "Multiple occurence of node map: " << map; |
|
| 1689 |
throw DataFormatError(msg.str().c_str()); |
|
| 1690 |
} |
|
| 1691 |
maps.insert(std::make_pair(map, index)); |
|
| 1692 |
++index; |
|
| 1693 |
} |
|
| 1694 |
|
|
| 1695 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 1696 |
std::map<std::string, int>::iterator jt = |
|
| 1697 |
maps.find(_node_maps[i].first); |
|
| 1698 |
if (jt == maps.end()) {
|
|
| 1699 |
std::ostringstream msg; |
|
| 1700 |
msg << "Map not found in file: " << _node_maps[i].first; |
|
| 1701 |
throw DataFormatError(msg.str().c_str()); |
|
| 1702 |
} |
|
| 1703 |
map_index[i] = jt->second; |
|
| 1704 |
} |
|
| 1705 |
|
|
| 1706 |
{
|
|
| 1707 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 1708 |
if (jt != maps.end()) {
|
|
| 1709 |
label_index = jt->second; |
|
| 1710 |
} else {
|
|
| 1711 |
label_index = -1; |
|
| 1712 |
} |
|
| 1713 |
} |
|
| 1714 |
map_num = maps.size(); |
|
| 1681 |
std::map<std::string, int> maps; |
|
| 1682 |
|
|
| 1683 |
std::string map; |
|
| 1684 |
int index = 0; |
|
| 1685 |
while (_reader_bits::readToken(line, map)) {
|
|
| 1686 |
if (maps.find(map) != maps.end()) {
|
|
| 1687 |
std::ostringstream msg; |
|
| 1688 |
msg << "Multiple occurence of node map: " << map; |
|
| 1689 |
throw DataFormatError(msg.str().c_str()); |
|
| 1690 |
} |
|
| 1691 |
maps.insert(std::make_pair(map, index)); |
|
| 1692 |
++index; |
|
| 1693 |
} |
|
| 1694 |
|
|
| 1695 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 1696 |
std::map<std::string, int>::iterator jt = |
|
| 1697 |
maps.find(_node_maps[i].first); |
|
| 1698 |
if (jt == maps.end()) {
|
|
| 1699 |
std::ostringstream msg; |
|
| 1700 |
msg << "Map not found in file: " << _node_maps[i].first; |
|
| 1701 |
throw DataFormatError(msg.str().c_str()); |
|
| 1702 |
} |
|
| 1703 |
map_index[i] = jt->second; |
|
| 1704 |
} |
|
| 1705 |
|
|
| 1706 |
{
|
|
| 1707 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 1708 |
if (jt != maps.end()) {
|
|
| 1709 |
label_index = jt->second; |
|
| 1710 |
} else {
|
|
| 1711 |
label_index = -1; |
|
| 1712 |
} |
|
| 1713 |
} |
|
| 1714 |
map_num = maps.size(); |
|
| 1715 | 1715 |
} |
| 1716 | 1716 |
|
| 1717 | 1717 |
while (readLine() && line >> c && c != '@') {
|
| 1718 |
line.putback(c); |
|
| 1719 |
|
|
| 1720 |
std::vector<std::string> tokens(map_num); |
|
| 1721 |
for (int i = 0; i < map_num; ++i) {
|
|
| 1722 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 1723 |
std::ostringstream msg; |
|
| 1724 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 1725 |
throw DataFormatError(msg.str().c_str()); |
|
| 1726 |
} |
|
| 1727 |
} |
|
| 1728 |
if (line >> std::ws >> c) |
|
| 1729 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1730 |
|
|
| 1731 |
Node n; |
|
| 1732 |
if (!_use_nodes) {
|
|
| 1733 |
n = _graph.addNode(); |
|
| 1734 |
if (label_index != -1) |
|
| 1735 |
_node_index.insert(std::make_pair(tokens[label_index], n)); |
|
| 1736 |
} else {
|
|
| 1737 |
if (label_index == -1) |
|
| 1738 |
throw DataFormatError("Label map not found in file");
|
|
| 1739 |
typename std::map<std::string, Node>::iterator it = |
|
| 1740 |
_node_index.find(tokens[label_index]); |
|
| 1741 |
if (it == _node_index.end()) {
|
|
| 1742 |
std::ostringstream msg; |
|
| 1743 |
msg << "Node with label not found: " << tokens[label_index]; |
|
| 1744 |
throw DataFormatError(msg.str().c_str()); |
|
| 1745 |
} |
|
| 1746 |
n = it->second; |
|
| 1747 |
} |
|
| 1748 |
|
|
| 1749 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 1750 |
_node_maps[i].second->set(n, tokens[map_index[i]]); |
|
| 1751 |
} |
|
| 1718 |
line.putback(c); |
|
| 1719 |
|
|
| 1720 |
std::vector<std::string> tokens(map_num); |
|
| 1721 |
for (int i = 0; i < map_num; ++i) {
|
|
| 1722 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 1723 |
std::ostringstream msg; |
|
| 1724 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 1725 |
throw DataFormatError(msg.str().c_str()); |
|
| 1726 |
} |
|
| 1727 |
} |
|
| 1728 |
if (line >> std::ws >> c) |
|
| 1729 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1730 |
|
|
| 1731 |
Node n; |
|
| 1732 |
if (!_use_nodes) {
|
|
| 1733 |
n = _graph.addNode(); |
|
| 1734 |
if (label_index != -1) |
|
| 1735 |
_node_index.insert(std::make_pair(tokens[label_index], n)); |
|
| 1736 |
} else {
|
|
| 1737 |
if (label_index == -1) |
|
| 1738 |
throw DataFormatError("Label map not found in file");
|
|
| 1739 |
typename std::map<std::string, Node>::iterator it = |
|
| 1740 |
_node_index.find(tokens[label_index]); |
|
| 1741 |
if (it == _node_index.end()) {
|
|
| 1742 |
std::ostringstream msg; |
|
| 1743 |
msg << "Node with label not found: " << tokens[label_index]; |
|
| 1744 |
throw DataFormatError(msg.str().c_str()); |
|
| 1745 |
} |
|
| 1746 |
n = it->second; |
|
| 1747 |
} |
|
| 1748 |
|
|
| 1749 |
for (int i = 0; i < static_cast<int>(_node_maps.size()); ++i) {
|
|
| 1750 |
_node_maps[i].second->set(n, tokens[map_index[i]]); |
|
| 1751 |
} |
|
| 1752 | 1752 |
|
| 1753 | 1753 |
} |
| 1754 | 1754 |
if (readSuccess()) {
|
| 1755 |
|
|
| 1755 |
line.putback(c); |
|
| 1756 | 1756 |
} |
| 1757 | 1757 |
} |
| 1758 | 1758 |
|
| 1759 | 1759 |
void readEdges() {
|
| 1760 | 1760 |
|
| 1761 | 1761 |
std::vector<int> map_index(_edge_maps.size()); |
| 1762 | 1762 |
int map_num, label_index; |
| 1763 | 1763 |
|
| 1764 | 1764 |
char c; |
| 1765 | 1765 |
if (!readLine() || !(line >> c) || c == '@') {
|
| 1766 |
if (readSuccess() && line) line.putback(c); |
|
| 1767 |
if (!_edge_maps.empty()) |
|
| 1768 |
throw DataFormatError("Cannot find map names");
|
|
| 1769 |
return; |
|
| 1766 |
if (readSuccess() && line) line.putback(c); |
|
| 1767 |
if (!_edge_maps.empty()) |
|
| 1768 |
throw DataFormatError("Cannot find map names");
|
|
| 1769 |
return; |
|
| 1770 | 1770 |
} |
| 1771 | 1771 |
line.putback(c); |
| 1772 |
|
|
| 1772 |
|
|
| 1773 | 1773 |
{
|
| 1774 |
std::map<std::string, int> maps; |
|
| 1775 |
|
|
| 1776 |
std::string map; |
|
| 1777 |
int index = 0; |
|
| 1778 |
while (_reader_bits::readToken(line, map)) {
|
|
| 1779 |
if (maps.find(map) != maps.end()) {
|
|
| 1780 |
std::ostringstream msg; |
|
| 1781 |
msg << "Multiple occurence of edge map: " << map; |
|
| 1782 |
throw DataFormatError(msg.str().c_str()); |
|
| 1783 |
} |
|
| 1784 |
maps.insert(std::make_pair(map, index)); |
|
| 1785 |
++index; |
|
| 1786 |
} |
|
| 1787 |
|
|
| 1788 |
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
| 1789 |
std::map<std::string, int>::iterator jt = |
|
| 1790 |
maps.find(_edge_maps[i].first); |
|
| 1791 |
if (jt == maps.end()) {
|
|
| 1792 |
std::ostringstream msg; |
|
| 1793 |
msg << "Map not found in file: " << _edge_maps[i].first; |
|
| 1794 |
throw DataFormatError(msg.str().c_str()); |
|
| 1795 |
} |
|
| 1796 |
map_index[i] = jt->second; |
|
| 1797 |
} |
|
| 1798 |
|
|
| 1799 |
{
|
|
| 1800 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 1801 |
if (jt != maps.end()) {
|
|
| 1802 |
label_index = jt->second; |
|
| 1803 |
} else {
|
|
| 1804 |
label_index = -1; |
|
| 1805 |
} |
|
| 1806 |
} |
|
| 1807 |
map_num = maps.size(); |
|
| 1774 |
std::map<std::string, int> maps; |
|
| 1775 |
|
|
| 1776 |
std::string map; |
|
| 1777 |
int index = 0; |
|
| 1778 |
while (_reader_bits::readToken(line, map)) {
|
|
| 1779 |
if (maps.find(map) != maps.end()) {
|
|
| 1780 |
std::ostringstream msg; |
|
| 1781 |
msg << "Multiple occurence of edge map: " << map; |
|
| 1782 |
throw DataFormatError(msg.str().c_str()); |
|
| 1783 |
} |
|
| 1784 |
maps.insert(std::make_pair(map, index)); |
|
| 1785 |
++index; |
|
| 1786 |
} |
|
| 1787 |
|
|
| 1788 |
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
| 1789 |
std::map<std::string, int>::iterator jt = |
|
| 1790 |
maps.find(_edge_maps[i].first); |
|
| 1791 |
if (jt == maps.end()) {
|
|
| 1792 |
std::ostringstream msg; |
|
| 1793 |
msg << "Map not found in file: " << _edge_maps[i].first; |
|
| 1794 |
throw DataFormatError(msg.str().c_str()); |
|
| 1795 |
} |
|
| 1796 |
map_index[i] = jt->second; |
|
| 1797 |
} |
|
| 1798 |
|
|
| 1799 |
{
|
|
| 1800 |
std::map<std::string, int>::iterator jt = maps.find("label");
|
|
| 1801 |
if (jt != maps.end()) {
|
|
| 1802 |
label_index = jt->second; |
|
| 1803 |
} else {
|
|
| 1804 |
label_index = -1; |
|
| 1805 |
} |
|
| 1806 |
} |
|
| 1807 |
map_num = maps.size(); |
|
| 1808 | 1808 |
} |
| 1809 | 1809 |
|
| 1810 | 1810 |
while (readLine() && line >> c && c != '@') {
|
| 1811 |
line.putback(c); |
|
| 1812 |
|
|
| 1813 |
std::string source_token; |
|
| 1814 |
std::string target_token; |
|
| 1815 |
|
|
| 1816 |
if (!_reader_bits::readToken(line, source_token)) |
|
| 1817 |
throw DataFormatError("Node u not found");
|
|
| 1818 |
|
|
| 1819 |
if (!_reader_bits::readToken(line, target_token)) |
|
| 1820 |
throw DataFormatError("Node v not found");
|
|
| 1821 |
|
|
| 1822 |
std::vector<std::string> tokens(map_num); |
|
| 1823 |
for (int i = 0; i < map_num; ++i) {
|
|
| 1824 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 1825 |
std::ostringstream msg; |
|
| 1826 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 1827 |
throw DataFormatError(msg.str().c_str()); |
|
| 1828 |
} |
|
| 1829 |
} |
|
| 1830 |
if (line >> std::ws >> c) |
|
| 1831 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1832 |
|
|
| 1833 |
Edge e; |
|
| 1834 |
if (!_use_edges) {
|
|
| 1811 |
line.putback(c); |
|
| 1812 |
|
|
| 1813 |
std::string source_token; |
|
| 1814 |
std::string target_token; |
|
| 1815 |
|
|
| 1816 |
if (!_reader_bits::readToken(line, source_token)) |
|
| 1817 |
throw DataFormatError("Node u not found");
|
|
| 1818 |
|
|
| 1819 |
if (!_reader_bits::readToken(line, target_token)) |
|
| 1820 |
throw DataFormatError("Node v not found");
|
|
| 1821 |
|
|
| 1822 |
std::vector<std::string> tokens(map_num); |
|
| 1823 |
for (int i = 0; i < map_num; ++i) {
|
|
| 1824 |
if (!_reader_bits::readToken(line, tokens[i])) {
|
|
| 1825 |
std::ostringstream msg; |
|
| 1826 |
msg << "Column not found (" << i + 1 << ")";
|
|
| 1827 |
throw DataFormatError(msg.str().c_str()); |
|
| 1828 |
} |
|
| 1829 |
} |
|
| 1830 |
if (line >> std::ws >> c) |
|
| 1831 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1832 |
|
|
| 1833 |
Edge e; |
|
| 1834 |
if (!_use_edges) {
|
|
| 1835 | 1835 |
|
| 1836 | 1836 |
typename NodeIndex::iterator it; |
| 1837 |
|
|
| 1837 |
|
|
| 1838 | 1838 |
it = _node_index.find(source_token); |
| 1839 | 1839 |
if (it == _node_index.end()) {
|
| 1840 | 1840 |
std::ostringstream msg; |
| 1841 | 1841 |
msg << "Item not found: " << source_token; |
| 1842 | 1842 |
throw DataFormatError(msg.str().c_str()); |
| 1843 | 1843 |
} |
| 1844 | 1844 |
Node source = it->second; |
| 1845 | 1845 |
|
| 1846 | 1846 |
it = _node_index.find(target_token); |
| 1847 |
if (it == _node_index.end()) {
|
|
| 1848 |
std::ostringstream msg; |
|
| 1847 |
if (it == _node_index.end()) {
|
|
| 1848 |
std::ostringstream msg; |
|
| 1849 | 1849 |
msg << "Item not found: " << target_token; |
| 1850 | 1850 |
throw DataFormatError(msg.str().c_str()); |
| 1851 |
} |
|
| 1852 |
Node target = it->second; |
|
| 1853 |
|
|
| 1854 |
e = _graph.addEdge(source, target); |
|
| 1855 |
if (label_index != -1) |
|
| 1856 |
_edge_index.insert(std::make_pair(tokens[label_index], e)); |
|
| 1857 |
} else {
|
|
| 1858 |
if (label_index == -1) |
|
| 1859 |
throw DataFormatError("Label map not found in file");
|
|
| 1860 |
typename std::map<std::string, Edge>::iterator it = |
|
| 1861 |
_edge_index.find(tokens[label_index]); |
|
| 1862 |
if (it == _edge_index.end()) {
|
|
| 1863 |
std::ostringstream msg; |
|
| 1864 |
msg << "Edge with label not found: " << tokens[label_index]; |
|
| 1865 |
throw DataFormatError(msg.str().c_str()); |
|
| 1866 |
} |
|
| 1867 |
e = it->second; |
|
| 1868 |
} |
|
| 1869 |
|
|
| 1870 |
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
| 1871 |
_edge_maps[i].second->set(e, tokens[map_index[i]]); |
|
| 1872 |
} |
|
| 1851 |
} |
|
| 1852 |
Node target = it->second; |
|
| 1853 |
|
|
| 1854 |
e = _graph.addEdge(source, target); |
|
| 1855 |
if (label_index != -1) |
|
| 1856 |
_edge_index.insert(std::make_pair(tokens[label_index], e)); |
|
| 1857 |
} else {
|
|
| 1858 |
if (label_index == -1) |
|
| 1859 |
throw DataFormatError("Label map not found in file");
|
|
| 1860 |
typename std::map<std::string, Edge>::iterator it = |
|
| 1861 |
_edge_index.find(tokens[label_index]); |
|
| 1862 |
if (it == _edge_index.end()) {
|
|
| 1863 |
std::ostringstream msg; |
|
| 1864 |
msg << "Edge with label not found: " << tokens[label_index]; |
|
| 1865 |
throw DataFormatError(msg.str().c_str()); |
|
| 1866 |
} |
|
| 1867 |
e = it->second; |
|
| 1868 |
} |
|
| 1869 |
|
|
| 1870 |
for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
|
|
| 1871 |
_edge_maps[i].second->set(e, tokens[map_index[i]]); |
|
| 1872 |
} |
|
| 1873 | 1873 |
|
| 1874 | 1874 |
} |
| 1875 | 1875 |
if (readSuccess()) {
|
| 1876 |
|
|
| 1876 |
line.putback(c); |
|
| 1877 | 1877 |
} |
| 1878 | 1878 |
} |
| 1879 | 1879 |
|
| 1880 | 1880 |
void readAttributes() {
|
| 1881 | 1881 |
|
| 1882 | 1882 |
std::set<std::string> read_attr; |
| 1883 | 1883 |
|
| 1884 | 1884 |
char c; |
| 1885 | 1885 |
while (readLine() && line >> c && c != '@') {
|
| 1886 |
line.putback(c); |
|
| 1887 |
|
|
| 1888 |
std::string attr, token; |
|
| 1889 |
if (!_reader_bits::readToken(line, attr)) |
|
| 1890 |
throw DataFormatError("Attribute name not found");
|
|
| 1891 |
if (!_reader_bits::readToken(line, token)) |
|
| 1892 |
throw DataFormatError("Attribute value not found");
|
|
| 1893 |
if (line >> c) |
|
| 1894 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1895 |
|
|
| 1896 |
{
|
|
| 1897 |
std::set<std::string>::iterator it = read_attr.find(attr); |
|
| 1898 |
if (it != read_attr.end()) {
|
|
| 1899 |
std::ostringstream msg; |
|
| 1900 |
msg << "Multiple occurence of attribute " << attr; |
|
| 1901 |
throw DataFormatError(msg.str().c_str()); |
|
| 1902 |
} |
|
| 1903 |
read_attr.insert(attr); |
|
| 1904 |
} |
|
| 1905 |
|
|
| 1906 |
{
|
|
| 1907 |
typename Attributes::iterator it = _attributes.lower_bound(attr); |
|
| 1908 |
while (it != _attributes.end() && it->first == attr) {
|
|
| 1909 |
it->second->set(token); |
|
| 1910 |
++it; |
|
| 1911 |
} |
|
| 1912 |
|
|
| 1886 |
line.putback(c); |
|
| 1887 |
|
|
| 1888 |
std::string attr, token; |
|
| 1889 |
if (!_reader_bits::readToken(line, attr)) |
|
| 1890 |
throw DataFormatError("Attribute name not found");
|
|
| 1891 |
if (!_reader_bits::readToken(line, token)) |
|
| 1892 |
throw DataFormatError("Attribute value not found");
|
|
| 1893 |
if (line >> c) |
|
| 1894 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1895 |
|
|
| 1896 |
{
|
|
| 1897 |
std::set<std::string>::iterator it = read_attr.find(attr); |
|
| 1898 |
if (it != read_attr.end()) {
|
|
| 1899 |
std::ostringstream msg; |
|
| 1900 |
msg << "Multiple occurence of attribute " << attr; |
|
| 1901 |
throw DataFormatError(msg.str().c_str()); |
|
| 1902 |
} |
|
| 1903 |
read_attr.insert(attr); |
|
| 1904 |
} |
|
| 1905 |
|
|
| 1906 |
{
|
|
| 1907 |
typename Attributes::iterator it = _attributes.lower_bound(attr); |
|
| 1908 |
while (it != _attributes.end() && it->first == attr) {
|
|
| 1909 |
it->second->set(token); |
|
| 1910 |
++it; |
|
| 1911 |
} |
|
| 1912 |
} |
|
| 1913 | 1913 |
|
| 1914 | 1914 |
} |
| 1915 | 1915 |
if (readSuccess()) {
|
| 1916 |
|
|
| 1916 |
line.putback(c); |
|
| 1917 | 1917 |
} |
| 1918 | 1918 |
for (typename Attributes::iterator it = _attributes.begin(); |
| 1919 |
it != _attributes.end(); ++it) {
|
|
| 1920 |
if (read_attr.find(it->first) == read_attr.end()) {
|
|
| 1921 |
std::ostringstream msg; |
|
| 1922 |
msg << "Attribute not found in file: " << it->first; |
|
| 1923 |
throw DataFormatError(msg.str().c_str()); |
|
| 1924 |
} |
|
| 1919 |
it != _attributes.end(); ++it) {
|
|
| 1920 |
if (read_attr.find(it->first) == read_attr.end()) {
|
|
| 1921 |
std::ostringstream msg; |
|
| 1922 |
msg << "Attribute not found in file: " << it->first; |
|
| 1923 |
throw DataFormatError(msg.str().c_str()); |
|
| 1924 |
} |
|
| 1925 | 1925 |
} |
| 1926 | 1926 |
} |
| 1927 | 1927 |
|
| 1928 | 1928 |
public: |
| 1929 | 1929 |
|
| 1930 |
/// \name Execution of the reader |
|
| 1930 |
/// \name Execution of the reader |
|
| 1931 | 1931 |
/// @{
|
| 1932 | 1932 |
|
| 1933 | 1933 |
/// \brief Start the batch processing |
| 1934 | 1934 |
/// |
| 1935 | 1935 |
/// This function starts the batch processing |
| 1936 | 1936 |
void run() {
|
| 1937 |
|
|
| 1937 |
|
|
| 1938 | 1938 |
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
| 1939 |
|
|
| 1939 |
|
|
| 1940 | 1940 |
bool nodes_done = _skip_nodes; |
| 1941 | 1941 |
bool edges_done = _skip_edges; |
| 1942 | 1942 |
bool attributes_done = false; |
| 1943 | 1943 |
|
| 1944 |
line_num = 0; |
|
| 1944 |
line_num = 0; |
|
| 1945 | 1945 |
readLine(); |
| 1946 | 1946 |
skipSection(); |
| 1947 | 1947 |
|
| 1948 | 1948 |
while (readSuccess()) {
|
| 1949 |
try {
|
|
| 1950 |
char c; |
|
| 1951 |
std::string section, caption; |
|
| 1952 |
line >> c; |
|
| 1953 |
_reader_bits::readToken(line, section); |
|
| 1954 |
_reader_bits::readToken(line, caption); |
|
| 1955 |
|
|
| 1956 |
if (line >> c) |
|
| 1957 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1958 |
|
|
| 1959 |
if (section == "nodes" && !nodes_done) {
|
|
| 1960 |
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
| 1961 |
readNodes(); |
|
| 1962 |
nodes_done = true; |
|
| 1963 |
} |
|
| 1964 |
} else if ((section == "edges" || section == "arcs") && |
|
| 1965 |
!edges_done) {
|
|
| 1966 |
if (_edges_caption.empty() || _edges_caption == caption) {
|
|
| 1967 |
readEdges(); |
|
| 1968 |
edges_done = true; |
|
| 1969 |
} |
|
| 1970 |
} else if (section == "attributes" && !attributes_done) {
|
|
| 1971 |
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
| 1972 |
readAttributes(); |
|
| 1973 |
attributes_done = true; |
|
| 1974 |
} |
|
| 1975 |
} else {
|
|
| 1976 |
readLine(); |
|
| 1977 |
skipSection(); |
|
| 1978 |
} |
|
| 1979 |
} catch (DataFormatError& error) {
|
|
| 1980 |
error.line(line_num); |
|
| 1981 |
throw; |
|
| 1982 |
} |
|
| 1949 |
try {
|
|
| 1950 |
char c; |
|
| 1951 |
std::string section, caption; |
|
| 1952 |
line >> c; |
|
| 1953 |
_reader_bits::readToken(line, section); |
|
| 1954 |
_reader_bits::readToken(line, caption); |
|
| 1955 |
|
|
| 1956 |
if (line >> c) |
|
| 1957 |
throw DataFormatError("Extra character on the end of line");
|
|
| 1958 |
|
|
| 1959 |
if (section == "nodes" && !nodes_done) {
|
|
| 1960 |
if (_nodes_caption.empty() || _nodes_caption == caption) {
|
|
| 1961 |
readNodes(); |
|
| 1962 |
nodes_done = true; |
|
| 1963 |
} |
|
| 1964 |
} else if ((section == "edges" || section == "arcs") && |
|
| 1965 |
!edges_done) {
|
|
| 1966 |
if (_edges_caption.empty() || _edges_caption == caption) {
|
|
| 1967 |
readEdges(); |
|
| 1968 |
edges_done = true; |
|
| 1969 |
} |
|
| 1970 |
} else if (section == "attributes" && !attributes_done) {
|
|
| 1971 |
if (_attributes_caption.empty() || _attributes_caption == caption) {
|
|
| 1972 |
readAttributes(); |
|
| 1973 |
attributes_done = true; |
|
| 1974 |
} |
|
| 1975 |
} else {
|
|
| 1976 |
readLine(); |
|
| 1977 |
skipSection(); |
|
| 1978 |
} |
|
| 1979 |
} catch (DataFormatError& error) {
|
|
| 1980 |
error.line(line_num); |
|
| 1981 |
throw; |
|
| 1982 |
} |
|
| 1983 | 1983 |
} |
| 1984 | 1984 |
|
| 1985 | 1985 |
if (!nodes_done) {
|
| 1986 |
|
|
| 1986 |
throw DataFormatError("Section @nodes not found");
|
|
| 1987 | 1987 |
} |
| 1988 | 1988 |
|
| 1989 | 1989 |
if (!edges_done) {
|
| 1990 |
|
|
| 1990 |
throw DataFormatError("Section @edges not found");
|
|
| 1991 | 1991 |
} |
| 1992 | 1992 |
|
| 1993 | 1993 |
if (!attributes_done && !_attributes.empty()) {
|
| 1994 |
|
|
| 1994 |
throw DataFormatError("Section @attributes not found");
|
|
| 1995 | 1995 |
} |
| 1996 | 1996 |
|
| 1997 | 1997 |
} |
| 1998 | 1998 |
|
| 1999 | 1999 |
/// @} |
| 2000 |
|
|
| 2000 |
|
|
| 2001 | 2001 |
}; |
| 2002 | 2002 |
|
| 2003 | 2003 |
/// \brief Return a \ref GraphReader class |
| 2004 |
/// |
|
| 2004 |
/// |
|
| 2005 | 2005 |
/// This function just returns a \ref GraphReader class. |
| 2006 | 2006 |
/// \relates GraphReader |
| 2007 | 2007 |
template <typename Graph> |
| 2008 | 2008 |
GraphReader<Graph> graphReader(std::istream& is, Graph& graph) {
|
| 2009 | 2009 |
GraphReader<Graph> tmp(is, graph); |
| 2010 | 2010 |
return tmp; |
| 2011 | 2011 |
} |
| 2012 | 2012 |
|
| 2013 | 2013 |
/// \brief Return a \ref GraphReader class |
| 2014 |
/// |
|
| 2014 |
/// |
|
| 2015 | 2015 |
/// This function just returns a \ref GraphReader class. |
| 2016 | 2016 |
/// \relates GraphReader |
| 2017 | 2017 |
template <typename Graph> |
| 2018 |
GraphReader<Graph> graphReader(const std::string& fn, |
|
| 2019 |
Graph& graph) {
|
|
| 2018 |
GraphReader<Graph> graphReader(const std::string& fn, |
|
| 2019 |
Graph& graph) {
|
|
| 2020 | 2020 |
GraphReader<Graph> tmp(fn, graph); |
| 2021 | 2021 |
return tmp; |
| 2022 | 2022 |
} |
| 2023 | 2023 |
|
| 2024 | 2024 |
/// \brief Return a \ref GraphReader class |
| 2025 |
/// |
|
| 2025 |
/// |
|
| 2026 | 2026 |
/// This function just returns a \ref GraphReader class. |
| 2027 | 2027 |
/// \relates GraphReader |
| 2028 | 2028 |
template <typename Graph> |
| 2029 | 2029 |
GraphReader<Graph> graphReader(const char* fn, Graph& graph) {
|
| 2030 | 2030 |
GraphReader<Graph> tmp(fn, graph); |
| 2031 | 2031 |
return tmp; |
| 2032 | 2032 |
} |
| 2033 | 2033 |
|
| 2034 | 2034 |
class SectionReader; |
| 2035 | 2035 |
|
| 2036 | 2036 |
SectionReader sectionReader(std::istream& is); |
| 2037 | 2037 |
SectionReader sectionReader(const std::string& fn); |
| 2038 | 2038 |
SectionReader sectionReader(const char* fn); |
| 2039 |
|
|
| 2039 |
|
|
| 2040 | 2040 |
/// \ingroup lemon_io |
| 2041 | 2041 |
/// |
| 2042 | 2042 |
/// \brief Section reader class |
| 2043 | 2043 |
/// |
| 2044 |
/// In the \ref lgf-format "LGF" file extra sections can be placed, |
|
| 2044 |
/// In the \ref lgf-format "LGF" file extra sections can be placed, |
|
| 2045 | 2045 |
/// which contain any data in arbitrary format. Such sections can be |
| 2046 |
/// read with this class. A reading rule can be added to the class |
|
| 2046 |
/// read with this class. A reading rule can be added to the class |
|
| 2047 | 2047 |
/// with two different functions. With the \c sectionLines() function a |
| 2048 | 2048 |
/// functor can process the section line-by-line, while with the \c |
| 2049 | 2049 |
/// sectionStream() member the section can be read from an input |
| 2050 | 2050 |
/// stream. |
| 2051 | 2051 |
class SectionReader {
|
| 2052 | 2052 |
private: |
| 2053 |
|
|
| 2053 |
|
|
| 2054 | 2054 |
std::istream* _is; |
| 2055 | 2055 |
bool local_is; |
| 2056 | 2056 |
|
| 2057 | 2057 |
typedef std::map<std::string, _reader_bits::Section*> Sections; |
| 2058 | 2058 |
Sections _sections; |
| 2059 | 2059 |
|
| 2060 | 2060 |
int line_num; |
| 2061 | 2061 |
std::istringstream line; |
| 2062 | 2062 |
|
| 2063 | 2063 |
public: |
| 2064 | 2064 |
|
| 2065 | 2065 |
/// \brief Constructor |
| 2066 | 2066 |
/// |
| 2067 | 2067 |
/// Construct a section reader, which reads from the given input |
| 2068 | 2068 |
/// stream. |
| 2069 |
SectionReader(std::istream& is) |
|
| 2069 |
SectionReader(std::istream& is) |
|
| 2070 | 2070 |
: _is(&is), local_is(false) {}
|
| 2071 | 2071 |
|
| 2072 | 2072 |
/// \brief Constructor |
| 2073 | 2073 |
/// |
| 2074 | 2074 |
/// Construct a section reader, which reads from the given file. |
| 2075 |
SectionReader(const std::string& fn) |
|
| 2075 |
SectionReader(const std::string& fn) |
|
| 2076 | 2076 |
: _is(new std::ifstream(fn.c_str())), local_is(true) {}
|
| 2077 |
|
|
| 2077 |
|
|
| 2078 | 2078 |
/// \brief Constructor |
| 2079 | 2079 |
/// |
| 2080 | 2080 |
/// Construct a section reader, which reads from the given file. |
| 2081 |
SectionReader(const char* fn) |
|
| 2081 |
SectionReader(const char* fn) |
|
| 2082 | 2082 |
: _is(new std::ifstream(fn)), local_is(true) {}
|
| 2083 | 2083 |
|
| 2084 | 2084 |
/// \brief Destructor |
| 2085 | 2085 |
~SectionReader() {
|
| 2086 |
for (Sections::iterator it = _sections.begin(); |
|
| 2087 |
it != _sections.end(); ++it) {
|
|
| 2088 |
|
|
| 2086 |
for (Sections::iterator it = _sections.begin(); |
|
| 2087 |
it != _sections.end(); ++it) {
|
|
| 2088 |
delete it->second; |
|
| 2089 | 2089 |
} |
| 2090 | 2090 |
|
| 2091 | 2091 |
if (local_is) {
|
| 2092 |
|
|
| 2092 |
delete _is; |
|
| 2093 | 2093 |
} |
| 2094 | 2094 |
|
| 2095 | 2095 |
} |
| 2096 | 2096 |
|
| 2097 | 2097 |
private: |
| 2098 | 2098 |
|
| 2099 | 2099 |
friend SectionReader sectionReader(std::istream& is); |
| 2100 | 2100 |
friend SectionReader sectionReader(const std::string& fn); |
| 2101 | 2101 |
friend SectionReader sectionReader(const char* fn); |
| 2102 | 2102 |
|
| 2103 |
SectionReader(SectionReader& other) |
|
| 2103 |
SectionReader(SectionReader& other) |
|
| 2104 | 2104 |
: _is(other._is), local_is(other.local_is) {
|
| 2105 | 2105 |
|
| 2106 | 2106 |
other._is = 0; |
| 2107 | 2107 |
other.local_is = false; |
| 2108 |
|
|
| 2108 |
|
|
| 2109 | 2109 |
_sections.swap(other._sections); |
| 2110 | 2110 |
} |
| 2111 |
|
|
| 2111 |
|
|
| 2112 | 2112 |
SectionReader& operator=(const SectionReader&); |
| 2113 | 2113 |
|
| 2114 | 2114 |
public: |
| 2115 | 2115 |
|
| 2116 | 2116 |
/// \name Section readers |
| 2117 | 2117 |
/// @{
|
| 2118 | 2118 |
|
| 2119 | 2119 |
/// \brief Add a section processor with line oriented reading |
| 2120 | 2120 |
/// |
| 2121 | 2121 |
/// The first parameter is the type descriptor of the section, the |
| 2122 | 2122 |
/// second is a functor, which takes just one \c std::string |
| 2123 | 2123 |
/// parameter. At the reading process, each line of the section |
| 2124 | 2124 |
/// will be given to the functor object. However, the empty lines |
| 2125 | 2125 |
/// and the comment lines are filtered out, and the leading |
| 2126 | 2126 |
/// whitespaces are trimmed from each processed string. |
| 2127 | 2127 |
/// |
| ... | ... |
@@ -2135,481 +2135,481 @@ |
| 2135 | 2135 |
///\endcode |
| 2136 | 2136 |
/// |
| 2137 | 2137 |
/// The functor is implemented as a struct: |
| 2138 | 2138 |
///\code |
| 2139 | 2139 |
/// struct NumberSection {
|
| 2140 | 2140 |
/// std::vector<int>& _data; |
| 2141 | 2141 |
/// NumberSection(std::vector<int>& data) : _data(data) {}
|
| 2142 | 2142 |
/// void operator()(const std::string& line) {
|
| 2143 | 2143 |
/// std::istringstream ls(line); |
| 2144 | 2144 |
/// int value; |
| 2145 | 2145 |
/// while (ls >> value) _data.push_back(value); |
| 2146 | 2146 |
/// } |
| 2147 | 2147 |
/// }; |
| 2148 | 2148 |
/// |
| 2149 | 2149 |
/// // ... |
| 2150 | 2150 |
/// |
| 2151 |
/// reader.sectionLines("numbers", NumberSection(vec));
|
|
| 2151 |
/// reader.sectionLines("numbers", NumberSection(vec));
|
|
| 2152 | 2152 |
///\endcode |
| 2153 | 2153 |
template <typename Functor> |
| 2154 | 2154 |
SectionReader& sectionLines(const std::string& type, Functor functor) {
|
| 2155 | 2155 |
LEMON_ASSERT(!type.empty(), "Type is empty."); |
| 2156 |
LEMON_ASSERT(_sections.find(type) == _sections.end(), |
|
| 2157 |
"Multiple reading of section."); |
|
| 2158 |
_sections. |
|
| 2156 |
LEMON_ASSERT(_sections.find(type) == _sections.end(), |
|
| 2157 |
"Multiple reading of section."); |
|
| 2158 |
_sections.insert(std::make_pair(type, |
|
| 2159 | 2159 |
new _reader_bits::LineSection<Functor>(functor))); |
| 2160 | 2160 |
return *this; |
| 2161 | 2161 |
} |
| 2162 | 2162 |
|
| 2163 | 2163 |
|
| 2164 | 2164 |
/// \brief Add a section processor with stream oriented reading |
| 2165 | 2165 |
/// |
| 2166 | 2166 |
/// The first parameter is the type of the section, the second is |
| 2167 | 2167 |
/// a functor, which takes an \c std::istream& and an \c int& |
| 2168 | 2168 |
/// parameter, the latter regard to the line number of stream. The |
| 2169 | 2169 |
/// functor can read the input while the section go on, and the |
| 2170 | 2170 |
/// line number should be modified accordingly. |
| 2171 | 2171 |
template <typename Functor> |
| 2172 | 2172 |
SectionReader& sectionStream(const std::string& type, Functor functor) {
|
| 2173 | 2173 |
LEMON_ASSERT(!type.empty(), "Type is empty."); |
| 2174 |
LEMON_ASSERT(_sections.find(type) == _sections.end(), |
|
| 2175 |
"Multiple reading of section."); |
|
| 2176 |
_sections.insert(std::make_pair(type, |
|
| 2177 |
new _reader_bits::StreamSection<Functor>(functor))); |
|
| 2174 |
LEMON_ASSERT(_sections.find(type) == _sections.end(), |
|
| 2175 |
"Multiple reading of section."); |
|
| 2176 |
_sections.insert(std::make_pair(type, |
|
| 2177 |
new _reader_bits::StreamSection<Functor>(functor))); |
|
| 2178 | 2178 |
return *this; |
| 2179 |
} |
|
| 2180 |
|
|
| 2179 |
} |
|
| 2180 |
|
|
| 2181 | 2181 |
/// @} |
| 2182 | 2182 |
|
| 2183 | 2183 |
private: |
| 2184 | 2184 |
|
| 2185 | 2185 |
bool readLine() {
|
| 2186 | 2186 |
std::string str; |
| 2187 | 2187 |
while(++line_num, std::getline(*_is, str)) {
|
| 2188 |
line.clear(); line.str(str); |
|
| 2189 |
char c; |
|
| 2190 |
if (line >> std::ws >> c && c != '#') {
|
|
| 2191 |
line.putback(c); |
|
| 2192 |
return true; |
|
| 2193 |
} |
|
| 2188 |
line.clear(); line.str(str); |
|
| 2189 |
char c; |
|
| 2190 |
if (line >> std::ws >> c && c != '#') {
|
|
| 2191 |
line.putback(c); |
|
| 2192 |
return true; |
|
| 2193 |
} |
|
| 2194 | 2194 |
} |
| 2195 | 2195 |
return false; |
| 2196 | 2196 |
} |
| 2197 | 2197 |
|
| 2198 | 2198 |
bool readSuccess() {
|
| 2199 | 2199 |
return static_cast<bool>(*_is); |
| 2200 | 2200 |
} |
| 2201 |
|
|
| 2201 |
|
|
| 2202 | 2202 |
void skipSection() {
|
| 2203 | 2203 |
char c; |
| 2204 | 2204 |
while (readSuccess() && line >> c && c != '@') {
|
| 2205 |
|
|
| 2205 |
readLine(); |
|
| 2206 | 2206 |
} |
| 2207 | 2207 |
line.putback(c); |
| 2208 | 2208 |
} |
| 2209 | 2209 |
|
| 2210 | 2210 |
public: |
| 2211 | 2211 |
|
| 2212 | 2212 |
|
| 2213 |
/// \name Execution of the reader |
|
| 2213 |
/// \name Execution of the reader |
|
| 2214 | 2214 |
/// @{
|
| 2215 | 2215 |
|
| 2216 | 2216 |
/// \brief Start the batch processing |
| 2217 | 2217 |
/// |
| 2218 | 2218 |
/// This function starts the batch processing. |
| 2219 | 2219 |
void run() {
|
| 2220 |
|
|
| 2220 |
|
|
| 2221 | 2221 |
LEMON_ASSERT(_is != 0, "This reader assigned to an other reader"); |
| 2222 |
|
|
| 2222 |
|
|
| 2223 | 2223 |
std::set<std::string> extra_sections; |
| 2224 | 2224 |
|
| 2225 |
line_num = 0; |
|
| 2225 |
line_num = 0; |
|
| 2226 | 2226 |
readLine(); |
| 2227 | 2227 |
skipSection(); |
| 2228 | 2228 |
|
| 2229 | 2229 |
while (readSuccess()) {
|
| 2230 |
try {
|
|
| 2231 |
char c; |
|
| 2232 |
std::string section, caption; |
|
| 2233 |
line >> c; |
|
| 2234 |
_reader_bits::readToken(line, section); |
|
| 2235 |
_reader_bits::readToken(line, caption); |
|
| 2236 |
|
|
| 2237 |
if (line >> c) |
|
| 2238 |
throw DataFormatError("Extra character on the end of line");
|
|
| 2239 |
|
|
| 2240 |
if (extra_sections.find(section) != extra_sections.end()) {
|
|
| 2241 |
std::ostringstream msg; |
|
| 2242 |
msg << "Multiple occurence of section " << section; |
|
| 2243 |
throw DataFormatError(msg.str().c_str()); |
|
| 2244 |
} |
|
| 2245 |
Sections::iterator it = _sections.find(section); |
|
| 2246 |
if (it != _sections.end()) {
|
|
| 2247 |
extra_sections.insert(section); |
|
| 2248 |
it->second->process(*_is, line_num); |
|
| 2249 |
} |
|
| 2250 |
readLine(); |
|
| 2251 |
skipSection(); |
|
| 2252 |
} catch (DataFormatError& error) {
|
|
| 2253 |
error.line(line_num); |
|
| 2254 |
throw; |
|
| 2255 |
} |
|
| 2230 |
try {
|
|
| 2231 |
char c; |
|
| 2232 |
std::string section, caption; |
|
| 2233 |
line >> c; |
|
| 2234 |
_reader_bits::readToken(line, section); |
|
| 2235 |
_reader_bits::readToken(line, caption); |
|
| 2236 |
|
|
| 2237 |
if (line >> c) |
|
| 2238 |
throw DataFormatError("Extra character on the end of line");
|
|
| 2239 |
|
|
| 2240 |
if (extra_sections.find(section) != extra_sections.end()) {
|
|
| 2241 |
std::ostringstream msg; |
|
| 2242 |
msg << "Multiple occurence of section " << section; |
|
| 2243 |
throw DataFormatError(msg.str().c_str()); |
|
| 2244 |
} |
|
| 2245 |
Sections::iterator it = _sections.find(section); |
|
| 2246 |
if (it != _sections.end()) {
|
|
| 2247 |
extra_sections.insert(section); |
|
| 2248 |
it->second->process(*_is, line_num); |
|
| 2249 |
} |
|
| 2250 |
readLine(); |
|
| 2251 |
skipSection(); |
|
| 2252 |
} catch (DataFormatError& error) {
|
|
| 2253 |
error.line(line_num); |
|
| 2254 |
throw; |
|
| 2255 |
} |
|
| 2256 | 2256 |
} |
| 2257 | 2257 |
for (Sections::iterator it = _sections.begin(); |
| 2258 |
it != _sections.end(); ++it) {
|
|
| 2259 |
if (extra_sections.find(it->first) == extra_sections.end()) {
|
|
| 2260 |
std::ostringstream os; |
|
| 2261 |
os << "Cannot find section: " << it->first; |
|
| 2262 |
throw DataFormatError(os.str().c_str()); |
|
| 2263 |
} |
|
| 2258 |
it != _sections.end(); ++it) {
|
|
| 2259 |
if (extra_sections.find(it->first) == extra_sections.end()) {
|
|
| 2260 |
std::ostringstream os; |
|
| 2261 |
os << "Cannot find section: " << it->first; |
|
| 2262 |
throw DataFormatError(os.str().c_str()); |
|
| 2263 |
} |
|
| 2264 | 2264 |
} |
| 2265 | 2265 |
} |
| 2266 | 2266 |
|
| 2267 | 2267 |
/// @} |
| 2268 |
|
|
| 2268 |
|
|
| 2269 | 2269 |
}; |
| 2270 | 2270 |
|
| 2271 | 2271 |
/// \brief Return a \ref SectionReader class |
| 2272 |
/// |
|
| 2272 |
/// |
|
| 2273 | 2273 |
/// This function just returns a \ref SectionReader class. |
| 2274 | 2274 |
/// \relates SectionReader |
| 2275 | 2275 |
inline SectionReader sectionReader(std::istream& is) {
|
| 2276 | 2276 |
SectionReader tmp(is); |
| 2277 | 2277 |
return tmp; |
| 2278 | 2278 |
} |
| 2279 | 2279 |
|
| 2280 | 2280 |
/// \brief Return a \ref SectionReader class |
| 2281 |
/// |
|
| 2281 |
/// |
|
| 2282 | 2282 |
/// This function just returns a \ref SectionReader class. |
| 2283 | 2283 |
/// \relates SectionReader |
| 2284 | 2284 |
inline SectionReader sectionReader(const std::string& fn) {
|
| 2285 | 2285 |
SectionReader tmp(fn); |
| 2286 | 2286 |
return tmp; |
| 2287 | 2287 |
} |
| 2288 | 2288 |
|
| 2289 | 2289 |
/// \brief Return a \ref SectionReader class |
| 2290 |
/// |
|
| 2290 |
/// |
|
| 2291 | 2291 |
/// This function just returns a \ref SectionReader class. |
| 2292 | 2292 |
/// \relates SectionReader |
| 2293 | 2293 |
inline SectionReader sectionReader(const char* fn) {
|
| 2294 | 2294 |
SectionReader tmp(fn); |
| 2295 | 2295 |
return tmp; |
| 2296 | 2296 |
} |
| 2297 | 2297 |
|
| 2298 | 2298 |
/// \ingroup lemon_io |
| 2299 | 2299 |
/// |
| 2300 |
/// \brief Reader for the contents of the \ref lgf-format "LGF" file |
|
| 2300 |
/// \brief Reader for the contents of the \ref lgf-format "LGF" file |
|
| 2301 | 2301 |
/// |
| 2302 | 2302 |
/// This class can be used to read the sections, the map names and |
| 2303 | 2303 |
/// the attributes from a file. Usually, the Lemon programs know |
| 2304 | 2304 |
/// that, which type of graph, which maps and which attributes |
| 2305 | 2305 |
/// should be read from a file, but in general tools (like glemon) |
| 2306 | 2306 |
/// the contents of an LGF file should be guessed somehow. This class |
| 2307 | 2307 |
/// reads the graph and stores the appropriate information for |
| 2308 | 2308 |
/// reading the graph. |
| 2309 | 2309 |
/// |
| 2310 |
///\code |
|
| 2311 |
/// LgfContents contents("graph.lgf");
|
|
| 2310 |
///\code |
|
| 2311 |
/// LgfContents contents("graph.lgf");
|
|
| 2312 | 2312 |
/// contents.run(); |
| 2313 | 2313 |
/// |
| 2314 | 2314 |
/// // Does it contain any node section and arc section? |
| 2315 | 2315 |
/// if (contents.nodeSectionNum() == 0 || contents.arcSectionNum()) {
|
| 2316 | 2316 |
/// std::cerr << "Failure, cannot find graph." << std::endl; |
| 2317 | 2317 |
/// return -1; |
| 2318 | 2318 |
/// } |
| 2319 |
/// std::cout << "The name of the default node section: " |
|
| 2319 |
/// std::cout << "The name of the default node section: " |
|
| 2320 | 2320 |
/// << contents.nodeSection(0) << std::endl; |
| 2321 |
/// std::cout << "The number of the arc maps: " |
|
| 2321 |
/// std::cout << "The number of the arc maps: " |
|
| 2322 | 2322 |
/// << contents.arcMaps(0).size() << std::endl; |
| 2323 |
/// std::cout << "The name of second arc map: " |
|
| 2323 |
/// std::cout << "The name of second arc map: " |
|
| 2324 | 2324 |
/// << contents.arcMaps(0)[1] << std::endl; |
| 2325 | 2325 |
///\endcode |
| 2326 |
class LgfContents {
|
|
| 2326 |
class LgfContents {
|
|
| 2327 | 2327 |
private: |
| 2328 | 2328 |
|
| 2329 | 2329 |
std::istream* _is; |
| 2330 | 2330 |
bool local_is; |
| 2331 | 2331 |
|
| 2332 | 2332 |
std::vector<std::string> _node_sections; |
| 2333 | 2333 |
std::vector<std::string> _edge_sections; |
| 2334 | 2334 |
std::vector<std::string> _attribute_sections; |
| 2335 | 2335 |
std::vector<std::string> _extra_sections; |
| 2336 | 2336 |
|
| 2337 | 2337 |
std::vector<bool> _arc_sections; |
| 2338 | 2338 |
|
| 2339 | 2339 |
std::vector<std::vector<std::string> > _node_maps; |
| 2340 | 2340 |
std::vector<std::vector<std::string> > _edge_maps; |
| 2341 | 2341 |
|
| 2342 | 2342 |
std::vector<std::vector<std::string> > _attributes; |
| 2343 | 2343 |
|
| 2344 | 2344 |
|
| 2345 | 2345 |
int line_num; |
| 2346 | 2346 |
std::istringstream line; |
| 2347 |
|
|
| 2347 |
|
|
| 2348 | 2348 |
public: |
| 2349 | 2349 |
|
| 2350 | 2350 |
/// \brief Constructor |
| 2351 | 2351 |
/// |
| 2352 | 2352 |
/// Construct an \e LGF contents reader, which reads from the given |
| 2353 | 2353 |
/// input stream. |
| 2354 |
LgfContents(std::istream& is) |
|
| 2354 |
LgfContents(std::istream& is) |
|
| 2355 | 2355 |
: _is(&is), local_is(false) {}
|
| 2356 | 2356 |
|
| 2357 | 2357 |
/// \brief Constructor |
| 2358 | 2358 |
/// |
| 2359 | 2359 |
/// Construct an \e LGF contents reader, which reads from the given |
| 2360 | 2360 |
/// file. |
| 2361 |
LgfContents(const std::string& fn) |
|
| 2361 |
LgfContents(const std::string& fn) |
|
| 2362 | 2362 |
: _is(new std::ifstream(fn.c_str())), local_is(true) {}
|
| 2363 | 2363 |
|
| 2364 | 2364 |
/// \brief Constructor |
| 2365 | 2365 |
/// |
| 2366 | 2366 |
/// Construct an \e LGF contents reader, which reads from the given |
| 2367 | 2367 |
/// file. |
| 2368 | 2368 |
LgfContents(const char* fn) |
| 2369 | 2369 |
: _is(new std::ifstream(fn)), local_is(true) {}
|
| 2370 |
|
|
| 2370 |
|
|
| 2371 | 2371 |
/// \brief Destructor |
| 2372 | 2372 |
~LgfContents() {
|
| 2373 | 2373 |
if (local_is) delete _is; |
| 2374 | 2374 |
} |
| 2375 | 2375 |
|
| 2376 | 2376 |
private: |
| 2377 |
|
|
| 2377 |
|
|
| 2378 | 2378 |
LgfContents(const LgfContents&); |
| 2379 | 2379 |
LgfContents& operator=(const LgfContents&); |
| 2380 | 2380 |
|
| 2381 | 2381 |
public: |
| 2382 | 2382 |
|
| 2383 | 2383 |
|
| 2384 | 2384 |
/// \name Node sections |
| 2385 | 2385 |
/// @{
|
| 2386 | 2386 |
|
| 2387 | 2387 |
/// \brief Gives back the number of node sections in the file. |
| 2388 | 2388 |
/// |
| 2389 | 2389 |
/// Gives back the number of node sections in the file. |
| 2390 | 2390 |
int nodeSectionNum() const {
|
| 2391 | 2391 |
return _node_sections.size(); |
| 2392 | 2392 |
} |
| 2393 | 2393 |
|
| 2394 |
/// \brief Returns the node section name at the given position. |
|
| 2394 |
/// \brief Returns the node section name at the given position. |
|
| 2395 | 2395 |
/// |
| 2396 |
/// Returns the node section name at the given position. |
|
| 2396 |
/// Returns the node section name at the given position. |
|
| 2397 | 2397 |
const std::string& nodeSection(int i) const {
|
| 2398 | 2398 |
return _node_sections[i]; |
| 2399 | 2399 |
} |
| 2400 | 2400 |
|
| 2401 | 2401 |
/// \brief Gives back the node maps for the given section. |
| 2402 | 2402 |
/// |
| 2403 | 2403 |
/// Gives back the node maps for the given section. |
| 2404 | 2404 |
const std::vector<std::string>& nodeMapNames(int i) const {
|
| 2405 | 2405 |
return _node_maps[i]; |
| 2406 | 2406 |
} |
| 2407 | 2407 |
|
| 2408 | 2408 |
/// @} |
| 2409 | 2409 |
|
| 2410 |
/// \name Arc/Edge sections |
|
| 2410 |
/// \name Arc/Edge sections |
|
| 2411 | 2411 |
/// @{
|
| 2412 | 2412 |
|
| 2413 | 2413 |
/// \brief Gives back the number of arc/edge sections in the file. |
| 2414 | 2414 |
/// |
| 2415 | 2415 |
/// Gives back the number of arc/edge sections in the file. |
| 2416 | 2416 |
/// \note It is synonym of \c edgeSectionNum(). |
| 2417 | 2417 |
int arcSectionNum() const {
|
| 2418 | 2418 |
return _edge_sections.size(); |
| 2419 | 2419 |
} |
| 2420 | 2420 |
|
| 2421 |
/// \brief Returns the arc/edge section name at the given position. |
|
| 2421 |
/// \brief Returns the arc/edge section name at the given position. |
|
| 2422 | 2422 |
/// |
| 2423 |
/// Returns the arc/edge section name at the given position. |
|
| 2423 |
/// Returns the arc/edge section name at the given position. |
|
| 2424 | 2424 |
/// \note It is synonym of \c edgeSection(). |
| 2425 | 2425 |
const std::string& arcSection(int i) const {
|
| 2426 | 2426 |
return _edge_sections[i]; |
| 2427 | 2427 |
} |
| 2428 | 2428 |
|
| 2429 | 2429 |
/// \brief Gives back the arc/edge maps for the given section. |
| 2430 | 2430 |
/// |
| 2431 | 2431 |
/// Gives back the arc/edge maps for the given section. |
| 2432 | 2432 |
/// \note It is synonym of \c edgeMapNames(). |
| 2433 | 2433 |
const std::vector<std::string>& arcMapNames(int i) const {
|
| 2434 | 2434 |
return _edge_maps[i]; |
| 2435 | 2435 |
} |
| 2436 | 2436 |
|
| 2437 | 2437 |
/// @} |
| 2438 | 2438 |
|
| 2439 | 2439 |
/// \name Synonyms |
| 2440 | 2440 |
/// @{
|
| 2441 | 2441 |
|
| 2442 | 2442 |
/// \brief Gives back the number of arc/edge sections in the file. |
| 2443 | 2443 |
/// |
| 2444 | 2444 |
/// Gives back the number of arc/edge sections in the file. |
| 2445 | 2445 |
/// \note It is synonym of \c arcSectionNum(). |
| 2446 | 2446 |
int edgeSectionNum() const {
|
| 2447 | 2447 |
return _edge_sections.size(); |
| 2448 | 2448 |
} |
| 2449 | 2449 |
|
| 2450 |
/// \brief Returns the section name at the given position. |
|
| 2450 |
/// \brief Returns the section name at the given position. |
|
| 2451 | 2451 |
/// |
| 2452 |
/// Returns the section name at the given position. |
|
| 2452 |
/// Returns the section name at the given position. |
|
| 2453 | 2453 |
/// \note It is synonym of \c arcSection(). |
| 2454 | 2454 |
const std::string& edgeSection(int i) const {
|
| 2455 | 2455 |
return _edge_sections[i]; |
| 2456 | 2456 |
} |
| 2457 | 2457 |
|
| 2458 | 2458 |
/// \brief Gives back the edge maps for the given section. |
| 2459 | 2459 |
/// |
| 2460 | 2460 |
/// Gives back the edge maps for the given section. |
| 2461 | 2461 |
/// \note It is synonym of \c arcMapNames(). |
| 2462 | 2462 |
const std::vector<std::string>& edgeMapNames(int i) const {
|
| 2463 | 2463 |
return _edge_maps[i]; |
| 2464 | 2464 |
} |
| 2465 | 2465 |
|
| 2466 | 2466 |
/// @} |
| 2467 | 2467 |
|
| 2468 |
/// \name Attribute sections |
|
| 2468 |
/// \name Attribute sections |
|
| 2469 | 2469 |
/// @{
|
| 2470 | 2470 |
|
| 2471 | 2471 |
/// \brief Gives back the number of attribute sections in the file. |
| 2472 | 2472 |
/// |
| 2473 | 2473 |
/// Gives back the number of attribute sections in the file. |
| 2474 | 2474 |
int attributeSectionNum() const {
|
| 2475 | 2475 |
return _attribute_sections.size(); |
| 2476 | 2476 |
} |
| 2477 | 2477 |
|
| 2478 |
/// \brief Returns the attribute section name at the given position. |
|
| 2478 |
/// \brief Returns the attribute section name at the given position. |
|
| 2479 | 2479 |
/// |
| 2480 |
/// Returns the attribute section name at the given position. |
|
| 2480 |
/// Returns the attribute section name at the given position. |
|
| 2481 | 2481 |
const std::string& attributeSectionNames(int i) const {
|
| 2482 | 2482 |
return _attribute_sections[i]; |
| 2483 | 2483 |
} |
| 2484 | 2484 |
|
| 2485 | 2485 |
/// \brief Gives back the attributes for the given section. |
| 2486 | 2486 |
/// |
| 2487 | 2487 |
/// Gives back the attributes for the given section. |
| 2488 | 2488 |
const std::vector<std::string>& attributes(int i) const {
|
| 2489 | 2489 |
return _attributes[i]; |
| 2490 | 2490 |
} |
| 2491 | 2491 |
|
| 2492 | 2492 |
/// @} |
| 2493 | 2493 |
|
| 2494 |
/// \name Extra sections |
|
| 2494 |
/// \name Extra sections |
|
| 2495 | 2495 |
/// @{
|
| 2496 | 2496 |
|
| 2497 | 2497 |
/// \brief Gives back the number of extra sections in the file. |
| 2498 | 2498 |
/// |
| 2499 | 2499 |
/// Gives back the number of extra sections in the file. |
| 2500 | 2500 |
int extraSectionNum() const {
|
| 2501 | 2501 |
return _extra_sections.size(); |
| 2502 | 2502 |
} |
| 2503 | 2503 |
|
| 2504 |
/// \brief Returns the extra section type at the given position. |
|
| 2504 |
/// \brief Returns the extra section type at the given position. |
|
| 2505 | 2505 |
/// |
| 2506 |
/// Returns the section type at the given position. |
|
| 2506 |
/// Returns the section type at the given position. |
|
| 2507 | 2507 |
const std::string& extraSection(int i) const {
|
| 2508 | 2508 |
return _extra_sections[i]; |
| 2509 | 2509 |
} |
| 2510 | 2510 |
|
| 2511 | 2511 |
/// @} |
| 2512 | 2512 |
|
| 2513 | 2513 |
private: |
| 2514 | 2514 |
|
| 2515 | 2515 |
bool readLine() {
|
| 2516 | 2516 |
std::string str; |
| 2517 | 2517 |
while(++line_num, std::getline(*_is, str)) {
|
| 2518 |
line.clear(); line.str(str); |
|
| 2519 |
char c; |
|
| 2520 |
if (line >> std::ws >> c && c != '#') {
|
|
| 2521 |
line.putback(c); |
|
| 2522 |
return true; |
|
| 2523 |
} |
|
| 2518 |
line.clear(); line.str(str); |
|
| 2519 |
char c; |
|
| 2520 |
if (line >> std::ws >> c && c != '#') {
|
|
| 2521 |
line.putback(c); |
|
| 2522 |
return true; |
|
| 2523 |
} |
|
| 2524 | 2524 |
} |
| 2525 | 2525 |
return false; |
| 2526 | 2526 |
} |
| 2527 | 2527 |
|
| 2528 | 2528 |
bool readSuccess() {
|
| 2529 | 2529 |
return static_cast<bool>(*_is); |
| 2530 | 2530 |
} |
| 2531 | 2531 |
|
| 2532 | 2532 |
void skipSection() {
|
| 2533 | 2533 |
char c; |
| 2534 | 2534 |
while (readSuccess() && line >> c && c != '@') {
|
| 2535 |
|
|
| 2535 |
readLine(); |
|
| 2536 | 2536 |
} |
| 2537 | 2537 |
line.putback(c); |
| 2538 | 2538 |
} |
| 2539 | 2539 |
|
| 2540 | 2540 |
void readMaps(std::vector<std::string>& maps) {
|
| 2541 | 2541 |
char c; |
| 2542 | 2542 |
if (!readLine() || !(line >> c) || c == '@') {
|
| 2543 |
if (readSuccess() && line) line.putback(c); |
|
| 2544 |
return; |
|
| 2543 |
if (readSuccess() && line) line.putback(c); |
|
| 2544 |
return; |
|
| 2545 | 2545 |
} |
| 2546 | 2546 |
line.putback(c); |
| 2547 | 2547 |
std::string map; |
| 2548 | 2548 |
while (_reader_bits::readToken(line, map)) {
|
| 2549 |
|
|
| 2549 |
maps.push_back(map); |
|
| 2550 | 2550 |
} |
| 2551 | 2551 |
} |
| 2552 | 2552 |
|
| 2553 | 2553 |
void readAttributes(std::vector<std::string>& attrs) {
|
| 2554 | 2554 |
readLine(); |
| 2555 | 2555 |
char c; |
| 2556 | 2556 |
while (readSuccess() && line >> c && c != '@') {
|
| 2557 |
line.putback(c); |
|
| 2558 |
std::string attr; |
|
| 2559 |
_reader_bits::readToken(line, attr); |
|
| 2560 |
attrs.push_back(attr); |
|
| 2561 |
|
|
| 2557 |
line.putback(c); |
|
| 2558 |
std::string attr; |
|
| 2559 |
_reader_bits::readToken(line, attr); |
|
| 2560 |
attrs.push_back(attr); |
|
| 2561 |
readLine(); |
|
| 2562 | 2562 |
} |
| 2563 | 2563 |
line.putback(c); |
| 2564 | 2564 |
} |
| 2565 | 2565 |
|
| 2566 | 2566 |
public: |
| 2567 | 2567 |
|
| 2568 |
/// \name Execution of the contents reader |
|
| 2568 |
/// \name Execution of the contents reader |
|
| 2569 | 2569 |
/// @{
|
| 2570 | 2570 |
|
| 2571 | 2571 |
/// \brief Starts the reading |
| 2572 | 2572 |
/// |
| 2573 | 2573 |
/// This function starts the reading. |
| 2574 | 2574 |
void run() {
|
| 2575 | 2575 |
|
| 2576 | 2576 |
readLine(); |
| 2577 | 2577 |
skipSection(); |
| 2578 | 2578 |
|
| 2579 | 2579 |
while (readSuccess()) {
|
| 2580 | 2580 |
|
| 2581 |
char c; |
|
| 2582 |
line >> c; |
|
| 2583 |
|
|
| 2584 |
std::string section, caption; |
|
| 2585 |
_reader_bits::readToken(line, section); |
|
| 2586 |
_reader_bits::readToken(line, caption); |
|
| 2587 |
|
|
| 2588 |
if (section == "nodes") {
|
|
| 2589 |
_node_sections.push_back(caption); |
|
| 2590 |
_node_maps.push_back(std::vector<std::string>()); |
|
| 2591 |
readMaps(_node_maps.back()); |
|
| 2592 |
readLine(); skipSection(); |
|
| 2593 |
} else if (section == "arcs" || section == "edges") {
|
|
| 2594 |
_edge_sections.push_back(caption); |
|
| 2595 |
_arc_sections.push_back(section == "arcs"); |
|
| 2596 |
_edge_maps.push_back(std::vector<std::string>()); |
|
| 2597 |
readMaps(_edge_maps.back()); |
|
| 2598 |
readLine(); skipSection(); |
|
| 2599 |
} else if (section == "attributes") {
|
|
| 2600 |
_attribute_sections.push_back(caption); |
|
| 2601 |
_attributes.push_back(std::vector<std::string>()); |
|
| 2602 |
readAttributes(_attributes.back()); |
|
| 2603 |
} else {
|
|
| 2604 |
_extra_sections.push_back(section); |
|
| 2605 |
readLine(); skipSection(); |
|
| 2606 |
} |
|
| 2581 |
char c; |
|
| 2582 |
line >> c; |
|
| 2583 |
|
|
| 2584 |
std::string section, caption; |
|
| 2585 |
_reader_bits::readToken(line, section); |
|
| 2586 |
_reader_bits::readToken(line, caption); |
|
| 2587 |
|
|
| 2588 |
if (section == "nodes") {
|
|
| 2589 |
_node_sections.push_back(caption); |
|
| 2590 |
_node_maps.push_back(std::vector<std::string>()); |
|
| 2591 |
readMaps(_node_maps.back()); |
|
| 2592 |
readLine(); skipSection(); |
|
| 2593 |
} else if (section == "arcs" || section == "edges") {
|
|
| 2594 |
_edge_sections.push_back(caption); |
|
| 2595 |
_arc_sections.push_back(section == "arcs"); |
|
| 2596 |
_edge_maps.push_back(std::vector<std::string>()); |
|
| 2597 |
readMaps(_edge_maps.back()); |
|
| 2598 |
readLine(); skipSection(); |
|
| 2599 |
} else if (section == "attributes") {
|
|
| 2600 |
_attribute_sections.push_back(caption); |
|
| 2601 |
_attributes.push_back(std::vector<std::string>()); |
|
| 2602 |
readAttributes(_attributes.back()); |
|
| 2603 |
} else {
|
|
| 2604 |
_extra_sections.push_back(section); |
|
| 2605 |
readLine(); skipSection(); |
|
| 2606 |
} |
|
| 2607 | 2607 |
} |
| 2608 | 2608 |
} |
| 2609 | 2609 |
|
| 2610 | 2610 |
/// @} |
| 2611 |
|
|
| 2611 |
|
|
| 2612 | 2612 |
}; |
| 2613 | 2613 |
} |
| 2614 | 2614 |
|
| 2615 | 2615 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
| ... | ... |
@@ -30,311 +30,311 @@ |
| 30 | 30 |
|
| 31 | 31 |
#include <algorithm> |
| 32 | 32 |
|
| 33 | 33 |
#include <vector> |
| 34 | 34 |
#include <functional> |
| 35 | 35 |
|
| 36 | 36 |
#include <lemon/assert.h> |
| 37 | 37 |
#include <lemon/graph_utils.h> |
| 38 | 38 |
|
| 39 | 39 |
namespace lemon {
|
| 40 | 40 |
|
| 41 | 41 |
namespace _writer_bits {
|
| 42 | 42 |
|
| 43 | 43 |
template <typename Value> |
| 44 | 44 |
struct DefaultConverter {
|
| 45 | 45 |
std::string operator()(const Value& value) {
|
| 46 |
std::ostringstream os; |
|
| 47 |
os << value; |
|
| 48 |
|
|
| 46 |
std::ostringstream os; |
|
| 47 |
os << value; |
|
| 48 |
return os.str(); |
|
| 49 | 49 |
} |
| 50 | 50 |
}; |
| 51 | 51 |
|
| 52 | 52 |
template <typename T> |
| 53 | 53 |
bool operator<(const T&, const T&) {
|
| 54 | 54 |
throw DataFormatError("Label map is not comparable");
|
| 55 | 55 |
} |
| 56 | 56 |
|
| 57 | 57 |
template <typename _Map> |
| 58 | 58 |
class MapLess {
|
| 59 | 59 |
public: |
| 60 | 60 |
typedef _Map Map; |
| 61 | 61 |
typedef typename Map::Key Item; |
| 62 | 62 |
|
| 63 | 63 |
private: |
| 64 | 64 |
const Map& _map; |
| 65 |
|
|
| 65 |
|
|
| 66 | 66 |
public: |
| 67 | 67 |
MapLess(const Map& map) : _map(map) {}
|
| 68 | 68 |
|
| 69 | 69 |
bool operator()(const Item& left, const Item& right) {
|
| 70 |
|
|
| 70 |
return _map[left] < _map[right]; |
|
| 71 | 71 |
} |
| 72 | 72 |
}; |
| 73 | 73 |
|
| 74 | 74 |
template <typename _Graph, bool _dir, typename _Map> |
| 75 | 75 |
class GraphArcMapLess {
|
| 76 | 76 |
public: |
| 77 | 77 |
typedef _Map Map; |
| 78 | 78 |
typedef _Graph Graph; |
| 79 | 79 |
typedef typename Graph::Edge Item; |
| 80 | 80 |
|
| 81 | 81 |
private: |
| 82 | 82 |
const Graph& _graph; |
| 83 | 83 |
const Map& _map; |
| 84 |
|
|
| 84 |
|
|
| 85 | 85 |
public: |
| 86 |
GraphArcMapLess(const Graph& graph, const Map& map) |
|
| 87 |
: _graph(graph), _map(map) {}
|
|
| 86 |
GraphArcMapLess(const Graph& graph, const Map& map) |
|
| 87 |
: _graph(graph), _map(map) {}
|
|
| 88 | 88 |
|
| 89 | 89 |
bool operator()(const Item& left, const Item& right) {
|
| 90 |
return _map[_graph.direct(left, _dir)] < |
|
| 91 |
_map[_graph.direct(right, _dir)]; |
|
| 90 |
return _map[_graph.direct(left, _dir)] < |
|
| 91 |
_map[_graph.direct(right, _dir)]; |
|
| 92 | 92 |
} |
| 93 | 93 |
}; |
| 94 | 94 |
|
| 95 |
template <typename _Item> |
|
| 95 |
template <typename _Item> |
|
| 96 | 96 |
class MapStorageBase {
|
| 97 | 97 |
public: |
| 98 | 98 |
typedef _Item Item; |
| 99 | 99 |
|
| 100 | 100 |
public: |
| 101 | 101 |
MapStorageBase() {}
|
| 102 | 102 |
virtual ~MapStorageBase() {}
|
| 103 | 103 |
|
| 104 | 104 |
virtual std::string get(const Item& item) = 0; |
| 105 | 105 |
virtual void sort(std::vector<Item>&) = 0; |
| 106 | 106 |
}; |
| 107 | 107 |
|
| 108 |
template <typename _Item, typename _Map, |
|
| 109 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 108 |
template <typename _Item, typename _Map, |
|
| 109 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 110 | 110 |
class MapStorage : public MapStorageBase<_Item> {
|
| 111 | 111 |
public: |
| 112 | 112 |
typedef _Map Map; |
| 113 | 113 |
typedef _Converter Converter; |
| 114 | 114 |
typedef _Item Item; |
| 115 |
|
|
| 115 |
|
|
| 116 | 116 |
private: |
| 117 | 117 |
const Map& _map; |
| 118 | 118 |
Converter _converter; |
| 119 | 119 |
|
| 120 | 120 |
public: |
| 121 |
MapStorage(const Map& map, const Converter& converter = Converter()) |
|
| 122 |
: _map(map), _converter(converter) {}
|
|
| 121 |
MapStorage(const Map& map, const Converter& converter = Converter()) |
|
| 122 |
: _map(map), _converter(converter) {}
|
|
| 123 | 123 |
virtual ~MapStorage() {}
|
| 124 | 124 |
|
| 125 | 125 |
virtual std::string get(const Item& item) {
|
| 126 |
|
|
| 126 |
return _converter(_map[item]); |
|
| 127 | 127 |
} |
| 128 | 128 |
virtual void sort(std::vector<Item>& items) {
|
| 129 |
MapLess<Map> less(_map); |
|
| 130 |
std::sort(items.begin(), items.end(), less); |
|
| 129 |
MapLess<Map> less(_map); |
|
| 130 |
std::sort(items.begin(), items.end(), less); |
|
| 131 | 131 |
} |
| 132 | 132 |
}; |
| 133 | 133 |
|
| 134 |
template <typename _Graph, bool _dir, typename _Map, |
|
| 135 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 134 |
template <typename _Graph, bool _dir, typename _Map, |
|
| 135 |
typename _Converter = DefaultConverter<typename _Map::Value> > |
|
| 136 | 136 |
class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
|
| 137 | 137 |
public: |
| 138 | 138 |
typedef _Map Map; |
| 139 | 139 |
typedef _Converter Converter; |
| 140 | 140 |
typedef _Graph Graph; |
| 141 | 141 |
typedef typename Graph::Edge Item; |
| 142 | 142 |
static const bool dir = _dir; |
| 143 |
|
|
| 143 |
|
|
| 144 | 144 |
private: |
| 145 | 145 |
const Graph& _graph; |
| 146 | 146 |
const Map& _map; |
| 147 | 147 |
Converter _converter; |
| 148 | 148 |
|
| 149 | 149 |
public: |
| 150 |
GraphArcMapStorage(const Graph& graph, const Map& map, |
|
| 151 |
const Converter& converter = Converter()) |
|
| 152 |
|
|
| 150 |
GraphArcMapStorage(const Graph& graph, const Map& map, |
|
| 151 |
const Converter& converter = Converter()) |
|
| 152 |
: _graph(graph), _map(map), _converter(converter) {}
|
|
| 153 | 153 |
virtual ~GraphArcMapStorage() {}
|
| 154 | 154 |
|
| 155 | 155 |
virtual std::string get(const Item& item) {
|
| 156 |
|
|
| 156 |
return _converter(_map[_graph.direct(item, dir)]); |
|
| 157 | 157 |
} |
| 158 | 158 |
virtual void sort(std::vector<Item>& items) {
|
| 159 |
GraphArcMapLess<Graph, dir, Map> less(_graph, _map); |
|
| 160 |
std::sort(items.begin(), items.end(), less); |
|
| 159 |
GraphArcMapLess<Graph, dir, Map> less(_graph, _map); |
|
| 160 |
std::sort(items.begin(), items.end(), less); |
|
| 161 | 161 |
} |
| 162 | 162 |
}; |
| 163 | 163 |
|
| 164 | 164 |
class ValueStorageBase {
|
| 165 | 165 |
public: |
| 166 | 166 |
ValueStorageBase() {}
|
| 167 | 167 |
virtual ~ValueStorageBase() {}
|
| 168 | 168 |
|
| 169 |
virtual std::string get() = 0; |
|
| 169 |
virtual std::string get() = 0; |
|
| 170 | 170 |
}; |
| 171 | 171 |
|
| 172 | 172 |
template <typename _Value, typename _Converter = DefaultConverter<_Value> > |
| 173 | 173 |
class ValueStorage : public ValueStorageBase {
|
| 174 | 174 |
public: |
| 175 | 175 |
typedef _Value Value; |
| 176 | 176 |
typedef _Converter Converter; |
| 177 | 177 |
|
| 178 | 178 |
private: |
| 179 | 179 |
const Value& _value; |
| 180 | 180 |
Converter _converter; |
| 181 | 181 |
|
| 182 | 182 |
public: |
| 183 | 183 |
ValueStorage(const Value& value, const Converter& converter = Converter()) |
| 184 |
|
|
| 184 |
: _value(value), _converter(converter) {}
|
|
| 185 | 185 |
|
| 186 | 186 |
virtual std::string get() {
|
| 187 |
|
|
| 187 |
return _converter(_value); |
|
| 188 | 188 |
} |
| 189 | 189 |
}; |
| 190 | 190 |
|
| 191 | 191 |
template <typename Value> |
| 192 | 192 |
struct MapLookUpConverter {
|
| 193 | 193 |
const std::map<Value, std::string>& _map; |
| 194 |
|
|
| 195 |
MapLookUpConverter(const std::map<Value, std::string>& map) |
|
| 196 |
: _map(map) {}
|
|
| 197 |
|
|
| 194 |
|
|
| 195 |
MapLookUpConverter(const std::map<Value, std::string>& map) |
|
| 196 |
: _map(map) {}
|
|
| 197 |
|
|
| 198 | 198 |
std::string operator()(const Value& str) {
|
| 199 |
typename std::map<Value, std::string>::const_iterator it = |
|
| 200 |
_map.find(str); |
|
| 201 |
if (it == _map.end()) {
|
|
| 202 |
throw DataFormatError("Item not found");
|
|
| 203 |
} |
|
| 204 |
return it->second; |
|
| 199 |
typename std::map<Value, std::string>::const_iterator it = |
|
| 200 |
_map.find(str); |
|
| 201 |
if (it == _map.end()) {
|
|
| 202 |
throw DataFormatError("Item not found");
|
|
| 203 |
} |
|
| 204 |
return it->second; |
|
| 205 | 205 |
} |
| 206 | 206 |
}; |
| 207 | 207 |
|
| 208 | 208 |
template <typename Graph> |
| 209 | 209 |
struct GraphArcLookUpConverter {
|
| 210 | 210 |
const Graph& _graph; |
| 211 | 211 |
const std::map<typename Graph::Edge, std::string>& _map; |
| 212 |
|
|
| 213 |
GraphArcLookUpConverter(const Graph& graph, |
|
| 214 |
const std::map<typename Graph::Edge, |
|
| 215 |
std::string>& map) |
|
| 216 |
: _graph(graph), _map(map) {}
|
|
| 217 |
|
|
| 212 |
|
|
| 213 |
GraphArcLookUpConverter(const Graph& graph, |
|
| 214 |
const std::map<typename Graph::Edge, |
|
| 215 |
std::string>& map) |
|
| 216 |
: _graph(graph), _map(map) {}
|
|
| 217 |
|
|
| 218 | 218 |
std::string operator()(const typename Graph::Arc& val) {
|
| 219 |
typename std::map<typename Graph::Edge, std::string> |
|
| 220 |
::const_iterator it = _map.find(val); |
|
| 221 |
if (it == _map.end()) {
|
|
| 222 |
throw DataFormatError("Item not found");
|
|
| 223 |
} |
|
| 224 |
return (_graph.direction(val) ? '+' : '-') + it->second; |
|
| 219 |
typename std::map<typename Graph::Edge, std::string> |
|
| 220 |
::const_iterator it = _map.find(val); |
|
| 221 |
if (it == _map.end()) {
|
|
| 222 |
throw DataFormatError("Item not found");
|
|
| 223 |
} |
|
| 224 |
return (_graph.direction(val) ? '+' : '-') + it->second; |
|
| 225 | 225 |
} |
| 226 | 226 |
}; |
| 227 | 227 |
|
| 228 | 228 |
inline bool isWhiteSpace(char c) {
|
| 229 |
return c == ' ' || c == '\t' || c == '\v' || |
|
| 230 |
c == '\n' || c == '\r' || c == '\f'; |
|
| 229 |
return c == ' ' || c == '\t' || c == '\v' || |
|
| 230 |
c == '\n' || c == '\r' || c == '\f'; |
|
| 231 | 231 |
} |
| 232 | 232 |
|
| 233 | 233 |
inline bool isEscaped(char c) {
|
| 234 |
return c == '\\' || c == '\"' || c == '\'' || |
|
| 235 |
c == '\a' || c == '\b'; |
|
| 234 |
return c == '\\' || c == '\"' || c == '\'' || |
|
| 235 |
c == '\a' || c == '\b'; |
|
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 | 238 |
inline static void writeEscape(std::ostream& os, char c) {
|
| 239 | 239 |
switch (c) {
|
| 240 | 240 |
case '\\': |
| 241 |
os << "\\\\"; |
|
| 242 |
return; |
|
| 241 |
os << "\\\\"; |
|
| 242 |
return; |
|
| 243 | 243 |
case '\"': |
| 244 |
os << "\\\""; |
|
| 245 |
return; |
|
| 244 |
os << "\\\""; |
|
| 245 |
return; |
|
| 246 | 246 |
case '\a': |
| 247 |
os << "\\a"; |
|
| 248 |
return; |
|
| 247 |
os << "\\a"; |
|
| 248 |
return; |
|
| 249 | 249 |
case '\b': |
| 250 |
os << "\\b"; |
|
| 251 |
return; |
|
| 250 |
os << "\\b"; |
|
| 251 |
return; |
|
| 252 | 252 |
case '\f': |
| 253 |
os << "\\f"; |
|
| 254 |
return; |
|
| 253 |
os << "\\f"; |
|
| 254 |
return; |
|
| 255 | 255 |
case '\r': |
| 256 |
os << "\\r"; |
|
| 257 |
return; |
|
| 256 |
os << "\\r"; |
|
| 257 |
return; |
|
| 258 | 258 |
case '\n': |
| 259 |
os << "\\n"; |
|
| 260 |
return; |
|
| 259 |
os << "\\n"; |
|
| 260 |
return; |
|
| 261 | 261 |
case '\t': |
| 262 |
os << "\\t"; |
|
| 263 |
return; |
|
| 262 |
os << "\\t"; |
|
| 263 |
return; |
|
| 264 | 264 |
case '\v': |
| 265 |
os << "\\v"; |
|
| 266 |
return; |
|
| 265 |
os << "\\v"; |
|
| 266 |
return; |
|
| 267 | 267 |
default: |
| 268 |
if (c < 0x20) {
|
|
| 269 |
std::ios::fmtflags flags = os.flags(); |
|
| 270 |
os << '\\' << std::oct << static_cast<int>(c); |
|
| 271 |
os.flags(flags); |
|
| 272 |
} else {
|
|
| 273 |
os << c; |
|
| 274 |
} |
|
| 275 |
return; |
|
| 276 |
|
|
| 268 |
if (c < 0x20) {
|
|
| 269 |
std::ios::fmtflags flags = os.flags(); |
|
| 270 |
os << '\\' << std::oct << static_cast<int>(c); |
|
| 271 |
os.flags(flags); |
|
| 272 |
} else {
|
|
| 273 |
os << c; |
|
| 274 |
} |
|
| 275 |
return; |
|
| 276 |
} |
|
| 277 | 277 |
} |
| 278 | 278 |
|
| 279 | 279 |
inline bool requireEscape(const std::string& str) {
|
| 280 | 280 |
if (str.empty() || str[0] == '@') return true; |
| 281 | 281 |
std::istringstream is(str); |
| 282 | 282 |
char c; |
| 283 | 283 |
while (is.get(c)) {
|
| 284 |
if (isWhiteSpace(c) || isEscaped(c)) {
|
|
| 285 |
return true; |
|
| 286 |
|
|
| 284 |
if (isWhiteSpace(c) || isEscaped(c)) {
|
|
| 285 |
return true; |
|
| 286 |
} |
|
| 287 | 287 |
} |
| 288 | 288 |
return false; |
| 289 | 289 |
} |
| 290 |
|
|
| 290 |
|
|
| 291 | 291 |
inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
|
| 292 | 292 |
|
| 293 | 293 |
if (requireEscape(str)) {
|
| 294 |
os << '\"'; |
|
| 295 |
for (std::string::const_iterator it = str.begin(); |
|
| 296 |
it != str.end(); ++it) {
|
|
| 297 |
writeEscape(os, *it); |
|
| 298 |
} |
|
| 299 |
os << '\"'; |
|
| 294 |
os << '\"'; |
|
| 295 |
for (std::string::const_iterator it = str.begin(); |
|
| 296 |
it != str.end(); ++it) {
|
|
| 297 |
writeEscape(os, *it); |
|
| 298 |
} |
|
| 299 |
os << '\"'; |
|
| 300 | 300 |
} else {
|
| 301 |
|
|
| 301 |
os << str; |
|
| 302 | 302 |
} |
| 303 | 303 |
return os; |
| 304 | 304 |
} |
| 305 | 305 |
|
| 306 | 306 |
} |
| 307 | 307 |
|
| 308 | 308 |
template <typename Digraph> |
| 309 | 309 |
class DigraphWriter; |
| 310 | 310 |
|
| 311 | 311 |
template <typename Digraph> |
| 312 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, |
|
| 313 |
const Digraph& digraph); |
|
| 312 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, |
|
| 313 |
const Digraph& digraph); |
|
| 314 | 314 |
|
| 315 | 315 |
template <typename Digraph> |
| 316 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
|
| 317 |
const Digraph& digraph); |
|
| 316 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
|
| 317 |
const Digraph& digraph); |
|
| 318 | 318 |
|
| 319 | 319 |
template <typename Digraph> |
| 320 |
DigraphWriter<Digraph> digraphWriter(const char *fn, |
|
| 321 |
const Digraph& digraph); |
|
| 322 |
|
|
| 320 |
DigraphWriter<Digraph> digraphWriter(const char *fn, |
|
| 321 |
const Digraph& digraph); |
|
| 322 |
|
|
| 323 | 323 |
/// \ingroup lemon_io |
| 324 |
/// |
|
| 324 |
/// |
|
| 325 | 325 |
/// \brief \ref lgf-format "LGF" writer for directed graphs |
| 326 | 326 |
/// |
| 327 | 327 |
/// This utility writes an \ref lgf-format "LGF" file. |
| 328 | 328 |
/// |
| 329 | 329 |
/// The writing method does a batch processing. The user creates a |
| 330 | 330 |
/// writer object, then various writing rules can be added to the |
| 331 | 331 |
/// writer, and eventually the writing is executed with the \c run() |
| 332 | 332 |
/// member function. A map writing rule can be added to the writer |
| 333 | 333 |
/// with the \c nodeMap() or \c arcMap() members. An optional |
| 334 | 334 |
/// converter parameter can also be added as a standard functor |
| 335 | 335 |
/// converting from the value type of the map to \c std::string. If it |
| 336 | 336 |
/// is set, it will determine how the value type of the map is written to |
| 337 | 337 |
/// the output stream. If the functor is not set, then a default |
| 338 | 338 |
/// conversion will be used. The \c attribute(), \c node() and \c |
| 339 | 339 |
/// arc() functions are used to add attribute writing rules. |
| 340 | 340 |
/// |
| ... | ... |
@@ -357,244 +357,244 @@ |
| 357 | 357 |
/// attributes() functions. |
| 358 | 358 |
/// |
| 359 | 359 |
/// The \c skipNodes() and \c skipArcs() functions forbid the |
| 360 | 360 |
/// writing of the sections. If two arc sections should be written |
| 361 | 361 |
/// to the output, it can be done in two passes, the first pass |
| 362 | 362 |
/// writes the node section and the first arc section, then the |
| 363 | 363 |
/// second pass skips the node section and writes just the arc |
| 364 | 364 |
/// section to the stream. The output stream can be retrieved with |
| 365 | 365 |
/// the \c ostream() function, hence the second pass can append its |
| 366 | 366 |
/// output to the output of the first pass. |
| 367 | 367 |
template <typename _Digraph> |
| 368 | 368 |
class DigraphWriter {
|
| 369 | 369 |
public: |
| 370 | 370 |
|
| 371 | 371 |
typedef _Digraph Digraph; |
| 372 | 372 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 373 |
|
|
| 373 |
|
|
| 374 | 374 |
private: |
| 375 | 375 |
|
| 376 | 376 |
|
| 377 | 377 |
std::ostream* _os; |
| 378 | 378 |
bool local_os; |
| 379 | 379 |
|
| 380 | 380 |
const Digraph& _digraph; |
| 381 | 381 |
|
| 382 | 382 |
std::string _nodes_caption; |
| 383 | 383 |
std::string _arcs_caption; |
| 384 | 384 |
std::string _attributes_caption; |
| 385 |
|
|
| 385 |
|
|
| 386 | 386 |
typedef std::map<Node, std::string> NodeIndex; |
| 387 | 387 |
NodeIndex _node_index; |
| 388 | 388 |
typedef std::map<Arc, std::string> ArcIndex; |
| 389 | 389 |
ArcIndex _arc_index; |
| 390 | 390 |
|
| 391 |
typedef std::vector<std::pair<std::string, |
|
| 392 |
_writer_bits::MapStorageBase<Node>* > > NodeMaps; |
|
| 393 |
|
|
| 391 |
typedef std::vector<std::pair<std::string, |
|
| 392 |
_writer_bits::MapStorageBase<Node>* > > NodeMaps; |
|
| 393 |
NodeMaps _node_maps; |
|
| 394 | 394 |
|
| 395 |
typedef std::vector<std::pair<std::string, |
|
| 395 |
typedef std::vector<std::pair<std::string, |
|
| 396 | 396 |
_writer_bits::MapStorageBase<Arc>* > >ArcMaps; |
| 397 | 397 |
ArcMaps _arc_maps; |
| 398 | 398 |
|
| 399 |
typedef std::vector<std::pair<std::string, |
|
| 399 |
typedef std::vector<std::pair<std::string, |
|
| 400 | 400 |
_writer_bits::ValueStorageBase*> > Attributes; |
| 401 | 401 |
Attributes _attributes; |
| 402 | 402 |
|
| 403 | 403 |
bool _skip_nodes; |
| 404 | 404 |
bool _skip_arcs; |
| 405 | 405 |
|
| 406 | 406 |
public: |
| 407 | 407 |
|
| 408 | 408 |
/// \brief Constructor |
| 409 | 409 |
/// |
| 410 | 410 |
/// Construct a directed graph writer, which writes to the given |
| 411 | 411 |
/// output stream. |
| 412 |
DigraphWriter(std::ostream& is, const Digraph& digraph) |
|
| 412 |
DigraphWriter(std::ostream& is, const Digraph& digraph) |
|
| 413 | 413 |
: _os(&is), local_os(false), _digraph(digraph), |
| 414 |
|
|
| 414 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 415 | 415 |
|
| 416 | 416 |
/// \brief Constructor |
| 417 | 417 |
/// |
| 418 | 418 |
/// Construct a directed graph writer, which writes to the given |
| 419 | 419 |
/// output file. |
| 420 |
DigraphWriter(const std::string& fn, const Digraph& digraph) |
|
| 420 |
DigraphWriter(const std::string& fn, const Digraph& digraph) |
|
| 421 | 421 |
: _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph), |
| 422 |
|
|
| 422 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 423 | 423 |
|
| 424 | 424 |
/// \brief Constructor |
| 425 | 425 |
/// |
| 426 | 426 |
/// Construct a directed graph writer, which writes to the given |
| 427 | 427 |
/// output file. |
| 428 |
DigraphWriter(const char* fn, const Digraph& digraph) |
|
| 428 |
DigraphWriter(const char* fn, const Digraph& digraph) |
|
| 429 | 429 |
: _os(new std::ofstream(fn)), local_os(true), _digraph(digraph), |
| 430 |
|
|
| 430 |
_skip_nodes(false), _skip_arcs(false) {}
|
|
| 431 | 431 |
|
| 432 | 432 |
/// \brief Destructor |
| 433 | 433 |
~DigraphWriter() {
|
| 434 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 435 |
it != _node_maps.end(); ++it) {
|
|
| 436 |
|
|
| 434 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 435 |
it != _node_maps.end(); ++it) {
|
|
| 436 |
delete it->second; |
|
| 437 | 437 |
} |
| 438 | 438 |
|
| 439 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 440 |
it != _arc_maps.end(); ++it) {
|
|
| 441 |
|
|
| 439 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 440 |
it != _arc_maps.end(); ++it) {
|
|
| 441 |
delete it->second; |
|
| 442 | 442 |
} |
| 443 | 443 |
|
| 444 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 445 |
it != _attributes.end(); ++it) {
|
|
| 446 |
|
|
| 444 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 445 |
it != _attributes.end(); ++it) {
|
|
| 446 |
delete it->second; |
|
| 447 | 447 |
} |
| 448 | 448 |
|
| 449 | 449 |
if (local_os) {
|
| 450 |
|
|
| 450 |
delete _os; |
|
| 451 | 451 |
} |
| 452 | 452 |
} |
| 453 | 453 |
|
| 454 | 454 |
private: |
| 455 | 455 |
|
| 456 |
friend DigraphWriter<Digraph> digraphWriter<>(std::ostream& os, |
|
| 457 |
const Digraph& digraph); |
|
| 458 |
friend DigraphWriter<Digraph> digraphWriter<>(const std::string& fn, |
|
| 459 |
const Digraph& digraph); |
|
| 460 |
friend DigraphWriter<Digraph> digraphWriter<>(const char *fn, |
|
| 461 |
const Digraph& digraph); |
|
| 456 |
friend DigraphWriter<Digraph> digraphWriter<>(std::ostream& os, |
|
| 457 |
const Digraph& digraph); |
|
| 458 |
friend DigraphWriter<Digraph> digraphWriter<>(const std::string& fn, |
|
| 459 |
const Digraph& digraph); |
|
| 460 |
friend DigraphWriter<Digraph> digraphWriter<>(const char *fn, |
|
| 461 |
const Digraph& digraph); |
|
| 462 | 462 |
|
| 463 |
DigraphWriter(DigraphWriter& other) |
|
| 463 |
DigraphWriter(DigraphWriter& other) |
|
| 464 | 464 |
: _os(other._os), local_os(other.local_os), _digraph(other._digraph), |
| 465 |
|
|
| 465 |
_skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
|
|
| 466 | 466 |
|
| 467 | 467 |
other._os = 0; |
| 468 | 468 |
other.local_os = false; |
| 469 | 469 |
|
| 470 | 470 |
_node_index.swap(other._node_index); |
| 471 | 471 |
_arc_index.swap(other._arc_index); |
| 472 | 472 |
|
| 473 | 473 |
_node_maps.swap(other._node_maps); |
| 474 | 474 |
_arc_maps.swap(other._arc_maps); |
| 475 | 475 |
_attributes.swap(other._attributes); |
| 476 | 476 |
|
| 477 | 477 |
_nodes_caption = other._nodes_caption; |
| 478 | 478 |
_arcs_caption = other._arcs_caption; |
| 479 | 479 |
_attributes_caption = other._attributes_caption; |
| 480 | 480 |
} |
| 481 |
|
|
| 481 |
|
|
| 482 | 482 |
DigraphWriter& operator=(const DigraphWriter&); |
| 483 | 483 |
|
| 484 | 484 |
public: |
| 485 | 485 |
|
| 486 | 486 |
/// \name Writing rules |
| 487 | 487 |
/// @{
|
| 488 |
|
|
| 488 |
|
|
| 489 | 489 |
/// \brief Node map writing rule |
| 490 | 490 |
/// |
| 491 | 491 |
/// Add a node map writing rule to the writer. |
| 492 | 492 |
template <typename Map> |
| 493 | 493 |
DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
|
| 494 | 494 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 495 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 496 |
new _writer_bits::MapStorage<Node, Map>(map); |
|
| 495 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 496 |
new _writer_bits::MapStorage<Node, Map>(map); |
|
| 497 | 497 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 498 | 498 |
return *this; |
| 499 | 499 |
} |
| 500 | 500 |
|
| 501 | 501 |
/// \brief Node map writing rule |
| 502 | 502 |
/// |
| 503 | 503 |
/// Add a node map writing rule with specialized converter to the |
| 504 | 504 |
/// writer. |
| 505 | 505 |
template <typename Map, typename Converter> |
| 506 |
DigraphWriter& nodeMap(const std::string& caption, const Map& map, |
|
| 507 |
const Converter& converter = Converter()) {
|
|
| 506 |
DigraphWriter& nodeMap(const std::string& caption, const Map& map, |
|
| 507 |
const Converter& converter = Converter()) {
|
|
| 508 | 508 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 509 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 510 |
new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 509 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 510 |
new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 511 | 511 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 512 | 512 |
return *this; |
| 513 | 513 |
} |
| 514 | 514 |
|
| 515 | 515 |
/// \brief Arc map writing rule |
| 516 | 516 |
/// |
| 517 | 517 |
/// Add an arc map writing rule to the writer. |
| 518 | 518 |
template <typename Map> |
| 519 | 519 |
DigraphWriter& arcMap(const std::string& caption, const Map& map) {
|
| 520 | 520 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 521 |
_writer_bits::MapStorageBase<Arc>* storage = |
|
| 522 |
new _writer_bits::MapStorage<Arc, Map>(map); |
|
| 521 |
_writer_bits::MapStorageBase<Arc>* storage = |
|
| 522 |
new _writer_bits::MapStorage<Arc, Map>(map); |
|
| 523 | 523 |
_arc_maps.push_back(std::make_pair(caption, storage)); |
| 524 | 524 |
return *this; |
| 525 | 525 |
} |
| 526 | 526 |
|
| 527 | 527 |
/// \brief Arc map writing rule |
| 528 | 528 |
/// |
| 529 | 529 |
/// Add an arc map writing rule with specialized converter to the |
| 530 | 530 |
/// writer. |
| 531 | 531 |
template <typename Map, typename Converter> |
| 532 |
DigraphWriter& arcMap(const std::string& caption, const Map& map, |
|
| 533 |
const Converter& converter = Converter()) {
|
|
| 532 |
DigraphWriter& arcMap(const std::string& caption, const Map& map, |
|
| 533 |
const Converter& converter = Converter()) {
|
|
| 534 | 534 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 535 |
_writer_bits::MapStorageBase<Arc>* storage = |
|
| 536 |
new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter); |
|
| 535 |
_writer_bits::MapStorageBase<Arc>* storage = |
|
| 536 |
new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter); |
|
| 537 | 537 |
_arc_maps.push_back(std::make_pair(caption, storage)); |
| 538 | 538 |
return *this; |
| 539 | 539 |
} |
| 540 | 540 |
|
| 541 | 541 |
/// \brief Attribute writing rule |
| 542 | 542 |
/// |
| 543 | 543 |
/// Add an attribute writing rule to the writer. |
| 544 | 544 |
template <typename Value> |
| 545 | 545 |
DigraphWriter& attribute(const std::string& caption, const Value& value) {
|
| 546 |
_writer_bits::ValueStorageBase* storage = |
|
| 547 |
new _writer_bits::ValueStorage<Value>(value); |
|
| 546 |
_writer_bits::ValueStorageBase* storage = |
|
| 547 |
new _writer_bits::ValueStorage<Value>(value); |
|
| 548 | 548 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 549 | 549 |
return *this; |
| 550 | 550 |
} |
| 551 | 551 |
|
| 552 | 552 |
/// \brief Attribute writing rule |
| 553 | 553 |
/// |
| 554 | 554 |
/// Add an attribute writing rule with specialized converter to the |
| 555 | 555 |
/// writer. |
| 556 | 556 |
template <typename Value, typename Converter> |
| 557 |
DigraphWriter& attribute(const std::string& caption, const Value& value, |
|
| 558 |
const Converter& converter = Converter()) {
|
|
| 559 |
_writer_bits::ValueStorageBase* storage = |
|
| 560 |
new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 557 |
DigraphWriter& attribute(const std::string& caption, const Value& value, |
|
| 558 |
const Converter& converter = Converter()) {
|
|
| 559 |
_writer_bits::ValueStorageBase* storage = |
|
| 560 |
new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 561 | 561 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 562 | 562 |
return *this; |
| 563 | 563 |
} |
| 564 | 564 |
|
| 565 | 565 |
/// \brief Node writing rule |
| 566 | 566 |
/// |
| 567 | 567 |
/// Add a node writing rule to the writer. |
| 568 | 568 |
DigraphWriter& node(const std::string& caption, const Node& node) {
|
| 569 | 569 |
typedef _writer_bits::MapLookUpConverter<Node> Converter; |
| 570 | 570 |
Converter converter(_node_index); |
| 571 |
_writer_bits::ValueStorageBase* storage = |
|
| 572 |
new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 571 |
_writer_bits::ValueStorageBase* storage = |
|
| 572 |
new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 573 | 573 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 574 | 574 |
return *this; |
| 575 | 575 |
} |
| 576 | 576 |
|
| 577 | 577 |
/// \brief Arc writing rule |
| 578 | 578 |
/// |
| 579 | 579 |
/// Add an arc writing rule to writer. |
| 580 | 580 |
DigraphWriter& arc(const std::string& caption, const Arc& arc) {
|
| 581 | 581 |
typedef _writer_bits::MapLookUpConverter<Arc> Converter; |
| 582 | 582 |
Converter converter(_arc_index); |
| 583 |
_writer_bits::ValueStorageBase* storage = |
|
| 584 |
new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 583 |
_writer_bits::ValueStorageBase* storage = |
|
| 584 |
new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 585 | 585 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 586 | 586 |
return *this; |
| 587 | 587 |
} |
| 588 | 588 |
|
| 589 | 589 |
/// \name Section captions |
| 590 | 590 |
/// @{
|
| 591 | 591 |
|
| 592 | 592 |
/// \brief Add an additional caption to the \c \@nodes section |
| 593 | 593 |
/// |
| 594 | 594 |
/// Add an additional caption to the \c \@nodes section. |
| 595 | 595 |
DigraphWriter& nodes(const std::string& caption) {
|
| 596 | 596 |
_nodes_caption = caption; |
| 597 | 597 |
return *this; |
| 598 | 598 |
} |
| 599 | 599 |
|
| 600 | 600 |
/// \brief Add an additional caption to the \c \@arcs section |
| ... | ... |
@@ -628,575 +628,575 @@ |
| 628 | 628 |
/// \brief Skip writing arc set |
| 629 | 629 |
/// |
| 630 | 630 |
/// The \c \@arcs section will not be written to the stream. |
| 631 | 631 |
DigraphWriter& skipArcs() {
|
| 632 | 632 |
LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member"); |
| 633 | 633 |
_skip_arcs = true; |
| 634 | 634 |
return *this; |
| 635 | 635 |
} |
| 636 | 636 |
|
| 637 | 637 |
/// @} |
| 638 | 638 |
|
| 639 | 639 |
private: |
| 640 | 640 |
|
| 641 | 641 |
void writeNodes() {
|
| 642 | 642 |
_writer_bits::MapStorageBase<Node>* label = 0; |
| 643 | 643 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 644 |
|
|
| 644 |
it != _node_maps.end(); ++it) {
|
|
| 645 | 645 |
if (it->first == "label") {
|
| 646 |
label = it->second; |
|
| 647 |
break; |
|
| 648 |
|
|
| 646 |
label = it->second; |
|
| 647 |
break; |
|
| 648 |
} |
|
| 649 | 649 |
} |
| 650 | 650 |
|
| 651 | 651 |
*_os << "@nodes"; |
| 652 | 652 |
if (!_nodes_caption.empty()) {
|
| 653 |
|
|
| 653 |
_writer_bits::writeToken(*_os << ' ', _nodes_caption); |
|
| 654 | 654 |
} |
| 655 | 655 |
*_os << std::endl; |
| 656 | 656 |
|
| 657 | 657 |
if (label == 0) {
|
| 658 |
|
|
| 658 |
*_os << "label" << '\t'; |
|
| 659 | 659 |
} |
| 660 | 660 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 661 |
it != _node_maps.end(); ++it) {
|
|
| 662 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 661 |
it != _node_maps.end(); ++it) {
|
|
| 662 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 663 | 663 |
} |
| 664 | 664 |
*_os << std::endl; |
| 665 | 665 |
|
| 666 | 666 |
std::vector<Node> nodes; |
| 667 | 667 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
| 668 |
|
|
| 668 |
nodes.push_back(n); |
|
| 669 | 669 |
} |
| 670 |
|
|
| 670 |
|
|
| 671 | 671 |
if (label == 0) {
|
| 672 |
IdMap<Digraph, Node> id_map(_digraph); |
|
| 673 |
_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map); |
|
| 674 |
|
|
| 672 |
IdMap<Digraph, Node> id_map(_digraph); |
|
| 673 |
_writer_bits::MapLess<IdMap<Digraph, Node> > id_less(id_map); |
|
| 674 |
std::sort(nodes.begin(), nodes.end(), id_less); |
|
| 675 | 675 |
} else {
|
| 676 |
|
|
| 676 |
label->sort(nodes); |
|
| 677 | 677 |
} |
| 678 | 678 |
|
| 679 | 679 |
for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
|
| 680 |
Node n = nodes[i]; |
|
| 681 |
if (label == 0) {
|
|
| 682 |
std::ostringstream os; |
|
| 683 |
os << _digraph.id(n); |
|
| 684 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 685 |
*_os << '\t'; |
|
| 686 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 687 |
} |
|
| 688 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 689 |
it != _node_maps.end(); ++it) {
|
|
| 690 |
std::string value = it->second->get(n); |
|
| 691 |
_writer_bits::writeToken(*_os, value); |
|
| 692 |
if (it->first == "label") {
|
|
| 693 |
_node_index.insert(std::make_pair(n, value)); |
|
| 694 |
} |
|
| 695 |
*_os << '\t'; |
|
| 696 |
} |
|
| 697 |
*_os << std::endl; |
|
| 680 |
Node n = nodes[i]; |
|
| 681 |
if (label == 0) {
|
|
| 682 |
std::ostringstream os; |
|
| 683 |
os << _digraph.id(n); |
|
| 684 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 685 |
*_os << '\t'; |
|
| 686 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 687 |
} |
|
| 688 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 689 |
it != _node_maps.end(); ++it) {
|
|
| 690 |
std::string value = it->second->get(n); |
|
| 691 |
_writer_bits::writeToken(*_os, value); |
|
| 692 |
if (it->first == "label") {
|
|
| 693 |
_node_index.insert(std::make_pair(n, value)); |
|
| 694 |
} |
|
| 695 |
*_os << '\t'; |
|
| 696 |
} |
|
| 697 |
*_os << std::endl; |
|
| 698 | 698 |
} |
| 699 | 699 |
} |
| 700 | 700 |
|
| 701 | 701 |
void createNodeIndex() {
|
| 702 | 702 |
_writer_bits::MapStorageBase<Node>* label = 0; |
| 703 | 703 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 704 |
|
|
| 704 |
it != _node_maps.end(); ++it) {
|
|
| 705 | 705 |
if (it->first == "label") {
|
| 706 |
label = it->second; |
|
| 707 |
break; |
|
| 708 |
|
|
| 706 |
label = it->second; |
|
| 707 |
break; |
|
| 708 |
} |
|
| 709 | 709 |
} |
| 710 | 710 |
|
| 711 | 711 |
if (label == 0) {
|
| 712 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
| 713 |
std::ostringstream os; |
|
| 714 |
os << _digraph.id(n); |
|
| 715 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 716 |
|
|
| 712 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
| 713 |
std::ostringstream os; |
|
| 714 |
os << _digraph.id(n); |
|
| 715 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 716 |
} |
|
| 717 | 717 |
} else {
|
| 718 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
| 719 |
std::string value = label->get(n); |
|
| 720 |
_node_index.insert(std::make_pair(n, value)); |
|
| 721 |
} |
|
| 718 |
for (NodeIt n(_digraph); n != INVALID; ++n) {
|
|
| 719 |
std::string value = label->get(n); |
|
| 720 |
_node_index.insert(std::make_pair(n, value)); |
|
| 721 |
} |
|
| 722 | 722 |
} |
| 723 | 723 |
} |
| 724 | 724 |
|
| 725 | 725 |
void writeArcs() {
|
| 726 | 726 |
_writer_bits::MapStorageBase<Arc>* label = 0; |
| 727 | 727 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
| 728 |
|
|
| 728 |
it != _arc_maps.end(); ++it) {
|
|
| 729 | 729 |
if (it->first == "label") {
|
| 730 |
label = it->second; |
|
| 731 |
break; |
|
| 732 |
|
|
| 730 |
label = it->second; |
|
| 731 |
break; |
|
| 732 |
} |
|
| 733 | 733 |
} |
| 734 | 734 |
|
| 735 | 735 |
*_os << "@arcs"; |
| 736 | 736 |
if (!_arcs_caption.empty()) {
|
| 737 |
|
|
| 737 |
_writer_bits::writeToken(*_os << ' ', _arcs_caption); |
|
| 738 | 738 |
} |
| 739 | 739 |
*_os << std::endl; |
| 740 | 740 |
|
| 741 | 741 |
*_os << '\t' << '\t'; |
| 742 | 742 |
if (label == 0) {
|
| 743 |
|
|
| 743 |
*_os << "label" << '\t'; |
|
| 744 | 744 |
} |
| 745 | 745 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
| 746 |
it != _arc_maps.end(); ++it) {
|
|
| 747 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 746 |
it != _arc_maps.end(); ++it) {
|
|
| 747 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 748 | 748 |
} |
| 749 | 749 |
*_os << std::endl; |
| 750 | 750 |
|
| 751 | 751 |
std::vector<Arc> arcs; |
| 752 | 752 |
for (ArcIt n(_digraph); n != INVALID; ++n) {
|
| 753 |
|
|
| 753 |
arcs.push_back(n); |
|
| 754 | 754 |
} |
| 755 |
|
|
| 755 |
|
|
| 756 | 756 |
if (label == 0) {
|
| 757 |
IdMap<Digraph, Arc> id_map(_digraph); |
|
| 758 |
_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map); |
|
| 759 |
|
|
| 757 |
IdMap<Digraph, Arc> id_map(_digraph); |
|
| 758 |
_writer_bits::MapLess<IdMap<Digraph, Arc> > id_less(id_map); |
|
| 759 |
std::sort(arcs.begin(), arcs.end(), id_less); |
|
| 760 | 760 |
} else {
|
| 761 |
|
|
| 761 |
label->sort(arcs); |
|
| 762 | 762 |
} |
| 763 | 763 |
|
| 764 | 764 |
for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
|
| 765 |
Arc a = arcs[i]; |
|
| 766 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 767 |
find(_digraph.source(a))->second); |
|
| 768 |
*_os << '\t'; |
|
| 769 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 770 |
find(_digraph.target(a))->second); |
|
| 771 |
*_os << '\t'; |
|
| 772 |
if (label == 0) {
|
|
| 773 |
std::ostringstream os; |
|
| 774 |
os << _digraph.id(a); |
|
| 775 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 776 |
*_os << '\t'; |
|
| 777 |
_arc_index.insert(std::make_pair(a, os.str())); |
|
| 778 |
} |
|
| 779 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 780 |
it != _arc_maps.end(); ++it) {
|
|
| 781 |
std::string value = it->second->get(a); |
|
| 782 |
_writer_bits::writeToken(*_os, value); |
|
| 783 |
if (it->first == "label") {
|
|
| 784 |
_arc_index.insert(std::make_pair(a, value)); |
|
| 785 |
} |
|
| 786 |
*_os << '\t'; |
|
| 787 |
} |
|
| 788 |
*_os << std::endl; |
|
| 765 |
Arc a = arcs[i]; |
|
| 766 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 767 |
find(_digraph.source(a))->second); |
|
| 768 |
*_os << '\t'; |
|
| 769 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 770 |
find(_digraph.target(a))->second); |
|
| 771 |
*_os << '\t'; |
|
| 772 |
if (label == 0) {
|
|
| 773 |
std::ostringstream os; |
|
| 774 |
os << _digraph.id(a); |
|
| 775 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 776 |
*_os << '\t'; |
|
| 777 |
_arc_index.insert(std::make_pair(a, os.str())); |
|
| 778 |
} |
|
| 779 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
|
| 780 |
it != _arc_maps.end(); ++it) {
|
|
| 781 |
std::string value = it->second->get(a); |
|
| 782 |
_writer_bits::writeToken(*_os, value); |
|
| 783 |
if (it->first == "label") {
|
|
| 784 |
_arc_index.insert(std::make_pair(a, value)); |
|
| 785 |
} |
|
| 786 |
*_os << '\t'; |
|
| 787 |
} |
|
| 788 |
*_os << std::endl; |
|
| 789 | 789 |
} |
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 | 792 |
void createArcIndex() {
|
| 793 | 793 |
_writer_bits::MapStorageBase<Arc>* label = 0; |
| 794 | 794 |
for (typename ArcMaps::iterator it = _arc_maps.begin(); |
| 795 |
|
|
| 795 |
it != _arc_maps.end(); ++it) {
|
|
| 796 | 796 |
if (it->first == "label") {
|
| 797 |
label = it->second; |
|
| 798 |
break; |
|
| 799 |
|
|
| 797 |
label = it->second; |
|
| 798 |
break; |
|
| 799 |
} |
|
| 800 | 800 |
} |
| 801 | 801 |
|
| 802 | 802 |
if (label == 0) {
|
| 803 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
| 804 |
std::ostringstream os; |
|
| 805 |
os << _digraph.id(a); |
|
| 806 |
_arc_index.insert(std::make_pair(a, os.str())); |
|
| 807 |
|
|
| 803 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
| 804 |
std::ostringstream os; |
|
| 805 |
os << _digraph.id(a); |
|
| 806 |
_arc_index.insert(std::make_pair(a, os.str())); |
|
| 807 |
} |
|
| 808 | 808 |
} else {
|
| 809 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
| 810 |
std::string value = label->get(a); |
|
| 811 |
_arc_index.insert(std::make_pair(a, value)); |
|
| 812 |
} |
|
| 809 |
for (ArcIt a(_digraph); a != INVALID; ++a) {
|
|
| 810 |
std::string value = label->get(a); |
|
| 811 |
_arc_index.insert(std::make_pair(a, value)); |
|
| 812 |
} |
|
| 813 | 813 |
} |
| 814 | 814 |
} |
| 815 | 815 |
|
| 816 | 816 |
void writeAttributes() {
|
| 817 | 817 |
if (_attributes.empty()) return; |
| 818 | 818 |
*_os << "@attributes"; |
| 819 | 819 |
if (!_attributes_caption.empty()) {
|
| 820 |
|
|
| 820 |
_writer_bits::writeToken(*_os << ' ', _attributes_caption); |
|
| 821 | 821 |
} |
| 822 | 822 |
*_os << std::endl; |
| 823 | 823 |
for (typename Attributes::iterator it = _attributes.begin(); |
| 824 |
it != _attributes.end(); ++it) {
|
|
| 825 |
_writer_bits::writeToken(*_os, it->first) << ' '; |
|
| 826 |
_writer_bits::writeToken(*_os, it->second->get()); |
|
| 827 |
*_os << std::endl; |
|
| 824 |
it != _attributes.end(); ++it) {
|
|
| 825 |
_writer_bits::writeToken(*_os, it->first) << ' '; |
|
| 826 |
_writer_bits::writeToken(*_os, it->second->get()); |
|
| 827 |
*_os << std::endl; |
|
| 828 | 828 |
} |
| 829 | 829 |
} |
| 830 |
|
|
| 830 |
|
|
| 831 | 831 |
public: |
| 832 |
|
|
| 833 |
/// \name Execution of the writer |
|
| 832 |
|
|
| 833 |
/// \name Execution of the writer |
|
| 834 | 834 |
/// @{
|
| 835 | 835 |
|
| 836 | 836 |
/// \brief Start the batch processing |
| 837 | 837 |
/// |
| 838 | 838 |
/// This function starts the batch processing. |
| 839 | 839 |
void run() {
|
| 840 | 840 |
if (!_skip_nodes) {
|
| 841 |
|
|
| 841 |
writeNodes(); |
|
| 842 | 842 |
} else {
|
| 843 |
|
|
| 843 |
createNodeIndex(); |
|
| 844 | 844 |
} |
| 845 |
if (!_skip_arcs) {
|
|
| 846 |
writeArcs(); |
|
| 845 |
if (!_skip_arcs) {
|
|
| 846 |
writeArcs(); |
|
| 847 | 847 |
} else {
|
| 848 |
|
|
| 848 |
createArcIndex(); |
|
| 849 | 849 |
} |
| 850 | 850 |
writeAttributes(); |
| 851 | 851 |
} |
| 852 | 852 |
|
| 853 | 853 |
/// \brief Give back the stream of the writer |
| 854 | 854 |
/// |
| 855 | 855 |
/// Give back the stream of the writer. |
| 856 | 856 |
std::ostream& ostream() {
|
| 857 | 857 |
return *_os; |
| 858 | 858 |
} |
| 859 | 859 |
|
| 860 | 860 |
/// @} |
| 861 | 861 |
}; |
| 862 | 862 |
|
| 863 | 863 |
/// \brief Return a \ref DigraphWriter class |
| 864 |
/// |
|
| 864 |
/// |
|
| 865 | 865 |
/// This function just returns a \ref DigraphWriter class. |
| 866 | 866 |
/// \relates DigraphWriter |
| 867 | 867 |
template <typename Digraph> |
| 868 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, |
|
| 869 |
const Digraph& digraph) {
|
|
| 868 |
DigraphWriter<Digraph> digraphWriter(std::ostream& os, |
|
| 869 |
const Digraph& digraph) {
|
|
| 870 | 870 |
DigraphWriter<Digraph> tmp(os, digraph); |
| 871 | 871 |
return tmp; |
| 872 | 872 |
} |
| 873 | 873 |
|
| 874 | 874 |
/// \brief Return a \ref DigraphWriter class |
| 875 |
/// |
|
| 875 |
/// |
|
| 876 | 876 |
/// This function just returns a \ref DigraphWriter class. |
| 877 | 877 |
/// \relates DigraphWriter |
| 878 | 878 |
template <typename Digraph> |
| 879 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
|
| 880 |
const Digraph& digraph) {
|
|
| 879 |
DigraphWriter<Digraph> digraphWriter(const std::string& fn, |
|
| 880 |
const Digraph& digraph) {
|
|
| 881 | 881 |
DigraphWriter<Digraph> tmp(fn, digraph); |
| 882 | 882 |
return tmp; |
| 883 | 883 |
} |
| 884 | 884 |
|
| 885 | 885 |
/// \brief Return a \ref DigraphWriter class |
| 886 |
/// |
|
| 886 |
/// |
|
| 887 | 887 |
/// This function just returns a \ref DigraphWriter class. |
| 888 | 888 |
/// \relates DigraphWriter |
| 889 | 889 |
template <typename Digraph> |
| 890 |
DigraphWriter<Digraph> digraphWriter(const char* fn, |
|
| 891 |
const Digraph& digraph) {
|
|
| 890 |
DigraphWriter<Digraph> digraphWriter(const char* fn, |
|
| 891 |
const Digraph& digraph) {
|
|
| 892 | 892 |
DigraphWriter<Digraph> tmp(fn, digraph); |
| 893 | 893 |
return tmp; |
| 894 | 894 |
} |
| 895 | 895 |
|
| 896 | 896 |
template <typename Graph> |
| 897 | 897 |
class GraphWriter; |
| 898 | 898 |
|
| 899 | 899 |
template <typename Graph> |
| 900 |
GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph); |
|
| 900 |
GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph); |
|
| 901 | 901 |
|
| 902 | 902 |
template <typename Graph> |
| 903 |
GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph); |
|
| 903 |
GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph); |
|
| 904 | 904 |
|
| 905 | 905 |
template <typename Graph> |
| 906 |
GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph); |
|
| 906 |
GraphWriter<Graph> graphWriter(const char *fn, const Graph& graph); |
|
| 907 | 907 |
|
| 908 | 908 |
/// \ingroup lemon_io |
| 909 |
/// |
|
| 909 |
/// |
|
| 910 | 910 |
/// \brief \ref lgf-format "LGF" writer for directed graphs |
| 911 | 911 |
/// |
| 912 | 912 |
/// This utility writes an \ref lgf-format "LGF" file. |
| 913 | 913 |
/// |
| 914 | 914 |
/// It can be used almost the same way as \c DigraphWriter. |
| 915 | 915 |
/// The only difference is that this class can handle edges and |
| 916 | 916 |
/// edge maps as well as arcs and arc maps. |
| 917 | 917 |
/// |
| 918 | 918 |
/// The arc maps are written into the file as two columns, the |
| 919 | 919 |
/// caption of the columns are the name of the map prefixed with \c |
| 920 | 920 |
/// '+' and \c '-'. The arcs are written into the \c \@attributes |
| 921 | 921 |
/// section as a \c '+' or a \c '-' prefix (depends on the direction |
| 922 | 922 |
/// of the arc) and the label of corresponding edge. |
| 923 | 923 |
template <typename _Graph> |
| 924 | 924 |
class GraphWriter {
|
| 925 | 925 |
public: |
| 926 | 926 |
|
| 927 | 927 |
typedef _Graph Graph; |
| 928 | 928 |
TEMPLATE_GRAPH_TYPEDEFS(Graph); |
| 929 |
|
|
| 929 |
|
|
| 930 | 930 |
private: |
| 931 | 931 |
|
| 932 | 932 |
|
| 933 | 933 |
std::ostream* _os; |
| 934 | 934 |
bool local_os; |
| 935 | 935 |
|
| 936 | 936 |
Graph& _graph; |
| 937 | 937 |
|
| 938 | 938 |
std::string _nodes_caption; |
| 939 | 939 |
std::string _edges_caption; |
| 940 | 940 |
std::string _attributes_caption; |
| 941 |
|
|
| 941 |
|
|
| 942 | 942 |
typedef std::map<Node, std::string> NodeIndex; |
| 943 | 943 |
NodeIndex _node_index; |
| 944 | 944 |
typedef std::map<Edge, std::string> EdgeIndex; |
| 945 | 945 |
EdgeIndex _edge_index; |
| 946 | 946 |
|
| 947 |
typedef std::vector<std::pair<std::string, |
|
| 948 |
_writer_bits::MapStorageBase<Node>* > > NodeMaps; |
|
| 949 |
|
|
| 947 |
typedef std::vector<std::pair<std::string, |
|
| 948 |
_writer_bits::MapStorageBase<Node>* > > NodeMaps; |
|
| 949 |
NodeMaps _node_maps; |
|
| 950 | 950 |
|
| 951 |
typedef std::vector<std::pair<std::string, |
|
| 951 |
typedef std::vector<std::pair<std::string, |
|
| 952 | 952 |
_writer_bits::MapStorageBase<Edge>* > >EdgeMaps; |
| 953 | 953 |
EdgeMaps _edge_maps; |
| 954 | 954 |
|
| 955 |
typedef std::vector<std::pair<std::string, |
|
| 955 |
typedef std::vector<std::pair<std::string, |
|
| 956 | 956 |
_writer_bits::ValueStorageBase*> > Attributes; |
| 957 | 957 |
Attributes _attributes; |
| 958 | 958 |
|
| 959 | 959 |
bool _skip_nodes; |
| 960 | 960 |
bool _skip_edges; |
| 961 | 961 |
|
| 962 | 962 |
public: |
| 963 | 963 |
|
| 964 | 964 |
/// \brief Constructor |
| 965 | 965 |
/// |
| 966 | 966 |
/// Construct a directed graph writer, which writes to the given |
| 967 | 967 |
/// output stream. |
| 968 |
GraphWriter(std::ostream& is, const Graph& graph) |
|
| 968 |
GraphWriter(std::ostream& is, const Graph& graph) |
|
| 969 | 969 |
: _os(&is), local_os(false), _graph(graph), |
| 970 |
|
|
| 970 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 971 | 971 |
|
| 972 | 972 |
/// \brief Constructor |
| 973 | 973 |
/// |
| 974 | 974 |
/// Construct a directed graph writer, which writes to the given |
| 975 | 975 |
/// output file. |
| 976 |
GraphWriter(const std::string& fn, const Graph& graph) |
|
| 976 |
GraphWriter(const std::string& fn, const Graph& graph) |
|
| 977 | 977 |
: _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph), |
| 978 |
|
|
| 978 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 979 | 979 |
|
| 980 | 980 |
/// \brief Constructor |
| 981 | 981 |
/// |
| 982 | 982 |
/// Construct a directed graph writer, which writes to the given |
| 983 | 983 |
/// output file. |
| 984 |
GraphWriter(const char* fn, const Graph& graph) |
|
| 984 |
GraphWriter(const char* fn, const Graph& graph) |
|
| 985 | 985 |
: _os(new std::ofstream(fn)), local_os(true), _graph(graph), |
| 986 |
|
|
| 986 |
_skip_nodes(false), _skip_edges(false) {}
|
|
| 987 | 987 |
|
| 988 | 988 |
/// \brief Destructor |
| 989 | 989 |
~GraphWriter() {
|
| 990 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 991 |
it != _node_maps.end(); ++it) {
|
|
| 992 |
|
|
| 990 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 991 |
it != _node_maps.end(); ++it) {
|
|
| 992 |
delete it->second; |
|
| 993 | 993 |
} |
| 994 | 994 |
|
| 995 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 996 |
it != _edge_maps.end(); ++it) {
|
|
| 997 |
|
|
| 995 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 996 |
it != _edge_maps.end(); ++it) {
|
|
| 997 |
delete it->second; |
|
| 998 | 998 |
} |
| 999 | 999 |
|
| 1000 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 1001 |
it != _attributes.end(); ++it) {
|
|
| 1002 |
|
|
| 1000 |
for (typename Attributes::iterator it = _attributes.begin(); |
|
| 1001 |
it != _attributes.end(); ++it) {
|
|
| 1002 |
delete it->second; |
|
| 1003 | 1003 |
} |
| 1004 | 1004 |
|
| 1005 | 1005 |
if (local_os) {
|
| 1006 |
|
|
| 1006 |
delete _os; |
|
| 1007 | 1007 |
} |
| 1008 | 1008 |
} |
| 1009 |
|
|
| 1009 |
|
|
| 1010 | 1010 |
private: |
| 1011 | 1011 |
|
| 1012 |
friend GraphWriter<Graph> graphWriter<>(std::ostream& os, |
|
| 1013 |
const Graph& graph); |
|
| 1014 |
friend GraphWriter<Graph> graphWriter<>(const std::string& fn, |
|
| 1015 |
const Graph& graph); |
|
| 1016 |
friend GraphWriter<Graph> graphWriter<>(const char *fn, |
|
| 1017 |
const Graph& graph); |
|
| 1012 |
friend GraphWriter<Graph> graphWriter<>(std::ostream& os, |
|
| 1013 |
const Graph& graph); |
|
| 1014 |
friend GraphWriter<Graph> graphWriter<>(const std::string& fn, |
|
| 1015 |
const Graph& graph); |
|
| 1016 |
friend GraphWriter<Graph> graphWriter<>(const char *fn, |
|
| 1017 |
const Graph& graph); |
|
| 1018 | 1018 |
|
| 1019 |
GraphWriter(GraphWriter& other) |
|
| 1019 |
GraphWriter(GraphWriter& other) |
|
| 1020 | 1020 |
: _os(other._os), local_os(other.local_os), _graph(other._graph), |
| 1021 |
|
|
| 1021 |
_skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
|
|
| 1022 | 1022 |
|
| 1023 | 1023 |
other._os = 0; |
| 1024 | 1024 |
other.local_os = false; |
| 1025 | 1025 |
|
| 1026 | 1026 |
_node_index.swap(other._node_index); |
| 1027 | 1027 |
_edge_index.swap(other._edge_index); |
| 1028 | 1028 |
|
| 1029 | 1029 |
_node_maps.swap(other._node_maps); |
| 1030 | 1030 |
_edge_maps.swap(other._edge_maps); |
| 1031 | 1031 |
_attributes.swap(other._attributes); |
| 1032 | 1032 |
|
| 1033 | 1033 |
_nodes_caption = other._nodes_caption; |
| 1034 | 1034 |
_edges_caption = other._edges_caption; |
| 1035 | 1035 |
_attributes_caption = other._attributes_caption; |
| 1036 | 1036 |
} |
| 1037 | 1037 |
|
| 1038 | 1038 |
GraphWriter& operator=(const GraphWriter&); |
| 1039 | 1039 |
|
| 1040 | 1040 |
public: |
| 1041 | 1041 |
|
| 1042 | 1042 |
/// \name Writing rules |
| 1043 | 1043 |
/// @{
|
| 1044 |
|
|
| 1044 |
|
|
| 1045 | 1045 |
/// \brief Node map writing rule |
| 1046 | 1046 |
/// |
| 1047 | 1047 |
/// Add a node map writing rule to the writer. |
| 1048 | 1048 |
template <typename Map> |
| 1049 | 1049 |
GraphWriter& nodeMap(const std::string& caption, const Map& map) {
|
| 1050 | 1050 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 1051 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 1052 |
new _writer_bits::MapStorage<Node, Map>(map); |
|
| 1051 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 1052 |
new _writer_bits::MapStorage<Node, Map>(map); |
|
| 1053 | 1053 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 1054 | 1054 |
return *this; |
| 1055 | 1055 |
} |
| 1056 | 1056 |
|
| 1057 | 1057 |
/// \brief Node map writing rule |
| 1058 | 1058 |
/// |
| 1059 | 1059 |
/// Add a node map writing rule with specialized converter to the |
| 1060 | 1060 |
/// writer. |
| 1061 | 1061 |
template <typename Map, typename Converter> |
| 1062 |
GraphWriter& nodeMap(const std::string& caption, const Map& map, |
|
| 1063 |
const Converter& converter = Converter()) {
|
|
| 1062 |
GraphWriter& nodeMap(const std::string& caption, const Map& map, |
|
| 1063 |
const Converter& converter = Converter()) {
|
|
| 1064 | 1064 |
checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
| 1065 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 1066 |
new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 1065 |
_writer_bits::MapStorageBase<Node>* storage = |
|
| 1066 |
new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
| 1067 | 1067 |
_node_maps.push_back(std::make_pair(caption, storage)); |
| 1068 | 1068 |
return *this; |
| 1069 | 1069 |
} |
| 1070 | 1070 |
|
| 1071 | 1071 |
/// \brief Edge map writing rule |
| 1072 | 1072 |
/// |
| 1073 | 1073 |
/// Add an edge map writing rule to the writer. |
| 1074 | 1074 |
template <typename Map> |
| 1075 | 1075 |
GraphWriter& edgeMap(const std::string& caption, const Map& map) {
|
| 1076 | 1076 |
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
| 1077 |
_writer_bits::MapStorageBase<Edge>* storage = |
|
| 1078 |
new _writer_bits::MapStorage<Edge, Map>(map); |
|
| 1077 |
_writer_bits::MapStorageBase<Edge>* storage = |
|
| 1078 |
new _writer_bits::MapStorage<Edge, Map>(map); |
|
| 1079 | 1079 |
_edge_maps.push_back(std::make_pair(caption, storage)); |
| 1080 | 1080 |
return *this; |
| 1081 | 1081 |
} |
| 1082 | 1082 |
|
| 1083 | 1083 |
/// \brief Edge map writing rule |
| 1084 | 1084 |
/// |
| 1085 | 1085 |
/// Add an edge map writing rule with specialized converter to the |
| 1086 | 1086 |
/// writer. |
| 1087 | 1087 |
template <typename Map, typename Converter> |
| 1088 |
GraphWriter& edgeMap(const std::string& caption, const Map& map, |
|
| 1089 |
const Converter& converter = Converter()) {
|
|
| 1088 |
GraphWriter& edgeMap(const std::string& caption, const Map& map, |
|
| 1089 |
const Converter& converter = Converter()) {
|
|
| 1090 | 1090 |
checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
| 1091 |
_writer_bits::MapStorageBase<Edge>* storage = |
|
| 1092 |
new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter); |
|
| 1091 |
_writer_bits::MapStorageBase<Edge>* storage = |
|
| 1092 |
new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter); |
|
| 1093 | 1093 |
_edge_maps.push_back(std::make_pair(caption, storage)); |
| 1094 | 1094 |
return *this; |
| 1095 | 1095 |
} |
| 1096 | 1096 |
|
| 1097 | 1097 |
/// \brief Arc map writing rule |
| 1098 | 1098 |
/// |
| 1099 | 1099 |
/// Add an arc map writing rule to the writer. |
| 1100 | 1100 |
template <typename Map> |
| 1101 | 1101 |
GraphWriter& arcMap(const std::string& caption, const Map& map) {
|
| 1102 | 1102 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 1103 |
_writer_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1104 |
new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
|
| 1103 |
_writer_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1104 |
new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
|
| 1105 | 1105 |
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
| 1106 |
_writer_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1107 |
new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
|
| 1106 |
_writer_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1107 |
new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
|
| 1108 | 1108 |
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
| 1109 | 1109 |
return *this; |
| 1110 | 1110 |
} |
| 1111 | 1111 |
|
| 1112 | 1112 |
/// \brief Arc map writing rule |
| 1113 | 1113 |
/// |
| 1114 | 1114 |
/// Add an arc map writing rule with specialized converter to the |
| 1115 | 1115 |
/// writer. |
| 1116 | 1116 |
template <typename Map, typename Converter> |
| 1117 |
GraphWriter& arcMap(const std::string& caption, const Map& map, |
|
| 1118 |
const Converter& converter = Converter()) {
|
|
| 1117 |
GraphWriter& arcMap(const std::string& caption, const Map& map, |
|
| 1118 |
const Converter& converter = Converter()) {
|
|
| 1119 | 1119 |
checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
| 1120 |
_writer_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1121 |
new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
|
| 1122 |
|
|
| 1120 |
_writer_bits::MapStorageBase<Edge>* forward_storage = |
|
| 1121 |
new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
|
| 1122 |
(_graph, map, converter); |
|
| 1123 | 1123 |
_edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
|
| 1124 |
_writer_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1125 |
new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
|
| 1126 |
|
|
| 1124 |
_writer_bits::MapStorageBase<Edge>* backward_storage = |
|
| 1125 |
new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
|
| 1126 |
(_graph, map, converter); |
|
| 1127 | 1127 |
_edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
|
| 1128 | 1128 |
return *this; |
| 1129 | 1129 |
} |
| 1130 | 1130 |
|
| 1131 | 1131 |
/// \brief Attribute writing rule |
| 1132 | 1132 |
/// |
| 1133 | 1133 |
/// Add an attribute writing rule to the writer. |
| 1134 | 1134 |
template <typename Value> |
| 1135 | 1135 |
GraphWriter& attribute(const std::string& caption, const Value& value) {
|
| 1136 |
_writer_bits::ValueStorageBase* storage = |
|
| 1137 |
new _writer_bits::ValueStorage<Value>(value); |
|
| 1136 |
_writer_bits::ValueStorageBase* storage = |
|
| 1137 |
new _writer_bits::ValueStorage<Value>(value); |
|
| 1138 | 1138 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 1139 | 1139 |
return *this; |
| 1140 | 1140 |
} |
| 1141 | 1141 |
|
| 1142 | 1142 |
/// \brief Attribute writing rule |
| 1143 | 1143 |
/// |
| 1144 | 1144 |
/// Add an attribute writing rule with specialized converter to the |
| 1145 | 1145 |
/// writer. |
| 1146 | 1146 |
template <typename Value, typename Converter> |
| 1147 |
GraphWriter& attribute(const std::string& caption, const Value& value, |
|
| 1148 |
const Converter& converter = Converter()) {
|
|
| 1149 |
_writer_bits::ValueStorageBase* storage = |
|
| 1150 |
new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 1147 |
GraphWriter& attribute(const std::string& caption, const Value& value, |
|
| 1148 |
const Converter& converter = Converter()) {
|
|
| 1149 |
_writer_bits::ValueStorageBase* storage = |
|
| 1150 |
new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
|
| 1151 | 1151 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 1152 | 1152 |
return *this; |
| 1153 | 1153 |
} |
| 1154 | 1154 |
|
| 1155 | 1155 |
/// \brief Node writing rule |
| 1156 | 1156 |
/// |
| 1157 | 1157 |
/// Add a node writing rule to the writer. |
| 1158 | 1158 |
GraphWriter& node(const std::string& caption, const Node& node) {
|
| 1159 | 1159 |
typedef _writer_bits::MapLookUpConverter<Node> Converter; |
| 1160 | 1160 |
Converter converter(_node_index); |
| 1161 |
_writer_bits::ValueStorageBase* storage = |
|
| 1162 |
new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 1161 |
_writer_bits::ValueStorageBase* storage = |
|
| 1162 |
new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
|
| 1163 | 1163 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 1164 | 1164 |
return *this; |
| 1165 | 1165 |
} |
| 1166 | 1166 |
|
| 1167 | 1167 |
/// \brief Edge writing rule |
| 1168 | 1168 |
/// |
| 1169 | 1169 |
/// Add an edge writing rule to writer. |
| 1170 | 1170 |
GraphWriter& edge(const std::string& caption, const Edge& edge) {
|
| 1171 | 1171 |
typedef _writer_bits::MapLookUpConverter<Edge> Converter; |
| 1172 | 1172 |
Converter converter(_edge_index); |
| 1173 |
_writer_bits::ValueStorageBase* storage = |
|
| 1174 |
new _writer_bits::ValueStorage<Edge, Converter>(edge, converter); |
|
| 1173 |
_writer_bits::ValueStorageBase* storage = |
|
| 1174 |
new _writer_bits::ValueStorage<Edge, Converter>(edge, converter); |
|
| 1175 | 1175 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 1176 | 1176 |
return *this; |
| 1177 | 1177 |
} |
| 1178 | 1178 |
|
| 1179 | 1179 |
/// \brief Arc writing rule |
| 1180 | 1180 |
/// |
| 1181 | 1181 |
/// Add an arc writing rule to writer. |
| 1182 | 1182 |
GraphWriter& arc(const std::string& caption, const Arc& arc) {
|
| 1183 | 1183 |
typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter; |
| 1184 | 1184 |
Converter converter(_graph, _edge_index); |
| 1185 |
_writer_bits::ValueStorageBase* storage = |
|
| 1186 |
new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 1185 |
_writer_bits::ValueStorageBase* storage = |
|
| 1186 |
new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
| 1187 | 1187 |
_attributes.push_back(std::make_pair(caption, storage)); |
| 1188 | 1188 |
return *this; |
| 1189 | 1189 |
} |
| 1190 | 1190 |
|
| 1191 | 1191 |
/// \name Section captions |
| 1192 | 1192 |
/// @{
|
| 1193 | 1193 |
|
| 1194 | 1194 |
/// \brief Add an additional caption to the \c \@nodes section |
| 1195 | 1195 |
/// |
| 1196 | 1196 |
/// Add an additional caption to the \c \@nodes section. |
| 1197 | 1197 |
GraphWriter& nodes(const std::string& caption) {
|
| 1198 | 1198 |
_nodes_caption = caption; |
| 1199 | 1199 |
return *this; |
| 1200 | 1200 |
} |
| 1201 | 1201 |
|
| 1202 | 1202 |
/// \brief Add an additional caption to the \c \@arcs section |
| ... | ... |
@@ -1230,267 +1230,267 @@ |
| 1230 | 1230 |
/// \brief Skip writing edge set |
| 1231 | 1231 |
/// |
| 1232 | 1232 |
/// The \c \@edges section will not be written to the stream. |
| 1233 | 1233 |
GraphWriter& skipEdges() {
|
| 1234 | 1234 |
LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member"); |
| 1235 | 1235 |
_skip_edges = true; |
| 1236 | 1236 |
return *this; |
| 1237 | 1237 |
} |
| 1238 | 1238 |
|
| 1239 | 1239 |
/// @} |
| 1240 | 1240 |
|
| 1241 | 1241 |
private: |
| 1242 | 1242 |
|
| 1243 | 1243 |
void writeNodes() {
|
| 1244 | 1244 |
_writer_bits::MapStorageBase<Node>* label = 0; |
| 1245 | 1245 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 1246 |
|
|
| 1246 |
it != _node_maps.end(); ++it) {
|
|
| 1247 | 1247 |
if (it->first == "label") {
|
| 1248 |
label = it->second; |
|
| 1249 |
break; |
|
| 1250 |
|
|
| 1248 |
label = it->second; |
|
| 1249 |
break; |
|
| 1250 |
} |
|
| 1251 | 1251 |
} |
| 1252 | 1252 |
|
| 1253 | 1253 |
*_os << "@nodes"; |
| 1254 | 1254 |
if (!_nodes_caption.empty()) {
|
| 1255 |
|
|
| 1255 |
_writer_bits::writeToken(*_os << ' ', _nodes_caption); |
|
| 1256 | 1256 |
} |
| 1257 | 1257 |
*_os << std::endl; |
| 1258 | 1258 |
|
| 1259 | 1259 |
if (label == 0) {
|
| 1260 |
|
|
| 1260 |
*_os << "label" << '\t'; |
|
| 1261 | 1261 |
} |
| 1262 | 1262 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 1263 |
it != _node_maps.end(); ++it) {
|
|
| 1264 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 1263 |
it != _node_maps.end(); ++it) {
|
|
| 1264 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 1265 | 1265 |
} |
| 1266 | 1266 |
*_os << std::endl; |
| 1267 | 1267 |
|
| 1268 | 1268 |
std::vector<Node> nodes; |
| 1269 | 1269 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
| 1270 |
|
|
| 1270 |
nodes.push_back(n); |
|
| 1271 | 1271 |
} |
| 1272 |
|
|
| 1272 |
|
|
| 1273 | 1273 |
if (label == 0) {
|
| 1274 |
IdMap<Graph, Node> id_map(_graph); |
|
| 1275 |
_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map); |
|
| 1276 |
|
|
| 1274 |
IdMap<Graph, Node> id_map(_graph); |
|
| 1275 |
_writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map); |
|
| 1276 |
std::sort(nodes.begin(), nodes.end(), id_less); |
|
| 1277 | 1277 |
} else {
|
| 1278 |
|
|
| 1278 |
label->sort(nodes); |
|
| 1279 | 1279 |
} |
| 1280 | 1280 |
|
| 1281 | 1281 |
for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
|
| 1282 |
Node n = nodes[i]; |
|
| 1283 |
if (label == 0) {
|
|
| 1284 |
std::ostringstream os; |
|
| 1285 |
os << _graph.id(n); |
|
| 1286 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 1287 |
*_os << '\t'; |
|
| 1288 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 1289 |
} |
|
| 1290 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 1291 |
it != _node_maps.end(); ++it) {
|
|
| 1292 |
std::string value = it->second->get(n); |
|
| 1293 |
_writer_bits::writeToken(*_os, value); |
|
| 1294 |
if (it->first == "label") {
|
|
| 1295 |
_node_index.insert(std::make_pair(n, value)); |
|
| 1296 |
} |
|
| 1297 |
*_os << '\t'; |
|
| 1298 |
} |
|
| 1299 |
*_os << std::endl; |
|
| 1282 |
Node n = nodes[i]; |
|
| 1283 |
if (label == 0) {
|
|
| 1284 |
std::ostringstream os; |
|
| 1285 |
os << _graph.id(n); |
|
| 1286 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 1287 |
*_os << '\t'; |
|
| 1288 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 1289 |
} |
|
| 1290 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
| 1291 |
it != _node_maps.end(); ++it) {
|
|
| 1292 |
std::string value = it->second->get(n); |
|
| 1293 |
_writer_bits::writeToken(*_os, value); |
|
| 1294 |
if (it->first == "label") {
|
|
| 1295 |
_node_index.insert(std::make_pair(n, value)); |
|
| 1296 |
} |
|
| 1297 |
*_os << '\t'; |
|
| 1298 |
} |
|
| 1299 |
*_os << std::endl; |
|
| 1300 | 1300 |
} |
| 1301 | 1301 |
} |
| 1302 | 1302 |
|
| 1303 | 1303 |
void createNodeIndex() {
|
| 1304 | 1304 |
_writer_bits::MapStorageBase<Node>* label = 0; |
| 1305 | 1305 |
for (typename NodeMaps::iterator it = _node_maps.begin(); |
| 1306 |
|
|
| 1306 |
it != _node_maps.end(); ++it) {
|
|
| 1307 | 1307 |
if (it->first == "label") {
|
| 1308 |
label = it->second; |
|
| 1309 |
break; |
|
| 1310 |
|
|
| 1308 |
label = it->second; |
|
| 1309 |
break; |
|
| 1310 |
} |
|
| 1311 | 1311 |
} |
| 1312 | 1312 |
|
| 1313 | 1313 |
if (label == 0) {
|
| 1314 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
| 1315 |
std::ostringstream os; |
|
| 1316 |
os << _graph.id(n); |
|
| 1317 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 1318 |
|
|
| 1314 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
| 1315 |
std::ostringstream os; |
|
| 1316 |
os << _graph.id(n); |
|
| 1317 |
_node_index.insert(std::make_pair(n, os.str())); |
|
| 1318 |
} |
|
| 1319 | 1319 |
} else {
|
| 1320 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
| 1321 |
std::string value = label->get(n); |
|
| 1322 |
_node_index.insert(std::make_pair(n, value)); |
|
| 1323 |
} |
|
| 1320 |
for (NodeIt n(_graph); n != INVALID; ++n) {
|
|
| 1321 |
std::string value = label->get(n); |
|
| 1322 |
_node_index.insert(std::make_pair(n, value)); |
|
| 1323 |
} |
|
| 1324 | 1324 |
} |
| 1325 | 1325 |
} |
| 1326 | 1326 |
|
| 1327 | 1327 |
void writeEdges() {
|
| 1328 | 1328 |
_writer_bits::MapStorageBase<Edge>* label = 0; |
| 1329 | 1329 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
| 1330 |
|
|
| 1330 |
it != _edge_maps.end(); ++it) {
|
|
| 1331 | 1331 |
if (it->first == "label") {
|
| 1332 |
label = it->second; |
|
| 1333 |
break; |
|
| 1334 |
|
|
| 1332 |
label = it->second; |
|
| 1333 |
break; |
|
| 1334 |
} |
|
| 1335 | 1335 |
} |
| 1336 | 1336 |
|
| 1337 | 1337 |
*_os << "@edges"; |
| 1338 | 1338 |
if (!_edges_caption.empty()) {
|
| 1339 |
|
|
| 1339 |
_writer_bits::writeToken(*_os << ' ', _edges_caption); |
|
| 1340 | 1340 |
} |
| 1341 | 1341 |
*_os << std::endl; |
| 1342 | 1342 |
|
| 1343 | 1343 |
*_os << '\t' << '\t'; |
| 1344 | 1344 |
if (label == 0) {
|
| 1345 |
|
|
| 1345 |
*_os << "label" << '\t'; |
|
| 1346 | 1346 |
} |
| 1347 | 1347 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
| 1348 |
it != _edge_maps.end(); ++it) {
|
|
| 1349 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 1348 |
it != _edge_maps.end(); ++it) {
|
|
| 1349 |
_writer_bits::writeToken(*_os, it->first) << '\t'; |
|
| 1350 | 1350 |
} |
| 1351 | 1351 |
*_os << std::endl; |
| 1352 | 1352 |
|
| 1353 | 1353 |
std::vector<Edge> edges; |
| 1354 | 1354 |
for (EdgeIt n(_graph); n != INVALID; ++n) {
|
| 1355 |
|
|
| 1355 |
edges.push_back(n); |
|
| 1356 | 1356 |
} |
| 1357 |
|
|
| 1357 |
|
|
| 1358 | 1358 |
if (label == 0) {
|
| 1359 |
IdMap<Graph, Edge> id_map(_graph); |
|
| 1360 |
_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map); |
|
| 1361 |
|
|
| 1359 |
IdMap<Graph, Edge> id_map(_graph); |
|
| 1360 |
_writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map); |
|
| 1361 |
std::sort(edges.begin(), edges.end(), id_less); |
|
| 1362 | 1362 |
} else {
|
| 1363 |
|
|
| 1363 |
label->sort(edges); |
|
| 1364 | 1364 |
} |
| 1365 | 1365 |
|
| 1366 | 1366 |
for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
|
| 1367 |
Edge e = edges[i]; |
|
| 1368 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 1369 |
find(_graph.u(e))->second); |
|
| 1370 |
*_os << '\t'; |
|
| 1371 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 1372 |
find(_graph.v(e))->second); |
|
| 1373 |
*_os << '\t'; |
|
| 1374 |
if (label == 0) {
|
|
| 1375 |
std::ostringstream os; |
|
| 1376 |
os << _graph.id(e); |
|
| 1377 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 1378 |
*_os << '\t'; |
|
| 1379 |
_edge_index.insert(std::make_pair(e, os.str())); |
|
| 1380 |
} |
|
| 1381 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 1382 |
it != _edge_maps.end(); ++it) {
|
|
| 1383 |
std::string value = it->second->get(e); |
|
| 1384 |
_writer_bits::writeToken(*_os, value); |
|
| 1385 |
if (it->first == "label") {
|
|
| 1386 |
_edge_index.insert(std::make_pair(e, value)); |
|
| 1387 |
} |
|
| 1388 |
*_os << '\t'; |
|
| 1389 |
} |
|
| 1390 |
*_os << std::endl; |
|
| 1367 |
Edge e = edges[i]; |
|
| 1368 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 1369 |
find(_graph.u(e))->second); |
|
| 1370 |
*_os << '\t'; |
|
| 1371 |
_writer_bits::writeToken(*_os, _node_index. |
|
| 1372 |
find(_graph.v(e))->second); |
|
| 1373 |
*_os << '\t'; |
|
| 1374 |
if (label == 0) {
|
|
| 1375 |
std::ostringstream os; |
|
| 1376 |
os << _graph.id(e); |
|
| 1377 |
_writer_bits::writeToken(*_os, os.str()); |
|
| 1378 |
*_os << '\t'; |
|
| 1379 |
_edge_index.insert(std::make_pair(e, os.str())); |
|
| 1380 |
} |
|
| 1381 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
| 1382 |
it != _edge_maps.end(); ++it) {
|
|
| 1383 |
std::string value = it->second->get(e); |
|
| 1384 |
_writer_bits::writeToken(*_os, value); |
|
| 1385 |
if (it->first == "label") {
|
|
| 1386 |
_edge_index.insert(std::make_pair(e, value)); |
|
| 1387 |
} |
|
| 1388 |
*_os << '\t'; |
|
| 1389 |
} |
|
| 1390 |
*_os << std::endl; |
|
| 1391 | 1391 |
} |
| 1392 | 1392 |
} |
| 1393 | 1393 |
|
| 1394 | 1394 |
void createEdgeIndex() {
|
| 1395 | 1395 |
_writer_bits::MapStorageBase<Edge>* label = 0; |
| 1396 | 1396 |
for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
| 1397 |
|
|
| 1397 |
it != _edge_maps.end(); ++it) {
|
|
| 1398 | 1398 |
if (it->first == "label") {
|
| 1399 |
label = it->second; |
|
| 1400 |
break; |
|
| 1401 |
|
|
| 1399 |
label = it->second; |
|
| 1400 |
break; |
|
| 1401 |
} |
|
| 1402 | 1402 |
} |
| 1403 | 1403 |
|
| 1404 | 1404 |
if (label == 0) {
|
| 1405 |
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
| 1406 |
std::ostringstream os; |
|
| 1407 |
os << _graph.id(e); |
|
| 1408 |
_edge_index.insert(std::make_pair(e, os.str())); |
|
| 1409 |
|
|
| 1405 |
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
| 1406 |
std::ostringstream os; |
|
| 1407 |
os << _graph.id(e); |
|
| 1408 |
_edge_index.insert(std::make_pair(e, os.str())); |
|
| 1409 |
} |
|
| 1410 | 1410 |
} else {
|
| 1411 |
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
| 1412 |
std::string value = label->get(e); |
|
| 1413 |
_edge_index.insert(std::make_pair(e, value)); |
|
| 1414 |
} |
|
| 1411 |
for (EdgeIt e(_graph); e != INVALID; ++e) {
|
|
| 1412 |
std::string value = label->get(e); |
|
| 1413 |
_edge_index.insert(std::make_pair(e, value)); |
|
| 1414 |
} |
|
| 1415 | 1415 |
} |
| 1416 | 1416 |
} |
| 1417 | 1417 |
|
| 1418 | 1418 |
void writeAttributes() {
|
| 1419 | 1419 |
if (_attributes.empty()) return; |
| 1420 | 1420 |
*_os << "@attributes"; |
| 1421 | 1421 |
if (!_attributes_caption.empty()) {
|
| 1422 |
|
|
| 1422 |
_writer_bits::writeToken(*_os << ' ', _attributes_caption); |
|
| 1423 | 1423 |
} |
| 1424 | 1424 |
*_os << std::endl; |
| 1425 | 1425 |
for (typename Attributes::iterator it = _attributes.begin(); |
| 1426 |
it != _attributes.end(); ++it) {
|
|
| 1427 |
_writer_bits::writeToken(*_os, it->first) << ' '; |
|
| 1428 |
_writer_bits::writeToken(*_os, it->second->get()); |
|
| 1429 |
*_os << std::endl; |
|
| 1426 |
it != _attributes.end(); ++it) {
|
|
| 1427 |
_writer_bits::writeToken(*_os, it->first) << ' '; |
|
| 1428 |
_writer_bits::writeToken(*_os, it->second->get()); |
|
| 1429 |
*_os << std::endl; |
|
| 1430 | 1430 |
} |
| 1431 | 1431 |
} |
| 1432 |
|
|
| 1432 |
|
|
| 1433 | 1433 |
public: |
| 1434 |
|
|
| 1435 |
/// \name Execution of the writer |
|
| 1434 |
|
|
| 1435 |
/// \name Execution of the writer |
|
| 1436 | 1436 |
/// @{
|
| 1437 | 1437 |
|
| 1438 | 1438 |
/// \brief Start the batch processing |
| 1439 | 1439 |
/// |
| 1440 | 1440 |
/// This function starts the batch processing. |
| 1441 | 1441 |
void run() {
|
| 1442 | 1442 |
if (!_skip_nodes) {
|
| 1443 |
|
|
| 1443 |
writeNodes(); |
|
| 1444 | 1444 |
} else {
|
| 1445 |
|
|
| 1445 |
createNodeIndex(); |
|
| 1446 | 1446 |
} |
| 1447 |
if (!_skip_edges) {
|
|
| 1448 |
writeEdges(); |
|
| 1447 |
if (!_skip_edges) {
|
|
| 1448 |
writeEdges(); |
|
| 1449 | 1449 |
} else {
|
| 1450 |
|
|
| 1450 |
createEdgeIndex(); |
|
| 1451 | 1451 |
} |
| 1452 | 1452 |
writeAttributes(); |
| 1453 | 1453 |
} |
| 1454 | 1454 |
|
| 1455 | 1455 |
/// \brief Give back the stream of the writer |
| 1456 | 1456 |
/// |
| 1457 | 1457 |
/// Give back the stream of the writer |
| 1458 | 1458 |
std::ostream& ostream() {
|
| 1459 | 1459 |
return *_os; |
| 1460 | 1460 |
} |
| 1461 | 1461 |
|
| 1462 | 1462 |
/// @} |
| 1463 | 1463 |
}; |
| 1464 | 1464 |
|
| 1465 | 1465 |
/// \brief Return a \ref GraphWriter class |
| 1466 |
/// |
|
| 1466 |
/// |
|
| 1467 | 1467 |
/// This function just returns a \ref GraphWriter class. |
| 1468 | 1468 |
/// \relates GraphWriter |
| 1469 | 1469 |
template <typename Graph> |
| 1470 | 1470 |
GraphWriter<Graph> graphWriter(std::ostream& os, const Graph& graph) {
|
| 1471 | 1471 |
GraphWriter<Graph> tmp(os, graph); |
| 1472 | 1472 |
return tmp; |
| 1473 | 1473 |
} |
| 1474 | 1474 |
|
| 1475 | 1475 |
/// \brief Return a \ref GraphWriter class |
| 1476 |
/// |
|
| 1476 |
/// |
|
| 1477 | 1477 |
/// This function just returns a \ref GraphWriter class. |
| 1478 | 1478 |
/// \relates GraphWriter |
| 1479 | 1479 |
template <typename Graph> |
| 1480 | 1480 |
GraphWriter<Graph> graphWriter(const std::string& fn, const Graph& graph) {
|
| 1481 | 1481 |
GraphWriter<Graph> tmp(fn, graph); |
| 1482 | 1482 |
return tmp; |
| 1483 | 1483 |
} |
| 1484 | 1484 |
|
| 1485 | 1485 |
/// \brief Return a \ref GraphWriter class |
| 1486 |
/// |
|
| 1486 |
/// |
|
| 1487 | 1487 |
/// This function just returns a \ref GraphWriter class. |
| 1488 | 1488 |
/// \relates GraphWriter |
| 1489 | 1489 |
template <typename Graph> |
| 1490 | 1490 |
GraphWriter<Graph> graphWriter(const char* fn, const Graph& graph) {
|
| 1491 | 1491 |
GraphWriter<Graph> tmp(fn, graph); |
| 1492 | 1492 |
return tmp; |
| 1493 | 1493 |
} |
| 1494 | 1494 |
} |
| 1495 | 1495 |
|
| 1496 | 1496 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_LIST_GRAPH_H |
| ... | ... |
@@ -24,53 +24,53 @@ |
| 24 | 24 |
///\brief ListDigraph, ListGraph classes. |
| 25 | 25 |
|
| 26 | 26 |
#include <lemon/bits/graph_extender.h> |
| 27 | 27 |
|
| 28 | 28 |
#include <vector> |
| 29 | 29 |
#include <list> |
| 30 | 30 |
|
| 31 | 31 |
namespace lemon {
|
| 32 | 32 |
|
| 33 | 33 |
class ListDigraphBase {
|
| 34 | 34 |
|
| 35 | 35 |
protected: |
| 36 | 36 |
struct NodeT {
|
| 37 | 37 |
int first_in, first_out; |
| 38 | 38 |
int prev, next; |
| 39 | 39 |
}; |
| 40 |
|
|
| 40 |
|
|
| 41 | 41 |
struct ArcT {
|
| 42 | 42 |
int target, source; |
| 43 | 43 |
int prev_in, prev_out; |
| 44 | 44 |
int next_in, next_out; |
| 45 | 45 |
}; |
| 46 | 46 |
|
| 47 | 47 |
std::vector<NodeT> nodes; |
| 48 | 48 |
|
| 49 | 49 |
int first_node; |
| 50 | 50 |
|
| 51 | 51 |
int first_free_node; |
| 52 | 52 |
|
| 53 | 53 |
std::vector<ArcT> arcs; |
| 54 | 54 |
|
| 55 | 55 |
int first_free_arc; |
| 56 |
|
|
| 56 |
|
|
| 57 | 57 |
public: |
| 58 |
|
|
| 58 |
|
|
| 59 | 59 |
typedef ListDigraphBase Digraph; |
| 60 |
|
|
| 60 |
|
|
| 61 | 61 |
class Node {
|
| 62 | 62 |
friend class ListDigraphBase; |
| 63 | 63 |
protected: |
| 64 | 64 |
|
| 65 | 65 |
int id; |
| 66 | 66 |
explicit Node(int pid) { id = pid;}
|
| 67 | 67 |
|
| 68 | 68 |
public: |
| 69 | 69 |
Node() {}
|
| 70 | 70 |
Node (Invalid) { id = -1; }
|
| 71 | 71 |
bool operator==(const Node& node) const {return id == node.id;}
|
| 72 | 72 |
bool operator!=(const Node& node) const {return id != node.id;}
|
| 73 | 73 |
bool operator<(const Node& node) const {return id < node.id;}
|
| 74 | 74 |
}; |
| 75 | 75 |
|
| 76 | 76 |
class Arc {
|
| ... | ... |
@@ -79,345 +79,345 @@ |
| 79 | 79 |
|
| 80 | 80 |
int id; |
| 81 | 81 |
explicit Arc(int pid) { id = pid;}
|
| 82 | 82 |
|
| 83 | 83 |
public: |
| 84 | 84 |
Arc() {}
|
| 85 | 85 |
Arc (Invalid) { id = -1; }
|
| 86 | 86 |
bool operator==(const Arc& arc) const {return id == arc.id;}
|
| 87 | 87 |
bool operator!=(const Arc& arc) const {return id != arc.id;}
|
| 88 | 88 |
bool operator<(const Arc& arc) const {return id < arc.id;}
|
| 89 | 89 |
}; |
| 90 | 90 |
|
| 91 | 91 |
|
| 92 | 92 |
|
| 93 | 93 |
ListDigraphBase() |
| 94 | 94 |
: nodes(), first_node(-1), |
| 95 |
|
|
| 95 |
first_free_node(-1), arcs(), first_free_arc(-1) {}
|
|
| 96 | 96 |
|
| 97 |
|
|
| 98 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 97 |
|
|
| 98 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 99 | 99 |
int maxArcId() const { return arcs.size()-1; }
|
| 100 | 100 |
|
| 101 | 101 |
Node source(Arc e) const { return Node(arcs[e.id].source); }
|
| 102 | 102 |
Node target(Arc e) const { return Node(arcs[e.id].target); }
|
| 103 | 103 |
|
| 104 | 104 |
|
| 105 |
void first(Node& node) const {
|
|
| 105 |
void first(Node& node) const {
|
|
| 106 | 106 |
node.id = first_node; |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
void next(Node& node) const {
|
| 110 | 110 |
node.id = nodes[node.id].next; |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 | 113 |
|
| 114 |
void first(Arc& arc) const {
|
|
| 114 |
void first(Arc& arc) const {
|
|
| 115 | 115 |
int n; |
| 116 |
for(n = first_node; |
|
| 117 |
n!=-1 && nodes[n].first_in == -1; |
|
| 118 |
|
|
| 116 |
for(n = first_node; |
|
| 117 |
n!=-1 && nodes[n].first_in == -1; |
|
| 118 |
n = nodes[n].next) {}
|
|
| 119 | 119 |
arc.id = (n == -1) ? -1 : nodes[n].first_in; |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
void next(Arc& arc) const {
|
| 123 | 123 |
if (arcs[arc.id].next_in != -1) {
|
| 124 |
|
|
| 124 |
arc.id = arcs[arc.id].next_in; |
|
| 125 | 125 |
} else {
|
| 126 |
int n; |
|
| 127 |
for(n = nodes[arcs[arc.id].target].next; |
|
| 128 |
n!=-1 && nodes[n].first_in == -1; |
|
| 129 |
n = nodes[n].next) {}
|
|
| 130 |
arc.id = (n == -1) ? -1 : nodes[n].first_in; |
|
| 131 |
} |
|
| 126 |
int n; |
|
| 127 |
for(n = nodes[arcs[arc.id].target].next; |
|
| 128 |
n!=-1 && nodes[n].first_in == -1; |
|
| 129 |
n = nodes[n].next) {}
|
|
| 130 |
arc.id = (n == -1) ? -1 : nodes[n].first_in; |
|
| 131 |
} |
|
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 | 134 |
void firstOut(Arc &e, const Node& v) const {
|
| 135 | 135 |
e.id = nodes[v.id].first_out; |
| 136 | 136 |
} |
| 137 | 137 |
void nextOut(Arc &e) const {
|
| 138 | 138 |
e.id=arcs[e.id].next_out; |
| 139 | 139 |
} |
| 140 | 140 |
|
| 141 | 141 |
void firstIn(Arc &e, const Node& v) const {
|
| 142 | 142 |
e.id = nodes[v.id].first_in; |
| 143 | 143 |
} |
| 144 | 144 |
void nextIn(Arc &e) const {
|
| 145 | 145 |
e.id=arcs[e.id].next_in; |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 |
|
|
| 148 |
|
|
| 149 | 149 |
static int id(Node v) { return v.id; }
|
| 150 | 150 |
static int id(Arc e) { return e.id; }
|
| 151 | 151 |
|
| 152 | 152 |
static Node nodeFromId(int id) { return Node(id);}
|
| 153 | 153 |
static Arc arcFromId(int id) { return Arc(id);}
|
| 154 | 154 |
|
| 155 |
bool valid(Node n) const {
|
|
| 156 |
return n.id >= 0 && n.id < static_cast<int>(nodes.size()) && |
|
| 157 |
|
|
| 155 |
bool valid(Node n) const {
|
|
| 156 |
return n.id >= 0 && n.id < static_cast<int>(nodes.size()) && |
|
| 157 |
nodes[n.id].prev != -2; |
|
| 158 | 158 |
} |
| 159 | 159 |
|
| 160 |
bool valid(Arc a) const {
|
|
| 161 |
return a.id >= 0 && a.id < static_cast<int>(arcs.size()) && |
|
| 162 |
|
|
| 160 |
bool valid(Arc a) const {
|
|
| 161 |
return a.id >= 0 && a.id < static_cast<int>(arcs.size()) && |
|
| 162 |
arcs[a.id].prev_in != -2; |
|
| 163 | 163 |
} |
| 164 | 164 |
|
| 165 |
Node addNode() {
|
|
| 165 |
Node addNode() {
|
|
| 166 | 166 |
int n; |
| 167 |
|
|
| 167 |
|
|
| 168 | 168 |
if(first_free_node==-1) {
|
| 169 |
n = nodes.size(); |
|
| 170 |
nodes.push_back(NodeT()); |
|
| 169 |
n = nodes.size(); |
|
| 170 |
nodes.push_back(NodeT()); |
|
| 171 | 171 |
} else {
|
| 172 |
n = first_free_node; |
|
| 173 |
first_free_node = nodes[n].next; |
|
| 172 |
n = first_free_node; |
|
| 173 |
first_free_node = nodes[n].next; |
|
| 174 | 174 |
} |
| 175 |
|
|
| 175 |
|
|
| 176 | 176 |
nodes[n].next = first_node; |
| 177 | 177 |
if(first_node != -1) nodes[first_node].prev = n; |
| 178 | 178 |
first_node = n; |
| 179 | 179 |
nodes[n].prev = -1; |
| 180 |
|
|
| 180 |
|
|
| 181 | 181 |
nodes[n].first_in = nodes[n].first_out = -1; |
| 182 |
|
|
| 182 |
|
|
| 183 | 183 |
return Node(n); |
| 184 | 184 |
} |
| 185 |
|
|
| 185 |
|
|
| 186 | 186 |
Arc addArc(Node u, Node v) {
|
| 187 |
int n; |
|
| 187 |
int n; |
|
| 188 | 188 |
|
| 189 | 189 |
if (first_free_arc == -1) {
|
| 190 |
n = arcs.size(); |
|
| 191 |
arcs.push_back(ArcT()); |
|
| 190 |
n = arcs.size(); |
|
| 191 |
arcs.push_back(ArcT()); |
|
| 192 | 192 |
} else {
|
| 193 |
n = first_free_arc; |
|
| 194 |
first_free_arc = arcs[n].next_in; |
|
| 193 |
n = first_free_arc; |
|
| 194 |
first_free_arc = arcs[n].next_in; |
|
| 195 | 195 |
} |
| 196 |
|
|
| 197 |
arcs[n].source = u.id; |
|
| 196 |
|
|
| 197 |
arcs[n].source = u.id; |
|
| 198 | 198 |
arcs[n].target = v.id; |
| 199 | 199 |
|
| 200 | 200 |
arcs[n].next_out = nodes[u.id].first_out; |
| 201 | 201 |
if(nodes[u.id].first_out != -1) {
|
| 202 |
|
|
| 202 |
arcs[nodes[u.id].first_out].prev_out = n; |
|
| 203 | 203 |
} |
| 204 |
|
|
| 204 |
|
|
| 205 | 205 |
arcs[n].next_in = nodes[v.id].first_in; |
| 206 | 206 |
if(nodes[v.id].first_in != -1) {
|
| 207 |
|
|
| 207 |
arcs[nodes[v.id].first_in].prev_in = n; |
|
| 208 | 208 |
} |
| 209 |
|
|
| 209 |
|
|
| 210 | 210 |
arcs[n].prev_in = arcs[n].prev_out = -1; |
| 211 |
|
|
| 211 |
|
|
| 212 | 212 |
nodes[u.id].first_out = nodes[v.id].first_in = n; |
| 213 | 213 |
|
| 214 | 214 |
return Arc(n); |
| 215 | 215 |
} |
| 216 |
|
|
| 216 |
|
|
| 217 | 217 |
void erase(const Node& node) {
|
| 218 | 218 |
int n = node.id; |
| 219 |
|
|
| 219 |
|
|
| 220 | 220 |
if(nodes[n].next != -1) {
|
| 221 |
|
|
| 221 |
nodes[nodes[n].next].prev = nodes[n].prev; |
|
| 222 | 222 |
} |
| 223 |
|
|
| 223 |
|
|
| 224 | 224 |
if(nodes[n].prev != -1) {
|
| 225 |
|
|
| 225 |
nodes[nodes[n].prev].next = nodes[n].next; |
|
| 226 | 226 |
} else {
|
| 227 |
|
|
| 227 |
first_node = nodes[n].next; |
|
| 228 | 228 |
} |
| 229 |
|
|
| 229 |
|
|
| 230 | 230 |
nodes[n].next = first_free_node; |
| 231 | 231 |
first_free_node = n; |
| 232 | 232 |
nodes[n].prev = -2; |
| 233 | 233 |
|
| 234 | 234 |
} |
| 235 |
|
|
| 235 |
|
|
| 236 | 236 |
void erase(const Arc& arc) {
|
| 237 | 237 |
int n = arc.id; |
| 238 |
|
|
| 238 |
|
|
| 239 | 239 |
if(arcs[n].next_in!=-1) {
|
| 240 |
|
|
| 240 |
arcs[arcs[n].next_in].prev_in = arcs[n].prev_in; |
|
| 241 | 241 |
} |
| 242 | 242 |
|
| 243 | 243 |
if(arcs[n].prev_in!=-1) {
|
| 244 |
|
|
| 244 |
arcs[arcs[n].prev_in].next_in = arcs[n].next_in; |
|
| 245 | 245 |
} else {
|
| 246 |
|
|
| 246 |
nodes[arcs[n].target].first_in = arcs[n].next_in; |
|
| 247 | 247 |
} |
| 248 | 248 |
|
| 249 |
|
|
| 249 |
|
|
| 250 | 250 |
if(arcs[n].next_out!=-1) {
|
| 251 |
arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; |
|
| 252 |
} |
|
| 251 |
arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; |
|
| 252 |
} |
|
| 253 | 253 |
|
| 254 | 254 |
if(arcs[n].prev_out!=-1) {
|
| 255 |
|
|
| 255 |
arcs[arcs[n].prev_out].next_out = arcs[n].next_out; |
|
| 256 | 256 |
} else {
|
| 257 |
|
|
| 257 |
nodes[arcs[n].source].first_out = arcs[n].next_out; |
|
| 258 | 258 |
} |
| 259 |
|
|
| 259 |
|
|
| 260 | 260 |
arcs[n].next_in = first_free_arc; |
| 261 | 261 |
first_free_arc = n; |
| 262 | 262 |
arcs[n].prev_in = -2; |
| 263 | 263 |
} |
| 264 | 264 |
|
| 265 | 265 |
void clear() {
|
| 266 | 266 |
arcs.clear(); |
| 267 | 267 |
nodes.clear(); |
| 268 | 268 |
first_node = first_free_node = first_free_arc = -1; |
| 269 | 269 |
} |
| 270 | 270 |
|
| 271 | 271 |
protected: |
| 272 |
void changeTarget(Arc e, Node n) |
|
| 272 |
void changeTarget(Arc e, Node n) |
|
| 273 | 273 |
{
|
| 274 | 274 |
if(arcs[e.id].next_in != -1) |
| 275 |
|
|
| 275 |
arcs[arcs[e.id].next_in].prev_in = arcs[e.id].prev_in; |
|
| 276 | 276 |
if(arcs[e.id].prev_in != -1) |
| 277 |
|
|
| 277 |
arcs[arcs[e.id].prev_in].next_in = arcs[e.id].next_in; |
|
| 278 | 278 |
else nodes[arcs[e.id].target].first_in = arcs[e.id].next_in; |
| 279 | 279 |
if (nodes[n.id].first_in != -1) {
|
| 280 |
|
|
| 280 |
arcs[nodes[n.id].first_in].prev_in = e.id; |
|
| 281 | 281 |
} |
| 282 | 282 |
arcs[e.id].target = n.id; |
| 283 | 283 |
arcs[e.id].prev_in = -1; |
| 284 | 284 |
arcs[e.id].next_in = nodes[n.id].first_in; |
| 285 | 285 |
nodes[n.id].first_in = e.id; |
| 286 | 286 |
} |
| 287 |
void changeSource(Arc e, Node n) |
|
| 287 |
void changeSource(Arc e, Node n) |
|
| 288 | 288 |
{
|
| 289 | 289 |
if(arcs[e.id].next_out != -1) |
| 290 |
|
|
| 290 |
arcs[arcs[e.id].next_out].prev_out = arcs[e.id].prev_out; |
|
| 291 | 291 |
if(arcs[e.id].prev_out != -1) |
| 292 |
|
|
| 292 |
arcs[arcs[e.id].prev_out].next_out = arcs[e.id].next_out; |
|
| 293 | 293 |
else nodes[arcs[e.id].source].first_out = arcs[e.id].next_out; |
| 294 | 294 |
if (nodes[n.id].first_out != -1) {
|
| 295 |
|
|
| 295 |
arcs[nodes[n.id].first_out].prev_out = e.id; |
|
| 296 | 296 |
} |
| 297 | 297 |
arcs[e.id].source = n.id; |
| 298 | 298 |
arcs[e.id].prev_out = -1; |
| 299 | 299 |
arcs[e.id].next_out = nodes[n.id].first_out; |
| 300 | 300 |
nodes[n.id].first_out = e.id; |
| 301 | 301 |
} |
| 302 | 302 |
|
| 303 | 303 |
}; |
| 304 | 304 |
|
| 305 | 305 |
typedef DigraphExtender<ListDigraphBase> ExtendedListDigraphBase; |
| 306 | 306 |
|
| 307 | 307 |
/// \addtogroup graphs |
| 308 | 308 |
/// @{
|
| 309 | 309 |
|
| 310 |
///A general directed graph structure. |
|
| 310 |
///A general directed graph structure. |
|
| 311 | 311 |
|
| 312 |
///\ref ListDigraph is a simple and fast <em>directed graph</em> |
|
| 313 |
///implementation based on static linked lists that are stored in |
|
| 314 |
///\ |
|
| 312 |
///\ref ListDigraph is a simple and fast <em>directed graph</em> |
|
| 313 |
///implementation based on static linked lists that are stored in |
|
| 314 |
///\c std::vector structures. |
|
| 315 | 315 |
/// |
| 316 | 316 |
///It conforms to the \ref concepts::Digraph "Digraph concept" and it |
| 317 | 317 |
///also provides several useful additional functionalities. |
| 318 | 318 |
///Most of the member functions and nested classes are documented |
| 319 | 319 |
///only in the concept class. |
| 320 | 320 |
/// |
| 321 | 321 |
///An important extra feature of this digraph implementation is that |
| 322 | 322 |
///its maps are real \ref concepts::ReferenceMap "reference map"s. |
| 323 | 323 |
/// |
| 324 | 324 |
///\sa concepts::Digraph |
| 325 | 325 |
|
| 326 | 326 |
class ListDigraph : public ExtendedListDigraphBase {
|
| 327 | 327 |
private: |
| 328 | 328 |
///ListDigraph is \e not copy constructible. Use copyDigraph() instead. |
| 329 |
|
|
| 329 |
|
|
| 330 | 330 |
///ListDigraph is \e not copy constructible. Use copyDigraph() instead. |
| 331 | 331 |
/// |
| 332 | 332 |
ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
|
| 333 | 333 |
///\brief Assignment of ListDigraph to another one is \e not allowed. |
| 334 | 334 |
///Use copyDigraph() instead. |
| 335 | 335 |
|
| 336 | 336 |
///Assignment of ListDigraph to another one is \e not allowed. |
| 337 | 337 |
///Use copyDigraph() instead. |
| 338 | 338 |
void operator=(const ListDigraph &) {}
|
| 339 | 339 |
public: |
| 340 | 340 |
|
| 341 | 341 |
typedef ExtendedListDigraphBase Parent; |
| 342 | 342 |
|
| 343 | 343 |
/// Constructor |
| 344 |
|
|
| 344 |
|
|
| 345 | 345 |
/// Constructor. |
| 346 | 346 |
/// |
| 347 | 347 |
ListDigraph() {}
|
| 348 | 348 |
|
| 349 | 349 |
///Add a new node to the digraph. |
| 350 |
|
|
| 350 |
|
|
| 351 | 351 |
///Add a new node to the digraph. |
| 352 | 352 |
///\return the new node. |
| 353 | 353 |
Node addNode() { return Parent::addNode(); }
|
| 354 | 354 |
|
| 355 | 355 |
///Add a new arc to the digraph. |
| 356 |
|
|
| 356 |
|
|
| 357 | 357 |
///Add a new arc to the digraph with source node \c s |
| 358 | 358 |
///and target node \c t. |
| 359 | 359 |
///\return the new arc. |
| 360 |
Arc addArc(const Node& s, const Node& t) {
|
|
| 361 |
return Parent::addArc(s, t); |
|
| 360 |
Arc addArc(const Node& s, const Node& t) {
|
|
| 361 |
return Parent::addArc(s, t); |
|
| 362 | 362 |
} |
| 363 | 363 |
|
| 364 | 364 |
/// Node validity check |
| 365 | 365 |
|
| 366 | 366 |
/// This function gives back true if the given node is valid, |
| 367 |
/// ie. it is a real node of the graph. |
|
| 367 |
/// ie. it is a real node of the graph. |
|
| 368 | 368 |
/// |
| 369 | 369 |
/// \warning A Node pointing to a removed item |
| 370 | 370 |
/// could become valid again later if new nodes are |
| 371 | 371 |
/// added to the graph. |
| 372 | 372 |
bool valid(Node n) const { return Parent::valid(n); }
|
| 373 | 373 |
|
| 374 | 374 |
/// Arc validity check |
| 375 | 375 |
|
| 376 | 376 |
/// This function gives back true if the given arc is valid, |
| 377 |
/// ie. it is a real arc of the graph. |
|
| 377 |
/// ie. it is a real arc of the graph. |
|
| 378 | 378 |
/// |
| 379 | 379 |
/// \warning An Arc pointing to a removed item |
| 380 | 380 |
/// could become valid again later if new nodes are |
| 381 | 381 |
/// added to the graph. |
| 382 | 382 |
bool valid(Arc a) const { return Parent::valid(a); }
|
| 383 | 383 |
|
| 384 | 384 |
/// Change the target of \c e to \c n |
| 385 | 385 |
|
| 386 | 386 |
/// Change the target of \c e to \c n |
| 387 | 387 |
/// |
| 388 | 388 |
///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing |
| 389 | 389 |
///the changed arc remain valid. However <tt>InArcIt</tt>s are |
| 390 | 390 |
///invalidated. |
| 391 | 391 |
/// |
| 392 | 392 |
///\warning This functionality cannot be used together with the Snapshot |
| 393 | 393 |
///feature. |
| 394 |
void changeTarget(Arc e, Node n) {
|
|
| 395 |
Parent::changeTarget(e,n); |
|
| 394 |
void changeTarget(Arc e, Node n) {
|
|
| 395 |
Parent::changeTarget(e,n); |
|
| 396 | 396 |
} |
| 397 | 397 |
/// Change the source of \c e to \c n |
| 398 | 398 |
|
| 399 | 399 |
/// Change the source of \c e to \c n |
| 400 | 400 |
/// |
| 401 | 401 |
///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s referencing |
| 402 | 402 |
///the changed arc remain valid. However <tt>OutArcIt</tt>s are |
| 403 | 403 |
///invalidated. |
| 404 | 404 |
/// |
| 405 | 405 |
///\warning This functionality cannot be used together with the Snapshot |
| 406 | 406 |
///feature. |
| 407 |
void changeSource(Arc e, Node n) {
|
|
| 407 |
void changeSource(Arc e, Node n) {
|
|
| 408 | 408 |
Parent::changeSource(e,n); |
| 409 | 409 |
} |
| 410 | 410 |
|
| 411 | 411 |
/// Invert the direction of an arc. |
| 412 | 412 |
|
| 413 | 413 |
///\note The <tt>ArcIt</tt>s referencing the changed arc remain |
| 414 | 414 |
///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are |
| 415 | 415 |
///invalidated. |
| 416 | 416 |
/// |
| 417 | 417 |
///\warning This functionality cannot be used together with the Snapshot |
| 418 | 418 |
///feature. |
| 419 | 419 |
void reverseArc(Arc e) {
|
| 420 | 420 |
Node t=target(e); |
| 421 | 421 |
changeTarget(e,source(e)); |
| 422 | 422 |
changeSource(e,t); |
| 423 | 423 |
} |
| ... | ... |
@@ -443,366 +443,366 @@ |
| 443 | 443 |
void reserveArc(int m) { arcs.reserve(m); };
|
| 444 | 444 |
|
| 445 | 445 |
///Contract two nodes. |
| 446 | 446 |
|
| 447 | 447 |
///This function contracts two nodes. |
| 448 | 448 |
///Node \p b will be removed but instead of deleting |
| 449 | 449 |
///incident arcs, they will be joined to \p a. |
| 450 | 450 |
///The last parameter \p r controls whether to remove loops. \c true |
| 451 | 451 |
///means that loops will be removed. |
| 452 | 452 |
/// |
| 453 | 453 |
///\note The <tt>ArcIt</tt>s referencing a moved arc remain |
| 454 | 454 |
///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s |
| 455 | 455 |
///may be invalidated. |
| 456 | 456 |
/// |
| 457 | 457 |
///\warning This functionality cannot be used together with the Snapshot |
| 458 | 458 |
///feature. |
| 459 |
void contract(Node a, Node b, bool r = true) |
|
| 459 |
void contract(Node a, Node b, bool r = true) |
|
| 460 | 460 |
{
|
| 461 | 461 |
for(OutArcIt e(*this,b);e!=INVALID;) {
|
| 462 |
OutArcIt f=e; |
|
| 463 |
++f; |
|
| 464 |
if(r && target(e)==a) erase(e); |
|
| 465 |
else changeSource(e,a); |
|
| 466 |
|
|
| 462 |
OutArcIt f=e; |
|
| 463 |
++f; |
|
| 464 |
if(r && target(e)==a) erase(e); |
|
| 465 |
else changeSource(e,a); |
|
| 466 |
e=f; |
|
| 467 | 467 |
} |
| 468 | 468 |
for(InArcIt e(*this,b);e!=INVALID;) {
|
| 469 |
InArcIt f=e; |
|
| 470 |
++f; |
|
| 471 |
if(r && source(e)==a) erase(e); |
|
| 472 |
else changeTarget(e,a); |
|
| 473 |
|
|
| 469 |
InArcIt f=e; |
|
| 470 |
++f; |
|
| 471 |
if(r && source(e)==a) erase(e); |
|
| 472 |
else changeTarget(e,a); |
|
| 473 |
e=f; |
|
| 474 | 474 |
} |
| 475 | 475 |
erase(b); |
| 476 | 476 |
} |
| 477 | 477 |
|
| 478 | 478 |
///Split a node. |
| 479 | 479 |
|
| 480 | 480 |
///This function splits a node. First a new node is added to the digraph, |
| 481 | 481 |
///then the source of each outgoing arc of \c n is moved to this new node. |
| 482 | 482 |
///If \c connect is \c true (this is the default value), then a new arc |
| 483 | 483 |
///from \c n to the newly created node is also added. |
| 484 | 484 |
///\return The newly created node. |
| 485 | 485 |
/// |
| 486 | 486 |
///\note The <tt>ArcIt</tt>s referencing a moved arc remain |
| 487 | 487 |
///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s may |
| 488 |
///be invalidated. |
|
| 488 |
///be invalidated. |
|
| 489 | 489 |
/// |
| 490 | 490 |
///\warning This functionality cannot be used together with the |
| 491 | 491 |
///Snapshot feature. |
| 492 | 492 |
/// |
| 493 | 493 |
///\todo It could be implemented in a bit faster way. |
| 494 | 494 |
Node split(Node n, bool connect = true) {
|
| 495 | 495 |
Node b = addNode(); |
| 496 | 496 |
for(OutArcIt e(*this,n);e!=INVALID;) {
|
| 497 |
OutArcIt f=e; |
|
| 498 |
++f; |
|
| 499 |
changeSource(e,b); |
|
| 500 |
e=f; |
|
| 497 |
OutArcIt f=e; |
|
| 498 |
++f; |
|
| 499 |
changeSource(e,b); |
|
| 500 |
e=f; |
|
| 501 | 501 |
} |
| 502 | 502 |
if (connect) addArc(n,b); |
| 503 | 503 |
return b; |
| 504 | 504 |
} |
| 505 |
|
|
| 505 |
|
|
| 506 | 506 |
///Split an arc. |
| 507 | 507 |
|
| 508 | 508 |
///This function splits an arc. First a new node \c b is added to |
| 509 | 509 |
///the digraph, then the original arc is re-targeted to \c |
| 510 | 510 |
///b. Finally an arc from \c b to the original target is added. |
| 511 | 511 |
/// |
| 512 | 512 |
///\return The newly created node. |
| 513 | 513 |
/// |
| 514 | 514 |
///\warning This functionality cannot be used together with the |
| 515 | 515 |
///Snapshot feature. |
| 516 | 516 |
Node split(Arc e) {
|
| 517 | 517 |
Node b = addNode(); |
| 518 | 518 |
addArc(b,target(e)); |
| 519 | 519 |
changeTarget(e,b); |
| 520 | 520 |
return b; |
| 521 | 521 |
} |
| 522 |
|
|
| 522 |
|
|
| 523 | 523 |
/// \brief Class to make a snapshot of the digraph and restore |
| 524 | 524 |
/// it later. |
| 525 | 525 |
/// |
| 526 | 526 |
/// Class to make a snapshot of the digraph and restore it later. |
| 527 | 527 |
/// |
| 528 | 528 |
/// The newly added nodes and arcs can be removed using the |
| 529 | 529 |
/// restore() function. |
| 530 | 530 |
/// |
| 531 | 531 |
/// \warning Arc and node deletions and other modifications (e.g. |
| 532 |
/// contracting, splitting, reversing arcs or nodes) cannot be |
|
| 533 |
/// restored. These events invalidate the snapshot. |
|
| 532 |
/// contracting, splitting, reversing arcs or nodes) cannot be |
|
| 533 |
/// restored. These events invalidate the snapshot. |
|
| 534 | 534 |
class Snapshot {
|
| 535 | 535 |
protected: |
| 536 | 536 |
|
| 537 | 537 |
typedef Parent::NodeNotifier NodeNotifier; |
| 538 | 538 |
|
| 539 | 539 |
class NodeObserverProxy : public NodeNotifier::ObserverBase {
|
| 540 | 540 |
public: |
| 541 | 541 |
|
| 542 | 542 |
NodeObserverProxy(Snapshot& _snapshot) |
| 543 | 543 |
: snapshot(_snapshot) {}
|
| 544 | 544 |
|
| 545 | 545 |
using NodeNotifier::ObserverBase::attach; |
| 546 | 546 |
using NodeNotifier::ObserverBase::detach; |
| 547 | 547 |
using NodeNotifier::ObserverBase::attached; |
| 548 |
|
|
| 548 |
|
|
| 549 | 549 |
protected: |
| 550 |
|
|
| 550 |
|
|
| 551 | 551 |
virtual void add(const Node& node) {
|
| 552 | 552 |
snapshot.addNode(node); |
| 553 | 553 |
} |
| 554 | 554 |
virtual void add(const std::vector<Node>& nodes) {
|
| 555 | 555 |
for (int i = nodes.size() - 1; i >= 0; ++i) {
|
| 556 | 556 |
snapshot.addNode(nodes[i]); |
| 557 | 557 |
} |
| 558 | 558 |
} |
| 559 | 559 |
virtual void erase(const Node& node) {
|
| 560 | 560 |
snapshot.eraseNode(node); |
| 561 | 561 |
} |
| 562 | 562 |
virtual void erase(const std::vector<Node>& nodes) {
|
| 563 | 563 |
for (int i = 0; i < int(nodes.size()); ++i) {
|
| 564 | 564 |
snapshot.eraseNode(nodes[i]); |
| 565 | 565 |
} |
| 566 | 566 |
} |
| 567 | 567 |
virtual void build() {
|
| 568 | 568 |
Node node; |
| 569 | 569 |
std::vector<Node> nodes; |
| 570 |
for (notifier()->first(node); node != INVALID; |
|
| 570 |
for (notifier()->first(node); node != INVALID; |
|
| 571 | 571 |
notifier()->next(node)) {
|
| 572 | 572 |
nodes.push_back(node); |
| 573 | 573 |
} |
| 574 | 574 |
for (int i = nodes.size() - 1; i >= 0; --i) {
|
| 575 | 575 |
snapshot.addNode(nodes[i]); |
| 576 | 576 |
} |
| 577 | 577 |
} |
| 578 | 578 |
virtual void clear() {
|
| 579 | 579 |
Node node; |
| 580 |
for (notifier()->first(node); node != INVALID; |
|
| 580 |
for (notifier()->first(node); node != INVALID; |
|
| 581 | 581 |
notifier()->next(node)) {
|
| 582 | 582 |
snapshot.eraseNode(node); |
| 583 | 583 |
} |
| 584 | 584 |
} |
| 585 | 585 |
|
| 586 | 586 |
Snapshot& snapshot; |
| 587 | 587 |
}; |
| 588 | 588 |
|
| 589 | 589 |
class ArcObserverProxy : public ArcNotifier::ObserverBase {
|
| 590 | 590 |
public: |
| 591 | 591 |
|
| 592 | 592 |
ArcObserverProxy(Snapshot& _snapshot) |
| 593 | 593 |
: snapshot(_snapshot) {}
|
| 594 | 594 |
|
| 595 | 595 |
using ArcNotifier::ObserverBase::attach; |
| 596 | 596 |
using ArcNotifier::ObserverBase::detach; |
| 597 | 597 |
using ArcNotifier::ObserverBase::attached; |
| 598 |
|
|
| 598 |
|
|
| 599 | 599 |
protected: |
| 600 | 600 |
|
| 601 | 601 |
virtual void add(const Arc& arc) {
|
| 602 | 602 |
snapshot.addArc(arc); |
| 603 | 603 |
} |
| 604 | 604 |
virtual void add(const std::vector<Arc>& arcs) {
|
| 605 | 605 |
for (int i = arcs.size() - 1; i >= 0; ++i) {
|
| 606 | 606 |
snapshot.addArc(arcs[i]); |
| 607 | 607 |
} |
| 608 | 608 |
} |
| 609 | 609 |
virtual void erase(const Arc& arc) {
|
| 610 | 610 |
snapshot.eraseArc(arc); |
| 611 | 611 |
} |
| 612 | 612 |
virtual void erase(const std::vector<Arc>& arcs) {
|
| 613 | 613 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 614 | 614 |
snapshot.eraseArc(arcs[i]); |
| 615 | 615 |
} |
| 616 | 616 |
} |
| 617 | 617 |
virtual void build() {
|
| 618 | 618 |
Arc arc; |
| 619 | 619 |
std::vector<Arc> arcs; |
| 620 |
for (notifier()->first(arc); arc != INVALID; |
|
| 620 |
for (notifier()->first(arc); arc != INVALID; |
|
| 621 | 621 |
notifier()->next(arc)) {
|
| 622 | 622 |
arcs.push_back(arc); |
| 623 | 623 |
} |
| 624 | 624 |
for (int i = arcs.size() - 1; i >= 0; --i) {
|
| 625 | 625 |
snapshot.addArc(arcs[i]); |
| 626 | 626 |
} |
| 627 | 627 |
} |
| 628 | 628 |
virtual void clear() {
|
| 629 | 629 |
Arc arc; |
| 630 |
for (notifier()->first(arc); arc != INVALID; |
|
| 630 |
for (notifier()->first(arc); arc != INVALID; |
|
| 631 | 631 |
notifier()->next(arc)) {
|
| 632 | 632 |
snapshot.eraseArc(arc); |
| 633 | 633 |
} |
| 634 | 634 |
} |
| 635 | 635 |
|
| 636 | 636 |
Snapshot& snapshot; |
| 637 | 637 |
}; |
| 638 |
|
|
| 638 |
|
|
| 639 | 639 |
ListDigraph *digraph; |
| 640 | 640 |
|
| 641 | 641 |
NodeObserverProxy node_observer_proxy; |
| 642 | 642 |
ArcObserverProxy arc_observer_proxy; |
| 643 | 643 |
|
| 644 | 644 |
std::list<Node> added_nodes; |
| 645 | 645 |
std::list<Arc> added_arcs; |
| 646 | 646 |
|
| 647 | 647 |
|
| 648 | 648 |
void addNode(const Node& node) {
|
| 649 |
added_nodes.push_front(node); |
|
| 649 |
added_nodes.push_front(node); |
|
| 650 | 650 |
} |
| 651 | 651 |
void eraseNode(const Node& node) {
|
| 652 |
std::list<Node>::iterator it = |
|
| 652 |
std::list<Node>::iterator it = |
|
| 653 | 653 |
std::find(added_nodes.begin(), added_nodes.end(), node); |
| 654 | 654 |
if (it == added_nodes.end()) {
|
| 655 | 655 |
clear(); |
| 656 | 656 |
arc_observer_proxy.detach(); |
| 657 | 657 |
throw NodeNotifier::ImmediateDetach(); |
| 658 | 658 |
} else {
|
| 659 | 659 |
added_nodes.erase(it); |
| 660 | 660 |
} |
| 661 | 661 |
} |
| 662 | 662 |
|
| 663 | 663 |
void addArc(const Arc& arc) {
|
| 664 |
added_arcs.push_front(arc); |
|
| 664 |
added_arcs.push_front(arc); |
|
| 665 | 665 |
} |
| 666 | 666 |
void eraseArc(const Arc& arc) {
|
| 667 |
std::list<Arc>::iterator it = |
|
| 667 |
std::list<Arc>::iterator it = |
|
| 668 | 668 |
std::find(added_arcs.begin(), added_arcs.end(), arc); |
| 669 | 669 |
if (it == added_arcs.end()) {
|
| 670 | 670 |
clear(); |
| 671 |
node_observer_proxy.detach(); |
|
| 671 |
node_observer_proxy.detach(); |
|
| 672 | 672 |
throw ArcNotifier::ImmediateDetach(); |
| 673 | 673 |
} else {
|
| 674 | 674 |
added_arcs.erase(it); |
| 675 |
} |
|
| 675 |
} |
|
| 676 | 676 |
} |
| 677 | 677 |
|
| 678 | 678 |
void attach(ListDigraph &_digraph) {
|
| 679 |
digraph = &_digraph; |
|
| 680 |
node_observer_proxy.attach(digraph->notifier(Node())); |
|
| 679 |
digraph = &_digraph; |
|
| 680 |
node_observer_proxy.attach(digraph->notifier(Node())); |
|
| 681 | 681 |
arc_observer_proxy.attach(digraph->notifier(Arc())); |
| 682 | 682 |
} |
| 683 |
|
|
| 683 |
|
|
| 684 | 684 |
void detach() {
|
| 685 |
node_observer_proxy.detach(); |
|
| 686 |
arc_observer_proxy.detach(); |
|
| 685 |
node_observer_proxy.detach(); |
|
| 686 |
arc_observer_proxy.detach(); |
|
| 687 | 687 |
} |
| 688 | 688 |
|
| 689 | 689 |
bool attached() const {
|
| 690 | 690 |
return node_observer_proxy.attached(); |
| 691 | 691 |
} |
| 692 | 692 |
|
| 693 | 693 |
void clear() {
|
| 694 | 694 |
added_nodes.clear(); |
| 695 |
added_arcs.clear(); |
|
| 695 |
added_arcs.clear(); |
|
| 696 | 696 |
} |
| 697 | 697 |
|
| 698 | 698 |
public: |
| 699 | 699 |
|
| 700 | 700 |
/// \brief Default constructor. |
| 701 | 701 |
/// |
| 702 | 702 |
/// Default constructor. |
| 703 | 703 |
/// To actually make a snapshot you must call save(). |
| 704 |
Snapshot() |
|
| 705 |
: digraph(0), node_observer_proxy(*this), |
|
| 704 |
Snapshot() |
|
| 705 |
: digraph(0), node_observer_proxy(*this), |
|
| 706 | 706 |
arc_observer_proxy(*this) {}
|
| 707 |
|
|
| 707 |
|
|
| 708 | 708 |
/// \brief Constructor that immediately makes a snapshot. |
| 709 |
/// |
|
| 709 |
/// |
|
| 710 | 710 |
/// This constructor immediately makes a snapshot of the digraph. |
| 711 | 711 |
/// \param _digraph The digraph we make a snapshot of. |
| 712 |
Snapshot(ListDigraph &_digraph) |
|
| 713 |
: node_observer_proxy(*this), |
|
| 712 |
Snapshot(ListDigraph &_digraph) |
|
| 713 |
: node_observer_proxy(*this), |
|
| 714 | 714 |
arc_observer_proxy(*this) {
|
| 715 |
|
|
| 715 |
attach(_digraph); |
|
| 716 | 716 |
} |
| 717 |
|
|
| 717 |
|
|
| 718 | 718 |
/// \brief Make a snapshot. |
| 719 | 719 |
/// |
| 720 | 720 |
/// Make a snapshot of the digraph. |
| 721 | 721 |
/// |
| 722 | 722 |
/// This function can be called more than once. In case of a repeated |
| 723 | 723 |
/// call, the previous snapshot gets lost. |
| 724 | 724 |
/// \param _digraph The digraph we make the snapshot of. |
| 725 | 725 |
void save(ListDigraph &_digraph) {
|
| 726 | 726 |
if (attached()) {
|
| 727 | 727 |
detach(); |
| 728 | 728 |
clear(); |
| 729 | 729 |
} |
| 730 | 730 |
attach(_digraph); |
| 731 | 731 |
} |
| 732 |
|
|
| 732 |
|
|
| 733 | 733 |
/// \brief Undo the changes until the last snapshot. |
| 734 |
// |
|
| 734 |
// |
|
| 735 | 735 |
/// Undo the changes until the last snapshot created by save(). |
| 736 | 736 |
void restore() {
|
| 737 |
detach(); |
|
| 738 |
for(std::list<Arc>::iterator it = added_arcs.begin(); |
|
| 737 |
detach(); |
|
| 738 |
for(std::list<Arc>::iterator it = added_arcs.begin(); |
|
| 739 | 739 |
it != added_arcs.end(); ++it) {
|
| 740 |
digraph->erase(*it); |
|
| 741 |
} |
|
| 742 |
|
|
| 740 |
digraph->erase(*it); |
|
| 741 |
} |
|
| 742 |
for(std::list<Node>::iterator it = added_nodes.begin(); |
|
| 743 | 743 |
it != added_nodes.end(); ++it) {
|
| 744 |
digraph->erase(*it); |
|
| 745 |
} |
|
| 744 |
digraph->erase(*it); |
|
| 745 |
} |
|
| 746 | 746 |
clear(); |
| 747 | 747 |
} |
| 748 | 748 |
|
| 749 | 749 |
/// \brief Gives back true when the snapshot is valid. |
| 750 | 750 |
/// |
| 751 | 751 |
/// Gives back true when the snapshot is valid. |
| 752 | 752 |
bool valid() const {
|
| 753 | 753 |
return attached(); |
| 754 | 754 |
} |
| 755 | 755 |
}; |
| 756 |
|
|
| 756 |
|
|
| 757 | 757 |
}; |
| 758 | 758 |
|
| 759 | 759 |
///@} |
| 760 | 760 |
|
| 761 | 761 |
class ListGraphBase {
|
| 762 | 762 |
|
| 763 | 763 |
protected: |
| 764 | 764 |
|
| 765 | 765 |
struct NodeT {
|
| 766 | 766 |
int first_out; |
| 767 | 767 |
int prev, next; |
| 768 | 768 |
}; |
| 769 |
|
|
| 769 |
|
|
| 770 | 770 |
struct ArcT {
|
| 771 | 771 |
int target; |
| 772 | 772 |
int prev_out, next_out; |
| 773 | 773 |
}; |
| 774 | 774 |
|
| 775 | 775 |
std::vector<NodeT> nodes; |
| 776 | 776 |
|
| 777 | 777 |
int first_node; |
| 778 | 778 |
|
| 779 | 779 |
int first_free_node; |
| 780 | 780 |
|
| 781 | 781 |
std::vector<ArcT> arcs; |
| 782 | 782 |
|
| 783 | 783 |
int first_free_arc; |
| 784 |
|
|
| 784 |
|
|
| 785 | 785 |
public: |
| 786 |
|
|
| 786 |
|
|
| 787 | 787 |
typedef ListGraphBase Digraph; |
| 788 | 788 |
|
| 789 | 789 |
class Node; |
| 790 | 790 |
class Arc; |
| 791 | 791 |
class Edge; |
| 792 |
|
|
| 792 |
|
|
| 793 | 793 |
class Node {
|
| 794 | 794 |
friend class ListGraphBase; |
| 795 | 795 |
protected: |
| 796 | 796 |
|
| 797 | 797 |
int id; |
| 798 | 798 |
explicit Node(int pid) { id = pid;}
|
| 799 | 799 |
|
| 800 | 800 |
public: |
| 801 | 801 |
Node() {}
|
| 802 | 802 |
Node (Invalid) { id = -1; }
|
| 803 | 803 |
bool operator==(const Node& node) const {return id == node.id;}
|
| 804 | 804 |
bool operator!=(const Node& node) const {return id != node.id;}
|
| 805 | 805 |
bool operator<(const Node& node) const {return id < node.id;}
|
| 806 | 806 |
}; |
| 807 | 807 |
|
| 808 | 808 |
class Edge {
|
| ... | ... |
@@ -828,117 +828,117 @@ |
| 828 | 828 |
explicit Arc(int pid) { id = pid;}
|
| 829 | 829 |
|
| 830 | 830 |
public: |
| 831 | 831 |
operator Edge() const { return edgeFromId(id / 2); }
|
| 832 | 832 |
|
| 833 | 833 |
Arc() {}
|
| 834 | 834 |
Arc (Invalid) { id = -1; }
|
| 835 | 835 |
bool operator==(const Arc& arc) const {return id == arc.id;}
|
| 836 | 836 |
bool operator!=(const Arc& arc) const {return id != arc.id;}
|
| 837 | 837 |
bool operator<(const Arc& arc) const {return id < arc.id;}
|
| 838 | 838 |
}; |
| 839 | 839 |
|
| 840 | 840 |
|
| 841 | 841 |
|
| 842 | 842 |
ListGraphBase() |
| 843 | 843 |
: nodes(), first_node(-1), |
| 844 |
|
|
| 844 |
first_free_node(-1), arcs(), first_free_arc(-1) {}
|
|
| 845 | 845 |
|
| 846 |
|
|
| 847 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 846 |
|
|
| 847 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 848 | 848 |
int maxEdgeId() const { return arcs.size() / 2 - 1; }
|
| 849 | 849 |
int maxArcId() const { return arcs.size()-1; }
|
| 850 | 850 |
|
| 851 | 851 |
Node source(Arc e) const { return Node(arcs[e.id ^ 1].target); }
|
| 852 | 852 |
Node target(Arc e) const { return Node(arcs[e.id].target); }
|
| 853 | 853 |
|
| 854 | 854 |
Node u(Edge e) const { return Node(arcs[2 * e.id].target); }
|
| 855 | 855 |
Node v(Edge e) const { return Node(arcs[2 * e.id + 1].target); }
|
| 856 | 856 |
|
| 857 | 857 |
static bool direction(Arc e) {
|
| 858 | 858 |
return (e.id & 1) == 1; |
| 859 | 859 |
} |
| 860 | 860 |
|
| 861 | 861 |
static Arc direct(Edge e, bool d) {
|
| 862 | 862 |
return Arc(e.id * 2 + (d ? 1 : 0)); |
| 863 | 863 |
} |
| 864 | 864 |
|
| 865 |
void first(Node& node) const {
|
|
| 865 |
void first(Node& node) const {
|
|
| 866 | 866 |
node.id = first_node; |
| 867 | 867 |
} |
| 868 | 868 |
|
| 869 | 869 |
void next(Node& node) const {
|
| 870 | 870 |
node.id = nodes[node.id].next; |
| 871 | 871 |
} |
| 872 | 872 |
|
| 873 |
void first(Arc& e) const {
|
|
| 873 |
void first(Arc& e) const {
|
|
| 874 | 874 |
int n = first_node; |
| 875 | 875 |
while (n != -1 && nodes[n].first_out == -1) {
|
| 876 | 876 |
n = nodes[n].next; |
| 877 | 877 |
} |
| 878 | 878 |
e.id = (n == -1) ? -1 : nodes[n].first_out; |
| 879 | 879 |
} |
| 880 | 880 |
|
| 881 | 881 |
void next(Arc& e) const {
|
| 882 | 882 |
if (arcs[e.id].next_out != -1) {
|
| 883 |
|
|
| 883 |
e.id = arcs[e.id].next_out; |
|
| 884 | 884 |
} else {
|
| 885 |
|
|
| 885 |
int n = nodes[arcs[e.id ^ 1].target].next; |
|
| 886 | 886 |
while(n != -1 && nodes[n].first_out == -1) {
|
| 887 | 887 |
n = nodes[n].next; |
| 888 | 888 |
} |
| 889 |
e.id = (n == -1) ? -1 : nodes[n].first_out; |
|
| 890 |
} |
|
| 889 |
e.id = (n == -1) ? -1 : nodes[n].first_out; |
|
| 890 |
} |
|
| 891 | 891 |
} |
| 892 | 892 |
|
| 893 |
void first(Edge& e) const {
|
|
| 893 |
void first(Edge& e) const {
|
|
| 894 | 894 |
int n = first_node; |
| 895 | 895 |
while (n != -1) {
|
| 896 | 896 |
e.id = nodes[n].first_out; |
| 897 | 897 |
while ((e.id & 1) != 1) {
|
| 898 | 898 |
e.id = arcs[e.id].next_out; |
| 899 | 899 |
} |
| 900 | 900 |
if (e.id != -1) {
|
| 901 | 901 |
e.id /= 2; |
| 902 | 902 |
return; |
| 903 |
} |
|
| 903 |
} |
|
| 904 | 904 |
n = nodes[n].next; |
| 905 | 905 |
} |
| 906 | 906 |
e.id = -1; |
| 907 | 907 |
} |
| 908 | 908 |
|
| 909 | 909 |
void next(Edge& e) const {
|
| 910 | 910 |
int n = arcs[e.id * 2].target; |
| 911 | 911 |
e.id = arcs[(e.id * 2) | 1].next_out; |
| 912 | 912 |
while ((e.id & 1) != 1) {
|
| 913 | 913 |
e.id = arcs[e.id].next_out; |
| 914 | 914 |
} |
| 915 | 915 |
if (e.id != -1) {
|
| 916 | 916 |
e.id /= 2; |
| 917 | 917 |
return; |
| 918 |
} |
|
| 918 |
} |
|
| 919 | 919 |
n = nodes[n].next; |
| 920 | 920 |
while (n != -1) {
|
| 921 | 921 |
e.id = nodes[n].first_out; |
| 922 | 922 |
while ((e.id & 1) != 1) {
|
| 923 | 923 |
e.id = arcs[e.id].next_out; |
| 924 | 924 |
} |
| 925 | 925 |
if (e.id != -1) {
|
| 926 | 926 |
e.id /= 2; |
| 927 | 927 |
return; |
| 928 |
} |
|
| 928 |
} |
|
| 929 | 929 |
n = nodes[n].next; |
| 930 | 930 |
} |
| 931 | 931 |
e.id = -1; |
| 932 | 932 |
} |
| 933 | 933 |
|
| 934 | 934 |
void firstOut(Arc &e, const Node& v) const {
|
| 935 | 935 |
e.id = nodes[v.id].first_out; |
| 936 | 936 |
} |
| 937 | 937 |
void nextOut(Arc &e) const {
|
| 938 | 938 |
e.id = arcs[e.id].next_out; |
| 939 | 939 |
} |
| 940 | 940 |
|
| 941 | 941 |
void firstIn(Arc &e, const Node& v) const {
|
| 942 | 942 |
e.id = ((nodes[v.id].first_out) ^ 1); |
| 943 | 943 |
if (e.id == -2) e.id = -1; |
| 944 | 944 |
} |
| ... | ... |
@@ -954,611 +954,611 @@ |
| 954 | 954 |
d = ((a & 1) == 1); |
| 955 | 955 |
} else {
|
| 956 | 956 |
e.id = -1; |
| 957 | 957 |
d = true; |
| 958 | 958 |
} |
| 959 | 959 |
} |
| 960 | 960 |
void nextInc(Edge &e, bool& d) const {
|
| 961 | 961 |
int a = (arcs[(e.id * 2) | (d ? 1 : 0)].next_out); |
| 962 | 962 |
if (a != -1 ) {
|
| 963 | 963 |
e.id = a / 2; |
| 964 | 964 |
d = ((a & 1) == 1); |
| 965 | 965 |
} else {
|
| 966 | 966 |
e.id = -1; |
| 967 | 967 |
d = true; |
| 968 | 968 |
} |
| 969 | 969 |
} |
| 970 |
|
|
| 970 |
|
|
| 971 | 971 |
static int id(Node v) { return v.id; }
|
| 972 | 972 |
static int id(Arc e) { return e.id; }
|
| 973 | 973 |
static int id(Edge e) { return e.id; }
|
| 974 | 974 |
|
| 975 | 975 |
static Node nodeFromId(int id) { return Node(id);}
|
| 976 | 976 |
static Arc arcFromId(int id) { return Arc(id);}
|
| 977 | 977 |
static Edge edgeFromId(int id) { return Edge(id);}
|
| 978 | 978 |
|
| 979 |
bool valid(Node n) const {
|
|
| 980 |
return n.id >= 0 && n.id < static_cast<int>(nodes.size()) && |
|
| 981 |
|
|
| 979 |
bool valid(Node n) const {
|
|
| 980 |
return n.id >= 0 && n.id < static_cast<int>(nodes.size()) && |
|
| 981 |
nodes[n.id].prev != -2; |
|
| 982 | 982 |
} |
| 983 | 983 |
|
| 984 |
bool valid(Arc a) const {
|
|
| 985 |
return a.id >= 0 && a.id < static_cast<int>(arcs.size()) && |
|
| 986 |
|
|
| 984 |
bool valid(Arc a) const {
|
|
| 985 |
return a.id >= 0 && a.id < static_cast<int>(arcs.size()) && |
|
| 986 |
arcs[a.id].prev_out != -2; |
|
| 987 | 987 |
} |
| 988 | 988 |
|
| 989 |
bool valid(Edge e) const {
|
|
| 990 |
return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) && |
|
| 991 |
|
|
| 989 |
bool valid(Edge e) const {
|
|
| 990 |
return e.id >= 0 && 2 * e.id < static_cast<int>(arcs.size()) && |
|
| 991 |
arcs[2 * e.id].prev_out != -2; |
|
| 992 | 992 |
} |
| 993 | 993 |
|
| 994 |
Node addNode() {
|
|
| 994 |
Node addNode() {
|
|
| 995 | 995 |
int n; |
| 996 |
|
|
| 996 |
|
|
| 997 | 997 |
if(first_free_node==-1) {
|
| 998 |
n = nodes.size(); |
|
| 999 |
nodes.push_back(NodeT()); |
|
| 998 |
n = nodes.size(); |
|
| 999 |
nodes.push_back(NodeT()); |
|
| 1000 | 1000 |
} else {
|
| 1001 |
n = first_free_node; |
|
| 1002 |
first_free_node = nodes[n].next; |
|
| 1001 |
n = first_free_node; |
|
| 1002 |
first_free_node = nodes[n].next; |
|
| 1003 | 1003 |
} |
| 1004 |
|
|
| 1004 |
|
|
| 1005 | 1005 |
nodes[n].next = first_node; |
| 1006 | 1006 |
if (first_node != -1) nodes[first_node].prev = n; |
| 1007 | 1007 |
first_node = n; |
| 1008 | 1008 |
nodes[n].prev = -1; |
| 1009 |
|
|
| 1009 |
|
|
| 1010 | 1010 |
nodes[n].first_out = -1; |
| 1011 |
|
|
| 1011 |
|
|
| 1012 | 1012 |
return Node(n); |
| 1013 | 1013 |
} |
| 1014 |
|
|
| 1014 |
|
|
| 1015 | 1015 |
Edge addEdge(Node u, Node v) {
|
| 1016 |
int n; |
|
| 1016 |
int n; |
|
| 1017 | 1017 |
|
| 1018 | 1018 |
if (first_free_arc == -1) {
|
| 1019 |
n = arcs.size(); |
|
| 1020 |
arcs.push_back(ArcT()); |
|
| 1021 |
|
|
| 1019 |
n = arcs.size(); |
|
| 1020 |
arcs.push_back(ArcT()); |
|
| 1021 |
arcs.push_back(ArcT()); |
|
| 1022 | 1022 |
} else {
|
| 1023 |
n = first_free_arc; |
|
| 1024 |
first_free_arc = arcs[n].next_out; |
|
| 1023 |
n = first_free_arc; |
|
| 1024 |
first_free_arc = arcs[n].next_out; |
|
| 1025 | 1025 |
} |
| 1026 |
|
|
| 1026 |
|
|
| 1027 | 1027 |
arcs[n].target = u.id; |
| 1028 | 1028 |
arcs[n | 1].target = v.id; |
| 1029 | 1029 |
|
| 1030 | 1030 |
arcs[n].next_out = nodes[v.id].first_out; |
| 1031 | 1031 |
if (nodes[v.id].first_out != -1) {
|
| 1032 |
arcs[nodes[v.id].first_out].prev_out = n; |
|
| 1033 |
} |
|
| 1032 |
arcs[nodes[v.id].first_out].prev_out = n; |
|
| 1033 |
} |
|
| 1034 | 1034 |
arcs[n].prev_out = -1; |
| 1035 | 1035 |
nodes[v.id].first_out = n; |
| 1036 |
|
|
| 1036 |
|
|
| 1037 | 1037 |
arcs[n | 1].next_out = nodes[u.id].first_out; |
| 1038 | 1038 |
if (nodes[u.id].first_out != -1) {
|
| 1039 |
|
|
| 1039 |
arcs[nodes[u.id].first_out].prev_out = (n | 1); |
|
| 1040 | 1040 |
} |
| 1041 |
arcs[n | 1].prev_out = -1; |
|
| 1041 |
arcs[n | 1].prev_out = -1; |
|
| 1042 | 1042 |
nodes[u.id].first_out = (n | 1); |
| 1043 | 1043 |
|
| 1044 | 1044 |
return Edge(n / 2); |
| 1045 | 1045 |
} |
| 1046 |
|
|
| 1046 |
|
|
| 1047 | 1047 |
void erase(const Node& node) {
|
| 1048 | 1048 |
int n = node.id; |
| 1049 |
|
|
| 1049 |
|
|
| 1050 | 1050 |
if(nodes[n].next != -1) {
|
| 1051 |
|
|
| 1051 |
nodes[nodes[n].next].prev = nodes[n].prev; |
|
| 1052 | 1052 |
} |
| 1053 |
|
|
| 1053 |
|
|
| 1054 | 1054 |
if(nodes[n].prev != -1) {
|
| 1055 |
|
|
| 1055 |
nodes[nodes[n].prev].next = nodes[n].next; |
|
| 1056 | 1056 |
} else {
|
| 1057 |
|
|
| 1057 |
first_node = nodes[n].next; |
|
| 1058 | 1058 |
} |
| 1059 |
|
|
| 1059 |
|
|
| 1060 | 1060 |
nodes[n].next = first_free_node; |
| 1061 | 1061 |
first_free_node = n; |
| 1062 | 1062 |
nodes[n].prev = -2; |
| 1063 | 1063 |
} |
| 1064 |
|
|
| 1064 |
|
|
| 1065 | 1065 |
void erase(const Edge& edge) {
|
| 1066 | 1066 |
int n = edge.id * 2; |
| 1067 |
|
|
| 1067 |
|
|
| 1068 | 1068 |
if (arcs[n].next_out != -1) {
|
| 1069 |
arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; |
|
| 1070 |
} |
|
| 1069 |
arcs[arcs[n].next_out].prev_out = arcs[n].prev_out; |
|
| 1070 |
} |
|
| 1071 | 1071 |
|
| 1072 | 1072 |
if (arcs[n].prev_out != -1) {
|
| 1073 |
|
|
| 1073 |
arcs[arcs[n].prev_out].next_out = arcs[n].next_out; |
|
| 1074 | 1074 |
} else {
|
| 1075 |
|
|
| 1075 |
nodes[arcs[n | 1].target].first_out = arcs[n].next_out; |
|
| 1076 | 1076 |
} |
| 1077 | 1077 |
|
| 1078 | 1078 |
if (arcs[n | 1].next_out != -1) {
|
| 1079 |
arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out; |
|
| 1080 |
} |
|
| 1079 |
arcs[arcs[n | 1].next_out].prev_out = arcs[n | 1].prev_out; |
|
| 1080 |
} |
|
| 1081 | 1081 |
|
| 1082 | 1082 |
if (arcs[n | 1].prev_out != -1) {
|
| 1083 |
|
|
| 1083 |
arcs[arcs[n | 1].prev_out].next_out = arcs[n | 1].next_out; |
|
| 1084 | 1084 |
} else {
|
| 1085 |
|
|
| 1085 |
nodes[arcs[n].target].first_out = arcs[n | 1].next_out; |
|
| 1086 | 1086 |
} |
| 1087 |
|
|
| 1087 |
|
|
| 1088 | 1088 |
arcs[n].next_out = first_free_arc; |
| 1089 |
first_free_arc = n; |
|
| 1089 |
first_free_arc = n; |
|
| 1090 | 1090 |
arcs[n].prev_out = -2; |
| 1091 | 1091 |
arcs[n | 1].prev_out = -2; |
| 1092 | 1092 |
|
| 1093 | 1093 |
} |
| 1094 | 1094 |
|
| 1095 | 1095 |
void clear() {
|
| 1096 | 1096 |
arcs.clear(); |
| 1097 | 1097 |
nodes.clear(); |
| 1098 | 1098 |
first_node = first_free_node = first_free_arc = -1; |
| 1099 | 1099 |
} |
| 1100 | 1100 |
|
| 1101 | 1101 |
protected: |
| 1102 | 1102 |
|
| 1103 | 1103 |
void changeTarget(Edge e, Node n) {
|
| 1104 | 1104 |
if(arcs[2 * e.id].next_out != -1) {
|
| 1105 |
|
|
| 1105 |
arcs[arcs[2 * e.id].next_out].prev_out = arcs[2 * e.id].prev_out; |
|
| 1106 | 1106 |
} |
| 1107 | 1107 |
if(arcs[2 * e.id].prev_out != -1) {
|
| 1108 |
|
|
| 1108 |
arcs[arcs[2 * e.id].prev_out].next_out = |
|
| 1109 | 1109 |
arcs[2 * e.id].next_out; |
| 1110 | 1110 |
} else {
|
| 1111 |
nodes[arcs[(2 * e.id) | 1].target].first_out = |
|
| 1111 |
nodes[arcs[(2 * e.id) | 1].target].first_out = |
|
| 1112 | 1112 |
arcs[2 * e.id].next_out; |
| 1113 | 1113 |
} |
| 1114 | 1114 |
|
| 1115 | 1115 |
if (nodes[n.id].first_out != -1) {
|
| 1116 |
|
|
| 1116 |
arcs[nodes[n.id].first_out].prev_out = 2 * e.id; |
|
| 1117 | 1117 |
} |
| 1118 | 1118 |
arcs[(2 * e.id) | 1].target = n.id; |
| 1119 | 1119 |
arcs[2 * e.id].prev_out = -1; |
| 1120 | 1120 |
arcs[2 * e.id].next_out = nodes[n.id].first_out; |
| 1121 | 1121 |
nodes[n.id].first_out = 2 * e.id; |
| 1122 | 1122 |
} |
| 1123 | 1123 |
|
| 1124 | 1124 |
void changeSource(Edge e, Node n) {
|
| 1125 | 1125 |
if(arcs[(2 * e.id) | 1].next_out != -1) {
|
| 1126 |
|
|
| 1126 |
arcs[arcs[(2 * e.id) | 1].next_out].prev_out = |
|
| 1127 | 1127 |
arcs[(2 * e.id) | 1].prev_out; |
| 1128 | 1128 |
} |
| 1129 | 1129 |
if(arcs[(2 * e.id) | 1].prev_out != -1) {
|
| 1130 |
|
|
| 1130 |
arcs[arcs[(2 * e.id) | 1].prev_out].next_out = |
|
| 1131 | 1131 |
arcs[(2 * e.id) | 1].next_out; |
| 1132 | 1132 |
} else {
|
| 1133 |
nodes[arcs[2 * e.id].target].first_out = |
|
| 1133 |
nodes[arcs[2 * e.id].target].first_out = |
|
| 1134 | 1134 |
arcs[(2 * e.id) | 1].next_out; |
| 1135 | 1135 |
} |
| 1136 | 1136 |
|
| 1137 | 1137 |
if (nodes[n.id].first_out != -1) {
|
| 1138 |
|
|
| 1138 |
arcs[nodes[n.id].first_out].prev_out = ((2 * e.id) | 1); |
|
| 1139 | 1139 |
} |
| 1140 | 1140 |
arcs[2 * e.id].target = n.id; |
| 1141 | 1141 |
arcs[(2 * e.id) | 1].prev_out = -1; |
| 1142 | 1142 |
arcs[(2 * e.id) | 1].next_out = nodes[n.id].first_out; |
| 1143 | 1143 |
nodes[n.id].first_out = ((2 * e.id) | 1); |
| 1144 | 1144 |
} |
| 1145 | 1145 |
|
| 1146 | 1146 |
}; |
| 1147 | 1147 |
|
| 1148 | 1148 |
typedef GraphExtender<ListGraphBase> ExtendedListGraphBase; |
| 1149 | 1149 |
|
| 1150 | 1150 |
|
| 1151 | 1151 |
/// \addtogroup graphs |
| 1152 | 1152 |
/// @{
|
| 1153 | 1153 |
|
| 1154 | 1154 |
///A general undirected graph structure. |
| 1155 | 1155 |
|
| 1156 |
///\ref ListGraph is a simple and fast <em>undirected graph</em> |
|
| 1157 |
///implementation based on static linked lists that are stored in |
|
| 1158 |
///\ |
|
| 1156 |
///\ref ListGraph is a simple and fast <em>undirected graph</em> |
|
| 1157 |
///implementation based on static linked lists that are stored in |
|
| 1158 |
///\c std::vector structures. |
|
| 1159 | 1159 |
/// |
| 1160 | 1160 |
///It conforms to the \ref concepts::Graph "Graph concept" and it |
| 1161 | 1161 |
///also provides several useful additional functionalities. |
| 1162 | 1162 |
///Most of the member functions and nested classes are documented |
| 1163 | 1163 |
///only in the concept class. |
| 1164 | 1164 |
/// |
| 1165 | 1165 |
///An important extra feature of this graph implementation is that |
| 1166 | 1166 |
///its maps are real \ref concepts::ReferenceMap "reference map"s. |
| 1167 | 1167 |
/// |
| 1168 | 1168 |
///\sa concepts::Graph |
| 1169 | 1169 |
|
| 1170 | 1170 |
class ListGraph : public ExtendedListGraphBase {
|
| 1171 | 1171 |
private: |
| 1172 | 1172 |
///ListGraph is \e not copy constructible. Use copyGraph() instead. |
| 1173 | 1173 |
|
| 1174 | 1174 |
///ListGraph is \e not copy constructible. Use copyGraph() instead. |
| 1175 | 1175 |
/// |
| 1176 | 1176 |
ListGraph(const ListGraph &) :ExtendedListGraphBase() {};
|
| 1177 | 1177 |
///\brief Assignment of ListGraph to another one is \e not allowed. |
| 1178 | 1178 |
///Use copyGraph() instead. |
| 1179 | 1179 |
|
| 1180 | 1180 |
///Assignment of ListGraph to another one is \e not allowed. |
| 1181 | 1181 |
///Use copyGraph() instead. |
| 1182 | 1182 |
void operator=(const ListGraph &) {}
|
| 1183 | 1183 |
public: |
| 1184 | 1184 |
/// Constructor |
| 1185 |
|
|
| 1185 |
|
|
| 1186 | 1186 |
/// Constructor. |
| 1187 | 1187 |
/// |
| 1188 | 1188 |
ListGraph() {}
|
| 1189 | 1189 |
|
| 1190 | 1190 |
typedef ExtendedListGraphBase Parent; |
| 1191 | 1191 |
|
| 1192 | 1192 |
typedef Parent::OutArcIt IncEdgeIt; |
| 1193 | 1193 |
|
| 1194 | 1194 |
/// \brief Add a new node to the graph. |
| 1195 | 1195 |
/// |
| 1196 | 1196 |
/// Add a new node to the graph. |
| 1197 | 1197 |
/// \return the new node. |
| 1198 | 1198 |
Node addNode() { return Parent::addNode(); }
|
| 1199 | 1199 |
|
| 1200 | 1200 |
/// \brief Add a new edge to the graph. |
| 1201 | 1201 |
/// |
| 1202 | 1202 |
/// Add a new edge to the graph with source node \c s |
| 1203 | 1203 |
/// and target node \c t. |
| 1204 | 1204 |
/// \return the new edge. |
| 1205 |
Edge addEdge(const Node& s, const Node& t) {
|
|
| 1206 |
return Parent::addEdge(s, t); |
|
| 1205 |
Edge addEdge(const Node& s, const Node& t) {
|
|
| 1206 |
return Parent::addEdge(s, t); |
|
| 1207 | 1207 |
} |
| 1208 | 1208 |
/// Node validity check |
| 1209 | 1209 |
|
| 1210 | 1210 |
/// This function gives back true if the given node is valid, |
| 1211 |
/// ie. it is a real node of the graph. |
|
| 1211 |
/// ie. it is a real node of the graph. |
|
| 1212 | 1212 |
/// |
| 1213 | 1213 |
/// \warning A Node pointing to a removed item |
| 1214 | 1214 |
/// could become valid again later if new nodes are |
| 1215 | 1215 |
/// added to the graph. |
| 1216 | 1216 |
bool valid(Node n) const { return Parent::valid(n); }
|
| 1217 | 1217 |
/// Arc validity check |
| 1218 | 1218 |
|
| 1219 | 1219 |
/// This function gives back true if the given arc is valid, |
| 1220 |
/// ie. it is a real arc of the graph. |
|
| 1220 |
/// ie. it is a real arc of the graph. |
|
| 1221 | 1221 |
/// |
| 1222 | 1222 |
/// \warning An Arc pointing to a removed item |
| 1223 | 1223 |
/// could become valid again later if new edges are |
| 1224 | 1224 |
/// added to the graph. |
| 1225 | 1225 |
bool valid(Arc a) const { return Parent::valid(a); }
|
| 1226 | 1226 |
/// Edge validity check |
| 1227 | 1227 |
|
| 1228 | 1228 |
/// This function gives back true if the given edge is valid, |
| 1229 |
/// ie. it is a real arc of the graph. |
|
| 1229 |
/// ie. it is a real arc of the graph. |
|
| 1230 | 1230 |
/// |
| 1231 | 1231 |
/// \warning A Edge pointing to a removed item |
| 1232 | 1232 |
/// could become valid again later if new edges are |
| 1233 | 1233 |
/// added to the graph. |
| 1234 | 1234 |
bool valid(Edge e) const { return Parent::valid(e); }
|
| 1235 | 1235 |
/// \brief Change the source of \c e to \c n |
| 1236 | 1236 |
/// |
| 1237 | 1237 |
/// This function changes the source of \c e to \c n. |
| 1238 | 1238 |
/// |
| 1239 | 1239 |
///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s |
| 1240 | 1240 |
///referencing the changed arc remain |
| 1241 | 1241 |
///valid. However <tt>OutArcIt</tt>s are invalidated. |
| 1242 | 1242 |
/// |
| 1243 | 1243 |
///\warning This functionality cannot be used together with the |
| 1244 | 1244 |
///Snapshot feature. |
| 1245 |
void changeSource(Edge e, Node n) {
|
|
| 1246 |
Parent::changeSource(e,n); |
|
| 1247 |
|
|
| 1245 |
void changeSource(Edge e, Node n) {
|
|
| 1246 |
Parent::changeSource(e,n); |
|
| 1247 |
} |
|
| 1248 | 1248 |
/// \brief Change the target of \c e to \c n |
| 1249 | 1249 |
/// |
| 1250 | 1250 |
/// This function changes the target of \c e to \c n. |
| 1251 | 1251 |
/// |
| 1252 | 1252 |
/// \note The <tt>ArcIt</tt>s referencing the changed arc remain |
| 1253 | 1253 |
/// valid. However the other iterators may be invalidated. |
| 1254 | 1254 |
/// |
| 1255 | 1255 |
///\warning This functionality cannot be used together with the |
| 1256 | 1256 |
///Snapshot feature. |
| 1257 |
void changeTarget(Edge e, Node n) {
|
|
| 1258 |
Parent::changeTarget(e,n); |
|
| 1257 |
void changeTarget(Edge e, Node n) {
|
|
| 1258 |
Parent::changeTarget(e,n); |
|
| 1259 | 1259 |
} |
| 1260 | 1260 |
/// \brief Change the source of \c e to \c n |
| 1261 | 1261 |
/// |
| 1262 |
/// This function changes the source of \c e to \c n. |
|
| 1262 |
/// This function changes the source of \c e to \c n. |
|
| 1263 | 1263 |
/// It also changes the proper node of the represented edge. |
| 1264 | 1264 |
/// |
| 1265 | 1265 |
///\note The <tt>ArcIt</tt>s and <tt>InArcIt</tt>s |
| 1266 | 1266 |
///referencing the changed arc remain |
| 1267 | 1267 |
///valid. However <tt>OutArcIt</tt>s are invalidated. |
| 1268 | 1268 |
/// |
| 1269 | 1269 |
///\warning This functionality cannot be used together with the |
| 1270 | 1270 |
///Snapshot feature. |
| 1271 |
void changeSource(Arc e, Node n) {
|
|
| 1271 |
void changeSource(Arc e, Node n) {
|
|
| 1272 | 1272 |
if (Parent::direction(e)) {
|
| 1273 | 1273 |
Parent::changeSource(e,n); |
| 1274 | 1274 |
} else {
|
| 1275 | 1275 |
Parent::changeTarget(e,n); |
| 1276 |
} |
|
| 1276 |
} |
|
| 1277 | 1277 |
} |
| 1278 | 1278 |
/// \brief Change the target of \c e to \c n |
| 1279 | 1279 |
/// |
| 1280 |
/// This function changes the target of \c e to \c n. |
|
| 1280 |
/// This function changes the target of \c e to \c n. |
|
| 1281 | 1281 |
/// It also changes the proper node of the represented edge. |
| 1282 | 1282 |
/// |
| 1283 | 1283 |
///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s |
| 1284 | 1284 |
///referencing the changed arc remain |
| 1285 | 1285 |
///valid. However <tt>InArcIt</tt>s are invalidated. |
| 1286 | 1286 |
/// |
| 1287 | 1287 |
///\warning This functionality cannot be used together with the |
| 1288 | 1288 |
///Snapshot feature. |
| 1289 |
void changeTarget(Arc e, Node n) {
|
|
| 1289 |
void changeTarget(Arc e, Node n) {
|
|
| 1290 | 1290 |
if (Parent::direction(e)) {
|
| 1291 | 1291 |
Parent::changeTarget(e,n); |
| 1292 | 1292 |
} else {
|
| 1293 | 1293 |
Parent::changeSource(e,n); |
| 1294 |
} |
|
| 1294 |
} |
|
| 1295 | 1295 |
} |
| 1296 | 1296 |
/// \brief Contract two nodes. |
| 1297 | 1297 |
/// |
| 1298 | 1298 |
/// This function contracts two nodes. |
| 1299 | 1299 |
/// Node \p b will be removed but instead of deleting |
| 1300 | 1300 |
/// its neighboring arcs, they will be joined to \p a. |
| 1301 | 1301 |
/// The last parameter \p r controls whether to remove loops. \c true |
| 1302 | 1302 |
/// means that loops will be removed. |
| 1303 | 1303 |
/// |
| 1304 | 1304 |
/// \note The <tt>ArcIt</tt>s referencing a moved arc remain |
| 1305 | 1305 |
/// valid. |
| 1306 | 1306 |
/// |
| 1307 | 1307 |
///\warning This functionality cannot be used together with the |
| 1308 | 1308 |
///Snapshot feature. |
| 1309 | 1309 |
void contract(Node a, Node b, bool r = true) {
|
| 1310 | 1310 |
for(IncEdgeIt e(*this, b); e!=INVALID;) {
|
| 1311 |
IncEdgeIt f = e; ++f; |
|
| 1312 |
if (r && runningNode(e) == a) {
|
|
| 1313 |
erase(e); |
|
| 1314 |
} else if (source(e) == b) {
|
|
| 1315 |
changeSource(e, a); |
|
| 1316 |
} else {
|
|
| 1317 |
changeTarget(e, a); |
|
| 1318 |
} |
|
| 1319 |
|
|
| 1311 |
IncEdgeIt f = e; ++f; |
|
| 1312 |
if (r && runningNode(e) == a) {
|
|
| 1313 |
erase(e); |
|
| 1314 |
} else if (source(e) == b) {
|
|
| 1315 |
changeSource(e, a); |
|
| 1316 |
} else {
|
|
| 1317 |
changeTarget(e, a); |
|
| 1318 |
} |
|
| 1319 |
e = f; |
|
| 1320 | 1320 |
} |
| 1321 | 1321 |
erase(b); |
| 1322 | 1322 |
} |
| 1323 | 1323 |
|
| 1324 | 1324 |
|
| 1325 | 1325 |
/// \brief Class to make a snapshot of the graph and restore |
| 1326 | 1326 |
/// it later. |
| 1327 | 1327 |
/// |
| 1328 | 1328 |
/// Class to make a snapshot of the graph and restore it later. |
| 1329 | 1329 |
/// |
| 1330 | 1330 |
/// The newly added nodes and edges can be removed |
| 1331 | 1331 |
/// using the restore() function. |
| 1332 | 1332 |
/// |
| 1333 | 1333 |
/// \warning Edge and node deletions and other modifications |
| 1334 |
/// (e.g. changing nodes of edges, contracting nodes) cannot be |
|
| 1334 |
/// (e.g. changing nodes of edges, contracting nodes) cannot be |
|
| 1335 | 1335 |
/// restored. These events invalidate the snapshot. |
| 1336 | 1336 |
class Snapshot {
|
| 1337 | 1337 |
protected: |
| 1338 | 1338 |
|
| 1339 | 1339 |
typedef Parent::NodeNotifier NodeNotifier; |
| 1340 | 1340 |
|
| 1341 | 1341 |
class NodeObserverProxy : public NodeNotifier::ObserverBase {
|
| 1342 | 1342 |
public: |
| 1343 | 1343 |
|
| 1344 | 1344 |
NodeObserverProxy(Snapshot& _snapshot) |
| 1345 | 1345 |
: snapshot(_snapshot) {}
|
| 1346 | 1346 |
|
| 1347 | 1347 |
using NodeNotifier::ObserverBase::attach; |
| 1348 | 1348 |
using NodeNotifier::ObserverBase::detach; |
| 1349 | 1349 |
using NodeNotifier::ObserverBase::attached; |
| 1350 |
|
|
| 1350 |
|
|
| 1351 | 1351 |
protected: |
| 1352 |
|
|
| 1352 |
|
|
| 1353 | 1353 |
virtual void add(const Node& node) {
|
| 1354 | 1354 |
snapshot.addNode(node); |
| 1355 | 1355 |
} |
| 1356 | 1356 |
virtual void add(const std::vector<Node>& nodes) {
|
| 1357 | 1357 |
for (int i = nodes.size() - 1; i >= 0; ++i) {
|
| 1358 | 1358 |
snapshot.addNode(nodes[i]); |
| 1359 | 1359 |
} |
| 1360 | 1360 |
} |
| 1361 | 1361 |
virtual void erase(const Node& node) {
|
| 1362 | 1362 |
snapshot.eraseNode(node); |
| 1363 | 1363 |
} |
| 1364 | 1364 |
virtual void erase(const std::vector<Node>& nodes) {
|
| 1365 | 1365 |
for (int i = 0; i < int(nodes.size()); ++i) {
|
| 1366 | 1366 |
snapshot.eraseNode(nodes[i]); |
| 1367 | 1367 |
} |
| 1368 | 1368 |
} |
| 1369 | 1369 |
virtual void build() {
|
| 1370 | 1370 |
Node node; |
| 1371 | 1371 |
std::vector<Node> nodes; |
| 1372 |
for (notifier()->first(node); node != INVALID; |
|
| 1372 |
for (notifier()->first(node); node != INVALID; |
|
| 1373 | 1373 |
notifier()->next(node)) {
|
| 1374 | 1374 |
nodes.push_back(node); |
| 1375 | 1375 |
} |
| 1376 | 1376 |
for (int i = nodes.size() - 1; i >= 0; --i) {
|
| 1377 | 1377 |
snapshot.addNode(nodes[i]); |
| 1378 | 1378 |
} |
| 1379 | 1379 |
} |
| 1380 | 1380 |
virtual void clear() {
|
| 1381 | 1381 |
Node node; |
| 1382 |
for (notifier()->first(node); node != INVALID; |
|
| 1382 |
for (notifier()->first(node); node != INVALID; |
|
| 1383 | 1383 |
notifier()->next(node)) {
|
| 1384 | 1384 |
snapshot.eraseNode(node); |
| 1385 | 1385 |
} |
| 1386 | 1386 |
} |
| 1387 | 1387 |
|
| 1388 | 1388 |
Snapshot& snapshot; |
| 1389 | 1389 |
}; |
| 1390 | 1390 |
|
| 1391 | 1391 |
class EdgeObserverProxy : public EdgeNotifier::ObserverBase {
|
| 1392 | 1392 |
public: |
| 1393 | 1393 |
|
| 1394 | 1394 |
EdgeObserverProxy(Snapshot& _snapshot) |
| 1395 | 1395 |
: snapshot(_snapshot) {}
|
| 1396 | 1396 |
|
| 1397 | 1397 |
using EdgeNotifier::ObserverBase::attach; |
| 1398 | 1398 |
using EdgeNotifier::ObserverBase::detach; |
| 1399 | 1399 |
using EdgeNotifier::ObserverBase::attached; |
| 1400 |
|
|
| 1400 |
|
|
| 1401 | 1401 |
protected: |
| 1402 | 1402 |
|
| 1403 | 1403 |
virtual void add(const Edge& edge) {
|
| 1404 | 1404 |
snapshot.addEdge(edge); |
| 1405 | 1405 |
} |
| 1406 | 1406 |
virtual void add(const std::vector<Edge>& edges) {
|
| 1407 | 1407 |
for (int i = edges.size() - 1; i >= 0; ++i) {
|
| 1408 | 1408 |
snapshot.addEdge(edges[i]); |
| 1409 | 1409 |
} |
| 1410 | 1410 |
} |
| 1411 | 1411 |
virtual void erase(const Edge& edge) {
|
| 1412 | 1412 |
snapshot.eraseEdge(edge); |
| 1413 | 1413 |
} |
| 1414 | 1414 |
virtual void erase(const std::vector<Edge>& edges) {
|
| 1415 | 1415 |
for (int i = 0; i < int(edges.size()); ++i) {
|
| 1416 | 1416 |
snapshot.eraseEdge(edges[i]); |
| 1417 | 1417 |
} |
| 1418 | 1418 |
} |
| 1419 | 1419 |
virtual void build() {
|
| 1420 | 1420 |
Edge edge; |
| 1421 | 1421 |
std::vector<Edge> edges; |
| 1422 |
for (notifier()->first(edge); edge != INVALID; |
|
| 1422 |
for (notifier()->first(edge); edge != INVALID; |
|
| 1423 | 1423 |
notifier()->next(edge)) {
|
| 1424 | 1424 |
edges.push_back(edge); |
| 1425 | 1425 |
} |
| 1426 | 1426 |
for (int i = edges.size() - 1; i >= 0; --i) {
|
| 1427 | 1427 |
snapshot.addEdge(edges[i]); |
| 1428 | 1428 |
} |
| 1429 | 1429 |
} |
| 1430 | 1430 |
virtual void clear() {
|
| 1431 | 1431 |
Edge edge; |
| 1432 |
for (notifier()->first(edge); edge != INVALID; |
|
| 1432 |
for (notifier()->first(edge); edge != INVALID; |
|
| 1433 | 1433 |
notifier()->next(edge)) {
|
| 1434 | 1434 |
snapshot.eraseEdge(edge); |
| 1435 | 1435 |
} |
| 1436 | 1436 |
} |
| 1437 | 1437 |
|
| 1438 | 1438 |
Snapshot& snapshot; |
| 1439 | 1439 |
}; |
| 1440 | 1440 |
|
| 1441 | 1441 |
ListGraph *graph; |
| 1442 | 1442 |
|
| 1443 | 1443 |
NodeObserverProxy node_observer_proxy; |
| 1444 | 1444 |
EdgeObserverProxy edge_observer_proxy; |
| 1445 | 1445 |
|
| 1446 | 1446 |
std::list<Node> added_nodes; |
| 1447 | 1447 |
std::list<Edge> added_edges; |
| 1448 | 1448 |
|
| 1449 | 1449 |
|
| 1450 | 1450 |
void addNode(const Node& node) {
|
| 1451 |
added_nodes.push_front(node); |
|
| 1451 |
added_nodes.push_front(node); |
|
| 1452 | 1452 |
} |
| 1453 | 1453 |
void eraseNode(const Node& node) {
|
| 1454 |
std::list<Node>::iterator it = |
|
| 1454 |
std::list<Node>::iterator it = |
|
| 1455 | 1455 |
std::find(added_nodes.begin(), added_nodes.end(), node); |
| 1456 | 1456 |
if (it == added_nodes.end()) {
|
| 1457 | 1457 |
clear(); |
| 1458 | 1458 |
edge_observer_proxy.detach(); |
| 1459 | 1459 |
throw NodeNotifier::ImmediateDetach(); |
| 1460 | 1460 |
} else {
|
| 1461 | 1461 |
added_nodes.erase(it); |
| 1462 | 1462 |
} |
| 1463 | 1463 |
} |
| 1464 | 1464 |
|
| 1465 | 1465 |
void addEdge(const Edge& edge) {
|
| 1466 |
added_edges.push_front(edge); |
|
| 1466 |
added_edges.push_front(edge); |
|
| 1467 | 1467 |
} |
| 1468 | 1468 |
void eraseEdge(const Edge& edge) {
|
| 1469 |
std::list<Edge>::iterator it = |
|
| 1469 |
std::list<Edge>::iterator it = |
|
| 1470 | 1470 |
std::find(added_edges.begin(), added_edges.end(), edge); |
| 1471 | 1471 |
if (it == added_edges.end()) {
|
| 1472 | 1472 |
clear(); |
| 1473 | 1473 |
node_observer_proxy.detach(); |
| 1474 | 1474 |
throw EdgeNotifier::ImmediateDetach(); |
| 1475 | 1475 |
} else {
|
| 1476 | 1476 |
added_edges.erase(it); |
| 1477 | 1477 |
} |
| 1478 | 1478 |
} |
| 1479 | 1479 |
|
| 1480 | 1480 |
void attach(ListGraph &_graph) {
|
| 1481 |
graph = &_graph; |
|
| 1482 |
node_observer_proxy.attach(graph->notifier(Node())); |
|
| 1481 |
graph = &_graph; |
|
| 1482 |
node_observer_proxy.attach(graph->notifier(Node())); |
|
| 1483 | 1483 |
edge_observer_proxy.attach(graph->notifier(Edge())); |
| 1484 | 1484 |
} |
| 1485 |
|
|
| 1485 |
|
|
| 1486 | 1486 |
void detach() {
|
| 1487 |
node_observer_proxy.detach(); |
|
| 1488 |
edge_observer_proxy.detach(); |
|
| 1487 |
node_observer_proxy.detach(); |
|
| 1488 |
edge_observer_proxy.detach(); |
|
| 1489 | 1489 |
} |
| 1490 | 1490 |
|
| 1491 | 1491 |
bool attached() const {
|
| 1492 | 1492 |
return node_observer_proxy.attached(); |
| 1493 | 1493 |
} |
| 1494 | 1494 |
|
| 1495 | 1495 |
void clear() {
|
| 1496 | 1496 |
added_nodes.clear(); |
| 1497 |
added_edges.clear(); |
|
| 1497 |
added_edges.clear(); |
|
| 1498 | 1498 |
} |
| 1499 | 1499 |
|
| 1500 | 1500 |
public: |
| 1501 | 1501 |
|
| 1502 | 1502 |
/// \brief Default constructor. |
| 1503 | 1503 |
/// |
| 1504 | 1504 |
/// Default constructor. |
| 1505 | 1505 |
/// To actually make a snapshot you must call save(). |
| 1506 |
Snapshot() |
|
| 1507 |
: graph(0), node_observer_proxy(*this), |
|
| 1506 |
Snapshot() |
|
| 1507 |
: graph(0), node_observer_proxy(*this), |
|
| 1508 | 1508 |
edge_observer_proxy(*this) {}
|
| 1509 |
|
|
| 1509 |
|
|
| 1510 | 1510 |
/// \brief Constructor that immediately makes a snapshot. |
| 1511 |
/// |
|
| 1511 |
/// |
|
| 1512 | 1512 |
/// This constructor immediately makes a snapshot of the graph. |
| 1513 | 1513 |
/// \param _graph The graph we make a snapshot of. |
| 1514 |
Snapshot(ListGraph &_graph) |
|
| 1515 |
: node_observer_proxy(*this), |
|
| 1514 |
Snapshot(ListGraph &_graph) |
|
| 1515 |
: node_observer_proxy(*this), |
|
| 1516 | 1516 |
edge_observer_proxy(*this) {
|
| 1517 |
|
|
| 1517 |
attach(_graph); |
|
| 1518 | 1518 |
} |
| 1519 |
|
|
| 1519 |
|
|
| 1520 | 1520 |
/// \brief Make a snapshot. |
| 1521 | 1521 |
/// |
| 1522 | 1522 |
/// Make a snapshot of the graph. |
| 1523 | 1523 |
/// |
| 1524 | 1524 |
/// This function can be called more than once. In case of a repeated |
| 1525 | 1525 |
/// call, the previous snapshot gets lost. |
| 1526 | 1526 |
/// \param _graph The graph we make the snapshot of. |
| 1527 | 1527 |
void save(ListGraph &_graph) {
|
| 1528 | 1528 |
if (attached()) {
|
| 1529 | 1529 |
detach(); |
| 1530 | 1530 |
clear(); |
| 1531 | 1531 |
} |
| 1532 | 1532 |
attach(_graph); |
| 1533 | 1533 |
} |
| 1534 |
|
|
| 1534 |
|
|
| 1535 | 1535 |
/// \brief Undo the changes until the last snapshot. |
| 1536 |
// |
|
| 1536 |
// |
|
| 1537 | 1537 |
/// Undo the changes until the last snapshot created by save(). |
| 1538 | 1538 |
void restore() {
|
| 1539 |
detach(); |
|
| 1540 |
for(std::list<Edge>::iterator it = added_edges.begin(); |
|
| 1539 |
detach(); |
|
| 1540 |
for(std::list<Edge>::iterator it = added_edges.begin(); |
|
| 1541 | 1541 |
it != added_edges.end(); ++it) {
|
| 1542 |
graph->erase(*it); |
|
| 1543 |
} |
|
| 1544 |
|
|
| 1542 |
graph->erase(*it); |
|
| 1543 |
} |
|
| 1544 |
for(std::list<Node>::iterator it = added_nodes.begin(); |
|
| 1545 | 1545 |
it != added_nodes.end(); ++it) {
|
| 1546 |
graph->erase(*it); |
|
| 1547 |
} |
|
| 1546 |
graph->erase(*it); |
|
| 1547 |
} |
|
| 1548 | 1548 |
clear(); |
| 1549 | 1549 |
} |
| 1550 | 1550 |
|
| 1551 | 1551 |
/// \brief Gives back true when the snapshot is valid. |
| 1552 | 1552 |
/// |
| 1553 | 1553 |
/// Gives back true when the snapshot is valid. |
| 1554 | 1554 |
bool valid() const {
|
| 1555 | 1555 |
return attached(); |
| 1556 | 1556 |
} |
| 1557 | 1557 |
}; |
| 1558 | 1558 |
}; |
| 1559 |
|
|
| 1560 |
/// @} |
|
| 1559 |
|
|
| 1560 |
/// @} |
|
| 1561 | 1561 |
} //namespace lemon |
| 1562 |
|
|
| 1562 |
|
|
| 1563 | 1563 |
|
| 1564 | 1564 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_MAPS_H |
| ... | ... |
@@ -391,53 +391,53 @@ |
| 391 | 391 |
|
| 392 | 392 |
/// \brief Constructs the map from another \ref SparseMap. |
| 393 | 393 |
template<typename V1, typename Comp1> |
| 394 | 394 |
SparseMap(const SparseMap<Key, V1, Comp1> &c) |
| 395 | 395 |
: _map(c._map.begin(), c._map.end()), _value(c._value) {}
|
| 396 | 396 |
|
| 397 | 397 |
private: |
| 398 | 398 |
|
| 399 | 399 |
SparseMap& operator=(const SparseMap&); |
| 400 | 400 |
|
| 401 | 401 |
public: |
| 402 | 402 |
|
| 403 | 403 |
///\e |
| 404 | 404 |
Reference operator[](const Key &k) {
|
| 405 | 405 |
typename Map::iterator it = _map.lower_bound(k); |
| 406 | 406 |
if (it != _map.end() && !_map.key_comp()(k, it->first)) |
| 407 |
|
|
| 407 |
return it->second; |
|
| 408 | 408 |
else |
| 409 |
|
|
| 409 |
return _map.insert(it, std::make_pair(k, _value))->second; |
|
| 410 | 410 |
} |
| 411 | 411 |
|
| 412 | 412 |
///\e |
| 413 | 413 |
ConstReference operator[](const Key &k) const {
|
| 414 | 414 |
typename Map::const_iterator it = _map.find(k); |
| 415 | 415 |
if (it != _map.end()) |
| 416 |
|
|
| 416 |
return it->second; |
|
| 417 | 417 |
else |
| 418 |
|
|
| 418 |
return _value; |
|
| 419 | 419 |
} |
| 420 | 420 |
|
| 421 | 421 |
///\e |
| 422 | 422 |
void set(const Key &k, const Value &v) {
|
| 423 | 423 |
typename Map::iterator it = _map.lower_bound(k); |
| 424 | 424 |
if (it != _map.end() && !_map.key_comp()(k, it->first)) |
| 425 |
|
|
| 425 |
it->second = v; |
|
| 426 | 426 |
else |
| 427 |
|
|
| 427 |
_map.insert(it, std::make_pair(k, v)); |
|
| 428 | 428 |
} |
| 429 | 429 |
|
| 430 | 430 |
///\e |
| 431 | 431 |
void setAll(const Value &v) {
|
| 432 | 432 |
_value = v; |
| 433 | 433 |
_map.clear(); |
| 434 | 434 |
} |
| 435 | 435 |
}; |
| 436 | 436 |
|
| 437 | 437 |
/// Returns a \ref SparseMap class |
| 438 | 438 |
|
| 439 | 439 |
/// This function just returns a \ref SparseMap class with specified |
| 440 | 440 |
/// default value. |
| 441 | 441 |
/// \relates SparseMap |
| 442 | 442 |
template<typename K, typename V, typename Compare> |
| 443 | 443 |
inline SparseMap<K, V, Compare> sparseMap(const V& value = V()) {
|
| ... | ... |
@@ -531,33 +531,33 @@ |
| 531 | 531 |
/// \endcode |
| 532 | 532 |
/// <tt>cm[x]</tt> will be equal to <tt>f(m1[x],m2[x])</tt>. |
| 533 | 533 |
/// |
| 534 | 534 |
/// The \c Key type of the map is inherited from \c M1 (\c M1::Key |
| 535 | 535 |
/// must be convertible to \c M2::Key) and the \c Value type is \c V. |
| 536 | 536 |
/// \c M2::Value and \c M1::Value must be convertible to the |
| 537 | 537 |
/// corresponding input parameter of \c F and the return type of \c F |
| 538 | 538 |
/// must be convertible to \c V. |
| 539 | 539 |
/// |
| 540 | 540 |
/// The simplest way of using this map is through the combineMap() |
| 541 | 541 |
/// function. |
| 542 | 542 |
/// |
| 543 | 543 |
/// \sa ComposeMap |
| 544 | 544 |
/// |
| 545 | 545 |
/// \todo Check the requirements. |
| 546 | 546 |
template<typename M1, typename M2, typename F, |
| 547 |
|
|
| 547 |
typename V = typename F::result_type> |
|
| 548 | 548 |
class CombineMap : public MapBase<typename M1::Key, V> {
|
| 549 | 549 |
const M1 &_m1; |
| 550 | 550 |
const M2 &_m2; |
| 551 | 551 |
F _f; |
| 552 | 552 |
public: |
| 553 | 553 |
typedef MapBase<typename M1::Key, V> Parent; |
| 554 | 554 |
typedef typename Parent::Key Key; |
| 555 | 555 |
typedef typename Parent::Value Value; |
| 556 | 556 |
|
| 557 | 557 |
/// Constructor |
| 558 | 558 |
CombineMap(const M1 &m1, const M2 &m2, const F &f = F()) |
| 559 | 559 |
: _m1(m1), _m2(m2), _f(f) {}
|
| 560 | 560 |
/// \e |
| 561 | 561 |
Value operator[](const Key &k) const { return _f(_m1[k],_m2[k]); }
|
| 562 | 562 |
}; |
| 563 | 563 |
|
| ... | ... |
@@ -602,34 +602,34 @@ |
| 602 | 602 |
|
| 603 | 603 |
/// This \ref concepts::ReadMap "read-only map" returns the value |
| 604 | 604 |
/// of a given functor. Actually, it just wraps the functor and |
| 605 | 605 |
/// provides the \c Key and \c Value typedefs. |
| 606 | 606 |
/// |
| 607 | 607 |
/// Template parameters \c K and \c V will become its \c Key and |
| 608 | 608 |
/// \c Value. In most cases they have to be given explicitly because |
| 609 | 609 |
/// a functor typically does not provide \c argument_type and |
| 610 | 610 |
/// \c result_type typedefs. |
| 611 | 611 |
/// Parameter \c F is the type of the used functor. |
| 612 | 612 |
/// |
| 613 | 613 |
/// The simplest way of using this map is through the functorToMap() |
| 614 | 614 |
/// function. |
| 615 | 615 |
/// |
| 616 | 616 |
/// \sa MapToFunctor |
| 617 | 617 |
template<typename F, |
| 618 |
typename K = typename F::argument_type, |
|
| 619 |
typename V = typename F::result_type> |
|
| 618 |
typename K = typename F::argument_type, |
|
| 619 |
typename V = typename F::result_type> |
|
| 620 | 620 |
class FunctorToMap : public MapBase<K, V> {
|
| 621 | 621 |
F _f; |
| 622 | 622 |
public: |
| 623 | 623 |
typedef MapBase<K, V> Parent; |
| 624 | 624 |
typedef typename Parent::Key Key; |
| 625 | 625 |
typedef typename Parent::Value Value; |
| 626 | 626 |
|
| 627 | 627 |
/// Constructor |
| 628 | 628 |
FunctorToMap(const F &f = F()) : _f(f) {}
|
| 629 | 629 |
/// \e |
| 630 | 630 |
Value operator[](const Key &k) const { return _f(k); }
|
| 631 | 631 |
}; |
| 632 | 632 |
|
| 633 | 633 |
/// Returns a \ref FunctorToMap class |
| 634 | 634 |
|
| 635 | 635 |
/// This function just returns a \ref FunctorToMap class. |
| ... | ... |
@@ -1304,33 +1304,33 @@ |
| 1304 | 1304 |
/// Returns an \ref AbsMap class |
| 1305 | 1305 |
|
| 1306 | 1306 |
/// This function just returns an \ref AbsMap class. |
| 1307 | 1307 |
/// |
| 1308 | 1308 |
/// For example, if \c m is a map with \c double values, then |
| 1309 | 1309 |
/// <tt>absMap(m)[x]</tt> will be equal to <tt>m[x]</tt> if |
| 1310 | 1310 |
/// it is positive or zero and <tt>-m[x]</tt> if <tt>m[x]</tt> is |
| 1311 | 1311 |
/// negative. |
| 1312 | 1312 |
/// |
| 1313 | 1313 |
/// \relates AbsMap |
| 1314 | 1314 |
template<typename M> |
| 1315 | 1315 |
inline AbsMap<M> absMap(const M &m) {
|
| 1316 | 1316 |
return AbsMap<M>(m); |
| 1317 | 1317 |
} |
| 1318 | 1318 |
|
| 1319 | 1319 |
/// @} |
| 1320 |
|
|
| 1320 |
|
|
| 1321 | 1321 |
// Logical maps and map adaptors: |
| 1322 | 1322 |
|
| 1323 | 1323 |
/// \addtogroup maps |
| 1324 | 1324 |
/// @{
|
| 1325 | 1325 |
|
| 1326 | 1326 |
/// Constant \c true map. |
| 1327 | 1327 |
|
| 1328 | 1328 |
/// This \ref concepts::ReadMap "read-only map" assigns \c true to |
| 1329 | 1329 |
/// each key. |
| 1330 | 1330 |
/// |
| 1331 | 1331 |
/// Note that |
| 1332 | 1332 |
/// \code |
| 1333 | 1333 |
/// TrueMap<K> tm; |
| 1334 | 1334 |
/// \endcode |
| 1335 | 1335 |
/// is equivalent to |
| 1336 | 1336 |
/// \code |
| ... | ... |
@@ -1702,67 +1702,67 @@ |
| 1702 | 1702 |
/// assigned elements (in order of the assignment), which can be |
| 1703 | 1703 |
/// easily done with LoggerBoolMap. |
| 1704 | 1704 |
/// |
| 1705 | 1705 |
/// The simplest way of using this map is through the loggerBoolMap() |
| 1706 | 1706 |
/// function. |
| 1707 | 1707 |
/// |
| 1708 | 1708 |
/// \tparam It The type of the iterator. |
| 1709 | 1709 |
/// \tparam Ke The key type of the map. The default value set |
| 1710 | 1710 |
/// according to the iterator type should work in most cases. |
| 1711 | 1711 |
/// |
| 1712 | 1712 |
/// \note The container of the iterator must contain enough space |
| 1713 | 1713 |
/// for the elements or the iterator should be an inserter iterator. |
| 1714 | 1714 |
#ifdef DOXYGEN |
| 1715 | 1715 |
template <typename It, typename Ke> |
| 1716 | 1716 |
#else |
| 1717 | 1717 |
template <typename It, |
| 1718 |
|
|
| 1718 |
typename Ke=typename _maps_bits::IteratorTraits<It>::Value> |
|
| 1719 | 1719 |
#endif |
| 1720 | 1720 |
class LoggerBoolMap {
|
| 1721 | 1721 |
public: |
| 1722 | 1722 |
typedef It Iterator; |
| 1723 | 1723 |
|
| 1724 | 1724 |
typedef Ke Key; |
| 1725 | 1725 |
typedef bool Value; |
| 1726 | 1726 |
|
| 1727 | 1727 |
/// Constructor |
| 1728 | 1728 |
LoggerBoolMap(Iterator it) |
| 1729 | 1729 |
: _begin(it), _end(it) {}
|
| 1730 | 1730 |
|
| 1731 | 1731 |
/// Gives back the given iterator set for the first key |
| 1732 | 1732 |
Iterator begin() const {
|
| 1733 | 1733 |
return _begin; |
| 1734 | 1734 |
} |
| 1735 | 1735 |
|
| 1736 | 1736 |
/// Gives back the the 'after the last' iterator |
| 1737 | 1737 |
Iterator end() const {
|
| 1738 | 1738 |
return _end; |
| 1739 | 1739 |
} |
| 1740 | 1740 |
|
| 1741 | 1741 |
/// The set function of the map |
| 1742 | 1742 |
void set(const Key& key, Value value) {
|
| 1743 | 1743 |
if (value) {
|
| 1744 |
|
|
| 1744 |
*_end++ = key; |
|
| 1745 | 1745 |
} |
| 1746 | 1746 |
} |
| 1747 | 1747 |
|
| 1748 | 1748 |
private: |
| 1749 | 1749 |
Iterator _begin; |
| 1750 | 1750 |
Iterator _end; |
| 1751 | 1751 |
}; |
| 1752 |
|
|
| 1752 |
|
|
| 1753 | 1753 |
/// Returns a \ref LoggerBoolMap class |
| 1754 | 1754 |
|
| 1755 | 1755 |
/// This function just returns a \ref LoggerBoolMap class. |
| 1756 | 1756 |
/// |
| 1757 | 1757 |
/// The most important usage of it is storing certain nodes or arcs |
| 1758 | 1758 |
/// that were marked \c true by an algorithm. |
| 1759 | 1759 |
/// For example it makes easier to store the nodes in the processing |
| 1760 | 1760 |
/// order of Dfs algorithm, as the following examples show. |
| 1761 | 1761 |
/// \code |
| 1762 | 1762 |
/// std::vector<Node> v; |
| 1763 | 1763 |
/// dfs(g,s).processedMap(loggerBoolMap(std::back_inserter(v))).run(); |
| 1764 | 1764 |
/// \endcode |
| 1765 | 1765 |
/// \code |
| 1766 | 1766 |
/// std::vector<Node> v(countNodes(g)); |
| 1767 | 1767 |
/// dfs(g,s).processedMap(loggerBoolMap(v.begin())).run(); |
| 1768 | 1768 |
/// \endcode |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_MATH_H |
| 20 | 20 |
#define LEMON_MATH_H |
| 21 | 21 |
|
| 22 | 22 |
///\ingroup misc |
| 23 | 23 |
///\file |
| 24 | 24 |
///\brief Some extensions to the standard \c cmath library. |
| 25 | 25 |
/// |
| 26 | 26 |
///Some extensions to the standard \c cmath library. |
| 27 | 27 |
/// |
| 28 | 28 |
///This file includes the standard math library (cmath). |
| 29 | 29 |
|
| 30 | 30 |
#include<cmath> |
| 31 | 31 |
|
| 32 | 32 |
namespace lemon {
|
| 33 | 33 |
|
| 34 | 34 |
/// \addtogroup misc |
| 35 | 35 |
/// @{
|
| 36 |
|
|
| 36 |
|
|
| 37 | 37 |
/// The Euler constant |
| 38 | 38 |
const long double E = 2.7182818284590452353602874713526625L; |
| 39 | 39 |
/// log_2(e) |
| 40 | 40 |
const long double LOG2E = 1.4426950408889634073599246810018921L; |
| 41 | 41 |
/// log_10(e) |
| 42 | 42 |
const long double LOG10E = 0.4342944819032518276511289189166051L; |
| 43 | 43 |
/// ln(2) |
| 44 | 44 |
const long double LN2 = 0.6931471805599453094172321214581766L; |
| 45 | 45 |
/// ln(10) |
| 46 | 46 |
const long double LN10 = 2.3025850929940456840179914546843642L; |
| 47 | 47 |
/// pi |
| 48 | 48 |
const long double PI = 3.1415926535897932384626433832795029L; |
| 49 | 49 |
/// pi/2 |
| 50 | 50 |
const long double PI_2 = 1.5707963267948966192313216916397514L; |
| 51 | 51 |
/// pi/4 |
| 52 | 52 |
const long double PI_4 = 0.7853981633974483096156608458198757L; |
| 53 | 53 |
/// sqrt(2) |
| 54 | 54 |
const long double SQRT2 = 1.4142135623730950488016887242096981L; |
| 55 | 55 |
/// 1/sqrt(2) |
| 56 | 56 |
const long double SQRT1_2 = 0.7071067811865475244008443621048490L; |
| 57 |
|
|
| 57 |
|
|
| 58 | 58 |
|
| 59 | 59 |
/// @} |
| 60 | 60 |
|
| 61 | 61 |
} //namespace lemon |
| 62 | 62 |
|
| 63 | 63 |
#endif //LEMON_TOLERANCE_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 paths |
| ... | ... |
@@ -80,52 +80,52 @@ |
| 80 | 80 |
Path& operator=(const CPath& cpath) {
|
| 81 | 81 |
copyPath(*this, cpath); |
| 82 | 82 |
return *this; |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 | 85 |
/// \brief Lemon style iterator for path arcs |
| 86 | 86 |
/// |
| 87 | 87 |
/// This class is used to iterate on the arcs of the paths. |
| 88 | 88 |
class ArcIt {
|
| 89 | 89 |
friend class Path; |
| 90 | 90 |
public: |
| 91 | 91 |
/// \brief Default constructor |
| 92 | 92 |
ArcIt() {}
|
| 93 | 93 |
/// \brief Invalid constructor |
| 94 | 94 |
ArcIt(Invalid) : path(0), idx(-1) {}
|
| 95 | 95 |
/// \brief Initializate the iterator to the first arc of path |
| 96 |
ArcIt(const Path &_path) |
|
| 96 |
ArcIt(const Path &_path) |
|
| 97 | 97 |
: path(&_path), idx(_path.empty() ? -1 : 0) {}
|
| 98 | 98 |
|
| 99 | 99 |
private: |
| 100 | 100 |
|
| 101 |
ArcIt(const Path &_path, int _idx) |
|
| 101 |
ArcIt(const Path &_path, int _idx) |
|
| 102 | 102 |
: path(&_path), idx(_idx) {}
|
| 103 | 103 |
|
| 104 | 104 |
public: |
| 105 | 105 |
|
| 106 | 106 |
/// \brief Conversion to Arc |
| 107 | 107 |
operator const Arc&() const {
|
| 108 | 108 |
return path->nth(idx); |
| 109 | 109 |
} |
| 110 | 110 |
|
| 111 | 111 |
/// \brief Next arc |
| 112 |
ArcIt& operator++() {
|
|
| 112 |
ArcIt& operator++() {
|
|
| 113 | 113 |
++idx; |
| 114 |
if (idx >= path->length()) idx = -1; |
|
| 115 |
return *this; |
|
| 114 |
if (idx >= path->length()) idx = -1; |
|
| 115 |
return *this; |
|
| 116 | 116 |
} |
| 117 | 117 |
|
| 118 | 118 |
/// \brief Comparison operator |
| 119 | 119 |
bool operator==(const ArcIt& e) const { return idx==e.idx; }
|
| 120 | 120 |
/// \brief Comparison operator |
| 121 | 121 |
bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
|
| 122 | 122 |
/// \brief Comparison operator |
| 123 | 123 |
bool operator<(const ArcIt& e) const { return idx<e.idx; }
|
| 124 | 124 |
|
| 125 | 125 |
private: |
| 126 | 126 |
const Path *path; |
| 127 | 127 |
int idx; |
| 128 | 128 |
}; |
| 129 | 129 |
|
| 130 | 130 |
/// \brief Length of the path. |
| 131 | 131 |
int length() const { return head.size() + tail.size(); }
|
| ... | ... |
@@ -271,53 +271,53 @@ |
| 271 | 271 |
return *this; |
| 272 | 272 |
} |
| 273 | 273 |
|
| 274 | 274 |
/// \brief Iterator class to iterate on the arcs of the paths |
| 275 | 275 |
/// |
| 276 | 276 |
/// This class is used to iterate on the arcs of the paths |
| 277 | 277 |
/// |
| 278 | 278 |
/// Of course it converts to Digraph::Arc |
| 279 | 279 |
class ArcIt {
|
| 280 | 280 |
friend class SimplePath; |
| 281 | 281 |
public: |
| 282 | 282 |
/// Default constructor |
| 283 | 283 |
ArcIt() {}
|
| 284 | 284 |
/// Invalid constructor |
| 285 | 285 |
ArcIt(Invalid) : path(0), idx(-1) {}
|
| 286 | 286 |
/// \brief Initializate the constructor to the first arc of path |
| 287 |
ArcIt(const SimplePath &_path) |
|
| 287 |
ArcIt(const SimplePath &_path) |
|
| 288 | 288 |
: path(&_path), idx(_path.empty() ? -1 : 0) {}
|
| 289 | 289 |
|
| 290 | 290 |
private: |
| 291 | 291 |
|
| 292 | 292 |
/// Constructor with starting point |
| 293 |
ArcIt(const SimplePath &_path, int _idx) |
|
| 293 |
ArcIt(const SimplePath &_path, int _idx) |
|
| 294 | 294 |
: idx(_idx), path(&_path) {}
|
| 295 | 295 |
|
| 296 | 296 |
public: |
| 297 | 297 |
|
| 298 | 298 |
///Conversion to Digraph::Arc |
| 299 | 299 |
operator const Arc&() const {
|
| 300 | 300 |
return path->nth(idx); |
| 301 | 301 |
} |
| 302 | 302 |
|
| 303 | 303 |
/// Next arc |
| 304 |
ArcIt& operator++() {
|
|
| 304 |
ArcIt& operator++() {
|
|
| 305 | 305 |
++idx; |
| 306 |
if (idx >= path->length()) idx = -1; |
|
| 307 |
return *this; |
|
| 306 |
if (idx >= path->length()) idx = -1; |
|
| 307 |
return *this; |
|
| 308 | 308 |
} |
| 309 | 309 |
|
| 310 | 310 |
/// Comparison operator |
| 311 | 311 |
bool operator==(const ArcIt& e) const { return idx==e.idx; }
|
| 312 | 312 |
/// Comparison operator |
| 313 | 313 |
bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
|
| 314 | 314 |
/// Comparison operator |
| 315 | 315 |
bool operator<(const ArcIt& e) const { return idx<e.idx; }
|
| 316 | 316 |
|
| 317 | 317 |
private: |
| 318 | 318 |
const SimplePath *path; |
| 319 | 319 |
int idx; |
| 320 | 320 |
}; |
| 321 | 321 |
|
| 322 | 322 |
/// \brief Length of the path. |
| 323 | 323 |
int length() const { return data.size(); }
|
| ... | ... |
@@ -400,45 +400,45 @@ |
| 400 | 400 |
/// cannot store the source. |
| 401 | 401 |
/// |
| 402 | 402 |
/// This implementation is a back and front insertable and erasable |
| 403 | 403 |
/// path type. It can be indexed in O(k) time, where k is the rank |
| 404 | 404 |
/// of the arc in the path. The length can be computed in O(n) |
| 405 | 405 |
/// time. The front and back insertion and erasure is O(1) time |
| 406 | 406 |
/// and it can be splited and spliced in O(1) time. |
| 407 | 407 |
template <typename _Digraph> |
| 408 | 408 |
class ListPath {
|
| 409 | 409 |
public: |
| 410 | 410 |
|
| 411 | 411 |
typedef _Digraph Digraph; |
| 412 | 412 |
typedef typename Digraph::Arc Arc; |
| 413 | 413 |
|
| 414 | 414 |
protected: |
| 415 | 415 |
|
| 416 |
// the std::list<> is incompatible |
|
| 416 |
// the std::list<> is incompatible |
|
| 417 | 417 |
// hard to create invalid iterator |
| 418 | 418 |
struct Node {
|
| 419 | 419 |
Arc arc; |
| 420 | 420 |
Node *next, *prev; |
| 421 | 421 |
}; |
| 422 | 422 |
|
| 423 | 423 |
Node *first, *last; |
| 424 | 424 |
|
| 425 | 425 |
std::allocator<Node> alloc; |
| 426 | 426 |
|
| 427 | 427 |
public: |
| 428 |
|
|
| 428 |
|
|
| 429 | 429 |
/// \brief Default constructor |
| 430 | 430 |
/// |
| 431 | 431 |
/// Default constructor |
| 432 | 432 |
ListPath() : first(0), last(0) {}
|
| 433 | 433 |
|
| 434 | 434 |
/// \brief Template copy constructor |
| 435 | 435 |
/// |
| 436 | 436 |
/// This path can be initialized with any other path type. It just |
| 437 | 437 |
/// makes a copy of the given path. |
| 438 | 438 |
template <typename CPath> |
| 439 | 439 |
ListPath(const CPath& cpath) : first(0), last(0) {
|
| 440 | 440 |
copyPath(*this, cpath); |
| 441 | 441 |
} |
| 442 | 442 |
|
| 443 | 443 |
/// \brief Destructor of the path |
| 444 | 444 |
/// |
| ... | ... |
@@ -457,52 +457,52 @@ |
| 457 | 457 |
return *this; |
| 458 | 458 |
} |
| 459 | 459 |
|
| 460 | 460 |
/// \brief Iterator class to iterate on the arcs of the paths |
| 461 | 461 |
/// |
| 462 | 462 |
/// This class is used to iterate on the arcs of the paths |
| 463 | 463 |
/// |
| 464 | 464 |
/// Of course it converts to Digraph::Arc |
| 465 | 465 |
class ArcIt {
|
| 466 | 466 |
friend class ListPath; |
| 467 | 467 |
public: |
| 468 | 468 |
/// Default constructor |
| 469 | 469 |
ArcIt() {}
|
| 470 | 470 |
/// Invalid constructor |
| 471 | 471 |
ArcIt(Invalid) : path(0), node(0) {}
|
| 472 | 472 |
/// \brief Initializate the constructor to the first arc of path |
| 473 |
ArcIt(const ListPath &_path) |
|
| 473 |
ArcIt(const ListPath &_path) |
|
| 474 | 474 |
: path(&_path), node(_path.first) {}
|
| 475 | 475 |
|
| 476 | 476 |
protected: |
| 477 | 477 |
|
| 478 |
ArcIt(const ListPath &_path, Node *_node) |
|
| 478 |
ArcIt(const ListPath &_path, Node *_node) |
|
| 479 | 479 |
: path(&_path), node(_node) {}
|
| 480 | 480 |
|
| 481 | 481 |
|
| 482 | 482 |
public: |
| 483 | 483 |
|
| 484 | 484 |
///Conversion to Digraph::Arc |
| 485 | 485 |
operator const Arc&() const {
|
| 486 | 486 |
return node->arc; |
| 487 | 487 |
} |
| 488 | 488 |
|
| 489 | 489 |
/// Next arc |
| 490 |
ArcIt& operator++() {
|
|
| 490 |
ArcIt& operator++() {
|
|
| 491 | 491 |
node = node->next; |
| 492 |
return *this; |
|
| 492 |
return *this; |
|
| 493 | 493 |
} |
| 494 | 494 |
|
| 495 | 495 |
/// Comparison operator |
| 496 | 496 |
bool operator==(const ArcIt& e) const { return node==e.node; }
|
| 497 | 497 |
/// Comparison operator |
| 498 | 498 |
bool operator!=(const ArcIt& e) const { return node!=e.node; }
|
| 499 | 499 |
/// Comparison operator |
| 500 | 500 |
bool operator<(const ArcIt& e) const { return node<e.node; }
|
| 501 | 501 |
|
| 502 | 502 |
private: |
| 503 | 503 |
const ListPath *path; |
| 504 | 504 |
Node *node; |
| 505 | 505 |
}; |
| 506 | 506 |
|
| 507 | 507 |
/// \brief The nth arc. |
| 508 | 508 |
/// |
| ... | ... |
@@ -744,33 +744,33 @@ |
| 744 | 744 |
/// modified. |
| 745 | 745 |
/// |
| 746 | 746 |
/// Being the the most memory efficient path type in LEMON, |
| 747 | 747 |
/// it is intented to be |
| 748 | 748 |
/// used when you want to store a large number of paths. |
| 749 | 749 |
template <typename _Digraph> |
| 750 | 750 |
class StaticPath {
|
| 751 | 751 |
public: |
| 752 | 752 |
|
| 753 | 753 |
typedef _Digraph Digraph; |
| 754 | 754 |
typedef typename Digraph::Arc Arc; |
| 755 | 755 |
|
| 756 | 756 |
/// \brief Default constructor |
| 757 | 757 |
/// |
| 758 | 758 |
/// Default constructor |
| 759 | 759 |
StaticPath() : len(0), arcs(0) {}
|
| 760 |
|
|
| 760 |
|
|
| 761 | 761 |
/// \brief Template copy constructor |
| 762 | 762 |
/// |
| 763 | 763 |
/// This path can be initialized from any other path type. |
| 764 | 764 |
template <typename CPath> |
| 765 | 765 |
StaticPath(const CPath& cpath) : arcs(0) {
|
| 766 | 766 |
copyPath(*this, cpath); |
| 767 | 767 |
} |
| 768 | 768 |
|
| 769 | 769 |
/// \brief Destructor of the path |
| 770 | 770 |
/// |
| 771 | 771 |
/// Destructor of the path |
| 772 | 772 |
~StaticPath() {
|
| 773 | 773 |
if (arcs) delete[] arcs; |
| 774 | 774 |
} |
| 775 | 775 |
|
| 776 | 776 |
/// \brief Template copy assignment |
| ... | ... |
@@ -783,53 +783,53 @@ |
| 783 | 783 |
return *this; |
| 784 | 784 |
} |
| 785 | 785 |
|
| 786 | 786 |
/// \brief Iterator class to iterate on the arcs of the paths |
| 787 | 787 |
/// |
| 788 | 788 |
/// This class is used to iterate on the arcs of the paths |
| 789 | 789 |
/// |
| 790 | 790 |
/// Of course it converts to Digraph::Arc |
| 791 | 791 |
class ArcIt {
|
| 792 | 792 |
friend class StaticPath; |
| 793 | 793 |
public: |
| 794 | 794 |
/// Default constructor |
| 795 | 795 |
ArcIt() {}
|
| 796 | 796 |
/// Invalid constructor |
| 797 | 797 |
ArcIt(Invalid) : path(0), idx(-1) {}
|
| 798 | 798 |
/// Initializate the constructor to the first arc of path |
| 799 |
ArcIt(const StaticPath &_path) |
|
| 799 |
ArcIt(const StaticPath &_path) |
|
| 800 | 800 |
: path(&_path), idx(_path.empty() ? -1 : 0) {}
|
| 801 | 801 |
|
| 802 | 802 |
private: |
| 803 | 803 |
|
| 804 | 804 |
/// Constructor with starting point |
| 805 |
ArcIt(const StaticPath &_path, int _idx) |
|
| 805 |
ArcIt(const StaticPath &_path, int _idx) |
|
| 806 | 806 |
: idx(_idx), path(&_path) {}
|
| 807 | 807 |
|
| 808 | 808 |
public: |
| 809 | 809 |
|
| 810 | 810 |
///Conversion to Digraph::Arc |
| 811 | 811 |
operator const Arc&() const {
|
| 812 | 812 |
return path->nth(idx); |
| 813 | 813 |
} |
| 814 | 814 |
|
| 815 | 815 |
/// Next arc |
| 816 |
ArcIt& operator++() {
|
|
| 816 |
ArcIt& operator++() {
|
|
| 817 | 817 |
++idx; |
| 818 |
if (idx >= path->length()) idx = -1; |
|
| 819 |
return *this; |
|
| 818 |
if (idx >= path->length()) idx = -1; |
|
| 819 |
return *this; |
|
| 820 | 820 |
} |
| 821 | 821 |
|
| 822 | 822 |
/// Comparison operator |
| 823 | 823 |
bool operator==(const ArcIt& e) const { return idx==e.idx; }
|
| 824 | 824 |
/// Comparison operator |
| 825 | 825 |
bool operator!=(const ArcIt& e) const { return idx!=e.idx; }
|
| 826 | 826 |
/// Comparison operator |
| 827 | 827 |
bool operator<(const ArcIt& e) const { return idx<e.idx; }
|
| 828 | 828 |
|
| 829 | 829 |
private: |
| 830 | 830 |
const StaticPath *path; |
| 831 | 831 |
int idx; |
| 832 | 832 |
}; |
| 833 | 833 |
|
| 834 | 834 |
/// \brief The nth arc. |
| 835 | 835 |
/// |
| ... | ... |
@@ -896,54 +896,54 @@ |
| 896 | 896 |
Arc* arcs; |
| 897 | 897 |
}; |
| 898 | 898 |
|
| 899 | 899 |
/////////////////////////////////////////////////////////////////////// |
| 900 | 900 |
// Additional utilities |
| 901 | 901 |
/////////////////////////////////////////////////////////////////////// |
| 902 | 902 |
|
| 903 | 903 |
namespace _path_bits {
|
| 904 | 904 |
|
| 905 | 905 |
template <typename Path, typename Enable = void> |
| 906 | 906 |
struct RevPathTagIndicator {
|
| 907 | 907 |
static const bool value = false; |
| 908 | 908 |
}; |
| 909 | 909 |
|
| 910 | 910 |
template <typename Path> |
| 911 | 911 |
struct RevPathTagIndicator< |
| 912 |
Path, |
|
| 912 |
Path, |
|
| 913 | 913 |
typename enable_if<typename Path::RevPathTag, void>::type |
| 914 | 914 |
> {
|
| 915 | 915 |
static const bool value = true; |
| 916 | 916 |
}; |
| 917 | 917 |
|
| 918 | 918 |
template <typename Path, typename Enable = void> |
| 919 | 919 |
struct BuildTagIndicator {
|
| 920 | 920 |
static const bool value = false; |
| 921 | 921 |
}; |
| 922 | 922 |
|
| 923 | 923 |
template <typename Path> |
| 924 | 924 |
struct BuildTagIndicator< |
| 925 |
Path, |
|
| 925 |
Path, |
|
| 926 | 926 |
typename enable_if<typename Path::BuildTag, void>::type |
| 927 | 927 |
> {
|
| 928 | 928 |
static const bool value = true; |
| 929 | 929 |
}; |
| 930 | 930 |
|
| 931 | 931 |
template <typename Target, typename Source, |
| 932 |
bool buildEnable = BuildTagIndicator<Target>::value, |
|
| 933 |
bool revEnable = RevPathTagIndicator<Source>::value> |
|
| 932 |
bool buildEnable = BuildTagIndicator<Target>::value, |
|
| 933 |
bool revEnable = RevPathTagIndicator<Source>::value> |
|
| 934 | 934 |
struct PathCopySelector {
|
| 935 | 935 |
static void copy(Target& target, const Source& source) {
|
| 936 | 936 |
target.clear(); |
| 937 | 937 |
for (typename Source::ArcIt it(source); it != INVALID; ++it) {
|
| 938 | 938 |
target.addBack(it); |
| 939 | 939 |
} |
| 940 | 940 |
} |
| 941 | 941 |
}; |
| 942 | 942 |
|
| 943 | 943 |
template <typename Target, typename Source> |
| 944 | 944 |
struct PathCopySelector<Target, Source, false, true> {
|
| 945 | 945 |
static void copy(Target& target, const Source& source) {
|
| 946 | 946 |
target.clear(); |
| 947 | 947 |
for (typename Source::RevArcIt it(source); it != INVALID; ++it) {
|
| 948 | 948 |
target.addFront(it); |
| 949 | 949 |
} |
| ... | ... |
@@ -968,34 +968,34 @@ |
| 968 | 968 |
|
| 969 | 969 |
} |
| 970 | 970 |
|
| 971 | 971 |
|
| 972 | 972 |
/// \brief Make a copy of a path. |
| 973 | 973 |
/// |
| 974 | 974 |
/// This function makes a copy of a path. |
| 975 | 975 |
template <typename Target, typename Source> |
| 976 | 976 |
void copyPath(Target& target, const Source& source) {
|
| 977 | 977 |
checkConcept<concepts::PathDumper<typename Source::Digraph>, Source>(); |
| 978 | 978 |
_path_bits::PathCopySelector<Target, Source>::copy(target, source); |
| 979 | 979 |
} |
| 980 | 980 |
|
| 981 | 981 |
/// \brief Check the consistency of a path. |
| 982 | 982 |
/// |
| 983 | 983 |
/// This function checks that the target of each arc is the same |
| 984 |
/// as the source of the next one. |
|
| 985 |
/// |
|
| 984 |
/// as the source of the next one. |
|
| 985 |
/// |
|
| 986 | 986 |
template <typename Digraph, typename Path> |
| 987 | 987 |
bool checkPath(const Digraph& digraph, const Path& path) {
|
| 988 | 988 |
typename Path::ArcIt it(path); |
| 989 | 989 |
if (it == INVALID) return true; |
| 990 | 990 |
typename Digraph::Node node = digraph.target(it); |
| 991 | 991 |
++it; |
| 992 | 992 |
while (it != INVALID) {
|
| 993 | 993 |
if (digraph.source(it) != node) return false; |
| 994 | 994 |
node = digraph.target(it); |
| 995 | 995 |
++it; |
| 996 | 996 |
} |
| 997 | 997 |
return true; |
| 998 | 998 |
} |
| 999 | 999 |
|
| 1000 | 1000 |
/// \brief The source of a path |
| 1001 | 1001 |
/// |
| ... | ... |
@@ -1021,66 +1021,66 @@ |
| 1021 | 1021 |
/// cannot have a source node. |
| 1022 | 1022 |
/// |
| 1023 | 1023 |
/// This class implements the node iterator of a path structure. To |
| 1024 | 1024 |
/// provide this feature, the underlying digraph should be passed to |
| 1025 | 1025 |
/// the constructor of the iterator. |
| 1026 | 1026 |
template <typename Path> |
| 1027 | 1027 |
class PathNodeIt {
|
| 1028 | 1028 |
private: |
| 1029 | 1029 |
const typename Path::Digraph *_digraph; |
| 1030 | 1030 |
typename Path::ArcIt _it; |
| 1031 | 1031 |
typename Path::Digraph::Node _nd; |
| 1032 | 1032 |
|
| 1033 | 1033 |
public: |
| 1034 | 1034 |
|
| 1035 | 1035 |
typedef typename Path::Digraph Digraph; |
| 1036 | 1036 |
typedef typename Digraph::Node Node; |
| 1037 |
|
|
| 1037 |
|
|
| 1038 | 1038 |
/// Default constructor |
| 1039 | 1039 |
PathNodeIt() {}
|
| 1040 | 1040 |
/// Invalid constructor |
| 1041 |
PathNodeIt(Invalid) |
|
| 1041 |
PathNodeIt(Invalid) |
|
| 1042 | 1042 |
: _digraph(0), _it(INVALID), _nd(INVALID) {}
|
| 1043 | 1043 |
/// Constructor |
| 1044 |
PathNodeIt(const Digraph& digraph, const Path& path) |
|
| 1044 |
PathNodeIt(const Digraph& digraph, const Path& path) |
|
| 1045 | 1045 |
: _digraph(&digraph), _it(path) {
|
| 1046 | 1046 |
_nd = (_it != INVALID ? _digraph->source(_it) : INVALID); |
| 1047 | 1047 |
} |
| 1048 | 1048 |
/// Constructor |
| 1049 |
PathNodeIt(const Digraph& digraph, const Path& path, const Node& src) |
|
| 1049 |
PathNodeIt(const Digraph& digraph, const Path& path, const Node& src) |
|
| 1050 | 1050 |
: _digraph(&digraph), _it(path), _nd(src) {}
|
| 1051 | 1051 |
|
| 1052 | 1052 |
///Conversion to Digraph::Node |
| 1053 | 1053 |
operator Node() const {
|
| 1054 | 1054 |
return _nd; |
| 1055 | 1055 |
} |
| 1056 | 1056 |
|
| 1057 | 1057 |
/// Next node |
| 1058 | 1058 |
PathNodeIt& operator++() {
|
| 1059 | 1059 |
if (_it == INVALID) _nd = INVALID; |
| 1060 | 1060 |
else {
|
| 1061 |
_nd = _digraph->target(_it); |
|
| 1062 |
++_it; |
|
| 1061 |
_nd = _digraph->target(_it); |
|
| 1062 |
++_it; |
|
| 1063 | 1063 |
} |
| 1064 | 1064 |
return *this; |
| 1065 | 1065 |
} |
| 1066 | 1066 |
|
| 1067 | 1067 |
/// Comparison operator |
| 1068 |
bool operator==(const PathNodeIt& n) const {
|
|
| 1069 |
return _it == n._it && _nd == n._nd; |
|
| 1068 |
bool operator==(const PathNodeIt& n) const {
|
|
| 1069 |
return _it == n._it && _nd == n._nd; |
|
| 1070 | 1070 |
} |
| 1071 | 1071 |
/// Comparison operator |
| 1072 |
bool operator!=(const PathNodeIt& n) const {
|
|
| 1073 |
return _it != n._it || _nd != n._nd; |
|
| 1072 |
bool operator!=(const PathNodeIt& n) const {
|
|
| 1073 |
return _it != n._it || _nd != n._nd; |
|
| 1074 | 1074 |
} |
| 1075 | 1075 |
/// Comparison operator |
| 1076 |
bool operator<(const PathNodeIt& n) const {
|
|
| 1076 |
bool operator<(const PathNodeIt& n) const {
|
|
| 1077 | 1077 |
return (_it < n._it && _nd != INVALID); |
| 1078 | 1078 |
} |
| 1079 |
|
|
| 1079 |
|
|
| 1080 | 1080 |
}; |
| 1081 |
|
|
| 1081 |
|
|
| 1082 | 1082 |
///@} |
| 1083 | 1083 |
|
| 1084 | 1084 |
} // namespace lemon |
| 1085 | 1085 |
|
| 1086 | 1086 |
#endif // LEMON_PATH_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
///\file |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
/* |
| 20 | 20 |
* This file contains the reimplemented version of the Mersenne Twister |
| 21 | 21 |
* Generator of Matsumoto and Nishimura. |
| 22 | 22 |
* |
| 23 | 23 |
* See the appropriate copyright notice below. |
| 24 |
* |
|
| 24 |
* |
|
| 25 | 25 |
* Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura, |
| 26 |
* All rights reserved. |
|
| 26 |
* All rights reserved. |
|
| 27 | 27 |
* |
| 28 | 28 |
* Redistribution and use in source and binary forms, with or without |
| 29 | 29 |
* modification, are permitted provided that the following conditions |
| 30 | 30 |
* are met: |
| 31 | 31 |
* |
| 32 | 32 |
* 1. Redistributions of source code must retain the above copyright |
| 33 | 33 |
* notice, this list of conditions and the following disclaimer. |
| 34 | 34 |
* |
| 35 | 35 |
* 2. Redistributions in binary form must reproduce the above copyright |
| 36 | 36 |
* notice, this list of conditions and the following disclaimer in the |
| 37 | 37 |
* documentation and/or other materials provided with the distribution. |
| 38 | 38 |
* |
| 39 |
* 3. The names of its contributors may not be used to endorse or promote |
|
| 40 |
* products derived from this software without specific prior written |
|
| 39 |
* 3. The names of its contributors may not be used to endorse or promote |
|
| 40 |
* products derived from this software without specific prior written |
|
| 41 | 41 |
* permission. |
| 42 | 42 |
* |
| 43 | 43 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| 44 | 44 |
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| 45 | 45 |
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| 46 | 46 |
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| 47 | 47 |
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| 48 | 48 |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| 49 | 49 |
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
| 50 | 50 |
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| 51 | 51 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| 52 | 52 |
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
| 53 | 53 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
| 54 | 54 |
* OF THE POSSIBILITY OF SUCH DAMAGE. |
| 55 | 55 |
* |
| 56 | 56 |
* |
| ... | ... |
@@ -74,45 +74,45 @@ |
| 74 | 74 |
#ifndef WIN32 |
| 75 | 75 |
#include <sys/time.h> |
| 76 | 76 |
#include <ctime> |
| 77 | 77 |
#include <sys/types.h> |
| 78 | 78 |
#include <unistd.h> |
| 79 | 79 |
#else |
| 80 | 80 |
#include <windows.h> |
| 81 | 81 |
#endif |
| 82 | 82 |
|
| 83 | 83 |
///\ingroup misc |
| 84 | 84 |
///\file |
| 85 | 85 |
///\brief Mersenne Twister random number generator |
| 86 | 86 |
|
| 87 | 87 |
namespace lemon {
|
| 88 | 88 |
|
| 89 | 89 |
namespace _random_bits {
|
| 90 |
|
|
| 90 |
|
|
| 91 | 91 |
template <typename _Word, int _bits = std::numeric_limits<_Word>::digits> |
| 92 | 92 |
struct RandomTraits {};
|
| 93 | 93 |
|
| 94 | 94 |
template <typename _Word> |
| 95 | 95 |
struct RandomTraits<_Word, 32> {
|
| 96 | 96 |
|
| 97 | 97 |
typedef _Word Word; |
| 98 | 98 |
static const int bits = 32; |
| 99 | 99 |
|
| 100 | 100 |
static const int length = 624; |
| 101 | 101 |
static const int shift = 397; |
| 102 |
|
|
| 102 |
|
|
| 103 | 103 |
static const Word mul = 0x6c078965u; |
| 104 | 104 |
static const Word arrayInit = 0x012BD6AAu; |
| 105 | 105 |
static const Word arrayMul1 = 0x0019660Du; |
| 106 | 106 |
static const Word arrayMul2 = 0x5D588B65u; |
| 107 | 107 |
|
| 108 | 108 |
static const Word mask = 0x9908B0DFu; |
| 109 | 109 |
static const Word loMask = (1u << 31) - 1; |
| 110 | 110 |
static const Word hiMask = ~loMask; |
| 111 | 111 |
|
| 112 | 112 |
|
| 113 | 113 |
static Word tempering(Word rnd) {
|
| 114 | 114 |
rnd ^= (rnd >> 11); |
| 115 | 115 |
rnd ^= (rnd << 7) & 0x9D2C5680u; |
| 116 | 116 |
rnd ^= (rnd << 15) & 0xEFC60000u; |
| 117 | 117 |
rnd ^= (rnd >> 18); |
| 118 | 118 |
return rnd; |
| ... | ... |
@@ -154,285 +154,285 @@ |
| 154 | 154 |
|
| 155 | 155 |
typedef _Word Word; |
| 156 | 156 |
|
| 157 | 157 |
private: |
| 158 | 158 |
|
| 159 | 159 |
static const int bits = RandomTraits<Word>::bits; |
| 160 | 160 |
|
| 161 | 161 |
static const int length = RandomTraits<Word>::length; |
| 162 | 162 |
static const int shift = RandomTraits<Word>::shift; |
| 163 | 163 |
|
| 164 | 164 |
public: |
| 165 | 165 |
|
| 166 | 166 |
void initState() {
|
| 167 | 167 |
static const Word seedArray[4] = {
|
| 168 | 168 |
0x12345u, 0x23456u, 0x34567u, 0x45678u |
| 169 | 169 |
}; |
| 170 |
|
|
| 170 |
|
|
| 171 | 171 |
initState(seedArray, seedArray + 4); |
| 172 | 172 |
} |
| 173 | 173 |
|
| 174 | 174 |
void initState(Word seed) {
|
| 175 | 175 |
|
| 176 | 176 |
static const Word mul = RandomTraits<Word>::mul; |
| 177 | 177 |
|
| 178 |
current = state; |
|
| 178 |
current = state; |
|
| 179 | 179 |
|
| 180 | 180 |
Word *curr = state + length - 1; |
| 181 | 181 |
curr[0] = seed; --curr; |
| 182 | 182 |
for (int i = 1; i < length; ++i) {
|
| 183 | 183 |
curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i); |
| 184 | 184 |
--curr; |
| 185 | 185 |
} |
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 | 188 |
template <typename Iterator> |
| 189 | 189 |
void initState(Iterator begin, Iterator end) {
|
| 190 | 190 |
|
| 191 | 191 |
static const Word init = RandomTraits<Word>::arrayInit; |
| 192 | 192 |
static const Word mul1 = RandomTraits<Word>::arrayMul1; |
| 193 | 193 |
static const Word mul2 = RandomTraits<Word>::arrayMul2; |
| 194 | 194 |
|
| 195 | 195 |
|
| 196 | 196 |
Word *curr = state + length - 1; --curr; |
| 197 | 197 |
Iterator it = begin; int cnt = 0; |
| 198 | 198 |
int num; |
| 199 | 199 |
|
| 200 | 200 |
initState(init); |
| 201 | 201 |
|
| 202 | 202 |
num = length > end - begin ? length : end - begin; |
| 203 | 203 |
while (num--) {
|
| 204 |
curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1)) |
|
| 204 |
curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1)) |
|
| 205 | 205 |
+ *it + cnt; |
| 206 | 206 |
++it; ++cnt; |
| 207 | 207 |
if (it == end) {
|
| 208 | 208 |
it = begin; cnt = 0; |
| 209 | 209 |
} |
| 210 | 210 |
if (curr == state) {
|
| 211 | 211 |
curr = state + length - 1; curr[0] = state[0]; |
| 212 | 212 |
} |
| 213 | 213 |
--curr; |
| 214 | 214 |
} |
| 215 | 215 |
|
| 216 | 216 |
num = length - 1; cnt = length - (curr - state) - 1; |
| 217 | 217 |
while (num--) {
|
| 218 | 218 |
curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2)) |
| 219 | 219 |
- cnt; |
| 220 | 220 |
--curr; ++cnt; |
| 221 | 221 |
if (curr == state) {
|
| 222 | 222 |
curr = state + length - 1; curr[0] = state[0]; --curr; |
| 223 | 223 |
cnt = 1; |
| 224 | 224 |
} |
| 225 | 225 |
} |
| 226 |
|
|
| 226 |
|
|
| 227 | 227 |
state[length - 1] = Word(1) << (bits - 1); |
| 228 | 228 |
} |
| 229 |
|
|
| 229 |
|
|
| 230 | 230 |
void copyState(const RandomCore& other) {
|
| 231 | 231 |
std::copy(other.state, other.state + length, state); |
| 232 | 232 |
current = state + (other.current - other.state); |
| 233 | 233 |
} |
| 234 | 234 |
|
| 235 | 235 |
Word operator()() {
|
| 236 | 236 |
if (current == state) fillState(); |
| 237 | 237 |
--current; |
| 238 | 238 |
Word rnd = *current; |
| 239 | 239 |
return RandomTraits<Word>::tempering(rnd); |
| 240 | 240 |
} |
| 241 | 241 |
|
| 242 | 242 |
private: |
| 243 | 243 |
|
| 244 |
|
|
| 244 |
|
|
| 245 | 245 |
void fillState() {
|
| 246 | 246 |
static const Word mask[2] = { 0x0ul, RandomTraits<Word>::mask };
|
| 247 | 247 |
static const Word loMask = RandomTraits<Word>::loMask; |
| 248 | 248 |
static const Word hiMask = RandomTraits<Word>::hiMask; |
| 249 | 249 |
|
| 250 |
current = state + length; |
|
| 250 |
current = state + length; |
|
| 251 | 251 |
|
| 252 | 252 |
register Word *curr = state + length - 1; |
| 253 | 253 |
register long num; |
| 254 |
|
|
| 254 |
|
|
| 255 | 255 |
num = length - shift; |
| 256 | 256 |
while (num--) {
|
| 257 | 257 |
curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ |
| 258 | 258 |
curr[- shift] ^ mask[curr[-1] & 1ul]; |
| 259 | 259 |
--curr; |
| 260 | 260 |
} |
| 261 | 261 |
num = shift - 1; |
| 262 | 262 |
while (num--) {
|
| 263 | 263 |
curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ |
| 264 | 264 |
curr[length - shift] ^ mask[curr[-1] & 1ul]; |
| 265 | 265 |
--curr; |
| 266 | 266 |
} |
| 267 | 267 |
state[0] = (((state[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^ |
| 268 | 268 |
curr[length - shift] ^ mask[curr[length - 1] & 1ul]; |
| 269 | 269 |
|
| 270 | 270 |
} |
| 271 | 271 |
|
| 272 |
|
|
| 272 |
|
|
| 273 | 273 |
Word *current; |
| 274 | 274 |
Word state[length]; |
| 275 |
|
|
| 275 |
|
|
| 276 | 276 |
}; |
| 277 | 277 |
|
| 278 | 278 |
|
| 279 |
template <typename Result, |
|
| 279 |
template <typename Result, |
|
| 280 | 280 |
int shift = (std::numeric_limits<Result>::digits + 1) / 2> |
| 281 | 281 |
struct Masker {
|
| 282 | 282 |
static Result mask(const Result& result) {
|
| 283 | 283 |
return Masker<Result, (shift + 1) / 2>:: |
| 284 | 284 |
mask(static_cast<Result>(result | (result >> shift))); |
| 285 | 285 |
} |
| 286 | 286 |
}; |
| 287 |
|
|
| 287 |
|
|
| 288 | 288 |
template <typename Result> |
| 289 | 289 |
struct Masker<Result, 1> {
|
| 290 | 290 |
static Result mask(const Result& result) {
|
| 291 | 291 |
return static_cast<Result>(result | (result >> 1)); |
| 292 | 292 |
} |
| 293 | 293 |
}; |
| 294 | 294 |
|
| 295 |
template <typename Result, typename Word, |
|
| 296 |
int rest = std::numeric_limits<Result>::digits, int shift = 0, |
|
| 295 |
template <typename Result, typename Word, |
|
| 296 |
int rest = std::numeric_limits<Result>::digits, int shift = 0, |
|
| 297 | 297 |
bool last = rest <= std::numeric_limits<Word>::digits> |
| 298 | 298 |
struct IntConversion {
|
| 299 | 299 |
static const int bits = std::numeric_limits<Word>::digits; |
| 300 |
|
|
| 300 |
|
|
| 301 | 301 |
static Result convert(RandomCore<Word>& rnd) {
|
| 302 | 302 |
return static_cast<Result>(rnd() >> (bits - rest)) << shift; |
| 303 | 303 |
} |
| 304 |
|
|
| 305 |
}; |
|
| 306 | 304 |
|
| 307 |
|
|
| 305 |
}; |
|
| 306 |
|
|
| 307 |
template <typename Result, typename Word, int rest, int shift> |
|
| 308 | 308 |
struct IntConversion<Result, Word, rest, shift, false> {
|
| 309 | 309 |
static const int bits = std::numeric_limits<Word>::digits; |
| 310 | 310 |
|
| 311 | 311 |
static Result convert(RandomCore<Word>& rnd) {
|
| 312 |
return (static_cast<Result>(rnd()) << shift) | |
|
| 312 |
return (static_cast<Result>(rnd()) << shift) | |
|
| 313 | 313 |
IntConversion<Result, Word, rest - bits, shift + bits>::convert(rnd); |
| 314 | 314 |
} |
| 315 | 315 |
}; |
| 316 | 316 |
|
| 317 | 317 |
|
| 318 | 318 |
template <typename Result, typename Word, |
| 319 |
bool one_word = (std::numeric_limits<Word>::digits < |
|
| 320 |
std::numeric_limits<Result>::digits) > |
|
| 319 |
bool one_word = (std::numeric_limits<Word>::digits < |
|
| 320 |
std::numeric_limits<Result>::digits) > |
|
| 321 | 321 |
struct Mapping {
|
| 322 | 322 |
static Result map(RandomCore<Word>& rnd, const Result& bound) {
|
| 323 | 323 |
Word max = Word(bound - 1); |
| 324 | 324 |
Result mask = Masker<Result>::mask(bound - 1); |
| 325 | 325 |
Result num; |
| 326 | 326 |
do {
|
| 327 |
num = IntConversion<Result, Word>::convert(rnd) & mask; |
|
| 327 |
num = IntConversion<Result, Word>::convert(rnd) & mask; |
|
| 328 | 328 |
} while (num > max); |
| 329 | 329 |
return num; |
| 330 | 330 |
} |
| 331 | 331 |
}; |
| 332 | 332 |
|
| 333 | 333 |
template <typename Result, typename Word> |
| 334 | 334 |
struct Mapping<Result, Word, false> {
|
| 335 | 335 |
static Result map(RandomCore<Word>& rnd, const Result& bound) {
|
| 336 | 336 |
Word max = Word(bound - 1); |
| 337 | 337 |
Word mask = Masker<Word, (std::numeric_limits<Result>::digits + 1) / 2> |
| 338 | 338 |
::mask(max); |
| 339 | 339 |
Word num; |
| 340 | 340 |
do {
|
| 341 | 341 |
num = rnd() & mask; |
| 342 | 342 |
} while (num > max); |
| 343 | 343 |
return num; |
| 344 | 344 |
} |
| 345 | 345 |
}; |
| 346 | 346 |
|
| 347 | 347 |
template <typename Result, int exp, bool pos = (exp >= 0)> |
| 348 | 348 |
struct ShiftMultiplier {
|
| 349 | 349 |
static const Result multiplier() {
|
| 350 | 350 |
Result res = ShiftMultiplier<Result, exp / 2>::multiplier(); |
| 351 | 351 |
res *= res; |
| 352 | 352 |
if ((exp & 1) == 1) res *= static_cast<Result>(2.0); |
| 353 |
return res; |
|
| 353 |
return res; |
|
| 354 | 354 |
} |
| 355 | 355 |
}; |
| 356 | 356 |
|
| 357 | 357 |
template <typename Result, int exp> |
| 358 | 358 |
struct ShiftMultiplier<Result, exp, false> {
|
| 359 | 359 |
static const Result multiplier() {
|
| 360 | 360 |
Result res = ShiftMultiplier<Result, exp / 2>::multiplier(); |
| 361 | 361 |
res *= res; |
| 362 | 362 |
if ((exp & 1) == 1) res *= static_cast<Result>(0.5); |
| 363 |
return res; |
|
| 363 |
return res; |
|
| 364 | 364 |
} |
| 365 | 365 |
}; |
| 366 | 366 |
|
| 367 | 367 |
template <typename Result> |
| 368 | 368 |
struct ShiftMultiplier<Result, 0, true> {
|
| 369 | 369 |
static const Result multiplier() {
|
| 370 |
return static_cast<Result>(1.0); |
|
| 370 |
return static_cast<Result>(1.0); |
|
| 371 | 371 |
} |
| 372 | 372 |
}; |
| 373 | 373 |
|
| 374 | 374 |
template <typename Result> |
| 375 | 375 |
struct ShiftMultiplier<Result, -20, true> {
|
| 376 | 376 |
static const Result multiplier() {
|
| 377 |
return static_cast<Result>(1.0/1048576.0); |
|
| 377 |
return static_cast<Result>(1.0/1048576.0); |
|
| 378 | 378 |
} |
| 379 | 379 |
}; |
| 380 |
|
|
| 380 |
|
|
| 381 | 381 |
template <typename Result> |
| 382 | 382 |
struct ShiftMultiplier<Result, -32, true> {
|
| 383 | 383 |
static const Result multiplier() {
|
| 384 |
return static_cast<Result>(1.0/424967296.0); |
|
| 384 |
return static_cast<Result>(1.0/424967296.0); |
|
| 385 | 385 |
} |
| 386 | 386 |
}; |
| 387 | 387 |
|
| 388 | 388 |
template <typename Result> |
| 389 | 389 |
struct ShiftMultiplier<Result, -53, true> {
|
| 390 | 390 |
static const Result multiplier() {
|
| 391 |
return static_cast<Result>(1.0/9007199254740992.0); |
|
| 391 |
return static_cast<Result>(1.0/9007199254740992.0); |
|
| 392 | 392 |
} |
| 393 | 393 |
}; |
| 394 | 394 |
|
| 395 | 395 |
template <typename Result> |
| 396 | 396 |
struct ShiftMultiplier<Result, -64, true> {
|
| 397 | 397 |
static const Result multiplier() {
|
| 398 |
return static_cast<Result>(1.0/18446744073709551616.0); |
|
| 398 |
return static_cast<Result>(1.0/18446744073709551616.0); |
|
| 399 | 399 |
} |
| 400 | 400 |
}; |
| 401 | 401 |
|
| 402 | 402 |
template <typename Result, int exp> |
| 403 | 403 |
struct Shifting {
|
| 404 | 404 |
static Result shift(const Result& result) {
|
| 405 | 405 |
return result * ShiftMultiplier<Result, exp>::multiplier(); |
| 406 | 406 |
} |
| 407 | 407 |
}; |
| 408 | 408 |
|
| 409 | 409 |
template <typename Result, typename Word, |
| 410 |
int rest = std::numeric_limits<Result>::digits, int shift = 0, |
|
| 410 |
int rest = std::numeric_limits<Result>::digits, int shift = 0, |
|
| 411 | 411 |
bool last = rest <= std::numeric_limits<Word>::digits> |
| 412 |
struct RealConversion{
|
|
| 412 |
struct RealConversion{
|
|
| 413 | 413 |
static const int bits = std::numeric_limits<Word>::digits; |
| 414 | 414 |
|
| 415 | 415 |
static Result convert(RandomCore<Word>& rnd) {
|
| 416 | 416 |
return Shifting<Result, - shift - rest>:: |
| 417 | 417 |
shift(static_cast<Result>(rnd() >> (bits - rest))); |
| 418 | 418 |
} |
| 419 | 419 |
}; |
| 420 | 420 |
|
| 421 | 421 |
template <typename Result, typename Word, int rest, int shift> |
| 422 |
struct RealConversion<Result, Word, rest, shift, false> {
|
|
| 422 |
struct RealConversion<Result, Word, rest, shift, false> {
|
|
| 423 | 423 |
static const int bits = std::numeric_limits<Word>::digits; |
| 424 | 424 |
|
| 425 | 425 |
static Result convert(RandomCore<Word>& rnd) {
|
| 426 | 426 |
return Shifting<Result, - shift - bits>:: |
| 427 | 427 |
shift(static_cast<Result>(rnd())) + |
| 428 | 428 |
RealConversion<Result, Word, rest-bits, shift + bits>:: |
| 429 | 429 |
convert(rnd); |
| 430 | 430 |
} |
| 431 | 431 |
}; |
| 432 | 432 |
|
| 433 | 433 |
template <typename Result, typename Word> |
| 434 | 434 |
struct Initializer {
|
| 435 | 435 |
|
| 436 | 436 |
template <typename Iterator> |
| 437 | 437 |
static void init(RandomCore<Word>& rnd, Iterator begin, Iterator end) {
|
| 438 | 438 |
std::vector<Word> ws; |
| ... | ... |
@@ -445,33 +445,33 @@ |
| 445 | 445 |
static void init(RandomCore<Word>& rnd, Result seed) {
|
| 446 | 446 |
rnd.initState(seed); |
| 447 | 447 |
} |
| 448 | 448 |
}; |
| 449 | 449 |
|
| 450 | 450 |
template <typename Word> |
| 451 | 451 |
struct BoolConversion {
|
| 452 | 452 |
static bool convert(RandomCore<Word>& rnd) {
|
| 453 | 453 |
return (rnd() & 1) == 1; |
| 454 | 454 |
} |
| 455 | 455 |
}; |
| 456 | 456 |
|
| 457 | 457 |
template <typename Word> |
| 458 | 458 |
struct BoolProducer {
|
| 459 | 459 |
Word buffer; |
| 460 | 460 |
int num; |
| 461 |
|
|
| 461 |
|
|
| 462 | 462 |
BoolProducer() : num(0) {}
|
| 463 | 463 |
|
| 464 | 464 |
bool convert(RandomCore<Word>& rnd) {
|
| 465 | 465 |
if (num == 0) {
|
| 466 | 466 |
buffer = rnd(); |
| 467 | 467 |
num = RandomTraits<Word>::bits; |
| 468 | 468 |
} |
| 469 | 469 |
bool r = (buffer & 1); |
| 470 | 470 |
buffer >>= 1; |
| 471 | 471 |
--num; |
| 472 | 472 |
return r; |
| 473 | 473 |
} |
| 474 | 474 |
}; |
| 475 | 475 |
|
| 476 | 476 |
} |
| 477 | 477 |
|
| ... | ... |
@@ -516,164 +516,164 @@ |
| 516 | 516 |
/// // int e = rnd.integer(1, 1 + 6); // 1..6 |
| 517 | 517 |
/// int b = rnd.uinteger<int>(); // 0 .. 2^31 - 1 |
| 518 | 518 |
/// int c = rnd.integer<int>(); // - 2^31 .. 2^31 - 1 |
| 519 | 519 |
/// bool g = rnd.boolean(); // P(g = true) = 0.5 |
| 520 | 520 |
/// bool h = rnd.boolean(0.8); // P(h = true) = 0.8 |
| 521 | 521 |
///\endcode |
| 522 | 522 |
/// |
| 523 | 523 |
/// LEMON provides a global instance of the random number |
| 524 | 524 |
/// generator which name is \ref lemon::rnd "rnd". Usually it is a |
| 525 | 525 |
/// good programming convenience to use this global generator to get |
| 526 | 526 |
/// random numbers. |
| 527 | 527 |
class Random {
|
| 528 | 528 |
private: |
| 529 | 529 |
|
| 530 | 530 |
// Architecture word |
| 531 | 531 |
typedef unsigned long Word; |
| 532 |
|
|
| 532 |
|
|
| 533 | 533 |
_random_bits::RandomCore<Word> core; |
| 534 | 534 |
_random_bits::BoolProducer<Word> bool_producer; |
| 535 |
|
|
| 535 |
|
|
| 536 | 536 |
|
| 537 | 537 |
public: |
| 538 | 538 |
|
| 539 | 539 |
///\name Initialization |
| 540 | 540 |
/// |
| 541 | 541 |
/// @{
|
| 542 | 542 |
|
| 543 | 543 |
///\name Initialization |
| 544 | 544 |
/// |
| 545 | 545 |
/// @{
|
| 546 | 546 |
|
| 547 | 547 |
/// \brief Default constructor |
| 548 | 548 |
/// |
| 549 | 549 |
/// Constructor with constant seeding. |
| 550 | 550 |
Random() { core.initState(); }
|
| 551 | 551 |
|
| 552 | 552 |
/// \brief Constructor with seed |
| 553 | 553 |
/// |
| 554 | 554 |
/// Constructor with seed. The current number type will be converted |
| 555 | 555 |
/// to the architecture word type. |
| 556 | 556 |
template <typename Number> |
| 557 |
Random(Number seed) {
|
|
| 557 |
Random(Number seed) {
|
|
| 558 | 558 |
_random_bits::Initializer<Number, Word>::init(core, seed); |
| 559 | 559 |
} |
| 560 | 560 |
|
| 561 | 561 |
/// \brief Constructor with array seeding |
| 562 | 562 |
/// |
| 563 | 563 |
/// Constructor with array seeding. The given range should contain |
| 564 | 564 |
/// any number type and the numbers will be converted to the |
| 565 | 565 |
/// architecture word type. |
| 566 | 566 |
template <typename Iterator> |
| 567 |
Random(Iterator begin, Iterator end) {
|
|
| 567 |
Random(Iterator begin, Iterator end) {
|
|
| 568 | 568 |
typedef typename std::iterator_traits<Iterator>::value_type Number; |
| 569 | 569 |
_random_bits::Initializer<Number, Word>::init(core, begin, end); |
| 570 | 570 |
} |
| 571 | 571 |
|
| 572 | 572 |
/// \brief Copy constructor |
| 573 | 573 |
/// |
| 574 | 574 |
/// Copy constructor. The generated sequence will be identical to |
| 575 | 575 |
/// the other sequence. It can be used to save the current state |
| 576 | 576 |
/// of the generator and later use it to generate the same |
| 577 | 577 |
/// sequence. |
| 578 | 578 |
Random(const Random& other) {
|
| 579 | 579 |
core.copyState(other.core); |
| 580 | 580 |
} |
| 581 | 581 |
|
| 582 | 582 |
/// \brief Assign operator |
| 583 | 583 |
/// |
| 584 | 584 |
/// Assign operator. The generated sequence will be identical to |
| 585 | 585 |
/// the other sequence. It can be used to save the current state |
| 586 | 586 |
/// of the generator and later use it to generate the same |
| 587 | 587 |
/// sequence. |
| 588 | 588 |
Random& operator=(const Random& other) {
|
| 589 | 589 |
if (&other != this) {
|
| 590 | 590 |
core.copyState(other.core); |
| 591 | 591 |
} |
| 592 | 592 |
return *this; |
| 593 | 593 |
} |
| 594 | 594 |
|
| 595 | 595 |
/// \brief Seeding random sequence |
| 596 | 596 |
/// |
| 597 | 597 |
/// Seeding the random sequence. The current number type will be |
| 598 | 598 |
/// converted to the architecture word type. |
| 599 | 599 |
template <typename Number> |
| 600 |
void seed(Number seed) {
|
|
| 600 |
void seed(Number seed) {
|
|
| 601 | 601 |
_random_bits::Initializer<Number, Word>::init(core, seed); |
| 602 | 602 |
} |
| 603 | 603 |
|
| 604 | 604 |
/// \brief Seeding random sequence |
| 605 | 605 |
/// |
| 606 | 606 |
/// Seeding the random sequence. The given range should contain |
| 607 | 607 |
/// any number type and the numbers will be converted to the |
| 608 | 608 |
/// architecture word type. |
| 609 | 609 |
template <typename Iterator> |
| 610 |
void seed(Iterator begin, Iterator end) {
|
|
| 610 |
void seed(Iterator begin, Iterator end) {
|
|
| 611 | 611 |
typedef typename std::iterator_traits<Iterator>::value_type Number; |
| 612 | 612 |
_random_bits::Initializer<Number, Word>::init(core, begin, end); |
| 613 | 613 |
} |
| 614 | 614 |
|
| 615 | 615 |
/// \brief Seeding from file or from process id and time |
| 616 | 616 |
/// |
| 617 | 617 |
/// By default, this function calls the \c seedFromFile() member |
| 618 | 618 |
/// function with the <tt>/dev/urandom</tt> file. If it does not success, |
| 619 | 619 |
/// it uses the \c seedFromTime(). |
| 620 | 620 |
/// \return Currently always true. |
| 621 | 621 |
bool seed() {
|
| 622 | 622 |
#ifndef WIN32 |
| 623 | 623 |
if (seedFromFile("/dev/urandom", 0)) return true;
|
| 624 | 624 |
#endif |
| 625 | 625 |
if (seedFromTime()) return true; |
| 626 | 626 |
return false; |
| 627 | 627 |
} |
| 628 |
|
|
| 628 |
|
|
| 629 | 629 |
/// \brief Seeding from file |
| 630 | 630 |
/// |
| 631 | 631 |
/// Seeding the random sequence from file. The linux kernel has two |
| 632 | 632 |
/// devices, <tt>/dev/random</tt> and <tt>/dev/urandom</tt> which |
| 633 | 633 |
/// could give good seed values for pseudo random generators (The |
| 634 | 634 |
/// difference between two devices is that the <tt>random</tt> may |
| 635 | 635 |
/// block the reading operation while the kernel can give good |
| 636 | 636 |
/// source of randomness, while the <tt>urandom</tt> does not |
| 637 | 637 |
/// block the input, but it could give back bytes with worse |
| 638 | 638 |
/// entropy). |
| 639 | 639 |
/// \param file The source file |
| 640 | 640 |
/// \param offset The offset, from the file read. |
| 641 | 641 |
/// \return True when the seeding successes. |
| 642 | 642 |
#ifndef WIN32 |
| 643 |
bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0) |
|
| 643 |
bool seedFromFile(const std::string& file = "/dev/urandom", int offset = 0) |
|
| 644 | 644 |
#else |
| 645 |
bool seedFromFile(const std::string& file = "", int offset = 0) |
|
| 645 |
bool seedFromFile(const std::string& file = "", int offset = 0) |
|
| 646 | 646 |
#endif |
| 647 | 647 |
{
|
| 648 | 648 |
std::ifstream rs(file.c_str()); |
| 649 | 649 |
const int size = 4; |
| 650 | 650 |
Word buf[size]; |
| 651 | 651 |
if (offset != 0 && !rs.seekg(offset)) return false; |
| 652 | 652 |
if (!rs.read(reinterpret_cast<char*>(buf), sizeof(buf))) return false; |
| 653 | 653 |
seed(buf, buf + size); |
| 654 | 654 |
return true; |
| 655 | 655 |
} |
| 656 | 656 |
|
| 657 | 657 |
/// \brief Seding from process id and time |
| 658 | 658 |
/// |
| 659 | 659 |
/// Seding from process id and time. This function uses the |
| 660 | 660 |
/// current process id and the current time for initialize the |
| 661 | 661 |
/// random sequence. |
| 662 | 662 |
/// \return Currently always true. |
| 663 |
bool seedFromTime() {
|
|
| 663 |
bool seedFromTime() {
|
|
| 664 | 664 |
#ifndef WIN32 |
| 665 | 665 |
timeval tv; |
| 666 | 666 |
gettimeofday(&tv, 0); |
| 667 | 667 |
seed(getpid() + tv.tv_sec + tv.tv_usec); |
| 668 | 668 |
#else |
| 669 | 669 |
FILETIME time; |
| 670 | 670 |
GetSystemTimeAsFileTime(&time); |
| 671 | 671 |
seed(GetCurrentProcessId() + time.dwHighDateTime + time.dwLowDateTime); |
| 672 | 672 |
#endif |
| 673 | 673 |
return true; |
| 674 | 674 |
} |
| 675 | 675 |
|
| 676 | 676 |
/// @} |
| 677 | 677 |
|
| 678 | 678 |
///\name Uniform distributions |
| 679 | 679 |
/// |
| ... | ... |
@@ -683,71 +683,71 @@ |
| 683 | 683 |
/// |
| 684 | 684 |
/// It returns a random real number from the range [0, 1). The |
| 685 | 685 |
/// default Number type is \c double. |
| 686 | 686 |
template <typename Number> |
| 687 | 687 |
Number real() {
|
| 688 | 688 |
return _random_bits::RealConversion<Number, Word>::convert(core); |
| 689 | 689 |
} |
| 690 | 690 |
|
| 691 | 691 |
double real() {
|
| 692 | 692 |
return real<double>(); |
| 693 | 693 |
} |
| 694 | 694 |
|
| 695 | 695 |
/// \brief Returns a random real number the range [0, b) |
| 696 | 696 |
/// |
| 697 | 697 |
/// It returns a random real number from the range [0, b). |
| 698 | 698 |
template <typename Number> |
| 699 |
Number real(Number b) {
|
|
| 700 |
return real<Number>() * b; |
|
| 699 |
Number real(Number b) {
|
|
| 700 |
return real<Number>() * b; |
|
| 701 | 701 |
} |
| 702 | 702 |
|
| 703 | 703 |
/// \brief Returns a random real number from the range [a, b) |
| 704 | 704 |
/// |
| 705 | 705 |
/// It returns a random real number from the range [a, b). |
| 706 | 706 |
template <typename Number> |
| 707 |
Number real(Number a, Number b) {
|
|
| 708 |
return real<Number>() * (b - a) + a; |
|
| 707 |
Number real(Number a, Number b) {
|
|
| 708 |
return real<Number>() * (b - a) + a; |
|
| 709 | 709 |
} |
| 710 | 710 |
|
| 711 | 711 |
/// @} |
| 712 | 712 |
|
| 713 | 713 |
///\name Uniform distributions |
| 714 | 714 |
/// |
| 715 | 715 |
/// @{
|
| 716 | 716 |
|
| 717 | 717 |
/// \brief Returns a random real number from the range [0, 1) |
| 718 | 718 |
/// |
| 719 | 719 |
/// It returns a random double from the range [0, 1). |
| 720 | 720 |
double operator()() {
|
| 721 | 721 |
return real<double>(); |
| 722 | 722 |
} |
| 723 | 723 |
|
| 724 | 724 |
/// \brief Returns a random real number from the range [0, b) |
| 725 | 725 |
/// |
| 726 | 726 |
/// It returns a random real number from the range [0, b). |
| 727 | 727 |
template <typename Number> |
| 728 |
Number operator()(Number b) {
|
|
| 729 |
return real<Number>() * b; |
|
| 728 |
Number operator()(Number b) {
|
|
| 729 |
return real<Number>() * b; |
|
| 730 | 730 |
} |
| 731 | 731 |
|
| 732 | 732 |
/// \brief Returns a random real number from the range [a, b) |
| 733 | 733 |
/// |
| 734 | 734 |
/// It returns a random real number from the range [a, b). |
| 735 | 735 |
template <typename Number> |
| 736 |
Number operator()(Number a, Number b) {
|
|
| 737 |
return real<Number>() * (b - a) + a; |
|
| 736 |
Number operator()(Number a, Number b) {
|
|
| 737 |
return real<Number>() * (b - a) + a; |
|
| 738 | 738 |
} |
| 739 | 739 |
|
| 740 | 740 |
/// \brief Returns a random integer from a range |
| 741 | 741 |
/// |
| 742 | 742 |
/// It returns a random integer from the range {0, 1, ..., b - 1}.
|
| 743 | 743 |
template <typename Number> |
| 744 | 744 |
Number integer(Number b) {
|
| 745 | 745 |
return _random_bits::Mapping<Number, Word>::map(core, b); |
| 746 | 746 |
} |
| 747 | 747 |
|
| 748 | 748 |
/// \brief Returns a random integer from a range |
| 749 | 749 |
/// |
| 750 | 750 |
/// It returns a random integer from the range {a, a + 1, ..., b - 1}.
|
| 751 | 751 |
template <typename Number> |
| 752 | 752 |
Number integer(Number a, Number b) {
|
| 753 | 753 |
return _random_bits::Mapping<Number, Word>::map(core, b - a) + a; |
| ... | ... |
@@ -771,240 +771,240 @@ |
| 771 | 771 |
return _random_bits::IntConversion<Number, Word>::convert(core); |
| 772 | 772 |
} |
| 773 | 773 |
|
| 774 | 774 |
/// @} |
| 775 | 775 |
|
| 776 | 776 |
unsigned int uinteger() {
|
| 777 | 777 |
return uinteger<unsigned int>(); |
| 778 | 778 |
} |
| 779 | 779 |
|
| 780 | 780 |
/// \brief Returns a random integer |
| 781 | 781 |
/// |
| 782 | 782 |
/// It returns a random integer uniformly from the whole range of |
| 783 | 783 |
/// the current \c Number type. The default result type of this |
| 784 | 784 |
/// function is \c int. |
| 785 | 785 |
template <typename Number> |
| 786 | 786 |
Number integer() {
|
| 787 |
static const int nb = std::numeric_limits<Number>::digits + |
|
| 787 |
static const int nb = std::numeric_limits<Number>::digits + |
|
| 788 | 788 |
(std::numeric_limits<Number>::is_signed ? 1 : 0); |
| 789 | 789 |
return _random_bits::IntConversion<Number, Word, nb>::convert(core); |
| 790 | 790 |
} |
| 791 | 791 |
|
| 792 | 792 |
int integer() {
|
| 793 | 793 |
return integer<int>(); |
| 794 | 794 |
} |
| 795 |
|
|
| 795 |
|
|
| 796 | 796 |
/// \brief Returns a random bool |
| 797 | 797 |
/// |
| 798 | 798 |
/// It returns a random bool. The generator holds a buffer for |
| 799 | 799 |
/// random bits. Every time when it become empty the generator makes |
| 800 | 800 |
/// a new random word and fill the buffer up. |
| 801 | 801 |
bool boolean() {
|
| 802 | 802 |
return bool_producer.convert(core); |
| 803 | 803 |
} |
| 804 | 804 |
|
| 805 | 805 |
/// @} |
| 806 | 806 |
|
| 807 | 807 |
///\name Non-uniform distributions |
| 808 | 808 |
/// |
| 809 |
|
|
| 809 |
|
|
| 810 | 810 |
///@{
|
| 811 |
|
|
| 811 |
|
|
| 812 | 812 |
/// \brief Returns a random bool |
| 813 | 813 |
/// |
| 814 | 814 |
/// It returns a random bool with given probability of true result. |
| 815 | 815 |
bool boolean(double p) {
|
| 816 | 816 |
return operator()() < p; |
| 817 | 817 |
} |
| 818 | 818 |
|
| 819 | 819 |
/// Standard Gauss distribution |
| 820 | 820 |
|
| 821 | 821 |
/// Standard Gauss distribution. |
| 822 | 822 |
/// \note The Cartesian form of the Box-Muller |
| 823 | 823 |
/// transformation is used to generate a random normal distribution. |
| 824 | 824 |
/// \todo Consider using the "ziggurat" method instead. |
| 825 |
double gauss() |
|
| 825 |
double gauss() |
|
| 826 | 826 |
{
|
| 827 | 827 |
double V1,V2,S; |
| 828 | 828 |
do {
|
| 829 |
V1=2*real<double>()-1; |
|
| 830 |
V2=2*real<double>()-1; |
|
| 831 |
|
|
| 829 |
V1=2*real<double>()-1; |
|
| 830 |
V2=2*real<double>()-1; |
|
| 831 |
S=V1*V1+V2*V2; |
|
| 832 | 832 |
} while(S>=1); |
| 833 | 833 |
return std::sqrt(-2*std::log(S)/S)*V1; |
| 834 | 834 |
} |
| 835 | 835 |
/// Gauss distribution with given mean and standard deviation |
| 836 | 836 |
|
| 837 | 837 |
/// Gauss distribution with given mean and standard deviation. |
| 838 | 838 |
/// \sa gauss() |
| 839 | 839 |
double gauss(double mean,double std_dev) |
| 840 | 840 |
{
|
| 841 | 841 |
return gauss()*std_dev+mean; |
| 842 | 842 |
} |
| 843 | 843 |
|
| 844 | 844 |
/// Exponential distribution with given mean |
| 845 | 845 |
|
| 846 | 846 |
/// This function generates an exponential distribution random number |
| 847 | 847 |
/// with mean <tt>1/lambda</tt>. |
| 848 | 848 |
/// |
| 849 | 849 |
double exponential(double lambda=1.0) |
| 850 | 850 |
{
|
| 851 | 851 |
return -std::log(1.0-real<double>())/lambda; |
| 852 | 852 |
} |
| 853 | 853 |
|
| 854 | 854 |
/// Gamma distribution with given integer shape |
| 855 | 855 |
|
| 856 | 856 |
/// This function generates a gamma distribution random number. |
| 857 |
/// |
|
| 857 |
/// |
|
| 858 | 858 |
///\param k shape parameter (<tt>k>0</tt> integer) |
| 859 |
double gamma(int k) |
|
| 859 |
double gamma(int k) |
|
| 860 | 860 |
{
|
| 861 | 861 |
double s = 0; |
| 862 | 862 |
for(int i=0;i<k;i++) s-=std::log(1.0-real<double>()); |
| 863 | 863 |
return s; |
| 864 | 864 |
} |
| 865 |
|
|
| 865 |
|
|
| 866 | 866 |
/// Gamma distribution with given shape and scale parameter |
| 867 | 867 |
|
| 868 | 868 |
/// This function generates a gamma distribution random number. |
| 869 |
/// |
|
| 869 |
/// |
|
| 870 | 870 |
///\param k shape parameter (<tt>k>0</tt>) |
| 871 | 871 |
///\param theta scale parameter |
| 872 | 872 |
/// |
| 873 | 873 |
double gamma(double k,double theta=1.0) |
| 874 | 874 |
{
|
| 875 | 875 |
double xi,nu; |
| 876 | 876 |
const double delta = k-std::floor(k); |
| 877 | 877 |
const double v0=E/(E-delta); |
| 878 | 878 |
do {
|
| 879 |
double V0=1.0-real<double>(); |
|
| 880 |
double V1=1.0-real<double>(); |
|
| 881 |
double V2=1.0-real<double>(); |
|
| 882 |
if(V2<=v0) |
|
| 883 |
{
|
|
| 884 |
xi=std::pow(V1,1.0/delta); |
|
| 885 |
nu=V0*std::pow(xi,delta-1.0); |
|
| 886 |
} |
|
| 887 |
else |
|
| 888 |
{
|
|
| 889 |
xi=1.0-std::log(V1); |
|
| 890 |
nu=V0*std::exp(-xi); |
|
| 891 |
|
|
| 879 |
double V0=1.0-real<double>(); |
|
| 880 |
double V1=1.0-real<double>(); |
|
| 881 |
double V2=1.0-real<double>(); |
|
| 882 |
if(V2<=v0) |
|
| 883 |
{
|
|
| 884 |
xi=std::pow(V1,1.0/delta); |
|
| 885 |
nu=V0*std::pow(xi,delta-1.0); |
|
| 886 |
} |
|
| 887 |
else |
|
| 888 |
{
|
|
| 889 |
xi=1.0-std::log(V1); |
|
| 890 |
nu=V0*std::exp(-xi); |
|
| 891 |
} |
|
| 892 | 892 |
} while(nu>std::pow(xi,delta-1.0)*std::exp(-xi)); |
| 893 | 893 |
return theta*(xi+gamma(int(std::floor(k)))); |
| 894 | 894 |
} |
| 895 |
|
|
| 895 |
|
|
| 896 | 896 |
/// Weibull distribution |
| 897 | 897 |
|
| 898 | 898 |
/// This function generates a Weibull distribution random number. |
| 899 |
/// |
|
| 899 |
/// |
|
| 900 | 900 |
///\param k shape parameter (<tt>k>0</tt>) |
| 901 | 901 |
///\param lambda scale parameter (<tt>lambda>0</tt>) |
| 902 | 902 |
/// |
| 903 | 903 |
double weibull(double k,double lambda) |
| 904 | 904 |
{
|
| 905 | 905 |
return lambda*pow(-std::log(1.0-real<double>()),1.0/k); |
| 906 |
} |
|
| 907 |
|
|
| 906 |
} |
|
| 907 |
|
|
| 908 | 908 |
/// Pareto distribution |
| 909 | 909 |
|
| 910 | 910 |
/// This function generates a Pareto distribution random number. |
| 911 |
/// |
|
| 911 |
/// |
|
| 912 | 912 |
///\param k shape parameter (<tt>k>0</tt>) |
| 913 | 913 |
///\param x_min location parameter (<tt>x_min>0</tt>) |
| 914 | 914 |
/// |
| 915 | 915 |
double pareto(double k,double x_min) |
| 916 | 916 |
{
|
| 917 | 917 |
return exponential(gamma(k,1.0/x_min))+x_min; |
| 918 |
} |
|
| 919 |
|
|
| 918 |
} |
|
| 919 |
|
|
| 920 | 920 |
/// Poisson distribution |
| 921 | 921 |
|
| 922 | 922 |
/// This function generates a Poisson distribution random number with |
| 923 | 923 |
/// parameter \c lambda. |
| 924 |
/// |
|
| 924 |
/// |
|
| 925 | 925 |
/// The probability mass function of this distribusion is |
| 926 | 926 |
/// \f[ \frac{e^{-\lambda}\lambda^k}{k!} \f]
|
| 927 | 927 |
/// \note The algorithm is taken from the book of Donald E. Knuth titled |
| 928 | 928 |
/// ''Seminumerical Algorithms'' (1969). Its running time is linear in the |
| 929 | 929 |
/// return value. |
| 930 |
|
|
| 930 |
|
|
| 931 | 931 |
int poisson(double lambda) |
| 932 | 932 |
{
|
| 933 | 933 |
const double l = std::exp(-lambda); |
| 934 | 934 |
int k=0; |
| 935 | 935 |
double p = 1.0; |
| 936 | 936 |
do {
|
| 937 |
k++; |
|
| 938 |
p*=real<double>(); |
|
| 937 |
k++; |
|
| 938 |
p*=real<double>(); |
|
| 939 | 939 |
} while (p>=l); |
| 940 | 940 |
return k-1; |
| 941 |
} |
|
| 942 |
|
|
| 941 |
} |
|
| 942 |
|
|
| 943 | 943 |
///@} |
| 944 |
|
|
| 944 |
|
|
| 945 | 945 |
///\name Two dimensional distributions |
| 946 | 946 |
/// |
| 947 | 947 |
|
| 948 | 948 |
///@{
|
| 949 |
|
|
| 949 |
|
|
| 950 | 950 |
/// Uniform distribution on the full unit circle |
| 951 | 951 |
|
| 952 | 952 |
/// Uniform distribution on the full unit circle. |
| 953 | 953 |
/// |
| 954 |
dim2::Point<double> disc() |
|
| 954 |
dim2::Point<double> disc() |
|
| 955 | 955 |
{
|
| 956 | 956 |
double V1,V2; |
| 957 | 957 |
do {
|
| 958 |
V1=2*real<double>()-1; |
|
| 959 |
V2=2*real<double>()-1; |
|
| 960 |
|
|
| 958 |
V1=2*real<double>()-1; |
|
| 959 |
V2=2*real<double>()-1; |
|
| 960 |
|
|
| 961 | 961 |
} while(V1*V1+V2*V2>=1); |
| 962 | 962 |
return dim2::Point<double>(V1,V2); |
| 963 | 963 |
} |
| 964 | 964 |
/// A kind of two dimensional Gauss distribution |
| 965 | 965 |
|
| 966 | 966 |
/// This function provides a turning symmetric two-dimensional distribution. |
| 967 | 967 |
/// Both coordinates are of standard normal distribution, but they are not |
| 968 | 968 |
/// independent. |
| 969 | 969 |
/// |
| 970 | 970 |
/// \note The coordinates are the two random variables provided by |
| 971 | 971 |
/// the Box-Muller method. |
| 972 | 972 |
dim2::Point<double> gauss2() |
| 973 | 973 |
{
|
| 974 | 974 |
double V1,V2,S; |
| 975 | 975 |
do {
|
| 976 |
V1=2*real<double>()-1; |
|
| 977 |
V2=2*real<double>()-1; |
|
| 978 |
|
|
| 976 |
V1=2*real<double>()-1; |
|
| 977 |
V2=2*real<double>()-1; |
|
| 978 |
S=V1*V1+V2*V2; |
|
| 979 | 979 |
} while(S>=1); |
| 980 | 980 |
double W=std::sqrt(-2*std::log(S)/S); |
| 981 | 981 |
return dim2::Point<double>(W*V1,W*V2); |
| 982 | 982 |
} |
| 983 | 983 |
/// A kind of two dimensional exponential distribution |
| 984 | 984 |
|
| 985 | 985 |
/// This function provides a turning symmetric two-dimensional distribution. |
| 986 | 986 |
/// The x-coordinate is of conditionally exponential distribution |
| 987 |
/// with the condition that x is positive and y=0. If x is negative and |
|
| 987 |
/// with the condition that x is positive and y=0. If x is negative and |
|
| 988 | 988 |
/// y=0 then, -x is of exponential distribution. The same is true for the |
| 989 | 989 |
/// y-coordinate. |
| 990 |
dim2::Point<double> exponential2() |
|
| 990 |
dim2::Point<double> exponential2() |
|
| 991 | 991 |
{
|
| 992 | 992 |
double V1,V2,S; |
| 993 | 993 |
do {
|
| 994 |
V1=2*real<double>()-1; |
|
| 995 |
V2=2*real<double>()-1; |
|
| 996 |
|
|
| 994 |
V1=2*real<double>()-1; |
|
| 995 |
V2=2*real<double>()-1; |
|
| 996 |
S=V1*V1+V2*V2; |
|
| 997 | 997 |
} while(S>=1); |
| 998 | 998 |
double W=-std::log(S)/S; |
| 999 | 999 |
return dim2::Point<double>(W*V1,W*V2); |
| 1000 | 1000 |
} |
| 1001 | 1001 |
|
| 1002 |
///@} |
|
| 1002 |
///@} |
|
| 1003 | 1003 |
}; |
| 1004 | 1004 |
|
| 1005 | 1005 |
|
| 1006 | 1006 |
extern Random rnd; |
| 1007 | 1007 |
|
| 1008 | 1008 |
} |
| 1009 | 1009 |
|
| 1010 | 1010 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_SMART_GRAPH_H |
| ... | ... |
@@ -32,124 +32,124 @@ |
| 32 | 32 |
|
| 33 | 33 |
#include <lemon/bits/utility.h> |
| 34 | 34 |
#include <lemon/error.h> |
| 35 | 35 |
|
| 36 | 36 |
#include <lemon/bits/graph_extender.h> |
| 37 | 37 |
|
| 38 | 38 |
namespace lemon {
|
| 39 | 39 |
|
| 40 | 40 |
class SmartDigraph; |
| 41 | 41 |
///Base of SmartDigraph |
| 42 | 42 |
|
| 43 | 43 |
///Base of SmartDigraph |
| 44 | 44 |
/// |
| 45 | 45 |
class SmartDigraphBase {
|
| 46 | 46 |
protected: |
| 47 | 47 |
|
| 48 |
struct NodeT |
|
| 48 |
struct NodeT |
|
| 49 | 49 |
{
|
| 50 |
int first_in, first_out; |
|
| 50 |
int first_in, first_out; |
|
| 51 | 51 |
NodeT() {}
|
| 52 | 52 |
}; |
| 53 |
struct ArcT |
|
| 53 |
struct ArcT |
|
| 54 | 54 |
{
|
| 55 |
int target, source, next_in, next_out; |
|
| 56 |
ArcT() {}
|
|
| 55 |
int target, source, next_in, next_out; |
|
| 56 |
ArcT() {}
|
|
| 57 | 57 |
}; |
| 58 | 58 |
|
| 59 | 59 |
std::vector<NodeT> nodes; |
| 60 | 60 |
std::vector<ArcT> arcs; |
| 61 |
|
|
| 61 |
|
|
| 62 | 62 |
public: |
| 63 | 63 |
|
| 64 | 64 |
typedef SmartDigraphBase Graph; |
| 65 | 65 |
|
| 66 | 66 |
class Node; |
| 67 | 67 |
class Arc; |
| 68 | 68 |
|
| 69 | 69 |
public: |
| 70 | 70 |
|
| 71 | 71 |
SmartDigraphBase() : nodes(), arcs() { }
|
| 72 |
SmartDigraphBase(const SmartDigraphBase &_g) |
|
| 72 |
SmartDigraphBase(const SmartDigraphBase &_g) |
|
| 73 | 73 |
: nodes(_g.nodes), arcs(_g.arcs) { }
|
| 74 |
|
|
| 74 |
|
|
| 75 | 75 |
typedef True NodeNumTag; |
| 76 | 76 |
typedef True EdgeNumTag; |
| 77 | 77 |
|
| 78 | 78 |
int nodeNum() const { return nodes.size(); }
|
| 79 | 79 |
int arcNum() const { return arcs.size(); }
|
| 80 | 80 |
|
| 81 | 81 |
int maxNodeId() const { return nodes.size()-1; }
|
| 82 | 82 |
int maxArcId() const { return arcs.size()-1; }
|
| 83 | 83 |
|
| 84 | 84 |
Node addNode() {
|
| 85 |
int n = nodes.size(); |
|
| 85 |
int n = nodes.size(); |
|
| 86 | 86 |
nodes.push_back(NodeT()); |
| 87 | 87 |
nodes[n].first_in = -1; |
| 88 | 88 |
nodes[n].first_out = -1; |
| 89 | 89 |
return Node(n); |
| 90 | 90 |
} |
| 91 |
|
|
| 91 |
|
|
| 92 | 92 |
Arc addArc(Node u, Node v) {
|
| 93 |
int n = arcs.size(); |
|
| 93 |
int n = arcs.size(); |
|
| 94 | 94 |
arcs.push_back(ArcT()); |
| 95 |
arcs[n].source = u._id; |
|
| 95 |
arcs[n].source = u._id; |
|
| 96 | 96 |
arcs[n].target = v._id; |
| 97 | 97 |
arcs[n].next_out = nodes[u._id].first_out; |
| 98 | 98 |
arcs[n].next_in = nodes[v._id].first_in; |
| 99 | 99 |
nodes[u._id].first_out = nodes[v._id].first_in = n; |
| 100 | 100 |
|
| 101 | 101 |
return Arc(n); |
| 102 | 102 |
} |
| 103 | 103 |
|
| 104 | 104 |
void clear() {
|
| 105 | 105 |
arcs.clear(); |
| 106 | 106 |
nodes.clear(); |
| 107 | 107 |
} |
| 108 | 108 |
|
| 109 | 109 |
Node source(Arc a) const { return Node(arcs[a._id].source); }
|
| 110 | 110 |
Node target(Arc a) const { return Node(arcs[a._id].target); }
|
| 111 | 111 |
|
| 112 | 112 |
static int id(Node v) { return v._id; }
|
| 113 | 113 |
static int id(Arc a) { return a._id; }
|
| 114 | 114 |
|
| 115 | 115 |
static Node nodeFromId(int id) { return Node(id);}
|
| 116 | 116 |
static Arc arcFromId(int id) { return Arc(id);}
|
| 117 | 117 |
|
| 118 |
bool valid(Node n) const {
|
|
| 119 |
return n._id >= 0 && n._id < static_cast<int>(nodes.size()); |
|
| 118 |
bool valid(Node n) const {
|
|
| 119 |
return n._id >= 0 && n._id < static_cast<int>(nodes.size()); |
|
| 120 | 120 |
} |
| 121 |
bool valid(Arc a) const {
|
|
| 122 |
return a._id >= 0 && a._id < static_cast<int>(arcs.size()); |
|
| 121 |
bool valid(Arc a) const {
|
|
| 122 |
return a._id >= 0 && a._id < static_cast<int>(arcs.size()); |
|
| 123 | 123 |
} |
| 124 | 124 |
|
| 125 | 125 |
class Node {
|
| 126 | 126 |
friend class SmartDigraphBase; |
| 127 | 127 |
friend class SmartDigraph; |
| 128 | 128 |
|
| 129 | 129 |
protected: |
| 130 | 130 |
int _id; |
| 131 | 131 |
explicit Node(int id) : _id(id) {}
|
| 132 | 132 |
public: |
| 133 | 133 |
Node() {}
|
| 134 | 134 |
Node (Invalid) : _id(-1) {}
|
| 135 | 135 |
bool operator==(const Node i) const {return _id == i._id;}
|
| 136 | 136 |
bool operator!=(const Node i) const {return _id != i._id;}
|
| 137 | 137 |
bool operator<(const Node i) const {return _id < i._id;}
|
| 138 | 138 |
}; |
| 139 |
|
|
| 139 |
|
|
| 140 | 140 |
|
| 141 | 141 |
class Arc {
|
| 142 | 142 |
friend class SmartDigraphBase; |
| 143 | 143 |
friend class SmartDigraph; |
| 144 | 144 |
|
| 145 | 145 |
protected: |
| 146 | 146 |
int _id; |
| 147 | 147 |
explicit Arc(int id) : _id(id) {}
|
| 148 | 148 |
public: |
| 149 | 149 |
Arc() { }
|
| 150 | 150 |
Arc (Invalid) : _id(-1) {}
|
| 151 | 151 |
bool operator==(const Arc i) const {return _id == i._id;}
|
| 152 | 152 |
bool operator!=(const Arc i) const {return _id != i._id;}
|
| 153 | 153 |
bool operator<(const Arc i) const {return _id < i._id;}
|
| 154 | 154 |
}; |
| 155 | 155 |
|
| ... | ... |
@@ -167,33 +167,33 @@ |
| 167 | 167 |
|
| 168 | 168 |
static void next(Arc& arc) {
|
| 169 | 169 |
--arc._id; |
| 170 | 170 |
} |
| 171 | 171 |
|
| 172 | 172 |
void firstOut(Arc& arc, const Node& node) const {
|
| 173 | 173 |
arc._id = nodes[node._id].first_out; |
| 174 | 174 |
} |
| 175 | 175 |
|
| 176 | 176 |
void nextOut(Arc& arc) const {
|
| 177 | 177 |
arc._id = arcs[arc._id].next_out; |
| 178 | 178 |
} |
| 179 | 179 |
|
| 180 | 180 |
void firstIn(Arc& arc, const Node& node) const {
|
| 181 | 181 |
arc._id = nodes[node._id].first_in; |
| 182 | 182 |
} |
| 183 |
|
|
| 183 |
|
|
| 184 | 184 |
void nextIn(Arc& arc) const {
|
| 185 | 185 |
arc._id = arcs[arc._id].next_in; |
| 186 | 186 |
} |
| 187 | 187 |
|
| 188 | 188 |
}; |
| 189 | 189 |
|
| 190 | 190 |
typedef DigraphExtender<SmartDigraphBase> ExtendedSmartDigraphBase; |
| 191 | 191 |
|
| 192 | 192 |
///\ingroup graphs |
| 193 | 193 |
/// |
| 194 | 194 |
///\brief A smart directed graph class. |
| 195 | 195 |
/// |
| 196 | 196 |
///This is a simple and fast digraph implementation. |
| 197 | 197 |
///It is also quite memory efficient, but at the price |
| 198 | 198 |
///that <b> it does support only limited (only stack-like) |
| 199 | 199 |
///node and arc deletions</b>. |
| ... | ... |
@@ -209,243 +209,243 @@ |
| 209 | 209 |
|
| 210 | 210 |
private: |
| 211 | 211 |
|
| 212 | 212 |
///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead. |
| 213 | 213 |
|
| 214 | 214 |
///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead. |
| 215 | 215 |
/// |
| 216 | 216 |
SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
|
| 217 | 217 |
///\brief Assignment of SmartDigraph to another one is \e not allowed. |
| 218 | 218 |
///Use DigraphCopy() instead. |
| 219 | 219 |
|
| 220 | 220 |
///Assignment of SmartDigraph to another one is \e not allowed. |
| 221 | 221 |
///Use DigraphCopy() instead. |
| 222 | 222 |
void operator=(const SmartDigraph &) {}
|
| 223 | 223 |
|
| 224 | 224 |
public: |
| 225 |
|
|
| 225 |
|
|
| 226 | 226 |
/// Constructor |
| 227 |
|
|
| 227 |
|
|
| 228 | 228 |
/// Constructor. |
| 229 | 229 |
/// |
| 230 | 230 |
SmartDigraph() {};
|
| 231 |
|
|
| 231 |
|
|
| 232 | 232 |
///Add a new node to the digraph. |
| 233 |
|
|
| 233 |
|
|
| 234 | 234 |
/// \return the new node. |
| 235 | 235 |
/// |
| 236 | 236 |
Node addNode() { return Parent::addNode(); }
|
| 237 |
|
|
| 237 |
|
|
| 238 | 238 |
///Add a new arc to the digraph. |
| 239 |
|
|
| 239 |
|
|
| 240 | 240 |
///Add a new arc to the digraph with source node \c s |
| 241 | 241 |
///and target node \c t. |
| 242 | 242 |
///\return the new arc. |
| 243 |
Arc addArc(const Node& s, const Node& t) {
|
|
| 244 |
return Parent::addArc(s, t); |
|
| 243 |
Arc addArc(const Node& s, const Node& t) {
|
|
| 244 |
return Parent::addArc(s, t); |
|
| 245 | 245 |
} |
| 246 | 246 |
|
| 247 | 247 |
/// \brief Using this it is possible to avoid the superfluous memory |
| 248 | 248 |
/// allocation. |
| 249 | 249 |
|
| 250 | 250 |
/// Using this it is possible to avoid the superfluous memory |
| 251 | 251 |
/// allocation: if you know that the digraph you want to build will |
| 252 | 252 |
/// be very large (e.g. it will contain millions of nodes and/or arcs) |
| 253 | 253 |
/// then it is worth reserving space for this amount before starting |
| 254 | 254 |
/// to build the digraph. |
| 255 | 255 |
/// \sa reserveArc |
| 256 | 256 |
void reserveNode(int n) { nodes.reserve(n); };
|
| 257 | 257 |
|
| 258 | 258 |
/// \brief Using this it is possible to avoid the superfluous memory |
| 259 | 259 |
/// allocation. |
| 260 | 260 |
|
| 261 | 261 |
/// Using this it is possible to avoid the superfluous memory |
| 262 | 262 |
/// allocation: if you know that the digraph you want to build will |
| 263 | 263 |
/// be very large (e.g. it will contain millions of nodes and/or arcs) |
| 264 | 264 |
/// then it is worth reserving space for this amount before starting |
| 265 | 265 |
/// to build the digraph. |
| 266 | 266 |
/// \sa reserveNode |
| 267 | 267 |
void reserveArc(int m) { arcs.reserve(m); };
|
| 268 | 268 |
|
| 269 | 269 |
/// \brief Node validity check |
| 270 | 270 |
/// |
| 271 | 271 |
/// This function gives back true if the given node is valid, |
| 272 |
/// ie. it is a real node of the graph. |
|
| 272 |
/// ie. it is a real node of the graph. |
|
| 273 | 273 |
/// |
| 274 | 274 |
/// \warning A removed node (using Snapshot) could become valid again |
| 275 | 275 |
/// when new nodes are added to the graph. |
| 276 | 276 |
bool valid(Node n) const { return Parent::valid(n); }
|
| 277 | 277 |
|
| 278 | 278 |
/// \brief Arc validity check |
| 279 | 279 |
/// |
| 280 | 280 |
/// This function gives back true if the given arc is valid, |
| 281 |
/// ie. it is a real arc of the graph. |
|
| 281 |
/// ie. it is a real arc of the graph. |
|
| 282 | 282 |
/// |
| 283 | 283 |
/// \warning A removed arc (using Snapshot) could become valid again |
| 284 | 284 |
/// when new arcs are added to the graph. |
| 285 | 285 |
bool valid(Arc a) const { return Parent::valid(a); }
|
| 286 | 286 |
|
| 287 | 287 |
///Clear the digraph. |
| 288 |
|
|
| 288 |
|
|
| 289 | 289 |
///Erase all the nodes and arcs from the digraph. |
| 290 | 290 |
/// |
| 291 | 291 |
void clear() {
|
| 292 | 292 |
Parent::clear(); |
| 293 | 293 |
} |
| 294 | 294 |
|
| 295 | 295 |
///Split a node. |
| 296 |
|
|
| 296 |
|
|
| 297 | 297 |
///This function splits a node. First a new node is added to the digraph, |
| 298 | 298 |
///then the source of each outgoing arc of \c n is moved to this new node. |
| 299 | 299 |
///If \c connect is \c true (this is the default value), then a new arc |
| 300 | 300 |
///from \c n to the newly created node is also added. |
| 301 | 301 |
///\return The newly created node. |
| 302 | 302 |
/// |
| 303 | 303 |
///\note The <tt>Arc</tt>s |
| 304 | 304 |
///referencing a moved arc remain |
| 305 | 305 |
///valid. However <tt>InArc</tt>'s and <tt>OutArc</tt>'s |
| 306 | 306 |
///may be invalidated. |
| 307 | 307 |
///\warning This functionality cannot be used together with the Snapshot |
| 308 | 308 |
///feature. |
| 309 | 309 |
///\todo It could be implemented in a bit faster way. |
| 310 | 310 |
Node split(Node n, bool connect = true) |
| 311 | 311 |
{
|
| 312 | 312 |
Node b = addNode(); |
| 313 | 313 |
nodes[b._id].first_out=nodes[n._id].first_out; |
| 314 | 314 |
nodes[n._id].first_out=-1; |
| 315 | 315 |
for(int i=nodes[b._id].first_out;i!=-1;i++) arcs[i].source=b._id; |
| 316 | 316 |
if(connect) addArc(n,b); |
| 317 | 317 |
return b; |
| 318 | 318 |
} |
| 319 | 319 |
|
| 320 | 320 |
public: |
| 321 |
|
|
| 321 |
|
|
| 322 | 322 |
class Snapshot; |
| 323 | 323 |
|
| 324 | 324 |
protected: |
| 325 | 325 |
|
| 326 | 326 |
void restoreSnapshot(const Snapshot &s) |
| 327 | 327 |
{
|
| 328 | 328 |
while(s.arc_num<arcs.size()) {
|
| 329 | 329 |
Arc arc = arcFromId(arcs.size()-1); |
| 330 |
Parent::notifier(Arc()).erase(arc); |
|
| 331 |
nodes[arcs.back().source].first_out=arcs.back().next_out; |
|
| 332 |
nodes[arcs.back().target].first_in=arcs.back().next_in; |
|
| 333 |
arcs.pop_back(); |
|
| 330 |
Parent::notifier(Arc()).erase(arc); |
|
| 331 |
nodes[arcs.back().source].first_out=arcs.back().next_out; |
|
| 332 |
nodes[arcs.back().target].first_in=arcs.back().next_in; |
|
| 333 |
arcs.pop_back(); |
|
| 334 | 334 |
} |
| 335 | 335 |
while(s.node_num<nodes.size()) {
|
| 336 | 336 |
Node node = nodeFromId(nodes.size()-1); |
| 337 |
Parent::notifier(Node()).erase(node); |
|
| 338 |
nodes.pop_back(); |
|
| 337 |
Parent::notifier(Node()).erase(node); |
|
| 338 |
nodes.pop_back(); |
|
| 339 | 339 |
} |
| 340 |
} |
|
| 340 |
} |
|
| 341 | 341 |
|
| 342 | 342 |
public: |
| 343 | 343 |
|
| 344 | 344 |
///Class to make a snapshot of the digraph and to restrore to it later. |
| 345 | 345 |
|
| 346 | 346 |
///Class to make a snapshot of the digraph and to restrore to it later. |
| 347 | 347 |
/// |
| 348 | 348 |
///The newly added nodes and arcs can be removed using the |
| 349 | 349 |
///restore() function. |
| 350 | 350 |
///\note After you restore a state, you cannot restore |
| 351 | 351 |
///a later state, in other word you cannot add again the arcs deleted |
| 352 | 352 |
///by restore() using another one Snapshot instance. |
| 353 | 353 |
/// |
| 354 | 354 |
///\warning If you do not use correctly the snapshot that can cause |
| 355 | 355 |
///either broken program, invalid state of the digraph, valid but |
| 356 | 356 |
///not the restored digraph or no change. Because the runtime performance |
| 357 | 357 |
///the validity of the snapshot is not stored. |
| 358 |
class Snapshot |
|
| 358 |
class Snapshot |
|
| 359 | 359 |
{
|
| 360 | 360 |
SmartDigraph *_graph; |
| 361 | 361 |
protected: |
| 362 | 362 |
friend class SmartDigraph; |
| 363 | 363 |
unsigned int node_num; |
| 364 | 364 |
unsigned int arc_num; |
| 365 | 365 |
public: |
| 366 | 366 |
///Default constructor. |
| 367 |
|
|
| 367 |
|
|
| 368 | 368 |
///Default constructor. |
| 369 | 369 |
///To actually make a snapshot you must call save(). |
| 370 | 370 |
/// |
| 371 | 371 |
Snapshot() : _graph(0) {}
|
| 372 | 372 |
///Constructor that immediately makes a snapshot |
| 373 |
|
|
| 373 |
|
|
| 374 | 374 |
///This constructor immediately makes a snapshot of the digraph. |
| 375 | 375 |
///\param _g The digraph we make a snapshot of. |
| 376 | 376 |
Snapshot(SmartDigraph &graph) : _graph(&graph) {
|
| 377 |
node_num=_graph->nodes.size(); |
|
| 378 |
arc_num=_graph->arcs.size(); |
|
| 377 |
node_num=_graph->nodes.size(); |
|
| 378 |
arc_num=_graph->arcs.size(); |
|
| 379 | 379 |
} |
| 380 | 380 |
|
| 381 | 381 |
///Make a snapshot. |
| 382 | 382 |
|
| 383 | 383 |
///Make a snapshot of the digraph. |
| 384 | 384 |
/// |
| 385 | 385 |
///This function can be called more than once. In case of a repeated |
| 386 | 386 |
///call, the previous snapshot gets lost. |
| 387 | 387 |
///\param _g The digraph we make the snapshot of. |
| 388 |
void save(SmartDigraph &graph) |
|
| 388 |
void save(SmartDigraph &graph) |
|
| 389 | 389 |
{
|
| 390 |
_graph=&graph; |
|
| 391 |
node_num=_graph->nodes.size(); |
|
| 392 |
|
|
| 390 |
_graph=&graph; |
|
| 391 |
node_num=_graph->nodes.size(); |
|
| 392 |
arc_num=_graph->arcs.size(); |
|
| 393 | 393 |
} |
| 394 | 394 |
|
| 395 | 395 |
///Undo the changes until a snapshot. |
| 396 |
|
|
| 396 |
|
|
| 397 | 397 |
///Undo the changes until a snapshot created by save(). |
| 398 | 398 |
/// |
| 399 | 399 |
///\note After you restored a state, you cannot restore |
| 400 | 400 |
///a later state, in other word you cannot add again the arcs deleted |
| 401 | 401 |
///by restore(). |
| 402 | 402 |
void restore() |
| 403 | 403 |
{
|
| 404 |
|
|
| 404 |
_graph->restoreSnapshot(*this); |
|
| 405 | 405 |
} |
| 406 | 406 |
}; |
| 407 | 407 |
}; |
| 408 | 408 |
|
| 409 | 409 |
|
| 410 | 410 |
class SmartGraphBase {
|
| 411 | 411 |
|
| 412 | 412 |
protected: |
| 413 | 413 |
|
| 414 | 414 |
struct NodeT {
|
| 415 | 415 |
int first_out; |
| 416 | 416 |
}; |
| 417 |
|
|
| 417 |
|
|
| 418 | 418 |
struct ArcT {
|
| 419 | 419 |
int target; |
| 420 | 420 |
int next_out; |
| 421 | 421 |
}; |
| 422 | 422 |
|
| 423 | 423 |
std::vector<NodeT> nodes; |
| 424 | 424 |
std::vector<ArcT> arcs; |
| 425 | 425 |
|
| 426 | 426 |
int first_free_arc; |
| 427 |
|
|
| 427 |
|
|
| 428 | 428 |
public: |
| 429 |
|
|
| 429 |
|
|
| 430 | 430 |
typedef SmartGraphBase Digraph; |
| 431 | 431 |
|
| 432 | 432 |
class Node; |
| 433 | 433 |
class Arc; |
| 434 | 434 |
class Edge; |
| 435 |
|
|
| 435 |
|
|
| 436 | 436 |
class Node {
|
| 437 | 437 |
friend class SmartGraphBase; |
| 438 | 438 |
protected: |
| 439 | 439 |
|
| 440 | 440 |
int _id; |
| 441 | 441 |
explicit Node(int id) { _id = id;}
|
| 442 | 442 |
|
| 443 | 443 |
public: |
| 444 | 444 |
Node() {}
|
| 445 | 445 |
Node (Invalid) { _id = -1; }
|
| 446 | 446 |
bool operator==(const Node& node) const {return _id == node._id;}
|
| 447 | 447 |
bool operator!=(const Node& node) const {return _id != node._id;}
|
| 448 | 448 |
bool operator<(const Node& node) const {return _id < node._id;}
|
| 449 | 449 |
}; |
| 450 | 450 |
|
| 451 | 451 |
class Edge {
|
| ... | ... |
@@ -472,68 +472,68 @@ |
| 472 | 472 |
|
| 473 | 473 |
public: |
| 474 | 474 |
operator Edge() const { return edgeFromId(_id / 2); }
|
| 475 | 475 |
|
| 476 | 476 |
Arc() {}
|
| 477 | 477 |
Arc (Invalid) { _id = -1; }
|
| 478 | 478 |
bool operator==(const Arc& arc) const {return _id == arc._id;}
|
| 479 | 479 |
bool operator!=(const Arc& arc) const {return _id != arc._id;}
|
| 480 | 480 |
bool operator<(const Arc& arc) const {return _id < arc._id;}
|
| 481 | 481 |
}; |
| 482 | 482 |
|
| 483 | 483 |
|
| 484 | 484 |
|
| 485 | 485 |
SmartGraphBase() |
| 486 | 486 |
: nodes(), arcs() {}
|
| 487 | 487 |
|
| 488 |
|
|
| 489 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 488 |
|
|
| 489 |
int maxNodeId() const { return nodes.size()-1; }
|
|
| 490 | 490 |
int maxEdgeId() const { return arcs.size() / 2 - 1; }
|
| 491 | 491 |
int maxArcId() const { return arcs.size()-1; }
|
| 492 | 492 |
|
| 493 | 493 |
Node source(Arc e) const { return Node(arcs[e._id ^ 1].target); }
|
| 494 | 494 |
Node target(Arc e) const { return Node(arcs[e._id].target); }
|
| 495 | 495 |
|
| 496 | 496 |
Node u(Edge e) const { return Node(arcs[2 * e._id].target); }
|
| 497 | 497 |
Node v(Edge e) const { return Node(arcs[2 * e._id + 1].target); }
|
| 498 | 498 |
|
| 499 | 499 |
static bool direction(Arc e) {
|
| 500 | 500 |
return (e._id & 1) == 1; |
| 501 | 501 |
} |
| 502 | 502 |
|
| 503 | 503 |
static Arc direct(Edge e, bool d) {
|
| 504 | 504 |
return Arc(e._id * 2 + (d ? 1 : 0)); |
| 505 | 505 |
} |
| 506 | 506 |
|
| 507 |
void first(Node& node) const {
|
|
| 507 |
void first(Node& node) const {
|
|
| 508 | 508 |
node._id = nodes.size() - 1; |
| 509 | 509 |
} |
| 510 | 510 |
|
| 511 | 511 |
void next(Node& node) const {
|
| 512 | 512 |
--node._id; |
| 513 | 513 |
} |
| 514 | 514 |
|
| 515 |
void first(Arc& arc) const {
|
|
| 515 |
void first(Arc& arc) const {
|
|
| 516 | 516 |
arc._id = arcs.size() - 1; |
| 517 | 517 |
} |
| 518 | 518 |
|
| 519 | 519 |
void next(Arc& arc) const {
|
| 520 | 520 |
--arc._id; |
| 521 | 521 |
} |
| 522 | 522 |
|
| 523 |
void first(Edge& arc) const {
|
|
| 523 |
void first(Edge& arc) const {
|
|
| 524 | 524 |
arc._id = arcs.size() / 2 - 1; |
| 525 | 525 |
} |
| 526 | 526 |
|
| 527 | 527 |
void next(Edge& arc) const {
|
| 528 | 528 |
--arc._id; |
| 529 | 529 |
} |
| 530 | 530 |
|
| 531 | 531 |
void firstOut(Arc &arc, const Node& v) const {
|
| 532 | 532 |
arc._id = nodes[v._id].first_out; |
| 533 | 533 |
} |
| 534 | 534 |
void nextOut(Arc &arc) const {
|
| 535 | 535 |
arc._id = arcs[arc._id].next_out; |
| 536 | 536 |
} |
| 537 | 537 |
|
| 538 | 538 |
void firstIn(Arc &arc, const Node& v) const {
|
| 539 | 539 |
arc._id = ((nodes[v._id].first_out) ^ 1); |
| ... | ... |
@@ -548,270 +548,270 @@ |
| 548 | 548 |
int de = nodes[v._id].first_out; |
| 549 | 549 |
if (de != -1) {
|
| 550 | 550 |
arc._id = de / 2; |
| 551 | 551 |
d = ((de & 1) == 1); |
| 552 | 552 |
} else {
|
| 553 | 553 |
arc._id = -1; |
| 554 | 554 |
d = true; |
| 555 | 555 |
} |
| 556 | 556 |
} |
| 557 | 557 |
void nextInc(Edge &arc, bool& d) const {
|
| 558 | 558 |
int de = (arcs[(arc._id * 2) | (d ? 1 : 0)].next_out); |
| 559 | 559 |
if (de != -1) {
|
| 560 | 560 |
arc._id = de / 2; |
| 561 | 561 |
d = ((de & 1) == 1); |
| 562 | 562 |
} else {
|
| 563 | 563 |
arc._id = -1; |
| 564 |
d = true; |
|
| 564 |
d = true; |
|
| 565 | 565 |
} |
| 566 | 566 |
} |
| 567 |
|
|
| 567 |
|
|
| 568 | 568 |
static int id(Node v) { return v._id; }
|
| 569 | 569 |
static int id(Arc e) { return e._id; }
|
| 570 | 570 |
static int id(Edge e) { return e._id; }
|
| 571 | 571 |
|
| 572 | 572 |
static Node nodeFromId(int id) { return Node(id);}
|
| 573 | 573 |
static Arc arcFromId(int id) { return Arc(id);}
|
| 574 | 574 |
static Edge edgeFromId(int id) { return Edge(id);}
|
| 575 | 575 |
|
| 576 |
bool valid(Node n) const {
|
|
| 577 |
return n._id >= 0 && n._id < static_cast<int>(nodes.size()); |
|
| 576 |
bool valid(Node n) const {
|
|
| 577 |
return n._id >= 0 && n._id < static_cast<int>(nodes.size()); |
|
| 578 | 578 |
} |
| 579 |
bool valid(Arc a) const {
|
|
| 579 |
bool valid(Arc a) const {
|
|
| 580 | 580 |
return a._id >= 0 && a._id < static_cast<int>(arcs.size()); |
| 581 | 581 |
} |
| 582 |
bool valid(Edge e) const {
|
|
| 583 |
return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size()); |
|
| 582 |
bool valid(Edge e) const {
|
|
| 583 |
return e._id >= 0 && 2 * e._id < static_cast<int>(arcs.size()); |
|
| 584 | 584 |
} |
| 585 | 585 |
|
| 586 |
Node addNode() {
|
|
| 586 |
Node addNode() {
|
|
| 587 | 587 |
int n = nodes.size(); |
| 588 | 588 |
nodes.push_back(NodeT()); |
| 589 | 589 |
nodes[n].first_out = -1; |
| 590 |
|
|
| 590 |
|
|
| 591 | 591 |
return Node(n); |
| 592 | 592 |
} |
| 593 |
|
|
| 593 |
|
|
| 594 | 594 |
Edge addEdge(Node u, Node v) {
|
| 595 | 595 |
int n = arcs.size(); |
| 596 | 596 |
arcs.push_back(ArcT()); |
| 597 | 597 |
arcs.push_back(ArcT()); |
| 598 |
|
|
| 598 |
|
|
| 599 | 599 |
arcs[n].target = u._id; |
| 600 | 600 |
arcs[n | 1].target = v._id; |
| 601 | 601 |
|
| 602 | 602 |
arcs[n].next_out = nodes[v._id].first_out; |
| 603 | 603 |
nodes[v._id].first_out = n; |
| 604 | 604 |
|
| 605 |
arcs[n | 1].next_out = nodes[u._id].first_out; |
|
| 605 |
arcs[n | 1].next_out = nodes[u._id].first_out; |
|
| 606 | 606 |
nodes[u._id].first_out = (n | 1); |
| 607 | 607 |
|
| 608 | 608 |
return Edge(n / 2); |
| 609 | 609 |
} |
| 610 |
|
|
| 610 |
|
|
| 611 | 611 |
void clear() {
|
| 612 | 612 |
arcs.clear(); |
| 613 | 613 |
nodes.clear(); |
| 614 | 614 |
} |
| 615 | 615 |
|
| 616 | 616 |
}; |
| 617 | 617 |
|
| 618 | 618 |
typedef GraphExtender<SmartGraphBase> ExtendedSmartGraphBase; |
| 619 | 619 |
|
| 620 | 620 |
/// \ingroup graphs |
| 621 | 621 |
/// |
| 622 | 622 |
/// \brief A smart undirected graph class. |
| 623 | 623 |
/// |
| 624 | 624 |
/// This is a simple and fast graph implementation. |
| 625 | 625 |
/// It is also quite memory efficient, but at the price |
| 626 | 626 |
/// that <b> it does support only limited (only stack-like) |
| 627 | 627 |
/// node and arc deletions</b>. |
| 628 |
/// Except from this it conforms to |
|
| 628 |
/// Except from this it conforms to |
|
| 629 | 629 |
/// the \ref concepts::Graph "Graph concept". |
| 630 | 630 |
/// |
| 631 | 631 |
/// It also has an |
| 632 | 632 |
/// important extra feature that |
| 633 | 633 |
/// its maps are real \ref concepts::ReferenceMap "reference map"s. |
| 634 | 634 |
/// |
| 635 | 635 |
/// \sa concepts::Graph. |
| 636 | 636 |
/// |
| 637 | 637 |
class SmartGraph : public ExtendedSmartGraphBase {
|
| 638 | 638 |
private: |
| 639 | 639 |
|
| 640 | 640 |
///SmartGraph is \e not copy constructible. Use GraphCopy() instead. |
| 641 | 641 |
|
| 642 | 642 |
///SmartGraph is \e not copy constructible. Use GraphCopy() instead. |
| 643 | 643 |
/// |
| 644 | 644 |
SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
|
| 645 | 645 |
|
| 646 | 646 |
///\brief Assignment of SmartGraph to another one is \e not allowed. |
| 647 | 647 |
///Use GraphCopy() instead. |
| 648 | 648 |
|
| 649 | 649 |
///Assignment of SmartGraph to another one is \e not allowed. |
| 650 | 650 |
///Use GraphCopy() instead. |
| 651 | 651 |
void operator=(const SmartGraph &) {}
|
| 652 | 652 |
|
| 653 | 653 |
public: |
| 654 | 654 |
|
| 655 | 655 |
typedef ExtendedSmartGraphBase Parent; |
| 656 | 656 |
|
| 657 | 657 |
/// Constructor |
| 658 |
|
|
| 658 |
|
|
| 659 | 659 |
/// Constructor. |
| 660 | 660 |
/// |
| 661 | 661 |
SmartGraph() {}
|
| 662 | 662 |
|
| 663 | 663 |
///Add a new node to the graph. |
| 664 |
|
|
| 664 |
|
|
| 665 | 665 |
/// \return the new node. |
| 666 | 666 |
/// |
| 667 | 667 |
Node addNode() { return Parent::addNode(); }
|
| 668 |
|
|
| 668 |
|
|
| 669 | 669 |
///Add a new edge to the graph. |
| 670 |
|
|
| 670 |
|
|
| 671 | 671 |
///Add a new edge to the graph with node \c s |
| 672 | 672 |
///and \c t. |
| 673 | 673 |
///\return the new edge. |
| 674 |
Edge addEdge(const Node& s, const Node& t) {
|
|
| 675 |
return Parent::addEdge(s, t); |
|
| 674 |
Edge addEdge(const Node& s, const Node& t) {
|
|
| 675 |
return Parent::addEdge(s, t); |
|
| 676 | 676 |
} |
| 677 | 677 |
|
| 678 | 678 |
/// \brief Node validity check |
| 679 | 679 |
/// |
| 680 | 680 |
/// This function gives back true if the given node is valid, |
| 681 |
/// ie. it is a real node of the graph. |
|
| 681 |
/// ie. it is a real node of the graph. |
|
| 682 | 682 |
/// |
| 683 | 683 |
/// \warning A removed node (using Snapshot) could become valid again |
| 684 | 684 |
/// when new nodes are added to the graph. |
| 685 | 685 |
bool valid(Node n) const { return Parent::valid(n); }
|
| 686 | 686 |
|
| 687 | 687 |
/// \brief Arc validity check |
| 688 | 688 |
/// |
| 689 | 689 |
/// This function gives back true if the given arc is valid, |
| 690 |
/// ie. it is a real arc of the graph. |
|
| 690 |
/// ie. it is a real arc of the graph. |
|
| 691 | 691 |
/// |
| 692 | 692 |
/// \warning A removed arc (using Snapshot) could become valid again |
| 693 | 693 |
/// when new edges are added to the graph. |
| 694 | 694 |
bool valid(Arc a) const { return Parent::valid(a); }
|
| 695 | 695 |
|
| 696 | 696 |
/// \brief Edge validity check |
| 697 | 697 |
/// |
| 698 | 698 |
/// This function gives back true if the given edge is valid, |
| 699 |
/// ie. it is a real edge of the graph. |
|
| 699 |
/// ie. it is a real edge of the graph. |
|
| 700 | 700 |
/// |
| 701 | 701 |
/// \warning A removed edge (using Snapshot) could become valid again |
| 702 | 702 |
/// when new edges are added to the graph. |
| 703 | 703 |
bool valid(Edge e) const { return Parent::valid(e); }
|
| 704 | 704 |
|
| 705 | 705 |
///Clear the graph. |
| 706 |
|
|
| 706 |
|
|
| 707 | 707 |
///Erase all the nodes and edges from the graph. |
| 708 | 708 |
/// |
| 709 | 709 |
void clear() {
|
| 710 | 710 |
Parent::clear(); |
| 711 | 711 |
} |
| 712 | 712 |
|
| 713 | 713 |
public: |
| 714 |
|
|
| 714 |
|
|
| 715 | 715 |
class Snapshot; |
| 716 | 716 |
|
| 717 | 717 |
protected: |
| 718 | 718 |
|
| 719 | 719 |
void saveSnapshot(Snapshot &s) |
| 720 | 720 |
{
|
| 721 | 721 |
s._graph = this; |
| 722 | 722 |
s.node_num = nodes.size(); |
| 723 | 723 |
s.arc_num = arcs.size(); |
| 724 | 724 |
} |
| 725 | 725 |
|
| 726 | 726 |
void restoreSnapshot(const Snapshot &s) |
| 727 | 727 |
{
|
| 728 | 728 |
while(s.arc_num<arcs.size()) {
|
| 729 | 729 |
int n=arcs.size()-1; |
| 730 | 730 |
Edge arc=edgeFromId(n/2); |
| 731 |
|
|
| 731 |
Parent::notifier(Edge()).erase(arc); |
|
| 732 | 732 |
std::vector<Arc> dir; |
| 733 | 733 |
dir.push_back(arcFromId(n)); |
| 734 | 734 |
dir.push_back(arcFromId(n-1)); |
| 735 |
Parent::notifier(Arc()).erase(dir); |
|
| 736 |
nodes[arcs[n].target].first_out=arcs[n].next_out; |
|
| 737 |
nodes[arcs[n-1].target].first_out=arcs[n-1].next_out; |
|
| 738 |
arcs.pop_back(); |
|
| 739 |
|
|
| 735 |
Parent::notifier(Arc()).erase(dir); |
|
| 736 |
nodes[arcs[n].target].first_out=arcs[n].next_out; |
|
| 737 |
nodes[arcs[n-1].target].first_out=arcs[n-1].next_out; |
|
| 738 |
arcs.pop_back(); |
|
| 739 |
arcs.pop_back(); |
|
| 740 | 740 |
} |
| 741 | 741 |
while(s.node_num<nodes.size()) {
|
| 742 | 742 |
int n=nodes.size()-1; |
| 743 | 743 |
Node node = nodeFromId(n); |
| 744 |
Parent::notifier(Node()).erase(node); |
|
| 745 |
nodes.pop_back(); |
|
| 744 |
Parent::notifier(Node()).erase(node); |
|
| 745 |
nodes.pop_back(); |
|
| 746 | 746 |
} |
| 747 |
} |
|
| 747 |
} |
|
| 748 | 748 |
|
| 749 | 749 |
public: |
| 750 | 750 |
|
| 751 | 751 |
///Class to make a snapshot of the digraph and to restrore to it later. |
| 752 | 752 |
|
| 753 | 753 |
///Class to make a snapshot of the digraph and to restrore to it later. |
| 754 | 754 |
/// |
| 755 | 755 |
///The newly added nodes and arcs can be removed using the |
| 756 | 756 |
///restore() function. |
| 757 | 757 |
/// |
| 758 | 758 |
///\note After you restore a state, you cannot restore |
| 759 | 759 |
///a later state, in other word you cannot add again the arcs deleted |
| 760 | 760 |
///by restore() using another one Snapshot instance. |
| 761 | 761 |
/// |
| 762 | 762 |
///\warning If you do not use correctly the snapshot that can cause |
| 763 | 763 |
///either broken program, invalid state of the digraph, valid but |
| 764 | 764 |
///not the restored digraph or no change. Because the runtime performance |
| 765 | 765 |
///the validity of the snapshot is not stored. |
| 766 |
class Snapshot |
|
| 766 |
class Snapshot |
|
| 767 | 767 |
{
|
| 768 | 768 |
SmartGraph *_graph; |
| 769 | 769 |
protected: |
| 770 | 770 |
friend class SmartGraph; |
| 771 | 771 |
unsigned int node_num; |
| 772 | 772 |
unsigned int arc_num; |
| 773 | 773 |
public: |
| 774 | 774 |
///Default constructor. |
| 775 |
|
|
| 775 |
|
|
| 776 | 776 |
///Default constructor. |
| 777 | 777 |
///To actually make a snapshot you must call save(). |
| 778 | 778 |
/// |
| 779 | 779 |
Snapshot() : _graph(0) {}
|
| 780 | 780 |
///Constructor that immediately makes a snapshot |
| 781 |
|
|
| 781 |
|
|
| 782 | 782 |
///This constructor immediately makes a snapshot of the digraph. |
| 783 | 783 |
///\param g The digraph we make a snapshot of. |
| 784 | 784 |
Snapshot(SmartGraph &graph) {
|
| 785 | 785 |
graph.saveSnapshot(*this); |
| 786 | 786 |
} |
| 787 | 787 |
|
| 788 | 788 |
///Make a snapshot. |
| 789 | 789 |
|
| 790 | 790 |
///Make a snapshot of the graph. |
| 791 | 791 |
/// |
| 792 | 792 |
///This function can be called more than once. In case of a repeated |
| 793 | 793 |
///call, the previous snapshot gets lost. |
| 794 | 794 |
///\param g The digraph we make the snapshot of. |
| 795 |
void save(SmartGraph &graph) |
|
| 795 |
void save(SmartGraph &graph) |
|
| 796 | 796 |
{
|
| 797 | 797 |
graph.saveSnapshot(*this); |
| 798 | 798 |
} |
| 799 | 799 |
|
| 800 | 800 |
///Undo the changes until a snapshot. |
| 801 |
|
|
| 801 |
|
|
| 802 | 802 |
///Undo the changes until a snapshot created by save(). |
| 803 | 803 |
/// |
| 804 | 804 |
///\note After you restored a state, you cannot restore |
| 805 | 805 |
///a later state, in other word you cannot add again the arcs deleted |
| 806 | 806 |
///by restore(). |
| 807 | 807 |
void restore() |
| 808 | 808 |
{
|
| 809 | 809 |
_graph->restoreSnapshot(*this); |
| 810 | 810 |
} |
| 811 | 811 |
}; |
| 812 | 812 |
}; |
| 813 |
|
|
| 813 |
|
|
| 814 | 814 |
} //namespace lemon |
| 815 | 815 |
|
| 816 | 816 |
|
| 817 | 817 |
#endif //LEMON_SMART_GRAPH_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TIME_MEASURE_H |
| ... | ... |
@@ -51,84 +51,84 @@ |
| 51 | 51 |
/// - a user cpu time of children |
| 52 | 52 |
/// - a system cpu time of children |
| 53 | 53 |
/// |
| 54 | 54 |
/// TimeStamp's can be added to or substracted from each other and |
| 55 | 55 |
/// they can be pushed to a stream. |
| 56 | 56 |
/// |
| 57 | 57 |
/// In most cases, perhaps the \ref Timer or the \ref TimeReport |
| 58 | 58 |
/// class is what you want to use instead. |
| 59 | 59 |
|
| 60 | 60 |
class TimeStamp |
| 61 | 61 |
{
|
| 62 | 62 |
double utime; |
| 63 | 63 |
double stime; |
| 64 | 64 |
double cutime; |
| 65 | 65 |
double cstime; |
| 66 | 66 |
double rtime; |
| 67 |
|
|
| 68 |
void _reset() {
|
|
| 67 |
|
|
| 68 |
void _reset() {
|
|
| 69 | 69 |
utime = stime = cutime = cstime = rtime = 0; |
| 70 | 70 |
} |
| 71 | 71 |
|
| 72 | 72 |
public: |
| 73 | 73 |
|
| 74 | 74 |
///Read the current time values of the process |
| 75 | 75 |
void stamp() |
| 76 | 76 |
{
|
| 77 | 77 |
#ifndef WIN32 |
| 78 | 78 |
timeval tv; |
| 79 | 79 |
gettimeofday(&tv, 0); |
| 80 | 80 |
rtime=tv.tv_sec+double(tv.tv_usec)/1e6; |
| 81 | 81 |
|
| 82 | 82 |
tms ts; |
| 83 | 83 |
double tck=sysconf(_SC_CLK_TCK); |
| 84 | 84 |
times(&ts); |
| 85 | 85 |
utime=ts.tms_utime/tck; |
| 86 | 86 |
stime=ts.tms_stime/tck; |
| 87 | 87 |
cutime=ts.tms_cutime/tck; |
| 88 | 88 |
cstime=ts.tms_cstime/tck; |
| 89 | 89 |
#else |
| 90 | 90 |
static const double ch = 4294967296.0e-7; |
| 91 | 91 |
static const double cl = 1.0e-7; |
| 92 | 92 |
|
| 93 | 93 |
FILETIME system; |
| 94 | 94 |
GetSystemTimeAsFileTime(&system); |
| 95 | 95 |
rtime = ch * system.dwHighDateTime + cl * system.dwLowDateTime; |
| 96 | 96 |
|
| 97 | 97 |
FILETIME create, exit, kernel, user; |
| 98 | 98 |
if (GetProcessTimes(GetCurrentProcess(),&create, &exit, &kernel, &user)) {
|
| 99 |
utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime; |
|
| 100 |
stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime; |
|
| 101 |
cutime = 0; |
|
| 102 |
cstime = 0; |
|
| 99 |
utime = ch * user.dwHighDateTime + cl * user.dwLowDateTime; |
|
| 100 |
stime = ch * kernel.dwHighDateTime + cl * kernel.dwLowDateTime; |
|
| 101 |
cutime = 0; |
|
| 102 |
cstime = 0; |
|
| 103 | 103 |
} else {
|
| 104 |
rtime = 0; |
|
| 105 |
utime = 0; |
|
| 106 |
stime = 0; |
|
| 107 |
cutime = 0; |
|
| 108 |
|
|
| 104 |
rtime = 0; |
|
| 105 |
utime = 0; |
|
| 106 |
stime = 0; |
|
| 107 |
cutime = 0; |
|
| 108 |
cstime = 0; |
|
| 109 | 109 |
} |
| 110 |
#endif |
|
| 110 |
#endif |
|
| 111 | 111 |
} |
| 112 |
|
|
| 112 |
|
|
| 113 | 113 |
/// Constructor initializing with zero |
| 114 | 114 |
TimeStamp() |
| 115 | 115 |
{ _reset(); }
|
| 116 | 116 |
///Constructor initializing with the current time values of the process |
| 117 | 117 |
TimeStamp(void *) { stamp();}
|
| 118 |
|
|
| 118 |
|
|
| 119 | 119 |
///Set every time value to zero |
| 120 | 120 |
TimeStamp &reset() {_reset();return *this;}
|
| 121 | 121 |
|
| 122 | 122 |
///\e |
| 123 | 123 |
TimeStamp &operator+=(const TimeStamp &b) |
| 124 | 124 |
{
|
| 125 | 125 |
utime+=b.utime; |
| 126 | 126 |
stime+=b.stime; |
| 127 | 127 |
cutime+=b.cutime; |
| 128 | 128 |
cstime+=b.cstime; |
| 129 | 129 |
rtime+=b.rtime; |
| 130 | 130 |
return *this; |
| 131 | 131 |
} |
| 132 | 132 |
///\e |
| 133 | 133 |
TimeStamp operator+(const TimeStamp &b) const |
| 134 | 134 |
{
|
| ... | ... |
@@ -177,70 +177,70 @@ |
| 177 | 177 |
cstime/=b; |
| 178 | 178 |
rtime/=b; |
| 179 | 179 |
return *this; |
| 180 | 180 |
} |
| 181 | 181 |
///\e |
| 182 | 182 |
TimeStamp operator/(double b) const |
| 183 | 183 |
{
|
| 184 | 184 |
TimeStamp t(*this); |
| 185 | 185 |
return t/=b; |
| 186 | 186 |
} |
| 187 | 187 |
///The time ellapsed since the last call of stamp() |
| 188 | 188 |
TimeStamp ellapsed() const |
| 189 | 189 |
{
|
| 190 | 190 |
TimeStamp t(NULL); |
| 191 | 191 |
return t-*this; |
| 192 | 192 |
} |
| 193 |
|
|
| 193 |
|
|
| 194 | 194 |
friend std::ostream& operator<<(std::ostream& os,const TimeStamp &t); |
| 195 |
|
|
| 195 |
|
|
| 196 | 196 |
///Gives back the user time of the process |
| 197 | 197 |
double userTime() const |
| 198 | 198 |
{
|
| 199 | 199 |
return utime; |
| 200 | 200 |
} |
| 201 | 201 |
///Gives back the system time of the process |
| 202 | 202 |
double systemTime() const |
| 203 | 203 |
{
|
| 204 | 204 |
return stime; |
| 205 | 205 |
} |
| 206 | 206 |
///Gives back the user time of the process' children |
| 207 | 207 |
|
| 208 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 208 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 209 | 209 |
/// |
| 210 | 210 |
double cUserTime() const |
| 211 | 211 |
{
|
| 212 | 212 |
return cutime; |
| 213 | 213 |
} |
| 214 | 214 |
///Gives back the user time of the process' children |
| 215 | 215 |
|
| 216 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 216 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 217 | 217 |
/// |
| 218 | 218 |
double cSystemTime() const |
| 219 | 219 |
{
|
| 220 | 220 |
return cstime; |
| 221 | 221 |
} |
| 222 | 222 |
///Gives back the real time |
| 223 | 223 |
double realTime() const {return rtime;}
|
| 224 | 224 |
}; |
| 225 | 225 |
|
| 226 |
TimeStamp operator*(double b,const TimeStamp &t) |
|
| 226 |
TimeStamp operator*(double b,const TimeStamp &t) |
|
| 227 | 227 |
{
|
| 228 | 228 |
return t*b; |
| 229 | 229 |
} |
| 230 |
|
|
| 230 |
|
|
| 231 | 231 |
///Prints the time counters |
| 232 | 232 |
|
| 233 | 233 |
///Prints the time counters in the following form: |
| 234 | 234 |
/// |
| 235 | 235 |
/// <tt>u: XX.XXs s: XX.XXs cu: XX.XXs cs: XX.XXs real: XX.XXs</tt> |
| 236 | 236 |
/// |
| 237 | 237 |
/// where the values are the |
| 238 | 238 |
/// \li \c u: user cpu time, |
| 239 | 239 |
/// \li \c s: system cpu time, |
| 240 | 240 |
/// \li \c cu: user cpu time of children, |
| 241 | 241 |
/// \li \c cs: system cpu time of children, |
| 242 | 242 |
/// \li \c real: real time. |
| 243 | 243 |
/// \relates TimeStamp |
| 244 | 244 |
/// \note On <tt>WIN32</tt> platform the cummulative values are not |
| 245 | 245 |
/// calculated. |
| 246 | 246 |
inline std::ostream& operator<<(std::ostream& os,const TimeStamp &t) |
| ... | ... |
@@ -286,175 +286,175 @@ |
| 286 | 286 |
///the time counters have a certain (10ms on a typical Linux system) |
| 287 | 287 |
///granularity. |
| 288 | 288 |
///Therefore this tool is not appropriate to measure very short times. |
| 289 | 289 |
///Also, if you start and stop the timer very frequently, it could lead to |
| 290 | 290 |
///distorted results. |
| 291 | 291 |
/// |
| 292 | 292 |
///\note If you want to measure the running time of the execution of a certain |
| 293 | 293 |
///function, consider the usage of \ref TimeReport instead. |
| 294 | 294 |
/// |
| 295 | 295 |
///\todo This shouldn't be Unix (Linux) specific. |
| 296 | 296 |
///\sa TimeReport |
| 297 | 297 |
class Timer |
| 298 | 298 |
{
|
| 299 | 299 |
int _running; //Timer is running iff _running>0; (_running>=0 always holds) |
| 300 | 300 |
TimeStamp start_time; //This is the relativ start-time if the timer |
| 301 | 301 |
//is _running, the collected _running time otherwise. |
| 302 |
|
|
| 302 |
|
|
| 303 | 303 |
void _reset() {if(_running) start_time.stamp(); else start_time.reset();}
|
| 304 |
|
|
| 305 |
public: |
|
| 304 |
|
|
| 305 |
public: |
|
| 306 | 306 |
///Constructor. |
| 307 | 307 |
|
| 308 | 308 |
///\param run indicates whether or not the timer starts immediately. |
| 309 | 309 |
/// |
| 310 | 310 |
Timer(bool run=true) :_running(run) {_reset();}
|
| 311 | 311 |
|
| 312 | 312 |
///\name Control the state of the timer |
| 313 | 313 |
///Basically a Timer can be either running or stopped, |
| 314 | 314 |
///but it provides a bit finer control on the execution. |
| 315 | 315 |
///The \ref Timer also counts the number of \ref start() |
| 316 | 316 |
///executions, and is stops only after the same amount (or more) |
| 317 | 317 |
///\ref stop() "stop()"s. This can be useful e.g. to compute the running time |
| 318 | 318 |
///of recursive functions. |
| 319 | 319 |
/// |
| 320 | 320 |
|
| 321 | 321 |
///@{
|
| 322 | 322 |
|
| 323 | 323 |
///Reset and stop the time counters |
| 324 | 324 |
|
| 325 | 325 |
///This function resets and stops the time counters |
| 326 | 326 |
///\sa restart() |
| 327 | 327 |
void reset() |
| 328 | 328 |
{
|
| 329 | 329 |
_running=0; |
| 330 | 330 |
_reset(); |
| 331 | 331 |
} |
| 332 | 332 |
|
| 333 | 333 |
///Start the time counters |
| 334 |
|
|
| 334 |
|
|
| 335 | 335 |
///This function starts the time counters. |
| 336 | 336 |
/// |
| 337 | 337 |
///If the timer is started more than ones, it will remain running |
| 338 | 338 |
///until the same amount of \ref stop() is called. |
| 339 | 339 |
///\sa stop() |
| 340 |
void start() |
|
| 340 |
void start() |
|
| 341 | 341 |
{
|
| 342 | 342 |
if(_running) _running++; |
| 343 | 343 |
else {
|
| 344 |
_running=1; |
|
| 345 |
TimeStamp t; |
|
| 346 |
t.stamp(); |
|
| 347 |
start_time=t-start_time; |
|
| 344 |
_running=1; |
|
| 345 |
TimeStamp t; |
|
| 346 |
t.stamp(); |
|
| 347 |
start_time=t-start_time; |
|
| 348 | 348 |
} |
| 349 | 349 |
} |
| 350 | 350 |
|
| 351 |
|
|
| 351 |
|
|
| 352 | 352 |
///Stop the time counters |
| 353 | 353 |
|
| 354 | 354 |
///This function stops the time counters. If start() was executed more than |
| 355 | 355 |
///once, then the same number of stop() execution is necessary the really |
| 356 | 356 |
///stop the timer. |
| 357 |
/// |
|
| 357 |
/// |
|
| 358 | 358 |
///\sa halt() |
| 359 | 359 |
///\sa start() |
| 360 | 360 |
///\sa restart() |
| 361 | 361 |
///\sa reset() |
| 362 | 362 |
|
| 363 |
void stop() |
|
| 363 |
void stop() |
|
| 364 | 364 |
{
|
| 365 | 365 |
if(_running && !--_running) {
|
| 366 |
TimeStamp t; |
|
| 367 |
t.stamp(); |
|
| 368 |
|
|
| 366 |
TimeStamp t; |
|
| 367 |
t.stamp(); |
|
| 368 |
start_time=t-start_time; |
|
| 369 | 369 |
} |
| 370 | 370 |
} |
| 371 | 371 |
|
| 372 | 372 |
///Halt (i.e stop immediately) the time counters |
| 373 | 373 |
|
| 374 | 374 |
///This function stops immediately the time counters, i.e. <tt>t.halt()</tt> |
| 375 | 375 |
///is a faster |
| 376 | 376 |
///equivalent of the following. |
| 377 | 377 |
///\code |
| 378 | 378 |
/// while(t.running()) t.stop() |
| 379 | 379 |
///\endcode |
| 380 | 380 |
/// |
| 381 | 381 |
/// |
| 382 | 382 |
///\sa stop() |
| 383 | 383 |
///\sa restart() |
| 384 | 384 |
///\sa reset() |
| 385 | 385 |
|
| 386 |
void halt() |
|
| 386 |
void halt() |
|
| 387 | 387 |
{
|
| 388 | 388 |
if(_running) {
|
| 389 |
_running=0; |
|
| 390 |
TimeStamp t; |
|
| 391 |
t.stamp(); |
|
| 392 |
start_time=t-start_time; |
|
| 389 |
_running=0; |
|
| 390 |
TimeStamp t; |
|
| 391 |
t.stamp(); |
|
| 392 |
start_time=t-start_time; |
|
| 393 | 393 |
} |
| 394 | 394 |
} |
| 395 | 395 |
|
| 396 | 396 |
///Returns the running state of the timer |
| 397 | 397 |
|
| 398 | 398 |
///This function returns the number of stop() exections that is |
| 399 | 399 |
///necessary to really stop the timer. |
| 400 | 400 |
///For example the timer |
| 401 | 401 |
///is running if and only if the return value is \c true |
| 402 | 402 |
///(i.e. greater than |
| 403 | 403 |
///zero). |
| 404 | 404 |
int running() { return _running; }
|
| 405 |
|
|
| 406 |
|
|
| 405 |
|
|
| 406 |
|
|
| 407 | 407 |
///Restart the time counters |
| 408 | 408 |
|
| 409 | 409 |
///This function is a shorthand for |
| 410 | 410 |
///a reset() and a start() calls. |
| 411 | 411 |
/// |
| 412 |
void restart() |
|
| 412 |
void restart() |
|
| 413 | 413 |
{
|
| 414 | 414 |
reset(); |
| 415 | 415 |
start(); |
| 416 | 416 |
} |
| 417 |
|
|
| 417 |
|
|
| 418 | 418 |
///@} |
| 419 | 419 |
|
| 420 | 420 |
///\name Query Functions for the ellapsed time |
| 421 | 421 |
|
| 422 | 422 |
///@{
|
| 423 | 423 |
|
| 424 | 424 |
///Gives back the ellapsed user time of the process |
| 425 | 425 |
double userTime() const |
| 426 | 426 |
{
|
| 427 | 427 |
return operator TimeStamp().userTime(); |
| 428 | 428 |
} |
| 429 | 429 |
///Gives back the ellapsed system time of the process |
| 430 | 430 |
double systemTime() const |
| 431 | 431 |
{
|
| 432 | 432 |
return operator TimeStamp().systemTime(); |
| 433 | 433 |
} |
| 434 | 434 |
///Gives back the ellapsed user time of the process' children |
| 435 | 435 |
|
| 436 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 436 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 437 | 437 |
/// |
| 438 | 438 |
double cUserTime() const |
| 439 | 439 |
{
|
| 440 | 440 |
return operator TimeStamp().cUserTime(); |
| 441 | 441 |
} |
| 442 | 442 |
///Gives back the ellapsed user time of the process' children |
| 443 | 443 |
|
| 444 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 444 |
///\note On <tt>WIN32</tt> platform this value is not calculated. |
|
| 445 | 445 |
/// |
| 446 | 446 |
double cSystemTime() const |
| 447 | 447 |
{
|
| 448 | 448 |
return operator TimeStamp().cSystemTime(); |
| 449 | 449 |
} |
| 450 | 450 |
///Gives back the ellapsed real time |
| 451 | 451 |
double realTime() const |
| 452 | 452 |
{
|
| 453 | 453 |
return operator TimeStamp().realTime(); |
| 454 | 454 |
} |
| 455 | 455 |
///Computes the ellapsed time |
| 456 | 456 |
|
| 457 | 457 |
///This conversion computes the ellapsed time, therefore you can print |
| 458 | 458 |
///the ellapsed time like this. |
| 459 | 459 |
///\code |
| 460 | 460 |
/// Timer t; |
| ... | ... |
@@ -474,102 +474,102 @@ |
| 474 | 474 |
|
| 475 | 475 |
///Same as \ref Timer but prints a report on destruction. |
| 476 | 476 |
|
| 477 | 477 |
///Same as \ref Timer but prints a report on destruction. |
| 478 | 478 |
///This example shows its usage. |
| 479 | 479 |
///\code |
| 480 | 480 |
/// void myAlg(ListGraph &g,int n) |
| 481 | 481 |
/// {
|
| 482 | 482 |
/// TimeReport tr("Running time of myAlg: ");
|
| 483 | 483 |
/// ... //Here comes the algorithm |
| 484 | 484 |
/// } |
| 485 | 485 |
///\endcode |
| 486 | 486 |
/// |
| 487 | 487 |
///\sa Timer |
| 488 | 488 |
///\sa NoTimeReport |
| 489 | 489 |
///\todo There is no test case for this |
| 490 |
class TimeReport : public Timer |
|
| 490 |
class TimeReport : public Timer |
|
| 491 | 491 |
{
|
| 492 | 492 |
std::string _title; |
| 493 | 493 |
std::ostream &_os; |
| 494 | 494 |
public: |
| 495 | 495 |
///\e |
| 496 | 496 |
|
| 497 | 497 |
///\param title This text will be printed before the ellapsed time. |
| 498 | 498 |
///\param os The stream to print the report to. |
| 499 | 499 |
///\param run Sets whether the timer should start immediately. |
| 500 | 500 |
|
| 501 |
TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true) |
|
| 501 |
TimeReport(std::string title,std::ostream &os=std::cerr,bool run=true) |
|
| 502 | 502 |
: Timer(run), _title(title), _os(os){}
|
| 503 | 503 |
///\e Prints the ellapsed time on destruction. |
| 504 |
~TimeReport() |
|
| 504 |
~TimeReport() |
|
| 505 | 505 |
{
|
| 506 | 506 |
_os << _title << *this << std::endl; |
| 507 | 507 |
} |
| 508 | 508 |
}; |
| 509 |
|
|
| 509 |
|
|
| 510 | 510 |
///'Do nothing' version of \ref TimeReport |
| 511 | 511 |
|
| 512 | 512 |
///\sa TimeReport |
| 513 | 513 |
/// |
| 514 | 514 |
class NoTimeReport |
| 515 | 515 |
{
|
| 516 | 516 |
public: |
| 517 | 517 |
///\e |
| 518 | 518 |
NoTimeReport(std::string,std::ostream &,bool) {}
|
| 519 | 519 |
///\e |
| 520 | 520 |
NoTimeReport(std::string,std::ostream &) {}
|
| 521 | 521 |
///\e |
| 522 | 522 |
NoTimeReport(std::string) {}
|
| 523 | 523 |
///\e Do nothing. |
| 524 | 524 |
~NoTimeReport() {}
|
| 525 | 525 |
|
| 526 | 526 |
operator TimeStamp () const { return TimeStamp(); }
|
| 527 | 527 |
void reset() {}
|
| 528 | 528 |
void start() {}
|
| 529 | 529 |
void stop() {}
|
| 530 |
void halt() {}
|
|
| 530 |
void halt() {}
|
|
| 531 | 531 |
int running() { return 0; }
|
| 532 | 532 |
void restart() {}
|
| 533 | 533 |
double userTime() const { return 0; }
|
| 534 | 534 |
double systemTime() const { return 0; }
|
| 535 | 535 |
double cUserTime() const { return 0; }
|
| 536 | 536 |
double cSystemTime() const { return 0; }
|
| 537 | 537 |
double realTime() const { return 0; }
|
| 538 | 538 |
}; |
| 539 |
|
|
| 539 |
|
|
| 540 | 540 |
///Tool to measure the running time more exactly. |
| 541 |
|
|
| 541 |
|
|
| 542 | 542 |
///This function calls \c f several times and returns the average |
| 543 | 543 |
///running time. The number of the executions will be choosen in such a way |
| 544 | 544 |
///that the full real running time will be roughly between \c min_time |
| 545 | 545 |
///and <tt>2*min_time</tt>. |
| 546 | 546 |
///\param f the function object to be measured. |
| 547 | 547 |
///\param min_time the minimum total running time. |
| 548 | 548 |
///\retval num if it is not \c NULL, then the actual |
| 549 | 549 |
/// number of execution of \c f will be written into <tt>*num</tt>. |
| 550 | 550 |
///\retval full_time if it is not \c NULL, then the actual |
| 551 | 551 |
/// total running time will be written into <tt>*full_time</tt>. |
| 552 | 552 |
///\return The average running time of \c f. |
| 553 |
|
|
| 553 |
|
|
| 554 | 554 |
template<class F> |
| 555 | 555 |
TimeStamp runningTimeTest(F f,double min_time=10,unsigned int *num = NULL, |
| 556 | 556 |
TimeStamp *full_time=NULL) |
| 557 | 557 |
{
|
| 558 | 558 |
TimeStamp full; |
| 559 | 559 |
unsigned int total=0; |
| 560 | 560 |
Timer t; |
| 561 | 561 |
for(unsigned int tn=1;tn <= 1U<<31 && full.realTime()<=min_time; tn*=2) {
|
| 562 | 562 |
for(;total<tn;total++) f(); |
| 563 | 563 |
full=t; |
| 564 | 564 |
} |
| 565 | 565 |
if(num) *num=total; |
| 566 | 566 |
if(full_time) *full_time=full; |
| 567 | 567 |
return full/total; |
| 568 | 568 |
} |
| 569 |
|
|
| 570 |
/// @} |
|
| 569 |
|
|
| 570 |
/// @} |
|
| 571 | 571 |
|
| 572 | 572 |
|
| 573 | 573 |
} //namespace lemon |
| 574 | 574 |
|
| 575 | 575 |
#endif //LEMON_TIME_MEASURE_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TOLERANCE_H |
| 20 | 20 |
#define LEMON_TOLERANCE_H |
| 21 | 21 |
|
| 22 | 22 |
///\ingroup misc |
| 23 | 23 |
///\file |
| 24 | 24 |
///\brief A basic tool to handle the anomalies of calculation with |
| 25 | 25 |
///floating point numbers. |
| 26 | 26 |
/// |
| 27 | 27 |
///\todo It should be in a module like "Basic tools" |
| 28 | 28 |
|
| 29 | 29 |
|
| 30 | 30 |
namespace lemon {
|
| 31 | 31 |
|
| 32 | 32 |
/// \addtogroup misc |
| 33 | 33 |
/// @{
|
| 34 |
|
|
| 34 |
|
|
| 35 | 35 |
///\brief A class to provide a basic way to |
| 36 | 36 |
///handle the comparison of numbers that are obtained |
| 37 | 37 |
///as a result of a probably inexact computation. |
| 38 | 38 |
/// |
| 39 | 39 |
///\ref Tolerance is a class to provide a basic way to |
| 40 | 40 |
///handle the comparison of numbers that are obtained |
| 41 | 41 |
///as a result of a probably inexact computation. |
| 42 | 42 |
/// |
| 43 |
///This is an abstract class, it should be specialized for all |
|
| 44 |
///numerical data types. These specialized classes like |
|
| 43 |
///This is an abstract class, it should be specialized for all |
|
| 44 |
///numerical data types. These specialized classes like |
|
| 45 | 45 |
///Tolerance<double> may offer additional tuning parameters. |
| 46 | 46 |
/// |
| 47 | 47 |
///\sa Tolerance<float> |
| 48 | 48 |
///\sa Tolerance<double> |
| 49 | 49 |
///\sa Tolerance<long double> |
| 50 | 50 |
///\sa Tolerance<int> |
| 51 | 51 |
///\sa Tolerance<long long int> |
| 52 | 52 |
///\sa Tolerance<unsigned int> |
| 53 | 53 |
///\sa Tolerance<unsigned long long int> |
| 54 | 54 |
|
| 55 | 55 |
template<class T> |
| 56 | 56 |
class Tolerance |
| 57 | 57 |
{
|
| 58 | 58 |
public: |
| 59 | 59 |
typedef T Value; |
| 60 | 60 |
|
| ... | ... |
@@ -292,33 +292,33 @@ |
| 292 | 292 |
///Returns \c true if \c a is \e surely strictly less than \c b |
| 293 | 293 |
static bool less(Value a,Value b) { return a<b;}
|
| 294 | 294 |
///Returns \c true if \c a is \e surely different from \c b |
| 295 | 295 |
static bool different(Value a,Value b) { return a!=b; }
|
| 296 | 296 |
///Returns \c true if \c a is \e surely positive |
| 297 | 297 |
static bool positive(Value a) { return 0<a; }
|
| 298 | 298 |
///Returns \c true if \c a is \e surely negative |
| 299 | 299 |
static bool negative(Value) { return false; }
|
| 300 | 300 |
///Returns \c true if \c a is \e surely non-zero |
| 301 | 301 |
static bool nonZero(Value a) { return a!=0; }
|
| 302 | 302 |
|
| 303 | 303 |
///@} |
| 304 | 304 |
|
| 305 | 305 |
///Returns zero |
| 306 | 306 |
static Value zero() {return 0;}
|
| 307 | 307 |
}; |
| 308 |
|
|
| 308 |
|
|
| 309 | 309 |
|
| 310 | 310 |
///Long integer specialization of Tolerance. |
| 311 | 311 |
|
| 312 | 312 |
///Long integer specialization of Tolerance. |
| 313 | 313 |
///\sa Tolerance |
| 314 | 314 |
template<> |
| 315 | 315 |
class Tolerance<long int> |
| 316 | 316 |
{
|
| 317 | 317 |
public: |
| 318 | 318 |
///\e |
| 319 | 319 |
typedef long int Value; |
| 320 | 320 |
|
| 321 | 321 |
///\name Comparisons |
| 322 | 322 |
///See \ref lemon::Tolerance "Tolerance" for more details. |
| 323 | 323 |
|
| 324 | 324 |
///@{
|
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_UNION_FIND_H |
| ... | ... |
@@ -25,45 +25,45 @@ |
| 25 | 25 |
//! |
| 26 | 26 |
|
| 27 | 27 |
#include <vector> |
| 28 | 28 |
#include <list> |
| 29 | 29 |
#include <utility> |
| 30 | 30 |
#include <algorithm> |
| 31 | 31 |
#include <functional> |
| 32 | 32 |
|
| 33 | 33 |
#include <lemon/bits/invalid.h> |
| 34 | 34 |
|
| 35 | 35 |
namespace lemon {
|
| 36 | 36 |
|
| 37 | 37 |
/// \ingroup auxdat |
| 38 | 38 |
/// |
| 39 | 39 |
/// \brief A \e Union-Find data structure implementation |
| 40 | 40 |
/// |
| 41 |
/// The class implements the \e Union-Find data structure. |
|
| 41 |
/// The class implements the \e Union-Find data structure. |
|
| 42 | 42 |
/// The union operation uses rank heuristic, while |
| 43 | 43 |
/// the find operation uses path compression. |
| 44 |
/// This is a very simple but efficient implementation, providing |
|
| 44 |
/// This is a very simple but efficient implementation, providing |
|
| 45 | 45 |
/// only four methods: join (union), find, insert and size. |
| 46 | 46 |
/// For more features see the \ref UnionFindEnum class. |
| 47 | 47 |
/// |
| 48 | 48 |
/// It is primarily used in Kruskal algorithm for finding minimal |
| 49 | 49 |
/// cost spanning tree in a graph. |
| 50 | 50 |
/// \sa kruskal() |
| 51 | 51 |
/// |
| 52 | 52 |
/// \pre You need to add all the elements by the \ref insert() |
| 53 |
/// method. |
|
| 53 |
/// method. |
|
| 54 | 54 |
template <typename _ItemIntMap> |
| 55 | 55 |
class UnionFind {
|
| 56 | 56 |
public: |
| 57 | 57 |
|
| 58 | 58 |
typedef _ItemIntMap ItemIntMap; |
| 59 | 59 |
typedef typename ItemIntMap::Key Item; |
| 60 | 60 |
|
| 61 | 61 |
private: |
| 62 | 62 |
// If the items vector stores negative value for an item then |
| 63 | 63 |
// that item is root item and it has -items[it] component size. |
| 64 | 64 |
// Else the items[it] contains the index of the parent. |
| 65 | 65 |
std::vector<int> items; |
| 66 | 66 |
ItemIntMap& index; |
| 67 | 67 |
|
| 68 | 68 |
bool rep(int idx) const {
|
| 69 | 69 |
return items[idx] < 0; |
| ... | ... |
@@ -98,61 +98,61 @@ |
| 98 | 98 |
/// The method returns the index of the element's component. |
| 99 | 99 |
/// This is an integer between zero and the number of inserted elements. |
| 100 | 100 |
/// |
| 101 | 101 |
int find(const Item& a) {
|
| 102 | 102 |
return repIndex(index[a]); |
| 103 | 103 |
} |
| 104 | 104 |
|
| 105 | 105 |
/// \brief Clears the union-find data structure |
| 106 | 106 |
/// |
| 107 | 107 |
/// Erase each item from the data structure. |
| 108 | 108 |
void clear() {
|
| 109 | 109 |
items.clear(); |
| 110 | 110 |
} |
| 111 | 111 |
|
| 112 | 112 |
/// \brief Inserts a new element into the structure. |
| 113 | 113 |
/// |
| 114 |
/// This method inserts a new element into the data structure. |
|
| 114 |
/// This method inserts a new element into the data structure. |
|
| 115 | 115 |
/// |
| 116 | 116 |
/// The method returns the index of the new component. |
| 117 | 117 |
int insert(const Item& a) {
|
| 118 | 118 |
int n = items.size(); |
| 119 | 119 |
items.push_back(-1); |
| 120 | 120 |
index.set(a,n); |
| 121 | 121 |
return n; |
| 122 | 122 |
} |
| 123 | 123 |
|
| 124 | 124 |
/// \brief Joining the components of element \e a and element \e b. |
| 125 | 125 |
/// |
| 126 |
/// This is the \e union operation of the Union-Find structure. |
|
| 126 |
/// This is the \e union operation of the Union-Find structure. |
|
| 127 | 127 |
/// Joins the component of element \e a and component of |
| 128 | 128 |
/// element \e b. If \e a and \e b are in the same component then |
| 129 | 129 |
/// it returns false otherwise it returns true. |
| 130 | 130 |
bool join(const Item& a, const Item& b) {
|
| 131 | 131 |
int ka = repIndex(index[a]); |
| 132 | 132 |
int kb = repIndex(index[b]); |
| 133 | 133 |
|
| 134 |
if ( ka == kb ) |
|
| 135 |
return false; |
|
| 134 |
if ( ka == kb ) |
|
| 135 |
return false; |
|
| 136 | 136 |
|
| 137 | 137 |
if (items[ka] < items[kb]) {
|
| 138 |
items[ka] += items[kb]; |
|
| 139 |
items[kb] = ka; |
|
| 138 |
items[ka] += items[kb]; |
|
| 139 |
items[kb] = ka; |
|
| 140 | 140 |
} else {
|
| 141 |
items[kb] += items[ka]; |
|
| 142 |
items[ka] = kb; |
|
| 141 |
items[kb] += items[ka]; |
|
| 142 |
items[ka] = kb; |
|
| 143 | 143 |
} |
| 144 | 144 |
return true; |
| 145 | 145 |
} |
| 146 | 146 |
|
| 147 | 147 |
/// \brief Returns the size of the component of element \e a. |
| 148 | 148 |
/// |
| 149 | 149 |
/// Returns the size of the component of element \e a. |
| 150 | 150 |
int size(const Item& a) {
|
| 151 | 151 |
int k = repIndex(index[a]); |
| 152 | 152 |
return - items[k]; |
| 153 | 153 |
} |
| 154 | 154 |
|
| 155 | 155 |
}; |
| 156 | 156 |
|
| 157 | 157 |
/// \ingroup auxdat |
| 158 | 158 |
/// |
| ... | ... |
@@ -160,86 +160,86 @@ |
| 160 | 160 |
/// is able to enumerate the components. |
| 161 | 161 |
/// |
| 162 | 162 |
/// The class implements a \e Union-Find data structure |
| 163 | 163 |
/// which is able to enumerate the components and the items in |
| 164 | 164 |
/// a component. If you don't need this feature then perhaps it's |
| 165 | 165 |
/// better to use the \ref UnionFind class which is more efficient. |
| 166 | 166 |
/// |
| 167 | 167 |
/// The union operation uses rank heuristic, while |
| 168 | 168 |
/// the find operation uses path compression. |
| 169 | 169 |
/// |
| 170 | 170 |
/// \pre You need to add all the elements by the \ref insert() |
| 171 | 171 |
/// method. |
| 172 | 172 |
/// |
| 173 | 173 |
template <typename _ItemIntMap> |
| 174 | 174 |
class UnionFindEnum {
|
| 175 | 175 |
public: |
| 176 |
|
|
| 176 |
|
|
| 177 | 177 |
typedef _ItemIntMap ItemIntMap; |
| 178 | 178 |
typedef typename ItemIntMap::Key Item; |
| 179 | 179 |
|
| 180 | 180 |
private: |
| 181 |
|
|
| 181 |
|
|
| 182 | 182 |
ItemIntMap& index; |
| 183 | 183 |
|
| 184 | 184 |
// If the parent stores negative value for an item then that item |
| 185 | 185 |
// is root item and it has ~(items[it].parent) component id. Else |
| 186 | 186 |
// the items[it].parent contains the index of the parent. |
| 187 | 187 |
// |
| 188 | 188 |
// The \c next and \c prev provides the double-linked |
| 189 | 189 |
// cyclic list of one component's items. |
| 190 | 190 |
struct ItemT {
|
| 191 | 191 |
int parent; |
| 192 | 192 |
Item item; |
| 193 | 193 |
|
| 194 | 194 |
int next, prev; |
| 195 | 195 |
}; |
| 196 | 196 |
|
| 197 | 197 |
std::vector<ItemT> items; |
| 198 | 198 |
int firstFreeItem; |
| 199 | 199 |
|
| 200 | 200 |
struct ClassT {
|
| 201 | 201 |
int size; |
| 202 | 202 |
int firstItem; |
| 203 | 203 |
int next, prev; |
| 204 | 204 |
}; |
| 205 |
|
|
| 205 |
|
|
| 206 | 206 |
std::vector<ClassT> classes; |
| 207 | 207 |
int firstClass, firstFreeClass; |
| 208 | 208 |
|
| 209 | 209 |
int newClass() {
|
| 210 | 210 |
if (firstFreeClass == -1) {
|
| 211 |
int cdx = classes.size(); |
|
| 212 |
classes.push_back(ClassT()); |
|
| 213 |
|
|
| 211 |
int cdx = classes.size(); |
|
| 212 |
classes.push_back(ClassT()); |
|
| 213 |
return cdx; |
|
| 214 | 214 |
} else {
|
| 215 |
int cdx = firstFreeClass; |
|
| 216 |
firstFreeClass = classes[firstFreeClass].next; |
|
| 217 |
|
|
| 215 |
int cdx = firstFreeClass; |
|
| 216 |
firstFreeClass = classes[firstFreeClass].next; |
|
| 217 |
return cdx; |
|
| 218 | 218 |
} |
| 219 | 219 |
} |
| 220 | 220 |
|
| 221 | 221 |
int newItem() {
|
| 222 | 222 |
if (firstFreeItem == -1) {
|
| 223 |
int idx = items.size(); |
|
| 224 |
items.push_back(ItemT()); |
|
| 225 |
|
|
| 223 |
int idx = items.size(); |
|
| 224 |
items.push_back(ItemT()); |
|
| 225 |
return idx; |
|
| 226 | 226 |
} else {
|
| 227 |
int idx = firstFreeItem; |
|
| 228 |
firstFreeItem = items[firstFreeItem].next; |
|
| 229 |
|
|
| 227 |
int idx = firstFreeItem; |
|
| 228 |
firstFreeItem = items[firstFreeItem].next; |
|
| 229 |
return idx; |
|
| 230 | 230 |
} |
| 231 | 231 |
} |
| 232 | 232 |
|
| 233 | 233 |
|
| 234 | 234 |
bool rep(int idx) const {
|
| 235 | 235 |
return items[idx].parent < 0; |
| 236 | 236 |
} |
| 237 | 237 |
|
| 238 | 238 |
int repIndex(int idx) const {
|
| 239 | 239 |
int k = idx; |
| 240 | 240 |
while (!rep(k)) {
|
| 241 | 241 |
k = items[k].parent; |
| 242 | 242 |
} |
| 243 | 243 |
while (idx != k) {
|
| 244 | 244 |
int next = items[idx].parent; |
| 245 | 245 |
const_cast<int&>(items[idx].parent) = k; |
| ... | ... |
@@ -254,238 +254,238 @@ |
| 254 | 254 |
|
| 255 | 255 |
void singletonItem(int idx) {
|
| 256 | 256 |
items[idx].next = idx; |
| 257 | 257 |
items[idx].prev = idx; |
| 258 | 258 |
} |
| 259 | 259 |
|
| 260 | 260 |
void laceItem(int idx, int rdx) {
|
| 261 | 261 |
items[idx].prev = rdx; |
| 262 | 262 |
items[idx].next = items[rdx].next; |
| 263 | 263 |
items[items[rdx].next].prev = idx; |
| 264 | 264 |
items[rdx].next = idx; |
| 265 | 265 |
} |
| 266 | 266 |
|
| 267 | 267 |
void unlaceItem(int idx) {
|
| 268 | 268 |
items[items[idx].prev].next = items[idx].next; |
| 269 | 269 |
items[items[idx].next].prev = items[idx].prev; |
| 270 |
|
|
| 270 |
|
|
| 271 | 271 |
items[idx].next = firstFreeItem; |
| 272 | 272 |
firstFreeItem = idx; |
| 273 | 273 |
} |
| 274 | 274 |
|
| 275 | 275 |
void spliceItems(int ak, int bk) {
|
| 276 | 276 |
items[items[ak].prev].next = bk; |
| 277 | 277 |
items[items[bk].prev].next = ak; |
| 278 | 278 |
int tmp = items[ak].prev; |
| 279 | 279 |
items[ak].prev = items[bk].prev; |
| 280 | 280 |
items[bk].prev = tmp; |
| 281 |
|
|
| 281 |
|
|
| 282 | 282 |
} |
| 283 | 283 |
|
| 284 | 284 |
void laceClass(int cls) {
|
| 285 | 285 |
if (firstClass != -1) {
|
| 286 | 286 |
classes[firstClass].prev = cls; |
| 287 | 287 |
} |
| 288 | 288 |
classes[cls].next = firstClass; |
| 289 | 289 |
classes[cls].prev = -1; |
| 290 | 290 |
firstClass = cls; |
| 291 |
} |
|
| 291 |
} |
|
| 292 | 292 |
|
| 293 | 293 |
void unlaceClass(int cls) {
|
| 294 | 294 |
if (classes[cls].prev != -1) {
|
| 295 | 295 |
classes[classes[cls].prev].next = classes[cls].next; |
| 296 | 296 |
} else {
|
| 297 | 297 |
firstClass = classes[cls].next; |
| 298 | 298 |
} |
| 299 | 299 |
if (classes[cls].next != -1) {
|
| 300 | 300 |
classes[classes[cls].next].prev = classes[cls].prev; |
| 301 | 301 |
} |
| 302 |
|
|
| 302 |
|
|
| 303 | 303 |
classes[cls].next = firstFreeClass; |
| 304 | 304 |
firstFreeClass = cls; |
| 305 |
} |
|
| 305 |
} |
|
| 306 | 306 |
|
| 307 | 307 |
public: |
| 308 | 308 |
|
| 309 |
UnionFindEnum(ItemIntMap& _index) |
|
| 310 |
: index(_index), items(), firstFreeItem(-1), |
|
| 311 |
firstClass(-1), firstFreeClass(-1) {}
|
|
| 312 |
|
|
| 309 |
UnionFindEnum(ItemIntMap& _index) |
|
| 310 |
: index(_index), items(), firstFreeItem(-1), |
|
| 311 |
firstClass(-1), firstFreeClass(-1) {}
|
|
| 312 |
|
|
| 313 | 313 |
/// \brief Inserts the given element into a new component. |
| 314 | 314 |
/// |
| 315 | 315 |
/// This method creates a new component consisting only of the |
| 316 | 316 |
/// given element. |
| 317 | 317 |
/// |
| 318 | 318 |
int insert(const Item& item) {
|
| 319 | 319 |
int idx = newItem(); |
| 320 | 320 |
|
| 321 | 321 |
index.set(item, idx); |
| 322 | 322 |
|
| 323 | 323 |
singletonItem(idx); |
| 324 | 324 |
items[idx].item = item; |
| 325 | 325 |
|
| 326 | 326 |
int cdx = newClass(); |
| 327 | 327 |
|
| 328 | 328 |
items[idx].parent = ~cdx; |
| 329 | 329 |
|
| 330 | 330 |
laceClass(cdx); |
| 331 | 331 |
classes[cdx].size = 1; |
| 332 | 332 |
classes[cdx].firstItem = idx; |
| 333 | 333 |
|
| 334 | 334 |
firstClass = cdx; |
| 335 |
|
|
| 335 |
|
|
| 336 | 336 |
return cdx; |
| 337 | 337 |
} |
| 338 | 338 |
|
| 339 | 339 |
/// \brief Inserts the given element into the component of the others. |
| 340 | 340 |
/// |
| 341 | 341 |
/// This methods inserts the element \e a into the component of the |
| 342 |
/// element \e comp. |
|
| 342 |
/// element \e comp. |
|
| 343 | 343 |
void insert(const Item& item, int cls) {
|
| 344 | 344 |
int rdx = classes[cls].firstItem; |
| 345 | 345 |
int idx = newItem(); |
| 346 | 346 |
|
| 347 | 347 |
index.set(item, idx); |
| 348 | 348 |
|
| 349 | 349 |
laceItem(idx, rdx); |
| 350 | 350 |
|
| 351 | 351 |
items[idx].item = item; |
| 352 | 352 |
items[idx].parent = rdx; |
| 353 | 353 |
|
| 354 | 354 |
++classes[~(items[rdx].parent)].size; |
| 355 | 355 |
} |
| 356 | 356 |
|
| 357 | 357 |
/// \brief Clears the union-find data structure |
| 358 | 358 |
/// |
| 359 | 359 |
/// Erase each item from the data structure. |
| 360 | 360 |
void clear() {
|
| 361 | 361 |
items.clear(); |
| 362 | 362 |
firstClass = -1; |
| 363 | 363 |
firstFreeItem = -1; |
| 364 | 364 |
} |
| 365 | 365 |
|
| 366 | 366 |
/// \brief Finds the component of the given element. |
| 367 | 367 |
/// |
| 368 | 368 |
/// The method returns the component id of the given element. |
| 369 | 369 |
int find(const Item &item) const {
|
| 370 | 370 |
return ~(items[repIndex(index[item])].parent); |
| 371 | 371 |
} |
| 372 | 372 |
|
| 373 | 373 |
/// \brief Joining the component of element \e a and element \e b. |
| 374 | 374 |
/// |
| 375 |
/// This is the \e union operation of the Union-Find structure. |
|
| 375 |
/// This is the \e union operation of the Union-Find structure. |
|
| 376 | 376 |
/// Joins the component of element \e a and component of |
| 377 | 377 |
/// element \e b. If \e a and \e b are in the same component then |
| 378 | 378 |
/// returns -1 else returns the remaining class. |
| 379 | 379 |
int join(const Item& a, const Item& b) {
|
| 380 | 380 |
|
| 381 | 381 |
int ak = repIndex(index[a]); |
| 382 | 382 |
int bk = repIndex(index[b]); |
| 383 | 383 |
|
| 384 | 384 |
if (ak == bk) {
|
| 385 |
|
|
| 385 |
return -1; |
|
| 386 | 386 |
} |
| 387 | 387 |
|
| 388 | 388 |
int acx = ~(items[ak].parent); |
| 389 | 389 |
int bcx = ~(items[bk].parent); |
| 390 | 390 |
|
| 391 | 391 |
int rcx; |
| 392 | 392 |
|
| 393 | 393 |
if (classes[acx].size > classes[bcx].size) {
|
| 394 |
classes[acx].size += classes[bcx].size; |
|
| 395 |
items[bk].parent = ak; |
|
| 394 |
classes[acx].size += classes[bcx].size; |
|
| 395 |
items[bk].parent = ak; |
|
| 396 | 396 |
unlaceClass(bcx); |
| 397 |
|
|
| 397 |
rcx = acx; |
|
| 398 | 398 |
} else {
|
| 399 |
classes[bcx].size += classes[acx].size; |
|
| 400 |
items[ak].parent = bk; |
|
| 399 |
classes[bcx].size += classes[acx].size; |
|
| 400 |
items[ak].parent = bk; |
|
| 401 | 401 |
unlaceClass(acx); |
| 402 |
|
|
| 402 |
rcx = bcx; |
|
| 403 | 403 |
} |
| 404 | 404 |
spliceItems(ak, bk); |
| 405 | 405 |
|
| 406 | 406 |
return rcx; |
| 407 | 407 |
} |
| 408 | 408 |
|
| 409 | 409 |
/// \brief Returns the size of the class. |
| 410 | 410 |
/// |
| 411 | 411 |
/// Returns the size of the class. |
| 412 | 412 |
int size(int cls) const {
|
| 413 | 413 |
return classes[cls].size; |
| 414 | 414 |
} |
| 415 | 415 |
|
| 416 |
/// \brief Splits up the component. |
|
| 416 |
/// \brief Splits up the component. |
|
| 417 | 417 |
/// |
| 418 | 418 |
/// Splitting the component into singleton components (component |
| 419 | 419 |
/// of size one). |
| 420 | 420 |
void split(int cls) {
|
| 421 | 421 |
int fdx = classes[cls].firstItem; |
| 422 | 422 |
int idx = items[fdx].next; |
| 423 | 423 |
while (idx != fdx) {
|
| 424 | 424 |
int next = items[idx].next; |
| 425 | 425 |
|
| 426 |
|
|
| 426 |
singletonItem(idx); |
|
| 427 | 427 |
|
| 428 |
|
|
| 428 |
int cdx = newClass(); |
|
| 429 | 429 |
items[idx].parent = ~cdx; |
| 430 | 430 |
|
| 431 |
laceClass(cdx); |
|
| 432 |
classes[cdx].size = 1; |
|
| 433 |
classes[cdx].firstItem = idx; |
|
| 434 |
|
|
| 431 |
laceClass(cdx); |
|
| 432 |
classes[cdx].size = 1; |
|
| 433 |
classes[cdx].firstItem = idx; |
|
| 434 |
|
|
| 435 | 435 |
idx = next; |
| 436 | 436 |
} |
| 437 | 437 |
|
| 438 | 438 |
items[idx].prev = idx; |
| 439 | 439 |
items[idx].next = idx; |
| 440 | 440 |
|
| 441 | 441 |
classes[~(items[idx].parent)].size = 1; |
| 442 |
|
|
| 442 |
|
|
| 443 | 443 |
} |
| 444 | 444 |
|
| 445 | 445 |
/// \brief Removes the given element from the structure. |
| 446 | 446 |
/// |
| 447 | 447 |
/// Removes the element from its component and if the component becomes |
| 448 | 448 |
/// empty then removes that component from the component list. |
| 449 | 449 |
/// |
| 450 | 450 |
/// \warning It is an error to remove an element which is not in |
| 451 | 451 |
/// the structure. |
| 452 | 452 |
/// \warning This running time of this operation is proportional to the |
| 453 | 453 |
/// number of the items in this class. |
| 454 | 454 |
void erase(const Item& item) {
|
| 455 | 455 |
int idx = index[item]; |
| 456 | 456 |
int fdx = items[idx].next; |
| 457 | 457 |
|
| 458 | 458 |
int cdx = classIndex(idx); |
| 459 | 459 |
if (idx == fdx) {
|
| 460 |
unlaceClass(cdx); |
|
| 461 |
items[idx].next = firstFreeItem; |
|
| 462 |
firstFreeItem = idx; |
|
| 463 |
return; |
|
| 460 |
unlaceClass(cdx); |
|
| 461 |
items[idx].next = firstFreeItem; |
|
| 462 |
firstFreeItem = idx; |
|
| 463 |
return; |
|
| 464 | 464 |
} else {
|
| 465 |
classes[cdx].firstItem = fdx; |
|
| 466 |
--classes[cdx].size; |
|
| 467 |
|
|
| 465 |
classes[cdx].firstItem = fdx; |
|
| 466 |
--classes[cdx].size; |
|
| 467 |
items[fdx].parent = ~cdx; |
|
| 468 | 468 |
|
| 469 |
unlaceItem(idx); |
|
| 470 |
idx = items[fdx].next; |
|
| 471 |
while (idx != fdx) {
|
|
| 472 |
items[idx].parent = fdx; |
|
| 473 |
idx = items[idx].next; |
|
| 474 |
} |
|
| 475 |
|
|
| 469 |
unlaceItem(idx); |
|
| 470 |
idx = items[fdx].next; |
|
| 471 |
while (idx != fdx) {
|
|
| 472 |
items[idx].parent = fdx; |
|
| 473 |
idx = items[idx].next; |
|
| 474 |
} |
|
| 475 |
|
|
| 476 | 476 |
} |
| 477 | 477 |
|
| 478 | 478 |
} |
| 479 | 479 |
|
| 480 | 480 |
/// \brief Gives back a representant item of the component. |
| 481 | 481 |
/// |
| 482 | 482 |
/// Gives back a representant item of the component. |
| 483 | 483 |
Item item(int cls) const {
|
| 484 | 484 |
return items[classes[cls].firstItem].item; |
| 485 | 485 |
} |
| 486 | 486 |
|
| 487 | 487 |
/// \brief Removes the component of the given element from the structure. |
| 488 | 488 |
/// |
| 489 | 489 |
/// Removes the component of the given element from the structure. |
| 490 | 490 |
/// |
| 491 | 491 |
/// \warning It is an error to give an element which is not in the |
| ... | ... |
@@ -501,62 +501,62 @@ |
| 501 | 501 |
/// |
| 502 | 502 |
/// ClassIt is a lemon style iterator for the components. It iterates |
| 503 | 503 |
/// on the ids of the classes. |
| 504 | 504 |
class ClassIt {
|
| 505 | 505 |
public: |
| 506 | 506 |
/// \brief Constructor of the iterator |
| 507 | 507 |
/// |
| 508 | 508 |
/// Constructor of the iterator |
| 509 | 509 |
ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
|
| 510 | 510 |
cdx = unionFind->firstClass; |
| 511 | 511 |
} |
| 512 | 512 |
|
| 513 | 513 |
/// \brief Constructor to get invalid iterator |
| 514 | 514 |
/// |
| 515 | 515 |
/// Constructor to get invalid iterator |
| 516 | 516 |
ClassIt(Invalid) : unionFind(0), cdx(-1) {}
|
| 517 |
|
|
| 517 |
|
|
| 518 | 518 |
/// \brief Increment operator |
| 519 | 519 |
/// |
| 520 | 520 |
/// It steps to the next representant item. |
| 521 | 521 |
ClassIt& operator++() {
|
| 522 | 522 |
cdx = unionFind->classes[cdx].next; |
| 523 | 523 |
return *this; |
| 524 | 524 |
} |
| 525 |
|
|
| 525 |
|
|
| 526 | 526 |
/// \brief Conversion operator |
| 527 | 527 |
/// |
| 528 | 528 |
/// It converts the iterator to the current representant item. |
| 529 | 529 |
operator int() const {
|
| 530 | 530 |
return cdx; |
| 531 | 531 |
} |
| 532 | 532 |
|
| 533 | 533 |
/// \brief Equality operator |
| 534 | 534 |
/// |
| 535 | 535 |
/// Equality operator |
| 536 |
bool operator==(const ClassIt& i) {
|
|
| 536 |
bool operator==(const ClassIt& i) {
|
|
| 537 | 537 |
return i.cdx == cdx; |
| 538 | 538 |
} |
| 539 | 539 |
|
| 540 | 540 |
/// \brief Inequality operator |
| 541 | 541 |
/// |
| 542 | 542 |
/// Inequality operator |
| 543 |
bool operator!=(const ClassIt& i) {
|
|
| 543 |
bool operator!=(const ClassIt& i) {
|
|
| 544 | 544 |
return i.cdx != cdx; |
| 545 | 545 |
} |
| 546 |
|
|
| 546 |
|
|
| 547 | 547 |
private: |
| 548 | 548 |
const UnionFindEnum* unionFind; |
| 549 | 549 |
int cdx; |
| 550 | 550 |
}; |
| 551 | 551 |
|
| 552 | 552 |
/// \brief Lemon style iterator for the items of a component. |
| 553 | 553 |
/// |
| 554 | 554 |
/// ClassIt is a lemon style iterator for the components. It iterates |
| 555 | 555 |
/// on the items of a class. By example if you want to iterate on |
| 556 | 556 |
/// each items of each classes then you may write the next code. |
| 557 | 557 |
///\code |
| 558 | 558 |
/// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
|
| 559 | 559 |
/// std::cout << "Class: "; |
| 560 | 560 |
/// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
|
| 561 | 561 |
/// std::cout << toString(iit) << ' ' << std::endl; |
| 562 | 562 |
/// } |
| ... | ... |
@@ -564,163 +564,163 @@ |
| 564 | 564 |
/// } |
| 565 | 565 |
///\endcode |
| 566 | 566 |
class ItemIt {
|
| 567 | 567 |
public: |
| 568 | 568 |
/// \brief Constructor of the iterator |
| 569 | 569 |
/// |
| 570 | 570 |
/// Constructor of the iterator. The iterator iterates |
| 571 | 571 |
/// on the class of the \c item. |
| 572 | 572 |
ItemIt(const UnionFindEnum& ufe, int cls) : unionFind(&ufe) {
|
| 573 | 573 |
fdx = idx = unionFind->classes[cls].firstItem; |
| 574 | 574 |
} |
| 575 | 575 |
|
| 576 | 576 |
/// \brief Constructor to get invalid iterator |
| 577 | 577 |
/// |
| 578 | 578 |
/// Constructor to get invalid iterator |
| 579 | 579 |
ItemIt(Invalid) : unionFind(0), idx(-1) {}
|
| 580 |
|
|
| 580 |
|
|
| 581 | 581 |
/// \brief Increment operator |
| 582 | 582 |
/// |
| 583 | 583 |
/// It steps to the next item in the class. |
| 584 | 584 |
ItemIt& operator++() {
|
| 585 | 585 |
idx = unionFind->items[idx].next; |
| 586 | 586 |
if (idx == fdx) idx = -1; |
| 587 | 587 |
return *this; |
| 588 | 588 |
} |
| 589 |
|
|
| 589 |
|
|
| 590 | 590 |
/// \brief Conversion operator |
| 591 | 591 |
/// |
| 592 | 592 |
/// It converts the iterator to the current item. |
| 593 | 593 |
operator const Item&() const {
|
| 594 | 594 |
return unionFind->items[idx].item; |
| 595 | 595 |
} |
| 596 | 596 |
|
| 597 | 597 |
/// \brief Equality operator |
| 598 | 598 |
/// |
| 599 | 599 |
/// Equality operator |
| 600 |
bool operator==(const ItemIt& i) {
|
|
| 600 |
bool operator==(const ItemIt& i) {
|
|
| 601 | 601 |
return i.idx == idx; |
| 602 | 602 |
} |
| 603 | 603 |
|
| 604 | 604 |
/// \brief Inequality operator |
| 605 | 605 |
/// |
| 606 | 606 |
/// Inequality operator |
| 607 |
bool operator!=(const ItemIt& i) {
|
|
| 607 |
bool operator!=(const ItemIt& i) {
|
|
| 608 | 608 |
return i.idx != idx; |
| 609 | 609 |
} |
| 610 |
|
|
| 610 |
|
|
| 611 | 611 |
private: |
| 612 | 612 |
const UnionFindEnum* unionFind; |
| 613 | 613 |
int idx, fdx; |
| 614 | 614 |
}; |
| 615 | 615 |
|
| 616 | 616 |
}; |
| 617 | 617 |
|
| 618 | 618 |
/// \ingroup auxdat |
| 619 | 619 |
/// |
| 620 | 620 |
/// \brief A \e Extend-Find data structure implementation which |
| 621 | 621 |
/// is able to enumerate the components. |
| 622 | 622 |
/// |
| 623 | 623 |
/// The class implements an \e Extend-Find data structure which is |
| 624 | 624 |
/// able to enumerate the components and the items in a |
| 625 | 625 |
/// component. The data structure is a simplification of the |
| 626 | 626 |
/// Union-Find structure, and it does not allow to merge two components. |
| 627 | 627 |
/// |
| 628 | 628 |
/// \pre You need to add all the elements by the \ref insert() |
| 629 | 629 |
/// method. |
| 630 | 630 |
template <typename _ItemIntMap> |
| 631 | 631 |
class ExtendFindEnum {
|
| 632 | 632 |
public: |
| 633 |
|
|
| 633 |
|
|
| 634 | 634 |
typedef _ItemIntMap ItemIntMap; |
| 635 | 635 |
typedef typename ItemIntMap::Key Item; |
| 636 | 636 |
|
| 637 | 637 |
private: |
| 638 |
|
|
| 638 |
|
|
| 639 | 639 |
ItemIntMap& index; |
| 640 | 640 |
|
| 641 | 641 |
struct ItemT {
|
| 642 | 642 |
int cls; |
| 643 | 643 |
Item item; |
| 644 | 644 |
int next, prev; |
| 645 | 645 |
}; |
| 646 | 646 |
|
| 647 | 647 |
std::vector<ItemT> items; |
| 648 | 648 |
int firstFreeItem; |
| 649 | 649 |
|
| 650 | 650 |
struct ClassT {
|
| 651 | 651 |
int firstItem; |
| 652 | 652 |
int next, prev; |
| 653 | 653 |
}; |
| 654 | 654 |
|
| 655 | 655 |
std::vector<ClassT> classes; |
| 656 | 656 |
|
| 657 | 657 |
int firstClass, firstFreeClass; |
| 658 | 658 |
|
| 659 | 659 |
int newClass() {
|
| 660 | 660 |
if (firstFreeClass != -1) {
|
| 661 |
int cdx = firstFreeClass; |
|
| 662 |
firstFreeClass = classes[cdx].next; |
|
| 663 |
|
|
| 661 |
int cdx = firstFreeClass; |
|
| 662 |
firstFreeClass = classes[cdx].next; |
|
| 663 |
return cdx; |
|
| 664 | 664 |
} else {
|
| 665 |
classes.push_back(ClassT()); |
|
| 666 |
return classes.size() - 1; |
|
| 665 |
classes.push_back(ClassT()); |
|
| 666 |
return classes.size() - 1; |
|
| 667 | 667 |
} |
| 668 | 668 |
} |
| 669 | 669 |
|
| 670 | 670 |
int newItem() {
|
| 671 | 671 |
if (firstFreeItem != -1) {
|
| 672 |
int idx = firstFreeItem; |
|
| 673 |
firstFreeItem = items[idx].next; |
|
| 674 |
|
|
| 672 |
int idx = firstFreeItem; |
|
| 673 |
firstFreeItem = items[idx].next; |
|
| 674 |
return idx; |
|
| 675 | 675 |
} else {
|
| 676 |
items.push_back(ItemT()); |
|
| 677 |
return items.size() - 1; |
|
| 676 |
items.push_back(ItemT()); |
|
| 677 |
return items.size() - 1; |
|
| 678 | 678 |
} |
| 679 | 679 |
} |
| 680 | 680 |
|
| 681 | 681 |
public: |
| 682 | 682 |
|
| 683 | 683 |
/// \brief Constructor |
| 684 |
ExtendFindEnum(ItemIntMap& _index) |
|
| 685 |
: index(_index), items(), firstFreeItem(-1), |
|
| 686 |
classes(), firstClass(-1), firstFreeClass(-1) {}
|
|
| 687 |
|
|
| 684 |
ExtendFindEnum(ItemIntMap& _index) |
|
| 685 |
: index(_index), items(), firstFreeItem(-1), |
|
| 686 |
classes(), firstClass(-1), firstFreeClass(-1) {}
|
|
| 687 |
|
|
| 688 | 688 |
/// \brief Inserts the given element into a new component. |
| 689 | 689 |
/// |
| 690 | 690 |
/// This method creates a new component consisting only of the |
| 691 | 691 |
/// given element. |
| 692 | 692 |
int insert(const Item& item) {
|
| 693 | 693 |
int cdx = newClass(); |
| 694 | 694 |
classes[cdx].prev = -1; |
| 695 | 695 |
classes[cdx].next = firstClass; |
| 696 | 696 |
if (firstClass != -1) {
|
| 697 |
|
|
| 697 |
classes[firstClass].prev = cdx; |
|
| 698 | 698 |
} |
| 699 | 699 |
firstClass = cdx; |
| 700 |
|
|
| 700 |
|
|
| 701 | 701 |
int idx = newItem(); |
| 702 | 702 |
items[idx].item = item; |
| 703 | 703 |
items[idx].cls = cdx; |
| 704 | 704 |
items[idx].prev = idx; |
| 705 | 705 |
items[idx].next = idx; |
| 706 | 706 |
|
| 707 | 707 |
classes[cdx].firstItem = idx; |
| 708 | 708 |
|
| 709 | 709 |
index.set(item, idx); |
| 710 |
|
|
| 710 |
|
|
| 711 | 711 |
return cdx; |
| 712 | 712 |
} |
| 713 | 713 |
|
| 714 | 714 |
/// \brief Inserts the given element into the given component. |
| 715 | 715 |
/// |
| 716 | 716 |
/// This methods inserts the element \e item a into the \e cls class. |
| 717 | 717 |
void insert(const Item& item, int cls) {
|
| 718 | 718 |
int idx = newItem(); |
| 719 | 719 |
int rdx = classes[cls].firstItem; |
| 720 | 720 |
items[idx].item = item; |
| 721 | 721 |
items[idx].cls = cls; |
| 722 | 722 |
|
| 723 | 723 |
items[idx].prev = rdx; |
| 724 | 724 |
items[idx].next = items[rdx].next; |
| 725 | 725 |
items[items[rdx].next].prev = idx; |
| 726 | 726 |
items[rdx].next = idx; |
| ... | ... |
@@ -737,136 +737,136 @@ |
| 737 | 737 |
firstClass = firstFreeClass = firstFreeItem = -1; |
| 738 | 738 |
} |
| 739 | 739 |
|
| 740 | 740 |
/// \brief Gives back the class of the \e item. |
| 741 | 741 |
/// |
| 742 | 742 |
/// Gives back the class of the \e item. |
| 743 | 743 |
int find(const Item &item) const {
|
| 744 | 744 |
return items[index[item]].cls; |
| 745 | 745 |
} |
| 746 | 746 |
|
| 747 | 747 |
/// \brief Gives back a representant item of the component. |
| 748 | 748 |
/// |
| 749 | 749 |
/// Gives back a representant item of the component. |
| 750 | 750 |
Item item(int cls) const {
|
| 751 | 751 |
return items[classes[cls].firstItem].item; |
| 752 | 752 |
} |
| 753 |
|
|
| 753 |
|
|
| 754 | 754 |
/// \brief Removes the given element from the structure. |
| 755 | 755 |
/// |
| 756 | 756 |
/// Removes the element from its component and if the component becomes |
| 757 | 757 |
/// empty then removes that component from the component list. |
| 758 | 758 |
/// |
| 759 | 759 |
/// \warning It is an error to remove an element which is not in |
| 760 | 760 |
/// the structure. |
| 761 | 761 |
void erase(const Item &item) {
|
| 762 | 762 |
int idx = index[item]; |
| 763 | 763 |
int cdx = items[idx].cls; |
| 764 |
|
|
| 764 |
|
|
| 765 | 765 |
if (idx == items[idx].next) {
|
| 766 |
if (classes[cdx].prev != -1) {
|
|
| 767 |
classes[classes[cdx].prev].next = classes[cdx].next; |
|
| 768 |
} else {
|
|
| 769 |
firstClass = classes[cdx].next; |
|
| 770 |
} |
|
| 771 |
if (classes[cdx].next != -1) {
|
|
| 772 |
classes[classes[cdx].next].prev = classes[cdx].prev; |
|
| 773 |
} |
|
| 774 |
classes[cdx].next = firstFreeClass; |
|
| 775 |
firstFreeClass = cdx; |
|
| 766 |
if (classes[cdx].prev != -1) {
|
|
| 767 |
classes[classes[cdx].prev].next = classes[cdx].next; |
|
| 768 |
} else {
|
|
| 769 |
firstClass = classes[cdx].next; |
|
| 770 |
} |
|
| 771 |
if (classes[cdx].next != -1) {
|
|
| 772 |
classes[classes[cdx].next].prev = classes[cdx].prev; |
|
| 773 |
} |
|
| 774 |
classes[cdx].next = firstFreeClass; |
|
| 775 |
firstFreeClass = cdx; |
|
| 776 | 776 |
} else {
|
| 777 |
classes[cdx].firstItem = items[idx].next; |
|
| 778 |
items[items[idx].next].prev = items[idx].prev; |
|
| 779 |
|
|
| 777 |
classes[cdx].firstItem = items[idx].next; |
|
| 778 |
items[items[idx].next].prev = items[idx].prev; |
|
| 779 |
items[items[idx].prev].next = items[idx].next; |
|
| 780 | 780 |
} |
| 781 | 781 |
items[idx].next = firstFreeItem; |
| 782 | 782 |
firstFreeItem = idx; |
| 783 |
|
|
| 784 |
} |
|
| 785 | 783 |
|
| 786 |
|
|
| 784 |
} |
|
| 785 |
|
|
| 786 |
|
|
| 787 | 787 |
/// \brief Removes the component of the given element from the structure. |
| 788 | 788 |
/// |
| 789 | 789 |
/// Removes the component of the given element from the structure. |
| 790 | 790 |
/// |
| 791 | 791 |
/// \warning It is an error to give an element which is not in the |
| 792 | 792 |
/// structure. |
| 793 | 793 |
void eraseClass(int cdx) {
|
| 794 | 794 |
int idx = classes[cdx].firstItem; |
| 795 | 795 |
items[items[idx].prev].next = firstFreeItem; |
| 796 | 796 |
firstFreeItem = idx; |
| 797 | 797 |
|
| 798 | 798 |
if (classes[cdx].prev != -1) {
|
| 799 |
|
|
| 799 |
classes[classes[cdx].prev].next = classes[cdx].next; |
|
| 800 | 800 |
} else {
|
| 801 |
|
|
| 801 |
firstClass = classes[cdx].next; |
|
| 802 | 802 |
} |
| 803 | 803 |
if (classes[cdx].next != -1) {
|
| 804 |
|
|
| 804 |
classes[classes[cdx].next].prev = classes[cdx].prev; |
|
| 805 | 805 |
} |
| 806 | 806 |
classes[cdx].next = firstFreeClass; |
| 807 | 807 |
firstFreeClass = cdx; |
| 808 | 808 |
} |
| 809 | 809 |
|
| 810 | 810 |
/// \brief Lemon style iterator for the classes. |
| 811 | 811 |
/// |
| 812 | 812 |
/// ClassIt is a lemon style iterator for the components. It iterates |
| 813 | 813 |
/// on the ids of classes. |
| 814 | 814 |
class ClassIt {
|
| 815 | 815 |
public: |
| 816 | 816 |
/// \brief Constructor of the iterator |
| 817 | 817 |
/// |
| 818 | 818 |
/// Constructor of the iterator |
| 819 | 819 |
ClassIt(const ExtendFindEnum& ufe) : extendFind(&ufe) {
|
| 820 | 820 |
cdx = extendFind->firstClass; |
| 821 | 821 |
} |
| 822 | 822 |
|
| 823 | 823 |
/// \brief Constructor to get invalid iterator |
| 824 | 824 |
/// |
| 825 | 825 |
/// Constructor to get invalid iterator |
| 826 | 826 |
ClassIt(Invalid) : extendFind(0), cdx(-1) {}
|
| 827 |
|
|
| 827 |
|
|
| 828 | 828 |
/// \brief Increment operator |
| 829 | 829 |
/// |
| 830 | 830 |
/// It steps to the next representant item. |
| 831 | 831 |
ClassIt& operator++() {
|
| 832 | 832 |
cdx = extendFind->classes[cdx].next; |
| 833 | 833 |
return *this; |
| 834 | 834 |
} |
| 835 |
|
|
| 835 |
|
|
| 836 | 836 |
/// \brief Conversion operator |
| 837 | 837 |
/// |
| 838 | 838 |
/// It converts the iterator to the current class id. |
| 839 | 839 |
operator int() const {
|
| 840 | 840 |
return cdx; |
| 841 | 841 |
} |
| 842 | 842 |
|
| 843 | 843 |
/// \brief Equality operator |
| 844 | 844 |
/// |
| 845 | 845 |
/// Equality operator |
| 846 |
bool operator==(const ClassIt& i) {
|
|
| 846 |
bool operator==(const ClassIt& i) {
|
|
| 847 | 847 |
return i.cdx == cdx; |
| 848 | 848 |
} |
| 849 | 849 |
|
| 850 | 850 |
/// \brief Inequality operator |
| 851 | 851 |
/// |
| 852 | 852 |
/// Inequality operator |
| 853 |
bool operator!=(const ClassIt& i) {
|
|
| 853 |
bool operator!=(const ClassIt& i) {
|
|
| 854 | 854 |
return i.cdx != cdx; |
| 855 | 855 |
} |
| 856 |
|
|
| 856 |
|
|
| 857 | 857 |
private: |
| 858 | 858 |
const ExtendFindEnum* extendFind; |
| 859 | 859 |
int cdx; |
| 860 | 860 |
}; |
| 861 | 861 |
|
| 862 | 862 |
/// \brief Lemon style iterator for the items of a component. |
| 863 | 863 |
/// |
| 864 | 864 |
/// ClassIt is a lemon style iterator for the components. It iterates |
| 865 | 865 |
/// on the items of a class. By example if you want to iterate on |
| 866 | 866 |
/// each items of each classes then you may write the next code. |
| 867 | 867 |
///\code |
| 868 | 868 |
/// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
|
| 869 | 869 |
/// std::cout << "Class: "; |
| 870 | 870 |
/// for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
|
| 871 | 871 |
/// std::cout << toString(iit) << ' ' << std::endl; |
| 872 | 872 |
/// } |
| ... | ... |
@@ -874,99 +874,99 @@ |
| 874 | 874 |
/// } |
| 875 | 875 |
///\endcode |
| 876 | 876 |
class ItemIt {
|
| 877 | 877 |
public: |
| 878 | 878 |
/// \brief Constructor of the iterator |
| 879 | 879 |
/// |
| 880 | 880 |
/// Constructor of the iterator. The iterator iterates |
| 881 | 881 |
/// on the class of the \c item. |
| 882 | 882 |
ItemIt(const ExtendFindEnum& ufe, int cls) : extendFind(&ufe) {
|
| 883 | 883 |
fdx = idx = extendFind->classes[cls].firstItem; |
| 884 | 884 |
} |
| 885 | 885 |
|
| 886 | 886 |
/// \brief Constructor to get invalid iterator |
| 887 | 887 |
/// |
| 888 | 888 |
/// Constructor to get invalid iterator |
| 889 | 889 |
ItemIt(Invalid) : extendFind(0), idx(-1) {}
|
| 890 |
|
|
| 890 |
|
|
| 891 | 891 |
/// \brief Increment operator |
| 892 | 892 |
/// |
| 893 | 893 |
/// It steps to the next item in the class. |
| 894 | 894 |
ItemIt& operator++() {
|
| 895 | 895 |
idx = extendFind->items[idx].next; |
| 896 |
|
|
| 896 |
if (fdx == idx) idx = -1; |
|
| 897 | 897 |
return *this; |
| 898 | 898 |
} |
| 899 |
|
|
| 899 |
|
|
| 900 | 900 |
/// \brief Conversion operator |
| 901 | 901 |
/// |
| 902 | 902 |
/// It converts the iterator to the current item. |
| 903 | 903 |
operator const Item&() const {
|
| 904 | 904 |
return extendFind->items[idx].item; |
| 905 | 905 |
} |
| 906 | 906 |
|
| 907 | 907 |
/// \brief Equality operator |
| 908 | 908 |
/// |
| 909 | 909 |
/// Equality operator |
| 910 |
bool operator==(const ItemIt& i) {
|
|
| 910 |
bool operator==(const ItemIt& i) {
|
|
| 911 | 911 |
return i.idx == idx; |
| 912 | 912 |
} |
| 913 | 913 |
|
| 914 | 914 |
/// \brief Inequality operator |
| 915 | 915 |
/// |
| 916 | 916 |
/// Inequality operator |
| 917 |
bool operator!=(const ItemIt& i) {
|
|
| 917 |
bool operator!=(const ItemIt& i) {
|
|
| 918 | 918 |
return i.idx != idx; |
| 919 | 919 |
} |
| 920 |
|
|
| 920 |
|
|
| 921 | 921 |
private: |
| 922 | 922 |
const ExtendFindEnum* extendFind; |
| 923 | 923 |
int idx, fdx; |
| 924 | 924 |
}; |
| 925 | 925 |
|
| 926 | 926 |
}; |
| 927 | 927 |
|
| 928 | 928 |
/// \ingroup auxdat |
| 929 | 929 |
/// |
| 930 | 930 |
/// \brief A \e Union-Find data structure implementation which |
| 931 | 931 |
/// is able to store a priority for each item and retrieve the minimum of |
| 932 | 932 |
/// each class. |
| 933 | 933 |
/// |
| 934 | 934 |
/// A \e Union-Find data structure implementation which is able to |
| 935 | 935 |
/// store a priority for each item and retrieve the minimum of each |
| 936 | 936 |
/// class. In addition, it supports the joining and splitting the |
| 937 | 937 |
/// components. If you don't need this feature then you makes |
| 938 | 938 |
/// better to use the \ref UnionFind class which is more efficient. |
| 939 | 939 |
/// |
| 940 | 940 |
/// The union-find data strcuture based on a (2, 16)-tree with a |
| 941 | 941 |
/// tournament minimum selection on the internal nodes. The insert |
| 942 | 942 |
/// operation takes O(1), the find, set, decrease and increase takes |
| 943 | 943 |
/// O(log(n)), where n is the number of nodes in the current |
| 944 | 944 |
/// component. The complexity of join and split is O(log(n)*k), |
| 945 | 945 |
/// where n is the sum of the number of the nodes and k is the |
| 946 | 946 |
/// number of joined components or the number of the components |
| 947 | 947 |
/// after the split. |
| 948 | 948 |
/// |
| 949 | 949 |
/// \pre You need to add all the elements by the \ref insert() |
| 950 | 950 |
/// method. |
| 951 | 951 |
/// |
| 952 |
template <typename _Value, typename _ItemIntMap, |
|
| 952 |
template <typename _Value, typename _ItemIntMap, |
|
| 953 | 953 |
typename _Comp = std::less<_Value> > |
| 954 | 954 |
class HeapUnionFind {
|
| 955 | 955 |
public: |
| 956 |
|
|
| 956 |
|
|
| 957 | 957 |
typedef _Value Value; |
| 958 | 958 |
typedef typename _ItemIntMap::Key Item; |
| 959 | 959 |
|
| 960 | 960 |
typedef _ItemIntMap ItemIntMap; |
| 961 | 961 |
|
| 962 | 962 |
typedef _Comp Comp; |
| 963 | 963 |
|
| 964 | 964 |
private: |
| 965 | 965 |
|
| 966 | 966 |
static const int cmax = 16; |
| 967 | 967 |
|
| 968 | 968 |
ItemIntMap& index; |
| 969 | 969 |
|
| 970 | 970 |
struct ClassNode {
|
| 971 | 971 |
int parent; |
| 972 | 972 |
int depth; |
| ... | ... |
@@ -1041,33 +1041,33 @@ |
| 1041 | 1041 |
kd = nodes[kd].left; |
| 1042 | 1042 |
} |
| 1043 | 1043 |
return kd; |
| 1044 | 1044 |
} |
| 1045 | 1045 |
|
| 1046 | 1046 |
int nextNode(int id) const {
|
| 1047 | 1047 |
int depth = 0; |
| 1048 | 1048 |
while (id >= 0 && nodes[id].next == -1) {
|
| 1049 | 1049 |
id = nodes[id].parent; |
| 1050 | 1050 |
++depth; |
| 1051 | 1051 |
} |
| 1052 | 1052 |
if (id < 0) {
|
| 1053 | 1053 |
return -1; |
| 1054 | 1054 |
} |
| 1055 | 1055 |
id = nodes[id].next; |
| 1056 | 1056 |
while (depth--) {
|
| 1057 |
id = nodes[id].left; |
|
| 1057 |
id = nodes[id].left; |
|
| 1058 | 1058 |
} |
| 1059 | 1059 |
return id; |
| 1060 | 1060 |
} |
| 1061 | 1061 |
|
| 1062 | 1062 |
|
| 1063 | 1063 |
void setPrio(int id) {
|
| 1064 | 1064 |
int jd = nodes[id].left; |
| 1065 | 1065 |
nodes[id].prio = nodes[jd].prio; |
| 1066 | 1066 |
nodes[id].item = nodes[jd].item; |
| 1067 | 1067 |
jd = nodes[jd].next; |
| 1068 | 1068 |
while (jd != -1) {
|
| 1069 | 1069 |
if (comp(nodes[jd].prio, nodes[id].prio)) {
|
| 1070 | 1070 |
nodes[id].prio = nodes[jd].prio; |
| 1071 | 1071 |
nodes[id].item = nodes[jd].item; |
| 1072 | 1072 |
} |
| 1073 | 1073 |
jd = nodes[jd].next; |
| ... | ... |
@@ -1119,143 +1119,143 @@ |
| 1119 | 1119 |
void splice(int id, int jd) {
|
| 1120 | 1120 |
nodes[id].size += nodes[jd].size; |
| 1121 | 1121 |
nodes[nodes[id].right].next = nodes[jd].left; |
| 1122 | 1122 |
nodes[nodes[jd].left].prev = nodes[id].right; |
| 1123 | 1123 |
int kd = nodes[jd].left; |
| 1124 | 1124 |
while (kd != -1) {
|
| 1125 | 1125 |
nodes[kd].parent = id; |
| 1126 | 1126 |
kd = nodes[kd].next; |
| 1127 | 1127 |
} |
| 1128 | 1128 |
nodes[id].right = nodes[jd].right; |
| 1129 | 1129 |
} |
| 1130 | 1130 |
|
| 1131 | 1131 |
void split(int id, int jd) {
|
| 1132 | 1132 |
int kd = nodes[id].parent; |
| 1133 | 1133 |
nodes[kd].right = nodes[id].prev; |
| 1134 | 1134 |
nodes[nodes[id].prev].next = -1; |
| 1135 |
|
|
| 1135 |
|
|
| 1136 | 1136 |
nodes[jd].left = id; |
| 1137 | 1137 |
nodes[id].prev = -1; |
| 1138 | 1138 |
int num = 0; |
| 1139 | 1139 |
while (id != -1) {
|
| 1140 | 1140 |
nodes[id].parent = jd; |
| 1141 | 1141 |
nodes[jd].right = id; |
| 1142 | 1142 |
id = nodes[id].next; |
| 1143 | 1143 |
++num; |
| 1144 |
} |
|
| 1144 |
} |
|
| 1145 | 1145 |
nodes[kd].size -= num; |
| 1146 | 1146 |
nodes[jd].size = num; |
| 1147 | 1147 |
} |
| 1148 | 1148 |
|
| 1149 | 1149 |
void pushLeft(int id, int jd) {
|
| 1150 | 1150 |
nodes[id].size += 1; |
| 1151 | 1151 |
nodes[jd].next = nodes[id].left; |
| 1152 | 1152 |
nodes[jd].prev = -1; |
| 1153 | 1153 |
nodes[nodes[id].left].prev = jd; |
| 1154 | 1154 |
nodes[id].left = jd; |
| 1155 | 1155 |
nodes[jd].parent = id; |
| 1156 | 1156 |
} |
| 1157 | 1157 |
|
| 1158 | 1158 |
void popLeft(int id) {
|
| 1159 | 1159 |
nodes[id].size -= 1; |
| 1160 | 1160 |
int jd = nodes[id].left; |
| 1161 | 1161 |
nodes[nodes[jd].next].prev = -1; |
| 1162 | 1162 |
nodes[id].left = nodes[jd].next; |
| 1163 | 1163 |
} |
| 1164 | 1164 |
|
| 1165 | 1165 |
void repairLeft(int id) {
|
| 1166 | 1166 |
int jd = ~(classes[id].parent); |
| 1167 | 1167 |
while (nodes[jd].left != -1) {
|
| 1168 |
int kd = nodes[jd].left; |
|
| 1169 |
if (nodes[jd].size == 1) {
|
|
| 1170 |
if (nodes[jd].parent < 0) {
|
|
| 1171 |
classes[id].parent = ~kd; |
|
| 1172 |
classes[id].depth -= 1; |
|
| 1173 |
nodes[kd].parent = ~id; |
|
| 1174 |
deleteNode(jd); |
|
| 1175 |
jd = kd; |
|
| 1176 |
} else {
|
|
| 1177 |
int pd = nodes[jd].parent; |
|
| 1178 |
if (nodes[nodes[jd].next].size < cmax) {
|
|
| 1179 |
pushLeft(nodes[jd].next, nodes[jd].left); |
|
| 1180 |
if (less(nodes[jd].left, nodes[jd].next)) {
|
|
| 1181 |
nodes[nodes[jd].next].prio = nodes[nodes[jd].left].prio; |
|
| 1182 |
nodes[nodes[jd].next].item = nodes[nodes[jd].left].item; |
|
| 1183 |
} |
|
| 1184 |
popLeft(pd); |
|
| 1185 |
deleteNode(jd); |
|
| 1186 |
jd = pd; |
|
| 1187 |
} else {
|
|
| 1188 |
int ld = nodes[nodes[jd].next].left; |
|
| 1189 |
popLeft(nodes[jd].next); |
|
| 1190 |
pushRight(jd, ld); |
|
| 1191 |
if (less(ld, nodes[jd].left)) {
|
|
| 1192 |
nodes[jd].item = nodes[ld].item; |
|
| 1193 |
nodes[jd].prio = nodes[jd].prio; |
|
| 1194 |
} |
|
| 1195 |
if (nodes[nodes[jd].next].item == nodes[ld].item) {
|
|
| 1196 |
setPrio(nodes[jd].next); |
|
| 1197 |
} |
|
| 1198 |
jd = nodes[jd].left; |
|
| 1199 |
} |
|
| 1200 |
} |
|
| 1201 |
} else {
|
|
| 1202 |
jd = nodes[jd].left; |
|
| 1203 |
} |
|
| 1168 |
int kd = nodes[jd].left; |
|
| 1169 |
if (nodes[jd].size == 1) {
|
|
| 1170 |
if (nodes[jd].parent < 0) {
|
|
| 1171 |
classes[id].parent = ~kd; |
|
| 1172 |
classes[id].depth -= 1; |
|
| 1173 |
nodes[kd].parent = ~id; |
|
| 1174 |
deleteNode(jd); |
|
| 1175 |
jd = kd; |
|
| 1176 |
} else {
|
|
| 1177 |
int pd = nodes[jd].parent; |
|
| 1178 |
if (nodes[nodes[jd].next].size < cmax) {
|
|
| 1179 |
pushLeft(nodes[jd].next, nodes[jd].left); |
|
| 1180 |
if (less(nodes[jd].left, nodes[jd].next)) {
|
|
| 1181 |
nodes[nodes[jd].next].prio = nodes[nodes[jd].left].prio; |
|
| 1182 |
nodes[nodes[jd].next].item = nodes[nodes[jd].left].item; |
|
| 1183 |
} |
|
| 1184 |
popLeft(pd); |
|
| 1185 |
deleteNode(jd); |
|
| 1186 |
jd = pd; |
|
| 1187 |
} else {
|
|
| 1188 |
int ld = nodes[nodes[jd].next].left; |
|
| 1189 |
popLeft(nodes[jd].next); |
|
| 1190 |
pushRight(jd, ld); |
|
| 1191 |
if (less(ld, nodes[jd].left)) {
|
|
| 1192 |
nodes[jd].item = nodes[ld].item; |
|
| 1193 |
nodes[jd].prio = nodes[jd].prio; |
|
| 1194 |
} |
|
| 1195 |
if (nodes[nodes[jd].next].item == nodes[ld].item) {
|
|
| 1196 |
setPrio(nodes[jd].next); |
|
| 1197 |
} |
|
| 1198 |
jd = nodes[jd].left; |
|
| 1199 |
} |
|
| 1200 |
} |
|
| 1201 |
} else {
|
|
| 1202 |
jd = nodes[jd].left; |
|
| 1203 |
} |
|
| 1204 | 1204 |
} |
| 1205 |
} |
|
| 1205 |
} |
|
| 1206 | 1206 |
|
| 1207 | 1207 |
void repairRight(int id) {
|
| 1208 | 1208 |
int jd = ~(classes[id].parent); |
| 1209 | 1209 |
while (nodes[jd].right != -1) {
|
| 1210 |
int kd = nodes[jd].right; |
|
| 1211 |
if (nodes[jd].size == 1) {
|
|
| 1212 |
if (nodes[jd].parent < 0) {
|
|
| 1213 |
classes[id].parent = ~kd; |
|
| 1214 |
classes[id].depth -= 1; |
|
| 1215 |
nodes[kd].parent = ~id; |
|
| 1216 |
deleteNode(jd); |
|
| 1217 |
jd = kd; |
|
| 1218 |
} else {
|
|
| 1219 |
int pd = nodes[jd].parent; |
|
| 1220 |
if (nodes[nodes[jd].prev].size < cmax) {
|
|
| 1221 |
pushRight(nodes[jd].prev, nodes[jd].right); |
|
| 1222 |
if (less(nodes[jd].right, nodes[jd].prev)) {
|
|
| 1223 |
nodes[nodes[jd].prev].prio = nodes[nodes[jd].right].prio; |
|
| 1224 |
nodes[nodes[jd].prev].item = nodes[nodes[jd].right].item; |
|
| 1225 |
} |
|
| 1226 |
popRight(pd); |
|
| 1227 |
deleteNode(jd); |
|
| 1228 |
jd = pd; |
|
| 1229 |
} else {
|
|
| 1230 |
int ld = nodes[nodes[jd].prev].right; |
|
| 1231 |
popRight(nodes[jd].prev); |
|
| 1232 |
pushLeft(jd, ld); |
|
| 1233 |
if (less(ld, nodes[jd].right)) {
|
|
| 1234 |
nodes[jd].item = nodes[ld].item; |
|
| 1235 |
nodes[jd].prio = nodes[jd].prio; |
|
| 1236 |
} |
|
| 1237 |
if (nodes[nodes[jd].prev].item == nodes[ld].item) {
|
|
| 1238 |
setPrio(nodes[jd].prev); |
|
| 1239 |
} |
|
| 1240 |
jd = nodes[jd].right; |
|
| 1241 |
} |
|
| 1242 |
} |
|
| 1243 |
} else {
|
|
| 1244 |
jd = nodes[jd].right; |
|
| 1245 |
} |
|
| 1210 |
int kd = nodes[jd].right; |
|
| 1211 |
if (nodes[jd].size == 1) {
|
|
| 1212 |
if (nodes[jd].parent < 0) {
|
|
| 1213 |
classes[id].parent = ~kd; |
|
| 1214 |
classes[id].depth -= 1; |
|
| 1215 |
nodes[kd].parent = ~id; |
|
| 1216 |
deleteNode(jd); |
|
| 1217 |
jd = kd; |
|
| 1218 |
} else {
|
|
| 1219 |
int pd = nodes[jd].parent; |
|
| 1220 |
if (nodes[nodes[jd].prev].size < cmax) {
|
|
| 1221 |
pushRight(nodes[jd].prev, nodes[jd].right); |
|
| 1222 |
if (less(nodes[jd].right, nodes[jd].prev)) {
|
|
| 1223 |
nodes[nodes[jd].prev].prio = nodes[nodes[jd].right].prio; |
|
| 1224 |
nodes[nodes[jd].prev].item = nodes[nodes[jd].right].item; |
|
| 1225 |
} |
|
| 1226 |
popRight(pd); |
|
| 1227 |
deleteNode(jd); |
|
| 1228 |
jd = pd; |
|
| 1229 |
} else {
|
|
| 1230 |
int ld = nodes[nodes[jd].prev].right; |
|
| 1231 |
popRight(nodes[jd].prev); |
|
| 1232 |
pushLeft(jd, ld); |
|
| 1233 |
if (less(ld, nodes[jd].right)) {
|
|
| 1234 |
nodes[jd].item = nodes[ld].item; |
|
| 1235 |
nodes[jd].prio = nodes[jd].prio; |
|
| 1236 |
} |
|
| 1237 |
if (nodes[nodes[jd].prev].item == nodes[ld].item) {
|
|
| 1238 |
setPrio(nodes[jd].prev); |
|
| 1239 |
} |
|
| 1240 |
jd = nodes[jd].right; |
|
| 1241 |
} |
|
| 1242 |
} |
|
| 1243 |
} else {
|
|
| 1244 |
jd = nodes[jd].right; |
|
| 1245 |
} |
|
| 1246 | 1246 |
} |
| 1247 | 1247 |
} |
| 1248 | 1248 |
|
| 1249 | 1249 |
|
| 1250 | 1250 |
bool less(int id, int jd) const {
|
| 1251 | 1251 |
return comp(nodes[id].prio, nodes[jd].prio); |
| 1252 | 1252 |
} |
| 1253 | 1253 |
|
| 1254 | 1254 |
bool equal(int id, int jd) const {
|
| 1255 | 1255 |
return !less(id, jd) && !less(jd, id); |
| 1256 | 1256 |
} |
| 1257 | 1257 |
|
| 1258 | 1258 |
|
| 1259 | 1259 |
public: |
| 1260 | 1260 |
|
| 1261 | 1261 |
/// \brief Returns true when the given class is alive. |
| ... | ... |
@@ -1263,89 +1263,89 @@ |
| 1263 | 1263 |
/// Returns true when the given class is alive, ie. the class is |
| 1264 | 1264 |
/// not nested into other class. |
| 1265 | 1265 |
bool alive(int cls) const {
|
| 1266 | 1266 |
return classes[cls].parent < 0; |
| 1267 | 1267 |
} |
| 1268 | 1268 |
|
| 1269 | 1269 |
/// \brief Returns true when the given class is trivial. |
| 1270 | 1270 |
/// |
| 1271 | 1271 |
/// Returns true when the given class is trivial, ie. the class |
| 1272 | 1272 |
/// contains just one item directly. |
| 1273 | 1273 |
bool trivial(int cls) const {
|
| 1274 | 1274 |
return classes[cls].left == -1; |
| 1275 | 1275 |
} |
| 1276 | 1276 |
|
| 1277 | 1277 |
/// \brief Constructs the union-find. |
| 1278 | 1278 |
/// |
| 1279 |
/// Constructs the union-find. |
|
| 1279 |
/// Constructs the union-find. |
|
| 1280 | 1280 |
/// \brief _index The index map of the union-find. The data |
| 1281 | 1281 |
/// structure uses internally for store references. |
| 1282 |
HeapUnionFind(ItemIntMap& _index) |
|
| 1283 |
: index(_index), first_class(-1), |
|
| 1284 |
|
|
| 1282 |
HeapUnionFind(ItemIntMap& _index) |
|
| 1283 |
: index(_index), first_class(-1), |
|
| 1284 |
first_free_class(-1), first_free_node(-1) {}
|
|
| 1285 | 1285 |
|
| 1286 | 1286 |
/// \brief Insert a new node into a new component. |
| 1287 | 1287 |
/// |
| 1288 | 1288 |
/// Insert a new node into a new component. |
| 1289 | 1289 |
/// \param item The item of the new node. |
| 1290 | 1290 |
/// \param prio The priority of the new node. |
| 1291 | 1291 |
/// \return The class id of the one-item-heap. |
| 1292 | 1292 |
int insert(const Item& item, const Value& prio) {
|
| 1293 | 1293 |
int id = newNode(); |
| 1294 | 1294 |
nodes[id].item = item; |
| 1295 | 1295 |
nodes[id].prio = prio; |
| 1296 | 1296 |
nodes[id].size = 0; |
| 1297 | 1297 |
|
| 1298 | 1298 |
nodes[id].prev = -1; |
| 1299 | 1299 |
nodes[id].next = -1; |
| 1300 | 1300 |
|
| 1301 | 1301 |
nodes[id].left = -1; |
| 1302 | 1302 |
nodes[id].right = -1; |
| 1303 | 1303 |
|
| 1304 | 1304 |
nodes[id].item = item; |
| 1305 | 1305 |
index[item] = id; |
| 1306 |
|
|
| 1306 |
|
|
| 1307 | 1307 |
int class_id = newClass(); |
| 1308 | 1308 |
classes[class_id].parent = ~id; |
| 1309 | 1309 |
classes[class_id].depth = 0; |
| 1310 | 1310 |
|
| 1311 | 1311 |
classes[class_id].left = -1; |
| 1312 | 1312 |
classes[class_id].right = -1; |
| 1313 |
|
|
| 1313 |
|
|
| 1314 | 1314 |
if (first_class != -1) {
|
| 1315 | 1315 |
classes[first_class].prev = class_id; |
| 1316 | 1316 |
} |
| 1317 | 1317 |
classes[class_id].next = first_class; |
| 1318 | 1318 |
classes[class_id].prev = -1; |
| 1319 | 1319 |
first_class = class_id; |
| 1320 | 1320 |
|
| 1321 | 1321 |
nodes[id].parent = ~class_id; |
| 1322 |
|
|
| 1322 |
|
|
| 1323 | 1323 |
return class_id; |
| 1324 | 1324 |
} |
| 1325 | 1325 |
|
| 1326 | 1326 |
/// \brief The class of the item. |
| 1327 | 1327 |
/// |
| 1328 | 1328 |
/// \return The alive class id of the item, which is not nested into |
| 1329 | 1329 |
/// other classes. |
| 1330 | 1330 |
/// |
| 1331 | 1331 |
/// The time complexity is O(log(n)). |
| 1332 | 1332 |
int find(const Item& item) const {
|
| 1333 | 1333 |
return findClass(index[item]); |
| 1334 | 1334 |
} |
| 1335 |
|
|
| 1335 |
|
|
| 1336 | 1336 |
/// \brief Joins the classes. |
| 1337 | 1337 |
/// |
| 1338 | 1338 |
/// The current function joins the given classes. The parameter is |
| 1339 | 1339 |
/// an STL range which should be contains valid class ids. The |
| 1340 | 1340 |
/// time complexity is O(log(n)*k) where n is the overall number |
| 1341 | 1341 |
/// of the joined nodes and k is the number of classes. |
| 1342 | 1342 |
/// \return The class of the joined classes. |
| 1343 | 1343 |
/// \pre The range should contain at least two class ids. |
| 1344 | 1344 |
template <typename Iterator> |
| 1345 | 1345 |
int join(Iterator begin, Iterator end) {
|
| 1346 | 1346 |
std::vector<int> cs; |
| 1347 | 1347 |
for (Iterator it = begin; it != end; ++it) {
|
| 1348 | 1348 |
cs.push_back(*it); |
| 1349 | 1349 |
} |
| 1350 | 1350 |
|
| 1351 | 1351 |
int class_id = newClass(); |
| ... | ... |
@@ -1358,39 +1358,39 @@ |
| 1358 | 1358 |
classes[class_id].prev = -1; |
| 1359 | 1359 |
first_class = class_id; |
| 1360 | 1360 |
|
| 1361 | 1361 |
classes[class_id].depth = classes[cs[0]].depth; |
| 1362 | 1362 |
classes[class_id].parent = classes[cs[0]].parent; |
| 1363 | 1363 |
nodes[~(classes[class_id].parent)].parent = ~class_id; |
| 1364 | 1364 |
|
| 1365 | 1365 |
int l = cs[0]; |
| 1366 | 1366 |
|
| 1367 | 1367 |
classes[class_id].left = l; |
| 1368 | 1368 |
classes[class_id].right = l; |
| 1369 | 1369 |
|
| 1370 | 1370 |
if (classes[l].next != -1) {
|
| 1371 | 1371 |
classes[classes[l].next].prev = classes[l].prev; |
| 1372 | 1372 |
} |
| 1373 | 1373 |
classes[classes[l].prev].next = classes[l].next; |
| 1374 |
|
|
| 1374 |
|
|
| 1375 | 1375 |
classes[l].prev = -1; |
| 1376 | 1376 |
classes[l].next = -1; |
| 1377 | 1377 |
|
| 1378 | 1378 |
classes[l].depth = leftNode(l); |
| 1379 | 1379 |
classes[l].parent = class_id; |
| 1380 |
|
|
| 1380 |
|
|
| 1381 | 1381 |
} |
| 1382 | 1382 |
|
| 1383 | 1383 |
{ // merging of heap
|
| 1384 | 1384 |
int l = class_id; |
| 1385 | 1385 |
for (int ci = 1; ci < int(cs.size()); ++ci) {
|
| 1386 | 1386 |
int r = cs[ci]; |
| 1387 | 1387 |
int rln = leftNode(r); |
| 1388 | 1388 |
if (classes[l].depth > classes[r].depth) {
|
| 1389 | 1389 |
int id = ~(classes[l].parent); |
| 1390 | 1390 |
for (int i = classes[r].depth + 1; i < classes[l].depth; ++i) {
|
| 1391 | 1391 |
id = nodes[id].right; |
| 1392 | 1392 |
} |
| 1393 | 1393 |
while (id >= 0 && nodes[id].size == cmax) {
|
| 1394 | 1394 |
int new_id = newNode(); |
| 1395 | 1395 |
int right_id = nodes[id].right; |
| 1396 | 1396 |
|
| ... | ... |
@@ -1442,65 +1442,65 @@ |
| 1442 | 1442 |
pushLeft(new_id, ~(classes[l].parent)); |
| 1443 | 1443 |
setPrio(new_id); |
| 1444 | 1444 |
|
| 1445 | 1445 |
id = nodes[id].parent; |
| 1446 | 1446 |
classes[l].parent = ~new_id; |
| 1447 | 1447 |
|
| 1448 | 1448 |
} |
| 1449 | 1449 |
if (id < 0) {
|
| 1450 | 1450 |
int new_parent = newNode(); |
| 1451 | 1451 |
nodes[new_parent].next = -1; |
| 1452 | 1452 |
nodes[new_parent].prev = -1; |
| 1453 | 1453 |
nodes[new_parent].parent = ~l; |
| 1454 | 1454 |
|
| 1455 | 1455 |
push(new_parent, ~(classes[r].parent)); |
| 1456 | 1456 |
pushLeft(new_parent, ~(classes[l].parent)); |
| 1457 | 1457 |
setPrio(new_parent); |
| 1458 |
|
|
| 1458 |
|
|
| 1459 | 1459 |
classes[r].parent = ~new_parent; |
| 1460 | 1460 |
classes[r].depth += 1; |
| 1461 | 1461 |
} else {
|
| 1462 | 1462 |
pushLeft(id, ~(classes[l].parent)); |
| 1463 | 1463 |
while (id >= 0 && less(~(classes[l].parent), id)) {
|
| 1464 | 1464 |
nodes[id].prio = nodes[~(classes[l].parent)].prio; |
| 1465 | 1465 |
nodes[id].item = nodes[~(classes[l].parent)].item; |
| 1466 | 1466 |
id = nodes[id].parent; |
| 1467 | 1467 |
} |
| 1468 | 1468 |
} |
| 1469 | 1469 |
nodes[~(classes[r].parent)].parent = ~l; |
| 1470 | 1470 |
classes[l].parent = classes[r].parent; |
| 1471 | 1471 |
classes[l].depth = classes[r].depth; |
| 1472 | 1472 |
} else {
|
| 1473 |
if (classes[l].depth != 0 && |
|
| 1474 |
nodes[~(classes[l].parent)].size + |
|
| 1473 |
if (classes[l].depth != 0 && |
|
| 1474 |
nodes[~(classes[l].parent)].size + |
|
| 1475 | 1475 |
nodes[~(classes[r].parent)].size <= cmax) {
|
| 1476 | 1476 |
splice(~(classes[l].parent), ~(classes[r].parent)); |
| 1477 | 1477 |
deleteNode(~(classes[r].parent)); |
| 1478 | 1478 |
if (less(~(classes[r].parent), ~(classes[l].parent))) {
|
| 1479 |
nodes[~(classes[l].parent)].prio = |
|
| 1479 |
nodes[~(classes[l].parent)].prio = |
|
| 1480 | 1480 |
nodes[~(classes[r].parent)].prio; |
| 1481 |
nodes[~(classes[l].parent)].item = |
|
| 1481 |
nodes[~(classes[l].parent)].item = |
|
| 1482 | 1482 |
nodes[~(classes[r].parent)].item; |
| 1483 | 1483 |
} |
| 1484 | 1484 |
} else {
|
| 1485 | 1485 |
int new_parent = newNode(); |
| 1486 | 1486 |
nodes[new_parent].next = nodes[new_parent].prev = -1; |
| 1487 | 1487 |
push(new_parent, ~(classes[l].parent)); |
| 1488 | 1488 |
pushRight(new_parent, ~(classes[r].parent)); |
| 1489 | 1489 |
setPrio(new_parent); |
| 1490 |
|
|
| 1490 |
|
|
| 1491 | 1491 |
classes[l].parent = ~new_parent; |
| 1492 | 1492 |
classes[l].depth += 1; |
| 1493 | 1493 |
nodes[new_parent].parent = ~l; |
| 1494 | 1494 |
} |
| 1495 | 1495 |
} |
| 1496 | 1496 |
if (classes[r].next != -1) {
|
| 1497 | 1497 |
classes[classes[r].next].prev = classes[r].prev; |
| 1498 | 1498 |
} |
| 1499 | 1499 |
classes[classes[r].prev].next = classes[r].next; |
| 1500 | 1500 |
|
| 1501 | 1501 |
classes[r].prev = classes[l].right; |
| 1502 | 1502 |
classes[classes[l].right].next = r; |
| 1503 | 1503 |
classes[l].right = r; |
| 1504 | 1504 |
classes[r].parent = l; |
| 1505 | 1505 |
|
| 1506 | 1506 |
classes[r].next = -1; |
| ... | ... |
@@ -1529,268 +1529,268 @@ |
| 1529 | 1529 |
|
| 1530 | 1530 |
classes[l].parent = classes[id].parent; |
| 1531 | 1531 |
classes[l].depth = classes[id].depth; |
| 1532 | 1532 |
|
| 1533 | 1533 |
nodes[~(classes[l].parent)].parent = ~l; |
| 1534 | 1534 |
|
| 1535 | 1535 |
*out++ = l; |
| 1536 | 1536 |
|
| 1537 | 1537 |
while (l != -1) {
|
| 1538 | 1538 |
cs.push_back(l); |
| 1539 | 1539 |
l = classes[l].next; |
| 1540 | 1540 |
} |
| 1541 | 1541 |
|
| 1542 | 1542 |
classes[classes[id].right].next = first_class; |
| 1543 | 1543 |
classes[first_class].prev = classes[id].right; |
| 1544 | 1544 |
first_class = classes[id].left; |
| 1545 |
|
|
| 1545 |
|
|
| 1546 | 1546 |
if (classes[id].next != -1) {
|
| 1547 | 1547 |
classes[classes[id].next].prev = classes[id].prev; |
| 1548 | 1548 |
} |
| 1549 | 1549 |
classes[classes[id].prev].next = classes[id].next; |
| 1550 |
|
|
| 1550 |
|
|
| 1551 | 1551 |
deleteClass(id); |
| 1552 | 1552 |
} |
| 1553 | 1553 |
|
| 1554 | 1554 |
{
|
| 1555 | 1555 |
for (int i = 1; i < int(cs.size()); ++i) {
|
| 1556 | 1556 |
int l = classes[cs[i]].depth; |
| 1557 | 1557 |
while (nodes[nodes[l].parent].left == l) {
|
| 1558 | 1558 |
l = nodes[l].parent; |
| 1559 | 1559 |
} |
| 1560 |
int r = l; |
|
| 1560 |
int r = l; |
|
| 1561 | 1561 |
while (nodes[l].parent >= 0) {
|
| 1562 | 1562 |
l = nodes[l].parent; |
| 1563 | 1563 |
int new_node = newNode(); |
| 1564 | 1564 |
|
| 1565 | 1565 |
nodes[new_node].prev = -1; |
| 1566 | 1566 |
nodes[new_node].next = -1; |
| 1567 | 1567 |
|
| 1568 | 1568 |
split(r, new_node); |
| 1569 | 1569 |
pushAfter(l, new_node); |
| 1570 | 1570 |
setPrio(l); |
| 1571 | 1571 |
setPrio(new_node); |
| 1572 | 1572 |
r = new_node; |
| 1573 | 1573 |
} |
| 1574 | 1574 |
classes[cs[i]].parent = ~r; |
| 1575 | 1575 |
classes[cs[i]].depth = classes[~(nodes[l].parent)].depth; |
| 1576 | 1576 |
nodes[r].parent = ~cs[i]; |
| 1577 | 1577 |
|
| 1578 | 1578 |
nodes[l].next = -1; |
| 1579 | 1579 |
nodes[r].prev = -1; |
| 1580 | 1580 |
|
| 1581 | 1581 |
repairRight(~(nodes[l].parent)); |
| 1582 | 1582 |
repairLeft(cs[i]); |
| 1583 |
|
|
| 1583 |
|
|
| 1584 | 1584 |
*out++ = cs[i]; |
| 1585 | 1585 |
} |
| 1586 | 1586 |
} |
| 1587 | 1587 |
} |
| 1588 | 1588 |
|
| 1589 | 1589 |
/// \brief Gives back the priority of the current item. |
| 1590 | 1590 |
/// |
| 1591 | 1591 |
/// \return Gives back the priority of the current item. |
| 1592 | 1592 |
const Value& operator[](const Item& item) const {
|
| 1593 | 1593 |
return nodes[index[item]].prio; |
| 1594 | 1594 |
} |
| 1595 | 1595 |
|
| 1596 | 1596 |
/// \brief Sets the priority of the current item. |
| 1597 | 1597 |
/// |
| 1598 | 1598 |
/// Sets the priority of the current item. |
| 1599 | 1599 |
void set(const Item& item, const Value& prio) {
|
| 1600 | 1600 |
if (comp(prio, nodes[index[item]].prio)) {
|
| 1601 | 1601 |
decrease(item, prio); |
| 1602 | 1602 |
} else if (!comp(prio, nodes[index[item]].prio)) {
|
| 1603 | 1603 |
increase(item, prio); |
| 1604 | 1604 |
} |
| 1605 | 1605 |
} |
| 1606 |
|
|
| 1606 |
|
|
| 1607 | 1607 |
/// \brief Increase the priority of the current item. |
| 1608 | 1608 |
/// |
| 1609 | 1609 |
/// Increase the priority of the current item. |
| 1610 | 1610 |
void increase(const Item& item, const Value& prio) {
|
| 1611 | 1611 |
int id = index[item]; |
| 1612 | 1612 |
int kd = nodes[id].parent; |
| 1613 | 1613 |
nodes[id].prio = prio; |
| 1614 | 1614 |
while (kd >= 0 && nodes[kd].item == item) {
|
| 1615 | 1615 |
setPrio(kd); |
| 1616 | 1616 |
kd = nodes[kd].parent; |
| 1617 | 1617 |
} |
| 1618 | 1618 |
} |
| 1619 | 1619 |
|
| 1620 | 1620 |
/// \brief Increase the priority of the current item. |
| 1621 | 1621 |
/// |
| 1622 | 1622 |
/// Increase the priority of the current item. |
| 1623 | 1623 |
void decrease(const Item& item, const Value& prio) {
|
| 1624 | 1624 |
int id = index[item]; |
| 1625 | 1625 |
int kd = nodes[id].parent; |
| 1626 | 1626 |
nodes[id].prio = prio; |
| 1627 | 1627 |
while (kd >= 0 && less(id, kd)) {
|
| 1628 | 1628 |
nodes[kd].prio = prio; |
| 1629 | 1629 |
nodes[kd].item = item; |
| 1630 | 1630 |
kd = nodes[kd].parent; |
| 1631 | 1631 |
} |
| 1632 | 1632 |
} |
| 1633 |
|
|
| 1633 |
|
|
| 1634 | 1634 |
/// \brief Gives back the minimum priority of the class. |
| 1635 | 1635 |
/// |
| 1636 | 1636 |
/// \return Gives back the minimum priority of the class. |
| 1637 | 1637 |
const Value& classPrio(int cls) const {
|
| 1638 | 1638 |
return nodes[~(classes[cls].parent)].prio; |
| 1639 | 1639 |
} |
| 1640 | 1640 |
|
| 1641 | 1641 |
/// \brief Gives back the minimum priority item of the class. |
| 1642 | 1642 |
/// |
| 1643 | 1643 |
/// \return Gives back the minimum priority item of the class. |
| 1644 | 1644 |
const Item& classTop(int cls) const {
|
| 1645 | 1645 |
return nodes[~(classes[cls].parent)].item; |
| 1646 | 1646 |
} |
| 1647 | 1647 |
|
| 1648 | 1648 |
/// \brief Gives back a representant item of the class. |
| 1649 |
/// |
|
| 1649 |
/// |
|
| 1650 | 1650 |
/// The representant is indpendent from the priorities of the |
| 1651 |
/// items. |
|
| 1651 |
/// items. |
|
| 1652 | 1652 |
/// \return Gives back a representant item of the class. |
| 1653 | 1653 |
const Item& classRep(int id) const {
|
| 1654 | 1654 |
int parent = classes[id].parent; |
| 1655 | 1655 |
return nodes[parent >= 0 ? classes[id].depth : leftNode(id)].item; |
| 1656 | 1656 |
} |
| 1657 | 1657 |
|
| 1658 | 1658 |
/// \brief Lemon style iterator for the items of a class. |
| 1659 | 1659 |
/// |
| 1660 | 1660 |
/// ClassIt is a lemon style iterator for the components. It iterates |
| 1661 | 1661 |
/// on the items of a class. By example if you want to iterate on |
| 1662 | 1662 |
/// each items of each classes then you may write the next code. |
| 1663 | 1663 |
///\code |
| 1664 | 1664 |
/// for (ClassIt cit(huf); cit != INVALID; ++cit) {
|
| 1665 | 1665 |
/// std::cout << "Class: "; |
| 1666 | 1666 |
/// for (ItemIt iit(huf, cit); iit != INVALID; ++iit) {
|
| 1667 | 1667 |
/// std::cout << toString(iit) << ' ' << std::endl; |
| 1668 | 1668 |
/// } |
| 1669 | 1669 |
/// std::cout << std::endl; |
| 1670 | 1670 |
/// } |
| 1671 | 1671 |
///\endcode |
| 1672 | 1672 |
class ItemIt {
|
| 1673 | 1673 |
private: |
| 1674 | 1674 |
|
| 1675 | 1675 |
const HeapUnionFind* _huf; |
| 1676 | 1676 |
int _id, _lid; |
| 1677 |
|
|
| 1677 |
|
|
| 1678 | 1678 |
public: |
| 1679 | 1679 |
|
| 1680 |
/// \brief Default constructor |
|
| 1680 |
/// \brief Default constructor |
|
| 1681 | 1681 |
/// |
| 1682 |
/// Default constructor |
|
| 1682 |
/// Default constructor |
|
| 1683 | 1683 |
ItemIt() {}
|
| 1684 | 1684 |
|
| 1685 | 1685 |
ItemIt(const HeapUnionFind& huf, int cls) : _huf(&huf) {
|
| 1686 | 1686 |
int id = cls; |
| 1687 | 1687 |
int parent = _huf->classes[id].parent; |
| 1688 | 1688 |
if (parent >= 0) {
|
| 1689 | 1689 |
_id = _huf->classes[id].depth; |
| 1690 | 1690 |
if (_huf->classes[id].next != -1) {
|
| 1691 | 1691 |
_lid = _huf->classes[_huf->classes[id].next].depth; |
| 1692 | 1692 |
} else {
|
| 1693 | 1693 |
_lid = -1; |
| 1694 | 1694 |
} |
| 1695 | 1695 |
} else {
|
| 1696 | 1696 |
_id = _huf->leftNode(id); |
| 1697 | 1697 |
_lid = -1; |
| 1698 |
} |
|
| 1698 |
} |
|
| 1699 | 1699 |
} |
| 1700 |
|
|
| 1700 |
|
|
| 1701 | 1701 |
/// \brief Increment operator |
| 1702 | 1702 |
/// |
| 1703 | 1703 |
/// It steps to the next item in the class. |
| 1704 | 1704 |
ItemIt& operator++() {
|
| 1705 | 1705 |
_id = _huf->nextNode(_id); |
| 1706 | 1706 |
return *this; |
| 1707 | 1707 |
} |
| 1708 | 1708 |
|
| 1709 | 1709 |
/// \brief Conversion operator |
| 1710 | 1710 |
/// |
| 1711 | 1711 |
/// It converts the iterator to the current item. |
| 1712 | 1712 |
operator const Item&() const {
|
| 1713 | 1713 |
return _huf->nodes[_id].item; |
| 1714 | 1714 |
} |
| 1715 |
|
|
| 1715 |
|
|
| 1716 | 1716 |
/// \brief Equality operator |
| 1717 | 1717 |
/// |
| 1718 | 1718 |
/// Equality operator |
| 1719 |
bool operator==(const ItemIt& i) {
|
|
| 1719 |
bool operator==(const ItemIt& i) {
|
|
| 1720 | 1720 |
return i._id == _id; |
| 1721 | 1721 |
} |
| 1722 | 1722 |
|
| 1723 | 1723 |
/// \brief Inequality operator |
| 1724 | 1724 |
/// |
| 1725 | 1725 |
/// Inequality operator |
| 1726 |
bool operator!=(const ItemIt& i) {
|
|
| 1726 |
bool operator!=(const ItemIt& i) {
|
|
| 1727 | 1727 |
return i._id != _id; |
| 1728 | 1728 |
} |
| 1729 | 1729 |
|
| 1730 | 1730 |
/// \brief Equality operator |
| 1731 | 1731 |
/// |
| 1732 | 1732 |
/// Equality operator |
| 1733 |
bool operator==(Invalid) {
|
|
| 1733 |
bool operator==(Invalid) {
|
|
| 1734 | 1734 |
return _id == _lid; |
| 1735 | 1735 |
} |
| 1736 | 1736 |
|
| 1737 | 1737 |
/// \brief Inequality operator |
| 1738 | 1738 |
/// |
| 1739 | 1739 |
/// Inequality operator |
| 1740 |
bool operator!=(Invalid) {
|
|
| 1740 |
bool operator!=(Invalid) {
|
|
| 1741 | 1741 |
return _id != _lid; |
| 1742 | 1742 |
} |
| 1743 |
|
|
| 1743 |
|
|
| 1744 | 1744 |
}; |
| 1745 | 1745 |
|
| 1746 | 1746 |
/// \brief Class iterator |
| 1747 | 1747 |
/// |
| 1748 |
/// The iterator stores |
|
| 1748 |
/// The iterator stores |
|
| 1749 | 1749 |
class ClassIt {
|
| 1750 | 1750 |
private: |
| 1751 | 1751 |
|
| 1752 | 1752 |
const HeapUnionFind* _huf; |
| 1753 | 1753 |
int _id; |
| 1754 | 1754 |
|
| 1755 | 1755 |
public: |
| 1756 | 1756 |
|
| 1757 |
ClassIt(const HeapUnionFind& huf) |
|
| 1757 |
ClassIt(const HeapUnionFind& huf) |
|
| 1758 | 1758 |
: _huf(&huf), _id(huf.first_class) {}
|
| 1759 | 1759 |
|
| 1760 |
ClassIt(const HeapUnionFind& huf, int cls) |
|
| 1760 |
ClassIt(const HeapUnionFind& huf, int cls) |
|
| 1761 | 1761 |
: _huf(&huf), _id(huf.classes[cls].left) {}
|
| 1762 | 1762 |
|
| 1763 | 1763 |
ClassIt(Invalid) : _huf(0), _id(-1) {}
|
| 1764 |
|
|
| 1764 |
|
|
| 1765 | 1765 |
const ClassIt& operator++() {
|
| 1766 | 1766 |
_id = _huf->classes[_id].next; |
| 1767 |
|
|
| 1767 |
return *this; |
|
| 1768 | 1768 |
} |
| 1769 | 1769 |
|
| 1770 | 1770 |
/// \brief Equality operator |
| 1771 | 1771 |
/// |
| 1772 | 1772 |
/// Equality operator |
| 1773 |
bool operator==(const ClassIt& i) {
|
|
| 1773 |
bool operator==(const ClassIt& i) {
|
|
| 1774 | 1774 |
return i._id == _id; |
| 1775 | 1775 |
} |
| 1776 | 1776 |
|
| 1777 | 1777 |
/// \brief Inequality operator |
| 1778 | 1778 |
/// |
| 1779 | 1779 |
/// Inequality operator |
| 1780 |
bool operator!=(const ClassIt& i) {
|
|
| 1780 |
bool operator!=(const ClassIt& i) {
|
|
| 1781 | 1781 |
return i._id != _id; |
| 1782 |
} |
|
| 1783 |
|
|
| 1782 |
} |
|
| 1783 |
|
|
| 1784 | 1784 |
operator int() const {
|
| 1785 |
|
|
| 1785 |
return _id; |
|
| 1786 | 1786 |
} |
| 1787 |
|
|
| 1787 |
|
|
| 1788 | 1788 |
}; |
| 1789 | 1789 |
|
| 1790 | 1790 |
}; |
| 1791 | 1791 |
|
| 1792 | 1792 |
//! @} |
| 1793 | 1793 |
|
| 1794 | 1794 |
} //namespace lemon |
| 1795 | 1795 |
|
| 1796 | 1796 |
#endif //LEMON_UNION_FIND_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/concepts/digraph.h> |
| 20 | 20 |
#include <lemon/smart_graph.h> |
| 21 | 21 |
#include <lemon/list_graph.h> |
| 22 | 22 |
#include <lemon/bfs.h> |
| 23 | 23 |
#include <lemon/path.h> |
| 24 | 24 |
|
| 25 | 25 |
#include "graph_test.h" |
| 26 | 26 |
#include "test_tools.h" |
| 27 | 27 |
|
| 28 | 28 |
using namespace lemon; |
| 29 | 29 |
|
| 30 |
void checkBfsCompile() |
|
| 30 |
void checkBfsCompile() |
|
| 31 | 31 |
{
|
| 32 | 32 |
typedef concepts::Digraph Digraph; |
| 33 | 33 |
typedef Bfs<Digraph> BType; |
| 34 |
|
|
| 34 |
|
|
| 35 | 35 |
Digraph G; |
| 36 | 36 |
Digraph::Node n; |
| 37 | 37 |
Digraph::Arc e; |
| 38 | 38 |
int l; |
| 39 | 39 |
bool b; |
| 40 | 40 |
BType::DistMap d(G); |
| 41 | 41 |
BType::PredMap p(G); |
| 42 | 42 |
// BType::PredNodeMap pn(G); |
| 43 |
|
|
| 43 |
|
|
| 44 | 44 |
BType bfs_test(G); |
| 45 |
|
|
| 45 |
|
|
| 46 | 46 |
bfs_test.run(n); |
| 47 |
|
|
| 47 |
|
|
| 48 | 48 |
l = bfs_test.dist(n); |
| 49 | 49 |
e = bfs_test.predArc(n); |
| 50 | 50 |
n = bfs_test.predNode(n); |
| 51 | 51 |
d = bfs_test.distMap(); |
| 52 | 52 |
p = bfs_test.predMap(); |
| 53 | 53 |
// pn = bfs_test.predNodeMap(); |
| 54 | 54 |
b = bfs_test.reached(n); |
| 55 | 55 |
|
| 56 | 56 |
Path<Digraph> pp = bfs_test.path(n); |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
void checkBfsFunctionCompile() |
|
| 59 |
void checkBfsFunctionCompile() |
|
| 60 | 60 |
{
|
| 61 | 61 |
typedef int VType; |
| 62 | 62 |
typedef concepts::Digraph Digraph; |
| 63 | 63 |
typedef Digraph::Arc Arc; |
| 64 | 64 |
typedef Digraph::Node Node; |
| 65 |
|
|
| 65 |
|
|
| 66 | 66 |
Digraph g; |
| 67 | 67 |
bfs(g,Node()).run(); |
| 68 | 68 |
bfs(g).source(Node()).run(); |
| 69 | 69 |
bfs(g) |
| 70 | 70 |
.predMap(concepts::WriteMap<Node,Arc>()) |
| 71 | 71 |
.distMap(concepts::WriteMap<Node,VType>()) |
| 72 | 72 |
.reachedMap(concepts::ReadWriteMap<Node,bool>()) |
| 73 | 73 |
.processedMap(concepts::WriteMap<Node,bool>()) |
| 74 | 74 |
.run(Node()); |
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 | 77 |
template <class Digraph> |
| 78 | 78 |
void checkBfs() {
|
| 79 | 79 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 80 | 80 |
|
| 81 | 81 |
Digraph G; |
| 82 | 82 |
Node s, t; |
| 83 | 83 |
PetStruct<Digraph> ps = addPetersen(G, 5); |
| 84 |
|
|
| 84 |
|
|
| 85 | 85 |
s=ps.outer[2]; |
| 86 | 86 |
t=ps.inner[0]; |
| 87 |
|
|
| 87 |
|
|
| 88 | 88 |
Bfs<Digraph> bfs_test(G); |
| 89 | 89 |
bfs_test.run(s); |
| 90 |
|
|
| 90 |
|
|
| 91 | 91 |
check(bfs_test.dist(t)==3,"Bfs found a wrong path." << bfs_test.dist(t)); |
| 92 | 92 |
|
| 93 | 93 |
Path<Digraph> p = bfs_test.path(t); |
| 94 | 94 |
check(p.length()==3,"path() found a wrong path."); |
| 95 | 95 |
check(checkPath(G, p),"path() found a wrong path."); |
| 96 | 96 |
check(pathSource(G, p) == s,"path() found a wrong path."); |
| 97 | 97 |
check(pathTarget(G, p) == t,"path() found a wrong path."); |
| 98 |
|
|
| 98 |
|
|
| 99 | 99 |
|
| 100 | 100 |
for(ArcIt e(G); e==INVALID; ++e) {
|
| 101 | 101 |
Node u=G.source(e); |
| 102 | 102 |
Node v=G.target(e); |
| 103 | 103 |
check( !bfs_test.reached(u) || |
| 104 |
(bfs_test.dist(v) > bfs_test.dist(u)+1), |
|
| 105 |
"Wrong output."); |
|
| 104 |
(bfs_test.dist(v) > bfs_test.dist(u)+1), |
|
| 105 |
"Wrong output."); |
|
| 106 | 106 |
} |
| 107 | 107 |
|
| 108 | 108 |
for(NodeIt v(G); v==INVALID; ++v) {
|
| 109 | 109 |
check(bfs_test.reached(v),"Each node should be reached."); |
| 110 | 110 |
if ( bfs_test.predArc(v)!=INVALID ) {
|
| 111 | 111 |
Arc e=bfs_test.predArc(v); |
| 112 | 112 |
Node u=G.source(e); |
| 113 | 113 |
check(u==bfs_test.predNode(v),"Wrong tree."); |
| 114 | 114 |
check(bfs_test.dist(v) - bfs_test.dist(u) == 1, |
| 115 |
"Wrong distance. Difference: " |
|
| 116 |
<< std::abs(bfs_test.dist(v) - bfs_test.dist(u) |
|
| 117 |
|
|
| 115 |
"Wrong distance. Difference: " |
|
| 116 |
<< std::abs(bfs_test.dist(v) - bfs_test.dist(u) |
|
| 117 |
- 1)); |
|
| 118 | 118 |
} |
| 119 | 119 |
} |
| 120 | 120 |
} |
| 121 | 121 |
|
| 122 | 122 |
int main() |
| 123 | 123 |
{
|
| 124 | 124 |
checkBfs<ListDigraph>(); |
| 125 | 125 |
checkBfs<SmartDigraph>(); |
| 126 | 126 |
return 0; |
| 127 | 127 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/counter.h> |
| ... | ... |
@@ -62,30 +62,30 @@ |
| 62 | 62 |
void counterTest() {
|
| 63 | 63 |
MyCounter c("Main Counter: ");
|
| 64 | 64 |
c++; |
| 65 | 65 |
typename MyCounter::SubCounter d(c, "SubCounter: "); |
| 66 | 66 |
d++; |
| 67 | 67 |
typename MyCounter::SubCounter::NoSubCounter e(d, "SubSubCounter: "); |
| 68 | 68 |
e++; |
| 69 | 69 |
d+=3; |
| 70 | 70 |
c-=4; |
| 71 | 71 |
e-=2; |
| 72 | 72 |
c.reset(2); |
| 73 | 73 |
c.reset(); |
| 74 | 74 |
} |
| 75 | 75 |
|
| 76 | 76 |
void init(std::vector<int>& v) {
|
| 77 | 77 |
v[0] = 10; v[1] = 60; v[2] = 20; v[3] = 90; v[4] = 100; |
| 78 |
v[5] = 80; v[6] = 40; v[7] = 30; v[8] = 50; v[9] = 70; |
|
| 78 |
v[5] = 80; v[6] = 40; v[7] = 30; v[8] = 50; v[9] = 70; |
|
| 79 | 79 |
} |
| 80 | 80 |
|
| 81 | 81 |
int main() |
| 82 | 82 |
{
|
| 83 | 83 |
counterTest<Counter>(); |
| 84 | 84 |
counterTest<NoCounter>(); |
| 85 |
|
|
| 85 |
|
|
| 86 | 86 |
std::vector<int> x(10); |
| 87 | 87 |
init(x); bubbleSort(x); |
| 88 | 88 |
init(x); insertionSort(x); |
| 89 | 89 |
|
| 90 | 90 |
return 0; |
| 91 | 91 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/concepts/digraph.h> |
| 20 | 20 |
#include <lemon/smart_graph.h> |
| 21 | 21 |
#include <lemon/list_graph.h> |
| 22 | 22 |
#include <lemon/dfs.h> |
| 23 | 23 |
#include <lemon/path.h> |
| 24 | 24 |
|
| 25 | 25 |
#include "graph_test.h" |
| 26 | 26 |
#include "test_tools.h" |
| 27 | 27 |
|
| 28 | 28 |
using namespace lemon; |
| 29 | 29 |
|
| 30 |
void checkDfsCompile() |
|
| 30 |
void checkDfsCompile() |
|
| 31 | 31 |
{
|
| 32 | 32 |
typedef concepts::Digraph Digraph; |
| 33 | 33 |
typedef Dfs<Digraph> DType; |
| 34 |
|
|
| 34 |
|
|
| 35 | 35 |
Digraph G; |
| 36 | 36 |
Digraph::Node n; |
| 37 | 37 |
Digraph::Arc e; |
| 38 | 38 |
int l; |
| 39 | 39 |
bool b; |
| 40 | 40 |
DType::DistMap d(G); |
| 41 | 41 |
DType::PredMap p(G); |
| 42 | 42 |
// DType::PredNodeMap pn(G); |
| 43 |
|
|
| 43 |
|
|
| 44 | 44 |
DType dfs_test(G); |
| 45 |
|
|
| 45 |
|
|
| 46 | 46 |
dfs_test.run(n); |
| 47 |
|
|
| 47 |
|
|
| 48 | 48 |
l = dfs_test.dist(n); |
| 49 | 49 |
e = dfs_test.predArc(n); |
| 50 | 50 |
n = dfs_test.predNode(n); |
| 51 | 51 |
d = dfs_test.distMap(); |
| 52 | 52 |
p = dfs_test.predMap(); |
| 53 | 53 |
// pn = dfs_test.predNodeMap(); |
| 54 | 54 |
b = dfs_test.reached(n); |
| 55 | 55 |
|
| 56 | 56 |
Path<Digraph> pp = dfs_test.path(n); |
| 57 | 57 |
} |
| 58 | 58 |
|
| 59 |
void checkDfsFunctionCompile() |
|
| 59 |
void checkDfsFunctionCompile() |
|
| 60 | 60 |
{
|
| 61 | 61 |
typedef int VType; |
| 62 | 62 |
typedef concepts::Digraph Digraph; |
| 63 | 63 |
typedef Digraph::Arc Arc; |
| 64 | 64 |
typedef Digraph::Node Node; |
| 65 |
|
|
| 65 |
|
|
| 66 | 66 |
Digraph g; |
| 67 | 67 |
dfs(g,Node()).run(); |
| 68 | 68 |
dfs(g).source(Node()).run(); |
| 69 | 69 |
dfs(g) |
| 70 | 70 |
.predMap(concepts::WriteMap<Node,Arc>()) |
| 71 | 71 |
.distMap(concepts::WriteMap<Node,VType>()) |
| 72 | 72 |
.reachedMap(concepts::ReadWriteMap<Node,bool>()) |
| 73 | 73 |
.processedMap(concepts::WriteMap<Node,bool>()) |
| 74 |
.run(Node()); |
|
| 74 |
.run(Node()); |
|
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 | 77 |
template <class Digraph> |
| 78 | 78 |
void checkDfs() {
|
| 79 | 79 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 80 | 80 |
|
| 81 | 81 |
Digraph G; |
| 82 | 82 |
Node s, t; |
| 83 | 83 |
PetStruct<Digraph> ps = addPetersen(G, 5); |
| 84 |
|
|
| 84 |
|
|
| 85 | 85 |
s=ps.outer[2]; |
| 86 | 86 |
t=ps.inner[0]; |
| 87 |
|
|
| 87 |
|
|
| 88 | 88 |
Dfs<Digraph> dfs_test(G); |
| 89 |
dfs_test.run(s); |
|
| 90 |
|
|
| 89 |
dfs_test.run(s); |
|
| 90 |
|
|
| 91 | 91 |
Path<Digraph> p = dfs_test.path(t); |
| 92 | 92 |
check(p.length() == dfs_test.dist(t),"path() found a wrong path."); |
| 93 | 93 |
check(checkPath(G, p),"path() found a wrong path."); |
| 94 | 94 |
check(pathSource(G, p) == s,"path() found a wrong path."); |
| 95 | 95 |
check(pathTarget(G, p) == t,"path() found a wrong path."); |
| 96 |
|
|
| 96 |
|
|
| 97 | 97 |
for(NodeIt v(G); v!=INVALID; ++v) {
|
| 98 | 98 |
check(dfs_test.reached(v),"Each node should be reached."); |
| 99 | 99 |
if ( dfs_test.predArc(v)!=INVALID ) {
|
| 100 | 100 |
Arc e=dfs_test.predArc(v); |
| 101 | 101 |
Node u=G.source(e); |
| 102 | 102 |
check(u==dfs_test.predNode(v),"Wrong tree."); |
| 103 | 103 |
check(dfs_test.dist(v) - dfs_test.dist(u) == 1, |
| 104 |
"Wrong distance. (" << dfs_test.dist(u) << "->"
|
|
| 105 |
<<dfs_test.dist(v) << ')'); |
|
| 104 |
"Wrong distance. (" << dfs_test.dist(u) << "->"
|
|
| 105 |
<<dfs_test.dist(v) << ')'); |
|
| 106 | 106 |
} |
| 107 | 107 |
} |
| 108 | 108 |
} |
| 109 | 109 |
|
| 110 | 110 |
int main() |
| 111 | 111 |
{
|
| 112 | 112 |
checkDfs<ListDigraph>(); |
| 113 | 113 |
checkDfs<SmartDigraph>(); |
| 114 | 114 |
return 0; |
| 115 | 115 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/concepts/digraph.h> |
| 20 | 20 |
#include <lemon/list_graph.h> |
| 21 | 21 |
#include <lemon/smart_graph.h> |
| 22 | 22 |
//#include <lemon/full_graph.h> |
| 23 | 23 |
//#include <lemon/hypercube_graph.h> |
| 24 | 24 |
|
| 25 | 25 |
#include "test_tools.h" |
| 26 | 26 |
#include "graph_test.h" |
| 27 | 27 |
#include "graph_maps_test.h" |
| 28 | 28 |
|
| 29 | 29 |
using namespace lemon; |
| 30 | 30 |
using namespace lemon::concepts; |
| 31 | 31 |
|
| 32 | 32 |
void check_concepts() {
|
| 33 | 33 |
{ // Checking digraph components
|
| 34 | 34 |
checkConcept<BaseDigraphComponent, BaseDigraphComponent >(); |
| 35 | 35 |
|
| 36 |
checkConcept<IDableDigraphComponent<>, |
|
| 36 |
checkConcept<IDableDigraphComponent<>, |
|
| 37 | 37 |
IDableDigraphComponent<> >(); |
| 38 | 38 |
|
| 39 |
checkConcept<IterableDigraphComponent<>, |
|
| 39 |
checkConcept<IterableDigraphComponent<>, |
|
| 40 | 40 |
IterableDigraphComponent<> >(); |
| 41 | 41 |
|
| 42 |
checkConcept<MappableDigraphComponent<>, |
|
| 42 |
checkConcept<MappableDigraphComponent<>, |
|
| 43 | 43 |
MappableDigraphComponent<> >(); |
| 44 | 44 |
} |
| 45 | 45 |
{ // Checking skeleton digraph
|
| 46 | 46 |
checkConcept<Digraph, Digraph>(); |
| 47 | 47 |
} |
| 48 | 48 |
{ // Checking ListDigraph
|
| 49 | 49 |
checkConcept<Digraph, ListDigraph>(); |
| 50 | 50 |
checkConcept<AlterableDigraphComponent<>, ListDigraph>(); |
| 51 | 51 |
checkConcept<ExtendableDigraphComponent<>, ListDigraph>(); |
| 52 | 52 |
checkConcept<ClearableDigraphComponent<>, ListDigraph>(); |
| 53 | 53 |
checkConcept<ErasableDigraphComponent<>, ListDigraph>(); |
| 54 | 54 |
checkDigraphIterators<ListDigraph>(); |
| 55 | 55 |
} |
| 56 | 56 |
{ // Checking SmartDigraph
|
| 57 | 57 |
checkConcept<Digraph, SmartDigraph>(); |
| 58 | 58 |
checkConcept<AlterableDigraphComponent<>, SmartDigraph>(); |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/concepts/digraph.h> |
| 20 | 20 |
#include <lemon/smart_graph.h> |
| 21 | 21 |
#include <lemon/list_graph.h> |
| 22 | 22 |
#include <lemon/graph_utils.h> |
| 23 | 23 |
#include <lemon/dijkstra.h> |
| 24 | 24 |
#include <lemon/path.h> |
| 25 | 25 |
|
| 26 | 26 |
#include "graph_test.h" |
| 27 | 27 |
#include "test_tools.h" |
| 28 | 28 |
|
| 29 | 29 |
using namespace lemon; |
| 30 | 30 |
|
| 31 |
void checkDijkstraCompile() |
|
| 31 |
void checkDijkstraCompile() |
|
| 32 | 32 |
{
|
| 33 | 33 |
typedef int VType; |
| 34 | 34 |
typedef concepts::Digraph Digraph; |
| 35 | 35 |
typedef concepts::ReadMap<Digraph::Arc,VType> LengthMap; |
| 36 | 36 |
typedef Dijkstra<Digraph, LengthMap> DType; |
| 37 |
|
|
| 37 |
|
|
| 38 | 38 |
Digraph G; |
| 39 | 39 |
Digraph::Node n; |
| 40 | 40 |
Digraph::Arc e; |
| 41 | 41 |
VType l; |
| 42 | 42 |
bool b; |
| 43 | 43 |
DType::DistMap d(G); |
| 44 | 44 |
DType::PredMap p(G); |
| 45 | 45 |
// DType::PredNodeMap pn(G); |
| 46 | 46 |
LengthMap length; |
| 47 | 47 |
|
| 48 | 48 |
DType dijkstra_test(G,length); |
| 49 | 49 |
|
| 50 | 50 |
dijkstra_test.run(n); |
| 51 | 51 |
|
| 52 | 52 |
l = dijkstra_test.dist(n); |
| 53 | 53 |
e = dijkstra_test.predArc(n); |
| 54 | 54 |
n = dijkstra_test.predNode(n); |
| 55 | 55 |
d = dijkstra_test.distMap(); |
| 56 | 56 |
p = dijkstra_test.predMap(); |
| 57 | 57 |
// pn = dijkstra_test.predNodeMap(); |
| 58 | 58 |
b = dijkstra_test.reached(n); |
| 59 | 59 |
|
| 60 | 60 |
Path<Digraph> pp = dijkstra_test.path(n); |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
void checkDijkstraFunctionCompile() |
|
| 63 |
void checkDijkstraFunctionCompile() |
|
| 64 | 64 |
{
|
| 65 | 65 |
typedef int VType; |
| 66 | 66 |
typedef concepts::Digraph Digraph; |
| 67 | 67 |
typedef Digraph::Arc Arc; |
| 68 | 68 |
typedef Digraph::Node Node; |
| 69 | 69 |
typedef concepts::ReadMap<Digraph::Arc,VType> LengthMap; |
| 70 |
|
|
| 70 |
|
|
| 71 | 71 |
Digraph g; |
| 72 | 72 |
dijkstra(g,LengthMap(),Node()).run(); |
| 73 | 73 |
dijkstra(g,LengthMap()).source(Node()).run(); |
| 74 | 74 |
dijkstra(g,LengthMap()) |
| 75 | 75 |
.predMap(concepts::WriteMap<Node,Arc>()) |
| 76 | 76 |
.distMap(concepts::WriteMap<Node,VType>()) |
| 77 | 77 |
.run(Node()); |
| 78 | 78 |
} |
| 79 | 79 |
|
| 80 | 80 |
template <class Digraph> |
| 81 |
void checkDijkstra() {
|
|
| 81 |
void checkDijkstra() {
|
|
| 82 | 82 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 83 | 83 |
typedef typename Digraph::template ArcMap<int> LengthMap; |
| 84 | 84 |
|
| 85 | 85 |
Digraph G; |
| 86 | 86 |
Node s, t; |
| 87 | 87 |
LengthMap length(G); |
| 88 | 88 |
PetStruct<Digraph> ps = addPetersen(G, 5); |
| 89 |
|
|
| 89 |
|
|
| 90 | 90 |
for(int i=0;i<5;i++) {
|
| 91 | 91 |
length[ps.outcir[i]]=4; |
| 92 | 92 |
length[ps.incir[i]]=1; |
| 93 | 93 |
length[ps.chords[i]]=10; |
| 94 | 94 |
} |
| 95 | 95 |
s=ps.outer[0]; |
| 96 | 96 |
t=ps.inner[1]; |
| 97 |
|
|
| 98 |
Dijkstra<Digraph, LengthMap> |
|
| 99 |
|
|
| 97 |
|
|
| 98 |
Dijkstra<Digraph, LengthMap> |
|
| 99 |
dijkstra_test(G, length); |
|
| 100 | 100 |
dijkstra_test.run(s); |
| 101 |
|
|
| 101 |
|
|
| 102 | 102 |
check(dijkstra_test.dist(t)==13,"Dijkstra found a wrong path."); |
| 103 | 103 |
|
| 104 | 104 |
Path<Digraph> p = dijkstra_test.path(t); |
| 105 | 105 |
check(p.length()==4,"getPath() found a wrong path."); |
| 106 | 106 |
check(checkPath(G, p),"path() found a wrong path."); |
| 107 | 107 |
check(pathSource(G, p) == s,"path() found a wrong path."); |
| 108 | 108 |
check(pathTarget(G, p) == t,"path() found a wrong path."); |
| 109 |
|
|
| 109 |
|
|
| 110 | 110 |
for(ArcIt e(G); e!=INVALID; ++e) {
|
| 111 | 111 |
Node u=G.source(e); |
| 112 | 112 |
Node v=G.target(e); |
| 113 | 113 |
check( !dijkstra_test.reached(u) || (dijkstra_test.dist(v) - dijkstra_test.dist(u) <= length[e]), |
| 114 |
|
|
| 114 |
"dist(target)-dist(source)-arc_length= " << dijkstra_test.dist(v) - dijkstra_test.dist(u) - length[e]); |
|
| 115 | 115 |
} |
| 116 | 116 |
|
| 117 | 117 |
for(NodeIt v(G); v!=INVALID; ++v){
|
| 118 | 118 |
check(dijkstra_test.reached(v),"Each node should be reached."); |
| 119 | 119 |
if ( dijkstra_test.predArc(v)!=INVALID ) {
|
| 120 | 120 |
Arc e=dijkstra_test.predArc(v); |
| 121 | 121 |
Node u=G.source(e); |
| 122 | 122 |
check(u==dijkstra_test.predNode(v),"Wrong tree."); |
| 123 | 123 |
check(dijkstra_test.dist(v) - dijkstra_test.dist(u) == length[e], |
| 124 |
|
|
| 124 |
"Wrong distance! Difference: " << std::abs(dijkstra_test.dist(v) - dijkstra_test.dist(u) - length[e])); |
|
| 125 | 125 |
} |
| 126 | 126 |
} |
| 127 |
|
|
| 127 |
|
|
| 128 | 128 |
{
|
| 129 | 129 |
NullMap<Node,Arc> myPredMap; |
| 130 | 130 |
dijkstra(G,length).predMap(myPredMap).run(s); |
| 131 | 131 |
} |
| 132 | 132 |
} |
| 133 | 133 |
|
| 134 | 134 |
int main() {
|
| 135 | 135 |
checkDijkstra<ListDigraph>(); |
| 136 | 136 |
checkDijkstra<SmartDigraph>(); |
| 137 | 137 |
return 0; |
| 138 | 138 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/dim2.h> |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <iostream> |
| ... | ... |
@@ -45,34 +45,34 @@ |
| 45 | 45 |
|
| 46 | 46 |
void fixme_disable() {
|
| 47 | 47 |
LEMON_FIXME("fixme_disable() is fixme!");
|
| 48 | 48 |
} |
| 49 | 49 |
|
| 50 | 50 |
void check_assertion_disable() {
|
| 51 | 51 |
no_assertion_text_disable(); |
| 52 | 52 |
assertion_text_disable(); |
| 53 | 53 |
fixme_disable(); |
| 54 | 54 |
} |
| 55 | 55 |
#undef LEMON_DISABLE_ASSERTS |
| 56 | 56 |
|
| 57 | 57 |
//checking custom assert handler |
| 58 | 58 |
#define LEMON_ASSERT_CUSTOM |
| 59 | 59 |
|
| 60 | 60 |
static int cnt = 0; |
| 61 |
void my_assert_handler(const char*, int, const char*, |
|
| 62 |
const char*, const char*) {
|
|
| 61 |
void my_assert_handler(const char*, int, const char*, |
|
| 62 |
const char*, const char*) {
|
|
| 63 | 63 |
++cnt; |
| 64 | 64 |
} |
| 65 | 65 |
|
| 66 | 66 |
#define LEMON_CUSTOM_ASSERT_HANDLER my_assert_handler |
| 67 | 67 |
#include <lemon/assert.h> |
| 68 | 68 |
|
| 69 | 69 |
void no_assertion_text_custom() {
|
| 70 | 70 |
LEMON_ASSERT(true, "This is a fault message"); |
| 71 | 71 |
} |
| 72 | 72 |
|
| 73 | 73 |
void assertion_text_custom() {
|
| 74 | 74 |
LEMON_ASSERT(false, "This is a fault message"); |
| 75 | 75 |
} |
| 76 | 76 |
|
| 77 | 77 |
void fixme_custom() {
|
| 78 | 78 |
LEMON_FIXME("fixme_custom() is fixme!");
|
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/smart_graph.h> |
| ... | ... |
@@ -109,33 +109,33 @@ |
| 109 | 109 |
SmartGraph::Node node = from.addNode(); |
| 110 | 110 |
fnv.push_back(node); |
| 111 | 111 |
fnm[node] = i * i; |
| 112 | 112 |
if (i == 0) fn = node; |
| 113 | 113 |
} |
| 114 | 114 |
|
| 115 | 115 |
for (int i = 0; i < nn; ++i) {
|
| 116 | 116 |
for (int j = 0; j < nn; ++j) {
|
| 117 | 117 |
SmartGraph::Edge edge = from.addEdge(fnv[i], fnv[j]); |
| 118 | 118 |
fem[edge] = i * i + j * j; |
| 119 | 119 |
fam[from.direct(edge, true)] = i + j * j; |
| 120 | 120 |
fam[from.direct(edge, false)] = i * i + j; |
| 121 | 121 |
if (i == 0 && j == 0) fa = from.direct(edge, true); |
| 122 | 122 |
if (i == 0 && j == 0) fe = edge; |
| 123 | 123 |
} |
| 124 | 124 |
} |
| 125 |
|
|
| 125 |
|
|
| 126 | 126 |
ListGraph to; |
| 127 | 127 |
ListGraph::NodeMap<int> tnm(to); |
| 128 | 128 |
ListGraph::ArcMap<int> tam(to); |
| 129 | 129 |
ListGraph::EdgeMap<int> tem(to); |
| 130 | 130 |
ListGraph::Node tn; |
| 131 | 131 |
ListGraph::Arc ta; |
| 132 | 132 |
ListGraph::Edge te; |
| 133 | 133 |
|
| 134 | 134 |
SmartGraph::NodeMap<ListGraph::Node> nr(from); |
| 135 | 135 |
SmartGraph::ArcMap<ListGraph::Arc> ar(from); |
| 136 | 136 |
SmartGraph::EdgeMap<ListGraph::Edge> er(from); |
| 137 | 137 |
|
| 138 | 138 |
ListGraph::NodeMap<SmartGraph::Node> ncr(to); |
| 139 | 139 |
ListGraph::ArcMap<SmartGraph::Arc> acr(to); |
| 140 | 140 |
ListGraph::EdgeMap<SmartGraph::Edge> ecr(to); |
| 141 | 141 |
|
| ... | ... |
@@ -147,46 +147,46 @@ |
| 147 | 147 |
|
| 148 | 148 |
for (SmartGraph::NodeIt it(from); it != INVALID; ++it) {
|
| 149 | 149 |
check(ncr[nr[it]] == it, "Wrong copy."); |
| 150 | 150 |
check(fnm[it] == tnm[nr[it]], "Wrong copy."); |
| 151 | 151 |
} |
| 152 | 152 |
|
| 153 | 153 |
for (SmartGraph::ArcIt it(from); it != INVALID; ++it) {
|
| 154 | 154 |
check(acr[ar[it]] == it, "Wrong copy."); |
| 155 | 155 |
check(fam[it] == tam[ar[it]], "Wrong copy."); |
| 156 | 156 |
check(nr[from.source(it)] == to.source(ar[it]), "Wrong copy."); |
| 157 | 157 |
check(nr[from.target(it)] == to.target(ar[it]), "Wrong copy."); |
| 158 | 158 |
} |
| 159 | 159 |
|
| 160 | 160 |
for (SmartGraph::EdgeIt it(from); it != INVALID; ++it) {
|
| 161 | 161 |
check(ecr[er[it]] == it, "Wrong copy."); |
| 162 | 162 |
check(fem[it] == tem[er[it]], "Wrong copy."); |
| 163 |
check(nr[from.u(it)] == to.u(er[it]) || nr[from.u(it)] == to.v(er[it]), |
|
| 164 |
"Wrong copy."); |
|
| 165 |
check(nr[from.v(it)] == to.u(er[it]) || nr[from.v(it)] == to.v(er[it]), |
|
| 166 |
"Wrong copy."); |
|
| 167 |
check((from.u(it) != from.v(it)) == (to.u(er[it]) != to.v(er[it])), |
|
| 168 |
"Wrong copy."); |
|
| 163 |
check(nr[from.u(it)] == to.u(er[it]) || nr[from.u(it)] == to.v(er[it]), |
|
| 164 |
"Wrong copy."); |
|
| 165 |
check(nr[from.v(it)] == to.u(er[it]) || nr[from.v(it)] == to.v(er[it]), |
|
| 166 |
"Wrong copy."); |
|
| 167 |
check((from.u(it) != from.v(it)) == (to.u(er[it]) != to.v(er[it])), |
|
| 168 |
"Wrong copy."); |
|
| 169 | 169 |
} |
| 170 | 170 |
|
| 171 | 171 |
for (ListGraph::NodeIt it(to); it != INVALID; ++it) {
|
| 172 | 172 |
check(nr[ncr[it]] == it, "Wrong copy."); |
| 173 | 173 |
} |
| 174 | 174 |
|
| 175 | 175 |
for (ListGraph::ArcIt it(to); it != INVALID; ++it) {
|
| 176 | 176 |
check(ar[acr[it]] == it, "Wrong copy."); |
| 177 | 177 |
} |
| 178 | 178 |
for (ListGraph::EdgeIt it(to); it != INVALID; ++it) {
|
| 179 | 179 |
check(er[ecr[it]] == it, "Wrong copy."); |
| 180 | 180 |
} |
| 181 | 181 |
check(tn == nr[fn], "Wrong copy."); |
| 182 | 182 |
check(ta == ar[fa], "Wrong copy."); |
| 183 | 183 |
check(te == er[fe], "Wrong copy."); |
| 184 | 184 |
} |
| 185 | 185 |
|
| 186 | 186 |
|
| 187 | 187 |
int main() {
|
| 188 | 188 |
digraph_copy_test(); |
| 189 | 189 |
graph_copy_test(); |
| 190 | 190 |
|
| 191 |
return 0; |
|
| 191 |
return 0; |
|
| 192 | 192 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TEST_MAP_TEST_H |
| ... | ... |
@@ -58,87 +58,87 @@ |
| 58 | 58 |
template <typename Graph> |
| 59 | 59 |
void checkGraphArcMap() {
|
| 60 | 60 |
Graph graph; |
| 61 | 61 |
const int num = 16; |
| 62 | 62 |
|
| 63 | 63 |
typedef typename Graph::Node Node; |
| 64 | 64 |
typedef typename Graph::Arc Arc; |
| 65 | 65 |
|
| 66 | 66 |
std::vector<Node> nodes; |
| 67 | 67 |
for (int i = 0; i < num; ++i) {
|
| 68 | 68 |
nodes.push_back(graph.addNode()); |
| 69 | 69 |
} |
| 70 | 70 |
|
| 71 | 71 |
std::vector<Arc> arcs; |
| 72 | 72 |
for (int i = 0; i < num; ++i) {
|
| 73 | 73 |
for (int j = 0; j < i; ++j) {
|
| 74 |
|
|
| 74 |
arcs.push_back(graph.addArc(nodes[i], nodes[j])); |
|
| 75 | 75 |
} |
| 76 | 76 |
} |
| 77 | 77 |
|
| 78 | 78 |
typedef typename Graph::template ArcMap<int> IntArcMap; |
| 79 | 79 |
IntArcMap map(graph, 42); |
| 80 | 80 |
|
| 81 | 81 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 82 | 82 |
check(map[arcs[i]] == 42, "Wrong map constructor."); |
| 83 | 83 |
} |
| 84 | 84 |
|
| 85 | 85 |
for (int i = 0; i < num; ++i) {
|
| 86 | 86 |
for (int j = i + 1; j < num; ++j) {
|
| 87 |
arcs.push_back(graph.addArc(nodes[i], nodes[j])); |
|
| 88 |
map[arcs.back()] = 23; |
|
| 87 |
arcs.push_back(graph.addArc(nodes[i], nodes[j])); |
|
| 88 |
map[arcs.back()] = 23; |
|
| 89 | 89 |
check(map[arcs.back()] == 23, "Wrong operator[]."); |
| 90 | 90 |
} |
| 91 | 91 |
} |
| 92 | 92 |
map = constMap<Arc>(12); |
| 93 | 93 |
for (int i = 0; i < int(arcs.size()); ++i) {
|
| 94 | 94 |
check(map[arcs[i]] == 12, "Wrong map constructor."); |
| 95 | 95 |
} |
| 96 | 96 |
graph.clear(); |
| 97 | 97 |
arcs.clear(); |
| 98 | 98 |
} |
| 99 | 99 |
|
| 100 | 100 |
template <typename Graph> |
| 101 | 101 |
void checkGraphEdgeMap() {
|
| 102 | 102 |
Graph graph; |
| 103 | 103 |
const int num = 16; |
| 104 | 104 |
|
| 105 | 105 |
typedef typename Graph::Node Node; |
| 106 | 106 |
typedef typename Graph::Edge Edge; |
| 107 | 107 |
|
| 108 | 108 |
std::vector<Node> nodes; |
| 109 | 109 |
for (int i = 0; i < num; ++i) {
|
| 110 | 110 |
nodes.push_back(graph.addNode()); |
| 111 | 111 |
} |
| 112 | 112 |
|
| 113 | 113 |
std::vector<Edge> edges; |
| 114 | 114 |
for (int i = 0; i < num; ++i) {
|
| 115 | 115 |
for (int j = 0; j < i; ++j) {
|
| 116 |
|
|
| 116 |
edges.push_back(graph.addEdge(nodes[i], nodes[j])); |
|
| 117 | 117 |
} |
| 118 | 118 |
} |
| 119 | 119 |
|
| 120 | 120 |
typedef typename Graph::template EdgeMap<int> IntEdgeMap; |
| 121 | 121 |
IntEdgeMap map(graph, 42); |
| 122 | 122 |
|
| 123 | 123 |
for (int i = 0; i < int(edges.size()); ++i) {
|
| 124 | 124 |
check(map[edges[i]] == 42, "Wrong map constructor."); |
| 125 | 125 |
} |
| 126 | 126 |
|
| 127 | 127 |
for (int i = 0; i < num; ++i) {
|
| 128 | 128 |
for (int j = i + 1; j < num; ++j) {
|
| 129 |
edges.push_back(graph.addEdge(nodes[i], nodes[j])); |
|
| 130 |
map[edges.back()] = 23; |
|
| 129 |
edges.push_back(graph.addEdge(nodes[i], nodes[j])); |
|
| 130 |
map[edges.back()] = 23; |
|
| 131 | 131 |
check(map[edges.back()] == 23, "Wrong operator[]."); |
| 132 | 132 |
} |
| 133 | 133 |
} |
| 134 | 134 |
map = constMap<Edge>(12); |
| 135 | 135 |
for (int i = 0; i < int(edges.size()); ++i) {
|
| 136 | 136 |
check(map[edges[i]] == 12, "Wrong map constructor."); |
| 137 | 137 |
} |
| 138 | 138 |
graph.clear(); |
| 139 | 139 |
edges.clear(); |
| 140 | 140 |
} |
| 141 | 141 |
|
| 142 | 142 |
} |
| 143 | 143 |
|
| 144 | 144 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/concepts/graph.h> |
| 20 | 20 |
#include <lemon/list_graph.h> |
| 21 | 21 |
#include <lemon/smart_graph.h> |
| 22 | 22 |
// #include <lemon/full_graph.h> |
| 23 | 23 |
// #include <lemon/grid_graph.h> |
| 24 | 24 |
|
| 25 | 25 |
#include "test_tools.h" |
| 26 | 26 |
#include "graph_test.h" |
| 27 | 27 |
#include "graph_maps_test.h" |
| 28 | 28 |
|
| 29 | 29 |
using namespace lemon; |
| 30 | 30 |
using namespace lemon::concepts; |
| 31 | 31 |
|
| 32 | 32 |
void check_concepts() {
|
| 33 | 33 |
{ // Checking graph components
|
| 34 | 34 |
checkConcept<BaseGraphComponent, BaseGraphComponent >(); |
| 35 | 35 |
|
| 36 |
checkConcept<IDableGraphComponent<>, |
|
| 36 |
checkConcept<IDableGraphComponent<>, |
|
| 37 | 37 |
IDableGraphComponent<> >(); |
| 38 | 38 |
|
| 39 |
checkConcept<IterableGraphComponent<>, |
|
| 39 |
checkConcept<IterableGraphComponent<>, |
|
| 40 | 40 |
IterableGraphComponent<> >(); |
| 41 | 41 |
|
| 42 |
checkConcept<MappableGraphComponent<>, |
|
| 42 |
checkConcept<MappableGraphComponent<>, |
|
| 43 | 43 |
MappableGraphComponent<> >(); |
| 44 | 44 |
} |
| 45 | 45 |
{ // Checking skeleton graph
|
| 46 | 46 |
checkConcept<Graph, Graph>(); |
| 47 | 47 |
} |
| 48 | 48 |
{ // Checking ListGraph
|
| 49 | 49 |
checkConcept<Graph, ListGraph>(); |
| 50 | 50 |
checkConcept<AlterableGraphComponent<>, ListGraph>(); |
| 51 | 51 |
checkConcept<ExtendableGraphComponent<>, ListGraph>(); |
| 52 | 52 |
checkConcept<ClearableGraphComponent<>, ListGraph>(); |
| 53 | 53 |
checkConcept<ErasableGraphComponent<>, ListGraph>(); |
| 54 | 54 |
checkGraphIterators<ListGraph>(); |
| 55 | 55 |
} |
| 56 | 56 |
{ // Checking SmartGraph
|
| 57 | 57 |
checkConcept<Graph, SmartGraph>(); |
| 58 | 58 |
checkConcept<AlterableGraphComponent<>, SmartGraph>(); |
| ... | ... |
@@ -121,63 +121,63 @@ |
| 121 | 121 |
|
| 122 | 122 |
check(!g.valid(g.nodeFromId(-1)), "Wrong validity check"); |
| 123 | 123 |
check(!g.valid(g.edgeFromId(-1)), "Wrong validity check"); |
| 124 | 124 |
check(!g.valid(g.arcFromId(-1)), "Wrong validity check"); |
| 125 | 125 |
} |
| 126 | 126 |
|
| 127 | 127 |
// void checkGridGraph(const GridGraph& g, int w, int h) {
|
| 128 | 128 |
// check(g.width() == w, "Wrong width"); |
| 129 | 129 |
// check(g.height() == h, "Wrong height"); |
| 130 | 130 |
|
| 131 | 131 |
// for (int i = 0; i < w; ++i) {
|
| 132 | 132 |
// for (int j = 0; j < h; ++j) {
|
| 133 | 133 |
// check(g.col(g(i, j)) == i, "Wrong col"); |
| 134 | 134 |
// check(g.row(g(i, j)) == j, "Wrong row"); |
| 135 | 135 |
// } |
| 136 | 136 |
// } |
| 137 |
|
|
| 137 |
|
|
| 138 | 138 |
// for (int i = 0; i < w; ++i) {
|
| 139 | 139 |
// for (int j = 0; j < h - 1; ++j) {
|
| 140 | 140 |
// check(g.source(g.down(g(i, j))) == g(i, j), "Wrong down"); |
| 141 | 141 |
// check(g.target(g.down(g(i, j))) == g(i, j + 1), "Wrong down"); |
| 142 | 142 |
// } |
| 143 | 143 |
// check(g.down(g(i, h - 1)) == INVALID, "Wrong down"); |
| 144 | 144 |
// } |
| 145 | 145 |
|
| 146 | 146 |
// for (int i = 0; i < w; ++i) {
|
| 147 | 147 |
// for (int j = 1; j < h; ++j) {
|
| 148 | 148 |
// check(g.source(g.up(g(i, j))) == g(i, j), "Wrong up"); |
| 149 | 149 |
// check(g.target(g.up(g(i, j))) == g(i, j - 1), "Wrong up"); |
| 150 | 150 |
// } |
| 151 | 151 |
// check(g.up(g(i, 0)) == INVALID, "Wrong up"); |
| 152 | 152 |
// } |
| 153 | 153 |
|
| 154 | 154 |
// for (int j = 0; j < h; ++j) {
|
| 155 | 155 |
// for (int i = 0; i < w - 1; ++i) {
|
| 156 | 156 |
// check(g.source(g.right(g(i, j))) == g(i, j), "Wrong right"); |
| 157 |
// check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right"); |
|
| 157 |
// check(g.target(g.right(g(i, j))) == g(i + 1, j), "Wrong right"); |
|
| 158 | 158 |
// } |
| 159 |
// check(g.right(g(w - 1, j)) == INVALID, "Wrong right"); |
|
| 159 |
// check(g.right(g(w - 1, j)) == INVALID, "Wrong right"); |
|
| 160 | 160 |
// } |
| 161 | 161 |
|
| 162 | 162 |
// for (int j = 0; j < h; ++j) {
|
| 163 | 163 |
// for (int i = 1; i < w; ++i) {
|
| 164 | 164 |
// check(g.source(g.left(g(i, j))) == g(i, j), "Wrong left"); |
| 165 |
// check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left"); |
|
| 165 |
// check(g.target(g.left(g(i, j))) == g(i - 1, j), "Wrong left"); |
|
| 166 | 166 |
// } |
| 167 |
// check(g.left(g(0, j)) == INVALID, "Wrong left"); |
|
| 167 |
// check(g.left(g(0, j)) == INVALID, "Wrong left"); |
|
| 168 | 168 |
// } |
| 169 | 169 |
// } |
| 170 | 170 |
|
| 171 | 171 |
void check_graphs() {
|
| 172 | 172 |
{ // Checking ListGraph
|
| 173 | 173 |
checkGraph<ListGraph>(); |
| 174 | 174 |
checkGraphNodeMap<ListGraph>(); |
| 175 | 175 |
checkGraphEdgeMap<ListGraph>(); |
| 176 | 176 |
|
| 177 | 177 |
check_graph_validity_erase<ListGraph>(); |
| 178 | 178 |
} |
| 179 | 179 |
{ // Checking SmartGraph
|
| 180 | 180 |
checkGraph<SmartGraph>(); |
| 181 | 181 |
checkGraphNodeMap<SmartGraph>(); |
| 182 | 182 |
checkGraphEdgeMap<SmartGraph>(); |
| 183 | 183 |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TEST_GRAPH_TEST_H |
| ... | ... |
@@ -204,59 +204,59 @@ |
| 204 | 204 |
// Returns the nodes and edges of the generated graph. |
| 205 | 205 |
template<typename Graph> |
| 206 | 206 |
UPetStruct<Graph> addUPetersen(Graph &G,int num=5) |
| 207 | 207 |
{
|
| 208 | 208 |
UPetStruct<Graph> n; |
| 209 | 209 |
|
| 210 | 210 |
for(int i=0;i<num;i++) {
|
| 211 | 211 |
n.outer.push_back(G.addNode()); |
| 212 | 212 |
n.inner.push_back(G.addNode()); |
| 213 | 213 |
} |
| 214 | 214 |
|
| 215 | 215 |
for(int i=0;i<num;i++) {
|
| 216 | 216 |
n.chords.push_back(G.addEdge(n.outer[i],n.inner[i])); |
| 217 | 217 |
n.outcir.push_back(G.addEdge(n.outer[i],n.outer[(i+1)%num])); |
| 218 | 218 |
n.incir.push_back(G.addEdge(n.inner[i],n.inner[(i+2)%num])); |
| 219 | 219 |
} |
| 220 |
|
|
| 220 |
|
|
| 221 | 221 |
return n; |
| 222 | 222 |
} |
| 223 | 223 |
|
| 224 | 224 |
// Checks the undirected Petersen graph |
| 225 | 225 |
template<class Graph> |
| 226 | 226 |
void checkUndirPetersen(const Graph &G, int num = 5) |
| 227 | 227 |
{
|
| 228 | 228 |
typedef typename Graph::NodeIt NodeIt; |
| 229 | 229 |
|
| 230 | 230 |
checkGraphNodeList(G, 2 * num); |
| 231 | 231 |
checkGraphEdgeList(G, 3 * num); |
| 232 | 232 |
checkGraphArcList(G, 6 * num); |
| 233 | 233 |
|
| 234 | 234 |
for(NodeIt n(G);n!=INVALID;++n) {
|
| 235 | 235 |
checkGraphIncEdgeList(G, n, 3); |
| 236 | 236 |
} |
| 237 | 237 |
} |
| 238 | 238 |
|
| 239 | 239 |
template <class Digraph> |
| 240 | 240 |
void checkDigraph() {
|
| 241 | 241 |
const int num = 5; |
| 242 | 242 |
Digraph G; |
| 243 | 243 |
checkGraphNodeList(G, 0); |
| 244 | 244 |
checkGraphArcList(G, 0); |
| 245 | 245 |
addPetersen(G, num); |
| 246 | 246 |
bidirDigraph(G); |
| 247 | 247 |
checkBidirPetersen(G, num); |
| 248 | 248 |
} |
| 249 |
|
|
| 249 |
|
|
| 250 | 250 |
template <class Graph> |
| 251 | 251 |
void checkGraph() {
|
| 252 | 252 |
const int num = 5; |
| 253 | 253 |
Graph G; |
| 254 | 254 |
checkGraphNodeList(G, 0); |
| 255 | 255 |
checkGraphEdgeList(G, 0); |
| 256 | 256 |
addUPetersen(G, num); |
| 257 | 257 |
checkUndirPetersen(G, num); |
| 258 | 258 |
} |
| 259 | 259 |
|
| 260 | 260 |
} //namespace lemon |
| 261 | 261 |
|
| 262 | 262 |
#endif |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <cstdlib> |
| ... | ... |
@@ -127,73 +127,73 @@ |
| 127 | 127 |
++found[con]; |
| 128 | 128 |
check(found[con] <= 2, "The edge found more than twice."); |
| 129 | 129 |
} |
| 130 | 130 |
} |
| 131 | 131 |
} |
| 132 | 132 |
for (EdgeIt it(graph); it != INVALID; ++it) {
|
| 133 | 133 |
check( (graph.u(it) != graph.v(it) && found[it] == 2) || |
| 134 | 134 |
(graph.u(it) == graph.v(it) && found[it] == 1), |
| 135 | 135 |
"The edge is not found correctly."); |
| 136 | 136 |
} |
| 137 | 137 |
} |
| 138 | 138 |
|
| 139 | 139 |
template <class Digraph> |
| 140 | 140 |
void checkDeg() |
| 141 | 141 |
{
|
| 142 | 142 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 143 |
|
|
| 143 |
|
|
| 144 | 144 |
const int nodeNum = 10; |
| 145 | 145 |
const int arcNum = 100; |
| 146 | 146 |
Digraph digraph; |
| 147 | 147 |
InDegMap<Digraph> inDeg(digraph); |
| 148 | 148 |
OutDegMap<Digraph> outDeg(digraph); |
| 149 | 149 |
std::vector<Node> nodes(nodeNum); |
| 150 | 150 |
for (int i = 0; i < nodeNum; ++i) {
|
| 151 | 151 |
nodes[i] = digraph.addNode(); |
| 152 | 152 |
} |
| 153 | 153 |
std::vector<Arc> arcs(arcNum); |
| 154 | 154 |
for (int i = 0; i < arcNum; ++i) {
|
| 155 | 155 |
arcs[i] = digraph.addArc(nodes[rnd[nodeNum]], nodes[rnd[nodeNum]]); |
| 156 | 156 |
} |
| 157 | 157 |
for (int i = 0; i < nodeNum; ++i) {
|
| 158 |
check(inDeg[nodes[i]] == countInArcs(digraph, nodes[i]), |
|
| 158 |
check(inDeg[nodes[i]] == countInArcs(digraph, nodes[i]), |
|
| 159 | 159 |
"Wrong in degree map"); |
| 160 | 160 |
} |
| 161 | 161 |
for (int i = 0; i < nodeNum; ++i) {
|
| 162 |
check(outDeg[nodes[i]] == countOutArcs(digraph, nodes[i]), |
|
| 162 |
check(outDeg[nodes[i]] == countOutArcs(digraph, nodes[i]), |
|
| 163 | 163 |
"Wrong out degree map"); |
| 164 | 164 |
} |
| 165 | 165 |
} |
| 166 | 166 |
|
| 167 | 167 |
template <class Digraph> |
| 168 | 168 |
void checkSnapDeg() |
| 169 | 169 |
{
|
| 170 | 170 |
TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); |
| 171 | 171 |
|
| 172 | 172 |
Digraph g; |
| 173 | 173 |
Node n1=g.addNode(); |
| 174 | 174 |
Node n2=g.addNode(); |
| 175 |
|
|
| 175 |
|
|
| 176 | 176 |
InDegMap<Digraph> ind(g); |
| 177 |
|
|
| 177 |
|
|
| 178 | 178 |
g.addArc(n1,n2); |
| 179 |
|
|
| 179 |
|
|
| 180 | 180 |
typename Digraph::Snapshot snap(g); |
| 181 |
|
|
| 181 |
|
|
| 182 | 182 |
OutDegMap<Digraph> outd(g); |
| 183 |
|
|
| 183 |
|
|
| 184 | 184 |
check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value."); |
| 185 | 185 |
check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value."); |
| 186 | 186 |
|
| 187 | 187 |
g.addArc(n1,n2); |
| 188 | 188 |
g.addArc(n2,n1); |
| 189 | 189 |
|
| 190 | 190 |
check(ind[n1]==1 && ind[n2]==2, "Wrong InDegMap value."); |
| 191 | 191 |
check(outd[n1]==2 && outd[n2]==1, "Wrong OutDegMap value."); |
| 192 | 192 |
|
| 193 | 193 |
snap.restore(); |
| 194 | 194 |
|
| 195 | 195 |
check(ind[n1]==0 && ind[n2]==1, "Wrong InDegMap value."); |
| 196 | 196 |
check(outd[n1]==1 && outd[n2]==0, "Wrong OutDegMap value."); |
| 197 | 197 |
} |
| 198 | 198 |
|
| 199 | 199 |
int main() {
|
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <iostream> |
| ... | ... |
@@ -27,161 +27,161 @@ |
| 27 | 27 |
#include <lemon/smart_graph.h> |
| 28 | 28 |
|
| 29 | 29 |
#include <lemon/lgf_reader.h> |
| 30 | 30 |
#include <lemon/dijkstra.h> |
| 31 | 31 |
#include <lemon/maps.h> |
| 32 | 32 |
|
| 33 | 33 |
#include <lemon/bin_heap.h> |
| 34 | 34 |
|
| 35 | 35 |
#include "test_tools.h" |
| 36 | 36 |
|
| 37 | 37 |
using namespace lemon; |
| 38 | 38 |
using namespace lemon::concepts; |
| 39 | 39 |
|
| 40 | 40 |
typedef ListDigraph Digraph; |
| 41 | 41 |
DIGRAPH_TYPEDEFS(Digraph); |
| 42 | 42 |
|
| 43 |
char test_lgf[] = |
|
| 44 |
"@nodes\n" |
|
| 45 |
"label\n" |
|
| 46 |
"0\n" |
|
| 47 |
"1\n" |
|
| 48 |
"2\n" |
|
| 49 |
"3\n" |
|
| 50 |
"4\n" |
|
| 51 |
"5\n" |
|
| 52 |
"6\n" |
|
| 53 |
"7\n" |
|
| 54 |
"8\n" |
|
| 55 |
"9\n" |
|
| 56 |
"@arcs\n" |
|
| 57 |
" label capacity\n" |
|
| 58 |
"0 5 0 94\n" |
|
| 59 |
"3 9 1 11\n" |
|
| 60 |
"8 7 2 83\n" |
|
| 61 |
"1 2 3 94\n" |
|
| 62 |
"5 7 4 35\n" |
|
| 63 |
"7 4 5 84\n" |
|
| 64 |
"9 5 6 38\n" |
|
| 65 |
"0 4 7 96\n" |
|
| 66 |
"6 7 8 6\n" |
|
| 67 |
"3 1 9 27\n" |
|
| 68 |
"5 2 10 77\n" |
|
| 69 |
"5 6 11 69\n" |
|
| 70 |
"6 5 12 41\n" |
|
| 71 |
"4 6 13 70\n" |
|
| 72 |
"3 2 14 45\n" |
|
| 73 |
"7 9 15 93\n" |
|
| 74 |
"5 9 16 50\n" |
|
| 75 |
"9 0 17 94\n" |
|
| 76 |
"9 6 18 67\n" |
|
| 77 |
"0 9 19 86\n" |
|
| 78 |
"@attributes\n" |
|
| 43 |
char test_lgf[] = |
|
| 44 |
"@nodes\n" |
|
| 45 |
"label\n" |
|
| 46 |
"0\n" |
|
| 47 |
"1\n" |
|
| 48 |
"2\n" |
|
| 49 |
"3\n" |
|
| 50 |
"4\n" |
|
| 51 |
"5\n" |
|
| 52 |
"6\n" |
|
| 53 |
"7\n" |
|
| 54 |
"8\n" |
|
| 55 |
"9\n" |
|
| 56 |
"@arcs\n" |
|
| 57 |
" label capacity\n" |
|
| 58 |
"0 5 0 94\n" |
|
| 59 |
"3 9 1 11\n" |
|
| 60 |
"8 7 2 83\n" |
|
| 61 |
"1 2 3 94\n" |
|
| 62 |
"5 7 4 35\n" |
|
| 63 |
"7 4 5 84\n" |
|
| 64 |
"9 5 6 38\n" |
|
| 65 |
"0 4 7 96\n" |
|
| 66 |
"6 7 8 6\n" |
|
| 67 |
"3 1 9 27\n" |
|
| 68 |
"5 2 10 77\n" |
|
| 69 |
"5 6 11 69\n" |
|
| 70 |
"6 5 12 41\n" |
|
| 71 |
"4 6 13 70\n" |
|
| 72 |
"3 2 14 45\n" |
|
| 73 |
"7 9 15 93\n" |
|
| 74 |
"5 9 16 50\n" |
|
| 75 |
"9 0 17 94\n" |
|
| 76 |
"9 6 18 67\n" |
|
| 77 |
"0 9 19 86\n" |
|
| 78 |
"@attributes\n" |
|
| 79 | 79 |
"source 3\n"; |
| 80 | 80 |
|
| 81 | 81 |
int test_seq[] = { 2, 28, 19, 27, 33, 25, 13, 41, 10, 26, 1, 9, 4, 34};
|
| 82 | 82 |
int test_inc[] = {20, 28, 34, 16, 0, 46, 44, 0, 42, 32, 14, 8, 6, 37};
|
| 83 | 83 |
|
| 84 | 84 |
int test_len = sizeof(test_seq) / sizeof(test_seq[0]); |
| 85 | 85 |
|
| 86 | 86 |
template <typename Heap> |
| 87 | 87 |
void heapSortTest() {
|
| 88 | 88 |
RangeMap<int> map(test_len, -1); |
| 89 | 89 |
|
| 90 | 90 |
Heap heap(map); |
| 91 |
|
|
| 91 |
|
|
| 92 | 92 |
std::vector<int> v(test_len); |
| 93 | 93 |
|
| 94 | 94 |
for (int i = 0; i < test_len; ++i) {
|
| 95 | 95 |
v[i] = test_seq[i]; |
| 96 | 96 |
heap.push(i, v[i]); |
| 97 | 97 |
} |
| 98 | 98 |
std::sort(v.begin(), v.end()); |
| 99 | 99 |
for (int i = 0; i < test_len; ++i) {
|
| 100 | 100 |
check(v[i] == heap.prio() ,"Wrong order in heap sort."); |
| 101 | 101 |
heap.pop(); |
| 102 | 102 |
} |
| 103 | 103 |
} |
| 104 | 104 |
|
| 105 | 105 |
template <typename Heap> |
| 106 | 106 |
void heapIncreaseTest() {
|
| 107 | 107 |
RangeMap<int> map(test_len, -1); |
| 108 | 108 |
|
| 109 | 109 |
Heap heap(map); |
| 110 |
|
|
| 110 |
|
|
| 111 | 111 |
std::vector<int> v(test_len); |
| 112 | 112 |
|
| 113 | 113 |
for (int i = 0; i < test_len; ++i) {
|
| 114 | 114 |
v[i] = test_seq[i]; |
| 115 | 115 |
heap.push(i, v[i]); |
| 116 | 116 |
} |
| 117 | 117 |
for (int i = 0; i < test_len; ++i) {
|
| 118 | 118 |
v[i] += test_inc[i]; |
| 119 | 119 |
heap.increase(i, v[i]); |
| 120 | 120 |
} |
| 121 | 121 |
std::sort(v.begin(), v.end()); |
| 122 | 122 |
for (int i = 0; i < test_len; ++i) {
|
| 123 | 123 |
check(v[i] == heap.prio() ,"Wrong order in heap increase test."); |
| 124 | 124 |
heap.pop(); |
| 125 | 125 |
} |
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 | 128 |
|
| 129 | 129 |
|
| 130 | 130 |
template <typename Heap> |
| 131 |
void dijkstraHeapTest(const Digraph& digraph, const IntArcMap& length, |
|
| 132 |
Node source) {
|
|
| 133 |
|
|
| 131 |
void dijkstraHeapTest(const Digraph& digraph, const IntArcMap& length, |
|
| 132 |
Node source) {
|
|
| 133 |
|
|
| 134 | 134 |
typename Dijkstra<Digraph, IntArcMap>::template DefStandardHeap<Heap>:: |
| 135 | 135 |
Create dijkstra(digraph, length); |
| 136 | 136 |
|
| 137 | 137 |
dijkstra.run(source); |
| 138 | 138 |
|
| 139 | 139 |
for(ArcIt a(digraph); a != INVALID; ++a) {
|
| 140 |
Node s = digraph.source(a); |
|
| 140 |
Node s = digraph.source(a); |
|
| 141 | 141 |
Node t = digraph.target(a); |
| 142 | 142 |
if (dijkstra.reached(s)) {
|
| 143 | 143 |
check( dijkstra.dist(t) - dijkstra.dist(s) <= length[a], |
| 144 |
|
|
| 144 |
"Error in a shortest path tree!"); |
|
| 145 | 145 |
} |
| 146 | 146 |
} |
| 147 | 147 |
|
| 148 | 148 |
for(NodeIt n(digraph); n != INVALID; ++n) {
|
| 149 | 149 |
if ( dijkstra.reached(n) && dijkstra.predArc(n) != INVALID ) {
|
| 150 | 150 |
Arc a = dijkstra.predArc(n); |
| 151 | 151 |
Node s = digraph.source(a); |
| 152 | 152 |
check( dijkstra.dist(n) - dijkstra.dist(s) == length[a], |
| 153 |
|
|
| 153 |
"Error in a shortest path tree!"); |
|
| 154 | 154 |
} |
| 155 | 155 |
} |
| 156 | 156 |
|
| 157 | 157 |
} |
| 158 | 158 |
|
| 159 | 159 |
int main() {
|
| 160 | 160 |
|
| 161 | 161 |
typedef int Item; |
| 162 | 162 |
typedef int Prio; |
| 163 | 163 |
typedef RangeMap<int> ItemIntMap; |
| 164 |
|
|
| 164 |
|
|
| 165 | 165 |
Digraph digraph; |
| 166 | 166 |
IntArcMap length(digraph); |
| 167 | 167 |
Node source; |
| 168 | 168 |
|
| 169 | 169 |
std::istringstream input(test_lgf); |
| 170 | 170 |
digraphReader(input, digraph). |
| 171 | 171 |
arcMap("capacity", length).
|
| 172 | 172 |
node("source", source).
|
| 173 |
run(); |
|
| 174 |
|
|
| 173 |
run(); |
|
| 174 |
|
|
| 175 | 175 |
{
|
| 176 | 176 |
typedef BinHeap<Prio, ItemIntMap> IntHeap; |
| 177 | 177 |
checkConcept<Heap<Prio, ItemIntMap>, IntHeap>(); |
| 178 | 178 |
heapSortTest<IntHeap>(); |
| 179 | 179 |
heapIncreaseTest<IntHeap>(); |
| 180 |
|
|
| 180 |
|
|
| 181 | 181 |
typedef BinHeap<Prio, IntNodeMap > NodeHeap; |
| 182 | 182 |
checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>(); |
| 183 | 183 |
dijkstraHeapTest<NodeHeap>(digraph, length, source); |
| 184 | 184 |
} |
| 185 | 185 |
|
| 186 | 186 |
return 0; |
| 187 | 187 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <iostream> |
| ... | ... |
@@ -60,88 +60,88 @@ |
| 60 | 60 |
|
| 61 | 61 |
int main() {
|
| 62 | 62 |
|
| 63 | 63 |
typedef ListGraph::Node Node; |
| 64 | 64 |
typedef ListGraph::Edge Edge; |
| 65 | 65 |
typedef ListGraph::NodeIt NodeIt; |
| 66 | 66 |
typedef ListGraph::ArcIt ArcIt; |
| 67 | 67 |
|
| 68 | 68 |
ListGraph G; |
| 69 | 69 |
|
| 70 | 70 |
Node s=G.addNode(); |
| 71 | 71 |
Node v1=G.addNode(); |
| 72 | 72 |
Node v2=G.addNode(); |
| 73 | 73 |
Node v3=G.addNode(); |
| 74 | 74 |
Node v4=G.addNode(); |
| 75 | 75 |
Node t=G.addNode(); |
| 76 |
|
|
| 76 |
|
|
| 77 | 77 |
Edge e1 = G.addEdge(s, v1); |
| 78 | 78 |
Edge e2 = G.addEdge(s, v2); |
| 79 | 79 |
Edge e3 = G.addEdge(v1, v2); |
| 80 | 80 |
Edge e4 = G.addEdge(v2, v1); |
| 81 | 81 |
Edge e5 = G.addEdge(v1, v3); |
| 82 | 82 |
Edge e6 = G.addEdge(v3, v2); |
| 83 | 83 |
Edge e7 = G.addEdge(v2, v4); |
| 84 | 84 |
Edge e8 = G.addEdge(v4, v3); |
| 85 | 85 |
Edge e9 = G.addEdge(v3, t); |
| 86 | 86 |
Edge e10 = G.addEdge(v4, t); |
| 87 | 87 |
|
| 88 | 88 |
typedef ListGraph::EdgeMap<int> ECostMap; |
| 89 | 89 |
typedef ListGraph::EdgeMap<bool> EBoolMap; |
| 90 | 90 |
|
| 91 | 91 |
ECostMap edge_cost_map(G, 2); |
| 92 | 92 |
EBoolMap tree_map(G); |
| 93 |
|
|
| 93 |
|
|
| 94 | 94 |
|
| 95 | 95 |
//Test with const map. |
| 96 | 96 |
check(kruskal(G, ConstMap<ListGraph::Edge,int>(2), tree_map)==10, |
| 97 |
|
|
| 97 |
"Total cost should be 10"); |
|
| 98 | 98 |
//Test with an edge map (filled with uniform costs). |
| 99 | 99 |
check(kruskal(G, edge_cost_map, tree_map)==10, |
| 100 |
|
|
| 100 |
"Total cost should be 10"); |
|
| 101 | 101 |
|
| 102 | 102 |
edge_cost_map.set(e1, -10); |
| 103 | 103 |
edge_cost_map.set(e2, -9); |
| 104 | 104 |
edge_cost_map.set(e3, -8); |
| 105 | 105 |
edge_cost_map.set(e4, -7); |
| 106 | 106 |
edge_cost_map.set(e5, -6); |
| 107 | 107 |
edge_cost_map.set(e6, -5); |
| 108 | 108 |
edge_cost_map.set(e7, -4); |
| 109 | 109 |
edge_cost_map.set(e8, -3); |
| 110 | 110 |
edge_cost_map.set(e9, -2); |
| 111 | 111 |
edge_cost_map.set(e10, -1); |
| 112 | 112 |
|
| 113 | 113 |
vector<Edge> tree_edge_vec(5); |
| 114 | 114 |
|
| 115 | 115 |
//Test with a edge map and inserter. |
| 116 | 116 |
check(kruskal(G, edge_cost_map, |
| 117 |
tree_edge_vec.begin()) |
|
| 118 |
==-31, |
|
| 119 |
"Total cost should be -31."); |
|
| 120 |
|
|
| 117 |
tree_edge_vec.begin()) |
|
| 118 |
==-31, |
|
| 119 |
"Total cost should be -31."); |
|
| 120 |
|
|
| 121 | 121 |
tree_edge_vec.clear(); |
| 122 | 122 |
|
| 123 | 123 |
check(kruskal(G, edge_cost_map, |
| 124 |
back_inserter(tree_edge_vec)) |
|
| 125 |
==-31, |
|
| 126 |
"Total cost should be -31."); |
|
| 127 |
|
|
| 124 |
back_inserter(tree_edge_vec)) |
|
| 125 |
==-31, |
|
| 126 |
"Total cost should be -31."); |
|
| 127 |
|
|
| 128 | 128 |
// tree_edge_vec.clear(); |
| 129 |
|
|
| 129 |
|
|
| 130 | 130 |
// //The above test could also be coded like this: |
| 131 | 131 |
// check(kruskal(G, |
| 132 |
// makeKruskalMapInput(G, edge_cost_map), |
|
| 133 |
// makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) |
|
| 134 |
// ==-31, |
|
| 135 |
// "Total cost should be -31."); |
|
| 132 |
// makeKruskalMapInput(G, edge_cost_map), |
|
| 133 |
// makeKruskalSequenceOutput(back_inserter(tree_edge_vec))) |
|
| 134 |
// ==-31, |
|
| 135 |
// "Total cost should be -31."); |
|
| 136 | 136 |
|
| 137 | 137 |
check(tree_edge_vec.size()==5,"The tree should have 5 edges."); |
| 138 | 138 |
|
| 139 | 139 |
check(tree_edge_vec[0]==e1 && |
| 140 |
tree_edge_vec[1]==e2 && |
|
| 141 |
tree_edge_vec[2]==e5 && |
|
| 142 |
tree_edge_vec[3]==e7 && |
|
| 143 |
tree_edge_vec[4]==e9, |
|
| 144 |
|
|
| 140 |
tree_edge_vec[1]==e2 && |
|
| 141 |
tree_edge_vec[2]==e5 && |
|
| 142 |
tree_edge_vec[3]==e7 && |
|
| 143 |
tree_edge_vec[4]==e9, |
|
| 144 |
"Wrong tree."); |
|
| 145 | 145 |
|
| 146 | 146 |
return 0; |
| 147 | 147 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <deque> |
| ... | ... |
@@ -291,41 +291,41 @@ |
| 291 | 291 |
rm[0] = true; rm[1] = false; |
| 292 | 292 |
check(andMap(tm,rm)[0] && !andMap(tm,rm)[1] && !andMap(fm,rm)[0] && !andMap(fm,rm)[1], |
| 293 | 293 |
"Something is wrong with AndMap"); |
| 294 | 294 |
check(orMap(tm,rm)[0] && orMap(tm,rm)[1] && orMap(fm,rm)[0] && !orMap(fm,rm)[1], |
| 295 | 295 |
"Something is wrong with OrMap"); |
| 296 | 296 |
check(!notMap(rm)[0] && notMap(rm)[1], "Something is wrong with NotMap"); |
| 297 | 297 |
check(!notWriteMap(rm)[0] && notWriteMap(rm)[1], "Something is wrong with NotWriteMap"); |
| 298 | 298 |
|
| 299 | 299 |
ConstMap<int, double> cm(2.0); |
| 300 | 300 |
IdentityMap<int> im; |
| 301 | 301 |
ConvertMap<IdentityMap<int>, double> id(im); |
| 302 | 302 |
check(lessMap(id,cm)[1] && !lessMap(id,cm)[2] && !lessMap(id,cm)[3], |
| 303 | 303 |
"Something is wrong with LessMap"); |
| 304 | 304 |
check(!equalMap(id,cm)[1] && equalMap(id,cm)[2] && !equalMap(id,cm)[3], |
| 305 | 305 |
"Something is wrong with EqualMap"); |
| 306 | 306 |
} |
| 307 |
|
|
| 307 |
|
|
| 308 | 308 |
// LoggerBoolMap |
| 309 | 309 |
{
|
| 310 | 310 |
typedef std::vector<int> vec; |
| 311 | 311 |
vec v1; |
| 312 | 312 |
vec v2(10); |
| 313 | 313 |
LoggerBoolMap<std::back_insert_iterator<vec> > map1(std::back_inserter(v1)); |
| 314 | 314 |
LoggerBoolMap<vec::iterator> map2(v2.begin()); |
| 315 | 315 |
map1.set(10, false); |
| 316 | 316 |
map1.set(20, true); map2.set(20, true); |
| 317 | 317 |
map1.set(30, false); map2.set(40, false); |
| 318 | 318 |
map1.set(50, true); map2.set(50, true); |
| 319 | 319 |
map1.set(60, true); map2.set(60, true); |
| 320 | 320 |
check(v1.size() == 3 && v2.size() == 10 && |
| 321 | 321 |
v1[0]==20 && v1[1]==50 && v1[2]==60 && v2[0]==20 && v2[1]==50 && v2[2]==60, |
| 322 | 322 |
"Something is wrong with LoggerBoolMap"); |
| 323 |
|
|
| 323 |
|
|
| 324 | 324 |
int i = 0; |
| 325 | 325 |
for ( LoggerBoolMap<vec::iterator>::Iterator it = map2.begin(); |
| 326 | 326 |
it != map2.end(); ++it ) |
| 327 | 327 |
check(v1[i++] == *it, "Something is wrong with LoggerBoolMap"); |
| 328 | 328 |
} |
| 329 | 329 |
|
| 330 | 330 |
return 0; |
| 331 | 331 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <string> |
| ... | ... |
@@ -26,19 +26,19 @@ |
| 26 | 26 |
#include <lemon/list_graph.h> |
| 27 | 27 |
|
| 28 | 28 |
#include "test_tools.h" |
| 29 | 29 |
|
| 30 | 30 |
using namespace std; |
| 31 | 31 |
using namespace lemon; |
| 32 | 32 |
|
| 33 | 33 |
void check_concepts() {
|
| 34 | 34 |
checkConcept<concepts::Path<ListDigraph>, concepts::Path<ListDigraph> >(); |
| 35 | 35 |
checkConcept<concepts::Path<ListDigraph>, Path<ListDigraph> >(); |
| 36 | 36 |
checkConcept<concepts::Path<ListDigraph>, SimplePath<ListDigraph> >(); |
| 37 | 37 |
checkConcept<concepts::Path<ListDigraph>, StaticPath<ListDigraph> >(); |
| 38 | 38 |
checkConcept<concepts::Path<ListDigraph>, ListPath<ListDigraph> >(); |
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 | 41 |
int main() {
|
| 42 |
check_concepts(); |
|
| 42 |
check_concepts(); |
|
| 43 | 43 |
return 0; |
| 44 | 44 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/random.h> |
| 20 | 20 |
#include "test_tools.h" |
| 21 | 21 |
|
| 22 | 22 |
int seed_array[] = {1, 2};
|
| 23 | 23 |
|
| 24 | 24 |
int main() |
| 25 | 25 |
{
|
| 26 | 26 |
double a=lemon::rnd(); |
| 27 | 27 |
check(a<1.0&&a>0.0,"This should be in [0,1)"); |
| 28 | 28 |
a=lemon::rnd.gauss(); |
| 29 | 29 |
a=lemon::rnd.gamma(3.45,0); |
| 30 | 30 |
a=lemon::rnd.gamma(4); |
| 31 | 31 |
//Does gamma work with integer k? |
| 32 | 32 |
a=lemon::rnd.gamma(4.0,0); |
| 33 | 33 |
a=lemon::rnd.poisson(.5); |
| 34 | 34 |
|
| 35 | 35 |
lemon::rnd.seed(100); |
| 36 |
lemon::rnd.seed(seed_array, seed_array + |
|
| 37 |
(sizeof(seed_array) / sizeof(seed_array[0]))); |
|
| 36 |
lemon::rnd.seed(seed_array, seed_array + |
|
| 37 |
(sizeof(seed_array) / sizeof(seed_array[0]))); |
|
| 38 | 38 |
|
| 39 | 39 |
return 0; |
| 40 | 40 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#ifndef LEMON_TEST_TEST_TOOLS_H |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include "test_tools.h" |
| 20 | 20 |
|
| 21 |
int main() |
|
| 21 |
int main() |
|
| 22 | 22 |
{
|
| 23 | 23 |
check(false, "Don't panic. Failing is the right behaviour here."); |
| 24 | 24 |
return 0; |
| 25 | 25 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include "test_tools.h" |
| 20 | 20 |
|
| 21 |
int main() |
|
| 21 |
int main() |
|
| 22 | 22 |
{
|
| 23 | 23 |
check(true, "It should pass."); |
| 24 | 24 |
return 0; |
| 25 | 25 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/time_measure.h> |
| 20 | 20 |
|
| 21 | 21 |
using namespace lemon; |
| 22 | 22 |
|
| 23 |
void f() |
|
| 23 |
void f() |
|
| 24 | 24 |
{
|
| 25 | 25 |
double d=0; |
| 26 | 26 |
for(int i=0;i<1000;i++) |
| 27 | 27 |
d+=0.1; |
| 28 | 28 |
} |
| 29 | 29 |
|
| 30 |
void g() |
|
| 30 |
void g() |
|
| 31 | 31 |
{
|
| 32 | 32 |
static Timer T; |
| 33 |
|
|
| 33 |
|
|
| 34 | 34 |
for(int i=0;i<1000;i++) |
| 35 | 35 |
TimeStamp x(T); |
| 36 | 36 |
} |
| 37 | 37 |
|
| 38 | 38 |
int main() |
| 39 | 39 |
{
|
| 40 | 40 |
Timer T; |
| 41 | 41 |
unsigned int n; |
| 42 | 42 |
for(n=0;T.realTime()<1.0;n++) ; |
| 43 | 43 |
std::cout << T << " (" << n << " time queries)\n";
|
| 44 | 44 |
T.restart(); |
| 45 | 45 |
while(T.realTime()<2.0) ; |
| 46 | 46 |
std::cout << T << '\n'; |
| 47 | 47 |
TimeStamp full; |
| 48 | 48 |
TimeStamp t; |
| 49 | 49 |
t=runningTimeTest(f,1,&n,&full); |
| 50 | 50 |
std::cout << t << " (" << n << " tests)\n";
|
| 51 | 51 |
std::cout << "Total: " << full << "\n"; |
| 52 |
|
|
| 52 |
|
|
| 53 | 53 |
t=runningTimeTest(g,1,&n,&full); |
| 54 | 54 |
std::cout << t << " (" << n << " tests)\n";
|
| 55 | 55 |
std::cout << "Total: " << full << "\n"; |
| 56 |
|
|
| 56 |
|
|
| 57 | 57 |
return 0; |
| 58 | 58 |
} |
| 1 |
/* -*- C++ -*- |
|
| 1 |
/* -*- mode: C++; indent-tabs-mode: nil; -*- |
|
| 2 | 2 |
* |
| 3 |
* This file is a part of LEMON, a generic C++ optimization library |
|
| 3 |
* This file is a part of LEMON, a generic C++ optimization library. |
|
| 4 | 4 |
* |
| 5 | 5 |
* Copyright (C) 2003-2008 |
| 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 |
#include <lemon/list_graph.h> |
| 20 | 20 |
#include <lemon/maps.h> |
| 21 | 21 |
#include <lemon/unionfind.h> |
| 22 | 22 |
#include "test_tools.h" |
| 23 | 23 |
|
| 24 | 24 |
using namespace lemon; |
| 25 | 25 |
using namespace std; |
| 26 | 26 |
|
| 27 | 27 |
typedef UnionFindEnum<ListGraph::NodeMap<int> > UFE; |
| 28 | 28 |
|
| 29 | 29 |
int main() {
|
| 30 | 30 |
ListGraph g; |
| 31 | 31 |
ListGraph::NodeMap<int> base(g); |
| 32 | 32 |
UFE U(base); |
| 33 | 33 |
vector<ListGraph::Node> n; |
| 34 |
|
|
| 34 |
|
|
| 35 | 35 |
for(int i=0;i<20;i++) n.push_back(g.addNode()); |
| 36 | 36 |
|
| 37 | 37 |
U.insert(n[1]); |
| 38 | 38 |
U.insert(n[2]); |
| 39 | 39 |
|
| 40 | 40 |
check(U.join(n[1],n[2]) != -1, "Something is wrong with UnionFindEnum"); |
| 41 | 41 |
|
| 42 | 42 |
U.insert(n[3]); |
| 43 | 43 |
U.insert(n[4]); |
| 44 | 44 |
U.insert(n[5]); |
| 45 | 45 |
U.insert(n[6]); |
| 46 | 46 |
U.insert(n[7]); |
| 47 | 47 |
|
| 48 | 48 |
|
| 49 | 49 |
check(U.join(n[1],n[4]) != -1, "Something is wrong with UnionFindEnum"); |
| 50 | 50 |
check(U.join(n[2],n[4]) == -1, "Something is wrong with UnionFindEnum"); |
0 comments (0 inline)