gravatar
alpar (Alpar Juttner)
alpar@cs.elte.hu
Merge #380
0 5 2
merge default
1 file changed with 879 insertions and 2 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2010
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#ifndef LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
20
#define LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
21

	
22
/// \ingroup approx_algs
23
///
24
/// \file
25
/// \brief The iterated local search algorithm of Grosso, Locatelli, and Pullan
26
/// for the maximum clique problem
27

	
28
#include <vector>
29
#include <limits>
30
#include <lemon/core.h>
31
#include <lemon/random.h>
32

	
33
namespace lemon {
34

	
35
  /// \addtogroup approx_algs
36
  /// @{
37

	
38
  /// \brief Implementation of the iterated local search algorithm of Grosso,
39
  /// Locatelli, and Pullan for the maximum clique problem
40
  ///
41
  /// \ref GrossoLocatelliPullanMc implements the iterated local search
42
  /// algorithm of Grosso, Locatelli, and Pullan for solving the \e maximum
43
  /// \e clique \e problem \ref grosso08maxclique.
44
  /// It is to find the largest complete subgraph (\e clique) in an
45
  /// undirected graph, i.e., the largest set of nodes where each
46
  /// pair of nodes is connected.
47
  ///
48
  /// This class provides a simple but highly efficient and robust heuristic
49
  /// method that quickly finds a large clique, but not necessarily the
50
  /// largest one.
51
  ///
52
  /// \tparam GR The undirected graph type the algorithm runs on.
53
  ///
54
  /// \note %GrossoLocatelliPullanMc provides three different node selection
55
  /// rules, from which the most powerful one is used by default.
56
  /// For more information, see \ref SelectionRule.
57
  template <typename GR>
58
  class GrossoLocatelliPullanMc
59
  {
60
  public:
61

	
62
    /// \brief Constants for specifying the node selection rule.
63
    ///
64
    /// Enum type containing constants for specifying the node selection rule
65
    /// for the \ref run() function.
66
    ///
67
    /// During the algorithm, nodes are selected for addition to the current
68
    /// clique according to the applied rule.
69
    /// In general, the PENALTY_BASED rule turned out to be the most powerful
70
    /// and the most robust, thus it is the default option.
71
    /// However, another selection rule can be specified using the \ref run()
72
    /// function with the proper parameter.
73
    enum SelectionRule {
74

	
75
      /// A node is selected randomly without any evaluation at each step.
76
      RANDOM,
77

	
78
      /// A node of maximum degree is selected randomly at each step.
79
      DEGREE_BASED,
80

	
81
      /// A node of minimum penalty is selected randomly at each step.
82
      /// The node penalties are updated adaptively after each stage of the
83
      /// search process.
84
      PENALTY_BASED
85
    };
86

	
87
  private:
88

	
89
    TEMPLATE_GRAPH_TYPEDEFS(GR);
90

	
91
    typedef std::vector<int> IntVector;
92
    typedef std::vector<char> BoolVector;
93
    typedef std::vector<BoolVector> BoolMatrix;
94
    // Note: vector<char> is used instead of vector<bool> for efficiency reasons
95

	
96
    const GR &_graph;
97
    IntNodeMap _id;
98

	
99
    // Internal matrix representation of the graph
100
    BoolMatrix _gr;
101
    int _n;
102

	
103
    // The current clique
104
    BoolVector _clique;
105
    int _size;
106

	
107
    // The best clique found so far
108
    BoolVector _best_clique;
109
    int _best_size;
110

	
111
    // The "distances" of the nodes from the current clique.
112
    // _delta[u] is the number of nodes in the clique that are
113
    // not connected with u.
114
    IntVector _delta;
115

	
116
    // The current tabu set
117
    BoolVector _tabu;
118

	
119
    // Random number generator
120
    Random _rnd;
121

	
122
  private:
123

	
124
    // Implementation of the RANDOM node selection rule.
125
    class RandomSelectionRule
126
    {
127
    private:
128

	
129
      // References to the algorithm instance
130
      const BoolVector &_clique;
131
      const IntVector  &_delta;
132
      const BoolVector &_tabu;
133
      Random &_rnd;
134

	
135
      // Pivot rule data
136
      int _n;
137

	
138
    public:
139

	
140
      // Constructor
141
      RandomSelectionRule(GrossoLocatelliPullanMc &mc) :
142
        _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
143
        _rnd(mc._rnd), _n(mc._n)
144
      {}
145

	
146
      // Return a node index for a feasible add move or -1 if no one exists
147
      int nextFeasibleAddNode() const {
148
        int start_node = _rnd[_n];
149
        for (int i = start_node; i != _n; i++) {
150
          if (_delta[i] == 0 && !_tabu[i]) return i;
151
        }
152
        for (int i = 0; i != start_node; i++) {
153
          if (_delta[i] == 0 && !_tabu[i]) return i;
154
        }
155
        return -1;
156
      }
157

	
158
      // Return a node index for a feasible swap move or -1 if no one exists
159
      int nextFeasibleSwapNode() const {
160
        int start_node = _rnd[_n];
161
        for (int i = start_node; i != _n; i++) {
162
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
163
        }
164
        for (int i = 0; i != start_node; i++) {
165
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i]) return i;
166
        }
167
        return -1;
168
      }
169

	
170
      // Return a node index for an add move or -1 if no one exists
171
      int nextAddNode() const {
172
        int start_node = _rnd[_n];
173
        for (int i = start_node; i != _n; i++) {
174
          if (_delta[i] == 0) return i;
175
        }
176
        for (int i = 0; i != start_node; i++) {
177
          if (_delta[i] == 0) return i;
178
        }
179
        return -1;
180
      }
181

	
182
      // Update internal data structures between stages (if necessary)
183
      void update() {}
184

	
185
    }; //class RandomSelectionRule
186

	
187

	
188
    // Implementation of the DEGREE_BASED node selection rule.
189
    class DegreeBasedSelectionRule
190
    {
191
    private:
192

	
193
      // References to the algorithm instance
194
      const BoolVector &_clique;
195
      const IntVector  &_delta;
196
      const BoolVector &_tabu;
197
      Random &_rnd;
198

	
199
      // Pivot rule data
200
      int _n;
201
      IntVector _deg;
202

	
203
    public:
204

	
205
      // Constructor
206
      DegreeBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
207
        _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
208
        _rnd(mc._rnd), _n(mc._n), _deg(_n)
209
      {
210
        for (int i = 0; i != _n; i++) {
211
          int d = 0;
212
          BoolVector &row = mc._gr[i];
213
          for (int j = 0; j != _n; j++) {
214
            if (row[j]) d++;
215
          }
216
          _deg[i] = d;
217
        }
218
      }
219

	
220
      // Return a node index for a feasible add move or -1 if no one exists
221
      int nextFeasibleAddNode() const {
222
        int start_node = _rnd[_n];
223
        int node = -1, max_deg = -1;
224
        for (int i = start_node; i != _n; i++) {
225
          if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
226
            node = i;
227
            max_deg = _deg[i];
228
          }
229
        }
230
        for (int i = 0; i != start_node; i++) {
231
          if (_delta[i] == 0 && !_tabu[i] && _deg[i] > max_deg) {
232
            node = i;
233
            max_deg = _deg[i];
234
          }
235
        }
236
        return node;
237
      }
238

	
239
      // Return a node index for a feasible swap move or -1 if no one exists
240
      int nextFeasibleSwapNode() const {
241
        int start_node = _rnd[_n];
242
        int node = -1, max_deg = -1;
243
        for (int i = start_node; i != _n; i++) {
244
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
245
              _deg[i] > max_deg) {
246
            node = i;
247
            max_deg = _deg[i];
248
          }
249
        }
250
        for (int i = 0; i != start_node; i++) {
251
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
252
              _deg[i] > max_deg) {
253
            node = i;
254
            max_deg = _deg[i];
255
          }
256
        }
257
        return node;
258
      }
259

	
260
      // Return a node index for an add move or -1 if no one exists
261
      int nextAddNode() const {
262
        int start_node = _rnd[_n];
263
        int node = -1, max_deg = -1;
264
        for (int i = start_node; i != _n; i++) {
265
          if (_delta[i] == 0 && _deg[i] > max_deg) {
266
            node = i;
267
            max_deg = _deg[i];
268
          }
269
        }
270
        for (int i = 0; i != start_node; i++) {
271
          if (_delta[i] == 0 && _deg[i] > max_deg) {
272
            node = i;
273
            max_deg = _deg[i];
274
          }
275
        }
276
        return node;
277
      }
278

	
279
      // Update internal data structures between stages (if necessary)
280
      void update() {}
281

	
282
    }; //class DegreeBasedSelectionRule
283

	
284

	
285
    // Implementation of the PENALTY_BASED node selection rule.
286
    class PenaltyBasedSelectionRule
287
    {
288
    private:
289

	
290
      // References to the algorithm instance
291
      const BoolVector &_clique;
292
      const IntVector  &_delta;
293
      const BoolVector &_tabu;
294
      Random &_rnd;
295

	
296
      // Pivot rule data
297
      int _n;
298
      IntVector _penalty;
299

	
300
    public:
301

	
302
      // Constructor
303
      PenaltyBasedSelectionRule(GrossoLocatelliPullanMc &mc) :
304
        _clique(mc._clique), _delta(mc._delta), _tabu(mc._tabu),
305
        _rnd(mc._rnd), _n(mc._n), _penalty(_n, 0)
306
      {}
307

	
308
      // Return a node index for a feasible add move or -1 if no one exists
309
      int nextFeasibleAddNode() const {
310
        int start_node = _rnd[_n];
311
        int node = -1, min_p = std::numeric_limits<int>::max();
312
        for (int i = start_node; i != _n; i++) {
313
          if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
314
            node = i;
315
            min_p = _penalty[i];
316
          }
317
        }
318
        for (int i = 0; i != start_node; i++) {
319
          if (_delta[i] == 0 && !_tabu[i] && _penalty[i] < min_p) {
320
            node = i;
321
            min_p = _penalty[i];
322
          }
323
        }
324
        return node;
325
      }
326

	
327
      // Return a node index for a feasible swap move or -1 if no one exists
328
      int nextFeasibleSwapNode() const {
329
        int start_node = _rnd[_n];
330
        int node = -1, min_p = std::numeric_limits<int>::max();
331
        for (int i = start_node; i != _n; i++) {
332
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
333
              _penalty[i] < min_p) {
334
            node = i;
335
            min_p = _penalty[i];
336
          }
337
        }
338
        for (int i = 0; i != start_node; i++) {
339
          if (!_clique[i] && _delta[i] == 1 && !_tabu[i] &&
340
              _penalty[i] < min_p) {
341
            node = i;
342
            min_p = _penalty[i];
343
          }
344
        }
345
        return node;
346
      }
347

	
348
      // Return a node index for an add move or -1 if no one exists
349
      int nextAddNode() const {
350
        int start_node = _rnd[_n];
351
        int node = -1, min_p = std::numeric_limits<int>::max();
352
        for (int i = start_node; i != _n; i++) {
353
          if (_delta[i] == 0 && _penalty[i] < min_p) {
354
            node = i;
355
            min_p = _penalty[i];
356
          }
357
        }
358
        for (int i = 0; i != start_node; i++) {
359
          if (_delta[i] == 0 && _penalty[i] < min_p) {
360
            node = i;
361
            min_p = _penalty[i];
362
          }
363
        }
364
        return node;
365
      }
366

	
367
      // Update internal data structures between stages (if necessary)
368
      void update() {}
369

	
370
    }; //class PenaltyBasedSelectionRule
371

	
372
  public:
373

	
374
    /// \brief Constructor.
375
    ///
376
    /// Constructor.
377
    /// The global \ref rnd "random number generator instance" is used
378
    /// during the algorithm.
379
    ///
380
    /// \param graph The undirected graph the algorithm runs on.
381
    GrossoLocatelliPullanMc(const GR& graph) :
382
      _graph(graph), _id(_graph), _rnd(rnd)
383
    {}
384

	
385
    /// \brief Constructor with random seed.
386
    ///
387
    /// Constructor with random seed.
388
    ///
389
    /// \param graph The undirected graph the algorithm runs on.
390
    /// \param seed Seed value for the internal random number generator
391
    /// that is used during the algorithm.
392
    GrossoLocatelliPullanMc(const GR& graph, int seed) :
393
      _graph(graph), _id(_graph), _rnd(seed)
394
    {}
395

	
396
    /// \brief Constructor with random number generator.
397
    ///
398
    /// Constructor with random number generator.
399
    ///
400
    /// \param graph The undirected graph the algorithm runs on.
401
    /// \param random A random number generator that is used during the
402
    /// algorithm.
403
    GrossoLocatelliPullanMc(const GR& graph, const Random& random) :
404
      _graph(graph), _id(_graph), _rnd(random)
405
    {}
406

	
407
    /// \name Execution Control
408
    /// @{
409

	
410
    /// \brief Runs the algorithm.
411
    ///
412
    /// This function runs the algorithm.
413
    ///
414
    /// \param step_num The maximum number of node selections (steps)
415
    /// during the search process.
416
    /// This parameter controls the running time and the success of the
417
    /// algorithm. For larger values, the algorithm runs slower but it more
418
    /// likely finds larger cliques. For smaller values, the algorithm is
419
    /// faster but probably gives worse results.
420
    /// \param rule The node selection rule. For more information, see
421
    /// \ref SelectionRule.
422
    ///
423
    /// \return The size of the found clique.
424
    int run(int step_num = 100000,
425
            SelectionRule rule = PENALTY_BASED)
426
    {
427
      init();
428
      switch (rule) {
429
        case RANDOM:
430
          return start<RandomSelectionRule>(step_num);
431
        case DEGREE_BASED:
432
          return start<DegreeBasedSelectionRule>(step_num);
433
        case PENALTY_BASED:
434
          return start<PenaltyBasedSelectionRule>(step_num);
435
      }
436
      return 0; // avoid warning
437
    }
438

	
439
    /// @}
440

	
441
    /// \name Query Functions
442
    /// @{
443

	
444
    /// \brief The size of the found clique
445
    ///
446
    /// This function returns the size of the found clique.
447
    ///
448
    /// \pre run() must be called before using this function.
449
    int cliqueSize() const {
450
      return _best_size;
451
    }
452

	
453
    /// \brief Gives back the found clique in a \c bool node map
454
    ///
455
    /// This function gives back the characteristic vector of the found
456
    /// clique in the given node map.
457
    /// It must be a \ref concepts::WriteMap "writable" node map with
458
    /// \c bool (or convertible) value type.
459
    ///
460
    /// \pre run() must be called before using this function.
461
    template <typename CliqueMap>
462
    void cliqueMap(CliqueMap &map) const {
463
      for (NodeIt n(_graph); n != INVALID; ++n) {
464
        map[n] = static_cast<bool>(_best_clique[_id[n]]);
465
      }
466
    }
467

	
468
    /// \brief Iterator to list the nodes of the found clique
469
    ///
470
    /// This iterator class lists the nodes of the found clique.
471
    /// Before using it, you must allocate a GrossoLocatelliPullanMc instance
472
    /// and call its \ref GrossoLocatelliPullanMc::run() "run()" method.
473
    ///
474
    /// The following example prints out the IDs of the nodes in the found
475
    /// clique.
476
    /// \code
477
    ///   GrossoLocatelliPullanMc<Graph> mc(g);
478
    ///   mc.run();
479
    ///   for (GrossoLocatelliPullanMc<Graph>::CliqueNodeIt n(mc);
480
    ///        n != INVALID; ++n)
481
    ///   {
482
    ///     std::cout << g.id(n) << std::endl;
483
    ///   }
484
    /// \endcode
485
    class CliqueNodeIt
486
    {
487
    private:
488
      NodeIt _it;
489
      BoolNodeMap _map;
490

	
491
    public:
492

	
493
      /// Constructor
494

	
495
      /// Constructor.
496
      /// \param mc The algorithm instance.
497
      CliqueNodeIt(const GrossoLocatelliPullanMc &mc)
498
       : _map(mc._graph)
499
      {
500
        mc.cliqueMap(_map);
501
        for (_it = NodeIt(mc._graph); _it != INVALID && !_map[_it]; ++_it) ;
502
      }
503

	
504
      /// Conversion to \c Node
505
      operator Node() const { return _it; }
506

	
507
      bool operator==(Invalid) const { return _it == INVALID; }
508
      bool operator!=(Invalid) const { return _it != INVALID; }
509

	
510
      /// Next node
511
      CliqueNodeIt &operator++() {
512
        for (++_it; _it != INVALID && !_map[_it]; ++_it) ;
513
        return *this;
514
      }
515

	
516
      /// Postfix incrementation
517

	
518
      /// Postfix incrementation.
519
      ///
520
      /// \warning This incrementation returns a \c Node, not a
521
      /// \c CliqueNodeIt as one may expect.
522
      typename GR::Node operator++(int) {
523
        Node n=*this;
524
        ++(*this);
525
        return n;
526
      }
527

	
528
    };
529

	
530
    /// @}
531

	
532
  private:
533

	
534
    // Adds a node to the current clique
535
    void addCliqueNode(int u) {
536
      if (_clique[u]) return;
537
      _clique[u] = true;
538
      _size++;
539
      BoolVector &row = _gr[u];
540
      for (int i = 0; i != _n; i++) {
541
        if (!row[i]) _delta[i]++;
542
      }
543
    }
544

	
545
    // Removes a node from the current clique
546
    void delCliqueNode(int u) {
547
      if (!_clique[u]) return;
548
      _clique[u] = false;
549
      _size--;
550
      BoolVector &row = _gr[u];
551
      for (int i = 0; i != _n; i++) {
552
        if (!row[i]) _delta[i]--;
553
      }
554
    }
555

	
556
    // Initialize data structures
557
    void init() {
558
      _n = countNodes(_graph);
559
      int ui = 0;
560
      for (NodeIt u(_graph); u != INVALID; ++u) {
561
        _id[u] = ui++;
562
      }
563
      _gr.clear();
564
      _gr.resize(_n, BoolVector(_n, false));
565
      ui = 0;
566
      for (NodeIt u(_graph); u != INVALID; ++u) {
567
        for (IncEdgeIt e(_graph, u); e != INVALID; ++e) {
568
          int vi = _id[_graph.runningNode(e)];
569
          _gr[ui][vi] = true;
570
          _gr[vi][ui] = true;
571
        }
572
        ++ui;
573
      }
574

	
575
      _clique.clear();
576
      _clique.resize(_n, false);
577
      _size = 0;
578
      _best_clique.clear();
579
      _best_clique.resize(_n, false);
580
      _best_size = 0;
581
      _delta.clear();
582
      _delta.resize(_n, 0);
583
      _tabu.clear();
584
      _tabu.resize(_n, false);
585
    }
586

	
587
    // Executes the algorithm
588
    template <typename SelectionRuleImpl>
589
    int start(int max_select) {
590
      // Options for the restart rule
591
      const bool delta_based_restart = true;
592
      const int restart_delta_limit = 4;
593

	
594
      if (_n == 0) return 0;
595
      if (_n == 1) {
596
        _best_clique[0] = true;
597
        _best_size = 1;
598
        return _best_size;
599
      }
600

	
601
      // Iterated local search
602
      SelectionRuleImpl sel_method(*this);
603
      int select = 0;
604
      IntVector restart_nodes;
605

	
606
      while (select < max_select) {
607

	
608
        // Perturbation/restart
609
        if (delta_based_restart) {
610
          restart_nodes.clear();
611
          for (int i = 0; i != _n; i++) {
612
            if (_delta[i] >= restart_delta_limit)
613
              restart_nodes.push_back(i);
614
          }
615
        }
616
        int rs_node = -1;
617
        if (restart_nodes.size() > 0) {
618
          rs_node = restart_nodes[_rnd[restart_nodes.size()]];
619
        } else {
620
          rs_node = _rnd[_n];
621
        }
622
        BoolVector &row = _gr[rs_node];
623
        for (int i = 0; i != _n; i++) {
624
          if (_clique[i] && !row[i]) delCliqueNode(i);
625
        }
626
        addCliqueNode(rs_node);
627

	
628
        // Local search
629
        _tabu.clear();
630
        _tabu.resize(_n, false);
631
        bool tabu_empty = true;
632
        int max_swap = _size;
633
        while (select < max_select) {
634
          select++;
635
          int u;
636
          if ((u = sel_method.nextFeasibleAddNode()) != -1) {
637
            // Feasible add move
638
            addCliqueNode(u);
639
            if (tabu_empty) max_swap = _size;
640
          }
641
          else if ((u = sel_method.nextFeasibleSwapNode()) != -1) {
642
            // Feasible swap move
643
            int v = -1;
644
            BoolVector &row = _gr[u];
645
            for (int i = 0; i != _n; i++) {
646
              if (_clique[i] && !row[i]) {
647
                v = i;
648
                break;
649
              }
650
            }
651
            addCliqueNode(u);
652
            delCliqueNode(v);
653
            _tabu[v] = true;
654
            tabu_empty = false;
655
            if (--max_swap <= 0) break;
656
          }
657
          else if ((u = sel_method.nextAddNode()) != -1) {
658
            // Non-feasible add move
659
            addCliqueNode(u);
660
          }
661
          else break;
662
        }
663
        if (_size > _best_size) {
664
          _best_clique = _clique;
665
          _best_size = _size;
666
          if (_best_size == _n) return _best_size;
667
        }
668
        sel_method.update();
669
      }
670

	
671
      return _best_size;
672
    }
673

	
674
  }; //class GrossoLocatelliPullanMc
675

	
676
  ///@}
677

	
678
} //namespace lemon
679

	
680
#endif //LEMON_GROSSO_LOCATELLI_PULLAN_MC_H
Ignore white space 6 line context
1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2
 *
3
 * This file is a part of LEMON, a generic C++ optimization library.
4
 *
5
 * Copyright (C) 2003-2010
6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8
 *
9
 * Permission to use, modify and distribute this software is granted
10
 * provided that this copyright notice appears in all copies. For
11
 * precise terms see the accompanying LICENSE file.
12
 *
13
 * This software is provided "AS IS" with no warranty of any kind,
14
 * express or implied, and with no claim as to its suitability for any
15
 * purpose.
16
 *
17
 */
18

	
19
#include <sstream>
20
#include <lemon/list_graph.h>
21
#include <lemon/full_graph.h>
22
#include <lemon/grid_graph.h>
23
#include <lemon/lgf_reader.h>
24
#include <lemon/grosso_locatelli_pullan_mc.h>
25

	
26
#include "test_tools.h"
27

	
28
using namespace lemon;
29

	
30
char test_lgf[] =
31
  "@nodes\n"
32
  "label max_clique\n"
33
  "1     0\n"
34
  "2     0\n"
35
  "3     0\n"
36
  "4     1\n"
37
  "5     1\n"
38
  "6     1\n"
39
  "7     1\n"
40
  "@edges\n"
41
  "    label\n"
42
  "1 2     1\n"
43
  "1 3     2\n"
44
  "1 4     3\n"
45
  "1 6     4\n"
46
  "2 3     5\n"
47
  "2 5     6\n"
48
  "2 7     7\n"
49
  "3 4     8\n"
50
  "3 5     9\n"
51
  "4 5    10\n"
52
  "4 6    11\n"
53
  "4 7    12\n"
54
  "5 6    13\n"
55
  "5 7    14\n"
56
  "6 7    15\n";
57
      
58

	
59
// Check with general graphs
60
template <typename Param>
61
void checkMaxCliqueGeneral(int max_sel, Param rule) {
62
  typedef ListGraph GR;
63
  typedef GrossoLocatelliPullanMc<GR> McAlg;
64
  typedef McAlg::CliqueNodeIt CliqueIt;
65
  
66
  // Basic tests
67
  {
68
    GR g;
69
    GR::NodeMap<bool> map(g);
70
    McAlg mc(g);
71
    check(mc.run(max_sel, rule) == 0, "Wrong clique size");
72
    check(mc.cliqueSize() == 0, "Wrong clique size");
73
    check(CliqueIt(mc) == INVALID, "Wrong CliqueNodeIt");
74

	
75
    GR::Node u = g.addNode();
76
    check(mc.run(max_sel, rule) == 1, "Wrong clique size");
77
    check(mc.cliqueSize() == 1, "Wrong clique size");
78
    mc.cliqueMap(map);
79
    check(map[u], "Wrong clique map");
80
    CliqueIt it1(mc);
81
    check(static_cast<GR::Node>(it1) == u && ++it1 == INVALID,
82
          "Wrong CliqueNodeIt");
83
    
84
    GR::Node v = g.addNode();
85
    check(mc.run(max_sel, rule) == 1, "Wrong clique size");
86
    check(mc.cliqueSize() == 1, "Wrong clique size");
87
    mc.cliqueMap(map);
88
    check((map[u] && !map[v]) || (map[v] && !map[u]), "Wrong clique map");
89
    CliqueIt it2(mc);
90
    check(it2 != INVALID && ++it2 == INVALID, "Wrong CliqueNodeIt");
91

	
92
    g.addEdge(u, v);
93
    check(mc.run(max_sel, rule) == 2, "Wrong clique size");
94
    check(mc.cliqueSize() == 2, "Wrong clique size");
95
    mc.cliqueMap(map);
96
    check(map[u] && map[v], "Wrong clique map");
97
    CliqueIt it3(mc);
98
    check(it3 != INVALID && ++it3 != INVALID && ++it3 == INVALID,
99
          "Wrong CliqueNodeIt");
100
  }
101

	
102
  // Test graph
103
  {
104
    GR g;
105
    GR::NodeMap<bool> max_clique(g);
106
    GR::NodeMap<bool> map(g);
107
    std::istringstream input(test_lgf);
108
    graphReader(g, input)
109
      .nodeMap("max_clique", max_clique)
110
      .run();
111
    
112
    McAlg mc(g);
113
    check(mc.run(max_sel, rule) == 4, "Wrong clique size");
114
    check(mc.cliqueSize() == 4, "Wrong clique size");
115
    mc.cliqueMap(map);
116
    for (GR::NodeIt n(g); n != INVALID; ++n) {
117
      check(map[n] == max_clique[n], "Wrong clique map");
118
    }
119
    int cnt = 0;
120
    for (CliqueIt n(mc); n != INVALID; ++n) {
121
      cnt++;
122
      check(map[n] && max_clique[n], "Wrong CliqueNodeIt");
123
    }
124
    check(cnt == 4, "Wrong CliqueNodeIt");
125
  }
126
}
127

	
128
// Check with full graphs
129
template <typename Param>
130
void checkMaxCliqueFullGraph(int max_sel, Param rule) {
131
  typedef FullGraph GR;
132
  typedef GrossoLocatelliPullanMc<FullGraph> McAlg;
133
  typedef McAlg::CliqueNodeIt CliqueIt;
134
  
135
  for (int size = 0; size <= 40; size = size * 3 + 1) {
136
    GR g(size);
137
    GR::NodeMap<bool> map(g);
138
    McAlg mc(g);
139
    check(mc.run(max_sel, rule) == size, "Wrong clique size");
140
    check(mc.cliqueSize() == size, "Wrong clique size");
141
    mc.cliqueMap(map);
142
    for (GR::NodeIt n(g); n != INVALID; ++n) {
143
      check(map[n], "Wrong clique map");
144
    }
145
    int cnt = 0;
146
    for (CliqueIt n(mc); n != INVALID; ++n) cnt++;
147
    check(cnt == size, "Wrong CliqueNodeIt");
148
  }
149
}
150

	
151
// Check with grid graphs
152
template <typename Param>
153
void checkMaxCliqueGridGraph(int max_sel, Param rule) {
154
  GridGraph g(5, 7);
155
  GridGraph::NodeMap<char> map(g);
156
  GrossoLocatelliPullanMc<GridGraph> mc(g);
157
  check(mc.run(max_sel, rule) == 2, "Wrong clique size");
158
  check(mc.cliqueSize() == 2, "Wrong clique size");
159
}
160

	
161

	
162
int main() {
163
  checkMaxCliqueGeneral(50, GrossoLocatelliPullanMc<ListGraph>::RANDOM);
164
  checkMaxCliqueGeneral(50, GrossoLocatelliPullanMc<ListGraph>::DEGREE_BASED);
165
  checkMaxCliqueGeneral(50, GrossoLocatelliPullanMc<ListGraph>::PENALTY_BASED);
166

	
167
  checkMaxCliqueFullGraph(50, GrossoLocatelliPullanMc<FullGraph>::RANDOM);
168
  checkMaxCliqueFullGraph(50, GrossoLocatelliPullanMc<FullGraph>::DEGREE_BASED);
169
  checkMaxCliqueFullGraph(50, GrossoLocatelliPullanMc<FullGraph>::PENALTY_BASED);
170
                       
171
  checkMaxCliqueGridGraph(50, GrossoLocatelliPullanMc<GridGraph>::RANDOM);
172
  checkMaxCliqueGridGraph(50, GrossoLocatelliPullanMc<GridGraph>::DEGREE_BASED);
173
  checkMaxCliqueGridGraph(50, GrossoLocatelliPullanMc<GridGraph>::PENALTY_BASED);
174
                       
175
  return 0;
176
}
Ignore white space 6 line context
... ...
@@ -362,390 +362,394 @@
362 362
\f[ \sum_{uv\in A} f(uv) = \sum_{vu\in A} f(vu)
363 363
    \quad \forall u\in V\setminus\{s,t\} \f]
364 364
\f[ 0 \leq f(uv) \leq cap(uv) \quad \forall uv\in A \f]
365 365

	
366 366
LEMON contains several algorithms for solving maximum flow problems:
367 367
- \ref EdmondsKarp Edmonds-Karp algorithm
368 368
  \ref edmondskarp72theoretical.
369 369
- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm
370 370
  \ref goldberg88newapproach.
371 371
- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees
372 372
  \ref dinic70algorithm, \ref sleator83dynamic.
373 373
- \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees
374 374
  \ref goldberg88newapproach, \ref sleator83dynamic.
375 375

	
376 376
In most cases the \ref Preflow algorithm provides the
377 377
fastest method for computing a maximum flow. All implementations
378 378
also provide functions to query the minimum cut, which is the dual
379 379
problem of maximum flow.
380 380

	
381 381
\ref Circulation is a preflow push-relabel algorithm implemented directly
382 382
for finding feasible circulations, which is a somewhat different problem,
383 383
but it is strongly related to maximum flow.
384 384
For more information, see \ref Circulation.
385 385
*/
386 386

	
387 387
/**
388 388
@defgroup min_cost_flow_algs Minimum Cost Flow Algorithms
389 389
@ingroup algs
390 390

	
391 391
\brief Algorithms for finding minimum cost flows and circulations.
392 392

	
393 393
This group contains the algorithms for finding minimum cost flows and
394 394
circulations \ref amo93networkflows. For more information about this
395 395
problem and its dual solution, see \ref min_cost_flow
396 396
"Minimum Cost Flow Problem".
397 397

	
398 398
LEMON contains several algorithms for this problem.
399 399
 - \ref NetworkSimplex Primal Network Simplex algorithm with various
400 400
   pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex.
401 401
 - \ref CostScaling Cost Scaling algorithm based on push/augment and
402 402
   relabel operations \ref goldberg90approximation, \ref goldberg97efficient,
403 403
   \ref bunnagel98efficient.
404 404
 - \ref CapacityScaling Capacity Scaling algorithm based on the successive
405 405
   shortest path method \ref edmondskarp72theoretical.
406 406
 - \ref CycleCanceling Cycle-Canceling algorithms, two of which are
407 407
   strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling.
408 408

	
409 409
In general NetworkSimplex is the most efficient implementation,
410 410
but in special cases other algorithms could be faster.
411 411
For example, if the total supply and/or capacities are rather small,
412 412
CapacityScaling is usually the fastest algorithm (without effective scaling).
413 413
*/
414 414

	
415 415
/**
416 416
@defgroup min_cut Minimum Cut Algorithms
417 417
@ingroup algs
418 418

	
419 419
\brief Algorithms for finding minimum cut in graphs.
420 420

	
421 421
This group contains the algorithms for finding minimum cut in graphs.
422 422

	
423 423
The \e minimum \e cut \e problem is to find a non-empty and non-complete
424 424
\f$X\f$ subset of the nodes with minimum overall capacity on
425 425
outgoing arcs. Formally, there is a \f$G=(V,A)\f$ digraph, a
426 426
\f$cap: A\rightarrow\mathbf{R}^+_0\f$ capacity function. The minimum
427 427
cut is the \f$X\f$ solution of the next optimization problem:
428 428

	
429 429
\f[ \min_{X \subset V, X\not\in \{\emptyset, V\}}
430 430
    \sum_{uv\in A: u\in X, v\not\in X}cap(uv) \f]
431 431

	
432 432
LEMON contains several algorithms related to minimum cut problems:
433 433

	
434 434
- \ref HaoOrlin "Hao-Orlin algorithm" for calculating minimum cut
435 435
  in directed graphs.
436 436
- \ref NagamochiIbaraki "Nagamochi-Ibaraki algorithm" for
437 437
  calculating minimum cut in undirected graphs.
438 438
- \ref GomoryHu "Gomory-Hu tree computation" for calculating
439 439
  all-pairs minimum cut in undirected graphs.
440 440

	
441 441
If you want to find minimum cut just between two distinict nodes,
442 442
see the \ref max_flow "maximum flow problem".
443 443
*/
444 444

	
445 445
/**
446 446
@defgroup min_mean_cycle Minimum Mean Cycle Algorithms
447 447
@ingroup algs
448 448
\brief Algorithms for finding minimum mean cycles.
449 449

	
450 450
This group contains the algorithms for finding minimum mean cycles
451 451
\ref clrs01algorithms, \ref amo93networkflows.
452 452

	
453 453
The \e minimum \e mean \e cycle \e problem is to find a directed cycle
454 454
of minimum mean length (cost) in a digraph.
455 455
The mean length of a cycle is the average length of its arcs, i.e. the
456 456
ratio between the total length of the cycle and the number of arcs on it.
457 457

	
458 458
This problem has an important connection to \e conservative \e length
459 459
\e functions, too. A length function on the arcs of a digraph is called
460 460
conservative if and only if there is no directed cycle of negative total
461 461
length. For an arbitrary length function, the negative of the minimum
462 462
cycle mean is the smallest \f$\epsilon\f$ value so that increasing the
463 463
arc lengths uniformly by \f$\epsilon\f$ results in a conservative length
464 464
function.
465 465

	
466 466
LEMON contains three algorithms for solving the minimum mean cycle problem:
467 467
- \ref KarpMmc Karp's original algorithm \ref amo93networkflows,
468 468
  \ref dasdan98minmeancycle.
469 469
- \ref HartmannOrlinMmc Hartmann-Orlin's algorithm, which is an improved
470 470
  version of Karp's algorithm \ref dasdan98minmeancycle.
471 471
- \ref HowardMmc Howard's policy iteration algorithm
472 472
  \ref dasdan98minmeancycle.
473 473

	
474 474
In practice, the \ref HowardMmc "Howard" algorithm proved to be by far the
475 475
most efficient one, though the best known theoretical bound on its running
476 476
time is exponential.
477 477
Both \ref KarpMmc "Karp" and \ref HartmannOrlinMmc "Hartmann-Orlin" algorithms
478 478
run in time O(ne) and use space O(n<sup>2</sup>+e), but the latter one is
479 479
typically faster due to the applied early termination scheme.
480 480
*/
481 481

	
482 482
/**
483 483
@defgroup matching Matching Algorithms
484 484
@ingroup algs
485 485
\brief Algorithms for finding matchings in graphs and bipartite graphs.
486 486

	
487 487
This group contains the algorithms for calculating
488 488
matchings in graphs and bipartite graphs. The general matching problem is
489 489
finding a subset of the edges for which each node has at most one incident
490 490
edge.
491 491

	
492 492
There are several different algorithms for calculate matchings in
493 493
graphs.  The matching problems in bipartite graphs are generally
494 494
easier than in general graphs. The goal of the matching optimization
495 495
can be finding maximum cardinality, maximum weight or minimum cost
496 496
matching. The search can be constrained to find perfect or
497 497
maximum cardinality matching.
498 498

	
499 499
The matching algorithms implemented in LEMON:
500 500
- \ref MaxBipartiteMatching Hopcroft-Karp augmenting path algorithm
501 501
  for calculating maximum cardinality matching in bipartite graphs.
502 502
- \ref PrBipartiteMatching Push-relabel algorithm
503 503
  for calculating maximum cardinality matching in bipartite graphs.
504 504
- \ref MaxWeightedBipartiteMatching
505 505
  Successive shortest path algorithm for calculating maximum weighted
506 506
  matching and maximum weighted bipartite matching in bipartite graphs.
507 507
- \ref MinCostMaxBipartiteMatching
508 508
  Successive shortest path algorithm for calculating minimum cost maximum
509 509
  matching in bipartite graphs.
510 510
- \ref MaxMatching Edmond's blossom shrinking algorithm for calculating
511 511
  maximum cardinality matching in general graphs.
512 512
- \ref MaxWeightedMatching Edmond's blossom shrinking algorithm for calculating
513 513
  maximum weighted matching in general graphs.
514 514
- \ref MaxWeightedPerfectMatching
515 515
  Edmond's blossom shrinking algorithm for calculating maximum weighted
516 516
  perfect matching in general graphs.
517 517
- \ref MaxFractionalMatching Push-relabel algorithm for calculating
518 518
  maximum cardinality fractional matching in general graphs.
519 519
- \ref MaxWeightedFractionalMatching Augmenting path algorithm for calculating
520 520
  maximum weighted fractional matching in general graphs.
521 521
- \ref MaxWeightedPerfectFractionalMatching
522 522
  Augmenting path algorithm for calculating maximum weighted
523 523
  perfect fractional matching in general graphs.
524 524

	
525 525
\image html matching.png
526 526
\image latex matching.eps "Min Cost Perfect Matching" width=\textwidth
527 527
*/
528 528

	
529 529
/**
530 530
@defgroup graph_properties Connectivity and Other Graph Properties
531 531
@ingroup algs
532 532
\brief Algorithms for discovering the graph properties
533 533

	
534 534
This group contains the algorithms for discovering the graph properties
535 535
like connectivity, bipartiteness, euler property, simplicity etc.
536 536

	
537 537
\image html connected_components.png
538 538
\image latex connected_components.eps "Connected components" width=\textwidth
539 539
*/
540 540

	
541 541
/**
542 542
@defgroup planar Planarity Embedding and Drawing
543 543
@ingroup algs
544 544
\brief Algorithms for planarity checking, embedding and drawing
545 545

	
546 546
This group contains the algorithms for planarity checking,
547 547
embedding and drawing.
548 548

	
549 549
\image html planar.png
550 550
\image latex planar.eps "Plane graph" width=\textwidth
551 551
*/
552 552

	
553 553
/**
554
@defgroup approx Approximation Algorithms
554
@defgroup approx_algs Approximation Algorithms
555 555
@ingroup algs
556 556
\brief Approximation algorithms.
557 557

	
558 558
This group contains the approximation and heuristic algorithms
559 559
implemented in LEMON.
560

	
561
<b>Maximum Clique Problem</b>
562
  - \ref GrossoLocatelliPullanMc An efficient heuristic algorithm of
563
    Grosso, Locatelli, and Pullan.
560 564
*/
561 565

	
562 566
/**
563 567
@defgroup auxalg Auxiliary Algorithms
564 568
@ingroup algs
565 569
\brief Auxiliary algorithms implemented in LEMON.
566 570

	
567 571
This group contains some algorithms implemented in LEMON
568 572
in order to make it easier to implement complex algorithms.
569 573
*/
570 574

	
571 575
/**
572 576
@defgroup gen_opt_group General Optimization Tools
573 577
\brief This group contains some general optimization frameworks
574 578
implemented in LEMON.
575 579

	
576 580
This group contains some general optimization frameworks
577 581
implemented in LEMON.
578 582
*/
579 583

	
580 584
/**
581 585
@defgroup lp_group LP and MIP Solvers
582 586
@ingroup gen_opt_group
583 587
\brief LP and MIP solver interfaces for LEMON.
584 588

	
585 589
This group contains LP and MIP solver interfaces for LEMON.
586 590
Various LP solvers could be used in the same manner with this
587 591
high-level interface.
588 592

	
589 593
The currently supported solvers are \ref glpk, \ref clp, \ref cbc,
590 594
\ref cplex, \ref soplex.
591 595
*/
592 596

	
593 597
/**
594 598
@defgroup lp_utils Tools for Lp and Mip Solvers
595 599
@ingroup lp_group
596 600
\brief Helper tools to the Lp and Mip solvers.
597 601

	
598 602
This group adds some helper tools to general optimization framework
599 603
implemented in LEMON.
600 604
*/
601 605

	
602 606
/**
603 607
@defgroup metah Metaheuristics
604 608
@ingroup gen_opt_group
605 609
\brief Metaheuristics for LEMON library.
606 610

	
607 611
This group contains some metaheuristic optimization tools.
608 612
*/
609 613

	
610 614
/**
611 615
@defgroup utils Tools and Utilities
612 616
\brief Tools and utilities for programming in LEMON
613 617

	
614 618
Tools and utilities for programming in LEMON.
615 619
*/
616 620

	
617 621
/**
618 622
@defgroup gutils Basic Graph Utilities
619 623
@ingroup utils
620 624
\brief Simple basic graph utilities.
621 625

	
622 626
This group contains some simple basic graph utilities.
623 627
*/
624 628

	
625 629
/**
626 630
@defgroup misc Miscellaneous Tools
627 631
@ingroup utils
628 632
\brief Tools for development, debugging and testing.
629 633

	
630 634
This group contains several useful tools for development,
631 635
debugging and testing.
632 636
*/
633 637

	
634 638
/**
635 639
@defgroup timecount Time Measuring and Counting
636 640
@ingroup misc
637 641
\brief Simple tools for measuring the performance of algorithms.
638 642

	
639 643
This group contains simple tools for measuring the performance
640 644
of algorithms.
641 645
*/
642 646

	
643 647
/**
644 648
@defgroup exceptions Exceptions
645 649
@ingroup utils
646 650
\brief Exceptions defined in LEMON.
647 651

	
648 652
This group contains the exceptions defined in LEMON.
649 653
*/
650 654

	
651 655
/**
652 656
@defgroup io_group Input-Output
653 657
\brief Graph Input-Output methods
654 658

	
655 659
This group contains the tools for importing and exporting graphs
656 660
and graph related data. Now it supports the \ref lgf-format
657 661
"LEMON Graph Format", the \c DIMACS format and the encapsulated
658 662
postscript (EPS) format.
659 663
*/
660 664

	
661 665
/**
662 666
@defgroup lemon_io LEMON Graph Format
663 667
@ingroup io_group
664 668
\brief Reading and writing LEMON Graph Format.
665 669

	
666 670
This group contains methods for reading and writing
667 671
\ref lgf-format "LEMON Graph Format".
668 672
*/
669 673

	
670 674
/**
671 675
@defgroup eps_io Postscript Exporting
672 676
@ingroup io_group
673 677
\brief General \c EPS drawer and graph exporter
674 678

	
675 679
This group contains general \c EPS drawing methods and special
676 680
graph exporting tools.
677 681
*/
678 682

	
679 683
/**
680 684
@defgroup dimacs_group DIMACS Format
681 685
@ingroup io_group
682 686
\brief Read and write files in DIMACS format
683 687

	
684 688
Tools to read a digraph from or write it to a file in DIMACS format data.
685 689
*/
686 690

	
687 691
/**
688 692
@defgroup nauty_group NAUTY Format
689 693
@ingroup io_group
690 694
\brief Read \e Nauty format
691 695

	
692 696
Tool to read graphs from \e Nauty format data.
693 697
*/
694 698

	
695 699
/**
696 700
@defgroup concept Concepts
697 701
\brief Skeleton classes and concept checking classes
698 702

	
699 703
This group contains the data/algorithm skeletons and concept checking
700 704
classes implemented in LEMON.
701 705

	
702 706
The purpose of the classes in this group is fourfold.
703 707

	
704 708
- These classes contain the documentations of the %concepts. In order
705 709
  to avoid document multiplications, an implementation of a concept
706 710
  simply refers to the corresponding concept class.
707 711

	
708 712
- These classes declare every functions, <tt>typedef</tt>s etc. an
709 713
  implementation of the %concepts should provide, however completely
710 714
  without implementations and real data structures behind the
711 715
  interface. On the other hand they should provide nothing else. All
712 716
  the algorithms working on a data structure meeting a certain concept
713 717
  should compile with these classes. (Though it will not run properly,
714 718
  of course.) In this way it is easily to check if an algorithm
715 719
  doesn't use any extra feature of a certain implementation.
716 720

	
717 721
- The concept descriptor classes also provide a <em>checker class</em>
718 722
  that makes it possible to check whether a certain implementation of a
719 723
  concept indeed provides all the required features.
720 724

	
721 725
- Finally, They can serve as a skeleton of a new implementation of a concept.
722 726
*/
723 727

	
724 728
/**
725 729
@defgroup graph_concepts Graph Structure Concepts
726 730
@ingroup concept
727 731
\brief Skeleton and concept checking classes for graph structures
728 732

	
729 733
This group contains the skeletons and concept checking classes of
730 734
graph structures.
731 735
*/
732 736

	
733 737
/**
734 738
@defgroup map_concepts Map Concepts
735 739
@ingroup concept
736 740
\brief Skeleton and concept checking classes for maps
737 741

	
738 742
This group contains the skeletons and concept checking classes of maps.
739 743
*/
740 744

	
741 745
/**
742 746
@defgroup tools Standalone Utility Applications
743 747

	
744 748
Some utility applications are listed here.
745 749

	
746 750
The standard compilation procedure (<tt>./configure;make</tt>) will compile
747 751
them, as well.
748 752
*/
749 753

	
750 754
/**
751 755
\anchor demoprograms
Ignore white space 6 line context
... ...
@@ -108,194 +108,207 @@
108 108
}
109 109

	
110 110

	
111 111
%%%%% General books %%%%%
112 112

	
113 113
@book{amo93networkflows,
114 114
  author =       {Ravindra K. Ahuja and Thomas L. Magnanti and James
115 115
                  B. Orlin},
116 116
  title =        {Network Flows: Theory, Algorithms, and Applications},
117 117
  publisher =    {Prentice-Hall, Inc.},
118 118
  year =         1993,
119 119
  month =        feb,
120 120
  isbn =         {978-0136175490}
121 121
}
122 122

	
123 123
@book{schrijver03combinatorial,
124 124
  author =       {Alexander Schrijver},
125 125
  title =        {Combinatorial Optimization: Polyhedra and Efficiency},
126 126
  publisher =    {Springer-Verlag},
127 127
  year =         2003,
128 128
  isbn =         {978-3540443896}
129 129
}
130 130

	
131 131
@book{clrs01algorithms,
132 132
  author =       {Thomas H. Cormen and Charles E. Leiserson and Ronald
133 133
                  L. Rivest and Clifford Stein},
134 134
  title =        {Introduction to Algorithms},
135 135
  publisher =    {The MIT Press},
136 136
  year =         2001,
137 137
  edition =      {2nd}
138 138
}
139 139

	
140 140
@book{stroustrup00cpp,
141 141
  author =       {Bjarne Stroustrup},
142 142
  title =        {The C++ Programming Language},
143 143
  edition =      {3rd},
144 144
  publisher =    {Addison-Wesley Professional},
145 145
  isbn =         0201700735,
146 146
  month =        {February},
147 147
  year =         2000
148 148
}
149 149

	
150 150

	
151 151
%%%%% Maximum flow algorithms %%%%%
152 152

	
153 153
@article{edmondskarp72theoretical,
154 154
  author =       {Jack Edmonds and Richard M. Karp},
155 155
  title =        {Theoretical improvements in algorithmic efficiency
156 156
                  for network flow problems},
157 157
  journal =      {Journal of the ACM},
158 158
  year =         1972,
159 159
  volume =       19,
160 160
  number =       2,
161 161
  pages =        {248-264}
162 162
}
163 163

	
164 164
@article{goldberg88newapproach,
165 165
  author =       {Andrew V. Goldberg and Robert E. Tarjan},
166 166
  title =        {A new approach to the maximum flow problem},
167 167
  journal =      {Journal of the ACM},
168 168
  year =         1988,
169 169
  volume =       35,
170 170
  number =       4,
171 171
  pages =        {921-940}
172 172
}
173 173

	
174 174
@article{dinic70algorithm,
175 175
  author =       {E. A. Dinic},
176 176
  title =        {Algorithm for solution of a problem of maximum flow
177 177
                  in a network with power estimation},
178 178
  journal =      {Soviet Math. Doklady},
179 179
  year =         1970,
180 180
  volume =       11,
181 181
  pages =        {1277-1280}
182 182
}
183 183

	
184 184
@article{goldberg08partial,
185 185
  author =       {Andrew V. Goldberg},
186 186
  title =        {The Partial Augment-Relabel Algorithm for the
187 187
                  Maximum Flow Problem},
188 188
  journal =      {16th Annual European Symposium on Algorithms},
189 189
  year =         2008,
190 190
  pages =        {466-477}
191 191
}
192 192

	
193 193
@article{sleator83dynamic,
194 194
  author =       {Daniel D. Sleator and Robert E. Tarjan},
195 195
  title =        {A data structure for dynamic trees},
196 196
  journal =      {Journal of Computer and System Sciences},
197 197
  year =         1983,
198 198
  volume =       26,
199 199
  number =       3,
200 200
  pages =        {362-391}
201 201
}
202 202

	
203 203

	
204 204
%%%%% Minimum mean cycle algorithms %%%%%
205 205

	
206 206
@article{karp78characterization,
207 207
  author =       {Richard M. Karp},
208 208
  title =        {A characterization of the minimum cycle mean in a
209 209
                  digraph},
210 210
  journal =      {Discrete Math.},
211 211
  year =         1978,
212 212
  volume =       23,
213 213
  pages =        {309-311}
214 214
}
215 215

	
216 216
@article{dasdan98minmeancycle,
217 217
  author =       {Ali Dasdan and Rajesh K. Gupta},
218 218
  title =        {Faster Maximum and Minimum Mean Cycle Alogrithms for
219 219
                  System Performance Analysis},
220 220
  journal =      {IEEE Transactions on Computer-Aided Design of
221 221
                  Integrated Circuits and Systems},
222 222
  year =         1998,
223 223
  volume =       17,
224 224
  number =       10,
225 225
  pages =        {889-899}
226 226
}
227 227

	
228 228

	
229 229
%%%%% Minimum cost flow algorithms %%%%%
230 230

	
231 231
@article{klein67primal,
232 232
  author =       {Morton Klein},
233 233
  title =        {A primal method for minimal cost flows with
234 234
                  applications to the assignment and transportation
235 235
                  problems},
236 236
  journal =      {Management Science},
237 237
  year =         1967,
238 238
  volume =       14,
239 239
  pages =        {205-220}
240 240
}
241 241

	
242 242
@article{goldberg89cyclecanceling,
243 243
  author =       {Andrew V. Goldberg and Robert E. Tarjan},
244 244
  title =        {Finding minimum-cost circulations by canceling
245 245
                  negative cycles},
246 246
  journal =      {Journal of the ACM},
247 247
  year =         1989,
248 248
  volume =       36,
249 249
  number =       4,
250 250
  pages =        {873-886}
251 251
}
252 252

	
253 253
@article{goldberg90approximation,
254 254
  author =       {Andrew V. Goldberg and Robert E. Tarjan},
255 255
  title =        {Finding Minimum-Cost Circulations by Successive
256 256
                  Approximation},
257 257
  journal =      {Mathematics of Operations Research},
258 258
  year =         1990,
259 259
  volume =       15,
260 260
  number =       3,
261 261
  pages =        {430-466}
262 262
}
263 263

	
264 264
@article{goldberg97efficient,
265 265
  author =       {Andrew V. Goldberg},
266 266
  title =        {An Efficient Implementation of a Scaling
267 267
                  Minimum-Cost Flow Algorithm},
268 268
  journal =      {Journal of Algorithms},
269 269
  year =         1997,
270 270
  volume =       22,
271 271
  number =       1,
272 272
  pages =        {1-29}
273 273
}
274 274

	
275 275
@article{bunnagel98efficient,
276 276
  author =       {Ursula B{\"u}nnagel and Bernhard Korte and Jens
277 277
                  Vygen},
278 278
  title =        {Efficient implementation of the {G}oldberg-{T}arjan
279 279
                  minimum-cost flow algorithm},
280 280
  journal =      {Optimization Methods and Software},
281 281
  year =         1998,
282 282
  volume =       10,
283 283
  pages =        {157-174}
284 284
}
285 285

	
286 286
@book{dantzig63linearprog,
287 287
  author =       {George B. Dantzig},
288 288
  title =        {Linear Programming and Extensions},
289 289
  publisher =    {Princeton University Press},
290 290
  year =         1963
291 291
}
292 292

	
293 293
@mastersthesis{kellyoneill91netsimplex,
294 294
  author =       {Damian J. Kelly and Garrett M. O'Neill},
295 295
  title =        {The Minimum Cost Flow Problem and The Network
296 296
                  Simplex Method},
297 297
  school =       {University College},
298 298
  address =      {Dublin, Ireland},
299 299
  year =         1991,
300
  month =        sep,
300
  month =        sep
301 301
}
302

	
303
%%%%% Other algorithms %%%%%
304

	
305
@article{grosso08maxclique,
306
  author =       {Andrea Grosso and Marco Locatelli and Wayne Pullan},
307
  title =        {Simple ingredients leading to very efficient
308
                  heuristics for the maximum clique problem},
309
  journal =      {Journal of Heuristics},
310
  year =         2008,
311
  volume =       14,
312
  number =       6,
313
  pages =        {587--612}
314
}
Ignore white space 6 line context
1 1
EXTRA_DIST += \
2 2
	lemon/lemon.pc.in \
3 3
	lemon/CMakeLists.txt \
4 4
	lemon/config.h.cmake
5 5

	
6 6
pkgconfig_DATA += lemon/lemon.pc
7 7

	
8 8
lib_LTLIBRARIES += lemon/libemon.la
9 9

	
10 10
lemon_libemon_la_SOURCES = \
11 11
	lemon/arg_parser.cc \
12 12
	lemon/base.cc \
13 13
	lemon/color.cc \
14 14
	lemon/lp_base.cc \
15 15
	lemon/lp_skeleton.cc \
16 16
	lemon/random.cc \
17 17
	lemon/bits/windows.cc
18 18

	
19 19
nodist_lemon_HEADERS = lemon/config.h	
20 20

	
21 21
lemon_libemon_la_CXXFLAGS = \
22 22
	$(AM_CXXFLAGS) \
23 23
	$(GLPK_CFLAGS) \
24 24
	$(CPLEX_CFLAGS) \
25 25
	$(SOPLEX_CXXFLAGS) \
26 26
	$(CLP_CXXFLAGS) \
27 27
	$(CBC_CXXFLAGS)
28 28

	
29 29
lemon_libemon_la_LDFLAGS = \
30 30
	$(GLPK_LIBS) \
31 31
	$(CPLEX_LIBS) \
32 32
	$(SOPLEX_LIBS) \
33 33
	$(CLP_LIBS) \
34 34
	$(CBC_LIBS)
35 35

	
36 36
if HAVE_GLPK
37 37
lemon_libemon_la_SOURCES += lemon/glpk.cc
38 38
endif
39 39

	
40 40
if HAVE_CPLEX
41 41
lemon_libemon_la_SOURCES += lemon/cplex.cc
42 42
endif
43 43

	
44 44
if HAVE_SOPLEX
45 45
lemon_libemon_la_SOURCES += lemon/soplex.cc
46 46
endif
47 47

	
48 48
if HAVE_CLP
49 49
lemon_libemon_la_SOURCES += lemon/clp.cc
50 50
endif
51 51

	
52 52
if HAVE_CBC
53 53
lemon_libemon_la_SOURCES += lemon/cbc.cc
54 54
endif
55 55

	
56 56
lemon_HEADERS += \
57 57
	lemon/adaptors.h \
58 58
	lemon/arg_parser.h \
59 59
	lemon/assert.h \
60 60
	lemon/bellman_ford.h \
61 61
	lemon/bfs.h \
62 62
	lemon/bin_heap.h \
63 63
	lemon/binomial_heap.h \
64 64
	lemon/bucket_heap.h \
65 65
	lemon/capacity_scaling.h \
66 66
	lemon/cbc.h \
67 67
	lemon/circulation.h \
68 68
	lemon/clp.h \
69 69
	lemon/color.h \
70 70
	lemon/concept_check.h \
71 71
	lemon/connectivity.h \
72 72
	lemon/core.h \
73 73
	lemon/cost_scaling.h \
74 74
	lemon/counter.h \
75 75
	lemon/cplex.h \
76 76
	lemon/cycle_canceling.h \
77 77
	lemon/dfs.h \
78 78
	lemon/dheap.h \
79 79
	lemon/dijkstra.h \
80 80
	lemon/dim2.h \
81 81
	lemon/dimacs.h \
82 82
	lemon/edge_set.h \
83 83
	lemon/elevator.h \
84 84
	lemon/error.h \
85 85
	lemon/euler.h \
86 86
	lemon/fib_heap.h \
87 87
	lemon/fractional_matching.h \
88 88
	lemon/full_graph.h \
89 89
	lemon/glpk.h \
90 90
	lemon/gomory_hu.h \
91 91
	lemon/graph_to_eps.h \
92 92
	lemon/grid_graph.h \
93
	lemon/grosso_locatelli_pullan_mc.h \
93 94
	lemon/hartmann_orlin_mmc.h \
94 95
	lemon/howard_mmc.h \
95 96
	lemon/hypercube_graph.h \
96 97
	lemon/karp_mmc.h \
97 98
	lemon/kruskal.h \
98 99
	lemon/hao_orlin.h \
99 100
	lemon/lgf_reader.h \
100 101
	lemon/lgf_writer.h \
101 102
	lemon/list_graph.h \
102 103
	lemon/lp.h \
103 104
	lemon/lp_base.h \
104 105
	lemon/lp_skeleton.h \
105 106
	lemon/maps.h \
106 107
	lemon/matching.h \
107 108
	lemon/math.h \
108 109
	lemon/min_cost_arborescence.h \
109 110
	lemon/nauty_reader.h \
110 111
	lemon/network_simplex.h \
111 112
	lemon/pairing_heap.h \
112 113
	lemon/path.h \
113 114
	lemon/planarity.h \
114 115
	lemon/preflow.h \
115 116
	lemon/quad_heap.h \
116 117
	lemon/radix_heap.h \
117 118
	lemon/radix_sort.h \
118 119
	lemon/random.h \
119 120
	lemon/smart_graph.h \
120 121
	lemon/soplex.h \
121 122
	lemon/static_graph.h \
122 123
	lemon/suurballe.h \
123 124
	lemon/time_measure.h \
124 125
	lemon/tolerance.h \
125 126
	lemon/unionfind.h \
126 127
	lemon/bits/windows.h
127 128

	
128 129
bits_HEADERS += \
129 130
	lemon/bits/alteration_notifier.h \
130 131
	lemon/bits/array_map.h \
131 132
	lemon/bits/bezier.h \
132 133
	lemon/bits/default_map.h \
133 134
	lemon/bits/edge_set_extender.h \
134 135
	lemon/bits/enable_if.h \
135 136
	lemon/bits/graph_adaptor_extender.h \
136 137
	lemon/bits/graph_extender.h \
137 138
	lemon/bits/map_extender.h \
138 139
	lemon/bits/path_dump.h \
139 140
	lemon/bits/solver_bits.h \
140 141
	lemon/bits/traits.h \
141 142
	lemon/bits/variant.h \
142 143
	lemon/bits/vector_map.h
143 144

	
144 145
concept_HEADERS += \
145 146
	lemon/concepts/digraph.h \
146 147
	lemon/concepts/graph.h \
147 148
	lemon/concepts/graph_components.h \
148 149
	lemon/concepts/heap.h \
149 150
	lemon/concepts/maps.h \
150 151
	lemon/concepts/path.h
Ignore white space 384 line context
1 1
INCLUDE_DIRECTORIES(
2 2
  ${PROJECT_SOURCE_DIR}
3 3
  ${PROJECT_BINARY_DIR}
4 4
)
5 5

	
6 6
LINK_DIRECTORIES(
7 7
  ${PROJECT_BINARY_DIR}/lemon
8 8
)
9 9

	
10 10
SET(TESTS
11 11
  adaptors_test
12 12
  bellman_ford_test
13 13
  bfs_test
14 14
  circulation_test
15 15
  connectivity_test
16 16
  counter_test
17 17
  dfs_test
18 18
  digraph_test
19 19
  dijkstra_test
20 20
  dim_test
21 21
  edge_set_test
22 22
  error_test
23 23
  euler_test
24 24
  fractional_matching_test
25 25
  gomory_hu_test
26 26
  graph_copy_test
27 27
  graph_test
28 28
  graph_utils_test
29 29
  hao_orlin_test
30 30
  heap_test
31 31
  kruskal_test
32 32
  maps_test
33 33
  matching_test
34
  max_clique_test
34 35
  min_cost_arborescence_test
35 36
  min_cost_flow_test
36 37
  min_mean_cycle_test
37 38
  path_test
38 39
  planarity_test
39 40
  preflow_test
40 41
  radix_sort_test
41 42
  random_test
42 43
  suurballe_test
43 44
  time_measure_test
44 45
  unionfind_test
45 46
)
46 47

	
47 48
IF(LEMON_HAVE_LP)
48 49
  ADD_EXECUTABLE(lp_test lp_test.cc)
49 50
  SET(LP_TEST_LIBS lemon)
50 51

	
51 52
  IF(LEMON_HAVE_GLPK)
52 53
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${GLPK_LIBRARIES})
53 54
  ENDIF()
54 55
  IF(LEMON_HAVE_CPLEX)
55 56
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${CPLEX_LIBRARIES})
56 57
  ENDIF()
57 58
  IF(LEMON_HAVE_CLP)
58 59
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${COIN_CLP_LIBRARIES})
59 60
  ENDIF()
60 61

	
61 62
  TARGET_LINK_LIBRARIES(lp_test ${LP_TEST_LIBS})
62 63
  ADD_TEST(lp_test lp_test)
63 64

	
64 65
  IF(WIN32 AND LEMON_HAVE_GLPK)
65 66
    GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
66 67
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
67 68
    ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
68 69
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
69 70
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
70 71
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
71 72
    )
72 73
  ENDIF()
73 74

	
74 75
  IF(WIN32 AND LEMON_HAVE_CPLEX)
75 76
    GET_TARGET_PROPERTY(TARGET_LOC lp_test LOCATION)
76 77
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
77 78
    ADD_CUSTOM_COMMAND(TARGET lp_test POST_BUILD
78 79
      COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex91.dll ${TARGET_PATH}
79 80
    )
80 81
  ENDIF()
81 82
ENDIF()
82 83

	
83 84
IF(LEMON_HAVE_MIP)
84 85
  ADD_EXECUTABLE(mip_test mip_test.cc)
85 86
  SET(MIP_TEST_LIBS lemon)
86 87

	
87 88
  IF(LEMON_HAVE_GLPK)
88 89
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${GLPK_LIBRARIES})
89 90
  ENDIF()
90 91
  IF(LEMON_HAVE_CPLEX)
91 92
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${CPLEX_LIBRARIES})
92 93
  ENDIF()
93 94
  IF(LEMON_HAVE_CBC)
94 95
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${COIN_CBC_LIBRARIES})
95 96
  ENDIF()
96 97

	
97 98
  TARGET_LINK_LIBRARIES(mip_test ${MIP_TEST_LIBS})
98 99
  ADD_TEST(mip_test mip_test)
99 100

	
100 101
  IF(WIN32 AND LEMON_HAVE_GLPK)
101 102
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
102 103
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
103 104
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
104 105
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
105 106
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
106 107
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
107 108
    )
108 109
  ENDIF()
109 110

	
110 111
  IF(WIN32 AND LEMON_HAVE_CPLEX)
111 112
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
112 113
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
113 114
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
114 115
      COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex91.dll ${TARGET_PATH}
115 116
    )
116 117
  ENDIF()
117 118
ENDIF()
118 119

	
119 120
FOREACH(TEST_NAME ${TESTS})
120 121
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
121 122
    ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.cc)
122 123
  ELSE()
123 124
    ADD_EXECUTABLE(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cc)
124 125
  ENDIF()
125 126
  TARGET_LINK_LIBRARIES(${TEST_NAME} lemon)
126 127
  ADD_TEST(${TEST_NAME} ${TEST_NAME})
127 128
  ADD_DEPENDENCIES(check ${TEST_NAME})
128 129
ENDFOREACH()
Ignore white space 6 line context
1 1
if USE_VALGRIND
2 2
TESTS_ENVIRONMENT=$(top_srcdir)/scripts/valgrind-wrapper.sh
3 3
endif
4 4

	
5 5
EXTRA_DIST += \
6 6
	test/CMakeLists.txt
7 7

	
8 8
noinst_HEADERS += \
9 9
	test/graph_test.h \
10 10
	test/test_tools.h
11 11

	
12 12
check_PROGRAMS += \
13 13
	test/adaptors_test \
14 14
	test/bellman_ford_test \
15 15
	test/bfs_test \
16 16
	test/circulation_test \
17 17
	test/connectivity_test \
18 18
	test/counter_test \
19 19
	test/dfs_test \
20 20
	test/digraph_test \
21 21
	test/dijkstra_test \
22 22
	test/dim_test \
23 23
	test/edge_set_test \
24 24
	test/error_test \
25 25
	test/euler_test \
26 26
	test/fractional_matching_test \
27 27
	test/gomory_hu_test \
28 28
	test/graph_copy_test \
29 29
	test/graph_test \
30 30
	test/graph_utils_test \
31 31
	test/hao_orlin_test \
32 32
	test/heap_test \
33 33
	test/kruskal_test \
34 34
	test/maps_test \
35 35
	test/matching_test \
36
	test/max_clique_test \
36 37
	test/min_cost_arborescence_test \
37 38
	test/min_cost_flow_test \
38 39
	test/min_mean_cycle_test \
39 40
	test/path_test \
40 41
	test/planarity_test \
41 42
	test/preflow_test \
42 43
	test/radix_sort_test \
43 44
	test/random_test \
44 45
	test/suurballe_test \
45 46
	test/test_tools_fail \
46 47
	test/test_tools_pass \
47 48
	test/time_measure_test \
48 49
	test/unionfind_test
49 50

	
50 51
test_test_tools_pass_DEPENDENCIES = demo
51 52

	
52 53
if HAVE_LP
53 54
check_PROGRAMS += test/lp_test
54 55
endif HAVE_LP
55 56
if HAVE_MIP
56 57
check_PROGRAMS += test/mip_test
57 58
endif HAVE_MIP
58 59

	
59 60
TESTS += $(check_PROGRAMS)
60 61
XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
61 62

	
62 63
test_adaptors_test_SOURCES = test/adaptors_test.cc
63 64
test_bellman_ford_test_SOURCES = test/bellman_ford_test.cc
64 65
test_bfs_test_SOURCES = test/bfs_test.cc
65 66
test_circulation_test_SOURCES = test/circulation_test.cc
66 67
test_counter_test_SOURCES = test/counter_test.cc
67 68
test_connectivity_test_SOURCES = test/connectivity_test.cc
68 69
test_dfs_test_SOURCES = test/dfs_test.cc
69 70
test_digraph_test_SOURCES = test/digraph_test.cc
70 71
test_dijkstra_test_SOURCES = test/dijkstra_test.cc
71 72
test_dim_test_SOURCES = test/dim_test.cc
72 73
test_edge_set_test_SOURCES = test/edge_set_test.cc
73 74
test_error_test_SOURCES = test/error_test.cc
74 75
test_euler_test_SOURCES = test/euler_test.cc
75 76
test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc
76 77
test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc
77 78
test_graph_copy_test_SOURCES = test/graph_copy_test.cc
78 79
test_graph_test_SOURCES = test/graph_test.cc
79 80
test_graph_utils_test_SOURCES = test/graph_utils_test.cc
80 81
test_heap_test_SOURCES = test/heap_test.cc
81 82
test_kruskal_test_SOURCES = test/kruskal_test.cc
82 83
test_hao_orlin_test_SOURCES = test/hao_orlin_test.cc
83 84
test_lp_test_SOURCES = test/lp_test.cc
84 85
test_maps_test_SOURCES = test/maps_test.cc
85 86
test_mip_test_SOURCES = test/mip_test.cc
86 87
test_matching_test_SOURCES = test/matching_test.cc
88
test_max_clique_test_SOURCES = test/max_clique_test.cc
87 89
test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
88 90
test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
89 91
test_min_mean_cycle_test_SOURCES = test/min_mean_cycle_test.cc
90 92
test_path_test_SOURCES = test/path_test.cc
91 93
test_planarity_test_SOURCES = test/planarity_test.cc
92 94
test_preflow_test_SOURCES = test/preflow_test.cc
93 95
test_radix_sort_test_SOURCES = test/radix_sort_test.cc
94 96
test_suurballe_test_SOURCES = test/suurballe_test.cc
95 97
test_random_test_SOURCES = test/random_test.cc
96 98
test_test_tools_fail_SOURCES = test/test_tools_fail.cc
97 99
test_test_tools_pass_SOURCES = test/test_tools_pass.cc
98 100
test_time_measure_test_SOURCES = test/time_measure_test.cc
99 101
test_unionfind_test_SOURCES = test/unionfind_test.cc
0 comments (0 inline)