adaptors.dox
author Peter Kovacs <kpeter@inf.elte.hu>
Mon, 15 Feb 2010 01:18:18 +0100
changeset 29 bc3ef6652f1b
child 32 ef12f83752f6
permissions -rw-r--r--
Add a preliminary page of graph adaptors
kpeter@29
     1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
kpeter@29
     2
 *
kpeter@29
     3
 * This file is a part of LEMON, a generic C++ optimization library.
kpeter@29
     4
 *
kpeter@29
     5
 * Copyright (C) 2003-2009
kpeter@29
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
kpeter@29
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
kpeter@29
     8
 *
kpeter@29
     9
 * Permission to use, modify and distribute this software is granted
kpeter@29
    10
 * provided that this copyright notice appears in all copies. For
kpeter@29
    11
 * precise terms see the accompanying LICENSE file.
kpeter@29
    12
 *
kpeter@29
    13
 * This software is provided "AS IS" with no warranty of any kind,
kpeter@29
    14
 * express or implied, and with no claim as to its suitability for any
kpeter@29
    15
 * purpose.
kpeter@29
    16
 *
kpeter@29
    17
 */
kpeter@29
    18
kpeter@29
    19
namespace lemon {
kpeter@29
    20
/**
kpeter@29
    21
[PAGE]sec_graph_adaptors[PAGE] Graph Adaptors
kpeter@29
    22
kpeter@29
    23
\todo Clarify this section.
kpeter@29
    24
kpeter@29
    25
Alteration of standard containers need a very limited number of
kpeter@29
    26
operations, these together satisfy the everyday requirements.
kpeter@29
    27
In the case of graph structures, different operations are needed which do
kpeter@29
    28
not alter the physical graph, but gives another view. If some nodes or
kpeter@29
    29
arcs have to be hidden or the reverse oriented graph have to be used, then
kpeter@29
    30
this is the case. It also may happen that in a flow implementation
kpeter@29
    31
the residual graph can be accessed by another algorithm, or a node-set
kpeter@29
    32
is to be shrunk for another algorithm.
kpeter@29
    33
LEMON also provides a variety of graphs for these requirements called
kpeter@29
    34
\ref graph_adaptors "graph adaptors". Adaptors cannot be used alone but only
kpeter@29
    35
in conjunction with other graph representations.
kpeter@29
    36
kpeter@29
    37
The main parts of LEMON are the different graph structures, generic
kpeter@29
    38
graph algorithms, graph concepts, which couple them, and graph
kpeter@29
    39
adaptors. While the previous notions are more or less clear, the
kpeter@29
    40
latter one needs further explanation. Graph adaptors are graph classes
kpeter@29
    41
which serve for considering graph structures in different ways.
kpeter@29
    42
kpeter@29
    43
A short example makes this much clearer.  Suppose that we have an
kpeter@29
    44
instance \c g of a directed graph type, say ListDigraph and an algorithm
kpeter@29
    45
\code
kpeter@29
    46
template <typename Digraph>
kpeter@29
    47
int algorithm(const Digraph&);
kpeter@29
    48
\endcode
kpeter@29
    49
is needed to run on the reverse oriented graph.  It may be expensive
kpeter@29
    50
(in time or in memory usage) to copy \c g with the reversed
kpeter@29
    51
arcs.  In this case, an adaptor class is used, which (according
kpeter@29
    52
to LEMON \ref concepts::Digraph "digraph concepts") works as a digraph.
kpeter@29
    53
The adaptor uses the original digraph structure and digraph operations when
kpeter@29
    54
methods of the reversed oriented graph are called.  This means that the adaptor
kpeter@29
    55
have minor memory usage, and do not perform sophisticated algorithmic
kpeter@29
    56
actions.  The purpose of it is to give a tool for the cases when a
kpeter@29
    57
graph have to be used in a specific alteration.  If this alteration is
kpeter@29
    58
obtained by a usual construction like filtering the node or the arc set or
kpeter@29
    59
considering a new orientation, then an adaptor is worthwhile to use.
kpeter@29
    60
To come back to the reverse oriented graph, in this situation
kpeter@29
    61
\code
kpeter@29
    62
template<typename Digraph> class ReverseDigraph;
kpeter@29
    63
\endcode
kpeter@29
    64
template class can be used. The code looks as follows
kpeter@29
    65
\code
kpeter@29
    66
ListDigraph g;
kpeter@29
    67
ReverseDigraph<ListDigraph> rg(g);
kpeter@29
    68
int result = algorithm(rg);
kpeter@29
    69
\endcode
kpeter@29
    70
During running the algorithm, the original digraph \c g is untouched.
kpeter@29
    71
This techniques give rise to an elegant code, and based on stable
kpeter@29
    72
graph adaptors, complex algorithms can be implemented easily.
kpeter@29
    73
kpeter@29
    74
In flow, circulation and matching problems, the residual
kpeter@29
    75
graph is of particular importance. Combining an adaptor implementing
kpeter@29
    76
this with shortest path algorithms or minimum mean cycle algorithms,
kpeter@29
    77
a range of weighted and cardinality optimization algorithms can be
kpeter@29
    78
obtained. For other examples, the interested user is referred to the
kpeter@29
    79
detailed documentation of particular adaptors.
kpeter@29
    80
kpeter@29
    81
The behavior of graph adaptors can be very different. Some of them keep
kpeter@29
    82
capabilities of the original graph while in other cases this would be
kpeter@29
    83
meaningless. This means that the concepts that they meet depend
kpeter@29
    84
on the graph adaptor, and the wrapped graph.
kpeter@29
    85
For example, if an arc of a reversed digraph is deleted, this is carried
kpeter@29
    86
out by deleting the corresponding arc of the original digraph, thus the
kpeter@29
    87
adaptor modifies the original digraph.
kpeter@29
    88
However in case of a residual digraph, this operation has no sense.
kpeter@29
    89
kpeter@29
    90
Let us stand one more example here to simplify your work.
kpeter@29
    91
ReverseDigraph has constructor
kpeter@29
    92
\code
kpeter@29
    93
ReverseDigraph(Digraph& digraph);
kpeter@29
    94
\endcode
kpeter@29
    95
This means that in a situation, when a <tt>const %ListDigraph&</tt>
kpeter@29
    96
reference to a graph is given, then it have to be instantiated with
kpeter@29
    97
<tt>Digraph=const %ListDigraph</tt>.
kpeter@29
    98
\code
kpeter@29
    99
int algorithm1(const ListDigraph& g) {
kpeter@29
   100
  ReverseDigraph<const ListDigraph> rg(g);
kpeter@29
   101
  return algorithm2(rg);
kpeter@29
   102
}
kpeter@29
   103
\endcode
kpeter@29
   104
kpeter@29
   105
<hr>
kpeter@29
   106
kpeter@29
   107
The LEMON graph adaptor classes serve for considering graphs in
kpeter@29
   108
different ways. The adaptors can be used exactly the same as "real"
kpeter@29
   109
graphs (i.e., they conform to the graph concepts), thus all generic
kpeter@29
   110
algorithms can be performed on them. However, the adaptor classes use
kpeter@29
   111
the underlying graph structures and operations when their methods are
kpeter@29
   112
called, thus they have only negligible memory usage and do not perform
kpeter@29
   113
sophisticated algorithmic actions. This technique yields convenient and
kpeter@29
   114
elegant tools for the cases when a graph has to be used in a specific
kpeter@29
   115
alteration, but copying it would be too expensive (in time or in memory
kpeter@29
   116
usage) compared to the algorithm that should be executed on it. The
kpeter@29
   117
following example shows how the \ref ReverseDigraph adaptor can be used
kpeter@29
   118
to run Dijksta's algorithm on the reverse oriented graph. Note that the
kpeter@29
   119
maps of the original graph can be used in connection with the adaptor,
kpeter@29
   120
since the node and arc types of the adaptors convert to the original
kpeter@29
   121
item types. 
kpeter@29
   122
kpeter@29
   123
\code
kpeter@29
   124
dijkstra(reverseDigraph(g), length).distMap(dist).run(s);
kpeter@29
   125
\endcode
kpeter@29
   126
kpeter@29
   127
Using \ref ReverseDigraph could be as efficient as working with the
kpeter@29
   128
original graph, but not all adaptors can be so fast, of course. For
kpeter@29
   129
example, the subgraph adaptors have to access filter maps for the nodes
kpeter@29
   130
and/or the arcs, thus their iterators are significantly slower than the
kpeter@29
   131
original iterators. LEMON also provides some more complex adaptors, for
kpeter@29
   132
instance, \ref SplitNodes, which can be used for splitting each node in
kpeter@29
   133
a directed graph and \ref ResidualDigraph for modeling the residual
kpeter@29
   134
network for flow and matching problems. 
kpeter@29
   135
kpeter@29
   136
Therefore, in cases when rather complex algorithms have to be used
kpeter@29
   137
on a subgraph (e.g. when the nodes and arcs have to be traversed several
kpeter@29
   138
times), it could worth copying the altered graph into an efficient structure
kpeter@29
   139
and run the algorithm on it.
kpeter@29
   140
Note that the adaptor classes can also be used for doing this easily,
kpeter@29
   141
without having to copy the graph manually, as shown in the following
kpeter@29
   142
example.
kpeter@29
   143
kpeter@29
   144
\code
kpeter@29
   145
  ListDigraph g;
kpeter@29
   146
  ListDigraph::NodeMap<bool> filter_map(g);
kpeter@29
   147
  // construct the graph and fill the filter map
kpeter@29
   148
kpeter@29
   149
  {
kpeter@29
   150
    SmartDigraph temp_graph;
kpeter@29
   151
    ListDigraph::NodeMap<SmartDigraph::Node> node_ref(g);
kpeter@29
   152
    digraphCopy(filterNodes(g, filter_map), temp_graph)
kpeter@29
   153
      .nodeRef(node_ref).run();
kpeter@29
   154
kpeter@29
   155
    // use temp_graph
kpeter@29
   156
  }
kpeter@29
   157
\endcode
kpeter@29
   158
kpeter@29
   159
<hr>
kpeter@29
   160
kpeter@29
   161
Another interesting adaptor in LEMON is \ref SplitNodes.
kpeter@29
   162
It can be used for splitting each node into an in-node and an out-node
kpeter@29
   163
in a directed graph. Formally, the adaptor replaces each node
kpeter@29
   164
u in the graph with two nodes, namely node u<sub>in</sub> and node
kpeter@29
   165
u<sub>out</sub>. Each arc (u,c) in the original graph will correspond to an
kpeter@29
   166
arc (u<sub>out</sub>,v<sub>in</sub>). The adaptor also adds an
kpeter@29
   167
additional bind arc (u<sub>in</sub>,u<sub>out</sub>) for each node u
kpeter@29
   168
of the original digraph.
kpeter@29
   169
kpeter@29
   170
The aim of this class is to assign costs to the nodes when using
kpeter@29
   171
algorithms which would otherwise consider arc costs only.
kpeter@29
   172
For example, let us suppose that we have a directed graph with costs
kpeter@29
   173
given for both the nodes and the arcs.
kpeter@29
   174
Then Dijkstra's algorithm can be used in connection with \ref SplitNodes
kpeter@29
   175
as follows.
kpeter@29
   176
kpeter@29
   177
\code
kpeter@29
   178
  typedef SplitNodes<ListDigraph> SplitGraph;
kpeter@29
   179
  SplitGraph sg(g);
kpeter@29
   180
  SplitGraph::CombinedArcMap<NodeCostMap, ArcCostMap>
kpeter@29
   181
    combined_cost(node_cost, arc_cost);
kpeter@29
   182
  SplitGraph::NodeMap<double> dist(sg);
kpeter@29
   183
  dijkstra(sg, combined_cost).distMap(dist).run(sg.outNode(u));
kpeter@29
   184
\endcode
kpeter@29
   185
kpeter@29
   186
Note that this problem can be solved more efficiently with
kpeter@29
   187
map adaptors.
kpeter@29
   188
kpeter@29
   189
These techniques help writing compact and elegant code, and makes it possible
kpeter@29
   190
to easily implement complex algorithms based on well tested standard components.
kpeter@29
   191
For instance, in flow and matching problems the residual graph is of
kpeter@29
   192
particular importance.
kpeter@29
   193
Combining \ref ResidualDigraph adaptor with various algorithms, a
kpeter@29
   194
range of weighted and cardinality optimization methods can be obtained
kpeter@29
   195
directly.
kpeter@29
   196
kpeter@29
   197
[TRAILER]
kpeter@29
   198
*/
kpeter@29
   199
}