[Lemon-commits] [lemon_svn] deba: r2652 - hugo/trunk/lemon

Lemon SVN svn at lemon.cs.elte.hu
Mon Nov 6 20:54:10 CET 2006


Author: deba
Date: Mon Mar 27 10:12:01 2006
New Revision: 2652

Added:
   hugo/trunk/lemon/min_cost_arborescence.h
Modified:
   hugo/trunk/lemon/Makefile.am

Log:
Minimum Cost Arborescence algorithm 



Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am	(original)
+++ hugo/trunk/lemon/Makefile.am	Mon Mar 27 10:12:01 2006
@@ -59,6 +59,7 @@
 	matrix_maps.h \
 	map_iterator.h \
 	max_matching.h \
+	min_cost_arborescence.h \
 	min_cost_flow.h \
 	min_cut.h \
 	suurballe.h \

Added: hugo/trunk/lemon/min_cost_arborescence.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/min_cost_arborescence.h	Mon Mar 27 10:12:01 2006
@@ -0,0 +1,561 @@
+/* -*- C++ -*-
+ *
+ * This file is a part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2003-2006
+ * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
+ * (Egervary Research Group on Combinatorial Optimization, EGRES).
+ *
+ * Permission to use, modify and distribute this software is granted
+ * provided that this copyright notice appears in all copies. For
+ * precise terms see the accompanying LICENSE file.
+ *
+ * This software is provided "AS IS" with no warranty of any kind,
+ * express or implied, and with no claim as to its suitability for any
+ * purpose.
+ *
+ */
+
+#ifndef LEMON_MIN_COST_ARBORESCENCE_H
+#define LEMON_MIN_COST_ARBORESCENCE_H
+
+///\ingroup spantree
+///\file
+///\brief Minimum Cost Arborescence algorithm.
+
+#include <vector>
+
+#include <lemon/list_graph.h>
+
+namespace lemon {
+
+
+  /// \brief Default traits class of MinCostArborescence class.
+  /// 
+  /// Default traits class of MinCostArborescence class.
+  /// \param _Graph Graph type.
+  /// \param _CostMap Type of cost map.
+  template <class _Graph, class _CostMap>
+  struct MinCostArborescenceDefaultTraits{
+
+    /// \brief The graph type the algorithm runs on. 
+    typedef _Graph Graph;
+
+    /// \brief The type of the map that stores the edge costs.
+    ///
+    /// The type of the map that stores the edge costs.
+    /// It must meet the \ref concept::ReadMap "ReadMap" concept.
+    typedef _CostMap CostMap;
+
+    /// \brief The value type of the costs.
+    ///
+    /// The value type of the costs.
+    typedef typename CostMap::Value Value;
+
+    /// \brief The type of the map that stores which edges are 
+    /// in the arborescence.
+    ///
+    /// The type of the map that stores which edges are in the arborescence.
+    /// It must meet the \ref concept::ReadWriteMap "ReadWriteMap" concept.
+    /// Initially it will be setted to false on each edge. The algorithm
+    /// may set each value one time to true and maybe after it to false again.
+    /// Therefore you cannot use maps like BackInserteBoolMap with this
+    /// algorithm.   
+    typedef typename Graph::template EdgeMap<bool> ArborescenceMap; 
+
+    /// \brief Instantiates a ArborescenceMap.
+    ///
+    /// This function instantiates a \ref ArborescenceMap. 
+    /// \param _graph is the graph, to which we would like to define the 
+    /// ArborescenceMap.
+    static ArborescenceMap *createArborescenceMap(const Graph &_graph){
+      return new ArborescenceMap(_graph);
+    }
+
+  };
+
+  /// \ingroup spantree
+  ///
+  /// \brief %MinCostArborescence algorithm class.
+  ///
+  /// This class provides an efficient implementation of 
+  /// %MinCostArborescence algorithm. The arborescence is a tree 
+  /// which is directed from a given source node of the graph. One or
+  /// more sources should be given for the algorithm and it will calculate
+  /// the minimum cost subgraph which are union of arborescences with the
+  /// given sources and spans all the nodes which are reachable from the
+  /// sources. The time complexity of the algorithm is O(n^2 + e).
+  ///
+  /// \param _Graph The graph type the algorithm runs on. The default value
+  /// is \ref ListGraph. The value of _Graph is not used directly by
+  /// MinCostArborescence, it is only passed to 
+  /// \ref MinCostArborescenceDefaultTraits.
+  /// \param _CostMap This read-only EdgeMap determines the costs of the
+  /// edges. It is read once for each edge, so the map may involve in
+  /// relatively time consuming process to compute the edge cost if
+  /// it is necessary. The default map type is \ref
+  /// concept::StaticGraph::EdgeMap "Graph::EdgeMap<int>".  The value
+  /// of _CostMap is not used directly by MinCostArborescence, 
+  /// it is only passed to \ref MinCostArborescenceDefaultTraits.  
+  /// \param _Traits Traits class to set various data types used 
+  /// by the algorithm.  The default traits class is 
+  /// \ref MinCostArborescenceDefaultTraits
+  /// "MinCostArborescenceDefaultTraits<_Graph,_CostMap>".  See \ref
+  /// MinCostArborescenceDefaultTraits for the documentation of a 
+  /// MinCostArborescence traits class.
+  ///
+  /// \author Balazs Dezso
+#ifndef DOXYGEN
+  template <typename _Graph = ListGraph, 
+            typename _CostMap = typename _Graph::template EdgeMap<int>,
+            typename _Traits = 
+            MinCostArborescenceDefaultTraits<_Graph, _CostMap> >
+#else 
+  template <typename _Graph, typename _CostMap, typedef _Traits>
+#endif
+  class MinCostArborescence {
+  public:
+
+    /// \brief \ref Exception for uninitialized parameters.
+    ///
+    /// This error represents problems in the initialization
+    /// of the parameters of the algorithms.    
+    class UninitializedParameter : public lemon::UninitializedParameter {
+    public:
+      virtual const char* exceptionName() const {
+	return "lemon::MinCostArborescence::UninitializedParameter";
+      }
+    };
+
+    /// The traits.
+    typedef _Traits Traits;
+    /// The type of the underlying graph.
+    typedef typename Traits::Graph Graph;
+    /// The type of the map that stores the edge costs.
+    typedef typename Traits::CostMap CostMap;
+    ///The type of the costs of the edges.
+    typedef typename Traits::Value Value;
+    ///The type of the map that stores which edges are in the arborescence.
+    typedef typename Traits::ArborescenceMap ArborescenceMap;
+
+  protected:
+
+    typedef typename Graph::Node Node;
+    typedef typename Graph::Edge Edge;
+    typedef typename Graph::NodeIt NodeIt;
+    typedef typename Graph::EdgeIt EdgeIt;
+    typedef typename Graph::InEdgeIt InEdgeIt;
+    typedef typename Graph::OutEdgeIt OutEdgeIt;
+
+    struct CostEdge {
+
+      Edge edge;
+      Value value;
+
+      CostEdge() {}
+      CostEdge(Edge _edge, Value _value) : edge(_edge), value(_value) {}
+
+    };
+
+    const Graph* graph;
+    const CostMap* cost;
+
+    ArborescenceMap* _arborescence_map;
+    bool local_arborescence_map;
+
+    typedef typename Graph::template NodeMap<int> LevelMap;
+    LevelMap *_level;
+
+    typedef typename Graph::template NodeMap<CostEdge> CostEdgeMap;
+    CostEdgeMap *_cost_edges; 
+
+    struct StackLevel {
+
+      std::vector<CostEdge> edges;
+      int node_level;
+
+    };
+
+    std::vector<StackLevel> level_stack;    
+    std::vector<Node> queue;
+
+    int node_counter;
+
+  public:
+
+    /// \name Named template parameters
+
+    /// @{
+
+    template <class T>
+    struct DefArborescenceMapTraits : public Traits {
+      typedef T ArborescenceMap;
+      static ArborescenceMap *createArborescenceMap(const Graph &)
+      {
+	throw UninitializedParameter();
+      }
+    };
+
+    /// \brief \ref named-templ-param "Named parameter" for 
+    /// setting ArborescenceMap type
+    ///
+    /// \ref named-templ-param "Named parameter" for setting 
+    /// ArborescenceMap type
+    template <class T>
+    struct DefArborescenceMap 
+      : public MinCostArborescence<Graph, CostMap,
+                                   DefArborescenceMapTraits<T> > {
+      typedef MinCostArborescence<Graph, CostMap, 
+                                   DefArborescenceMapTraits<T> > Create;
+    };
+    
+    /// @}
+
+    /// \brief Constructor.
+    ///
+    /// \param _graph The graph the algorithm will run on.
+    /// \param _cost The cost map used by the algorithm.
+    MinCostArborescence(const Graph& _graph, const CostMap& _cost) 
+      : graph(&_graph), cost(&_cost),
+        _arborescence_map(0), local_arborescence_map(false), 
+        _level(0), _cost_edges(0) {}
+
+    /// \brief Destructor.
+    ~MinCostArborescence() {
+      destroyStructures();
+    }
+
+    /// \brief Sets the arborescence map.
+    /// 
+    /// Sets the arborescence map.
+    /// \return \c (*this)
+    MinCostArborescence& arborescenceMap(ArborescenceMap& m) {
+      _arborescence_map = &m;
+      return *this;
+    }
+
+    /// \name Query Functions
+    /// The result of the %MinCostArborescence algorithm can be obtained 
+    /// using these functions.\n
+    /// Before the use of these functions,
+    /// either run() or start() must be called.
+    
+    /// @{
+
+    /// \brief Returns a reference to the arborescence map.
+    ///
+    /// Returns a reference to the arborescence map.
+    const ArborescenceMap& arborescenceMap() const {
+      return *_arborescence_map;
+    }
+
+    /// \brief Returns true if the edge is in the arborescence.
+    ///
+    /// Returns true if the edge is in the arborescence.
+    /// \param edge The edge of the graph.
+    /// \pre \ref run() must be called before using this function.
+    bool arborescenceEdge(Edge edge) const {
+      return (*_arborescence_map)[edge];
+    }
+ 
+    /// \brief Returns the cost of the arborescence.
+    ///
+    /// Returns the cost of the arborescence.
+   Value arborescenceCost() const {
+      Value sum = 0;
+      for (EdgeIt it(*graph); it != INVALID; ++it) {
+        if (arborescenceEdge(it)) {
+          sum += (*cost)[it];
+        }
+      }
+      return sum;
+    }
+
+    /// @}
+    
+    /// \name Execution control
+    /// The simplest way to execute the algorithm is to use
+    /// one of the member functions called \c run(...). \n
+    /// If you need more control on the execution,
+    /// first you must call \ref init(), then you can add several 
+    /// source nodes with \ref addSource().
+    /// Finally \ref start() will perform the actual path
+    /// computation.
+
+    ///@{
+
+    /// \brief Initializes the internal data structures.
+    ///
+    /// Initializes the internal data structures.
+    ///
+    void init() {
+      initStructures();
+      for (NodeIt it(*graph); it != INVALID; ++it) {
+        (*_cost_edges)[it].edge = INVALID;
+        (*_level)[it] = -3; 
+      }
+      for (EdgeIt it(*graph); it != INVALID; ++it) {
+        _arborescence_map->set(it, false);
+      }
+    }
+
+    /// \brief Adds a new source node.
+    ///
+    /// Adds a new source node to the algorithm.
+    void addSource(Node source) {
+      std::vector<Node> nodes;
+      nodes.push_back(source);
+      while (!nodes.empty()) {
+        Node node = nodes.back();
+        nodes.pop_back();
+        for (OutEdgeIt it(*graph, node); it != INVALID; ++it) {
+          if ((*_level)[graph->target(it)] == -3) {
+            (*_level)[graph->target(it)] = -2;
+            nodes.push_back(graph->target(it));
+            queue.push_back(graph->target(it));
+          }
+        }
+      }
+      (*_level)[source] = -1;
+    }
+
+    /// \brief Processes the next node in the priority queue.
+    ///
+    /// Processes the next node in the priority queue.
+    ///
+    /// \return The processed node.
+    ///
+    /// \warning The queue must not be empty!
+    Node processNextNode() {
+      node_counter = 0;
+      Node node = queue.back();
+      queue.pop_back();
+      if ((*_level)[node] == -2) {
+        Edge edge = prepare(node);
+        while ((*_level)[graph->source(edge)] != -1) {
+          if ((*_level)[graph->source(edge)] >= 0) {
+            edge = contract(bottom((*_level)[graph->source(edge)]));
+          } else {
+            edge = prepare(graph->source(edge));
+          }
+        }
+        finalize(graph->target(edge));
+        level_stack.clear();        
+      }
+      return node;
+    }
+
+    /// \brief Returns the number of the nodes to be processed.
+    ///
+    /// Returns the number of the nodes to be processed.
+    int queueSize() const {
+      return queue.size();
+    }
+
+    /// \brief Returns \c false if there are nodes to be processed.
+    ///
+    /// Returns \c false if there are nodes to be processed.
+    bool emptyQueue() const {
+      return queue.empty();
+    }
+
+    /// \brief Executes the algorithm.
+    ///
+    /// Executes the algorithm.
+    ///
+    /// \pre init() must be called and at least one node should be added
+    /// with addSource() before using this function.
+    ///
+    ///\note mca.start() is just a shortcut of the following code.
+    ///\code
+    ///while (!mca.emptyQueue()) {
+    ///  mca.processNextNode();
+    ///}
+    ///\endcode
+    void start() {
+      while (!emptyQueue()) {
+        processNextNode();
+      }
+    }
+
+    /// \brief Runs %MinCostArborescence algorithm from node \c s.
+    /// 
+    /// This method runs the %MinCostArborescence algorithm from 
+    /// a root node \c s.
+    ///
+    ///\note mca.run(s) is just a shortcut of the following code.
+    ///\code
+    ///mca.init();
+    ///mca.addSource(s);
+    ///mca.start();
+    ///\endcode
+    void run(Node node) {
+      init();
+      addSource(node);
+      start();
+    }
+
+    ///@}
+
+  protected:
+
+    void initStructures() {
+      if (!_arborescence_map) {
+        local_arborescence_map = true;
+        _arborescence_map = Traits::createArborescenceMap(*graph);
+      }
+      if (!_level) {
+        _level = new LevelMap(*graph);
+      }
+      if (!_cost_edges) {
+        _cost_edges = new CostEdgeMap(*graph);
+      }
+    }
+
+    void destroyStructures() {
+      if (_level) {
+        delete _level;
+      }
+      if (!_cost_edges) {
+        delete _cost_edges;
+      }
+      if (local_arborescence_map) {
+        delete _arborescence_map;
+      }
+    }
+
+    Edge prepare(Node node) {
+      std::vector<Node> nodes;
+      (*_level)[node] = node_counter;
+      for (InEdgeIt it(*graph, node); it != INVALID; ++it) {
+        Edge edge = it;
+        Value value = (*cost)[it];
+        if (graph->source(edge) == node || 
+            (*_level)[graph->source(edge)] == -3) continue;
+        if ((*_cost_edges)[graph->source(edge)].edge == INVALID) {
+          (*_cost_edges)[graph->source(edge)].edge = edge;
+          (*_cost_edges)[graph->source(edge)].value = value;
+          nodes.push_back(graph->source(edge));
+        } else {
+          if ((*_cost_edges)[graph->source(edge)].value > value) {
+            (*_cost_edges)[graph->source(edge)].edge = edge;
+            (*_cost_edges)[graph->source(edge)].value = value;
+          }
+        }      
+      }
+      CostEdge minimum = (*_cost_edges)[nodes[0]]; 
+      for (int i = 1; i < (int)nodes.size(); ++i) {
+        if ((*_cost_edges)[nodes[i]].value < minimum.value) {
+          minimum = (*_cost_edges)[nodes[i]];
+        }
+      }
+      StackLevel level;
+      level.node_level = node_counter;
+      for (int i = 0; i < (int)nodes.size(); ++i) {
+        (*_cost_edges)[nodes[i]].value -= minimum.value;
+        level.edges.push_back((*_cost_edges)[nodes[i]]);
+        (*_cost_edges)[nodes[i]].edge = INVALID;
+      }
+      level_stack.push_back(level);
+      ++node_counter;
+      _arborescence_map->set(minimum.edge, true);
+      return minimum.edge;
+    }
+  
+    Edge contract(int node_bottom) {
+      std::vector<Node> nodes;
+      while (!level_stack.empty() && 
+             level_stack.back().node_level >= node_bottom) {
+        for (int i = 0; i < (int)level_stack.back().edges.size(); ++i) {
+          Edge edge = level_stack.back().edges[i].edge;
+          Value value = level_stack.back().edges[i].value;
+          if ((*_level)[graph->source(edge)] >= node_bottom) continue;
+          if ((*_cost_edges)[graph->source(edge)].edge == INVALID) {
+            (*_cost_edges)[graph->source(edge)].edge = edge;
+            (*_cost_edges)[graph->source(edge)].value = value;
+            nodes.push_back(graph->source(edge));
+          } else {
+            if ((*_cost_edges)[graph->source(edge)].value > value) {
+              (*_cost_edges)[graph->source(edge)].edge = edge;
+              (*_cost_edges)[graph->source(edge)].value = value;
+            }
+          }
+        }
+        level_stack.pop_back();
+      }
+      CostEdge minimum = (*_cost_edges)[nodes[0]]; 
+      for (int i = 1; i < (int)nodes.size(); ++i) {
+        if ((*_cost_edges)[nodes[i]].value < minimum.value) {
+          minimum = (*_cost_edges)[nodes[i]];
+        }
+      }
+      StackLevel level;
+      level.node_level = node_bottom;
+      for (int i = 0; i < (int)nodes.size(); ++i) {
+        (*_cost_edges)[nodes[i]].value -= minimum.value;
+        level.edges.push_back((*_cost_edges)[nodes[i]]);
+        (*_cost_edges)[nodes[i]].edge = INVALID;
+      }
+      level_stack.push_back(level);
+      _arborescence_map->set(minimum.edge, true);
+      return minimum.edge;
+    }
+
+    int bottom(int level) {
+      int k = level_stack.size() - 1;
+      while (level_stack[k].node_level > level) {
+        --k;
+      }
+      return level_stack[k].node_level;
+    }
+
+    void finalize(Node source) {
+      std::vector<Node> nodes;
+      nodes.push_back(source);
+      while (!nodes.empty()) {
+        Node node = nodes.back();
+        nodes.pop_back();
+        for (OutEdgeIt it(*graph, node); it != INVALID; ++it) {
+          if ((*_level)[graph->target(it)] >= 0 && (*_arborescence_map)[it]) {
+            (*_level)[graph->target(it)] = -1;
+            nodes.push_back(graph->target(it));
+          } else {
+            _arborescence_map->set(it, false);
+          }
+        }
+      }
+      (*_level)[source] = -1;      
+    }
+
+  };
+
+  /// \ingroup spantree
+  ///
+  /// \brief Function type interface for MinCostArborescence algorithm.
+  ///
+  /// Function type interface for MinCostArborescence algorithm.
+  /// \param graph The Graph that the algorithm runs on.
+  /// \param cost The CostMap of the edges.
+  /// \param source The source of the arborescence.
+  /// \retval arborescence The bool EdgeMap which stores the arborescence.
+  /// \return The cost of the arborescence. 
+  ///
+  /// \sa MinCostArborescence
+  template <typename Graph, typename CostMap, typename ArborescenceMap>
+  typename CostMap::Value minCostArborescence(const Graph& graph, 
+                                              const CostMap& cost,
+                                              typename Graph::Node source,
+                                              ArborescenceMap& arborescence) {
+    typename MinCostArborescence<Graph, CostMap>
+      ::template DefArborescenceMap<ArborescenceMap>
+      ::Create mca(graph, cost);
+    mca.arborescenceMap(arborescence);
+    mca.run(source);
+    return mca.arborescenceCost();
+  }
+
+}
+
+#endif
+
+// Hilbert - Huang



More information about the Lemon-commits mailing list