gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add a heuristic algorithm for the max clique problem (#380)
0 5 2
default
7 files 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 128 line context
... ...
@@ -490,134 +490,138 @@
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
*/
Ignore white space 6 line context
... ...
@@ -236,66 +236,79 @@
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
... ...
@@ -29,122 +29,123 @@
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 6 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})
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)