gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Small doc improvements + unifications in MCF classes (#180)
0 3 0
default
3 files changed with 32 insertions and 32 deletions:
↑ Collapse diff ↑
Ignore white space 24 line context
... ...
@@ -26,27 +26,27 @@
26 26

	
27 27
#include <vector>
28 28
#include <limits>
29 29
#include <lemon/core.h>
30 30
#include <lemon/bin_heap.h>
31 31

	
32 32
namespace lemon {
33 33

	
34 34
  /// \brief Default traits class of CapacityScaling algorithm.
35 35
  ///
36 36
  /// Default traits class of CapacityScaling algorithm.
37 37
  /// \tparam GR Digraph type.
38
  /// \tparam V The value type used for flow amounts, capacity bounds
38
  /// \tparam V The number type used for flow amounts, capacity bounds
39 39
  /// and supply values. By default it is \c int.
40
  /// \tparam C The value type used for costs and potentials.
40
  /// \tparam C The number type used for costs and potentials.
41 41
  /// By default it is the same as \c V.
42 42
  template <typename GR, typename V = int, typename C = V>
43 43
  struct CapacityScalingDefaultTraits
44 44
  {
45 45
    /// The type of the digraph
46 46
    typedef GR Digraph;
47 47
    /// The type of the flow amounts, capacity bounds and supply values
48 48
    typedef V Value;
49 49
    /// The type of the arc costs
50 50
    typedef C Cost;
51 51

	
52 52
    /// \brief The type of the heap used for internal Dijkstra computations.
... ...
@@ -66,30 +66,30 @@
66 66
  ///
67 67
  /// \ref CapacityScaling implements the capacity scaling version
68 68
  /// of the successive shortest path algorithm for finding a
69 69
  /// \ref min_cost_flow "minimum cost flow". It is an efficient dual
70 70
  /// solution method.
71 71
  ///
72 72
  /// Most of the parameters of the problem (except for the digraph)
73 73
  /// can be given using separate functions, and the algorithm can be
74 74
  /// executed using the \ref run() function. If some parameters are not
75 75
  /// specified, then default values will be used.
76 76
  ///
77 77
  /// \tparam GR The digraph type the algorithm runs on.
78
  /// \tparam V The value type used for flow amounts, capacity bounds
78
  /// \tparam V The number type used for flow amounts, capacity bounds
79 79
  /// and supply values in the algorithm. By default it is \c int.
80
  /// \tparam C The value type used for costs and potentials in the
80
  /// \tparam C The number type used for costs and potentials in the
81 81
  /// algorithm. By default it is the same as \c V.
82 82
  ///
83
  /// \warning Both value types must be signed and all input data must
83
  /// \warning Both number types must be signed and all input data must
84 84
  /// be integer.
85 85
  /// \warning This algorithm does not support negative costs for such
86 86
  /// arcs that have infinite upper bound.
87 87
#ifdef DOXYGEN
88 88
  template <typename GR, typename V, typename C, typename TR>
89 89
#else
90 90
  template < typename GR, typename V = int, typename C = V,
91 91
             typename TR = CapacityScalingDefaultTraits<GR, V, C> >
92 92
#endif
93 93
  class CapacityScaling
94 94
  {
95 95
  public:
... ...
@@ -113,25 +113,25 @@
113 113
    ///
114 114
    /// Enum type containing the problem type constants that can be
115 115
    /// returned by the \ref run() function of the algorithm.
116 116
    enum ProblemType {
117 117
      /// The problem has no feasible solution (flow).
118 118
      INFEASIBLE,
119 119
      /// The problem has optimal solution (i.e. it is feasible and
120 120
      /// bounded), and the algorithm has found optimal flow and node
121 121
      /// potentials (primal and dual solutions).
122 122
      OPTIMAL,
123 123
      /// The digraph contains an arc of negative cost and infinite
124 124
      /// upper bound. It means that the objective function is unbounded
125
      /// on that arc, however note that it could actually be bounded
125
      /// on that arc, however, note that it could actually be bounded
126 126
      /// over the feasible flows, but this algroithm cannot handle
127 127
      /// these cases.
128 128
      UNBOUNDED
129 129
    };
130 130
  
131 131
  private:
132 132

	
133 133
    TEMPLATE_DIGRAPH_TYPEDEFS(GR);
134 134

	
135 135
    typedef std::vector<int> IntVector;
136 136
    typedef std::vector<char> BoolVector;
137 137
    typedef std::vector<Value> ValueVector;
... ...
@@ -298,25 +298,25 @@
298 298

	
299 299
    /// \brief Constructor.
300 300
    ///
301 301
    /// The constructor of the class.
302 302
    ///
303 303
    /// \param graph The digraph the algorithm runs on.
304 304
    CapacityScaling(const GR& graph) :
305 305
      _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
306 306
      INF(std::numeric_limits<Value>::has_infinity ?
307 307
          std::numeric_limits<Value>::infinity() :
308 308
          std::numeric_limits<Value>::max())
309 309
    {
310
      // Check the value types
310
      // Check the number types
311 311
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
312 312
        "The flow type of CapacityScaling must be signed");
313 313
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
314 314
        "The cost type of CapacityScaling must be signed");
315 315

	
316 316
      // Resize vectors
317 317
      _node_num = countNodes(_graph);
318 318
      _arc_num = countArcs(_graph);
319 319
      _res_arc_num = 2 * (_arc_num + _node_num);
320 320
      _root = _node_num;
321 321
      ++_node_num;
322 322

	
... ...
@@ -402,25 +402,25 @@
402 402
      for (ArcIt a(_graph); a != INVALID; ++a) {
403 403
        _lower[_arc_idf[a]] = map[a];
404 404
        _lower[_arc_idb[a]] = map[a];
405 405
      }
406 406
      return *this;
407 407
    }
408 408

	
409 409
    /// \brief Set the upper bounds (capacities) on the arcs.
410 410
    ///
411 411
    /// This function sets the upper bounds (capacities) on the arcs.
412 412
    /// If it is not used before calling \ref run(), the upper bounds
413 413
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
414
    /// unbounded from above on each arc).
414
    /// unbounded from above).
415 415
    ///
416 416
    /// \param map An arc map storing the upper bounds.
417 417
    /// Its \c Value type must be convertible to the \c Value type
418 418
    /// of the algorithm.
419 419
    ///
420 420
    /// \return <tt>(*this)</tt>
421 421
    template<typename UpperMap>
422 422
    CapacityScaling& upperMap(const UpperMap& map) {
423 423
      for (ArcIt a(_graph); a != INVALID; ++a) {
424 424
        _upper[_arc_idf[a]] = map[a];
425 425
      }
426 426
      return *this;
... ...
@@ -505,38 +505,38 @@
505 505
    /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
506 506
    /// For example,
507 507
    /// \code
508 508
    ///   CapacityScaling<ListDigraph> cs(graph);
509 509
    ///   cs.lowerMap(lower).upperMap(upper).costMap(cost)
510 510
    ///     .supplyMap(sup).run();
511 511
    /// \endcode
512 512
    ///
513 513
    /// This function can be called more than once. All the parameters
514 514
    /// that have been given are kept for the next call, unless
515 515
    /// \ref reset() is called, thus only the modified parameters
516 516
    /// have to be set again. See \ref reset() for examples.
517
    /// However the underlying digraph must not be modified after this
517
    /// However, the underlying digraph must not be modified after this
518 518
    /// class have been constructed, since it copies and extends the graph.
519 519
    ///
520 520
    /// \param factor The capacity scaling factor. It must be larger than
521 521
    /// one to use scaling. If it is less or equal to one, then scaling
522 522
    /// will be disabled.
523 523
    ///
524 524
    /// \return \c INFEASIBLE if no feasible flow exists,
525 525
    /// \n \c OPTIMAL if the problem has optimal solution
526 526
    /// (i.e. it is feasible and bounded), and the algorithm has found
527 527
    /// optimal flow and node potentials (primal and dual solutions),
528 528
    /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
529 529
    /// and infinite upper bound. It means that the objective function
530
    /// is unbounded on that arc, however note that it could actually be
530
    /// is unbounded on that arc, however, note that it could actually be
531 531
    /// bounded over the feasible flows, but this algroithm cannot handle
532 532
    /// these cases.
533 533
    ///
534 534
    /// \see ProblemType
535 535
    ProblemType run(int factor = 4) {
536 536
      _factor = factor;
537 537
      ProblemType pt = init();
538 538
      if (pt != OPTIMAL) return pt;
539 539
      return start();
540 540
    }
541 541

	
542 542
    /// \brief Reset all the parameters that have been given before.
Ignore white space 24 line context
... ...
@@ -31,27 +31,27 @@
31 31
#include <lemon/maps.h>
32 32
#include <lemon/math.h>
33 33
#include <lemon/static_graph.h>
34 34
#include <lemon/circulation.h>
35 35
#include <lemon/bellman_ford.h>
36 36

	
37 37
namespace lemon {
38 38

	
39 39
  /// \brief Default traits class of CostScaling algorithm.
40 40
  ///
41 41
  /// Default traits class of CostScaling algorithm.
42 42
  /// \tparam GR Digraph type.
43
  /// \tparam V The value type used for flow amounts, capacity bounds
43
  /// \tparam V The number type used for flow amounts, capacity bounds
44 44
  /// and supply values. By default it is \c int.
45
  /// \tparam C The value type used for costs and potentials.
45
  /// \tparam C The number type used for costs and potentials.
46 46
  /// By default it is the same as \c V.
47 47
#ifdef DOXYGEN
48 48
  template <typename GR, typename V = int, typename C = V>
49 49
#else
50 50
  template < typename GR, typename V = int, typename C = V,
51 51
             bool integer = std::numeric_limits<C>::is_integer >
52 52
#endif
53 53
  struct CostScalingDefaultTraits
54 54
  {
55 55
    /// The type of the digraph
56 56
    typedef GR Digraph;
57 57
    /// The type of the flow amounts, capacity bounds and supply values
... ...
@@ -92,30 +92,30 @@
92 92
  /// \ref CostScaling implements a cost scaling algorithm that performs
93 93
  /// push/augment and relabel operations for finding a minimum cost
94 94
  /// flow. It is an efficient primal-dual solution method, which
95 95
  /// can be viewed as the generalization of the \ref Preflow
96 96
  /// "preflow push-relabel" algorithm for the maximum flow problem.
97 97
  ///
98 98
  /// Most of the parameters of the problem (except for the digraph)
99 99
  /// can be given using separate functions, and the algorithm can be
100 100
  /// executed using the \ref run() function. If some parameters are not
101 101
  /// specified, then default values will be used.
102 102
  ///
103 103
  /// \tparam GR The digraph type the algorithm runs on.
104
  /// \tparam V The value type used for flow amounts, capacity bounds
104
  /// \tparam V The number type used for flow amounts, capacity bounds
105 105
  /// and supply values in the algorithm. By default it is \c int.
106
  /// \tparam C The value type used for costs and potentials in the
106
  /// \tparam C The number type used for costs and potentials in the
107 107
  /// algorithm. By default it is the same as \c V.
108 108
  ///
109
  /// \warning Both value types must be signed and all input data must
109
  /// \warning Both number types must be signed and all input data must
110 110
  /// be integer.
111 111
  /// \warning This algorithm does not support negative costs for such
112 112
  /// arcs that have infinite upper bound.
113 113
  ///
114 114
  /// \note %CostScaling provides three different internal methods,
115 115
  /// from which the most efficient one is used by default.
116 116
  /// For more information, see \ref Method.
117 117
#ifdef DOXYGEN
118 118
  template <typename GR, typename V, typename C, typename TR>
119 119
#else
120 120
  template < typename GR, typename V = int, typename C = V,
121 121
             typename TR = CostScalingDefaultTraits<GR, V, C> >
... ...
@@ -148,25 +148,25 @@
148 148
    ///
149 149
    /// Enum type containing the problem type constants that can be
150 150
    /// returned by the \ref run() function of the algorithm.
151 151
    enum ProblemType {
152 152
      /// The problem has no feasible solution (flow).
153 153
      INFEASIBLE,
154 154
      /// The problem has optimal solution (i.e. it is feasible and
155 155
      /// bounded), and the algorithm has found optimal flow and node
156 156
      /// potentials (primal and dual solutions).
157 157
      OPTIMAL,
158 158
      /// The digraph contains an arc of negative cost and infinite
159 159
      /// upper bound. It means that the objective function is unbounded
160
      /// on that arc, however note that it could actually be bounded
160
      /// on that arc, however, note that it could actually be bounded
161 161
      /// over the feasible flows, but this algroithm cannot handle
162 162
      /// these cases.
163 163
      UNBOUNDED
164 164
    };
165 165

	
166 166
    /// \brief Constants for selecting the internal method.
167 167
    ///
168 168
    /// Enum type containing constants for selecting the internal method
169 169
    /// for the \ref run() function.
170 170
    ///
171 171
    /// \ref CostScaling provides three internal methods that differ mainly
172 172
    /// in their base operations, which are used in conjunction with the
... ...
@@ -316,25 +316,25 @@
316 316
    /// \brief Constructor.
317 317
    ///
318 318
    /// The constructor of the class.
319 319
    ///
320 320
    /// \param graph The digraph the algorithm runs on.
321 321
    CostScaling(const GR& graph) :
322 322
      _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
323 323
      _cost_map(_cost_vec), _pi_map(_pi),
324 324
      INF(std::numeric_limits<Value>::has_infinity ?
325 325
          std::numeric_limits<Value>::infinity() :
326 326
          std::numeric_limits<Value>::max())
327 327
    {
328
      // Check the value types
328
      // Check the number types
329 329
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
330 330
        "The flow type of CostScaling must be signed");
331 331
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
332 332
        "The cost type of CostScaling must be signed");
333 333

	
334 334
      // Resize vectors
335 335
      _node_num = countNodes(_graph);
336 336
      _arc_num = countArcs(_graph);
337 337
      _res_node_num = _node_num + 1;
338 338
      _res_arc_num = 2 * (_arc_num + _node_num);
339 339
      _root = _node_num;
340 340

	
... ...
@@ -424,25 +424,25 @@
424 424
      for (ArcIt a(_graph); a != INVALID; ++a) {
425 425
        _lower[_arc_idf[a]] = map[a];
426 426
        _lower[_arc_idb[a]] = map[a];
427 427
      }
428 428
      return *this;
429 429
    }
430 430

	
431 431
    /// \brief Set the upper bounds (capacities) on the arcs.
432 432
    ///
433 433
    /// This function sets the upper bounds (capacities) on the arcs.
434 434
    /// If it is not used before calling \ref run(), the upper bounds
435 435
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
436
    /// unbounded from above on each arc).
436
    /// unbounded from above).
437 437
    ///
438 438
    /// \param map An arc map storing the upper bounds.
439 439
    /// Its \c Value type must be convertible to the \c Value type
440 440
    /// of the algorithm.
441 441
    ///
442 442
    /// \return <tt>(*this)</tt>
443 443
    template<typename UpperMap>
444 444
    CostScaling& upperMap(const UpperMap& map) {
445 445
      for (ArcIt a(_graph); a != INVALID; ++a) {
446 446
        _upper[_arc_idf[a]] = map[a];
447 447
      }
448 448
      return *this;
... ...
@@ -540,47 +540,47 @@
540 540
    /// class have been constructed, since it copies and extends the graph.
541 541
    ///
542 542
    /// \param method The internal method that will be used in the
543 543
    /// algorithm. For more information, see \ref Method.
544 544
    /// \param factor The cost scaling factor. It must be larger than one.
545 545
    ///
546 546
    /// \return \c INFEASIBLE if no feasible flow exists,
547 547
    /// \n \c OPTIMAL if the problem has optimal solution
548 548
    /// (i.e. it is feasible and bounded), and the algorithm has found
549 549
    /// optimal flow and node potentials (primal and dual solutions),
550 550
    /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
551 551
    /// and infinite upper bound. It means that the objective function
552
    /// is unbounded on that arc, however note that it could actually be
552
    /// is unbounded on that arc, however, note that it could actually be
553 553
    /// bounded over the feasible flows, but this algroithm cannot handle
554 554
    /// these cases.
555 555
    ///
556 556
    /// \see ProblemType, Method
557 557
    ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 8) {
558 558
      _alpha = factor;
559 559
      ProblemType pt = init();
560 560
      if (pt != OPTIMAL) return pt;
561 561
      start(method);
562 562
      return OPTIMAL;
563 563
    }
564 564

	
565 565
    /// \brief Reset all the parameters that have been given before.
566 566
    ///
567 567
    /// This function resets all the paramaters that have been given
568 568
    /// before using functions \ref lowerMap(), \ref upperMap(),
569 569
    /// \ref costMap(), \ref supplyMap(), \ref stSupply().
570 570
    ///
571 571
    /// It is useful for multiple run() calls. If this function is not
572 572
    /// used, all the parameters given before are kept for the next
573 573
    /// \ref run() call.
574
    /// However the underlying digraph must not be modified after this
574
    /// However, the underlying digraph must not be modified after this
575 575
    /// class have been constructed, since it copies and extends the graph.
576 576
    ///
577 577
    /// For example,
578 578
    /// \code
579 579
    ///   CostScaling<ListDigraph> cs(graph);
580 580
    ///
581 581
    ///   // First run
582 582
    ///   cs.lowerMap(lower).upperMap(upper).costMap(cost)
583 583
    ///     .supplyMap(sup).run();
584 584
    ///
585 585
    ///   // Run again with modified cost map (reset() is not called,
586 586
    ///   // so only the cost map have to be set again)
Ignore white space 24 line context
... ...
@@ -34,45 +34,45 @@
34 34
namespace lemon {
35 35

	
36 36
  /// \addtogroup min_cost_flow_algs
37 37
  /// @{
38 38

	
39 39
  /// \brief Implementation of the primal Network Simplex algorithm
40 40
  /// for finding a \ref min_cost_flow "minimum cost flow".
41 41
  ///
42 42
  /// \ref NetworkSimplex implements the primal Network Simplex algorithm
43 43
  /// for finding a \ref min_cost_flow "minimum cost flow"
44 44
  /// \ref amo93networkflows, \ref dantzig63linearprog,
45 45
  /// \ref kellyoneill91netsimplex.
46
  /// This algorithm is a specialized version of the linear programming
47
  /// simplex method directly for the minimum cost flow problem.
48
  /// It is one of the most efficient solution methods.
46
  /// This algorithm is a highly efficient specialized version of the
47
  /// linear programming simplex method directly for the minimum cost
48
  /// flow problem.
49 49
  ///
50
  /// In general this class is the fastest implementation available
51
  /// in LEMON for the minimum cost flow problem.
52
  /// Moreover it supports both directions of the supply/demand inequality
50
  /// In general, %NetworkSimplex is the fastest implementation available
51
  /// in LEMON for this problem.
52
  /// Moreover, it supports both directions of the supply/demand inequality
53 53
  /// constraints. For more information, see \ref SupplyType.
54 54
  ///
55 55
  /// Most of the parameters of the problem (except for the digraph)
56 56
  /// can be given using separate functions, and the algorithm can be
57 57
  /// executed using the \ref run() function. If some parameters are not
58 58
  /// specified, then default values will be used.
59 59
  ///
60 60
  /// \tparam GR The digraph type the algorithm runs on.
61
  /// \tparam V The value type used for flow amounts, capacity bounds
61
  /// \tparam V The number type used for flow amounts, capacity bounds
62 62
  /// and supply values in the algorithm. By default, it is \c int.
63
  /// \tparam C The value type used for costs and potentials in the
63
  /// \tparam C The number type used for costs and potentials in the
64 64
  /// algorithm. By default, it is the same as \c V.
65 65
  ///
66
  /// \warning Both value types must be signed and all input data must
66
  /// \warning Both number types must be signed and all input data must
67 67
  /// be integer.
68 68
  ///
69 69
  /// \note %NetworkSimplex provides five different pivot rule
70 70
  /// implementations, from which the most efficient one is used
71 71
  /// by default. For more information, see \ref PivotRule.
72 72
  template <typename GR, typename V = int, typename C = V>
73 73
  class NetworkSimplex
74 74
  {
75 75
  public:
76 76

	
77 77
    /// The type of the flow amounts, capacity bounds and supply values
78 78
    typedef V Value;
... ...
@@ -117,25 +117,25 @@
117 117
    };
118 118
    
119 119
    /// \brief Constants for selecting the pivot rule.
120 120
    ///
121 121
    /// Enum type containing constants for selecting the pivot rule for
122 122
    /// the \ref run() function.
123 123
    ///
124 124
    /// \ref NetworkSimplex provides five different pivot rule
125 125
    /// implementations that significantly affect the running time
126 126
    /// of the algorithm.
127 127
    /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
128 128
    /// proved to be the most efficient and the most robust on various
129
    /// test inputs according to our benchmark tests.
129
    /// test inputs.
130 130
    /// However, another pivot rule can be selected using the \ref run()
131 131
    /// function with the proper parameter.
132 132
    enum PivotRule {
133 133

	
134 134
      /// The \e First \e Eligible pivot rule.
135 135
      /// The next eligible arc is selected in a wraparound fashion
136 136
      /// in every iteration.
137 137
      FIRST_ELIGIBLE,
138 138

	
139 139
      /// The \e Best \e Eligible pivot rule.
140 140
      /// The best eligible arc is selected in every iteration.
141 141
      BEST_ELIGIBLE,
... ...
@@ -628,25 +628,25 @@
628 628
    ///
629 629
    /// \param graph The digraph the algorithm runs on.
630 630
    /// \param arc_mixing Indicate if the arcs have to be stored in a
631 631
    /// mixed order in the internal data structure. 
632 632
    /// In special cases, it could lead to better overall performance,
633 633
    /// but it is usually slower. Therefore it is disabled by default.
634 634
    NetworkSimplex(const GR& graph, bool arc_mixing = false) :
635 635
      _graph(graph), _node_id(graph), _arc_id(graph),
636 636
      MAX(std::numeric_limits<Value>::max()),
637 637
      INF(std::numeric_limits<Value>::has_infinity ?
638 638
          std::numeric_limits<Value>::infinity() : MAX)
639 639
    {
640
      // Check the value types
640
      // Check the number types
641 641
      LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
642 642
        "The flow type of NetworkSimplex must be signed");
643 643
      LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
644 644
        "The cost type of NetworkSimplex must be signed");
645 645
        
646 646
      // Resize vectors
647 647
      _node_num = countNodes(_graph);
648 648
      _arc_num = countArcs(_graph);
649 649
      int all_node_num = _node_num + 1;
650 650
      int max_arc_num = _arc_num + 2 * _node_num;
651 651

	
652 652
      _source.resize(max_arc_num);
... ...
@@ -720,25 +720,25 @@
720 720
      _have_lower = true;
721 721
      for (ArcIt a(_graph); a != INVALID; ++a) {
722 722
        _lower[_arc_id[a]] = map[a];
723 723
      }
724 724
      return *this;
725 725
    }
726 726

	
727 727
    /// \brief Set the upper bounds (capacities) on the arcs.
728 728
    ///
729 729
    /// This function sets the upper bounds (capacities) on the arcs.
730 730
    /// If it is not used before calling \ref run(), the upper bounds
731 731
    /// will be set to \ref INF on all arcs (i.e. the flow value will be
732
    /// unbounded from above on each arc).
732
    /// unbounded from above).
733 733
    ///
734 734
    /// \param map An arc map storing the upper bounds.
735 735
    /// Its \c Value type must be convertible to the \c Value type
736 736
    /// of the algorithm.
737 737
    ///
738 738
    /// \return <tt>(*this)</tt>
739 739
    template<typename UpperMap>
740 740
    NetworkSimplex& upperMap(const UpperMap& map) {
741 741
      for (ArcIt a(_graph); a != INVALID; ++a) {
742 742
        _upper[_arc_id[a]] = map[a];
743 743
      }
744 744
      return *this;
0 comments (0 inline)