alpar@2391
|
1 |
/* -*- C++ -*-
|
alpar@2391
|
2 |
*
|
alpar@2391
|
3 |
* This file is a part of LEMON, a generic C++ optimization library
|
alpar@2391
|
4 |
*
|
alpar@2391
|
5 |
* Copyright (C) 2003-2007
|
alpar@2391
|
6 |
* Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
|
alpar@2391
|
7 |
* (Egervary Research Group on Combinatorial Optimization, EGRES).
|
alpar@2391
|
8 |
*
|
alpar@2391
|
9 |
* Permission to use, modify and distribute this software is granted
|
alpar@2391
|
10 |
* provided that this copyright notice appears in all copies. For
|
alpar@2391
|
11 |
* precise terms see the accompanying LICENSE file.
|
alpar@2391
|
12 |
*
|
alpar@2391
|
13 |
* This software is provided "AS IS" with no warranty of any kind,
|
alpar@2391
|
14 |
* express or implied, and with no claim as to its suitability for any
|
alpar@2391
|
15 |
* purpose.
|
alpar@2391
|
16 |
*
|
alpar@2391
|
17 |
*/
|
alpar@2391
|
18 |
|
alpar@2216
|
19 |
namespace lemon {
|
alpar@2196
|
20 |
/**
|
alpar@2196
|
21 |
\page algorithms Algorithms
|
alpar@2196
|
22 |
|
alpar@2216
|
23 |
\section algo_bfs_dfs Bfs/Dfs
|
alpar@2216
|
24 |
Both \ref lemon::Bfs "Bfs" and \ref lemon::Dfs "Dfs" are highly adaptable and efficient
|
alpar@2216
|
25 |
implementations of the well known algorithms. The algorithms are placed most cases in
|
alpar@2216
|
26 |
separated files named after the algorithm itself but lower case as all other header file names.
|
alpar@2216
|
27 |
For example the next Bfs class is in the \c lemon/bfs.h.
|
alpar@2216
|
28 |
|
alpar@2216
|
29 |
\subsection Bfs
|
alpar@2216
|
30 |
The algorithm is implemented in the \ref lemon::Bfs "Bfs" template class - rather than as function.
|
alpar@2408
|
31 |
The class has two template parameters: \b GR and \b TR.<br>
|
alpar@2216
|
32 |
GR is the graph the algorithm runs on. It has \ref lemon::ListGraph "ListGraph" as default type.
|
alpar@2216
|
33 |
TR is a Traits class commonly used to easy the parametrization of templates. In most cases you
|
alpar@2216
|
34 |
wont need to modify the default type \ref lemon::BfsDefaultTraits "BfsDefaultTraits<GR>".
|
alpar@2216
|
35 |
|
alpar@2216
|
36 |
To use the class, declare it!
|
alpar@2216
|
37 |
\code
|
alpar@2216
|
38 |
Bfs<ListUGraph> bfs(gr);
|
alpar@2216
|
39 |
\endcode
|
alpar@2216
|
40 |
Note the lack of second template argument because of the default parameter.
|
alpar@2216
|
41 |
|
alpar@2216
|
42 |
It provides a simple but powerful interface to control the execution.
|
alpar@2216
|
43 |
\code
|
alpar@2216
|
44 |
int dist = bfs.run(s,t);
|
alpar@2216
|
45 |
\endcode
|
alpar@2216
|
46 |
It finds the shortest path from node \c s to node \c t and returns it, or zero
|
alpar@2216
|
47 |
if there is no path from \c s to \c t.<br>
|
alpar@2216
|
48 |
If you want the shortest path from a specified node to all other node, just write:
|
alpar@2216
|
49 |
\code
|
alpar@2216
|
50 |
bfs.run(s);
|
alpar@2216
|
51 |
\endcode
|
alpar@2216
|
52 |
Now the distances and path information are stored in maps which you can access with
|
alpar@2216
|
53 |
member functions like \ref lemon::Bfs::distMap "distMap()" or \ref lemon::Bfs::predMap "predMap()".<br>
|
alpar@2408
|
54 |
Or more directly with other member functions like \ref lemon::Bfs::predNode "predNode()". Once the algorithm
|
alpar@2216
|
55 |
is finished (or to be precise reached that node) \ref lemon::Bfs::dist "dist()" or \ref lemon::Bfs::predNode
|
alpar@2216
|
56 |
"predNode()" can be called.
|
alpar@2216
|
57 |
|
alpar@2216
|
58 |
For an example let's say we want to print the shortest path of those nodes which
|
alpar@2216
|
59 |
are in a certain distance.
|
alpar@2216
|
60 |
\code
|
alpar@2216
|
61 |
bfs.run(s);
|
alpar@2216
|
62 |
|
alpar@2216
|
63 |
for( ListUGraph::NodeIt n(gr); n != INVALID; ++n ) {
|
alpar@2216
|
64 |
if( bfs.reached(n) && bfs.dist(n) <= max_dist ) {
|
alpar@2216
|
65 |
std::cout << gr.id(n);
|
alpar@2216
|
66 |
|
alpar@2216
|
67 |
Node prev = bfs.prevNode(n);
|
alpar@2216
|
68 |
while( prev != INVALID ) {
|
alpar@2216
|
69 |
std::cout << "<-" << gr.id(prev);
|
alpar@2216
|
70 |
prev = bfs.prevNode(n);
|
alpar@2216
|
71 |
}
|
alpar@2216
|
72 |
|
alpar@2216
|
73 |
std::cout << std::endl;
|
alpar@2216
|
74 |
}
|
alpar@2216
|
75 |
}
|
alpar@2216
|
76 |
\endcode
|
alpar@2216
|
77 |
|
alpar@2216
|
78 |
\subsubsection bfs_adv_control Advanced control
|
alpar@2216
|
79 |
In the previous code we only used \c run(). Now we introduce the way you can directly
|
alpar@2216
|
80 |
control the execution of the algorithm.
|
alpar@2216
|
81 |
|
alpar@2216
|
82 |
First you have to initialize the variables with \ref lemon::Bfs::init "init()".
|
alpar@2216
|
83 |
\code
|
alpar@2216
|
84 |
bfs.init();
|
alpar@2216
|
85 |
\endcode
|
alpar@2216
|
86 |
|
alpar@2216
|
87 |
Then you add one or more source nodes to the queue. They will be processed, as they would
|
alpar@2216
|
88 |
be reached by the algorithm before. And yes - you can add more sources during the execution.
|
alpar@2216
|
89 |
\code
|
alpar@2216
|
90 |
bfs.addSource(node_1);
|
alpar@2216
|
91 |
bfs.addSource(node_2);
|
alpar@2216
|
92 |
...
|
alpar@2216
|
93 |
\endcode
|
alpar@2216
|
94 |
|
alpar@2216
|
95 |
And finally you can start the process with \ref lemon::Bfs::start "start()", or
|
alpar@2216
|
96 |
you can write your own loop to process the nodes one-by-one.
|
alpar@2216
|
97 |
|
kpeter@2470
|
98 |
\todo Demo for Bfs advanced control.
|
alpar@2216
|
99 |
|
alpar@2216
|
100 |
\subsection Dfs
|
alpar@2216
|
101 |
Since Dfs is very similar to Bfs with a few tiny differences we only see a bit more complex example
|
alpar@2216
|
102 |
to demonstrate Dfs's capabilities.
|
alpar@2216
|
103 |
|
alpar@2216
|
104 |
We will see a program, which solves the problem of <b>topological ordering</b>.
|
alpar@2216
|
105 |
We need to know in which order we should put on our clothes. The program will do the following:
|
alpar@2216
|
106 |
<ol>
|
alpar@2216
|
107 |
<li>We run the dfs algorithm to all nodes.
|
alpar@2216
|
108 |
<li>Put every node into a list when processed completely.
|
alpar@2216
|
109 |
<li>Write out the list in reverse order.
|
alpar@2216
|
110 |
</ol>
|
alpar@2216
|
111 |
|
alpar@2216
|
112 |
\dontinclude topological_ordering.cc
|
alpar@2216
|
113 |
First of all we will need an own \ref lemon::Dfs::ProcessedMap "ProcessedMap". The ordering
|
alpar@2216
|
114 |
will be done through it.
|
mqrelly@2281
|
115 |
\skip MyOrdererMap
|
alpar@2216
|
116 |
\until };
|
kpeter@2476
|
117 |
The class meets the \ref concepts::WriteMap "WriteMap" concept. In it's \c set() method the only thing
|
alpar@2408
|
118 |
we need to do is insert the key - that is the node whose processing just finished - into the beginning
|
mqrelly@2281
|
119 |
of the list.<br>
|
mqrelly@2281
|
120 |
Although we implemented this needed helper class ourselves it was not necessary.
|
mqrelly@2281
|
121 |
The \ref lemon::FrontInserterBoolMap "FrontInserterBoolMap" class does exactly
|
mqrelly@2281
|
122 |
what we needed. To be correct it's more general - and it's all in \c LEMON. But
|
mqrelly@2281
|
123 |
we wanted to show you, how easy is to add additional functionality.
|
alpar@2216
|
124 |
|
alpar@2216
|
125 |
First we declare the needed data structures: the graph and a map to store the nodes' label.
|
alpar@2216
|
126 |
\skip ListGraph
|
alpar@2216
|
127 |
\until label
|
alpar@2216
|
128 |
|
alpar@2216
|
129 |
Now we build a graph. But keep in mind that it must be DAG because cyclic graphs has no topological
|
alpar@2216
|
130 |
ordering.
|
alpar@2216
|
131 |
\skip belt
|
alpar@2216
|
132 |
\until trousers
|
alpar@2216
|
133 |
We label them...
|
alpar@2216
|
134 |
\skip label
|
alpar@2216
|
135 |
\until trousers
|
alpar@2216
|
136 |
Then add directed edges which represent the precedences between those items.
|
alpar@2216
|
137 |
\skip trousers, belt
|
alpar@2216
|
138 |
\until );
|
alpar@2216
|
139 |
|
alpar@2216
|
140 |
See how easy is to access the internal information of this algorithm trough maps.
|
alpar@2216
|
141 |
We only need to set our own map as the class's \ref lemon::Dfs::ProcessedMap "ProcessedMap".
|
alpar@2216
|
142 |
\skip Dfs
|
alpar@2216
|
143 |
\until run
|
alpar@2216
|
144 |
|
alpar@2216
|
145 |
And now comes the third part. Write out the list in reverse order. But the list was
|
alpar@2216
|
146 |
composed in reverse way (with \c push_front() instead of \c push_back() so we just iterate it.
|
alpar@2216
|
147 |
\skip std
|
alpar@2216
|
148 |
\until endl
|
alpar@2216
|
149 |
|
alpar@2216
|
150 |
The program is to be found in the \ref demo directory: \ref topological_ordering.cc
|
mqrelly@2281
|
151 |
|
kpeter@2470
|
152 |
\todo Check the linking of the demo file, the code samples are missing.
|
kpeter@2470
|
153 |
|
mqrelly@2281
|
154 |
More algorithms are described in the \ref algorithms2 "second part".
|
alpar@2196
|
155 |
*/
|
alpar@2216
|
156 |
}
|