COIN-OR::LEMON - Graph Library

Ticket #397: 42a752f840ef.patch

File 42a752f840ef.patch, 32.2 KB (added by thoneyvazul, 14 years ago)
  • lemon/Makefile.am

    # HG changeset patch
    # User Antal Nemes <thoneyvazul@gmail.com>
    # Date 1289341823 -3600
    # Node ID 42a752f840eff75c22b340387c0024a7bef7c916
    # Parent  1937b6455b7d0cff4f1e21bdd7c5a66b4c1af1cf
    Port max. card. search alg. from svn -r3512 (#397) and (#56)
    
    diff --git a/lemon/Makefile.am b/lemon/Makefile.am
    a b  
    107107        lemon/matching.h \
    108108        lemon/math.h \
    109109        lemon/min_cost_arborescence.h \
     110        lemon/max_cardinality_search.h \
    110111        lemon/nauty_reader.h \
    111112        lemon/network_simplex.h \
    112113        lemon/pairing_heap.h \
  • new file lemon/max_cardinality_search.h

    diff --git a/lemon/max_cardinality_search.h b/lemon/max_cardinality_search.h
    new file mode 100644
    - +  
     1/* -*- C++ -*-
     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_MAX_CARDINALITY_SEARCH_H
     20#define LEMON_MAX_CARDINALITY_SEARCH_H
     21
     22
     23/// \ingroup auxalg
     24/// \file
     25/// \brief Maximum cardinality search in undirected digraphs.
     26
     27#include <lemon/bin_heap.h>
     28#include <lemon/bucket_heap.h>
     29
     30#include <lemon/error.h>
     31#include <lemon/maps.h>
     32
     33#include <functional>
     34
     35namespace lemon {
     36
     37  /// \brief Default traits class of MaxCardinalitySearch class.
     38  ///
     39  /// Default traits class of MaxCardinalitySearch class.
     40  /// \param Digraph Digraph type.
     41  /// \param CapacityMap Type of capacity map.
     42  template <typename GR, typename CAP>
     43  struct MaxCardinalitySearchDefaultTraits {
     44    /// The digraph type the algorithm runs on.
     45    typedef GR Digraph;
     46
     47    template <typename CM>
     48    struct CapMapSelector {
     49
     50      typedef CM CapacityMap;
     51
     52      static CapacityMap *createCapacityMap(const Digraph& g) {
     53        return new CapacityMap(g);
     54      }
     55    };
     56
     57    template <typename CM>
     58    struct CapMapSelector<ConstMap<CM, Const<int, 1> > > {
     59
     60      typedef ConstMap<CM, Const<int, 1> > CapacityMap;
     61
     62      static CapacityMap *createCapacityMap(const Digraph& g) {
     63        ignore_unused_variable_warning(g);
     64        return new CapacityMap;
     65      }
     66    };
     67
     68    /// \brief The type of the map that stores the arc capacities.
     69    ///
     70    /// The type of the map that stores the arc capacities.
     71    /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
     72    typedef typename CapMapSelector<CAP>::CapacityMap CapacityMap;
     73
     74    /// \brief The type of the capacity of the arcs.
     75    typedef typename CapacityMap::Value Value;
     76
     77    /// \brief Instantiates a CapacityMap.
     78    ///
     79    /// This function instantiates a \ref CapacityMap.
     80    /// \param digraph is the digraph, to which we would like to define
     81    /// the CapacityMap.
     82    static CapacityMap *createCapacityMap(const Digraph& digraph) {
     83      return CapMapSelector<CapacityMap>::createCapacityMap(digraph);
     84    }
     85
     86    /// \brief The cross reference type used by heap.
     87    ///
     88    /// The cross reference type used by heap.
     89    /// Usually it is \c Digraph::NodeMap<int>.
     90    typedef typename Digraph::template NodeMap<int> HeapCrossRef;
     91
     92    /// \brief Instantiates a HeapCrossRef.
     93    ///
     94    /// This function instantiates a \ref HeapCrossRef.
     95    /// \param digraph is the digraph, to which we would like to define the
     96    /// HeapCrossRef.
     97    static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
     98      return new HeapCrossRef(digraph);
     99    }
     100   
     101    template <typename CapacityMap>
     102    struct HeapSelector {
     103      template <typename Value, typename Ref>
     104      struct Selector {
     105        typedef BinHeap<Value, Ref, std::greater<Value> > Heap;
     106      };
     107    };
     108
     109    template <typename CapacityKey>
     110    struct HeapSelector<ConstMap<CapacityKey, Const<int, 1> > > {
     111      template <typename Value, typename Ref>
     112      struct Selector {
     113        typedef BucketHeap<Ref, false > Heap;
     114      };
     115    };
     116
     117    /// \brief The heap type used by MaxCardinalitySearch algorithm.
     118    ///
     119    /// The heap type used by MaxCardinalitySearch algorithm. It should
     120    /// maximalize the priorities. The default heap type is
     121    /// the \ref BinHeap, but it is specialized when the
     122    /// CapacityMap is ConstMap<Digraph::Node, Const<int, 1> >
     123    /// to BucketHeap.
     124    ///
     125    /// \sa MaxCardinalitySearch
     126    typedef typename HeapSelector<CapacityMap>
     127    ::template Selector<Value, HeapCrossRef>
     128    ::Heap Heap;
     129
     130    /// \brief Instantiates a Heap.
     131    ///
     132    /// This function instantiates a \ref Heap.
     133    /// \param crossref The cross reference of the heap.
     134    static Heap *createHeap(HeapCrossRef& crossref) {
     135      return new Heap(crossref);
     136    }
     137
     138    /// \brief The type of the map that stores whether a node is processed.
     139    ///
     140    /// The type of the map that stores whether a node is processed.
     141    /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
     142    /// By default it is a NullMap.
     143    typedef NullMap<typename Digraph::Node, bool> ProcessedMap;
     144
     145    /// \brief Instantiates a ProcessedMap.
     146    ///
     147    /// This function instantiates a \ref ProcessedMap.
     148    /// \param digraph is the digraph, to which
     149    /// we would like to define the \ref ProcessedMap
     150#ifdef DOXYGEN
     151    static ProcessedMap *createProcessedMap(const Digraph &digraph)
     152#else
     153    static ProcessedMap *createProcessedMap(const Digraph &)
     154#endif
     155    {
     156      return new ProcessedMap();
     157    }
     158
     159    /// \brief The type of the map that stores the cardinalities of the nodes.
     160    ///
     161    /// The type of the map that stores the cardinalities of the nodes.
     162    /// It must meet the \ref concepts::WriteMap "WriteMap" concept.
     163    typedef typename Digraph::template NodeMap<Value> CardinalityMap;
     164
     165    /// \brief Instantiates a CardinalityMap.
     166    ///
     167    /// This function instantiates a \ref CardinalityMap.
     168    /// \param digraph is the digraph, to which we would like to define the \ref
     169    /// CardinalityMap
     170    static CardinalityMap *createCardinalityMap(const Digraph &digraph) {
     171      return new CardinalityMap(digraph);
     172    }
     173
     174
     175  };
     176 
     177  /// \ingroup search
     178  ///
     179  /// \brief Maximum Cardinality Search algorithm class.
     180  ///
     181  /// This class provides an efficient implementation of Maximum Cardinality
     182  /// Search algorithm. The maximum cardinality search first chooses any
     183  /// node of the digraph. Then every time it chooses one unprocessed node
     184  /// with maximum cardinality, i.e the sum of capacities on out arcs to the nodes
     185  /// which were previusly processed.
     186  /// If there is a cut in the digraph the algorithm should choose
     187  /// again any unprocessed node of the digraph.
     188
     189  /// The arc capacities are passed to the algorithm using a
     190  /// \ref concepts::ReadMap "ReadMap", so it is easy to change it to any
     191  /// kind of capacity.
     192  ///
     193  /// The type of the capacity is determined by the \ref
     194  /// concepts::ReadMap::Value "Value" of the capacity map.
     195  ///
     196  /// It is also possible to change the underlying priority heap.
     197  ///
     198  ///
     199  /// \param GR The digraph type the algorithm runs on. The value of
     200  /// Digraph is not used directly by the search algorithm, it
     201  /// is only passed to \ref MaxCardinalitySearchDefaultTraits.
     202  /// \param CAP This read-only ArcMap determines the capacities of
     203  /// the arcs. It is read once for each arc, so the map may involve in
     204  /// relatively time consuming process to compute the arc capacity if
     205  /// it is necessary. The default map type is \ref
     206  /// ConstMap "ConstMap<concepts::Digraph::Arc, Const<int,1> >". The value
     207  /// of CapacityMap is not used directly by search algorithm, it is only
     208  /// passed to \ref MaxCardinalitySearchDefaultTraits. 
     209  /// \param TR Traits class to set various data types used by the
     210  /// algorithm.  The default traits class is
     211  /// \ref MaxCardinalitySearchDefaultTraits
     212  /// "MaxCardinalitySearchDefaultTraits<GR, CAP>". 
     213  /// See \ref MaxCardinalitySearchDefaultTraits
     214  /// for the documentation of a MaxCardinalitySearch traits class.
     215
     216#ifdef DOXYGEN
     217  template <typename GR, typename CAP, typename TR>
     218#else
     219  template <typename GR, typename CAP =
     220            ConstMap<typename GR::Arc, Const<int,1> >,
     221            typename TR =
     222            MaxCardinalitySearchDefaultTraits<GR, CAP> >
     223#endif
     224  class MaxCardinalitySearch {
     225  public:
     226
     227    typedef TR Traits;
     228    ///The type of the underlying digraph.
     229    typedef typename Traits::Digraph Digraph;
     230   
     231    ///The type of the capacity of the arcs.
     232    typedef typename Traits::CapacityMap::Value Value;
     233    ///The type of the map that stores the arc capacities.
     234    typedef typename Traits::CapacityMap CapacityMap;
     235    ///The type of the map indicating if a node is processed.
     236    typedef typename Traits::ProcessedMap ProcessedMap;
     237    ///The type of the map that stores the cardinalities of the nodes.
     238    typedef typename Traits::CardinalityMap CardinalityMap;
     239    ///The cross reference type used for the current heap.
     240    typedef typename Traits::HeapCrossRef HeapCrossRef;
     241    ///The heap type used by the algorithm. It maximizes the priorities.
     242    typedef typename Traits::Heap Heap;
     243  private:
     244    /// Pointer to the underlying digraph.
     245    const Digraph *_graph;
     246    /// Pointer to the capacity map
     247    const CapacityMap *_capacity;
     248    /// Indicates if \ref _capacity is locally allocated (\c true) or not.
     249    bool local_capacity;
     250    ///Pointer to the map of cardinality.
     251    CardinalityMap *_cardinality;
     252    ///Indicates if \ref _cardinality is locally allocated (\c true) or not.
     253    bool local_cardinality;
     254    ///Pointer to the map of processed status of the nodes.
     255    ProcessedMap *_processed;
     256    ///Indicates if \ref _processed is locally allocated (\c true) or not.
     257    bool local_processed;
     258    ///Pointer to the heap cross references.
     259    HeapCrossRef *_heap_cross_ref;
     260    ///Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not.
     261    bool local_heap_cross_ref;
     262    ///Pointer to the heap.
     263    Heap *_heap;
     264    ///Indicates if \ref _heap is locally allocated (\c true) or not.
     265    bool local_heap;
     266
     267  public :
     268
     269    typedef MaxCardinalitySearch Create;
     270 
     271    ///\name Named template parameters
     272
     273    ///@{
     274
     275    template <class T>
     276    struct DefCapacityMapTraits : public Traits {
     277      typedef T CapacityMap;
     278      static CapacityMap *createCapacityMap(const Digraph &) {
     279        LEMON_ASSERT(false,"Uninitialized parameter.");
     280        return 0;
     281      }
     282    };
     283    /// \brief \ref named-templ-param "Named parameter" for setting
     284    /// CapacityMap type
     285    ///
     286    /// \ref named-templ-param "Named parameter" for setting CapacityMap type
     287    ///
     288    template <class T>
     289    struct SetCapacityMap
     290      : public MaxCardinalitySearch<Digraph, CapacityMap,
     291                                    DefCapacityMapTraits<T> > {
     292      typedef MaxCardinalitySearch<Digraph, CapacityMap,
     293                                   DefCapacityMapTraits<T> > Create;
     294    };
     295
     296    template <class T>
     297    struct DefCardinalityMapTraits : public Traits {
     298      typedef T CardinalityMap;
     299      static CardinalityMap *createCardinalityMap(const Digraph &)
     300      {
     301        LEMON_ASSERT(false,"Uninitialized parameter.");
     302        return 0;
     303      }
     304    };
     305    /// \brief \ref named-templ-param "Named parameter" for setting
     306    /// CardinalityMap type
     307    ///
     308    /// \ref named-templ-param "Named parameter" for setting CardinalityMap
     309    /// type
     310    template <class T>
     311    struct SetCardinalityMap
     312      : public MaxCardinalitySearch<Digraph, CapacityMap,
     313                                    DefCardinalityMapTraits<T> > {
     314      typedef MaxCardinalitySearch<Digraph, CapacityMap,
     315                                   DefCardinalityMapTraits<T> > Create;
     316    };
     317   
     318    template <class T>
     319    struct DefProcessedMapTraits : public Traits {
     320      typedef T ProcessedMap;
     321      static ProcessedMap *createProcessedMap(const Digraph &) {
     322        LEMON_ASSERT(false,"Uninitialized parameter.");
     323        return 0;
     324      }
     325    };
     326    /// \brief \ref named-templ-param "Named parameter" for setting
     327    /// ProcessedMap type
     328    ///
     329    /// \ref named-templ-param "Named parameter" for setting ProcessedMap type
     330    ///
     331    template <class T>
     332    struct SetProcessedMap
     333      : public MaxCardinalitySearch<Digraph, CapacityMap,
     334                                    DefProcessedMapTraits<T> > {
     335      typedef MaxCardinalitySearch<Digraph, CapacityMap,
     336                                   DefProcessedMapTraits<T> > Create;
     337    };
     338   
     339    template <class H, class CR>
     340    struct DefHeapTraits : public Traits {
     341      typedef CR HeapCrossRef;
     342      typedef H Heap;
     343      static HeapCrossRef *createHeapCrossRef(const Digraph &) {
     344        LEMON_ASSERT(false,"Uninitialized parameter.");
     345        return 0;
     346      }
     347      static Heap *createHeap(HeapCrossRef &) {
     348        LEMON_ASSERT(false,"Uninitialized parameter.");
     349        return 0;
     350      }
     351    };
     352    /// \brief \ref named-templ-param "Named parameter" for setting heap
     353    /// and cross reference type
     354    ///
     355    /// \ref named-templ-param "Named parameter" for setting heap and cross
     356    /// reference type
     357    template <class H, class CR = typename Digraph::template NodeMap<int> >
     358    struct SetHeap
     359      : public MaxCardinalitySearch<Digraph, CapacityMap,
     360                                    DefHeapTraits<H, CR> > {
     361      typedef MaxCardinalitySearch< Digraph, CapacityMap,
     362                                    DefHeapTraits<H, CR> > Create;
     363    };
     364
     365    template <class H, class CR>
     366    struct DefStandardHeapTraits : public Traits {
     367      typedef CR HeapCrossRef;
     368      typedef H Heap;
     369      static HeapCrossRef *createHeapCrossRef(const Digraph &digraph) {
     370        return new HeapCrossRef(digraph);
     371      }
     372      static Heap *createHeap(HeapCrossRef &crossref) {
     373        return new Heap(crossref);
     374      }
     375    };
     376
     377    /// \brief \ref named-templ-param "Named parameter" for setting heap and
     378    /// cross reference type with automatic allocation
     379    ///
     380    /// \ref named-templ-param "Named parameter" for setting heap and cross
     381    /// reference type. It can allocate the heap and the cross reference
     382    /// object if the cross reference's constructor waits for the digraph as
     383    /// parameter and the heap's constructor waits for the cross reference.
     384    template <class H, class CR = typename Digraph::template NodeMap<int> >
     385    struct SetStandardHeap
     386      : public MaxCardinalitySearch<Digraph, CapacityMap,
     387                                    DefStandardHeapTraits<H, CR> > {
     388      typedef MaxCardinalitySearch<Digraph, CapacityMap,
     389                                   DefStandardHeapTraits<H, CR> >
     390      Create;
     391    };
     392   
     393    ///@}
     394
     395
     396  protected:
     397
     398    MaxCardinalitySearch() {}
     399
     400  public:     
     401   
     402    /// \brief Constructor.
     403    ///
     404    ///\param digraph the digraph the algorithm will run on.
     405    ///\param capacity the capacity map used by the algorithm.
     406    ///When no capacity map given, a constant 1 capacity map will
     407    ///be allocated.
     408#ifdef DOXYGEN
     409    MaxCardinalitySearch(const Digraph& digraph,
     410                         const CapacityMap& capacity=0 ) :
     411#else
     412    MaxCardinalitySearch(const Digraph& digraph,
     413                         const CapacityMap& capacity=*static_cast<const CapacityMap*>(0) ) :
     414#endif
     415      _graph(&digraph),
     416      _capacity(&capacity), local_capacity(false),
     417      _cardinality(0), local_cardinality(false),
     418      _processed(0), local_processed(false),
     419      _heap_cross_ref(0), local_heap_cross_ref(false),
     420      _heap(0), local_heap(false)
     421    { }
     422
     423    /// \brief Destructor.
     424    ~MaxCardinalitySearch() {
     425      if(local_capacity) delete _capacity;
     426      if(local_cardinality) delete _cardinality;
     427      if(local_processed) delete _processed;
     428      if(local_heap_cross_ref) delete _heap_cross_ref;
     429      if(local_heap) delete _heap;
     430    }
     431
     432    /// \brief Sets the capacity map.
     433    ///
     434    /// Sets the capacity map.
     435    /// \return <tt> (*this) </tt>
     436    MaxCardinalitySearch &capacityMap(const CapacityMap &m) {
     437      if (local_capacity) {
     438        delete _capacity;
     439        local_capacity=false;
     440      }
     441      _capacity=&m;
     442      return *this;
     443    }
     444
     445    /// \brief Returns a const reference to the capacity map.
     446    ///
     447    /// Returns a const reference to the capacity map used by
     448    /// the algorithm.
     449    const CapacityMap &capacityMap() const {
     450      return *_capacity;
     451    }
     452
     453    /// \brief Sets the map storing the cardinalities calculated by the
     454    /// algorithm.
     455    ///
     456    /// Sets the map storing the cardinalities calculated by the algorithm.
     457    /// If you don't use this function before calling \ref run(),
     458    /// it will allocate one. The destuctor deallocates this
     459    /// automatically allocated map, of course.
     460    /// \return <tt> (*this) </tt>
     461    MaxCardinalitySearch &cardinalityMap(CardinalityMap &m) {
     462      if(local_cardinality) {
     463        delete _cardinality;
     464        local_cardinality=false;
     465      }
     466      _cardinality = &m;
     467      return *this;
     468    }
     469
     470    /// \brief Sets the map storing the processed nodes.
     471    ///
     472    /// Sets the map storing the processed nodes.
     473    /// If you don't use this function before calling \ref run(),
     474    /// it will allocate one. The destuctor deallocates this
     475    /// automatically allocated map, of course.
     476    /// \return <tt> (*this) </tt>
     477    MaxCardinalitySearch &processedMap(ProcessedMap &m)
     478    {
     479      if(local_processed) {
     480        delete _processed;
     481        local_processed=false;
     482      }
     483      _processed = &m;
     484      return *this;
     485    }
     486
     487    /// \brief Returns a const reference to the cardinality map.
     488    ///
     489    /// Returns a const reference to the cardinality map used by
     490    /// the algorithm.
     491    const ProcessedMap &processedMap() const {
     492      return *_processed;
     493    }
     494
     495    /// \brief Sets the heap and the cross reference used by algorithm.
     496    ///
     497    /// Sets the heap and the cross reference used by algorithm.
     498    /// If you don't use this function before calling \ref run(),
     499    /// it will allocate one. The destuctor deallocates this
     500    /// automatically allocated map, of course.
     501    /// \return <tt> (*this) </tt>
     502    MaxCardinalitySearch &heap(Heap& hp, HeapCrossRef &cr) {
     503      if(local_heap_cross_ref) {
     504        delete _heap_cross_ref;
     505        local_heap_cross_ref = false;
     506      }
     507      _heap_cross_ref = &cr;
     508      if(local_heap) {
     509        delete _heap;
     510        local_heap = false;
     511      }
     512      _heap = &hp;
     513      return *this;
     514    }
     515
     516    /// \brief Returns a const reference to the heap.
     517    ///
     518    /// Returns a const reference to the heap used by
     519    /// the algorithm.
     520    const Heap &heap() const {
     521      return *_heap;
     522    }
     523
     524    /// \brief Returns a const reference to the cross reference.
     525    ///
     526    /// Returns a const reference to the cross reference
     527    /// of the heap.
     528    const HeapCrossRef &heapCrossRef() const {
     529      return *_heap_cross_ref;
     530    }
     531
     532  private:
     533
     534    typedef typename Digraph::Node Node;
     535    typedef typename Digraph::NodeIt NodeIt;
     536    typedef typename Digraph::Arc Arc;
     537    typedef typename Digraph::InArcIt InArcIt;
     538
     539    void create_maps() {
     540      if(!_capacity) {
     541        local_capacity = true;
     542        _capacity = Traits::createCapacityMap(*_graph);
     543      }
     544      if(!_cardinality) {
     545        local_cardinality = true;
     546        _cardinality = Traits::createCardinalityMap(*_graph);
     547      }
     548      if(!_processed) {
     549        local_processed = true;
     550        _processed = Traits::createProcessedMap(*_graph);
     551      }
     552      if (!_heap_cross_ref) {
     553        local_heap_cross_ref = true;
     554        _heap_cross_ref = Traits::createHeapCrossRef(*_graph);
     555      }
     556      if (!_heap) {
     557        local_heap = true;
     558        _heap = Traits::createHeap(*_heap_cross_ref);
     559      }
     560    }
     561   
     562    void finalizeNodeData(Node node, Value capacity) {
     563      _processed->set(node, true);
     564      _cardinality->set(node, capacity);
     565    }
     566
     567  public:
     568    /// \name Execution control
     569    /// The simplest way to execute the algorithm is to use
     570    /// one of the member functions called \ref run().
     571    /// \n
     572    /// If you need more control on the execution,
     573    /// first you must call \ref init(), then you can add several source nodes
     574    /// with \ref addSource().
     575    /// Finally \ref start() will perform the computation.
     576
     577    ///@{
     578
     579    /// \brief Initializes the internal data structures.
     580    ///
     581    /// Initializes the internal data structures, and clears the heap.
     582    void init() {
     583      create_maps();
     584      _heap->clear();
     585      for (NodeIt it(*_graph) ; it != INVALID ; ++it) {
     586        _processed->set(it, false);
     587        _heap_cross_ref->set(it, Heap::PRE_HEAP);
     588      }
     589    }
     590   
     591    /// \brief Adds a new source node.
     592    ///
     593    /// Adds a new source node to the priority heap.
     594    ///
     595    /// It checks if the node has not yet been added to the heap.
     596    void addSource(Node source, Value capacity = 0) {
     597      if(_heap->state(source) == Heap::PRE_HEAP) {
     598        _heap->push(source, capacity);
     599      }
     600    }
     601   
     602    /// \brief Processes the next node in the priority heap
     603    ///
     604    /// Processes the next node in the priority heap.
     605    ///
     606    /// \return The processed node.
     607    ///
     608    /// \warning The priority heap must not be empty!
     609    Node processNextNode() {
     610      Node node = _heap->top();
     611      finalizeNodeData(node, _heap->prio());
     612      _heap->pop();
     613     
     614      for (InArcIt it(*_graph, node); it != INVALID; ++it) {
     615        Node source = _graph->source(it);
     616        switch (_heap->state(source)) {
     617        case Heap::PRE_HEAP:
     618          _heap->push(source, (*_capacity)[it]);
     619          break;
     620        case Heap::IN_HEAP:
     621          _heap->decrease(source, (*_heap)[source] + (*_capacity)[it]);
     622          break;
     623        case Heap::POST_HEAP:
     624          break;
     625        }
     626      }
     627      return node;
     628    }
     629
     630    /// \brief Next node to be processed.
     631    ///
     632    /// Next node to be processed.
     633    ///
     634    /// \return The next node to be processed or INVALID if the
     635    /// priority heap is empty.
     636    Node nextNode() {
     637      return !_heap->empty() ? _heap->top() : INVALID;
     638    }
     639 
     640    /// \brief Returns \c false if there are nodes
     641    /// to be processed in the priority heap
     642    ///
     643    /// Returns \c false if there are nodes
     644    /// to be processed in the priority heap
     645    bool emptyHeap() { return _heap->empty(); }
     646    /// \brief Returns the number of the nodes to be processed
     647    /// in the priority heap
     648    ///
     649    /// Returns the number of the nodes to be processed in the priority heap
     650    int heapSize() { return _heap->size(); }
     651   
     652    /// \brief Executes the algorithm.
     653    ///
     654    /// Executes the algorithm.
     655    ///
     656    ///\pre init() must be called and at least one node should be added
     657    /// with addSource() before using this function.
     658    ///
     659    /// This method runs the Maximum Cardinality Search algorithm from the
     660    /// source node(s).
     661    void start() {
     662      while ( !_heap->empty() ) processNextNode();
     663    }
     664   
     665    /// \brief Executes the algorithm until \c dest is reached.
     666    ///
     667    /// Executes the algorithm until \c dest is reached.
     668    ///
     669    /// \pre init() must be called and at least one node should be added
     670    /// with addSource() before using this function.
     671    ///
     672    /// This method runs the %MaxCardinalitySearch algorithm from the source
     673    /// nodes.
     674    void start(Node dest) {
     675      while ( !_heap->empty() && _heap->top()!=dest ) processNextNode();
     676      if ( !_heap->empty() ) finalizeNodeData(_heap->top(), _heap->prio());
     677    }
     678   
     679    /// \brief Executes the algorithm until a condition is met.
     680    ///
     681    /// Executes the algorithm until a condition is met.
     682    ///
     683    /// \pre init() must be called and at least one node should be added
     684    /// with addSource() before using this function.
     685    ///
     686    /// \param nm must be a bool (or convertible) node map. The algorithm
     687    /// will stop when it reaches a node \c v with <tt>nm[v]==true</tt>.
     688    template <typename NodeBoolMap>
     689    void start(const NodeBoolMap &nm) {
     690      while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode();
     691      if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio());
     692    }
     693   
     694    /// \brief Runs the maximum cardinality search algorithm from node \c s.
     695    ///
     696    /// This method runs the %MaxCardinalitySearch algorithm from a root
     697    /// node \c s.
     698    ///
     699    ///\note d.run(s) is just a shortcut of the following code.
     700    ///\code
     701    ///  d.init();
     702    ///  d.addSource(s);
     703    ///  d.start();
     704    ///\endcode
     705    void run(Node s) {
     706      init();
     707      addSource(s);
     708      start();
     709    }
     710
     711    /// \brief Runs the maximum cardinality search algorithm for the
     712    /// whole digraph.
     713    ///
     714    /// This method runs the %MaxCardinalitySearch algorithm from all
     715    /// unprocessed node of the digraph.
     716    ///
     717    ///\note d.run(s) is just a shortcut of the following code.
     718    ///\code
     719    ///  d.init();
     720    ///  for (NodeIt it(digraph); it != INVALID; ++it) {
     721    ///    if (!d.reached(it)) {
     722    ///      d.addSource(s);
     723    ///      d.start();
     724    ///    }
     725    ///  }
     726    ///\endcode
     727    void run() {
     728      init();
     729      for (NodeIt it(*_graph); it != INVALID; ++it) {
     730        if (!reached(it)) {
     731          addSource(it);
     732          start();
     733        }
     734      }
     735    }
     736   
     737    ///@}
     738
     739    /// \name Query Functions
     740    /// The results of the maximum cardinality search algorithm can be
     741    /// obtained using these functions.
     742    /// \n
     743    /// Before the use of these functions, either run() or start() must be
     744    /// called.
     745   
     746    ///@{
     747
     748    /// \brief The cardinality of a node.
     749    ///
     750    /// Returns the cardinality of a node.
     751    /// \pre \ref run() must be called before using this function.
     752    /// \warning If node \c v in unreachable from the root the return value
     753    /// of this funcion is undefined.
     754    Value cardinality(Node node) const { return (*_cardinality)[node]; }
     755
     756    /// \brief The current cardinality of a node.
     757    ///
     758    /// Returns the current cardinality of a node.
     759    /// \pre the given node should be reached but not processed
     760    Value currentCardinality(Node node) const { return (*_heap)[node]; }
     761
     762    /// \brief Returns a reference to the NodeMap of cardinalities.
     763    ///
     764    /// Returns a reference to the NodeMap of cardinalities. \pre \ref run()
     765    /// must be called before using this function.
     766    const CardinalityMap &cardinalityMap() const { return *_cardinality;}
     767 
     768    /// \brief Checks if a node is reachable from the root.
     769    ///
     770    /// Returns \c true if \c v is reachable from the root.
     771    /// \warning The source nodes are initated as unreached.
     772    /// \pre \ref run() must be called before using this function.
     773    bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; }
     774
     775    /// \brief Checks if a node is processed.
     776    ///
     777    /// Returns \c true if \c v is processed, i.e. the shortest
     778    /// path to \c v has already found.
     779    /// \pre \ref run() must be called before using this function.
     780    bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; }
     781   
     782    ///@}
     783  };
     784
     785}
     786
     787#endif
  • test/CMakeLists.txt

    diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
    a b  
    3131  kruskal_test
    3232  maps_test
    3333  matching_test
     34  max_cardinality_search_test
    3435  max_clique_test
    3536  min_cost_arborescence_test
    3637  min_cost_flow_test
  • test/Makefile.am

    diff --git a/test/Makefile.am b/test/Makefile.am
    a b  
    3333        test/kruskal_test \
    3434        test/maps_test \
    3535        test/matching_test \
     36        test/max_cardinality_search_test \
    3637        test/max_clique_test \
    3738        test/min_cost_arborescence_test \
    3839        test/min_cost_flow_test \
     
    8586test_maps_test_SOURCES = test/maps_test.cc
    8687test_mip_test_SOURCES = test/mip_test.cc
    8788test_matching_test_SOURCES = test/matching_test.cc
     89test_max_cardinality_search_test_SOURCES = test/max_cardinality_search_test.cc
    8890test_max_clique_test_SOURCES = test/max_clique_test.cc
    8991test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
    9092test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
  • new file test/max_cardinality_search_test.cc

    diff --git a/test/max_cardinality_search_test.cc b/test/max_cardinality_search_test.cc
    new file mode 100644
    - +  
     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 <iostream>
     20
     21#include "test_tools.h"
     22#include <lemon/smart_graph.h>
     23#include <lemon/max_cardinality_search.h>
     24#include <lemon/concepts/digraph.h>
     25#include <lemon/concepts/maps.h>
     26#include <lemon/concepts/heap.h>
     27#include <lemon/lgf_reader.h>
     28
     29using namespace lemon;
     30using namespace std;
     31
     32char test_lgf[] =
     33  "@nodes\n"
     34  "label\n"
     35  "0\n"
     36  "1\n"
     37  "2\n"
     38  "3\n"
     39  "@arcs\n"
     40  "    label capacity\n"
     41  "0 1 0     2\n"
     42  "1 0 1     2\n"
     43  "2 1 2     1\n"
     44  "2 3 3     3\n"
     45  "3 2 4     3\n"
     46  "3 1 5     5\n"
     47  "@attributes\n"
     48  "s 0\n"
     49  "x 1\n"
     50  "y 2\n"
     51  "z 3\n";
     52
     53void checkMaxCardSearchCompile() {
     54
     55  typedef concepts::Digraph Digraph;
     56  typedef int Value;
     57  typedef Digraph::Node Node;
     58  typedef Digraph::Arc Arc;
     59  typedef concepts::ReadMap<Arc,Value> CapMap;
     60  typedef concepts::ReadWriteMap<Node,Value> CardMap;
     61  typedef concepts::ReadWriteMap<Node,bool> ProcMap;
     62  typedef Digraph::NodeMap<int> HeapCrossRef;
     63
     64  Digraph g;
     65  Node n,s;
     66  CapMap cap;
     67  CardMap card;
     68  ProcMap proc;
     69  HeapCrossRef crossref(g);
     70 
     71  typedef MaxCardinalitySearch<Digraph,CapMap>
     72    ::SetCapacityMap<CapMap>
     73    ::SetCardinalityMap<CardMap>
     74    ::SetProcessedMap<ProcMap>
     75    ::SetStandardHeap<BinHeap<Value,HeapCrossRef> >
     76    ::Create MaxCardType;
     77
     78  MaxCardType maxcard(g,cap);
     79  const MaxCardType& const_maxcard = maxcard;
     80
     81  const MaxCardType::Heap& heap_const = const_maxcard.heap();
     82  MaxCardType::Heap& heap = const_cast<MaxCardType::Heap&>(heap_const);
     83  maxcard.heap(heap,crossref);
     84 
     85  maxcard.capacityMap(cap).cardinalityMap(card).processedMap(proc);
     86
     87  maxcard.init();
     88  maxcard.addSource(s);
     89  n = maxcard.nextNode();
     90   maxcard.processNextNode();
     91   maxcard.start();
     92   maxcard.run(s);
     93   maxcard.run();
     94 }
     95
     96 void checkWithIntMap( std::istringstream& input)
     97 {
     98   typedef SmartDigraph Digraph;
     99   typedef Digraph::Node Node;
     100   typedef Digraph::ArcMap<int> CapMap;
     101
     102   Digraph g;
     103   Node s,x,y,z,a;
     104   CapMap cap(g);
     105
     106   DigraphReader<Digraph>(g,input).
     107     arcMap("capacity", cap).
     108     node("s",s).
     109     node("x",x).
     110     node("y",y).
     111     node("z",z).
     112     run();
     113
     114   MaxCardinalitySearch<Digraph,CapMap> maxcard(g,cap);
     115
     116   maxcard.init();
     117   maxcard.addSource(s);
     118   maxcard.start(x);
     119
     120   check(maxcard.processed(s) and !maxcard.processed(x) and
     121         !maxcard.processed(y), "Wrong processed()!");
     122
     123   a=maxcard.nextNode();
     124   check(maxcard.processNextNode()==a,
     125         "Wrong nextNode() or processNextNode() return value!");
     126
     127   check(maxcard.processed(a), "Wrong processNextNode()!");
     128
     129   maxcard.start();
     130   check(maxcard.cardinality(x)==2 and maxcard.cardinality(y)>=4,
     131         "Wrong cardinalities!");
     132 }
     133
     134 void checkWithConst1Map(std::istringstream &input) {
     135   typedef SmartDigraph Digraph;
     136   typedef Digraph::Node Node;
     137
     138   Digraph g;
     139   Node s,x,y,z;
     140
     141  DigraphReader<Digraph>(g,input).
     142    node("s",s).
     143    node("x",x).
     144    node("y",y).
     145    node("z",z).
     146    run();
     147
     148  MaxCardinalitySearch<Digraph> maxcard(g);
     149  maxcard.run(s);
     150  check(maxcard.cardinality(x)==1 &&
     151        maxcard.cardinality(y)+maxcard.cardinality(z)==3,
     152        "Wrong cardinalities!");
     153}
     154
     155int main() {
     156
     157  std::istringstream input1(test_lgf);
     158  checkWithIntMap(input1);
     159
     160  std::istringstream input2(test_lgf);
     161  checkWithConst1Map(input2);
     162}