↑ Collapse diff ↑
Ignore white space 3221225472 line context
1
prefix=@CMAKE_INSTALL_PREFIX@
2
exec_prefix=@CMAKE_INSTALL_PREFIX@/bin
3
libdir=@CMAKE_INSTALL_PREFIX@/lib
4
includedir=@CMAKE_INSTALL_PREFIX@/include
5

	
6
Name: @PROJECT_NAME@
7
Description: Library for Efficient Modeling and Optimization in Networks
8
Version: @PROJECT_VERSION@
9
Libs: -L${libdir} -lemon @GLPK_LIBS@ @CPLEX_LIBS@ @SOPLEX_LIBS@ @CLP_LIBS@ @CBC_LIBS@
10
Cflags: -I${includedir}
Ignore white space 3221225472 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_NAGAMOCHI_IBARAKI_H
20
#define LEMON_NAGAMOCHI_IBARAKI_H
21

	
22

	
23
/// \ingroup min_cut
24
/// \file
25
/// \brief Implementation of the Nagamochi-Ibaraki algorithm.
26

	
27
#include <lemon/core.h>
28
#include <lemon/bin_heap.h>
29
#include <lemon/bucket_heap.h>
30
#include <lemon/maps.h>
31
#include <lemon/radix_sort.h>
32
#include <lemon/unionfind.h>
33

	
34
#include <cassert>
35

	
36
namespace lemon {
37

	
38
  /// \brief Default traits class for NagamochiIbaraki class.
39
  ///
40
  /// Default traits class for NagamochiIbaraki class.
41
  /// \param GR The undirected graph type.
42
  /// \param CM Type of capacity map.
43
  template <typename GR, typename CM>
44
  struct NagamochiIbarakiDefaultTraits {
45
    /// The type of the capacity map.
46
    typedef typename CM::Value Value;
47

	
48
    /// The undirected graph type the algorithm runs on.
49
    typedef GR Graph;
50

	
51
    /// \brief The type of the map that stores the edge capacities.
52
    ///
53
    /// The type of the map that stores the edge capacities.
54
    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
55
    typedef CM CapacityMap;
56

	
57
    /// \brief Instantiates a CapacityMap.
58
    ///
59
    /// This function instantiates a \ref CapacityMap.
60
#ifdef DOXYGEN
61
    static CapacityMap *createCapacityMap(const Graph& graph)
62
#else
63
    static CapacityMap *createCapacityMap(const Graph&)
64
#endif
65
    {
66
        LEMON_ASSERT(false, "CapacityMap is not initialized");
67
        return 0; // ignore warnings
68
    }
69

	
70
    /// \brief The cross reference type used by heap.
71
    ///
72
    /// The cross reference type used by heap.
73
    /// Usually \c Graph::NodeMap<int>.
74
    typedef typename Graph::template NodeMap<int> HeapCrossRef;
75

	
76
    /// \brief Instantiates a HeapCrossRef.
77
    ///
78
    /// This function instantiates a \ref HeapCrossRef.
79
    /// \param g is the graph, to which we would like to define the
80
    /// \ref HeapCrossRef.
81
    static HeapCrossRef *createHeapCrossRef(const Graph& g) {
82
      return new HeapCrossRef(g);
83
    }
84

	
85
    /// \brief The heap type used by NagamochiIbaraki algorithm.
86
    ///
87
    /// The heap type used by NagamochiIbaraki algorithm. It has to
88
    /// maximize the priorities.
89
    ///
90
    /// \sa BinHeap
91
    /// \sa NagamochiIbaraki
92
    typedef BinHeap<Value, HeapCrossRef, std::greater<Value> > Heap;
93

	
94
    /// \brief Instantiates a Heap.
95
    ///
96
    /// This function instantiates a \ref Heap.
97
    /// \param r is the cross reference of the heap.
98
    static Heap *createHeap(HeapCrossRef& r) {
99
      return new Heap(r);
100
    }
101
  };
102

	
103
  /// \ingroup min_cut
104
  ///
105
  /// \brief Calculates the minimum cut in an undirected graph.
106
  ///
107
  /// Calculates the minimum cut in an undirected graph with the
108
  /// Nagamochi-Ibaraki algorithm. The algorithm separates the graph's
109
  /// nodes into two partitions with the minimum sum of edge capacities
110
  /// between the two partitions. The algorithm can be used to test
111
  /// the network reliability, especially to test how many links have
112
  /// to be destroyed in the network to split it to at least two
113
  /// distinict subnetworks.
114
  ///
115
  /// The complexity of the algorithm is \f$ O(nm\log(n)) \f$ but with
116
  /// \ref FibHeap "Fibonacci heap" it can be decreased to
117
  /// \f$ O(nm+n^2\log(n)) \f$.  When the edges have unit capacities,
118
  /// \c BucketHeap can be used which yields \f$ O(nm) \f$ time
119
  /// complexity.
120
  ///
121
  /// \warning The value type of the capacity map should be able to
122
  /// hold any cut value of the graph, otherwise the result can
123
  /// overflow.
124
  /// \note This capacity is supposed to be integer type.
125
#ifdef DOXYGEN
126
  template <typename GR, typename CM, typename TR>
127
#else
128
  template <typename GR,
129
            typename CM = typename GR::template EdgeMap<int>,
130
            typename TR = NagamochiIbarakiDefaultTraits<GR, CM> >
131
#endif
132
  class NagamochiIbaraki {
133
  public:
134

	
135
    typedef TR Traits;
136
    /// The type of the underlying graph.
137
    typedef typename Traits::Graph Graph;
138

	
139
    /// The type of the capacity map.
140
    typedef typename Traits::CapacityMap CapacityMap;
141
    /// The value type of the capacity map.
142
    typedef typename Traits::CapacityMap::Value Value;
143

	
144
    /// The heap type used by the algorithm.
145
    typedef typename Traits::Heap Heap;
146
    /// The cross reference type used for the heap.
147
    typedef typename Traits::HeapCrossRef HeapCrossRef;
148

	
149
    ///\name Named template parameters
150

	
151
    ///@{
152

	
153
    struct SetUnitCapacityTraits : public Traits {
154
      typedef ConstMap<typename Graph::Edge, Const<int, 1> > CapacityMap;
155
      static CapacityMap *createCapacityMap(const Graph&) {
156
        return new CapacityMap();
157
      }
158
    };
159

	
160
    /// \brief \ref named-templ-param "Named parameter" for setting
161
    /// the capacity map to a constMap<Edge, int, 1>() instance
162
    ///
163
    /// \ref named-templ-param "Named parameter" for setting
164
    /// the capacity map to a constMap<Edge, int, 1>() instance
165
    struct SetUnitCapacity
166
      : public NagamochiIbaraki<Graph, CapacityMap,
167
                                SetUnitCapacityTraits> {
168
      typedef NagamochiIbaraki<Graph, CapacityMap,
169
                               SetUnitCapacityTraits> Create;
170
    };
171

	
172

	
173
    template <class H, class CR>
174
    struct SetHeapTraits : public Traits {
175
      typedef CR HeapCrossRef;
176
      typedef H Heap;
177
      static HeapCrossRef *createHeapCrossRef(int num) {
178
        LEMON_ASSERT(false, "HeapCrossRef is not initialized");
179
        return 0; // ignore warnings
180
      }
181
      static Heap *createHeap(HeapCrossRef &) {
182
        LEMON_ASSERT(false, "Heap is not initialized");
183
        return 0; // ignore warnings
184
      }
185
    };
186

	
187
    /// \brief \ref named-templ-param "Named parameter" for setting
188
    /// heap and cross reference type
189
    ///
190
    /// \ref named-templ-param "Named parameter" for setting heap and
191
    /// cross reference type. The heap has to maximize the priorities.
192
    template <class H, class CR = RangeMap<int> >
193
    struct SetHeap
194
      : public NagamochiIbaraki<Graph, CapacityMap, SetHeapTraits<H, CR> > {
195
      typedef NagamochiIbaraki< Graph, CapacityMap, SetHeapTraits<H, CR> >
196
      Create;
197
    };
198

	
199
    template <class H, class CR>
200
    struct SetStandardHeapTraits : public Traits {
201
      typedef CR HeapCrossRef;
202
      typedef H Heap;
203
      static HeapCrossRef *createHeapCrossRef(int size) {
204
        return new HeapCrossRef(size);
205
      }
206
      static Heap *createHeap(HeapCrossRef &crossref) {
207
        return new Heap(crossref);
208
      }
209
    };
210

	
211
    /// \brief \ref named-templ-param "Named parameter" for setting
212
    /// heap and cross reference type with automatic allocation
213
    ///
214
    /// \ref named-templ-param "Named parameter" for setting heap and
215
    /// cross reference type with automatic allocation. They should
216
    /// have standard constructor interfaces to be able to
217
    /// automatically created by the algorithm (i.e. the graph should
218
    /// be passed to the constructor of the cross reference and the
219
    /// cross reference should be passed to the constructor of the
220
    /// heap). However, external heap and cross reference objects
221
    /// could also be passed to the algorithm using the \ref heap()
222
    /// function before calling \ref run() or \ref init(). The heap
223
    /// has to maximize the priorities.
224
    /// \sa SetHeap
225
    template <class H, class CR = RangeMap<int> >
226
    struct SetStandardHeap
227
      : public NagamochiIbaraki<Graph, CapacityMap,
228
                                SetStandardHeapTraits<H, CR> > {
229
      typedef NagamochiIbaraki<Graph, CapacityMap,
230
                               SetStandardHeapTraits<H, CR> > Create;
231
    };
232

	
233
    ///@}
234

	
235

	
236
  private:
237

	
238
    const Graph &_graph;
239
    const CapacityMap *_capacity;
240
    bool _local_capacity; // unit capacity
241

	
242
    struct ArcData {
243
      typename Graph::Node target;
244
      int prev, next;
245
    };
246
    struct EdgeData {
247
      Value capacity;
248
      Value cut;
249
    };
250

	
251
    struct NodeData {
252
      int first_arc;
253
      typename Graph::Node prev, next;
254
      int curr_arc;
255
      typename Graph::Node last_rep;
256
      Value sum;
257
    };
258

	
259
    typename Graph::template NodeMap<NodeData> *_nodes;
260
    std::vector<ArcData> _arcs;
261
    std::vector<EdgeData> _edges;
262

	
263
    typename Graph::Node _first_node;
264
    int _node_num;
265

	
266
    Value _min_cut;
267

	
268
    HeapCrossRef *_heap_cross_ref;
269
    bool _local_heap_cross_ref;
270
    Heap *_heap;
271
    bool _local_heap;
272

	
273
    typedef typename Graph::template NodeMap<typename Graph::Node> NodeList;
274
    NodeList *_next_rep;
275

	
276
    typedef typename Graph::template NodeMap<bool> MinCutMap;
277
    MinCutMap *_cut_map;
278

	
279
    void createStructures() {
280
      if (!_nodes) {
281
        _nodes = new (typename Graph::template NodeMap<NodeData>)(_graph);
282
      }
283
      if (!_capacity) {
284
        _local_capacity = true;
285
        _capacity = Traits::createCapacityMap(_graph);
286
      }
287
      if (!_heap_cross_ref) {
288
        _local_heap_cross_ref = true;
289
        _heap_cross_ref = Traits::createHeapCrossRef(_graph);
290
      }
291
      if (!_heap) {
292
        _local_heap = true;
293
        _heap = Traits::createHeap(*_heap_cross_ref);
294
      }
295
      if (!_next_rep) {
296
        _next_rep = new NodeList(_graph);
297
      }
298
      if (!_cut_map) {
299
        _cut_map = new MinCutMap(_graph);
300
      }
301
    }
302

	
303
  public :
304

	
305
    typedef NagamochiIbaraki Create;
306

	
307

	
308
    /// \brief Constructor.
309
    ///
310
    /// \param graph The graph the algorithm runs on.
311
    /// \param capacity The capacity map used by the algorithm.
312
    NagamochiIbaraki(const Graph& graph, const CapacityMap& capacity)
313
      : _graph(graph), _capacity(&capacity), _local_capacity(false),
314
        _nodes(0), _arcs(), _edges(), _min_cut(),
315
        _heap_cross_ref(0), _local_heap_cross_ref(false),
316
        _heap(0), _local_heap(false),
317
        _next_rep(0), _cut_map(0) {}
318

	
319
    /// \brief Constructor.
320
    ///
321
    /// This constructor can be used only when the Traits class
322
    /// defines how can the local capacity map be instantiated.
323
    /// If the SetUnitCapacity used the algorithm automatically
324
    /// constructs the capacity map.
325
    ///
326
    ///\param graph The graph the algorithm runs on.
327
    NagamochiIbaraki(const Graph& graph)
328
      : _graph(graph), _capacity(0), _local_capacity(false),
329
        _nodes(0), _arcs(), _edges(), _min_cut(),
330
        _heap_cross_ref(0), _local_heap_cross_ref(false),
331
        _heap(0), _local_heap(false),
332
        _next_rep(0), _cut_map(0) {}
333

	
334
    /// \brief Destructor.
335
    ///
336
    /// Destructor.
337
    ~NagamochiIbaraki() {
338
      if (_local_capacity) delete _capacity;
339
      if (_nodes) delete _nodes;
340
      if (_local_heap) delete _heap;
341
      if (_local_heap_cross_ref) delete _heap_cross_ref;
342
      if (_next_rep) delete _next_rep;
343
      if (_cut_map) delete _cut_map;
344
    }
345

	
346
    /// \brief Sets the heap and the cross reference used by algorithm.
347
    ///
348
    /// Sets the heap and the cross reference used by algorithm.
349
    /// If you don't use this function before calling \ref run(),
350
    /// it will allocate one. The destuctor deallocates this
351
    /// automatically allocated heap and cross reference, of course.
352
    /// \return <tt> (*this) </tt>
353
    NagamochiIbaraki &heap(Heap& hp, HeapCrossRef &cr)
354
    {
355
      if (_local_heap_cross_ref) {
356
        delete _heap_cross_ref;
357
        _local_heap_cross_ref = false;
358
      }
359
      _heap_cross_ref = &cr;
360
      if (_local_heap) {
361
        delete _heap;
362
        _local_heap = false;
363
      }
364
      _heap = &hp;
365
      return *this;
366
    }
367

	
368
    /// \name Execution control
369
    /// The simplest way to execute the algorithm is to use
370
    /// one of the member functions called \c run().
371
    /// \n
372
    /// If you need more control on the execution,
373
    /// first you must call \ref init() and then call the start()
374
    /// or proper times the processNextPhase() member functions.
375

	
376
    ///@{
377

	
378
    /// \brief Initializes the internal data structures.
379
    ///
380
    /// Initializes the internal data structures.
381
    void init() {
382
      createStructures();
383

	
384
      int edge_num = countEdges(_graph);
385
      _edges.resize(edge_num);
386
      _arcs.resize(2 * edge_num);
387

	
388
      typename Graph::Node prev = INVALID;
389
      _node_num = 0;
390
      for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
391
        (*_cut_map)[n] = false;
392
        (*_next_rep)[n] = INVALID;
393
        (*_nodes)[n].last_rep = n;
394
        (*_nodes)[n].first_arc = -1;
395
        (*_nodes)[n].curr_arc = -1;
396
        (*_nodes)[n].prev = prev;
397
        if (prev != INVALID) {
398
          (*_nodes)[prev].next = n;
399
        }
400
        (*_nodes)[n].next = INVALID;
401
        (*_nodes)[n].sum = 0;
402
        prev = n;
403
        ++_node_num;
404
      }
405

	
406
      _first_node = typename Graph::NodeIt(_graph);
407

	
408
      int index = 0;
409
      for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
410
        for (typename Graph::OutArcIt a(_graph, n); a != INVALID; ++a) {
411
          typename Graph::Node m = _graph.target(a);
412
          
413
          if (!(n < m)) continue;
414

	
415
          (*_nodes)[n].sum += (*_capacity)[a];
416
          (*_nodes)[m].sum += (*_capacity)[a];
417
          
418
          int c = (*_nodes)[m].curr_arc;
419
          if (c != -1 && _arcs[c ^ 1].target == n) {
420
            _edges[c >> 1].capacity += (*_capacity)[a];
421
          } else {
422
            _edges[index].capacity = (*_capacity)[a];
423
            
424
            _arcs[index << 1].prev = -1;
425
            if ((*_nodes)[n].first_arc != -1) {
426
              _arcs[(*_nodes)[n].first_arc].prev = (index << 1);
427
            }
428
            _arcs[index << 1].next = (*_nodes)[n].first_arc;
429
            (*_nodes)[n].first_arc = (index << 1);
430
            _arcs[index << 1].target = m;
431

	
432
            (*_nodes)[m].curr_arc = (index << 1);
433
            
434
            _arcs[(index << 1) | 1].prev = -1;
435
            if ((*_nodes)[m].first_arc != -1) {
436
              _arcs[(*_nodes)[m].first_arc].prev = ((index << 1) | 1);
437
            }
438
            _arcs[(index << 1) | 1].next = (*_nodes)[m].first_arc;
439
            (*_nodes)[m].first_arc = ((index << 1) | 1);
440
            _arcs[(index << 1) | 1].target = n;
441
            
442
            ++index;
443
          }
444
        }
445
      }
446

	
447
      typename Graph::Node cut_node = INVALID;
448
      _min_cut = std::numeric_limits<Value>::max();
449

	
450
      for (typename Graph::Node n = _first_node; 
451
           n != INVALID; n = (*_nodes)[n].next) {
452
        if ((*_nodes)[n].sum < _min_cut) {
453
          cut_node = n;
454
          _min_cut = (*_nodes)[n].sum;
455
        }
456
      }
457
      (*_cut_map)[cut_node] = true;
458
      if (_min_cut == 0) {
459
        _first_node = INVALID;
460
      }
461
    }
462

	
463
  public:
464

	
465
    /// \brief Processes the next phase
466
    ///
467
    /// Processes the next phase in the algorithm. It must be called
468
    /// at most one less the number of the nodes in the graph.
469
    ///
470
    ///\return %True when the algorithm finished.
471
    bool processNextPhase() {
472
      if (_first_node == INVALID) return true;
473

	
474
      _heap->clear();
475
      for (typename Graph::Node n = _first_node; 
476
           n != INVALID; n = (*_nodes)[n].next) {
477
        (*_heap_cross_ref)[n] = Heap::PRE_HEAP;
478
      }
479

	
480
      std::vector<typename Graph::Node> order;
481
      order.reserve(_node_num);
482
      int sep = 0;
483

	
484
      Value alpha = 0;
485
      Value pmc = std::numeric_limits<Value>::max();
486

	
487
      _heap->push(_first_node, static_cast<Value>(0));
488
      while (!_heap->empty()) {
489
        typename Graph::Node n = _heap->top();
490
        Value v = _heap->prio();
491

	
492
        _heap->pop();
493
        for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
494
          switch (_heap->state(_arcs[a].target)) {
495
          case Heap::PRE_HEAP: 
496
            {
497
              Value nv = _edges[a >> 1].capacity;
498
              _heap->push(_arcs[a].target, nv);
499
              _edges[a >> 1].cut = nv;
500
            } break;
501
          case Heap::IN_HEAP:
502
            {
503
              Value nv = _edges[a >> 1].capacity + (*_heap)[_arcs[a].target];
504
              _heap->decrease(_arcs[a].target, nv);
505
              _edges[a >> 1].cut = nv;
506
            } break;
507
          case Heap::POST_HEAP:
508
            break;
509
          }
510
        }
511

	
512
        alpha += (*_nodes)[n].sum;
513
        alpha -= 2 * v;
514

	
515
        order.push_back(n);
516
        if (!_heap->empty()) {
517
          if (alpha < pmc) {
518
            pmc = alpha;
519
            sep = order.size();
520
          }
521
        }
522
      }
523

	
524
      if (static_cast<int>(order.size()) < _node_num) {
525
        _first_node = INVALID;
526
        for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
527
          (*_cut_map)[n] = false;
528
        }
529
        for (int i = 0; i < static_cast<int>(order.size()); ++i) {
530
          typename Graph::Node n = order[i];
531
          while (n != INVALID) {
532
            (*_cut_map)[n] = true;
533
            n = (*_next_rep)[n];
534
          }
535
        }
536
        _min_cut = 0;
537
        return true;
538
      }
539

	
540
      if (pmc < _min_cut) {
541
        for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
542
          (*_cut_map)[n] = false;
543
        }
544
        for (int i = 0; i < sep; ++i) {
545
          typename Graph::Node n = order[i];
546
          while (n != INVALID) {
547
            (*_cut_map)[n] = true;
548
            n = (*_next_rep)[n];
549
          }
550
        }
551
        _min_cut = pmc;
552
      }
553

	
554
      for (typename Graph::Node n = _first_node;
555
           n != INVALID; n = (*_nodes)[n].next) {
556
        bool merged = false;
557
        for (int a = (*_nodes)[n].first_arc; a != -1; a = _arcs[a].next) {
558
          if (!(_edges[a >> 1].cut < pmc)) {
559
            if (!merged) {
560
              for (int b = (*_nodes)[n].first_arc; b != -1; b = _arcs[b].next) {
561
                (*_nodes)[_arcs[b].target].curr_arc = b;          
562
              }
563
              merged = true;
564
            }
565
            typename Graph::Node m = _arcs[a].target;
566
            int nb = 0;
567
            for (int b = (*_nodes)[m].first_arc; b != -1; b = nb) {
568
              nb = _arcs[b].next;
569
              if ((b ^ a) == 1) continue;
570
              typename Graph::Node o = _arcs[b].target;
571
              int c = (*_nodes)[o].curr_arc; 
572
              if (c != -1 && _arcs[c ^ 1].target == n) {
573
                _edges[c >> 1].capacity += _edges[b >> 1].capacity;
574
                (*_nodes)[n].sum += _edges[b >> 1].capacity;
575
                if (_edges[b >> 1].cut < _edges[c >> 1].cut) {
576
                  _edges[b >> 1].cut = _edges[c >> 1].cut;
577
                }
578
                if (_arcs[b ^ 1].prev != -1) {
579
                  _arcs[_arcs[b ^ 1].prev].next = _arcs[b ^ 1].next;
580
                } else {
581
                  (*_nodes)[o].first_arc = _arcs[b ^ 1].next;
582
                }
583
                if (_arcs[b ^ 1].next != -1) {
584
                  _arcs[_arcs[b ^ 1].next].prev = _arcs[b ^ 1].prev;
585
                }
586
              } else {
587
                if (_arcs[a].next != -1) {
588
                  _arcs[_arcs[a].next].prev = b;
589
                }
590
                _arcs[b].next = _arcs[a].next;
591
                _arcs[b].prev = a;
592
                _arcs[a].next = b;
593
                _arcs[b ^ 1].target = n;
594

	
595
                (*_nodes)[n].sum += _edges[b >> 1].capacity;
596
                (*_nodes)[o].curr_arc = b;
597
              }
598
            }
599

	
600
            if (_arcs[a].prev != -1) {
601
              _arcs[_arcs[a].prev].next = _arcs[a].next;
602
            } else {
603
              (*_nodes)[n].first_arc = _arcs[a].next;
604
            }            
605
            if (_arcs[a].next != -1) {
606
              _arcs[_arcs[a].next].prev = _arcs[a].prev;
607
            }
608

	
609
            (*_nodes)[n].sum -= _edges[a >> 1].capacity;
610
            (*_next_rep)[(*_nodes)[n].last_rep] = m;
611
            (*_nodes)[n].last_rep = (*_nodes)[m].last_rep;
612
            
613
            if ((*_nodes)[m].prev != INVALID) {
614
              (*_nodes)[(*_nodes)[m].prev].next = (*_nodes)[m].next;
615
            } else{
616
              _first_node = (*_nodes)[m].next;
617
            }
618
            if ((*_nodes)[m].next != INVALID) {
619
              (*_nodes)[(*_nodes)[m].next].prev = (*_nodes)[m].prev;
620
            }
621
            --_node_num;
622
          }
623
        }
624
      }
625

	
626
      if (_node_num == 1) {
627
        _first_node = INVALID;
628
        return true;
629
      }
630

	
631
      return false;
632
    }
633

	
634
    /// \brief Executes the algorithm.
635
    ///
636
    /// Executes the algorithm.
637
    ///
638
    /// \pre init() must be called
639
    void start() {
640
      while (!processNextPhase()) {}
641
    }
642

	
643

	
644
    /// \brief Runs %NagamochiIbaraki algorithm.
645
    ///
646
    /// This method runs the %Min cut algorithm
647
    ///
648
    /// \note mc.run(s) is just a shortcut of the following code.
649
    ///\code
650
    ///  mc.init();
651
    ///  mc.start();
652
    ///\endcode
653
    void run() {
654
      init();
655
      start();
656
    }
657

	
658
    ///@}
659

	
660
    /// \name Query Functions
661
    ///
662
    /// The result of the %NagamochiIbaraki
663
    /// algorithm can be obtained using these functions.\n
664
    /// Before the use of these functions, either run() or start()
665
    /// must be called.
666

	
667
    ///@{
668

	
669
    /// \brief Returns the min cut value.
670
    ///
671
    /// Returns the min cut value if the algorithm finished.
672
    /// After the first processNextPhase() it is a value of a
673
    /// valid cut in the graph.
674
    Value minCutValue() const {
675
      return _min_cut;
676
    }
677

	
678
    /// \brief Returns a min cut in a NodeMap.
679
    ///
680
    /// It sets the nodes of one of the two partitions to true and
681
    /// the other partition to false.
682
    /// \param cutMap A \ref concepts::WriteMap "writable" node map with
683
    /// \c bool (or convertible) value type.
684
    template <typename CutMap>
685
    Value minCutMap(CutMap& cutMap) const {
686
      for (typename Graph::NodeIt n(_graph); n != INVALID; ++n) {
687
        cutMap.set(n, (*_cut_map)[n]);
688
      }
689
      return minCutValue();
690
    }
691

	
692
    ///@}
693

	
694
  };
695
}
696

	
697
#endif
Ignore white space 3221225472 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

	
21
#include <lemon/smart_graph.h>
22
#include <lemon/adaptors.h>
23
#include <lemon/concepts/graph.h>
24
#include <lemon/concepts/maps.h>
25
#include <lemon/lgf_reader.h>
26
#include <lemon/nagamochi_ibaraki.h>
27

	
28
#include "test_tools.h"
29

	
30
using namespace lemon;
31
using namespace std;
32

	
33
const std::string lgf =
34
  "@nodes\n"
35
  "label\n"
36
  "0\n"
37
  "1\n"
38
  "2\n"
39
  "3\n"
40
  "4\n"
41
  "5\n"
42
  "@edges\n"
43
  "     cap1 cap2 cap3\n"
44
  "0 1  1    1    1   \n"
45
  "0 2  2    2    4   \n"
46
  "1 2  4    4    4   \n"
47
  "3 4  1    1    1   \n"
48
  "3 5  2    2    4   \n"
49
  "4 5  4    4    4   \n"
50
  "2 3  1    6    6   \n";
51

	
52
void checkNagamochiIbarakiCompile()
53
{
54
  typedef int Value;
55
  typedef concepts::Graph Graph;
56

	
57
  typedef Graph::Node Node;
58
  typedef Graph::Edge Edge;
59
  typedef concepts::ReadMap<Edge, Value> CapMap;
60
  typedef concepts::WriteMap<Node, bool> CutMap;
61

	
62
  Graph g;
63
  Node n;
64
  CapMap cap;
65
  CutMap cut;
66
  Value v;
67
  bool b;
68

	
69
  NagamochiIbaraki<Graph, CapMap> ni_test(g, cap);
70
  const NagamochiIbaraki<Graph, CapMap>& const_ni_test = ni_test;
71

	
72
  ni_test.init();
73
  ni_test.start();
74
  b = ni_test.processNextPhase();
75
  ni_test.run();
76

	
77
  v = const_ni_test.minCutValue();
78
  v = const_ni_test.minCutMap(cut);
79
}
80

	
81
template <typename Graph, typename CapMap, typename CutMap>
82
typename CapMap::Value
83
  cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
84
{
85
  typename CapMap::Value sum = 0;
86
  for (typename Graph::EdgeIt e(graph); e != INVALID; ++e) {
87
    if (cut[graph.u(e)] != cut[graph.v(e)]) {
88
      sum += cap[e];
89
    }
90
  }
91
  return sum;
92
}
93

	
94
int main() {
95
  SmartGraph graph;
96
  SmartGraph::EdgeMap<int> cap1(graph), cap2(graph), cap3(graph);
97
  SmartGraph::NodeMap<bool> cut(graph);
98

	
99
  istringstream input(lgf);
100
  graphReader(graph, input)
101
    .edgeMap("cap1", cap1)
102
    .edgeMap("cap2", cap2)
103
    .edgeMap("cap3", cap3)
104
    .run();
105

	
106
  {
107
    NagamochiIbaraki<SmartGraph> ni(graph, cap1);
108
    ni.run();
109
    ni.minCutMap(cut);
110

	
111
    check(ni.minCutValue() == 1, "Wrong cut value");
112
    check(ni.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
113
  }
114
  {
115
    NagamochiIbaraki<SmartGraph> ni(graph, cap2);
116
    ni.run();
117
    ni.minCutMap(cut);
118

	
119
    check(ni.minCutValue() == 3, "Wrong cut value");
120
    check(ni.minCutValue() == cutValue(graph, cap2, cut), "Wrong cut value");
121
  }
122
  {
123
    NagamochiIbaraki<SmartGraph> ni(graph, cap3);
124
    ni.run();
125
    ni.minCutMap(cut);
126

	
127
    check(ni.minCutValue() == 5, "Wrong cut value");
128
    check(ni.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
129
  }
130
  {
131
    NagamochiIbaraki<SmartGraph>::SetUnitCapacity::Create ni(graph);
132
    ni.run();
133
    ni.minCutMap(cut);
134

	
135
    ConstMap<SmartGraph::Edge, int> cap4(1);
136
    check(ni.minCutValue() == 1, "Wrong cut value");
137
    check(ni.minCutValue() == cutValue(graph, cap4, cut), "Wrong cut value");
138
  }
139

	
140
  return 0;
141
}
Ignore white space 3221225472 line context
1 1
CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
2 2

	
3 3
SET(PROJECT_NAME "LEMON")
4 4
PROJECT(${PROJECT_NAME})
5 5

	
6 6
INCLUDE(FindPythonInterp)
7
INCLUDE(FindWget)
7 8

	
8 9
IF(EXISTS ${PROJECT_SOURCE_DIR}/cmake/version.cmake)
9 10
  INCLUDE(${PROJECT_SOURCE_DIR}/cmake/version.cmake)
10 11
ELSEIF(DEFINED ENV{LEMON_VERSION})
11 12
  SET(LEMON_VERSION $ENV{LEMON_VERSION} CACHE STRING "LEMON version string.")
12 13
ELSE()
13 14
  EXECUTE_PROCESS(
14 15
    COMMAND ${PYTHON_EXECUTABLE} ./scripts/chg-len.py
15 16
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
16 17
    OUTPUT_VARIABLE HG_REVISION_PATH
17 18
    ERROR_QUIET
18 19
    OUTPUT_STRIP_TRAILING_WHITESPACE
19 20
  )
20 21
  EXECUTE_PROCESS(
21 22
    COMMAND hg id -i
22 23
    WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
23 24
    OUTPUT_VARIABLE HG_REVISION
24 25
    ERROR_QUIET
25 26
    OUTPUT_STRIP_TRAILING_WHITESPACE
26 27
  )
27 28
  IF(HG_REVISION STREQUAL "")
28 29
    SET(HG_REVISION_ID "hg-tip")
29 30
  ELSE()
30 31
    IF(HG_REVISION_PATH STREQUAL "")
31 32
      SET(HG_REVISION_ID ${HG_REVISION})
32 33
    ELSE()
33 34
      SET(HG_REVISION_ID ${HG_REVISION_PATH}.${HG_REVISION})
34 35
    ENDIF()
35 36
  ENDIF()
36 37
  SET(LEMON_VERSION ${HG_REVISION_ID} CACHE STRING "LEMON version string.")
37 38
ENDIF()
38 39

	
39 40
SET(PROJECT_VERSION ${LEMON_VERSION})
40 41

	
41 42
SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
42 43

	
43 44
FIND_PACKAGE(Doxygen)
44 45
FIND_PACKAGE(Ghostscript)
45 46
FIND_PACKAGE(GLPK 4.33)
46 47
FIND_PACKAGE(CPLEX)
47 48
FIND_PACKAGE(COIN)
48 49

	
49 50
IF(DEFINED ENV{LEMON_CXX_WARNING})
50 51
  SET(CXX_WARNING $ENV{LEMON_CXX_WARNING})
51 52
ELSE()
52 53
  IF(CMAKE_COMPILER_IS_GNUCXX)
53 54
    SET(CXX_WARNING "-Wall -W -Wunused -Wformat=2 -Wctor-dtor-privacy -Wnon-virtual-dtor -Wno-char-subscripts -Wwrite-strings -Wno-char-subscripts -Wreturn-type -Wcast-qual -Wcast-align -Wsign-promo -Woverloaded-virtual -ansi -fno-strict-aliasing -Wold-style-cast -Wno-unknown-pragmas")
54 55
    SET(CMAKE_CXX_FLAGS_DEBUG CACHE STRING "-ggdb")
55 56
    SET(CMAKE_C_FLAGS_DEBUG CACHE STRING "-ggdb")
56 57
  ELSEIF(MSVC)
57 58
    # This part is unnecessary 'casue the same is set by the lemon/core.h.
58 59
    # Still keep it as an example.
59 60
    SET(CXX_WARNING "/wd4250 /wd4355 /wd4503 /wd4800 /wd4996")
60 61
    # Suppressed warnings:
61 62
    # C4250: 'class1' : inherits 'class2::member' via dominance
62 63
    # C4355: 'this' : used in base member initializer list
63 64
    # C4503: 'function' : decorated name length exceeded, name was truncated
64 65
    # C4800: 'type' : forcing value to bool 'true' or 'false'
65 66
    #        (performance warning)
66 67
    # C4996: 'function': was declared deprecated
67 68
  ELSE()
68 69
    SET(CXX_WARNING "-Wall -W")
69 70
  ENDIF()
70 71
ENDIF()
71 72
SET(LEMON_CXX_WARNING_FLAGS ${CXX_WARNING} CACHE STRING "LEMON warning flags.")
72 73

	
73 74
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${LEMON_CXX_WARNING_FLAGS}")
74 75

	
75 76
SET( CMAKE_CXX_FLAGS_MAINTAINER "-Werror -ggdb" CACHE STRING
76 77
    "Flags used by the C++ compiler during maintainer builds."
77 78
    FORCE )
78 79
SET( CMAKE_C_FLAGS_MAINTAINER "-Werror" CACHE STRING
79 80
    "Flags used by the C compiler during maintainer builds."
80 81
    FORCE )
81 82
SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER
82 83
    "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING
83 84
    "Flags used for linking binaries during maintainer builds."
84 85
    FORCE )
85 86
SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER
86 87
    "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING
87 88
    "Flags used by the shared libraries linker during maintainer builds."
88 89
    FORCE )
89 90
MARK_AS_ADVANCED(
90 91
    CMAKE_CXX_FLAGS_MAINTAINER
91 92
    CMAKE_C_FLAGS_MAINTAINER
92 93
    CMAKE_EXE_LINKER_FLAGS_MAINTAINER
93 94
    CMAKE_SHARED_LINKER_FLAGS_MAINTAINER )
94 95

	
95 96
IF(CMAKE_CONFIGURATION_TYPES)
96 97
  LIST(APPEND CMAKE_CONFIGURATION_TYPES Maintainer)
97 98
  LIST(REMOVE_DUPLICATES CMAKE_CONFIGURATION_TYPES)
98 99
  SET(CMAKE_CONFIGURATION_TYPES "${CMAKE_CONFIGURATION_TYPES}" CACHE STRING
99 100
      "Add the configurations that we need"
100 101
      FORCE)
101 102
 endif()
102 103

	
103 104
IF(NOT CMAKE_BUILD_TYPE)
104 105
  SET(CMAKE_BUILD_TYPE "Release")
105 106
ENDIF()
106 107

	
107 108
SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING
108 109
    "Choose the type of build, options are: None(CMAKE_CXX_FLAGS or CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel Maintainer."
109 110
    FORCE )
110 111

	
111 112

	
112 113
INCLUDE(CheckTypeSize)
113 114
CHECK_TYPE_SIZE("long long" LONG_LONG)
114 115
SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
115 116

	
116 117
ENABLE_TESTING()
117 118

	
118 119
IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
119 120
  ADD_CUSTOM_TARGET(check ALL COMMAND ${CMAKE_CTEST_COMMAND})
120 121
ELSE()
121 122
  ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND})
122 123
ENDIF()
123 124

	
124 125
ADD_SUBDIRECTORY(lemon)
125 126
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
126 127
  ADD_SUBDIRECTORY(demo)
127 128
  ADD_SUBDIRECTORY(tools)
128 129
  ADD_SUBDIRECTORY(doc)
129 130
  ADD_SUBDIRECTORY(test)
130 131
ENDIF()
131 132

	
132 133
CONFIGURE_FILE(
133 134
  ${PROJECT_SOURCE_DIR}/cmake/LEMONConfig.cmake.in
134 135
  ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
135 136
  @ONLY
136 137
)
137 138
IF(UNIX)
138 139
  INSTALL(
139 140
    FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
140 141
    DESTINATION share/lemon/cmake
141 142
  )
142 143
ELSEIF(WIN32)
143 144
  INSTALL(
144 145
    FILES ${PROJECT_BINARY_DIR}/cmake/LEMONConfig.cmake
145 146
    DESTINATION cmake
146 147
  )
147 148
ENDIF()
148 149

	
149 150
IF(${CMAKE_SOURCE_DIR} STREQUAL ${PROJECT_SOURCE_DIR})
150 151
  SET(CPACK_PACKAGE_NAME ${PROJECT_NAME})
151 152
  SET(CPACK_PACKAGE_VENDOR "EGRES")
152 153
  SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY
153 154
    "LEMON - Library for Efficient Modeling and Optimization in Networks")
154 155
  SET(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE")
155 156

	
156 157
  SET(CPACK_PACKAGE_VERSION ${PROJECT_VERSION})
157 158

	
158 159
  SET(CPACK_PACKAGE_INSTALL_DIRECTORY
159 160
    "${PROJECT_NAME} ${PROJECT_VERSION}")
160 161
  SET(CPACK_PACKAGE_INSTALL_REGISTRY_KEY
161 162
    "${PROJECT_NAME} ${PROJECT_VERSION}")
162 163

	
163 164
  SET(CPACK_COMPONENTS_ALL headers library html_documentation bin)
164 165

	
165 166
  SET(CPACK_COMPONENT_HEADERS_DISPLAY_NAME "C++ headers")
166 167
  SET(CPACK_COMPONENT_LIBRARY_DISPLAY_NAME "Dynamic-link library")
167 168
  SET(CPACK_COMPONENT_BIN_DISPLAY_NAME "Command line utilities")
168 169
  SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DISPLAY_NAME "HTML documentation")
169 170

	
170 171
  SET(CPACK_COMPONENT_HEADERS_DESCRIPTION
171 172
    "C++ header files")
172 173
  SET(CPACK_COMPONENT_LIBRARY_DESCRIPTION
173 174
    "DLL and import library")
174 175
  SET(CPACK_COMPONENT_BIN_DESCRIPTION
175 176
    "Command line utilities")
176 177
  SET(CPACK_COMPONENT_HTML_DOCUMENTATION_DESCRIPTION
177 178
    "Doxygen generated documentation")
178 179

	
179 180
  SET(CPACK_COMPONENT_HEADERS_DEPENDS library)
180 181

	
181 182
  SET(CPACK_COMPONENT_HEADERS_GROUP "Development")
182 183
  SET(CPACK_COMPONENT_LIBRARY_GROUP "Development")
183 184
  SET(CPACK_COMPONENT_HTML_DOCUMENTATION_GROUP "Documentation")
184 185

	
185 186
  SET(CPACK_COMPONENT_GROUP_DEVELOPMENT_DESCRIPTION
186 187
    "Components needed to develop software using LEMON")
187 188
  SET(CPACK_COMPONENT_GROUP_DOCUMENTATION_DESCRIPTION
188 189
    "Documentation of LEMON")
189 190

	
190 191
  SET(CPACK_ALL_INSTALL_TYPES Full Developer)
191 192

	
192 193
  SET(CPACK_COMPONENT_HEADERS_INSTALL_TYPES Developer Full)
193 194
  SET(CPACK_COMPONENT_LIBRARY_INSTALL_TYPES Developer Full)
194 195
  SET(CPACK_COMPONENT_HTML_DOCUMENTATION_INSTALL_TYPES Full)
195 196

	
196 197
  SET(CPACK_GENERATOR "NSIS")
197 198
  SET(CPACK_NSIS_MUI_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis/lemon.ico")
198 199
  SET(CPACK_NSIS_MUI_UNIICON "${PROJECT_SOURCE_DIR}/cmake/nsis/uninstall.ico")
199 200
  #SET(CPACK_PACKAGE_ICON "${PROJECT_SOURCE_DIR}/cmake/nsis\\\\installer.bmp")
200 201
  SET(CPACK_NSIS_INSTALLED_ICON_NAME "bin\\\\lemon.ico")
201 202
  SET(CPACK_NSIS_DISPLAY_NAME "${CPACK_PACKAGE_INSTALL_DIRECTORY} ${PROJECT_NAME}")
202 203
  SET(CPACK_NSIS_HELP_LINK "http:\\\\\\\\lemon.cs.elte.hu")
203 204
  SET(CPACK_NSIS_URL_INFO_ABOUT "http:\\\\\\\\lemon.cs.elte.hu")
204 205
  SET(CPACK_NSIS_CONTACT "lemon-user@lemon.cs.elte.hu")
205 206
  SET(CPACK_NSIS_CREATE_ICONS_EXTRA "
206 207
    CreateShortCut \\\"$SMPROGRAMS\\\\$STARTMENU_FOLDER\\\\Documentation.lnk\\\" \\\"$INSTDIR\\\\share\\\\doc\\\\index.html\\\"
207 208
    ")
208 209
  SET(CPACK_NSIS_DELETE_ICONS_EXTRA "
209 210
    !insertmacro MUI_STARTMENU_GETFOLDER Application $MUI_TEMP
210 211
    Delete \\\"$SMPROGRAMS\\\\$MUI_TEMP\\\\Documentation.lnk\\\"
211 212
    ")
212 213

	
213 214
  INCLUDE(CPack)
214 215
ENDIF()
Ignore white space 3221225472 line context
1 1
SET(PACKAGE_NAME ${PROJECT_NAME})
2 2
SET(PACKAGE_VERSION ${PROJECT_VERSION})
3 3
SET(abs_top_srcdir ${PROJECT_SOURCE_DIR})
4 4
SET(abs_top_builddir ${PROJECT_BINARY_DIR})
5 5

	
6
SET(LEMON_DOC_SOURCE_BROWSER "NO" CACHE STRING "Include source into the doc (YES/NO).")
7

	
6 8
CONFIGURE_FILE(
7 9
  ${PROJECT_SOURCE_DIR}/doc/Doxyfile.in
8 10
  ${PROJECT_BINARY_DIR}/doc/Doxyfile
9 11
  @ONLY
10 12
)
11 13

	
12 14
IF(DOXYGEN_EXECUTABLE AND PYTHONINTERP_FOUND AND GHOSTSCRIPT_EXECUTABLE)
13 15
  FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/)
14 16
  SET(GHOSTSCRIPT_OPTIONS -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=pngalpha)
15 17
  ADD_CUSTOM_TARGET(html
16 18
    COMMAND ${CMAKE_COMMAND} -E remove_directory gen-images
17 19
    COMMAND ${CMAKE_COMMAND} -E make_directory gen-images
18 20
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/bipartite_matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_matching.eps
19 21
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/bipartite_partitions.png ${CMAKE_CURRENT_SOURCE_DIR}/images/bipartite_partitions.eps
20 22
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/connected_components.eps
21 23
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/edge_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/edge_biconnected_components.eps
22 24
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/grid_graph.png ${CMAKE_CURRENT_SOURCE_DIR}/images/grid_graph.eps
23 25
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/matching.eps
24 26
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/node_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/node_biconnected_components.eps
25 27
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_0.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_0.eps
26 28
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_1.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_1.eps
27 29
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_2.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_2.eps
28 30
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
29 31
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
30 32
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/planar.png ${CMAKE_CURRENT_SOURCE_DIR}/images/planar.eps
31 33
    COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/strongly_connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/strongly_connected_components.eps
32 34
    COMMAND ${CMAKE_COMMAND} -E remove_directory html
33 35
    COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox
34 36
    COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
35 37
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
36 38
  )
37 39

	
38 40
  SET_TARGET_PROPERTIES(html PROPERTIES PROJECT_LABEL BUILD_DOC)
39 41

	
40 42
  IF(UNIX)
41 43
    INSTALL(
42 44
      DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
43 45
      DESTINATION share/doc/lemon/html
44 46
      COMPONENT html_documentation
45 47
    )
46 48
  ELSEIF(WIN32)
47 49
    INSTALL(
48 50
      DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/
49 51
      DESTINATION doc
50 52
      COMPONENT html_documentation
51 53
    )
52 54
  ENDIF()
53 55

	
54 56
ENDIF()
57

	
58
IF(WGET_FOUND)
59
ADD_CUSTOM_TARGET(update-external-tags
60
  COMMAND ${CMAKE_COMMAND} -E make_directory dl
61
  # COMMAND ${CMAKE_COMMAND} -E copy libstdc++.tag dl
62
  COMMAND ${WGET_EXECUTABLE} wget -P dl -N libstdc++.tag.tmp http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/libstdc++.tag
63
  COMMAND ${CMAKE_COMMAND} -E rename dl/libstdc++.tag libstdc++.tag
64
  COMMAND ${CMAKE_COMMAND} -E remove dl/libstdc++.tag
65
  COMMAND ${CMAKE_COMMAND} -E remove_directory dl
66
  WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
67
  )
68
ENDIF()
Ignore white space 3221225472 line context
1 1
# Doxyfile 1.5.9
2 2

	
3 3
#---------------------------------------------------------------------------
4 4
# Project related configuration options
5 5
#---------------------------------------------------------------------------
6 6
DOXYFILE_ENCODING      = UTF-8
7 7
PROJECT_NAME           = @PACKAGE_NAME@
8 8
PROJECT_NUMBER         = @PACKAGE_VERSION@
9 9
OUTPUT_DIRECTORY       = 
10 10
CREATE_SUBDIRS         = NO
11 11
OUTPUT_LANGUAGE        = English
12 12
BRIEF_MEMBER_DESC      = YES
13 13
REPEAT_BRIEF           = NO
14 14
ABBREVIATE_BRIEF       = 
15 15
ALWAYS_DETAILED_SEC    = NO
16 16
INLINE_INHERITED_MEMB  = NO
17 17
FULL_PATH_NAMES        = YES
18 18
STRIP_FROM_PATH        = "@abs_top_srcdir@"
19 19
STRIP_FROM_INC_PATH    = "@abs_top_srcdir@"
20 20
SHORT_NAMES            = YES
21 21
JAVADOC_AUTOBRIEF      = NO
22 22
QT_AUTOBRIEF           = NO
23 23
MULTILINE_CPP_IS_BRIEF = NO
24 24
INHERIT_DOCS           = NO
25 25
SEPARATE_MEMBER_PAGES  = NO
26 26
TAB_SIZE               = 8
27 27
ALIASES                = 
28 28
OPTIMIZE_OUTPUT_FOR_C  = NO
29 29
OPTIMIZE_OUTPUT_JAVA   = NO
30 30
OPTIMIZE_FOR_FORTRAN   = NO
31 31
OPTIMIZE_OUTPUT_VHDL   = NO
32 32
BUILTIN_STL_SUPPORT    = YES
33 33
CPP_CLI_SUPPORT        = NO
34 34
SIP_SUPPORT            = NO
35 35
IDL_PROPERTY_SUPPORT   = YES
36 36
DISTRIBUTE_GROUP_DOC   = NO
37 37
SUBGROUPING            = YES
38 38
TYPEDEF_HIDES_STRUCT   = NO
39 39
SYMBOL_CACHE_SIZE      = 0
40 40
#---------------------------------------------------------------------------
41 41
# Build related configuration options
42 42
#---------------------------------------------------------------------------
43 43
EXTRACT_ALL            = NO
44 44
EXTRACT_PRIVATE        = YES
45 45
EXTRACT_STATIC         = YES
46 46
EXTRACT_LOCAL_CLASSES  = NO
47 47
EXTRACT_LOCAL_METHODS  = NO
48 48
EXTRACT_ANON_NSPACES   = NO
49 49
HIDE_UNDOC_MEMBERS     = YES
50 50
HIDE_UNDOC_CLASSES     = YES
51 51
HIDE_FRIEND_COMPOUNDS  = NO
52 52
HIDE_IN_BODY_DOCS      = NO
53 53
INTERNAL_DOCS          = NO
54 54
CASE_SENSE_NAMES       = YES
55 55
HIDE_SCOPE_NAMES       = YES
56 56
SHOW_INCLUDE_FILES     = YES
57 57
INLINE_INFO            = YES
58 58
SORT_MEMBER_DOCS       = NO
59 59
SORT_BRIEF_DOCS        = NO
60 60
SORT_GROUP_NAMES       = NO
61 61
SORT_BY_SCOPE_NAME     = NO
62 62
GENERATE_TODOLIST      = YES
63 63
GENERATE_TESTLIST      = YES
64 64
GENERATE_BUGLIST       = YES
65 65
GENERATE_DEPRECATEDLIST= YES
66 66
ENABLED_SECTIONS       = 
67 67
MAX_INITIALIZER_LINES  = 5
68 68
SHOW_USED_FILES        = NO
69 69
SHOW_DIRECTORIES       = YES
70 70
SHOW_FILES             = YES
71 71
SHOW_NAMESPACES        = YES
72 72
FILE_VERSION_FILTER    = 
73
LAYOUT_FILE            = DoxygenLayout.xml
73
LAYOUT_FILE            = "@abs_top_srcdir@/doc/DoxygenLayout.xml"
74 74
#---------------------------------------------------------------------------
75 75
# configuration options related to warning and progress messages
76 76
#---------------------------------------------------------------------------
77 77
QUIET                  = NO
78 78
WARNINGS               = YES
79 79
WARN_IF_UNDOCUMENTED   = YES
80 80
WARN_IF_DOC_ERROR      = YES
81 81
WARN_NO_PARAMDOC       = NO
82 82
WARN_FORMAT            = "$file:$line: $text"
83 83
WARN_LOGFILE           = doxygen.log
84 84
#---------------------------------------------------------------------------
85 85
# configuration options related to the input files
86 86
#---------------------------------------------------------------------------
87 87
INPUT                  = "@abs_top_srcdir@/doc" \
88 88
                         "@abs_top_srcdir@/lemon" \
89 89
                         "@abs_top_srcdir@/lemon/bits" \
90 90
                         "@abs_top_srcdir@/lemon/concepts" \
91 91
                         "@abs_top_srcdir@/demo" \
92 92
                         "@abs_top_srcdir@/tools" \
93 93
                         "@abs_top_srcdir@/test/test_tools.h" \
94 94
                         "@abs_top_builddir@/doc/references.dox"
95 95
INPUT_ENCODING         = UTF-8
96 96
FILE_PATTERNS          = *.h \
97 97
                         *.cc \
98 98
                         *.dox
99 99
RECURSIVE              = NO
100 100
EXCLUDE                = 
101 101
EXCLUDE_SYMLINKS       = NO
102 102
EXCLUDE_PATTERNS       = 
103 103
EXCLUDE_SYMBOLS        = 
104 104
EXAMPLE_PATH           = "@abs_top_srcdir@/demo" \
105 105
                         "@abs_top_srcdir@/LICENSE" \
106 106
                         "@abs_top_srcdir@/doc"
107 107
EXAMPLE_PATTERNS       = 
108 108
EXAMPLE_RECURSIVE      = NO
109 109
IMAGE_PATH             = "@abs_top_srcdir@/doc/images" \
110 110
                         "@abs_top_builddir@/doc/gen-images"
111 111
INPUT_FILTER           = 
112 112
FILTER_PATTERNS        = 
113 113
FILTER_SOURCE_FILES    = NO
114 114
#---------------------------------------------------------------------------
115 115
# configuration options related to source browsing
116 116
#---------------------------------------------------------------------------
117
SOURCE_BROWSER         = NO
117
SOURCE_BROWSER         = @LEMON_DOC_SOURCE_BROWSER@
118 118
INLINE_SOURCES         = NO
119 119
STRIP_CODE_COMMENTS    = YES
120 120
REFERENCED_BY_RELATION = NO
121 121
REFERENCES_RELATION    = NO
122 122
REFERENCES_LINK_SOURCE = YES
123 123
USE_HTAGS              = NO
124 124
VERBATIM_HEADERS       = NO
125 125
#---------------------------------------------------------------------------
126 126
# configuration options related to the alphabetical class index
127 127
#---------------------------------------------------------------------------
128 128
ALPHABETICAL_INDEX     = YES
129 129
COLS_IN_ALPHA_INDEX    = 2
130 130
IGNORE_PREFIX          = 
131 131
#---------------------------------------------------------------------------
132 132
# configuration options related to the HTML output
133 133
#---------------------------------------------------------------------------
134 134
GENERATE_HTML          = YES
135 135
HTML_OUTPUT            = html
136 136
HTML_FILE_EXTENSION    = .html
137 137
HTML_HEADER            = 
138 138
HTML_FOOTER            = 
139 139
HTML_STYLESHEET        = 
140 140
HTML_ALIGN_MEMBERS     = YES
141 141
HTML_DYNAMIC_SECTIONS  = NO
142 142
GENERATE_DOCSET        = NO
143 143
DOCSET_FEEDNAME        = "Doxygen generated docs"
144 144
DOCSET_BUNDLE_ID       = org.doxygen.Project
145 145
GENERATE_HTMLHELP      = NO
146 146
CHM_FILE               = 
147 147
HHC_LOCATION           = 
148 148
GENERATE_CHI           = NO
149 149
CHM_INDEX_ENCODING     = 
150 150
BINARY_TOC             = NO
151 151
TOC_EXPAND             = NO
152 152
GENERATE_QHP           = NO
153 153
QCH_FILE               = 
154 154
QHP_NAMESPACE          = org.doxygen.Project
155 155
QHP_VIRTUAL_FOLDER     = doc
156 156
QHG_LOCATION           = 
157 157
DISABLE_INDEX          = NO
158 158
ENUM_VALUES_PER_LINE   = 4
159 159
GENERATE_TREEVIEW      = NO
160 160
TREEVIEW_WIDTH         = 250
161 161
FORMULA_FONTSIZE       = 10
162 162
#---------------------------------------------------------------------------
163 163
# configuration options related to the LaTeX output
164 164
#---------------------------------------------------------------------------
165 165
GENERATE_LATEX         = NO
166 166
LATEX_OUTPUT           = latex
167 167
LATEX_CMD_NAME         = latex
168 168
MAKEINDEX_CMD_NAME     = makeindex
169 169
COMPACT_LATEX          = YES
170 170
PAPER_TYPE             = a4wide
171 171
EXTRA_PACKAGES         = amsmath \
172 172
                         amssymb
173 173
LATEX_HEADER           = 
174 174
PDF_HYPERLINKS         = YES
175 175
USE_PDFLATEX           = YES
176 176
LATEX_BATCHMODE        = NO
177 177
LATEX_HIDE_INDICES     = NO
178 178
#---------------------------------------------------------------------------
179 179
# configuration options related to the RTF output
180 180
#---------------------------------------------------------------------------
181 181
GENERATE_RTF           = NO
182 182
RTF_OUTPUT             = rtf
183 183
COMPACT_RTF            = NO
184 184
RTF_HYPERLINKS         = NO
185 185
RTF_STYLESHEET_FILE    = 
186 186
RTF_EXTENSIONS_FILE    = 
187 187
#---------------------------------------------------------------------------
188 188
# configuration options related to the man page output
189 189
#---------------------------------------------------------------------------
190 190
GENERATE_MAN           = NO
191 191
MAN_OUTPUT             = man
192 192
MAN_EXTENSION          = .3
193 193
MAN_LINKS              = NO
194 194
#---------------------------------------------------------------------------
195 195
# configuration options related to the XML output
196 196
#---------------------------------------------------------------------------
197 197
GENERATE_XML           = NO
198 198
XML_OUTPUT             = xml
199 199
XML_SCHEMA             = 
200 200
XML_DTD                = 
201 201
XML_PROGRAMLISTING     = YES
202 202
#---------------------------------------------------------------------------
203 203
# configuration options for the AutoGen Definitions output
204 204
#---------------------------------------------------------------------------
205 205
GENERATE_AUTOGEN_DEF   = NO
206 206
#---------------------------------------------------------------------------
207 207
# configuration options related to the Perl module output
208 208
#---------------------------------------------------------------------------
209 209
GENERATE_PERLMOD       = NO
210 210
PERLMOD_LATEX          = NO
211 211
PERLMOD_PRETTY         = YES
212 212
PERLMOD_MAKEVAR_PREFIX = 
213 213
#---------------------------------------------------------------------------
214 214
# Configuration options related to the preprocessor   
215 215
#---------------------------------------------------------------------------
216 216
ENABLE_PREPROCESSING   = YES
217 217
MACRO_EXPANSION        = NO
218 218
EXPAND_ONLY_PREDEF     = NO
219 219
SEARCH_INCLUDES        = YES
220 220
INCLUDE_PATH           = 
221 221
INCLUDE_FILE_PATTERNS  = 
222 222
PREDEFINED             = DOXYGEN
223 223
EXPAND_AS_DEFINED      = 
224 224
SKIP_FUNCTION_MACROS   = YES
225 225
#---------------------------------------------------------------------------
226 226
# Options related to the search engine   
227 227
#---------------------------------------------------------------------------
228
TAGFILES               = "@abs_top_srcdir@/doc/libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/  "
228
TAGFILES               = "@abs_top_builddir@/doc/libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/  "
229 229
GENERATE_TAGFILE       = html/lemon.tag
230 230
ALLEXTERNALS           = NO
231 231
EXTERNAL_GROUPS        = NO
232 232
PERL_PATH              = /usr/bin/perl
233 233
#---------------------------------------------------------------------------
234 234
# Configuration options related to the dot tool   
235 235
#---------------------------------------------------------------------------
236 236
CLASS_DIAGRAMS         = YES
237 237
MSCGEN_PATH            = 
238 238
HIDE_UNDOC_RELATIONS   = YES
239 239
HAVE_DOT               = YES
240 240
DOT_FONTNAME           = FreeSans
241 241
DOT_FONTSIZE           = 10
242 242
DOT_FONTPATH           = 
243 243
CLASS_GRAPH            = YES
244 244
COLLABORATION_GRAPH    = NO
245 245
GROUP_GRAPHS           = NO
246 246
UML_LOOK               = NO
247 247
TEMPLATE_RELATIONS     = NO
248 248
INCLUDE_GRAPH          = NO
249 249
INCLUDED_BY_GRAPH      = NO
250 250
CALL_GRAPH             = NO
251 251
CALLER_GRAPH           = NO
252 252
GRAPHICAL_HIERARCHY    = NO
253 253
DIRECTORY_GRAPH        = NO
254 254
DOT_IMAGE_FORMAT       = png
255 255
DOT_PATH               = 
256 256
DOTFILE_DIRS           = 
257 257
DOT_GRAPH_MAX_NODES    = 50
258 258
MAX_DOT_GRAPH_DEPTH    = 0
259 259
DOT_TRANSPARENT        = NO
260 260
DOT_MULTI_TARGETS      = NO
261 261
GENERATE_LEGEND        = YES
262 262
DOT_CLEANUP            = YES
263 263
#---------------------------------------------------------------------------
264 264
# Configuration::additions related to the search engine   
265 265
#---------------------------------------------------------------------------
266 266
SEARCHENGINE           = NO
Ignore white space 3221225472 line context
1 1
INCLUDE_DIRECTORIES(
2 2
  ${PROJECT_SOURCE_DIR}
3 3
  ${PROJECT_BINARY_DIR}
4 4
)
5 5

	
6 6
CONFIGURE_FILE(
7 7
  ${CMAKE_CURRENT_SOURCE_DIR}/config.h.cmake
8 8
  ${CMAKE_CURRENT_BINARY_DIR}/config.h
9 9
)
10 10

	
11
CONFIGURE_FILE(
12
  ${CMAKE_CURRENT_SOURCE_DIR}/lemon.pc.cmake
13
  ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
14
  @ONLY
15
)
16

	
11 17
SET(LEMON_SOURCES
12 18
  arg_parser.cc
13 19
  base.cc
14 20
  color.cc
15 21
  lp_base.cc
16 22
  lp_skeleton.cc
17 23
  random.cc
18 24
  bits/windows.cc
19 25
)
20 26

	
21 27
IF(LEMON_HAVE_GLPK)
22 28
  SET(LEMON_SOURCES ${LEMON_SOURCES} glpk.cc)
23 29
  INCLUDE_DIRECTORIES(${GLPK_INCLUDE_DIRS})
24 30
  IF(WIN32)
25 31
    INSTALL(FILES ${GLPK_BIN_DIR}/glpk.dll DESTINATION bin)
26 32
    INSTALL(FILES ${GLPK_BIN_DIR}/libltdl3.dll DESTINATION bin)
27 33
    INSTALL(FILES ${GLPK_BIN_DIR}/zlib1.dll DESTINATION bin)
28 34
  ENDIF()
29 35
ENDIF()
30 36

	
31 37
IF(LEMON_HAVE_CPLEX)
32 38
  SET(LEMON_SOURCES ${LEMON_SOURCES} cplex.cc)
33 39
  INCLUDE_DIRECTORIES(${CPLEX_INCLUDE_DIRS})
34 40
ENDIF()
35 41

	
36 42
IF(LEMON_HAVE_CLP)
37 43
  SET(LEMON_SOURCES ${LEMON_SOURCES} clp.cc)
38 44
  INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
39 45
ENDIF()
40 46

	
41 47
IF(LEMON_HAVE_CBC)
42 48
  SET(LEMON_SOURCES ${LEMON_SOURCES} cbc.cc)
43 49
  INCLUDE_DIRECTORIES(${COIN_INCLUDE_DIRS})
44 50
ENDIF()
45 51

	
46 52
ADD_LIBRARY(lemon ${LEMON_SOURCES})
47 53
IF(UNIX)
48 54
  SET_TARGET_PROPERTIES(lemon PROPERTIES OUTPUT_NAME emon)
49 55
ENDIF()
50 56

	
51 57
INSTALL(
52 58
  TARGETS lemon
53 59
  ARCHIVE DESTINATION lib
54 60
  COMPONENT library
55 61
)
56 62

	
57 63
INSTALL(
58 64
  DIRECTORY . bits concepts
59 65
  DESTINATION include/lemon
60 66
  COMPONENT headers
61 67
  FILES_MATCHING PATTERN "*.h"
62 68
)
63 69

	
64 70
INSTALL(
65 71
  FILES ${CMAKE_CURRENT_BINARY_DIR}/config.h
66 72
  DESTINATION include/lemon
67 73
  COMPONENT headers
68 74
)
75

	
76
INSTALL(
77
  FILES ${CMAKE_CURRENT_BINARY_DIR}/lemon.pc
78
  DESTINATION lib/pkgconfig
79
)
80

	
Ignore white space 3221225472 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 93
	lemon/grosso_locatelli_pullan_mc.h \
94 94
	lemon/hartmann_orlin_mmc.h \
95 95
	lemon/howard_mmc.h \
96 96
	lemon/hypercube_graph.h \
97 97
	lemon/karp_mmc.h \
98 98
	lemon/kruskal.h \
99 99
	lemon/hao_orlin.h \
100 100
	lemon/lgf_reader.h \
101 101
	lemon/lgf_writer.h \
102 102
	lemon/list_graph.h \
103 103
	lemon/lp.h \
104 104
	lemon/lp_base.h \
105 105
	lemon/lp_skeleton.h \
106 106
	lemon/maps.h \
107 107
	lemon/matching.h \
108 108
	lemon/math.h \
109 109
	lemon/min_cost_arborescence.h \
110 110
	lemon/max_cardinality_search.h \
111
	lemon/nagamochi_ibaraki.h \
111 112
	lemon/nauty_reader.h \
112 113
	lemon/network_simplex.h \
113 114
	lemon/pairing_heap.h \
114 115
	lemon/path.h \
115 116
	lemon/planarity.h \
116 117
	lemon/preflow.h \
117 118
	lemon/quad_heap.h \
118 119
	lemon/radix_heap.h \
119 120
	lemon/radix_sort.h \
120 121
	lemon/random.h \
121 122
	lemon/smart_graph.h \
122 123
	lemon/soplex.h \
123 124
	lemon/static_graph.h \
124 125
	lemon/suurballe.h \
125 126
	lemon/time_measure.h \
126 127
	lemon/tolerance.h \
127 128
	lemon/unionfind.h \
128 129
	lemon/bits/windows.h
129 130

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

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

	
19 19
#ifndef LEMON_HAO_ORLIN_H
20 20
#define LEMON_HAO_ORLIN_H
21 21

	
22 22
#include <vector>
23 23
#include <list>
24 24
#include <limits>
25 25

	
26 26
#include <lemon/maps.h>
27 27
#include <lemon/core.h>
28 28
#include <lemon/tolerance.h>
29 29

	
30 30
/// \file
31 31
/// \ingroup min_cut
32 32
/// \brief Implementation of the Hao-Orlin algorithm.
33 33
///
34 34
/// Implementation of the Hao-Orlin algorithm for finding a minimum cut
35 35
/// in a digraph.
36 36

	
37 37
namespace lemon {
38 38

	
39 39
  /// \ingroup min_cut
40 40
  ///
41 41
  /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
42 42
  ///
43 43
  /// This class implements the Hao-Orlin algorithm for finding a minimum
44 44
  /// value cut in a directed graph \f$D=(V,A)\f$.
45 45
  /// It takes a fixed node \f$ source \in V \f$ and
46 46
  /// consists of two phases: in the first phase it determines a
47 47
  /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
48 48
  /// \f$ X\subsetneq V \f$ with \f$ source \in X \f$ and minimal outgoing
49 49
  /// capacity) and in the second phase it determines a minimum cut
50 50
  /// with \f$ source \f$ on the sink-side (i.e. a set
51 51
  /// \f$ X\subsetneq V \f$ with \f$ source \notin X \f$ and minimal outgoing
52 52
  /// capacity). Obviously, the smaller of these two cuts will be a
53 53
  /// minimum cut of \f$ D \f$. The algorithm is a modified
54 54
  /// preflow push-relabel algorithm. Our implementation calculates
55 55
  /// the minimum cut in \f$ O(n^2\sqrt{m}) \f$ time (we use the
56
  /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. The
57
  /// purpose of such algorithm is e.g. testing network reliability.
56
  /// highest-label rule), or in \f$O(nm)\f$ for unit capacities. A notable
57
  /// use of this algorithm is testing network reliability.
58 58
  ///
59 59
  /// For an undirected graph you can run just the first phase of the
60 60
  /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
61 61
  /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
62 62
  /// time. It is implemented in the NagamochiIbaraki algorithm class.
63 63
  ///
64 64
  /// \tparam GR The type of the digraph the algorithm runs on.
65 65
  /// \tparam CAP The type of the arc map containing the capacities,
66 66
  /// which can be any numreric type. The default map type is
67 67
  /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
68 68
  /// \tparam TOL Tolerance class for handling inexact computations. The
69 69
  /// default tolerance type is \ref Tolerance "Tolerance<CAP::Value>".
70 70
#ifdef DOXYGEN
71 71
  template <typename GR, typename CAP, typename TOL>
72 72
#else
73 73
  template <typename GR,
74 74
            typename CAP = typename GR::template ArcMap<int>,
75 75
            typename TOL = Tolerance<typename CAP::Value> >
76 76
#endif
77 77
  class HaoOrlin {
78 78
  public:
79 79

	
80 80
    /// The digraph type of the algorithm
81 81
    typedef GR Digraph;
82 82
    /// The capacity map type of the algorithm
83 83
    typedef CAP CapacityMap;
84 84
    /// The tolerance type of the algorithm
85 85
    typedef TOL Tolerance;
86 86

	
87 87
  private:
88 88

	
89 89
    typedef typename CapacityMap::Value Value;
90 90

	
91 91
    TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
92 92

	
93 93
    const Digraph& _graph;
94 94
    const CapacityMap* _capacity;
95 95

	
96 96
    typedef typename Digraph::template ArcMap<Value> FlowMap;
97 97
    FlowMap* _flow;
98 98

	
99 99
    Node _source;
100 100

	
101 101
    int _node_num;
102 102

	
103 103
    // Bucketing structure
104 104
    std::vector<Node> _first, _last;
105 105
    typename Digraph::template NodeMap<Node>* _next;
106 106
    typename Digraph::template NodeMap<Node>* _prev;
107 107
    typename Digraph::template NodeMap<bool>* _active;
108 108
    typename Digraph::template NodeMap<int>* _bucket;
109 109

	
110 110
    std::vector<bool> _dormant;
111 111

	
112 112
    std::list<std::list<int> > _sets;
113 113
    std::list<int>::iterator _highest;
114 114

	
115 115
    typedef typename Digraph::template NodeMap<Value> ExcessMap;
116 116
    ExcessMap* _excess;
117 117

	
118 118
    typedef typename Digraph::template NodeMap<bool> SourceSetMap;
119 119
    SourceSetMap* _source_set;
120 120

	
121 121
    Value _min_cut;
122 122

	
123 123
    typedef typename Digraph::template NodeMap<bool> MinCutMap;
124 124
    MinCutMap* _min_cut_map;
125 125

	
126 126
    Tolerance _tolerance;
127 127

	
128 128
  public:
129 129

	
130 130
    /// \brief Constructor
131 131
    ///
132 132
    /// Constructor of the algorithm class.
133 133
    HaoOrlin(const Digraph& graph, const CapacityMap& capacity,
134 134
             const Tolerance& tolerance = Tolerance()) :
135 135
      _graph(graph), _capacity(&capacity), _flow(0), _source(),
136 136
      _node_num(), _first(), _last(), _next(0), _prev(0),
137 137
      _active(0), _bucket(0), _dormant(), _sets(), _highest(),
138 138
      _excess(0), _source_set(0), _min_cut(), _min_cut_map(0),
139 139
      _tolerance(tolerance) {}
140 140

	
141 141
    ~HaoOrlin() {
142 142
      if (_min_cut_map) {
143 143
        delete _min_cut_map;
144 144
      }
145 145
      if (_source_set) {
146 146
        delete _source_set;
147 147
      }
148 148
      if (_excess) {
149 149
        delete _excess;
150 150
      }
151 151
      if (_next) {
152 152
        delete _next;
153 153
      }
154 154
      if (_prev) {
155 155
        delete _prev;
156 156
      }
157 157
      if (_active) {
158 158
        delete _active;
159 159
      }
160 160
      if (_bucket) {
161 161
        delete _bucket;
162 162
      }
163 163
      if (_flow) {
164 164
        delete _flow;
165 165
      }
166 166
    }
167 167

	
168 168
    /// \brief Set the tolerance used by the algorithm.
169 169
    ///
170 170
    /// This function sets the tolerance object used by the algorithm.
171 171
    /// \return <tt>(*this)</tt>
172 172
    HaoOrlin& tolerance(const Tolerance& tolerance) {
173 173
      _tolerance = tolerance;
174 174
      return *this;
175 175
    }
176 176

	
177 177
    /// \brief Returns a const reference to the tolerance.
178 178
    ///
179 179
    /// This function returns a const reference to the tolerance object
180 180
    /// used by the algorithm.
181 181
    const Tolerance& tolerance() const {
182 182
      return _tolerance;
183 183
    }
184 184

	
185 185
  private:
186 186

	
187 187
    void activate(const Node& i) {
188 188
      (*_active)[i] = true;
189 189

	
190 190
      int bucket = (*_bucket)[i];
191 191

	
192 192
      if ((*_prev)[i] == INVALID || (*_active)[(*_prev)[i]]) return;
193 193
      //unlace
194 194
      (*_next)[(*_prev)[i]] = (*_next)[i];
195 195
      if ((*_next)[i] != INVALID) {
196 196
        (*_prev)[(*_next)[i]] = (*_prev)[i];
197 197
      } else {
198 198
        _last[bucket] = (*_prev)[i];
199 199
      }
200 200
      //lace
201 201
      (*_next)[i] = _first[bucket];
202 202
      (*_prev)[_first[bucket]] = i;
203 203
      (*_prev)[i] = INVALID;
204 204
      _first[bucket] = i;
205 205
    }
206 206

	
207 207
    void deactivate(const Node& i) {
208 208
      (*_active)[i] = false;
209 209
      int bucket = (*_bucket)[i];
210 210

	
211 211
      if ((*_next)[i] == INVALID || !(*_active)[(*_next)[i]]) return;
212 212

	
213 213
      //unlace
214 214
      (*_prev)[(*_next)[i]] = (*_prev)[i];
215 215
      if ((*_prev)[i] != INVALID) {
216 216
        (*_next)[(*_prev)[i]] = (*_next)[i];
217 217
      } else {
218 218
        _first[bucket] = (*_next)[i];
219 219
      }
220 220
      //lace
221 221
      (*_prev)[i] = _last[bucket];
222 222
      (*_next)[_last[bucket]] = i;
223 223
      (*_next)[i] = INVALID;
224 224
      _last[bucket] = i;
225 225
    }
226 226

	
227 227
    void addItem(const Node& i, int bucket) {
228 228
      (*_bucket)[i] = bucket;
229 229
      if (_last[bucket] != INVALID) {
230 230
        (*_prev)[i] = _last[bucket];
231 231
        (*_next)[_last[bucket]] = i;
232 232
        (*_next)[i] = INVALID;
233 233
        _last[bucket] = i;
234 234
      } else {
235 235
        (*_prev)[i] = INVALID;
236 236
        _first[bucket] = i;
237 237
        (*_next)[i] = INVALID;
238 238
        _last[bucket] = i;
239 239
      }
240 240
    }
241 241

	
242 242
    void findMinCutOut() {
243 243

	
244 244
      for (NodeIt n(_graph); n != INVALID; ++n) {
245 245
        (*_excess)[n] = 0;
246 246
        (*_source_set)[n] = false;
247 247
      }
248 248

	
249 249
      for (ArcIt a(_graph); a != INVALID; ++a) {
250 250
        (*_flow)[a] = 0;
251 251
      }
252 252

	
253 253
      int bucket_num = 0;
254 254
      std::vector<Node> queue(_node_num);
255 255
      int qfirst = 0, qlast = 0, qsep = 0;
256 256

	
257 257
      {
258 258
        typename Digraph::template NodeMap<bool> reached(_graph, false);
259 259

	
260 260
        reached[_source] = true;
261 261
        bool first_set = true;
262 262

	
263 263
        for (NodeIt t(_graph); t != INVALID; ++t) {
264 264
          if (reached[t]) continue;
265 265
          _sets.push_front(std::list<int>());
266 266

	
267 267
          queue[qlast++] = t;
268 268
          reached[t] = true;
269 269

	
270 270
          while (qfirst != qlast) {
271 271
            if (qsep == qfirst) {
272 272
              ++bucket_num;
273 273
              _sets.front().push_front(bucket_num);
274 274
              _dormant[bucket_num] = !first_set;
275 275
              _first[bucket_num] = _last[bucket_num] = INVALID;
276 276
              qsep = qlast;
277 277
            }
278 278

	
279 279
            Node n = queue[qfirst++];
280 280
            addItem(n, bucket_num);
281 281

	
282 282
            for (InArcIt a(_graph, n); a != INVALID; ++a) {
283 283
              Node u = _graph.source(a);
284 284
              if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
285 285
                reached[u] = true;
286 286
                queue[qlast++] = u;
287 287
              }
288 288
            }
289 289
          }
290 290
          first_set = false;
291 291
        }
292 292

	
293 293
        ++bucket_num;
294 294
        (*_bucket)[_source] = 0;
295 295
        _dormant[0] = true;
296 296
      }
297 297
      (*_source_set)[_source] = true;
298 298

	
299 299
      Node target = _last[_sets.back().back()];
300 300
      {
301 301
        for (OutArcIt a(_graph, _source); a != INVALID; ++a) {
302 302
          if (_tolerance.positive((*_capacity)[a])) {
303 303
            Node u = _graph.target(a);
304 304
            (*_flow)[a] = (*_capacity)[a];
305 305
            (*_excess)[u] += (*_capacity)[a];
306 306
            if (!(*_active)[u] && u != _source) {
307 307
              activate(u);
308 308
            }
309 309
          }
310 310
        }
311 311

	
312 312
        if ((*_active)[target]) {
313 313
          deactivate(target);
314 314
        }
315 315

	
316 316
        _highest = _sets.back().begin();
317 317
        while (_highest != _sets.back().end() &&
318 318
               !(*_active)[_first[*_highest]]) {
319 319
          ++_highest;
320 320
        }
321 321
      }
322 322

	
323 323
      while (true) {
324 324
        while (_highest != _sets.back().end()) {
325 325
          Node n = _first[*_highest];
326 326
          Value excess = (*_excess)[n];
327 327
          int next_bucket = _node_num;
328 328

	
329 329
          int under_bucket;
330 330
          if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
331 331
            under_bucket = -1;
332 332
          } else {
333 333
            under_bucket = *(++std::list<int>::iterator(_highest));
334 334
          }
335 335

	
336 336
          for (OutArcIt a(_graph, n); a != INVALID; ++a) {
337 337
            Node v = _graph.target(a);
338 338
            if (_dormant[(*_bucket)[v]]) continue;
339 339
            Value rem = (*_capacity)[a] - (*_flow)[a];
340 340
            if (!_tolerance.positive(rem)) continue;
341 341
            if ((*_bucket)[v] == under_bucket) {
342 342
              if (!(*_active)[v] && v != target) {
343 343
                activate(v);
344 344
              }
345 345
              if (!_tolerance.less(rem, excess)) {
346 346
                (*_flow)[a] += excess;
347 347
                (*_excess)[v] += excess;
348 348
                excess = 0;
349 349
                goto no_more_push;
350 350
              } else {
351 351
                excess -= rem;
352 352
                (*_excess)[v] += rem;
353 353
                (*_flow)[a] = (*_capacity)[a];
354 354
              }
355 355
            } else if (next_bucket > (*_bucket)[v]) {
356 356
              next_bucket = (*_bucket)[v];
357 357
            }
358 358
          }
359 359

	
360 360
          for (InArcIt a(_graph, n); a != INVALID; ++a) {
361 361
            Node v = _graph.source(a);
362 362
            if (_dormant[(*_bucket)[v]]) continue;
363 363
            Value rem = (*_flow)[a];
364 364
            if (!_tolerance.positive(rem)) continue;
365 365
            if ((*_bucket)[v] == under_bucket) {
366 366
              if (!(*_active)[v] && v != target) {
367 367
                activate(v);
368 368
              }
369 369
              if (!_tolerance.less(rem, excess)) {
370 370
                (*_flow)[a] -= excess;
371 371
                (*_excess)[v] += excess;
372 372
                excess = 0;
373 373
                goto no_more_push;
374 374
              } else {
375 375
                excess -= rem;
376 376
                (*_excess)[v] += rem;
377 377
                (*_flow)[a] = 0;
378 378
              }
379 379
            } else if (next_bucket > (*_bucket)[v]) {
380 380
              next_bucket = (*_bucket)[v];
381 381
            }
382 382
          }
383 383

	
384 384
        no_more_push:
385 385

	
386 386
          (*_excess)[n] = excess;
387 387

	
388 388
          if (excess != 0) {
389 389
            if ((*_next)[n] == INVALID) {
390 390
              typename std::list<std::list<int> >::iterator new_set =
391 391
                _sets.insert(--_sets.end(), std::list<int>());
392 392
              new_set->splice(new_set->end(), _sets.back(),
393 393
                              _sets.back().begin(), ++_highest);
394 394
              for (std::list<int>::iterator it = new_set->begin();
395 395
                   it != new_set->end(); ++it) {
396 396
                _dormant[*it] = true;
397 397
              }
398 398
              while (_highest != _sets.back().end() &&
399 399
                     !(*_active)[_first[*_highest]]) {
400 400
                ++_highest;
401 401
              }
402 402
            } else if (next_bucket == _node_num) {
403 403
              _first[(*_bucket)[n]] = (*_next)[n];
404 404
              (*_prev)[(*_next)[n]] = INVALID;
405 405

	
406 406
              std::list<std::list<int> >::iterator new_set =
407 407
                _sets.insert(--_sets.end(), std::list<int>());
408 408

	
409 409
              new_set->push_front(bucket_num);
410 410
              (*_bucket)[n] = bucket_num;
411 411
              _first[bucket_num] = _last[bucket_num] = n;
412 412
              (*_next)[n] = INVALID;
413 413
              (*_prev)[n] = INVALID;
414 414
              _dormant[bucket_num] = true;
415 415
              ++bucket_num;
416 416

	
417 417
              while (_highest != _sets.back().end() &&
418 418
                     !(*_active)[_first[*_highest]]) {
419 419
                ++_highest;
420 420
              }
421 421
            } else {
422 422
              _first[*_highest] = (*_next)[n];
423 423
              (*_prev)[(*_next)[n]] = INVALID;
424 424

	
425 425
              while (next_bucket != *_highest) {
426 426
                --_highest;
427 427
              }
428 428

	
429 429
              if (_highest == _sets.back().begin()) {
430 430
                _sets.back().push_front(bucket_num);
431 431
                _dormant[bucket_num] = false;
432 432
                _first[bucket_num] = _last[bucket_num] = INVALID;
433 433
                ++bucket_num;
434 434
              }
435 435
              --_highest;
436 436

	
437 437
              (*_bucket)[n] = *_highest;
438 438
              (*_next)[n] = _first[*_highest];
439 439
              if (_first[*_highest] != INVALID) {
440 440
                (*_prev)[_first[*_highest]] = n;
441 441
              } else {
442 442
                _last[*_highest] = n;
443 443
              }
444 444
              _first[*_highest] = n;
445 445
            }
446 446
          } else {
447 447

	
448 448
            deactivate(n);
449 449
            if (!(*_active)[_first[*_highest]]) {
450 450
              ++_highest;
451 451
              if (_highest != _sets.back().end() &&
452 452
                  !(*_active)[_first[*_highest]]) {
453 453
                _highest = _sets.back().end();
454 454
              }
455 455
            }
456 456
          }
457 457
        }
458 458

	
459 459
        if ((*_excess)[target] < _min_cut) {
460 460
          _min_cut = (*_excess)[target];
461 461
          for (NodeIt i(_graph); i != INVALID; ++i) {
462 462
            (*_min_cut_map)[i] = true;
463 463
          }
464 464
          for (std::list<int>::iterator it = _sets.back().begin();
465 465
               it != _sets.back().end(); ++it) {
466 466
            Node n = _first[*it];
467 467
            while (n != INVALID) {
468 468
              (*_min_cut_map)[n] = false;
469 469
              n = (*_next)[n];
470 470
            }
471 471
          }
472 472
        }
473 473

	
474 474
        {
475 475
          Node new_target;
476 476
          if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
477 477
            if ((*_next)[target] == INVALID) {
478 478
              _last[(*_bucket)[target]] = (*_prev)[target];
479 479
              new_target = (*_prev)[target];
480 480
            } else {
481 481
              (*_prev)[(*_next)[target]] = (*_prev)[target];
482 482
              new_target = (*_next)[target];
483 483
            }
484 484
            if ((*_prev)[target] == INVALID) {
485 485
              _first[(*_bucket)[target]] = (*_next)[target];
486 486
            } else {
487 487
              (*_next)[(*_prev)[target]] = (*_next)[target];
488 488
            }
489 489
          } else {
490 490
            _sets.back().pop_back();
491 491
            if (_sets.back().empty()) {
492 492
              _sets.pop_back();
493 493
              if (_sets.empty())
494 494
                break;
495 495
              for (std::list<int>::iterator it = _sets.back().begin();
496 496
                   it != _sets.back().end(); ++it) {
497 497
                _dormant[*it] = false;
498 498
              }
499 499
            }
500 500
            new_target = _last[_sets.back().back()];
501 501
          }
502 502

	
503 503
          (*_bucket)[target] = 0;
504 504

	
505 505
          (*_source_set)[target] = true;
506 506
          for (OutArcIt a(_graph, target); a != INVALID; ++a) {
507 507
            Value rem = (*_capacity)[a] - (*_flow)[a];
508 508
            if (!_tolerance.positive(rem)) continue;
509 509
            Node v = _graph.target(a);
510 510
            if (!(*_active)[v] && !(*_source_set)[v]) {
511 511
              activate(v);
512 512
            }
513 513
            (*_excess)[v] += rem;
514 514
            (*_flow)[a] = (*_capacity)[a];
515 515
          }
516 516

	
517 517
          for (InArcIt a(_graph, target); a != INVALID; ++a) {
518 518
            Value rem = (*_flow)[a];
519 519
            if (!_tolerance.positive(rem)) continue;
520 520
            Node v = _graph.source(a);
521 521
            if (!(*_active)[v] && !(*_source_set)[v]) {
522 522
              activate(v);
523 523
            }
524 524
            (*_excess)[v] += rem;
525 525
            (*_flow)[a] = 0;
526 526
          }
527 527

	
528 528
          target = new_target;
529 529
          if ((*_active)[target]) {
530 530
            deactivate(target);
531 531
          }
532 532

	
533 533
          _highest = _sets.back().begin();
534 534
          while (_highest != _sets.back().end() &&
535 535
                 !(*_active)[_first[*_highest]]) {
536 536
            ++_highest;
537 537
          }
538 538
        }
539 539
      }
540 540
    }
541 541

	
542 542
    void findMinCutIn() {
543 543

	
544 544
      for (NodeIt n(_graph); n != INVALID; ++n) {
545 545
        (*_excess)[n] = 0;
546 546
        (*_source_set)[n] = false;
547 547
      }
548 548

	
549 549
      for (ArcIt a(_graph); a != INVALID; ++a) {
550 550
        (*_flow)[a] = 0;
551 551
      }
552 552

	
553 553
      int bucket_num = 0;
554 554
      std::vector<Node> queue(_node_num);
555 555
      int qfirst = 0, qlast = 0, qsep = 0;
556 556

	
557 557
      {
558 558
        typename Digraph::template NodeMap<bool> reached(_graph, false);
559 559

	
560 560
        reached[_source] = true;
561 561

	
562 562
        bool first_set = true;
563 563

	
564 564
        for (NodeIt t(_graph); t != INVALID; ++t) {
565 565
          if (reached[t]) continue;
566 566
          _sets.push_front(std::list<int>());
567 567

	
568 568
          queue[qlast++] = t;
569 569
          reached[t] = true;
570 570

	
571 571
          while (qfirst != qlast) {
572 572
            if (qsep == qfirst) {
573 573
              ++bucket_num;
574 574
              _sets.front().push_front(bucket_num);
575 575
              _dormant[bucket_num] = !first_set;
576 576
              _first[bucket_num] = _last[bucket_num] = INVALID;
577 577
              qsep = qlast;
578 578
            }
579 579

	
580 580
            Node n = queue[qfirst++];
581 581
            addItem(n, bucket_num);
582 582

	
583 583
            for (OutArcIt a(_graph, n); a != INVALID; ++a) {
584 584
              Node u = _graph.target(a);
585 585
              if (!reached[u] && _tolerance.positive((*_capacity)[a])) {
586 586
                reached[u] = true;
587 587
                queue[qlast++] = u;
588 588
              }
589 589
            }
590 590
          }
591 591
          first_set = false;
592 592
        }
593 593

	
594 594
        ++bucket_num;
595 595
        (*_bucket)[_source] = 0;
596 596
        _dormant[0] = true;
597 597
      }
598 598
      (*_source_set)[_source] = true;
599 599

	
600 600
      Node target = _last[_sets.back().back()];
601 601
      {
602 602
        for (InArcIt a(_graph, _source); a != INVALID; ++a) {
603 603
          if (_tolerance.positive((*_capacity)[a])) {
604 604
            Node u = _graph.source(a);
605 605
            (*_flow)[a] = (*_capacity)[a];
606 606
            (*_excess)[u] += (*_capacity)[a];
607 607
            if (!(*_active)[u] && u != _source) {
608 608
              activate(u);
609 609
            }
610 610
          }
611 611
        }
612 612
        if ((*_active)[target]) {
613 613
          deactivate(target);
614 614
        }
615 615

	
616 616
        _highest = _sets.back().begin();
617 617
        while (_highest != _sets.back().end() &&
618 618
               !(*_active)[_first[*_highest]]) {
619 619
          ++_highest;
620 620
        }
621 621
      }
622 622

	
623 623

	
624 624
      while (true) {
625 625
        while (_highest != _sets.back().end()) {
626 626
          Node n = _first[*_highest];
627 627
          Value excess = (*_excess)[n];
628 628
          int next_bucket = _node_num;
629 629

	
630 630
          int under_bucket;
631 631
          if (++std::list<int>::iterator(_highest) == _sets.back().end()) {
632 632
            under_bucket = -1;
633 633
          } else {
634 634
            under_bucket = *(++std::list<int>::iterator(_highest));
635 635
          }
636 636

	
637 637
          for (InArcIt a(_graph, n); a != INVALID; ++a) {
638 638
            Node v = _graph.source(a);
639 639
            if (_dormant[(*_bucket)[v]]) continue;
640 640
            Value rem = (*_capacity)[a] - (*_flow)[a];
641 641
            if (!_tolerance.positive(rem)) continue;
642 642
            if ((*_bucket)[v] == under_bucket) {
643 643
              if (!(*_active)[v] && v != target) {
644 644
                activate(v);
645 645
              }
646 646
              if (!_tolerance.less(rem, excess)) {
647 647
                (*_flow)[a] += excess;
648 648
                (*_excess)[v] += excess;
649 649
                excess = 0;
650 650
                goto no_more_push;
651 651
              } else {
652 652
                excess -= rem;
653 653
                (*_excess)[v] += rem;
654 654
                (*_flow)[a] = (*_capacity)[a];
655 655
              }
656 656
            } else if (next_bucket > (*_bucket)[v]) {
657 657
              next_bucket = (*_bucket)[v];
658 658
            }
659 659
          }
660 660

	
661 661
          for (OutArcIt a(_graph, n); a != INVALID; ++a) {
662 662
            Node v = _graph.target(a);
663 663
            if (_dormant[(*_bucket)[v]]) continue;
664 664
            Value rem = (*_flow)[a];
665 665
            if (!_tolerance.positive(rem)) continue;
666 666
            if ((*_bucket)[v] == under_bucket) {
667 667
              if (!(*_active)[v] && v != target) {
668 668
                activate(v);
669 669
              }
670 670
              if (!_tolerance.less(rem, excess)) {
671 671
                (*_flow)[a] -= excess;
672 672
                (*_excess)[v] += excess;
673 673
                excess = 0;
674 674
                goto no_more_push;
675 675
              } else {
676 676
                excess -= rem;
677 677
                (*_excess)[v] += rem;
678 678
                (*_flow)[a] = 0;
679 679
              }
680 680
            } else if (next_bucket > (*_bucket)[v]) {
681 681
              next_bucket = (*_bucket)[v];
682 682
            }
683 683
          }
684 684

	
685 685
        no_more_push:
686 686

	
687 687
          (*_excess)[n] = excess;
688 688

	
689 689
          if (excess != 0) {
690 690
            if ((*_next)[n] == INVALID) {
691 691
              typename std::list<std::list<int> >::iterator new_set =
692 692
                _sets.insert(--_sets.end(), std::list<int>());
693 693
              new_set->splice(new_set->end(), _sets.back(),
694 694
                              _sets.back().begin(), ++_highest);
695 695
              for (std::list<int>::iterator it = new_set->begin();
696 696
                   it != new_set->end(); ++it) {
697 697
                _dormant[*it] = true;
698 698
              }
699 699
              while (_highest != _sets.back().end() &&
700 700
                     !(*_active)[_first[*_highest]]) {
701 701
                ++_highest;
702 702
              }
703 703
            } else if (next_bucket == _node_num) {
704 704
              _first[(*_bucket)[n]] = (*_next)[n];
705 705
              (*_prev)[(*_next)[n]] = INVALID;
706 706

	
707 707
              std::list<std::list<int> >::iterator new_set =
708 708
                _sets.insert(--_sets.end(), std::list<int>());
709 709

	
710 710
              new_set->push_front(bucket_num);
711 711
              (*_bucket)[n] = bucket_num;
712 712
              _first[bucket_num] = _last[bucket_num] = n;
713 713
              (*_next)[n] = INVALID;
714 714
              (*_prev)[n] = INVALID;
715 715
              _dormant[bucket_num] = true;
716 716
              ++bucket_num;
717 717

	
718 718
              while (_highest != _sets.back().end() &&
719 719
                     !(*_active)[_first[*_highest]]) {
720 720
                ++_highest;
721 721
              }
722 722
            } else {
723 723
              _first[*_highest] = (*_next)[n];
724 724
              (*_prev)[(*_next)[n]] = INVALID;
725 725

	
726 726
              while (next_bucket != *_highest) {
727 727
                --_highest;
728 728
              }
729 729
              if (_highest == _sets.back().begin()) {
730 730
                _sets.back().push_front(bucket_num);
731 731
                _dormant[bucket_num] = false;
732 732
                _first[bucket_num] = _last[bucket_num] = INVALID;
733 733
                ++bucket_num;
734 734
              }
735 735
              --_highest;
736 736

	
737 737
              (*_bucket)[n] = *_highest;
738 738
              (*_next)[n] = _first[*_highest];
739 739
              if (_first[*_highest] != INVALID) {
740 740
                (*_prev)[_first[*_highest]] = n;
741 741
              } else {
742 742
                _last[*_highest] = n;
743 743
              }
744 744
              _first[*_highest] = n;
745 745
            }
746 746
          } else {
747 747

	
748 748
            deactivate(n);
749 749
            if (!(*_active)[_first[*_highest]]) {
750 750
              ++_highest;
751 751
              if (_highest != _sets.back().end() &&
752 752
                  !(*_active)[_first[*_highest]]) {
753 753
                _highest = _sets.back().end();
754 754
              }
755 755
            }
756 756
          }
757 757
        }
758 758

	
759 759
        if ((*_excess)[target] < _min_cut) {
760 760
          _min_cut = (*_excess)[target];
761 761
          for (NodeIt i(_graph); i != INVALID; ++i) {
762 762
            (*_min_cut_map)[i] = false;
763 763
          }
764 764
          for (std::list<int>::iterator it = _sets.back().begin();
765 765
               it != _sets.back().end(); ++it) {
766 766
            Node n = _first[*it];
767 767
            while (n != INVALID) {
768 768
              (*_min_cut_map)[n] = true;
769 769
              n = (*_next)[n];
770 770
            }
771 771
          }
772 772
        }
773 773

	
774 774
        {
775 775
          Node new_target;
776 776
          if ((*_prev)[target] != INVALID || (*_next)[target] != INVALID) {
777 777
            if ((*_next)[target] == INVALID) {
778 778
              _last[(*_bucket)[target]] = (*_prev)[target];
779 779
              new_target = (*_prev)[target];
780 780
            } else {
781 781
              (*_prev)[(*_next)[target]] = (*_prev)[target];
782 782
              new_target = (*_next)[target];
783 783
            }
784 784
            if ((*_prev)[target] == INVALID) {
785 785
              _first[(*_bucket)[target]] = (*_next)[target];
786 786
            } else {
787 787
              (*_next)[(*_prev)[target]] = (*_next)[target];
788 788
            }
789 789
          } else {
790 790
            _sets.back().pop_back();
791 791
            if (_sets.back().empty()) {
792 792
              _sets.pop_back();
793 793
              if (_sets.empty())
794 794
                break;
795 795
              for (std::list<int>::iterator it = _sets.back().begin();
796 796
                   it != _sets.back().end(); ++it) {
797 797
                _dormant[*it] = false;
798 798
              }
799 799
            }
800 800
            new_target = _last[_sets.back().back()];
801 801
          }
802 802

	
803 803
          (*_bucket)[target] = 0;
804 804

	
805 805
          (*_source_set)[target] = true;
806 806
          for (InArcIt a(_graph, target); a != INVALID; ++a) {
807 807
            Value rem = (*_capacity)[a] - (*_flow)[a];
808 808
            if (!_tolerance.positive(rem)) continue;
809 809
            Node v = _graph.source(a);
810 810
            if (!(*_active)[v] && !(*_source_set)[v]) {
811 811
              activate(v);
812 812
            }
813 813
            (*_excess)[v] += rem;
814 814
            (*_flow)[a] = (*_capacity)[a];
815 815
          }
816 816

	
817 817
          for (OutArcIt a(_graph, target); a != INVALID; ++a) {
818 818
            Value rem = (*_flow)[a];
819 819
            if (!_tolerance.positive(rem)) continue;
820 820
            Node v = _graph.target(a);
821 821
            if (!(*_active)[v] && !(*_source_set)[v]) {
822 822
              activate(v);
823 823
            }
824 824
            (*_excess)[v] += rem;
825 825
            (*_flow)[a] = 0;
826 826
          }
827 827

	
828 828
          target = new_target;
829 829
          if ((*_active)[target]) {
830 830
            deactivate(target);
831 831
          }
832 832

	
833 833
          _highest = _sets.back().begin();
834 834
          while (_highest != _sets.back().end() &&
835 835
                 !(*_active)[_first[*_highest]]) {
836 836
            ++_highest;
837 837
          }
838 838
        }
839 839
      }
840 840
    }
841 841

	
842 842
  public:
843 843

	
844 844
    /// \name Execution Control
845 845
    /// The simplest way to execute the algorithm is to use
846 846
    /// one of the member functions called \ref run().
847 847
    /// \n
848 848
    /// If you need better control on the execution,
849 849
    /// you have to call one of the \ref init() functions first, then
850 850
    /// \ref calculateOut() and/or \ref calculateIn().
851 851

	
852 852
    /// @{
853 853

	
854 854
    /// \brief Initialize the internal data structures.
855 855
    ///
856 856
    /// This function initializes the internal data structures. It creates
857 857
    /// the maps and some bucket structures for the algorithm.
858 858
    /// The first node is used as the source node for the push-relabel
859 859
    /// algorithm.
860 860
    void init() {
861 861
      init(NodeIt(_graph));
862 862
    }
863 863

	
864 864
    /// \brief Initialize the internal data structures.
865 865
    ///
866 866
    /// This function initializes the internal data structures. It creates
867 867
    /// the maps and some bucket structures for the algorithm.
868 868
    /// The given node is used as the source node for the push-relabel
869 869
    /// algorithm.
870 870
    void init(const Node& source) {
871 871
      _source = source;
872 872

	
873 873
      _node_num = countNodes(_graph);
874 874

	
875 875
      _first.resize(_node_num);
876 876
      _last.resize(_node_num);
877 877

	
878 878
      _dormant.resize(_node_num);
879 879

	
880 880
      if (!_flow) {
881 881
        _flow = new FlowMap(_graph);
882 882
      }
883 883
      if (!_next) {
884 884
        _next = new typename Digraph::template NodeMap<Node>(_graph);
885 885
      }
886 886
      if (!_prev) {
887 887
        _prev = new typename Digraph::template NodeMap<Node>(_graph);
888 888
      }
889 889
      if (!_active) {
890 890
        _active = new typename Digraph::template NodeMap<bool>(_graph);
891 891
      }
892 892
      if (!_bucket) {
893 893
        _bucket = new typename Digraph::template NodeMap<int>(_graph);
894 894
      }
895 895
      if (!_excess) {
896 896
        _excess = new ExcessMap(_graph);
897 897
      }
898 898
      if (!_source_set) {
899 899
        _source_set = new SourceSetMap(_graph);
900 900
      }
901 901
      if (!_min_cut_map) {
902 902
        _min_cut_map = new MinCutMap(_graph);
903 903
      }
904 904

	
905 905
      _min_cut = std::numeric_limits<Value>::max();
906 906
    }
907 907

	
908 908

	
909 909
    /// \brief Calculate a minimum cut with \f$ source \f$ on the
910 910
    /// source-side.
911 911
    ///
912 912
    /// This function calculates a minimum cut with \f$ source \f$ on the
913 913
    /// source-side (i.e. a set \f$ X\subsetneq V \f$ with
914 914
    /// \f$ source \in X \f$ and minimal outgoing capacity).
915
    /// It updates the stored cut if (and only if) the newly found one
916
    /// is better.
915 917
    ///
916 918
    /// \pre \ref init() must be called before using this function.
917 919
    void calculateOut() {
918 920
      findMinCutOut();
919 921
    }
920 922

	
921 923
    /// \brief Calculate a minimum cut with \f$ source \f$ on the
922 924
    /// sink-side.
923 925
    ///
924 926
    /// This function calculates a minimum cut with \f$ source \f$ on the
925 927
    /// sink-side (i.e. a set \f$ X\subsetneq V \f$ with
926 928
    /// \f$ source \notin X \f$ and minimal outgoing capacity).
929
    /// It updates the stored cut if (and only if) the newly found one
930
    /// is better.
927 931
    ///
928 932
    /// \pre \ref init() must be called before using this function.
929 933
    void calculateIn() {
930 934
      findMinCutIn();
931 935
    }
932 936

	
933 937

	
934 938
    /// \brief Run the algorithm.
935 939
    ///
936
    /// This function runs the algorithm. It finds nodes \c source and
937
    /// \c target arbitrarily and then calls \ref init(), \ref calculateOut()
940
    /// This function runs the algorithm. It chooses source node,
941
    /// then calls \ref init(), \ref calculateOut()
938 942
    /// and \ref calculateIn().
939 943
    void run() {
940 944
      init();
941 945
      calculateOut();
942 946
      calculateIn();
943 947
    }
944 948

	
945 949
    /// \brief Run the algorithm.
946 950
    ///
947
    /// This function runs the algorithm. It uses the given \c source node,
948
    /// finds a proper \c target node and then calls the \ref init(),
949
    /// \ref calculateOut() and \ref calculateIn().
951
    /// This function runs the algorithm. It calls \ref init(),
952
    /// \ref calculateOut() and \ref calculateIn() with the given
953
    /// source node.
950 954
    void run(const Node& s) {
951 955
      init(s);
952 956
      calculateOut();
953 957
      calculateIn();
954 958
    }
955 959

	
956 960
    /// @}
957 961

	
958 962
    /// \name Query Functions
959 963
    /// The result of the %HaoOrlin algorithm
960 964
    /// can be obtained using these functions.\n
961 965
    /// \ref run(), \ref calculateOut() or \ref calculateIn()
962 966
    /// should be called before using them.
963 967

	
964 968
    /// @{
965 969

	
966 970
    /// \brief Return the value of the minimum cut.
967 971
    ///
968
    /// This function returns the value of the minimum cut.
972
    /// This function returns the value of the best cut found by the
973
    /// previously called \ref run(), \ref calculateOut() or \ref
974
    /// calculateIn().
969 975
    ///
970 976
    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
971 977
    /// must be called before using this function.
972 978
    Value minCutValue() const {
973 979
      return _min_cut;
974 980
    }
975 981

	
976 982

	
977 983
    /// \brief Return a minimum cut.
978 984
    ///
979
    /// This function sets \c cutMap to the characteristic vector of a
980
    /// minimum value cut: it will give a non-empty set \f$ X\subsetneq V \f$
981
    /// with minimal outgoing capacity (i.e. \c cutMap will be \c true exactly
985
    /// This function gives the best cut found by the
986
    /// previously called \ref run(), \ref calculateOut() or \ref
987
    /// calculateIn().
988
    ///
989
    /// It sets \c cutMap to the characteristic vector of the found
990
    /// minimum value cut - a non-empty set \f$ X\subsetneq V \f$
991
    /// of minimum outgoing capacity (i.e. \c cutMap will be \c true exactly
982 992
    /// for the nodes of \f$ X \f$).
983 993
    ///
984 994
    /// \param cutMap A \ref concepts::WriteMap "writable" node map with
985 995
    /// \c bool (or convertible) value type.
986 996
    ///
987 997
    /// \return The value of the minimum cut.
988 998
    ///
989 999
    /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
990 1000
    /// must be called before using this function.
991 1001
    template <typename CutMap>
992 1002
    Value minCutMap(CutMap& cutMap) const {
993 1003
      for (NodeIt it(_graph); it != INVALID; ++it) {
994 1004
        cutMap.set(it, (*_min_cut_map)[it]);
995 1005
      }
996 1006
      return _min_cut;
997 1007
    }
998 1008

	
999 1009
    /// @}
1000 1010

	
1001 1011
  }; //class HaoOrlin
1002 1012

	
1003 1013
} //namespace lemon
1004 1014

	
1005 1015
#endif //LEMON_HAO_ORLIN_H
Ignore white space 3221225472 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 34
  max_cardinality_search_test
35 35
  max_clique_test
36 36
  min_cost_arborescence_test
37 37
  min_cost_flow_test
38 38
  min_mean_cycle_test
39
  nagamochi_ibaraki_test
39 40
  path_test
40 41
  planarity_test
41 42
  preflow_test
42 43
  radix_sort_test
43 44
  random_test
44 45
  suurballe_test
45 46
  time_measure_test
46 47
  unionfind_test
47 48
)
48 49

	
49 50
IF(LEMON_HAVE_LP)
50
  ADD_EXECUTABLE(lp_test lp_test.cc)
51
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
52
    ADD_EXECUTABLE(lp_test lp_test.cc)
53
  ELSE()
54
    ADD_EXECUTABLE(lp_test EXCLUDE_FROM_ALL lp_test.cc)
55
  ENDIF()
56

	
51 57
  SET(LP_TEST_LIBS lemon)
52 58

	
53 59
  IF(LEMON_HAVE_GLPK)
54 60
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${GLPK_LIBRARIES})
55 61
  ENDIF()
56 62
  IF(LEMON_HAVE_CPLEX)
57 63
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${CPLEX_LIBRARIES})
58 64
  ENDIF()
59 65
  IF(LEMON_HAVE_CLP)
60 66
    SET(LP_TEST_LIBS ${LP_TEST_LIBS} ${COIN_CLP_LIBRARIES})
61 67
  ENDIF()
62 68

	
63 69
  TARGET_LINK_LIBRARIES(lp_test ${LP_TEST_LIBS})
64 70
  ADD_TEST(lp_test lp_test)
65 71

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

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

	
85 91
IF(LEMON_HAVE_MIP)
86
  ADD_EXECUTABLE(mip_test mip_test.cc)
92
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
93
    ADD_EXECUTABLE(mip_test mip_test.cc)
94
  ELSE()
95
    ADD_EXECUTABLE(mip_test EXCLUDE_FROM_ALL mip_test.cc)
96
  ENDIF()
97

	
87 98
  SET(MIP_TEST_LIBS lemon)
88 99

	
89 100
  IF(LEMON_HAVE_GLPK)
90 101
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${GLPK_LIBRARIES})
91 102
  ENDIF()
92 103
  IF(LEMON_HAVE_CPLEX)
93 104
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${CPLEX_LIBRARIES})
94 105
  ENDIF()
95 106
  IF(LEMON_HAVE_CBC)
96 107
    SET(MIP_TEST_LIBS ${MIP_TEST_LIBS} ${COIN_CBC_LIBRARIES})
97 108
  ENDIF()
98 109

	
99 110
  TARGET_LINK_LIBRARIES(mip_test ${MIP_TEST_LIBS})
100 111
  ADD_TEST(mip_test mip_test)
101 112

	
102 113
  IF(WIN32 AND LEMON_HAVE_GLPK)
103 114
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
104 115
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
105 116
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
106 117
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/glpk.dll ${TARGET_PATH}
107 118
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/libltdl3.dll ${TARGET_PATH}
108 119
      COMMAND ${CMAKE_COMMAND} -E copy ${GLPK_BIN_DIR}/zlib1.dll ${TARGET_PATH}
109 120
    )
110 121
  ENDIF()
111 122

	
112 123
  IF(WIN32 AND LEMON_HAVE_CPLEX)
113 124
    GET_TARGET_PROPERTY(TARGET_LOC mip_test LOCATION)
114 125
    GET_FILENAME_COMPONENT(TARGET_PATH ${TARGET_LOC} PATH)
115 126
    ADD_CUSTOM_COMMAND(TARGET mip_test POST_BUILD
116 127
      COMMAND ${CMAKE_COMMAND} -E copy ${CPLEX_BIN_DIR}/cplex91.dll ${TARGET_PATH}
117 128
    )
118 129
  ENDIF()
119 130
ENDIF()
120 131

	
121 132
FOREACH(TEST_NAME ${TESTS})
122 133
  IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
123 134
    ADD_EXECUTABLE(${TEST_NAME} ${TEST_NAME}.cc)
124 135
  ELSE()
125 136
    ADD_EXECUTABLE(${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_NAME}.cc)
126 137
  ENDIF()
127 138
  TARGET_LINK_LIBRARIES(${TEST_NAME} lemon)
128 139
  ADD_TEST(${TEST_NAME} ${TEST_NAME})
129 140
  ADD_DEPENDENCIES(check ${TEST_NAME})
130 141
ENDFOREACH()
Ignore white space 3221225472 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 36
	test/max_cardinality_search_test \
37 37
	test/max_clique_test \
38 38
	test/min_cost_arborescence_test \
39 39
	test/min_cost_flow_test \
40 40
	test/min_mean_cycle_test \
41
	test/nagamochi_ibaraki_test \
41 42
	test/path_test \
42 43
	test/planarity_test \
43 44
	test/preflow_test \
44 45
	test/radix_sort_test \
45 46
	test/random_test \
46 47
	test/suurballe_test \
47 48
	test/test_tools_fail \
48 49
	test/test_tools_pass \
49 50
	test/time_measure_test \
50 51
	test/unionfind_test
51 52

	
52 53
test_test_tools_pass_DEPENDENCIES = demo
53 54

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

	
61 62
TESTS += $(check_PROGRAMS)
62 63
XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
63 64

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