doc/quicktour.dox
author athos
Mon, 27 Jun 2005 15:22:34 +0000
changeset 1517 b303c1741c9a
parent 1514 c9b9bc63db4e
child 1521 5815b382421b
permissions -rw-r--r--
Some modifications in this and that.
athos@1169
     1
/**
athos@1169
     2
alpar@1170
     3
\page quicktour Quick Tour to LEMON
alpar@1170
     4
athos@1175
     5
Let us first answer the question <b>"What do I want to use LEMON for?"
athos@1175
     6
</b>. 
athos@1175
     7
LEMON is a C++ library, so you can use it if you want to write C++ 
athos@1175
     8
programs. What kind of tasks does the library LEMON help to solve? 
athos@1175
     9
It helps to write programs that solve optimization problems that arise
athos@1175
    10
frequently when <b>designing and testing certain networks</b>, for example
athos@1175
    11
in telecommunication, computer networks, and other areas that I cannot
athos@1175
    12
think of now. A very natural way of modelling these networks is by means
athos@1183
    13
of a <b> graph</b> (we will always mean a directed graph by that and say
athos@1183
    14
<b> undirected graph </b> otherwise). 
athos@1175
    15
So if you want to write a program that works with 
athos@1183
    16
graphs then you might find it useful to use our library LEMON. LEMON 
athos@1183
    17
defines various graph concepts depending on what you want to do with the 
athos@1183
    18
graph: a very good description can be found in the page
athos@1183
    19
about \ref graphs "graphs".
athos@1175
    20
athos@1514
    21
You will also want to assign data to the edges or nodes of the graph, for
athos@1514
    22
example a length or capacity function defined on the edges. You can do this in
athos@1514
    23
LEMON using so called \b maps. You can define a map on the nodes or on the edges of the graph and the value of the map (the range of the function) can be practically almost of any type. Read more about maps \ref maps-page "here".
athos@1175
    24
athos@1511
    25
Some examples are the following (you will find links next to the code fragments that help to download full demo programs: save them on your computer and compile them according to the description in the page about \ref getsart How to start using LEMON):
athos@1175
    26
athos@1514
    27
<ul>
athos@1514
    28
<li> First we give two examples that show how to instantiate a graph. The
athos@1175
    29
first one shows the methods that add nodes and edges, but one will
athos@1175
    30
usually use the second way which reads a graph from a stream (file).
athos@1514
    31
<ol>
athos@1514
    32
<li>The following code fragment shows how to fill a graph with data. It creates a complete graph on 4 nodes. The type Listgraph is one of the LEMON graph types: the typedefs in the beginning are for convenience and we will suppose them later as well.
athos@1175
    33
 \code
athos@1175
    34
  typedef ListGraph Graph;
athos@1175
    35
  typedef Graph::NodeIt NodeIt;
athos@1175
    36
athos@1175
    37
  Graph g;
athos@1175
    38
  
athos@1175
    39
  for (int i = 0; i < 3; i++)
athos@1175
    40
    g.addNode();
athos@1175
    41
  
athos@1175
    42
  for (NodeIt i(g); i!=INVALID; ++i)
athos@1175
    43
    for (NodeIt j(g); j!=INVALID; ++j)
athos@1175
    44
      if (i != j) g.addEdge(i, j);
athos@1175
    45
 \endcode 
athos@1175
    46
athos@1511
    47
See the whole program in file \ref helloworld.cc.
athos@1511
    48
athos@1514
    49
    If you want to read more on the LEMON graph structures and concepts, read the page about \ref graphs "graphs". 
athos@1181
    50
athos@1514
    51
<li> The following code shows how to read a graph from a stream (e.g. a file). LEMON supports the DIMACS file format: it can read a graph instance from a file 
athos@1511
    52
in that format (find the documentation of the DIMACS file format on the web). 
athos@1181
    53
\code
athos@1181
    54
Graph g;
athos@1181
    55
std::ifstream f("graph.dim");
athos@1181
    56
readDimacs(f, g);
athos@1181
    57
\endcode
athos@1183
    58
One can also store network (graph+capacity on the edges) instances and other things in DIMACS format and use these in LEMON: to see the details read the documentation of the \ref dimacs.h "Dimacs file format reader".
athos@1181
    59
athos@1514
    60
</ol>
athos@1514
    61
<li> If you want to solve some transportation problems in a network then 
athos@1175
    62
you will want to find shortest paths between nodes of a graph. This is 
athos@1175
    63
usually solved using Dijkstra's algorithm. A utility
athos@1175
    64
that solves this is  the \ref lemon::Dijkstra "LEMON Dijkstra class".
athos@1183
    65
The following code is a simple program using the \ref lemon::Dijkstra "LEMON
athos@1183
    66
Dijkstra class" and it also shows how to define a map on the edges (the length
athos@1183
    67
function):
athos@1175
    68
athos@1175
    69
\code
athos@1183
    70
athos@1183
    71
    typedef ListGraph Graph;
athos@1183
    72
    typedef Graph::Node Node;
athos@1183
    73
    typedef Graph::Edge Edge;
athos@1183
    74
    typedef Graph::EdgeMap<int> LengthMap;
athos@1183
    75
athos@1183
    76
    Graph g;
athos@1183
    77
athos@1183
    78
    //An example from Ahuja's book
athos@1183
    79
athos@1183
    80
    Node s=g.addNode();
athos@1183
    81
    Node v2=g.addNode();
athos@1183
    82
    Node v3=g.addNode();
athos@1183
    83
    Node v4=g.addNode();
athos@1183
    84
    Node v5=g.addNode();
athos@1183
    85
    Node t=g.addNode();
athos@1183
    86
athos@1183
    87
    Edge s_v2=g.addEdge(s, v2);
athos@1183
    88
    Edge s_v3=g.addEdge(s, v3);
athos@1183
    89
    Edge v2_v4=g.addEdge(v2, v4);
athos@1183
    90
    Edge v2_v5=g.addEdge(v2, v5);
athos@1183
    91
    Edge v3_v5=g.addEdge(v3, v5);
athos@1183
    92
    Edge v4_t=g.addEdge(v4, t);
athos@1183
    93
    Edge v5_t=g.addEdge(v5, t);
athos@1183
    94
  
athos@1183
    95
    LengthMap len(g);
athos@1183
    96
athos@1183
    97
    len.set(s_v2, 10);
athos@1183
    98
    len.set(s_v3, 10);
athos@1183
    99
    len.set(v2_v4, 5);
athos@1183
   100
    len.set(v2_v5, 8);
athos@1183
   101
    len.set(v3_v5, 5);
athos@1183
   102
    len.set(v4_t, 8);
athos@1183
   103
    len.set(v5_t, 8);
athos@1183
   104
athos@1511
   105
    std::cout << "The id of s is " << g.id(s)<< std::endl;
athos@1511
   106
    std::cout <<"The id of t is " << g.id(t)<<"."<<std::endl;
athos@1183
   107
athos@1183
   108
    std::cout << "Dijkstra algorithm test..." << std::endl;
athos@1183
   109
athos@1183
   110
    Dijkstra<Graph, LengthMap> dijkstra_test(g,len);
athos@1183
   111
    
athos@1183
   112
    dijkstra_test.run(s);
athos@1183
   113
athos@1183
   114
    
athos@1183
   115
    std::cout << "The distance of node t from node s: " << dijkstra_test.dist(t)<<std::endl;
athos@1183
   116
athos@1511
   117
    std::cout << "The shortest path from s to t goes through the following nodes" <<std::endl;
athos@1511
   118
 std::cout << " (the first one is t, the last one is s): "<<std::endl;
athos@1183
   119
athos@1183
   120
    for (Node v=t;v != s; v=dijkstra_test.predNode(v)){
athos@1183
   121
	std::cout << g.id(v) << "<-";
athos@1183
   122
    }
athos@1183
   123
    std::cout << g.id(s) << std::endl;	
athos@1175
   124
\endcode
athos@1175
   125
alpar@1287
   126
See the whole program in \ref dijkstra_demo.cc.
athos@1183
   127
athos@1183
   128
The first part of the code is self-explanatory: we build the graph and set the
athos@1183
   129
length values of the edges. Then we instantiate a member of the Dijkstra class
athos@1183
   130
and run the Dijkstra algorithm from node \c s. After this we read some of the
athos@1183
   131
results. 
athos@1183
   132
You can do much more with the Dijkstra class, for example you can run it step
athos@1183
   133
by step and gain full control of the execution. For a detailed description, see the documentation of the \ref lemon::Dijkstra "LEMON Dijkstra class".
athos@1183
   134
athos@1183
   135
athos@1514
   136
<li> If you want to design a network and want to minimize the total length
athos@1175
   137
of wires then you might be looking for a <b>minimum spanning tree</b> in
athos@1175
   138
an undirected graph. This can be found using the Kruskal algorithm: the 
athos@1175
   139
class \ref lemon::Kruskal "LEMON Kruskal class" does this job for you.
athos@1175
   140
The following code fragment shows an example:
athos@1175
   141
athos@1511
   142
Ide Zsuzska fog irni!
athos@1511
   143
athos@1517
   144
<li>Many problems in network optimization can be formalized by means
athos@1517
   145
of a linear programming problem (LP problem, for short). In our
athos@1517
   146
library we decided not to write an LP solver, since such packages are
athos@1517
   147
available in the commercial world just as well as in the open source
athos@1517
   148
world, and it is also a difficult task to compete these. Instead we
athos@1517
   149
decided to develop an interface that makes it easier to use these
athos@1517
   150
solvers together with LEMON. The advantage of this approach is
athos@1517
   151
twofold. Firstly our C++ interface is more comfortable than the
athos@1517
   152
solvers' native interface. Secondly, changing the underlying solver in
athos@1517
   153
a certain software using LEMON's LP interface needs zero effort. So,
athos@1517
   154
for example, one may try his idea using a free solver, demonstrate its
athos@1517
   155
usability for a customer and if it works well, but the performance
athos@1517
   156
should be improved, then one may decide to purchase and use a better
athos@1517
   157
commercial solver.
athos@1517
   158
athos@1517
   159
So far we have an
athos@1514
   160
interface for the commercial LP solver software \b CLPLEX (developed by ILOG)
athos@1514
   161
and for the open source solver \b GLPK (a shorthand for Gnu Linear Programming
athos@1517
   162
Toolkit).
athos@1514
   163
athos@1514
   164
We will show two examples, the first one shows how simple it is to formalize
athos@1514
   165
and solve an LP problem in LEMON, while the second one shows how LEMON
athos@1514
   166
facilitates solving network optimization problems using LP solvers.
athos@1514
   167
athos@1514
   168
<ol>
athos@1514
   169
<li>The following code shows how to solve an LP problem using the LEMON lp
athos@1517
   170
interface. The code together with the comments is self-explanatory.
athos@1511
   171
athos@1175
   172
\code
athos@1175
   173
athos@1514
   174
  //A default solver is taken
athos@1514
   175
  LpDefault lp;
athos@1514
   176
  typedef LpDefault::Row Row;
athos@1514
   177
  typedef LpDefault::Col Col;
athos@1514
   178
  
athos@1514
   179
athos@1514
   180
  //This will be a maximization
athos@1514
   181
  lp.max();
athos@1514
   182
athos@1514
   183
  //We add coloumns (variables) to our problem
athos@1514
   184
  Col x1 = lp.addCol();
athos@1514
   185
  Col x2 = lp.addCol();
athos@1514
   186
  Col x3 = lp.addCol();
athos@1514
   187
athos@1514
   188
  //Constraints
athos@1514
   189
  lp.addRow(x1+x2+x3 <=100);  
athos@1514
   190
  lp.addRow(10*x1+4*x2+5*x3<=600);  
athos@1514
   191
  lp.addRow(2*x1+2*x2+6*x3<=300);  
athos@1514
   192
  //Nonnegativity of the variables
athos@1514
   193
  lp.colLowerBound(x1, 0);
athos@1514
   194
  lp.colLowerBound(x2, 0);
athos@1514
   195
  lp.colLowerBound(x3, 0);
athos@1514
   196
  //Objective function
athos@1514
   197
  lp.setObj(10*x1+6*x2+4*x3);
athos@1514
   198
  
athos@1514
   199
  //Call the routine of the underlying LP solver
athos@1514
   200
  lp.solve();
athos@1514
   201
athos@1514
   202
  //Print results
athos@1514
   203
  if (lp.primalStatus()==LpSolverBase::OPTIMAL){
athos@1514
   204
    printf("Z = %g; x1 = %g; x2 = %g; x3 = %g\n", 
athos@1514
   205
	   lp.primalValue(), 
athos@1514
   206
	   lp.primal(x1), lp.primal(x2), lp.primal(x3));
athos@1514
   207
  }
athos@1514
   208
  else{
athos@1514
   209
    std::cout<<"Optimal solution not found!"<<std::endl;
athos@1514
   210
  }
athos@1514
   211
athos@1514
   212
athos@1175
   213
\endcode
athos@1175
   214
athos@1514
   215
See the whole code in \ref lp_demo.cc.
athos@1514
   216
athos@1517
   217
<li>The second example shows how easy it is to formalize a max-flow
athos@1517
   218
problem as an LP problem using the LEMON LP interface: we are looking
athos@1517
   219
for a real valued function defined on the edges of the digraph
athos@1517
   220
satisfying the nonnegativity-, the capacity constraints and the
athos@1517
   221
flow-conservation constraints and giving the largest flow value
athos@1517
   222
between to designated nodes.
athos@1517
   223
athos@1517
   224
In the following code we suppose that we already have the graph \c g,
athos@1517
   225
the capacity map \c cap, the source node \c s and the target node \c t
athos@1517
   226
in the memory. We will also omit the typedefs.
athos@1517
   227
athos@1517
   228
\code
athos@1517
   229
  //Define a map on the edges for the variables of the LP problem
athos@1517
   230
  typename G::template EdgeMap<LpDefault::Col> x(g);
athos@1517
   231
  lp.addColSet(x);
athos@1517
   232
  
athos@1517
   233
  //Nonnegativity and capacity constraints
athos@1517
   234
  for(EdgeIt e(g);e!=INVALID;++e) {
athos@1517
   235
    lp.colUpperBound(x[e],cap[e]);
athos@1517
   236
    lp.colLowerBound(x[e],0);
athos@1517
   237
  }
athos@1517
   238
athos@1517
   239
athos@1517
   240
  //Flow conservation constraints for the nodes (except for 's' and 't')
athos@1517
   241
  for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) {
athos@1517
   242
    LpDefault::Expr ex;
athos@1517
   243
    for(InEdgeIt  e(g,n);e!=INVALID;++e) ex+=x[e];
athos@1517
   244
    for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e];
athos@1517
   245
    lp.addRow(ex==0);
athos@1517
   246
  }
athos@1517
   247
  
athos@1517
   248
  //Objective function: the flow value entering 't'
athos@1517
   249
  {
athos@1517
   250
    LpDefault::Expr ex;
athos@1517
   251
    for(InEdgeIt  e(g,t);e!=INVALID;++e) ex+=x[e];
athos@1517
   252
    for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e];
athos@1517
   253
    lp.setObj(ex);
athos@1517
   254
  }
athos@1517
   255
athos@1517
   256
  //Maximization
athos@1517
   257
  lp.max();
athos@1517
   258
athos@1517
   259
  //Solve with the underlying solver
athos@1517
   260
  lp.solve();
athos@1517
   261
athos@1517
   262
\endcode
athos@1517
   263
athos@1517
   264
The complete program can be found in file \ref lp_maxflow_demo.cc. After compiling run it in the form:
athos@1517
   265
athos@1517
   266
<tt>./lp_maxflow_demo < ?????????.lgf</tt>
athos@1517
   267
athos@1517
   268
where ?????????.lgf is a file in the lemon format containing a maxflow instance (designated "source", "target" nodes and "capacity" map).
athos@1517
   269
athos@1517
   270
athos@1517
   271
See the whole code in \ref lp_demo.cc.
athos@1517
   272
athos@1514
   273
athos@1514
   274
</ol>
athos@1514
   275
</ul>
athos@1175
   276
athos@1175
   277
*/