[Lemon-commits] [lemon_svn] deba: r2545 - hugo/trunk/lemon
Lemon SVN
svn at lemon.cs.elte.hu
Mon Nov 6 20:53:28 CET 2006
Author: deba
Date: Mon Feb 13 10:42:53 2006
New Revision: 2545
Added:
hugo/trunk/lemon/minimal_cut.h
Modified:
hugo/trunk/lemon/Makefile.am
Log:
New algorithm:
MaxCardinalitySearch
MinimalCut // in UGraph
Modified: hugo/trunk/lemon/Makefile.am
==============================================================================
--- hugo/trunk/lemon/Makefile.am (original)
+++ hugo/trunk/lemon/Makefile.am Mon Feb 13 10:42:53 2006
@@ -58,6 +58,7 @@
map_iterator.h \
max_matching.h \
min_cost_flow.h \
+ minimal_cut.h \
suurballe.h \
preflow.h \
path.h \
Added: hugo/trunk/lemon/minimal_cut.h
==============================================================================
--- (empty file)
+++ hugo/trunk/lemon/minimal_cut.h Mon Feb 13 10:42:53 2006
@@ -0,0 +1,1351 @@
+/* -*- C++ -*-
+ * lemon/minimal_cut.h - Part of LEMON, a generic C++ optimization library
+ *
+ * Copyright (C) 2005 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_MINIMAL_CUT_H
+#define LEMON_MINIMAL_CUT_H
+
+
+/// \ingroup topology
+/// \file
+/// \brief Maximum cardinality search and minimal cut in undirected graphs.
+
+#include <lemon/list_graph.h>
+#include <lemon/bin_heap.h>
+#include <lemon/linear_heap.h>
+
+#include <lemon/invalid.h>
+#include <lemon/error.h>
+#include <lemon/maps.h>
+
+#include <functional>
+
+namespace lemon {
+
+ namespace _minimal_cut_bits {
+
+ template <typename CapacityMap>
+ struct HeapSelector {
+ template <typename Key, typename Value, typename Ref>
+ struct Selector {
+ typedef BinHeap<Key, Value, Ref, std::greater<Value> > Heap;
+ };
+ };
+
+ template <typename CapacityKey>
+ struct HeapSelector<ConstMap<CapacityKey, Const<int, 1> > > {
+ template <typename Key, typename Value, typename Ref>
+ struct Selector {
+ typedef LinearHeap<Key, Ref, false > Heap;
+ };
+ };
+
+ }
+
+ /// \brief Default traits class of MaxCardinalitySearch class.
+ ///
+ /// Default traits class of MaxCardinalitySearch class.
+ /// \param Graph Graph type.
+ /// \param CapacityMap Type of length map.
+ template <typename _Graph, typename _CapacityMap>
+ struct MaxCardinalitySearchDefaultTraits {
+ /// The graph type the algorithm runs on.
+ typedef _Graph Graph;
+
+ /// \brief The type of the map that stores the edge capacities.
+ ///
+ /// The type of the map that stores the edge capacities.
+ /// It must meet the \ref concept::ReadMap "ReadMap" concept.
+ typedef _CapacityMap CapacityMap;
+
+ /// \brief The type of the capacity of the edges.
+ typedef typename CapacityMap::Value Value;
+
+ /// \brief The cross reference type used by heap.
+ ///
+ /// The cross reference type used by heap.
+ /// Usually it is \c Graph::NodeMap<int>.
+ typedef typename Graph::template NodeMap<int> HeapCrossRef;
+
+ /// \brief Instantiates a HeapCrossRef.
+ ///
+ /// This function instantiates a \ref HeapCrossRef.
+ /// \param graph is the graph, to which we would like to define the
+ /// HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const Graph &graph) {
+ return new HeapCrossRef(graph);
+ }
+
+ /// \brief The heap type used by MaxCardinalitySearch algorithm.
+ ///
+ /// The heap type used by MaxCardinalitySearch algorithm. It should
+ /// maximalize the priorities. The default heap type is
+ /// the \ref BinHeap, but it is specialized when the
+ /// CapacityMap is ConstMap<Graph::Node, Const<int, 1> >
+ /// to LinearHeap.
+ ///
+ /// \sa MaxCardinalitySearch
+ typedef typename _minimal_cut_bits
+ ::HeapSelector<CapacityMap>
+ ::template Selector<typename Graph::Node, Value, HeapCrossRef>
+ ::Heap Heap;
+
+ /// \brief Instantiates a Heap.
+ ///
+ /// This function instantiates a \ref Heap.
+ /// \param crossref The cross reference of the heap.
+ static Heap *createHeap(HeapCrossRef& crossref) {
+ return new Heap(crossref);
+ }
+
+ /// \brief The type of the map that stores whether a nodes is processed.
+ ///
+ /// The type of the map that stores whether a nodes is processed.
+ /// It must meet the \ref concept::WriteMap "WriteMap" concept.
+ /// By default it is a NullMap.
+ typedef NullMap<typename Graph::Node, bool> ProcessedMap;
+
+ /// \brief Instantiates a ProcessedMap.
+ ///
+ /// This function instantiates a \ref ProcessedMap.
+ /// \param g is the graph, to which
+ /// we would like to define the \ref ProcessedMap
+#ifdef DOXYGEN
+ static ProcessedMap *createProcessedMap(const Graph &graph)
+#else
+ static ProcessedMap *createProcessedMap(const Graph &)
+#endif
+ {
+ return new ProcessedMap();
+ }
+
+ /// \brief The type of the map that stores the cardinalties of the nodes.
+ ///
+ /// The type of the map that stores the cardinalities of the nodes.
+ /// It must meet the \ref concept::WriteMap "WriteMap" concept.
+ typedef typename Graph::template NodeMap<Value> CardinalityMap;
+
+ /// \brief Instantiates a CardinalityMap.
+ ///
+ /// This function instantiates a \ref CardinalityMap.
+ /// \param graph is the graph, to which we would like to define the \ref
+ /// CardinalityMap
+ static CardinalityMap *createCardinalityMap(const Graph &graph) {
+ return new CardinalityMap(graph);
+ }
+
+ };
+
+ /// \ingroup topology
+ ///
+ /// \brief Maximum Cardinality Search algorithm class.
+ ///
+ /// This class provides an efficient implementation of Maximum Cardinality
+ /// Search algorithm. The maximum cardinality search chooses first time any
+ /// node of the graph. Then every time chooses that node which connected
+ /// to the processed nodes at most in the sum of capacities on the out
+ /// edges. If there is a cut in the graph the algorithm should choose
+ /// again any unprocessed node of the graph. Each nodes cardinality is
+ /// the sum of capacities on the out edges to the nodes which are processed
+ /// before the given node.
+ ///
+ /// The edge capacities are passed to the algorithm using a
+ /// \ref concept::ReadMap "ReadMap", so it is easy to change it to any
+ /// kind of capacity.
+ ///
+ /// The type of the capacity is determined by the \ref
+ /// concept::ReadMap::Value "Value" of the capacity map.
+ ///
+ /// It is also possible to change the underlying priority heap.
+ ///
+ ///
+ /// \param _Graph The graph type the algorithm runs on. The default value
+ /// is \ref ListGraph. The value of Graph is not used directly by
+ /// the search algorithm, it is only passed to
+ /// \ref MaxCardinalitySearchDefaultTraits.
+ /// \param _CapacityMap This read-only EdgeMap determines the capacities of
+ /// the edges. It is read once for each edge, so the map may involve in
+ /// relatively time consuming process to compute the edge capacity if
+ /// it is necessary. The default map type is \ref
+ /// concept::StaticGraph::EdgeMap "Graph::EdgeMap<int>". The value
+ /// of CapacityMap is not used directly by search algorithm, it is only
+ /// passed to \ref MaxCardinalitySearchDefaultTraits.
+ /// \param _Traits Traits class to set various data types used by the
+ /// algorithm. The default traits class is
+ /// \ref MaxCardinalitySearchDefaultTraits
+ /// "MaxCardinalitySearchDefaultTraits<_Graph, _CapacityMap>".
+ /// See \ref MaxCardinalitySearchDefaultTraits
+ /// for the documentation of a MaxCardinalitySearch traits class.
+ ///
+ /// \author Balazs Dezso
+
+#ifdef DOXYGEN
+ template <typename _Graph, typename _CapacityMap, typename _Traits>
+#else
+ template <typename _Graph = ListUGraph,
+ typename _CapacityMap = typename _Graph::template EdgeMap<int>,
+ typename _Traits =
+ MaxCardinalitySearchDefaultTraits<_Graph, _CapacityMap> >
+#endif
+ class MaxCardinalitySearch {
+ 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::MaxCardinalitySearch::UninitializedParameter";
+ }
+ };
+
+ typedef _Traits Traits;
+ ///The type of the underlying graph.
+ typedef typename Traits::Graph Graph;
+
+ ///The type of the capacity of the edges.
+ typedef typename Traits::CapacityMap::Value Value;
+ ///The type of the map that stores the edge capacities.
+ typedef typename Traits::CapacityMap CapacityMap;
+ ///The type of the map indicating if a node is processed.
+ typedef typename Traits::ProcessedMap ProcessedMap;
+ ///The type of the map that stores the cardinalities of the nodes.
+ typedef typename Traits::CardinalityMap CardinalityMap;
+ ///The cross reference type used for the current heap.
+ typedef typename Traits::HeapCrossRef HeapCrossRef;
+ ///The heap type used by the algorithm. It maximize the priorities.
+ typedef typename Traits::Heap Heap;
+ private:
+ /// Pointer to the underlying graph.
+ const Graph *_graph;
+ /// Pointer to the capacity map
+ const CapacityMap *_capacity;
+ ///Pointer to the map of cardinality.
+ CardinalityMap *_cardinality;
+ ///Indicates if \ref _cardinality is locally allocated (\c true) or not.
+ bool local_cardinality;
+ ///Pointer to the map of processed status of the nodes.
+ ProcessedMap *_processed;
+ ///Indicates if \ref _processed is locally allocated (\c true) or not.
+ bool local_processed;
+ ///Pointer to the heap cross references.
+ HeapCrossRef *_heap_cross_ref;
+ ///Indicates if \ref _heap_cross_ref is locally allocated (\c true) or not.
+ bool local_heap_cross_ref;
+ ///Pointer to the heap.
+ Heap *_heap;
+ ///Indicates if \ref _heap is locally allocated (\c true) or not.
+ bool local_heap;
+
+ public :
+
+ typedef MaxCardinalitySearch Create;
+
+ ///\name Named template parameters
+
+ ///@{
+
+ template <class T>
+ struct DefCardinalityMapTraits : public Traits {
+ typedef T CardinalityMap;
+ static CardinalityMap *createCardinalityMap(const Graph &)
+ {
+ throw UninitializedParameter();
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// CardinalityMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting CardinalityMap
+ /// type
+ template <class T>
+ struct DefCardinalityMap
+ : public MaxCardinalitySearch<Graph, CapacityMap,
+ DefCardinalityMapTraits<T> > {
+ typedef MaxCardinalitySearch<Graph, CapacityMap,
+ DefCardinalityMapTraits<T> > Create;
+ };
+
+ template <class T>
+ struct DefProcessedMapTraits : public Traits {
+ typedef T ProcessedMap;
+ static ProcessedMap *createProcessedMap(const Graph &) {
+ throw UninitializedParameter();
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// ProcessedMap type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting ProcessedMap type
+ ///
+ template <class T>
+ struct DefProcessedMap
+ : public MaxCardinalitySearch<Graph, CapacityMap,
+ DefProcessedMapTraits<T> > {
+ typedef MaxCardinalitySearch<Graph, CapacityMap,
+ DefProcessedMapTraits<T> > Create;
+ };
+
+ template <class H, class CR>
+ struct DefHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Graph &) {
+ throw UninitializedParameter();
+ }
+ static Heap *createHeap(HeapCrossRef &) {
+ throw UninitializedParameter();
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting heap
+ /// and cross reference type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type
+ template <class H, class CR = typename Graph::template NodeMap<int> >
+ struct DefHeap
+ : public MaxCardinalitySearch<Graph, CapacityMap,
+ DefHeapTraits<H, CR> > {
+ typedef MaxCardinalitySearch< Graph, CapacityMap,
+ DefHeapTraits<H, CR> > Create;
+ };
+
+ template <class H, class CR>
+ struct DefStandardHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const Graph &graph) {
+ return new HeapCrossRef(graph);
+ }
+ static Heap *createHeap(HeapCrossRef &crossref) {
+ return new Heap(crossref);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting heap and
+ /// cross reference type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type. It can allocate the heap and the cross reference
+ /// object if the cross reference's constructor waits for the graph as
+ /// parameter and the heap's constructor waits for the cross reference.
+ template <class H, class CR = typename Graph::template NodeMap<int> >
+ struct DefStandardHeap
+ : public MaxCardinalitySearch<Graph, CapacityMap,
+ DefStandardHeapTraits<H, CR> > {
+ typedef MaxCardinalitySearch<Graph, CapacityMap,
+ DefStandardHeapTraits<H, CR> >
+ Create;
+ };
+
+ ///@}
+
+
+ protected:
+
+ MaxCardinalitySearch() {}
+
+ public:
+
+ /// \brief Constructor.
+ ///
+ ///\param _graph the graph the algorithm will run on.
+ ///\param _capacity the capacity map used by the algorithm.
+ MaxCardinalitySearch(const Graph& graph, const CapacityMap& capacity) :
+ _graph(&graph), _capacity(&capacity),
+ _cardinality(0), local_cardinality(false),
+ _processed(0), local_processed(false),
+ _heap_cross_ref(0), local_heap_cross_ref(false),
+ _heap(0), local_heap(false)
+ { }
+
+ /// \brief Destructor.
+ ~MaxCardinalitySearch() {
+ if(local_cardinality) delete _cardinality;
+ if(local_processed) delete _processed;
+ if(local_heap_cross_ref) delete _heap_cross_ref;
+ if(local_heap) delete _heap;
+ }
+
+ /// \brief Sets the capacity map.
+ ///
+ /// Sets the capacity map.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &capacityMap(const CapacityMap &m) {
+ _capacity = &m;
+ return *this;
+ }
+
+ /// \brief Sets the map storing the cardinalities calculated by the
+ /// algorithm.
+ ///
+ /// Sets the map storing the cardinalities calculated by the algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &cardinalityMap(CardinalityMap &m) {
+ if(local_cardinality) {
+ delete _cardinality;
+ local_cardinality=false;
+ }
+ _cardinality = &m;
+ return *this;
+ }
+
+ /// \brief Sets the map storing the processed nodes.
+ ///
+ /// Sets the map storing the processed nodes.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &processedMap(ProcessedMap &m)
+ {
+ if(local_processed) {
+ delete _processed;
+ local_processed=false;
+ }
+ _processed = &m;
+ return *this;
+ }
+
+ /// \brief Sets the heap and the cross reference used by algorithm.
+ ///
+ /// Sets the heap and the cross reference used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated map, of course.
+ /// \return <tt> (*this) </tt>
+ MaxCardinalitySearch &heap(Heap& heap, HeapCrossRef &crossRef) {
+ if(local_heap_cross_ref) {
+ delete _heap_cross_ref;
+ local_heap_cross_ref = false;
+ }
+ _heap_cross_ref = &crossRef;
+ if(local_heap) {
+ delete _heap;
+ local_heap = false;
+ }
+ _heap = &heap;
+ return *this;
+ }
+
+ private:
+
+ typedef typename Graph::Node Node;
+ typedef typename Graph::NodeIt NodeIt;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::InEdgeIt InEdgeIt;
+
+ void create_maps() {
+ if(!_cardinality) {
+ local_cardinality = true;
+ _cardinality = Traits::createCardinalityMap(*_graph);
+ }
+ if(!_processed) {
+ local_processed = true;
+ _processed = Traits::createProcessedMap(*_graph);
+ }
+ if (!_heap_cross_ref) {
+ local_heap_cross_ref = true;
+ _heap_cross_ref = Traits::createHeapCrossRef(*_graph);
+ }
+ if (!_heap) {
+ local_heap = true;
+ _heap = Traits::createHeap(*_heap_cross_ref);
+ }
+ }
+
+ void finalizeNodeData(Node node, Value capacity) {
+ _processed->set(node, true);
+ _cardinality->set(node, capacity);
+ }
+
+ public:
+ /// \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() {
+ create_maps();
+ _heap->clear();
+ for (NodeIt it(*_graph) ; it != INVALID ; ++it) {
+ _processed->set(it, false);
+ _heap_cross_ref->set(it, Heap::PRE_HEAP);
+ }
+ }
+
+ /// \brief Adds a new source node.
+ ///
+ /// Adds a new source node to the priority heap.
+ ///
+ /// It checks if the node has not yet been added to the heap.
+ void addSource(Node source, Value capacity = 0) {
+ if(_heap->state(source) == Heap::PRE_HEAP) {
+ _heap->push(source, capacity);
+ }
+ }
+
+ /// \brief Processes the next node in the priority heap
+ ///
+ /// Processes the next node in the priority heap.
+ ///
+ /// \return The processed node.
+ ///
+ /// \warning The priority heap must not be empty!
+ Node processNextNode() {
+ Node node = _heap->top();
+ finalizeNodeData(node, _heap->prio());
+ _heap->pop();
+
+ for (InEdgeIt it(*_graph, node); it != INVALID; ++it) {
+ Node source = _graph->source(it);
+ switch (_heap->state(source)) {
+ case Heap::PRE_HEAP:
+ _heap->push(source, (*_capacity)[it]);
+ break;
+ case Heap::IN_HEAP:
+ _heap->decrease(source, (*_heap)[source] + (*_capacity)[it]);
+ break;
+ case Heap::POST_HEAP:
+ break;
+ }
+ }
+ return node;
+ }
+
+ /// \brief Next node to be processed.
+ ///
+ /// Next node to be processed.
+ ///
+ /// \return The next node to be processed or INVALID if the
+ /// priority heap is empty.
+ Node nextNode() {
+ return _heap->empty() ? _heap->top() : INVALID;
+ }
+
+ /// \brief Returns \c false if there are nodes
+ /// to be processed in the priority heap
+ ///
+ /// Returns \c false if there are nodes
+ /// to be processed in the priority heap
+ bool emptyQueue() { return _heap->empty(); }
+ /// \brief Returns the number of the nodes to be processed
+ /// in the priority heap
+ ///
+ /// Returns the number of the nodes to be processed in the priority heap
+ int queueSize() { return _heap->size(); }
+
+ /// \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.
+ ///
+ /// This method runs the Maximum Cardinality Search algorithm from the
+ /// source node(s).
+ void start() {
+ while ( !_heap->empty() ) processNextNode();
+ }
+
+ /// \brief Executes the algorithm until \c dest is reached.
+ ///
+ /// Executes the algorithm until \c dest is reached.
+ ///
+ /// \pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from the source
+ /// nodes.
+ void start(Node dest) {
+ while ( !_heap->empty() && _heap->top()!=dest ) processNextNode();
+ if ( !_heap->empty() ) finalizeNodeData(_heap->top(), _heap->prio());
+ }
+
+ /// \brief Executes the algorithm until a condition is met.
+ ///
+ /// Executes the algorithm until a condition is met.
+ ///
+ /// \pre init() must be called and at least one node should be added
+ /// with addSource() before using this function.
+ ///
+ /// \param nm must be a bool (or convertible) node map. The algorithm
+ /// will stop when it reaches a node \c v with <tt>nm[v]==true</tt>.
+ template <typename NodeBoolMap>
+ void start(const NodeBoolMap &nm) {
+ while ( !_heap->empty() && !nm[_heap->top()] ) processNextNode();
+ if ( !_heap->empty() ) finalizeNodeData(_heap->top(),_heap->prio());
+ }
+
+ /// \brief Runs the maximal cardinality search algorithm from node \c s.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from a root
+ /// node \c s.
+ ///
+ ///\note d.run(s) is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// d.addSource(s);
+ /// d.start();
+ ///\endcode
+ void run(Node s) {
+ init();
+ addSource(s);
+ start();
+ }
+
+ /// \brief Runs the maximal cardinality search algorithm for the
+ /// whole graph.
+ ///
+ /// This method runs the %MaxCardinalitySearch algorithm from all
+ /// unprocessed node of the graph.
+ ///
+ ///\note d.run(s) is just a shortcut of the following code.
+ ///\code
+ /// d.init();
+ /// for (NodeIt it(graph); it != INVALID; ++it) {
+ /// if (!d.reached(it)) {
+ /// d.addSource(s);
+ /// d.start();
+ /// }
+ /// }
+ ///\endcode
+ void run() {
+ init();
+ for (NodeIt it(*_graph); it != INVALID; ++it) {
+ if (!reached(it)) {
+ addSource(it);
+ start();
+ }
+ }
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The result of the maximum cardinality search algorithm can be
+ /// obtained using these functions.
+ /// \n
+ /// Before the use of these functions, either run() or start() must be
+ /// called.
+
+ ///@{
+
+ /// \brief The cardinality of a node.
+ ///
+ /// Returns the cardinality of a node.
+ /// \pre \ref run() must be called before using this function.
+ /// \warning If node \c v in unreachable from the root the return value
+ /// of this funcion is undefined.
+ Value cardinality(Node node) const { return (*_cardinality)[node]; }
+
+ /// \brief Returns a reference to the NodeMap of cardinalities.
+ ///
+ /// Returns a reference to the NodeMap of cardinalities. \pre \ref run()
+ /// must be called before using this function.
+ const CardinalityMap &cardinalityMap() const { return *_cardinality;}
+
+ /// \brief Checks if a node is reachable from the root.
+ ///
+ /// Returns \c true if \c v is reachable from the root.
+ /// \warning The source nodes are inditated as unreached.
+ /// \pre \ref run() must be called before using this function.
+ bool reached(Node v) { return (*_heap_cross_ref)[v] != Heap::PRE_HEAP; }
+
+ /// \brief Checks if a node is processed.
+ ///
+ /// Returns \c true if \c v is processed, i.e. the shortest
+ /// path to \c v has already found.
+ /// \pre \ref run() must be called before using this function.
+ bool processed(Node v) { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; }
+
+ ///@}
+ };
+
+ /// \brief Default traits class of MinimalCut class.
+ ///
+ /// Default traits class of MinimalCut class.
+ /// \param Graph Graph type.
+ /// \param CapacityMap Type of length map.
+ template <typename _Graph, typename _CapacityMap>
+ struct MinimalCutDefaultTraits {
+ /// \brief The type of the capacity of the edges.
+ typedef typename _CapacityMap::Value Value;
+
+ /// The graph type the algorithm runs on.
+ typedef _Graph Graph;
+
+ /// The WorkGraph type which is an EraseableGraph
+ typedef ListUGraph WorkGraph;
+
+ /// \brief Instantiates a WorkGraph.
+ ///
+ /// This function instantiates a \ref WorkGraph.
+ static WorkGraph *createWorkGraph() {
+ return new WorkGraph();
+ }
+
+ /// \brief The type of the map that stores the edge capacities.
+ ///
+ /// The type of the map that stores the edge capacities.
+ /// It must meet the \ref concept::ReadMap "ReadMap" concept.
+ typedef _CapacityMap CapacityMap;
+
+ /// \brief Instantiates a CapacityMap.
+ ///
+ /// This function instantiates a \ref CapacityMap.
+#ifdef DOXYGEN
+ static CapacityMap *createCapacityMap(const Graph& graph)
+#else
+ static CapacityMap *createCapacityMap(const Graph&)
+#endif
+ {
+ throw UninitializedParameter();
+ }
+
+ /// \brief The WorkCapacityMap type
+ ///
+ /// The type of the map that stores the working edge capacities.
+ typedef WorkGraph::UEdgeMap<Value> WorkCapacityMap;
+
+ /// \brief Instantiates a WorkCapacityMap.
+ ///
+ /// This function instantiates a \ref WorkCapacityMap.
+ static WorkCapacityMap *createWorkCapacityMap(const WorkGraph& graph) {
+ return new WorkCapacityMap(graph);
+ }
+
+ /// \brief The cross reference type used by heap.
+ ///
+ /// The cross reference type used by heap.
+ /// Usually it is \c Graph::NodeMap<int>.
+ typedef WorkGraph::NodeMap<int> HeapCrossRef;
+
+ /// \brief Instantiates a HeapCrossRef.
+ ///
+ /// This function instantiates a \ref HeapCrossRef.
+ /// \param graph is the graph, to which we would like to define the
+ /// HeapCrossRef.
+ static HeapCrossRef *createHeapCrossRef(const WorkGraph &graph) {
+ return new HeapCrossRef(graph);
+ }
+
+ /// \brief The heap type used by MinimalCut algorithm.
+ ///
+ /// The heap type used by MinimalCut algorithm. It should
+ /// maximalize the priorities and the heap's key type is
+ /// the work graph's node.
+ ///
+ /// \sa BinHeap
+ /// \sa MinimalCut
+ typedef typename _minimal_cut_bits
+ ::HeapSelector<CapacityMap>
+ ::template Selector<typename WorkGraph::Node, Value, HeapCrossRef>
+ ::Heap Heap;
+
+ /// \brief Instantiates a Heap.
+ ///
+ /// This function instantiates a \ref Heap.
+ /// \param crossref The cross reference of the heap.
+ static Heap *createHeap(HeapCrossRef& crossref) {
+ return new Heap(crossref);
+ }
+
+ /// \brief Map from the WorkGraph's node type to the Graph's node type.
+ ///
+ /// Map from the WorkGraph's node type to the Graph's node type.
+ typedef typename WorkGraph
+ ::template NodeMap<typename Graph::Node> NodeRefMap;
+
+ /// \brief Instantiates a NodeRefMap.
+ ///
+ /// This function instantiates a \ref NodeRefMap.
+ static NodeRefMap *createNodeRefMap(const WorkGraph& graph) {
+ return new NodeRefMap(graph);
+ }
+
+ /// \brief Map from the Graph's node type to the Graph's node type.
+ ///
+ /// Map from the Graph's node type to the Graph's node type.
+ typedef typename Graph
+ ::template NodeMap<typename Graph::Node> ListRefMap;
+
+ /// \brief Instantiates a ListRefMap.
+ ///
+ /// This function instantiates a \ref ListRefMap.
+ static ListRefMap *createListRefMap(const Graph& graph) {
+ return new ListRefMap(graph);
+ }
+
+
+ };
+
+ namespace _minimal_cut_bits {
+ template <typename _Key>
+ class LastTwoMap {
+ public:
+ typedef _Key Key;
+ typedef bool Value;
+
+ LastTwoMap(int _num) : num(_num) {}
+ void set(const Key& key, bool val) {
+ if (!val) return;
+ --num;
+ if (num > 1) return;
+ keys[num] = key;
+ }
+
+ Key operator[](int index) const { return keys[index]; }
+ private:
+ Key keys[2];
+ int num;
+ };
+ }
+
+ /// \ingroup topology
+ ///
+ /// \brief Calculates the minimal cut in an undirected graph.
+ ///
+ /// Calculates the minimal cut in an undirected graph.
+ /// The algorithm separates the graph's nodes to two partitions with the
+ /// minimal sum of edge capacities between the two partitions. The
+ /// algorithm can be used to test the network reliability specifically
+ /// to test how many links have to be destroyed in the network to split it
+ /// at least two distinict subnetwork.
+ ///
+ /// The complexity of the algorithm is O(n*e*log(n)) but with Fibonacci
+ /// heap it can be decreased to O(n*e+n^2*log(n)). When the neutral capacity
+ /// map is used then it uses LinearHeap which results O(n*e) time complexity.
+#ifdef DOXYGEN
+ template <typename _Graph, typename _CapacityMap, typename _Traits>
+#else
+ template <typename _Graph = ListUGraph,
+ typename _CapacityMap = typename _Graph::template UEdgeMap<int>,
+ typename _Traits = MinimalCutDefaultTraits<_Graph, _CapacityMap> >
+#endif
+ class MinimalCut {
+ 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::MinimalCut::UninitializedParameter";
+ }
+ };
+
+
+ private:
+
+ typedef _Traits Traits;
+ /// The type of the underlying graph.
+ typedef typename Traits::Graph Graph;
+
+ /// The type of the capacity of the edges.
+ typedef typename Traits::CapacityMap::Value Value;
+ /// The type of the map that stores the edge capacities.
+ typedef typename Traits::CapacityMap CapacityMap;
+ /// The type of the work graph
+ typedef typename Traits::WorkGraph WorkGraph;
+ /// The type of the work capacity map
+ typedef typename Traits::WorkCapacityMap WorkCapacityMap;
+ /// The cross reference type used for the current heap.
+ typedef typename Traits::HeapCrossRef HeapCrossRef;
+ /// The heap type used by the max cardinality algorithm.
+ typedef typename Traits::Heap Heap;
+ /// The node refrefernces between the original and work graph type.
+ typedef typename Traits::NodeRefMap NodeRefMap;
+ /// The list node refrefernces in the original graph type.
+ typedef typename Traits::ListRefMap ListRefMap;
+
+ public:
+
+ ///\name Named template parameters
+
+ ///@{
+
+ struct DefNeutralCapacityTraits : public Traits {
+ typedef ConstMap<typename Graph::UEdge, Const<int, 1> > CapacityMap;
+ static CapacityMap *createCapacityMap(const Graph&) {
+ return new CapacityMap();
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting
+ /// the capacity type to constMap<UEdge, int, 1>()
+ ///
+ /// \ref named-templ-param "Named parameter" for setting
+ /// the capacity type to constMap<UEdge, int, 1>()
+ struct DefNeutralCapacity
+ : public MinimalCut<Graph, CapacityMap, DefNeutralCapacityTraits> {
+ typedef MinimalCut<Graph, CapacityMap, DefNeutralCapacityTraits> Create;
+ };
+
+
+ template <class H, class CR>
+ struct DefHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const WorkGraph &) {
+ throw UninitializedParameter();
+ }
+ static Heap *createHeap(HeapCrossRef &) {
+ throw UninitializedParameter();
+ }
+ };
+ /// \brief \ref named-templ-param "Named parameter" for setting heap
+ /// and cross reference type
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type
+ template <class H, class CR = typename Graph::template NodeMap<int> >
+ struct DefHeap
+ : public MinimalCut<Graph, CapacityMap, DefHeapTraits<H, CR> > {
+ typedef MinimalCut< Graph, CapacityMap, DefHeapTraits<H, CR> > Create;
+ };
+
+ template <class H, class CR>
+ struct DefStandardHeapTraits : public Traits {
+ typedef CR HeapCrossRef;
+ typedef H Heap;
+ static HeapCrossRef *createHeapCrossRef(const WorkGraph &graph) {
+ return new HeapCrossRef(graph);
+ }
+ static Heap *createHeap(HeapCrossRef &crossref) {
+ return new Heap(crossref);
+ }
+ };
+
+ /// \brief \ref named-templ-param "Named parameter" for setting heap and
+ /// cross reference type with automatic allocation
+ ///
+ /// \ref named-templ-param "Named parameter" for setting heap and cross
+ /// reference type. It can allocate the heap and the cross reference
+ /// object if the cross reference's constructor waits for the graph as
+ /// parameter and the heap's constructor waits for the cross reference.
+ template <class H, class CR = typename Graph::template NodeMap<int> >
+ struct DefStandardHeap
+ : public MinimalCut<Graph, CapacityMap, DefStandardHeapTraits<H, CR> > {
+ typedef MinimalCut<Graph, CapacityMap, DefStandardHeapTraits<H, CR> >
+ Create;
+ };
+
+ ///@}
+
+
+ private:
+ /// Pointer to the underlying graph.
+ const Graph *_graph;
+ /// Pointer to the capacity map
+ const CapacityMap *_capacity;
+ /// \brief Indicates if \ref _capacity is locally allocated
+ /// (\c true) or not.
+ bool local_capacity;
+
+ /// Pointer to the work graph.
+ WorkGraph *_work_graph;
+ /// \brief Indicates if \ref _work_graph is locally allocated
+ /// (\c true) or not.
+ bool local_work_graph;
+ /// Pointer to the work capacity map
+ WorkCapacityMap *_work_capacity;
+ /// \brief Indicates if \ref _work_capacity is locally allocated
+ /// (\c true) or not.
+ bool local_work_capacity;
+ /// Pointer to the heap cross references.
+ HeapCrossRef *_heap_cross_ref;
+ /// \brief Indicates if \ref _heap_cross_ref is locally allocated
+ /// (\c true) or not.
+ bool local_heap_cross_ref;
+ /// Pointer to the heap.
+ Heap *_heap;
+ /// Indicates if \ref _heap is locally allocated (\c true) or not.
+ bool local_heap;
+
+ /// The minimal cut value.
+ Value _minimal_cut;
+ /// The number of the nodes of the work graph.
+ int _node_num;
+ /// The first and last node of the min cut in the next list;
+ typename Graph::Node _first_node, _last_node;
+
+ /// \brief The first and last element in the list associated
+ /// to the work graph node.
+ NodeRefMap *_first, *_last;
+ /// \brief The next node in the node lists.
+ ListRefMap *_next;
+
+ void create_structures() {
+ if (!_capacity) {
+ local_capacity = true;
+ _capacity = Traits::createCapacityMap(*_graph);
+ }
+ if(!_work_graph) {
+ local_work_graph = true;
+ _work_graph = Traits::createWorkGraph();
+ }
+ if(!_work_capacity) {
+ local_work_capacity = true;
+ _work_capacity = Traits::createWorkCapacityMap(*_work_graph);
+ }
+
+ _first = Traits::createNodeRefMap(*_work_graph);
+ _last = Traits::createNodeRefMap(*_work_graph);
+
+ _next = Traits::createListRefMap(*_graph);
+
+ typename Graph::template NodeMap<typename WorkGraph::Node> ref(*_graph);
+
+ for (typename Graph::NodeIt it(*_graph); it != INVALID; ++it) {
+ _next->set(it, INVALID);
+ typename WorkGraph::Node node = _work_graph->addNode();
+ _first->set(node, it);
+ _last->set(node, it);
+ ref.set(it, node);
+ }
+
+ for (typename Graph::UEdgeIt it(*_graph); it != INVALID; ++it) {
+ if (_graph->source(it) == _graph->target(it)) continue;
+ typename WorkGraph::UEdge uedge =
+ _work_graph->addEdge(ref[_graph->source(it)],
+ ref[_graph->target(it)]);
+ _work_capacity->set(uedge, (*_capacity)[it]);
+
+ }
+
+ if (!_heap_cross_ref) {
+ local_heap_cross_ref = true;
+ _heap_cross_ref = Traits::createHeapCrossRef(*_work_graph);
+ }
+ if (!_heap) {
+ local_heap = true;
+ _heap = Traits::createHeap(*_heap_cross_ref);
+ }
+ }
+
+ public :
+
+ typedef MinimalCut Create;
+
+
+ /// \brief Constructor.
+ ///
+ ///\param graph the graph the algorithm will run on.
+ ///\param capacity the capacity map used by the algorithm.
+ MinimalCut(const Graph& graph, const CapacityMap& capacity)
+ : _graph(&graph),
+ _capacity(&capacity), local_capacity(false),
+ _work_graph(0), local_work_graph(false),
+ _work_capacity(0), local_work_capacity(false),
+ _heap_cross_ref(0), local_heap_cross_ref(false),
+ _heap(0), local_heap(false),
+ _first(0), _last(0), _next(0) {}
+
+ /// \brief Constructor.
+ ///
+ /// This constructor can be used only when the Traits class
+ /// defines how can we instantiate a local capacity map.
+ /// If the DefNeutralCapacity used the algorithm automatically
+ /// construct the capacity map.
+ ///
+ ///\param graph the graph the algorithm will run on.
+ MinimalCut(const Graph& graph)
+ : _graph(&graph),
+ _capacity(0), local_capacity(false),
+ _work_graph(0), local_work_graph(false),
+ _work_capacity(0), local_work_capacity(false),
+ _heap_cross_ref(0), local_heap_cross_ref(false),
+ _heap(0), local_heap(false),
+ _first(0), _last(0), _next(0) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor.
+ ~MinimalCut() {
+ if (local_heap) delete _heap;
+ if (local_heap_cross_ref) delete _heap_cross_ref;
+ if (_first) delete _first;
+ if (_last) delete _last;
+ if (_next) delete _next;
+ if (local_work_capacity) delete _work_capacity;
+ if (local_work_graph) delete _work_graph;
+ if (local_capacity) delete _capacity;
+ }
+
+ /// \brief Sets the heap and the cross reference used by algorithm.
+ ///
+ /// Sets the heap and the cross reference used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated heap and cross reference, of course.
+ /// \return <tt> (*this) </tt>
+ MinimalCut &heap(Heap& heap, HeapCrossRef &crossRef)
+ {
+ if (local_heap_cross_ref) {
+ delete _heap_cross_ref;
+ local_heap_cross_ref=false;
+ }
+ _heap_cross_ref = &crossRef;
+ if (local_heap) {
+ delete _heap;
+ local_heap=false;
+ }
+ _heap = &heap;
+ return *this;
+ }
+
+ /// \brief Sets the work graph.
+ ///
+ /// Sets the work graph used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated graph, of course.
+ /// \return <tt> (*this) </tt>
+ MinimalCut &workGraph(WorkGraph& work_graph)
+ {
+ if(local_work_graph) {
+ delete _work_graph;
+ local_work_graph=false;
+ }
+ _work_graph = &work_graph;
+ return *this;
+ }
+
+ /// \brief Sets the work capacity map.
+ ///
+ /// Sets the work capacity map used by algorithm.
+ /// If you don't use this function before calling \ref run(),
+ /// it will allocate one. The destuctor deallocates this
+ /// automatically allocated graph, of course.
+ /// \return <tt> (*this) </tt>
+ MinimalCut &workCapacityMap(WorkCapacityMap& work_capacity_map)
+ {
+ if(local_work_capacity) {
+ delete _work_capacity;
+ local_work_capacity=false;
+ }
+ _work_capacity = &work_capacity_map;
+ return *this;
+ }
+
+ /// \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() and then call the start()
+ /// or proper times the processNextPhase() member functions.
+
+ ///@{
+
+ /// \brief Initializes the internal data structures.
+ ///
+ /// Initializes the internal data structures.
+ void init() {
+ create_structures();
+ _first_node = _last_node = INVALID;
+ _node_num = countNodes(*_graph);
+ }
+
+ /// \brief Processes the next phase
+ ///
+ /// Processes the next phase in the algorithm. The function
+ /// should be called countNodes(graph) - 1 times to get
+ /// surely the minimal cut in the graph. The
+ ///
+ ///\return %True when the algorithm finished.
+ bool processNextPhase() {
+ if (_node_num <= 1) return true;
+ using namespace _minimal_cut_bits;
+
+ typedef typename WorkGraph::Node Node;
+ typedef typename WorkGraph::NodeIt NodeIt;
+ typedef typename WorkGraph::UEdge UEdge;
+ typedef typename WorkGraph::IncEdgeIt IncEdgeIt;
+
+ typedef typename MaxCardinalitySearch<WorkGraph, WorkCapacityMap>::
+ template DefHeap<Heap, HeapCrossRef>::
+ template DefCardinalityMap<NullMap<Node, Value> >::
+ template DefProcessedMap<LastTwoMap<Node> >::
+ Create MaxCardinalitySearch;
+
+ MaxCardinalitySearch mcs(*_work_graph, *_work_capacity);
+ for (NodeIt it(*_work_graph); it != INVALID; ++it) {
+ _heap_cross_ref->set(it, Heap::PRE_HEAP);
+ }
+ mcs.heap(*_heap, *_heap_cross_ref);
+
+ LastTwoMap<Node> last_two_nodes(_node_num);
+ mcs.processedMap(last_two_nodes);
+
+ NullMap<Node, Value> cardinality;
+ mcs.cardinalityMap(cardinality);
+
+ mcs.run();
+
+ Node new_node = _work_graph->addNode();
+
+ typename WorkGraph::template NodeMap<UEdge> edges(*_work_graph, INVALID);
+
+ Node first_node = last_two_nodes[0];
+ Node second_node = last_two_nodes[1];
+
+ _next->set((*_last)[first_node], (*_first)[second_node]);
+ _first->set(new_node, (*_first)[first_node]);
+ _last->set(new_node, (*_last)[second_node]);
+
+ Value current_cut = 0;
+ for (IncEdgeIt it(*_work_graph, first_node); it != INVALID; ++it) {
+ Node node = _work_graph->runningNode(it);
+ current_cut += (*_work_capacity)[it];
+ if (node == second_node) continue;
+ if (edges[node] == INVALID) {
+ edges[node] = _work_graph->addEdge(new_node, node);
+ (*_work_capacity)[edges[node]] = (*_work_capacity)[it];
+ } else {
+ (*_work_capacity)[edges[node]] += (*_work_capacity)[it];
+ }
+ }
+
+ if (_first_node == INVALID || current_cut < _minimal_cut) {
+ _first_node = (*_first)[first_node];
+ _last_node = (*_last)[first_node];
+ _minimal_cut = current_cut;
+ }
+
+ _work_graph->erase(first_node);
+
+ for (IncEdgeIt it(*_work_graph, second_node); it != INVALID; ++it) {
+ Node node = _work_graph->runningNode(it);
+ if (edges[node] == INVALID) {
+ edges[node] = _work_graph->addEdge(new_node, node);
+ (*_work_capacity)[edges[node]] = (*_work_capacity)[it];
+ } else {
+ (*_work_capacity)[edges[node]] += (*_work_capacity)[it];
+ }
+ }
+ _work_graph->erase(second_node);
+
+ --_node_num;
+ return _node_num == 1;
+ }
+
+ /// \brief Executes the algorithm.
+ ///
+ /// Executes the algorithm.
+ ///
+ /// \pre init() must be called
+ void start() {
+ while (!processNextPhase());
+ }
+
+
+ /// \brief Runs %MinimalCut algorithm.
+ ///
+ /// This method runs the %Minimal cut algorithm
+ ///
+ /// \note mc.run(s) is just a shortcut of the following code.
+ ///\code
+ /// mc.init();
+ /// mc.start();
+ ///\endcode
+ void run() {
+ init();
+ start();
+ }
+
+ ///@}
+
+ /// \name Query Functions
+ /// The result of the %MinimalCut algorithm can be obtained using these
+ /// functions.\n
+ /// Before the use of these functions,
+ /// either run() or start() must be called.
+
+ ///@{
+
+ /// \brief Returns the minimal cut value.
+ ///
+ /// Returns the minimal cut value if the algorithm finished.
+ /// After the first processNextPhase() it is a value of a
+ /// valid cut in the graph.
+ Value minCut() const {
+ return _minimal_cut;
+ }
+
+ /// \brief Returns a minimal cut in a NodeMap.
+ ///
+ /// It sets the nodes of one of the two partitions to true in
+ /// the given BoolNodeMap. The map contains a valid cut if the
+ /// map have been setted false previously.
+ template <typename NodeMap>
+ Value quickMinCut(NodeMap& nodeMap) const {
+ for (typename Graph::Node it = _first_node;
+ it != _last_node; it = (*_next)[it]) {
+ nodeMap.set(it, true);
+ }
+ nodeMap.set(_last_node, true);
+ return minCut();
+ }
+
+ /// \brief Returns a minimal cut in a NodeMap.
+ ///
+ /// It sets the nodes of one of the two partitions to true and
+ /// the other partition to false. The function first set all of the
+ /// nodes to false and after it call the quickMinCut() member.
+ template <typename NodeMap>
+ Value minCut(NodeMap& nodeMap) const {
+ for (typename Graph::NodeIt it(*_graph); it != INVALID; ++it) {
+ nodeMap.set(it, false);
+ }
+ quickMinCut(nodeMap);
+ return minCut();
+ }
+
+ /// \brief Returns a minimal cut in an EdgeMap.
+ ///
+ /// If an undirected edge is cut edge then it will be
+ /// setted to true and the others will be setted to false in the given map.
+ template <typename EdgeMap>
+ Value cutEdges(EdgeMap& edgeMap) const {
+ typename Graph::template NodeMap<bool> cut(*_graph, false);
+ quickMinCut(cut);
+ for (typename Graph::EdgeIt it(*_graph); it != INVALID; ++it) {
+ edgeMap.set(it, cut[_graph->source(it)] ^ cut[_graph->target(it)]);
+ }
+ return minCut();
+ }
+
+ ///@}
+
+ };
+}
+
+#endif
More information about the Lemon-commits
mailing list