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