doc/quicktour.dox
author athos
Fri, 01 Jul 2005 10:33:27 +0000
changeset 1527 7ceab500e1f6
parent 1522 321661278137
child 1528 1aa71600000c
permissions -rw-r--r--
Doc review+corrections in my own documentation according to the reviewers comments.
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@1522
    27
<ul> <li> The first thing to discuss is the way one can create data structures
athos@1522
    28
like graphs and maps in a program using LEMON. 
athos@1522
    29
//There are more graph types
athos@1522
    30
//implemented in LEMON and you can implement your own graph type just as well:
athos@1522
    31
//read more about this in the already mentioned page on \ref graphs "graphs".
athos@1522
    32
athos@1522
    33
First we show how to add nodes and edges to a graph manually. We will also
athos@1522
    34
define a map on the edges of the graph. After this we show the way one can
athos@1522
    35
read a graph (and perhaps maps on it) from a stream (e.g. a file). Of course
athos@1522
    36
we also have routines that write a graph (and perhaps maps) to a stream
athos@1522
    37
(file): this will also be shown. LEMON supports the DIMACS file formats to
athos@1522
    38
store network optimization problems, but more importantly we also have our own
athos@1522
    39
file format that gives a more flexible way to store data related to network
athos@1522
    40
optimization.
athos@1522
    41
athos@1522
    42
<ol> <li>The following code fragment shows how to fill a graph with
athos@1522
    43
data. It creates a complete graph on 4 nodes. The type Listgraph is one of the
athos@1522
    44
LEMON graph types: the typedefs in the beginning are for convenience and we
athos@1522
    45
will suppose them later as well.  
athos@1522
    46
athos@1526
    47
\dontinclude hello_lemon.cc
athos@1526
    48
\skip ListGraph
athos@1526
    49
\until addEdge
athos@1522
    50
athos@1526
    51
See the whole program in file \ref hello_lemon.cc in \c demo subdir of
athos@1526
    52
LEMON package.
athos@1175
    53
athos@1526
    54
    If you want to read more on the LEMON graph structures and
athos@1526
    55
concepts, read the page about \ref graphs "graphs".
athos@1522
    56
athos@1526
    57
<li> The following code shows how to read a graph from a stream
athos@1526
    58
(e.g. a file) in the DIMACS file format (find the documentation of the
athos@1526
    59
DIMACS file formats on the web).
athos@1522
    60
athos@1181
    61
\code
athos@1181
    62
Graph g;
athos@1181
    63
std::ifstream f("graph.dim");
athos@1181
    64
readDimacs(f, g);
athos@1181
    65
\endcode
athos@1522
    66
athos@1526
    67
One can also store network (graph+capacity on the edges) instances and
athos@1526
    68
other things (minimum cost flow instances etc.) in DIMACS format and
athos@1526
    69
use these in LEMON: to see the details read the documentation of the
athos@1526
    70
\ref dimacs.h "Dimacs file format reader". There you will also find
athos@1526
    71
the details about the output routines into files of the DIMACS format.
athos@1522
    72
athos@1526
    73
<li>DIMACS formats could not give us the flexibility we needed,
athos@1522
    74
so we worked out our own file format. Instead of any explanation let us give a
athos@1522
    75
short example file in this format: read the detailed description of the LEMON
athos@1522
    76
graph file format and input-output routines \ref graph-io-page here.
athos@1522
    77
athos@1522
    78
So here is a file describing a graph of 10 nodes (0 to 9), two nodemaps
athos@1522
    79
(called \c coordinates_x and \c coordinates_y), several edges, an edge map
athos@1522
    80
called \c length and two designated nodes (called \c source and \c target).
athos@1522
    81
athos@1522
    82
\todo Maybe another example would be better here.
athos@1522
    83
athos@1522
    84
\code
athos@1522
    85
@nodeset
athos@1522
    86
id	coordinates_x	coordinates_y	
athos@1522
    87
9	447.907	578.328	
athos@1522
    88
8	79.2573	909.464	
athos@1522
    89
7	878.677	960.04	
athos@1522
    90
6	11.5504	938.413	
athos@1522
    91
5	327.398	815.035	
athos@1522
    92
4	427.002	954.002	
athos@1522
    93
3	148.549	753.748	
athos@1522
    94
2	903.889	326.476	
athos@1522
    95
1	408.248	577.327	
athos@1522
    96
0	189.239	92.5316	
athos@1522
    97
@edgeset
athos@1522
    98
		length	
athos@1522
    99
2	3	901.074	
athos@1522
   100
8	5	270.85	
athos@1522
   101
6	9	601.553	
athos@1522
   102
5	9	285.022	
athos@1522
   103
9	4	408.091	
athos@1522
   104
3	0	719.712	
athos@1522
   105
7	5	612.836	
athos@1522
   106
0	4	933.353	
athos@1522
   107
5	0	778.871	
athos@1522
   108
5	5	0	
athos@1522
   109
7	1	664.049	
athos@1522
   110
5	5	0	
athos@1522
   111
0	9	560.464	
athos@1522
   112
4	8	352.36	
athos@1522
   113
4	9	399.625	
athos@1522
   114
4	1	402.171	
athos@1522
   115
1	2	591.688	
athos@1522
   116
3	8	182.376	
athos@1522
   117
4	5	180.254	
athos@1522
   118
3	1	345.283	
athos@1522
   119
5	4	184.511	
athos@1522
   120
6	2	1112.45	
athos@1522
   121
0	1	556.624	
athos@1522
   122
@nodes
athos@1522
   123
source	1	
athos@1522
   124
target	8	
athos@1522
   125
@end
athos@1522
   126
\endcode
athos@1522
   127
athos@1522
   128
Finally let us give a simple example that reads a graph from a file and writes
athos@1522
   129
it to another.
athos@1522
   130
athos@1522
   131
\todo This is to be done!
athos@1181
   132
athos@1514
   133
</ol>
athos@1514
   134
<li> If you want to solve some transportation problems in a network then 
athos@1175
   135
you will want to find shortest paths between nodes of a graph. This is 
athos@1175
   136
usually solved using Dijkstra's algorithm. A utility
athos@1175
   137
that solves this is  the \ref lemon::Dijkstra "LEMON Dijkstra class".
athos@1522
   138
The following code is a simple program using the 
athos@1522
   139
\ref lemon::Dijkstra "LEMON Dijkstra class" and it also shows how to define a map on the edges (the length
athos@1183
   140
function):
athos@1175
   141
athos@1175
   142
\code
athos@1183
   143
athos@1183
   144
    typedef ListGraph Graph;
athos@1183
   145
    typedef Graph::Node Node;
athos@1183
   146
    typedef Graph::Edge Edge;
athos@1183
   147
    typedef Graph::EdgeMap<int> LengthMap;
athos@1183
   148
athos@1183
   149
    Graph g;
athos@1183
   150
athos@1183
   151
    //An example from Ahuja's book
athos@1183
   152
athos@1183
   153
    Node s=g.addNode();
athos@1183
   154
    Node v2=g.addNode();
athos@1183
   155
    Node v3=g.addNode();
athos@1183
   156
    Node v4=g.addNode();
athos@1183
   157
    Node v5=g.addNode();
athos@1183
   158
    Node t=g.addNode();
athos@1183
   159
athos@1183
   160
    Edge s_v2=g.addEdge(s, v2);
athos@1183
   161
    Edge s_v3=g.addEdge(s, v3);
athos@1183
   162
    Edge v2_v4=g.addEdge(v2, v4);
athos@1183
   163
    Edge v2_v5=g.addEdge(v2, v5);
athos@1183
   164
    Edge v3_v5=g.addEdge(v3, v5);
athos@1183
   165
    Edge v4_t=g.addEdge(v4, t);
athos@1183
   166
    Edge v5_t=g.addEdge(v5, t);
athos@1183
   167
  
athos@1183
   168
    LengthMap len(g);
athos@1183
   169
athos@1183
   170
    len.set(s_v2, 10);
athos@1183
   171
    len.set(s_v3, 10);
athos@1183
   172
    len.set(v2_v4, 5);
athos@1183
   173
    len.set(v2_v5, 8);
athos@1183
   174
    len.set(v3_v5, 5);
athos@1183
   175
    len.set(v4_t, 8);
athos@1183
   176
    len.set(v5_t, 8);
athos@1183
   177
athos@1511
   178
    std::cout << "The id of s is " << g.id(s)<< std::endl;
athos@1511
   179
    std::cout <<"The id of t is " << g.id(t)<<"."<<std::endl;
athos@1183
   180
athos@1183
   181
    std::cout << "Dijkstra algorithm test..." << std::endl;
athos@1183
   182
athos@1183
   183
    Dijkstra<Graph, LengthMap> dijkstra_test(g,len);
athos@1183
   184
    
athos@1183
   185
    dijkstra_test.run(s);
athos@1183
   186
athos@1183
   187
    
athos@1183
   188
    std::cout << "The distance of node t from node s: " << dijkstra_test.dist(t)<<std::endl;
athos@1183
   189
athos@1511
   190
    std::cout << "The shortest path from s to t goes through the following nodes" <<std::endl;
athos@1511
   191
 std::cout << " (the first one is t, the last one is s): "<<std::endl;
athos@1183
   192
athos@1183
   193
    for (Node v=t;v != s; v=dijkstra_test.predNode(v)){
athos@1183
   194
	std::cout << g.id(v) << "<-";
athos@1183
   195
    }
athos@1183
   196
    std::cout << g.id(s) << std::endl;	
athos@1175
   197
\endcode
athos@1175
   198
alpar@1287
   199
See the whole program in \ref dijkstra_demo.cc.
athos@1183
   200
athos@1183
   201
The first part of the code is self-explanatory: we build the graph and set the
athos@1183
   202
length values of the edges. Then we instantiate a member of the Dijkstra class
athos@1183
   203
and run the Dijkstra algorithm from node \c s. After this we read some of the
athos@1183
   204
results. 
athos@1183
   205
You can do much more with the Dijkstra class, for example you can run it step
athos@1183
   206
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
   207
athos@1183
   208
athos@1514
   209
<li> If you want to design a network and want to minimize the total length
athos@1175
   210
of wires then you might be looking for a <b>minimum spanning tree</b> in
athos@1175
   211
an undirected graph. This can be found using the Kruskal algorithm: the 
athos@1175
   212
class \ref lemon::Kruskal "LEMON Kruskal class" does this job for you.
athos@1175
   213
The following code fragment shows an example:
athos@1175
   214
athos@1511
   215
Ide Zsuzska fog irni!
athos@1511
   216
athos@1517
   217
<li>Many problems in network optimization can be formalized by means
athos@1517
   218
of a linear programming problem (LP problem, for short). In our
athos@1517
   219
library we decided not to write an LP solver, since such packages are
athos@1517
   220
available in the commercial world just as well as in the open source
athos@1517
   221
world, and it is also a difficult task to compete these. Instead we
athos@1517
   222
decided to develop an interface that makes it easier to use these
athos@1517
   223
solvers together with LEMON. The advantage of this approach is
athos@1517
   224
twofold. Firstly our C++ interface is more comfortable than the
athos@1517
   225
solvers' native interface. Secondly, changing the underlying solver in
athos@1517
   226
a certain software using LEMON's LP interface needs zero effort. So,
athos@1517
   227
for example, one may try his idea using a free solver, demonstrate its
athos@1517
   228
usability for a customer and if it works well, but the performance
athos@1517
   229
should be improved, then one may decide to purchase and use a better
athos@1517
   230
commercial solver.
athos@1517
   231
athos@1517
   232
So far we have an
athos@1526
   233
interface for the commercial LP solver software \b CPLEX (developed by ILOG)
athos@1514
   234
and for the open source solver \b GLPK (a shorthand for Gnu Linear Programming
athos@1517
   235
Toolkit).
athos@1514
   236
athos@1514
   237
We will show two examples, the first one shows how simple it is to formalize
athos@1514
   238
and solve an LP problem in LEMON, while the second one shows how LEMON
athos@1514
   239
facilitates solving network optimization problems using LP solvers.
athos@1514
   240
athos@1514
   241
<ol>
athos@1514
   242
<li>The following code shows how to solve an LP problem using the LEMON lp
athos@1517
   243
interface. The code together with the comments is self-explanatory.
athos@1511
   244
athos@1175
   245
\code
athos@1175
   246
athos@1514
   247
  //A default solver is taken
athos@1514
   248
  LpDefault lp;
athos@1514
   249
  typedef LpDefault::Row Row;
athos@1514
   250
  typedef LpDefault::Col Col;
athos@1514
   251
  
athos@1514
   252
athos@1514
   253
  //This will be a maximization
athos@1514
   254
  lp.max();
athos@1514
   255
athos@1514
   256
  //We add coloumns (variables) to our problem
athos@1514
   257
  Col x1 = lp.addCol();
athos@1514
   258
  Col x2 = lp.addCol();
athos@1514
   259
  Col x3 = lp.addCol();
athos@1514
   260
athos@1514
   261
  //Constraints
athos@1514
   262
  lp.addRow(x1+x2+x3 <=100);  
athos@1514
   263
  lp.addRow(10*x1+4*x2+5*x3<=600);  
athos@1514
   264
  lp.addRow(2*x1+2*x2+6*x3<=300);  
athos@1514
   265
  //Nonnegativity of the variables
athos@1514
   266
  lp.colLowerBound(x1, 0);
athos@1514
   267
  lp.colLowerBound(x2, 0);
athos@1514
   268
  lp.colLowerBound(x3, 0);
athos@1514
   269
  //Objective function
athos@1514
   270
  lp.setObj(10*x1+6*x2+4*x3);
athos@1514
   271
  
athos@1514
   272
  //Call the routine of the underlying LP solver
athos@1514
   273
  lp.solve();
athos@1514
   274
athos@1514
   275
  //Print results
athos@1514
   276
  if (lp.primalStatus()==LpSolverBase::OPTIMAL){
athos@1514
   277
    printf("Z = %g; x1 = %g; x2 = %g; x3 = %g\n", 
athos@1514
   278
	   lp.primalValue(), 
athos@1514
   279
	   lp.primal(x1), lp.primal(x2), lp.primal(x3));
athos@1514
   280
  }
athos@1514
   281
  else{
athos@1514
   282
    std::cout<<"Optimal solution not found!"<<std::endl;
athos@1514
   283
  }
athos@1514
   284
athos@1514
   285
athos@1175
   286
\endcode
athos@1175
   287
athos@1514
   288
See the whole code in \ref lp_demo.cc.
athos@1514
   289
athos@1517
   290
<li>The second example shows how easy it is to formalize a max-flow
athos@1517
   291
problem as an LP problem using the LEMON LP interface: we are looking
athos@1517
   292
for a real valued function defined on the edges of the digraph
athos@1517
   293
satisfying the nonnegativity-, the capacity constraints and the
athos@1517
   294
flow-conservation constraints and giving the largest flow value
athos@1517
   295
between to designated nodes.
athos@1517
   296
athos@1517
   297
In the following code we suppose that we already have the graph \c g,
athos@1517
   298
the capacity map \c cap, the source node \c s and the target node \c t
athos@1517
   299
in the memory. We will also omit the typedefs.
athos@1517
   300
athos@1517
   301
\code
athos@1517
   302
  //Define a map on the edges for the variables of the LP problem
athos@1517
   303
  typename G::template EdgeMap<LpDefault::Col> x(g);
athos@1517
   304
  lp.addColSet(x);
athos@1517
   305
  
athos@1517
   306
  //Nonnegativity and capacity constraints
athos@1517
   307
  for(EdgeIt e(g);e!=INVALID;++e) {
athos@1517
   308
    lp.colUpperBound(x[e],cap[e]);
athos@1517
   309
    lp.colLowerBound(x[e],0);
athos@1517
   310
  }
athos@1517
   311
athos@1517
   312
athos@1517
   313
  //Flow conservation constraints for the nodes (except for 's' and 't')
athos@1517
   314
  for(NodeIt n(g);n!=INVALID;++n) if(n!=s&&n!=t) {
athos@1517
   315
    LpDefault::Expr ex;
athos@1517
   316
    for(InEdgeIt  e(g,n);e!=INVALID;++e) ex+=x[e];
athos@1517
   317
    for(OutEdgeIt e(g,n);e!=INVALID;++e) ex-=x[e];
athos@1517
   318
    lp.addRow(ex==0);
athos@1517
   319
  }
athos@1517
   320
  
athos@1517
   321
  //Objective function: the flow value entering 't'
athos@1517
   322
  {
athos@1517
   323
    LpDefault::Expr ex;
athos@1517
   324
    for(InEdgeIt  e(g,t);e!=INVALID;++e) ex+=x[e];
athos@1517
   325
    for(OutEdgeIt e(g,t);e!=INVALID;++e) ex-=x[e];
athos@1517
   326
    lp.setObj(ex);
athos@1517
   327
  }
athos@1517
   328
athos@1517
   329
  //Maximization
athos@1517
   330
  lp.max();
athos@1517
   331
athos@1517
   332
  //Solve with the underlying solver
athos@1517
   333
  lp.solve();
athos@1517
   334
athos@1517
   335
\endcode
athos@1517
   336
athos@1517
   337
The complete program can be found in file \ref lp_maxflow_demo.cc. After compiling run it in the form:
athos@1517
   338
athos@1517
   339
<tt>./lp_maxflow_demo < ?????????.lgf</tt>
athos@1517
   340
athos@1521
   341
where ?????????.lgf is a file in the lemon format containing a maxflow instance (designated "source", "target" nodes and "capacity" map on the edges).
athos@1517
   342
athos@1517
   343
athos@1514
   344
athos@1514
   345
</ol>
athos@1514
   346
</ul>
athos@1175
   347
athos@1175
   348
*/