File: _doxygen.h

package info (click to toggle)
polymake 4.14-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 35,888 kB
  • sloc: cpp: 168,933; perl: 43,407; javascript: 31,575; ansic: 3,007; java: 2,654; python: 632; sh: 268; xml: 117; makefile: 61
file content (401 lines) | stat: -rw-r--r-- 19,711 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
/* Copyright (c) 1997-2024
   Ewgenij Gawrilow, Michael Joswig, and the polymake team
   Technische Universität Berlin, Germany
   https://polymake.org

   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the
   Free Software Foundation; either version 2, or (at your option) any
   later version: http://www.gnu.org/licenses/gpl.txt.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
--------------------------------------------------------------------------------
*/

#pragma once
// Artificial header file whose sole purpose is to be processed by doxygen

/** @namespace pm
    @brief global namespace for all classes from the %polymake project

    The most common classes/functions/... are exported to the namespace
    polymake.  Use this for your client code.
 */

/** @namespace polymake
    @brief namespace to be used for client code
 */

namespace pm {

/** @mainpage

    @section design_sec Design Principles

    @subsection container_view_sec Container-centric view

    PTL is based on STL and makes exhaustive use of the
    three main concepts of the latter: containers, iterators, and
    functors. There is a subtle difference, however, in the implementation of
    algorithms: in STL, they are designed to work with iterators, while in PTL
    the most of them accept containers as arguments. PTL containers are more
    than pure data structures, they bear some additional semantics, in that
    they belong to one of the @ref generic "generic families".  See
    http://www.cplusplus.com/reference/stl/ for a description of STL's
    container concept.

    Besides real containers, which own their data as prescribed by the
    standard, PTL makes heavy use of @ref manipulations. The latter implement
    though the standard container interface, but do not possess any data at
    all; instead, they refer to other container objects supplying the data
    items. There are three kinds of pseudo-containers in PTL: @ref alias_sec
    alias, @ref masquerade_sec masquerade, and @ref lazy_sec "lazy
    containers".

    @subsection lazy_sec Lazy evaluation

    Many operators defined for PTL container classes, such as vector and
    matrix arithmetic, set-theoretical %operations, etc., don't perform the
    computations immediately, but rather create a temporary object which
    "remembers" the operands and the operation and evaluates it later, on
    demand. This is a well-known technique called @em{lazy evaluation},
    sometimes also referred to as @em{expression templates}. It helps to spare
    unnecessary computations and copying of objects.
    
    The lazy objects fit well in the container concept of PTL, as they always
    belong to the same generic family and implement the same container
    interface as the result of the real operation would do.

    @see 
    - @ref refcounting "Reference Counting"
    - @ref generic "Generic and Persistent Types"

    @section container_sec Container Classes

    @subsection set_sec Set Types

    - Bitset is a container class for dense sets of integers.  Data
      representation is a bit string as implemented in the GNU Multiprecision
      Library (mpz_t).
 
    - Set is a container class for sparse sets of ordered elements.  Data
      representation as a modified kind of AVL tree.

    @subsection vector_sec Vector Types

    The vector class family implement vectors in the usual algebraic notion.
    It contains three @ref generic "persistent" vector types with different
    data storage organization.  These implementations result in @ref
    vector_performance "performance differences" for various functions on
    vectors.

    - Vector holds the elements in a contiguous array.

    - SparseVector is an associative container with element indices
      (coordinates) as keys; elements equal to the default value (@c
      ElementType(), which is 0 for most numerical types) are not stored, but
      implicitly encoded by the gaps in the key set.  It is based on an AVL
      tree.

    @subsection matrix_sec Matrix Types

    The matrix class family implement matrices in the usual algebraic notion.
    It contains three @ref generic "persistent" matrix types with different
    data storage organization.

    - Matrix holds the elements in a contiguous array.

    - SparseMatrix is a two-dimensional associative array with row and column
      indices as keys; elements equal to the default value (@c ElementType(),
      which is 0 for most numerical types) are not stored, but implicitly
      encoded by the gaps in the key set. Each row and column is organized as
      an AVL::tree.

    - ListMatrix is a list of row vectors. Based on @c std::list. Can be
      parameterized with any \ref generic "persistent" \ref vector_sec "vector
      type".

    @subsection other_sec Other Container Types

    - Array class with @ref refcounting "smart pointers".

    - Map - an associative container class based on an AVL tree structure.

    - The AVL::tree class implements balanced binary search trees.

    @section generic_sec Generic Class Families

    - GenericVector - an abstract vector class

    - GenericMatrix - an abstract matrix class 

    - GenericSet - an abstract set class 

    @section gmp_sec Number Types

    These are borrowed from @ref GMP "GMP" and wrapped.

    - Integer
    - Rational
    - QuadraticExtension


    @section polytope_sec Classes Useful for Computions in Geometric Combinatorics

    - EquivalenceRelation
    - FacetList
    - graph::Graph
    - IncidenceMatrix
*/

/** @page vector_performance Performance Comparison of Vector Classes
 
    The following brief analysis might help you when choosing the most efficient representation for a concrete case.
    @a n is the number of (non-zero in sparse case) elements in the vector.

<table class="borderless" border="0" cellspacing="10">
   <caption>Performance comparison</caption>
   <tr>
      <th align="left">Operation</th>
      <th align="left">Vector</th>
      <th align="left">SparseVector</th>
   </tr>
   <tr>
      <td>sequential iteration</td>
      <td>O(n)</td>
      <td>O(n), but with greater overhead constant</td>
   </tr>
   <tr>
      <td>random element access</td>
      <td>O(1)</td>
      <td>O(log(n))</td>
   </tr>
   <tr>
      <td>append an element</td>
      <td>O(n) + reallocation costs</td>
      <td>O(1) if no preceding random access operations were performed on the sparse vector; O(log(n)) if there already were random access operations on the sparse vector</td>
   </tr>
</table>

*/

/** @page refcounting Reference Counting

   Most of the top-level PTL data structures keep their data attached to a smart pointer combined with a reference
   counter.  This technique provides for cheap copy and assignment operations and return of complex objects by value.
   As long as several objects are not changed, they can safely share a single physical collection of data.  A non-const
   access eventually forces the creation of one's own copy of the data (so called @em{copy-on-write strategy}.)
   Obviously, there's also a drawback of reference counting, since the counter checking produces some overhead.  So, one
   should declare one's objects @c const whenever one can - this will surely bring a considerable runtime gain.

   In general, another danger usually entailed by reference counting is the possibility of creating self-referenced
   cyclic structures which can never get destroyed.  However, this is impossible in the PTL, since we do not use
   any recursive list structures.
 */

/** @page generic Generic and Persistent Types

   Many of the PTL container classes have "relative" classes having much the same sematics and interface but different
   data organization as the "primary" class. Especially the wide deployment of the lazy evaluation technique has born a
   plenty of relative classes.  For instance, an object representing a sum of two vectors or a slice of a vector (both
   using lazy evaluation) should be usable in every context where a normal vector object (or at least an immutable one)
   is accepted.

   The classical approach here would be to define an abstract vector base class with all methods declared as pure
   virtual functions, and derive everything from it. Although it would be a clearer design, it causes a serious
   performance penalty due to the fact that virtual functions practically inhibit inlining, and thus impair the
   compiler's optimization. Fortunately, a template library can make use of more tricky concepts.

   A generic class is a template analogon for a classical abstract class. PTL defines a generic class template for each
   family of related classes, for instance, GenericVector for everything looking like a vector.  As in the abstract
   class approach, all concrete classes have to be derived from the generic class. And exactly as an abstract class, a
   generic class should not be instantiated "naked"; to enforce this, its constructor and destructor are always defined
   @c protected.

   To eliminate the need for virtual functions, an instance of the generic class has to know statically (i.e., already
   during the compilation,) what concrete class it belongs to. This is achieved by parameterizing the generic class (you
   remember, it's a template!) with the concrete class derived from it.  Staying by the vectors, an example would look
   like this:

   <pre>
      template &lt;typename _Vector&gt;
      class GenericVector {
         typedef _Vector top_type;
         ...
      };

      template &lt;typename ElementType&gt;
      class Vector : public GenericVector&lt; Vector&lt;ElementType&gt; &gt; { ... };
   </pre>

   It this setting it is very easy for the generic class instance to achieve the full concrete object: it's just
   a @c{ static_cast<top_type*>(this) }.  Such an inverted cast is explicitly allowed by the ANSI/ISO
   Standard C++.  To keep the code more readable, each generic class defines a @c top() method encapsulating
   exactly this cast (in fact, two methods, with and without @c const.)

   The same cast can be applied by every external function working with class families as well:

   <pre>
      template &lt;typename _Vector&gt;
      void f(const GenericVector&lt;_Vector&gt;& v) {
         int s=v.top().size();
         ...
      }
   </pre>

   In many cases, however, the cast is not necessary, since many methods are defined already in the generic class;
   please consult the documentation of the corresponding class family.

   The generic classes can also carry additional attributes, allowing for more fine-granular distinction between
   overloaded template functions. All these attributes are declared with default settings extracted
   from the concrete class, therefore the application functions don't always need to refer to them explicitly.
   The real PTL definition of the @c GenericVector class has the vector element type as the second parameter:

   <pre>
      template &lt;typename _Vector, typename ElementType=typename _Vector::element_type&gt;
      class GenericVector {
         typedef ElementType element_type;
         ...
      };
   </pre>

   Now you can easily distinct between two versions of an algorithm, one requiring two vectors of identical element type,
   and another handling the heterogeneous case:

   <pre>
      // homogeneous case
      template &lt;typename _Vector1, typename _Vector2, typename ElementType&gt;
      void f(const GenericVector&lt;_Vector1, ElementType&gt;& v1, const GenericVector&lt;_Vector2, ElementType&gt;& v2);

      // heterogeneous case
      template &lt;typename _Vector1, typename _Vector2&gt;
      void f(const GenericVector&lt;_Vector1&gt;& v1, const GenericVector&lt;_Vector2&gt;& v2);
   </pre>

   @section generic_caveats_sec Caveats

   However smart this technique might be, it has its not negligible caveats. First of all, it is the problem of so called
   @em{code bloat}: each function designed to work with a generic family has to be a template in its turn.
   Often this "templatization" spreads itself over the entire program module, stopping only at the @c main()
   function. This leads to considerable code size growth and to an immense time and memory consumption by the compiler.

   Another problem arises when you make a mistake in your template code: the compiler diagnostics are very
   heavy to understand, most of them referring to the code you had not written yourself, namely the guts of the
   template library. Mistakes also often stay undiscovered for long periods of time, until the method containing it
   is really used (due to the @em{lazy template instantiation} deployed by the most of the modern C++ compilers.)
   There are some recently invented approaches that can alleviated this, in particular the @em{concept checks}
   originating from the Boost library. They will be probably built in PTL, as soon as their deployment in STL
   will seem stable enough.

 */

/** @page manipulations Container Manipulations

    All constructions described on this page are similar in that they take one or more objects and produce a new object
    which behaves like a container, too.  However, in all these cases it is not a container in the strict sense: it does
    not own any data.  We will call them @em pseudo-container throughout this documentation.

    The pseudo-containers can be divided in three categories according to their functionality:

    - An @em alias pseudo-container forwards all element access operation to the original data container(s).  It can
    hide some elements away or let them appear in other order, in any case its elements are at the same times elements
    of the original container.  This implies that assigning new values to the elements of a mutable alias container in
    fact changes the elements in the original container.  }

    - A @em lazy pseudo-container computes its elements on the fly, just at the moment they are accessed to.  Thus the
    elements are temporary objects returned by container access methods (@c front(), @c back(), or @c operator[]) or
    reside in the iterator.  Traversing a lazy container object multiple times object incurs repeating computations,
    which should be kept in mind when sticking it into a multi-pass algorithm template.

    When you write an algorithm template, you can make it safe from multiple evaluation of lazy objects using the
    following construction:

    <pre>
       typename <Object>::type X=prevent_lazy<Object>::get(x);
    </pre>

    where @a x is an input parameter and @a Object its type. If @a Object is really lazy, it performs the evaluation
    exactly once and stores the results in an appropriate persistent object; if not, it does nothing.

    - A @em masquerade pseudo-container is just another view on the original object. Unlike the first two kinds, masquerade
    objects are never created: the original object address is reinterpreted instead; they even can't be created, since
    their constructors and destructors are purposely declared @c protected and left undefined.
    
    To make the classification complete, let's call the standard containers,
    whose lifetime is the same as of their elements, @em persistent.  This
    notion is traditionally used in the context of data base query languages,
    where it describes objects that can outlive the programs creating them.
    This is also applicable to objects in Polymake Template Library, since
    they can be stored in and retrieved from the a data file via the client
    communication interface without any loss in structure or contents.
    
    @section refcopy_sec Reference or copy?

    For instantiable pseudo-containers (alias and lazy) it is important to
    know how to find the original data containers.  Generally, the latter have
    a lifetime much longer than a pseudo-container object, which in the most
    cases exists during exactly one expression. Thus an internal reference to
    the original object would be sufficient.

    On the other hand, the pseudo-containers are easy to combine and nest (it
    was, after all, the main design aim to made them interchangeable building
    blocks!)  For example, one can first select a subset of elements and then
    apply an operation to it. In this case, the first operand of the outer
    pseudo-container will be the inner pseudo-container, which in its turn is
    a temporary object.  It doesn't create a problem until the entire
    construction is copied outside the scope the components are confined to.

    The best example is a @c return statement: if a function has to return the
    outer pseudo-container object, it @em{may not} contain a reference to the
    inner object, since it was created in the function's scope and will be
    destroyed after the @c return completion.  Therefore the inner object @em
    must be copied into the outer object.

    All pseudo-container objects in the Polymake Template Library can be
    configured for both scenarios. The template parameters describing the data
    sources are @em{optional references}: they can be specified as references
    as well as reference-free data types.  Note that the @em{convenience
    functions} always create pseudo-containers with internal references, as a
    more efficient and more often occurring variant; the referenceless variant
    should be used only when it's really necessary, like in the @c return
    context explained above.
    
*/

/** @page GMP Number Types, Borrowed from GMP

    Most calculations in %polymake are made exactly, using rational numbers.
    The best implementation known to us which provides arbitrary precision and
    high-tuned performance on various computer platforms, is
    http://www.swox.com/gmp/ .  On the other hand, we did like very much the
    convenient interface of the Rational and Integer classes from the (in the
    meanwhile obsolete and no more supported) libg++, which allowed to use the
    rational values in expressions in the most natural way, as if they were
    built-in numeric types.  So we have decided to union the advantages of
    both and have written thin wrapper classes mimicking the old Rational and
    Integer classes.  They perform almost no calculations on their own, but
    delegate the whole hard job to GMP functions.

    In the meanwhile, GMP has got its own C++ wrapper classes. They are
    implemented differently from our classes: all arithmetic %operators are
    "lazy", returning expression templates instead of ready results.  While
    this technique has proven to improve the performance in longer chained
    expressions, and is massively used in %polymake vector and matrix classes
    too, we consider it a bit dangerous for the basic numerical type.

    In an innocent expression like @c (a+b)*M, where @c a and @c b are
    rational scalars and @c M is a rational matrix, the sum @c a+b would be
    repeatedly calculated for each element of the resulting matrix.  Since
    such mixed expressions are prevailing in %polymake code, we have decided to
    stay with our own wrappers, relying on the so called @em{return value
    optimization} of the compiler. Future changes in GMP may let us revise
    this decision.

    GMP numbers can be constructed from the most built-in types.  They can be
    converted to each other and to the most built-in types.
*/

} // namespace pm