| 1 | /* -*- C++ -*- | 
|---|
| 2 |  * | 
|---|
| 3 |  * This file is a part of LEMON, a generic C++ optimization library | 
|---|
| 4 |  * | 
|---|
| 5 |  * Copyright (C) 2003-2008 | 
|---|
| 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_HOWARD_H | 
|---|
| 20 | #define LEMON_HOWARD_H | 
|---|
| 21 |  | 
|---|
| 22 | /// \ingroup min_mean_cycle | 
|---|
| 23 | /// | 
|---|
| 24 | /// \file | 
|---|
| 25 | /// \brief Howard's algorithm for finding a minimum mean cycle. | 
|---|
| 26 |  | 
|---|
| 27 | #include <vector> | 
|---|
| 28 | #include <limits> | 
|---|
| 29 | #include <lemon/core.h> | 
|---|
| 30 | #include <lemon/path.h> | 
|---|
| 31 | #include <lemon/tolerance.h> | 
|---|
| 32 | #include <lemon/connectivity.h> | 
|---|
| 33 |  | 
|---|
| 34 | namespace lemon { | 
|---|
| 35 |  | 
|---|
| 36 |   /// \brief Default traits class of Howard class. | 
|---|
| 37 |   /// | 
|---|
| 38 |   /// Default traits class of Howard class. | 
|---|
| 39 |   /// \tparam GR The type of the digraph. | 
|---|
| 40 |   /// \tparam LEN The type of the length map. | 
|---|
| 41 |   /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. | 
|---|
| 42 | #ifdef DOXYGEN | 
|---|
| 43 |   template <typename GR, typename LEN> | 
|---|
| 44 | #else | 
|---|
| 45 |   template <typename GR, typename LEN, | 
|---|
| 46 |     bool integer = std::numeric_limits<typename LEN::Value>::is_integer> | 
|---|
| 47 | #endif | 
|---|
| 48 |   struct HowardDefaultTraits | 
|---|
| 49 |   { | 
|---|
| 50 |     /// The type of the digraph | 
|---|
| 51 |     typedef GR Digraph; | 
|---|
| 52 |     /// The type of the length map | 
|---|
| 53 |     typedef LEN LengthMap; | 
|---|
| 54 |     /// The type of the arc lengths | 
|---|
| 55 |     typedef typename LengthMap::Value Value; | 
|---|
| 56 |  | 
|---|
| 57 |     /// \brief The large value type used for internal computations | 
|---|
| 58 |     /// | 
|---|
| 59 |     /// The large value type used for internal computations. | 
|---|
| 60 |     /// It is \c long \c long if the \c Value type is integer, | 
|---|
| 61 |     /// otherwise it is \c double. | 
|---|
| 62 |     /// \c Value must be convertible to \c LargeValue. | 
|---|
| 63 |     typedef double LargeValue; | 
|---|
| 64 |  | 
|---|
| 65 |     /// The tolerance type used for internal computations | 
|---|
| 66 |     typedef lemon::Tolerance<LargeValue> Tolerance; | 
|---|
| 67 |  | 
|---|
| 68 |     /// \brief The path type of the found cycles | 
|---|
| 69 |     /// | 
|---|
| 70 |     /// The path type of the found cycles. | 
|---|
| 71 |     /// It must conform to the \ref lemon::concepts::Path "Path" concept | 
|---|
| 72 |     /// and it must have an \c addBack() function. | 
|---|
| 73 |     typedef lemon::Path<Digraph> Path; | 
|---|
| 74 |   }; | 
|---|
| 75 |  | 
|---|
| 76 |   // Default traits class for integer value types | 
|---|
| 77 |   template <typename GR, typename LEN> | 
|---|
| 78 |   struct HowardDefaultTraits<GR, LEN, true> | 
|---|
| 79 |   { | 
|---|
| 80 |     typedef GR Digraph; | 
|---|
| 81 |     typedef LEN LengthMap; | 
|---|
| 82 |     typedef typename LengthMap::Value Value; | 
|---|
| 83 | #ifdef LEMON_HAVE_LONG_LONG | 
|---|
| 84 |     typedef long long LargeValue; | 
|---|
| 85 | #else | 
|---|
| 86 |     typedef long LargeValue; | 
|---|
| 87 | #endif | 
|---|
| 88 |     typedef lemon::Tolerance<LargeValue> Tolerance; | 
|---|
| 89 |     typedef lemon::Path<Digraph> Path; | 
|---|
| 90 |   }; | 
|---|
| 91 |  | 
|---|
| 92 |  | 
|---|
| 93 |   /// \addtogroup min_mean_cycle | 
|---|
| 94 |   /// @{ | 
|---|
| 95 |  | 
|---|
| 96 |   /// \brief Implementation of Howard's algorithm for finding a minimum | 
|---|
| 97 |   /// mean cycle. | 
|---|
| 98 |   /// | 
|---|
| 99 |   /// This class implements Howard's policy iteration algorithm for finding | 
|---|
| 100 |   /// a directed cycle of minimum mean length (cost) in a digraph. | 
|---|
| 101 |   /// This class provides the most efficient algorithm for the | 
|---|
| 102 |   /// minimum mean cycle problem, though the best known theoretical | 
|---|
| 103 |   /// bound on its running time is exponential. | 
|---|
| 104 |   /// | 
|---|
| 105 |   /// \tparam GR The type of the digraph the algorithm runs on. | 
|---|
| 106 |   /// \tparam LEN The type of the length map. The default | 
|---|
| 107 |   /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>". | 
|---|
| 108 | #ifdef DOXYGEN | 
|---|
| 109 |   template <typename GR, typename LEN, typename TR> | 
|---|
| 110 | #else | 
|---|
| 111 |   template < typename GR, | 
|---|
| 112 |              typename LEN = typename GR::template ArcMap<int>, | 
|---|
| 113 |              typename TR = HowardDefaultTraits<GR, LEN> > | 
|---|
| 114 | #endif | 
|---|
| 115 |   class Howard | 
|---|
| 116 |   { | 
|---|
| 117 |   public: | 
|---|
| 118 |    | 
|---|
| 119 |     /// The type of the digraph | 
|---|
| 120 |     typedef typename TR::Digraph Digraph; | 
|---|
| 121 |     /// The type of the length map | 
|---|
| 122 |     typedef typename TR::LengthMap LengthMap; | 
|---|
| 123 |     /// The type of the arc lengths | 
|---|
| 124 |     typedef typename TR::Value Value; | 
|---|
| 125 |  | 
|---|
| 126 |     /// \brief The large value type | 
|---|
| 127 |     /// | 
|---|
| 128 |     /// The large value type used for internal computations. | 
|---|
| 129 |     /// Using the \ref HowardDefaultTraits "default traits class", | 
|---|
| 130 |     /// it is \c long \c long if the \c Value type is integer, | 
|---|
| 131 |     /// otherwise it is \c double. | 
|---|
| 132 |     typedef typename TR::LargeValue LargeValue; | 
|---|
| 133 |  | 
|---|
| 134 |     /// The tolerance type | 
|---|
| 135 |     typedef typename TR::Tolerance Tolerance; | 
|---|
| 136 |  | 
|---|
| 137 |     /// \brief The path type of the found cycles | 
|---|
| 138 |     /// | 
|---|
| 139 |     /// The path type of the found cycles. | 
|---|
| 140 |     /// Using the \ref HowardDefaultTraits "default traits class", | 
|---|
| 141 |     /// it is \ref lemon::Path "Path<Digraph>". | 
|---|
| 142 |     typedef typename TR::Path Path; | 
|---|
| 143 |  | 
|---|
| 144 |     /// The \ref HowardDefaultTraits "traits class" of the algorithm | 
|---|
| 145 |     typedef TR Traits; | 
|---|
| 146 |  | 
|---|
| 147 |   private: | 
|---|
| 148 |  | 
|---|
| 149 |     TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); | 
|---|
| 150 |    | 
|---|
| 151 |     // The digraph the algorithm runs on | 
|---|
| 152 |     const Digraph &_gr; | 
|---|
| 153 |     // The length of the arcs | 
|---|
| 154 |     const LengthMap &_length; | 
|---|
| 155 |  | 
|---|
| 156 |     // Data for the found cycles | 
|---|
| 157 |     bool _curr_found, _best_found; | 
|---|
| 158 |     LargeValue _curr_length, _best_length; | 
|---|
| 159 |     int _curr_size, _best_size; | 
|---|
| 160 |     Node _curr_node, _best_node; | 
|---|
| 161 |  | 
|---|
| 162 |     Path *_cycle_path; | 
|---|
| 163 |     bool _local_path; | 
|---|
| 164 |  | 
|---|
| 165 |     // Internal data used by the algorithm | 
|---|
| 166 |     typename Digraph::template NodeMap<Arc> _policy; | 
|---|
| 167 |     typename Digraph::template NodeMap<bool> _reached; | 
|---|
| 168 |     typename Digraph::template NodeMap<int> _level; | 
|---|
| 169 |     typename Digraph::template NodeMap<LargeValue> _dist; | 
|---|
| 170 |  | 
|---|
| 171 |     // Data for storing the strongly connected components | 
|---|
| 172 |     int _comp_num; | 
|---|
| 173 |     typename Digraph::template NodeMap<int> _comp; | 
|---|
| 174 |     std::vector<std::vector<Node> > _comp_nodes; | 
|---|
| 175 |     std::vector<Node>* _nodes; | 
|---|
| 176 |     typename Digraph::template NodeMap<std::vector<Arc> > _in_arcs; | 
|---|
| 177 |      | 
|---|
| 178 |     // Queue used for BFS search | 
|---|
| 179 |     std::vector<Node> _queue; | 
|---|
| 180 |     int _qfront, _qback; | 
|---|
| 181 |  | 
|---|
| 182 |     Tolerance _tolerance; | 
|---|
| 183 |    | 
|---|
| 184 |     // Infinite constant | 
|---|
| 185 |     const LargeValue INF; | 
|---|
| 186 |  | 
|---|
| 187 |   public: | 
|---|
| 188 |    | 
|---|
| 189 |     /// \name Named Template Parameters | 
|---|
| 190 |     /// @{ | 
|---|
| 191 |  | 
|---|
| 192 |     template <typename T> | 
|---|
| 193 |     struct SetLargeValueTraits : public Traits { | 
|---|
| 194 |       typedef T LargeValue; | 
|---|
| 195 |       typedef lemon::Tolerance<T> Tolerance; | 
|---|
| 196 |     }; | 
|---|
| 197 |  | 
|---|
| 198 |     /// \brief \ref named-templ-param "Named parameter" for setting | 
|---|
| 199 |     /// \c LargeValue type. | 
|---|
| 200 |     /// | 
|---|
| 201 |     /// \ref named-templ-param "Named parameter" for setting \c LargeValue | 
|---|
| 202 |     /// type. It is used for internal computations in the algorithm. | 
|---|
| 203 |     template <typename T> | 
|---|
| 204 |     struct SetLargeValue | 
|---|
| 205 |       : public Howard<GR, LEN, SetLargeValueTraits<T> > { | 
|---|
| 206 |       typedef Howard<GR, LEN, SetLargeValueTraits<T> > Create; | 
|---|
| 207 |     }; | 
|---|
| 208 |  | 
|---|
| 209 |     template <typename T> | 
|---|
| 210 |     struct SetPathTraits : public Traits { | 
|---|
| 211 |       typedef T Path; | 
|---|
| 212 |     }; | 
|---|
| 213 |  | 
|---|
| 214 |     /// \brief \ref named-templ-param "Named parameter" for setting | 
|---|
| 215 |     /// \c %Path type. | 
|---|
| 216 |     /// | 
|---|
| 217 |     /// \ref named-templ-param "Named parameter" for setting the \c %Path | 
|---|
| 218 |     /// type of the found cycles. | 
|---|
| 219 |     /// It must conform to the \ref lemon::concepts::Path "Path" concept | 
|---|
| 220 |     /// and it must have an \c addBack() function. | 
|---|
| 221 |     template <typename T> | 
|---|
| 222 |     struct SetPath | 
|---|
| 223 |       : public Howard<GR, LEN, SetPathTraits<T> > { | 
|---|
| 224 |       typedef Howard<GR, LEN, SetPathTraits<T> > Create; | 
|---|
| 225 |     }; | 
|---|
| 226 |      | 
|---|
| 227 |     /// @} | 
|---|
| 228 |  | 
|---|
| 229 |   public: | 
|---|
| 230 |  | 
|---|
| 231 |     /// \brief Constructor. | 
|---|
| 232 |     /// | 
|---|
| 233 |     /// The constructor of the class. | 
|---|
| 234 |     /// | 
|---|
| 235 |     /// \param digraph The digraph the algorithm runs on. | 
|---|
| 236 |     /// \param length The lengths (costs) of the arcs. | 
|---|
| 237 |     Howard( const Digraph &digraph, | 
|---|
| 238 |             const LengthMap &length ) : | 
|---|
| 239 |       _gr(digraph), _length(length), _best_found(false), | 
|---|
| 240 |       _best_length(0), _best_size(1), _cycle_path(NULL), _local_path(false), | 
|---|
| 241 |       _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph), | 
|---|
| 242 |       _comp(digraph), _in_arcs(digraph), | 
|---|
| 243 |       INF(std::numeric_limits<LargeValue>::has_infinity ? | 
|---|
| 244 |           std::numeric_limits<LargeValue>::infinity() : | 
|---|
| 245 |           std::numeric_limits<LargeValue>::max()) | 
|---|
| 246 |     {} | 
|---|
| 247 |  | 
|---|
| 248 |     /// Destructor. | 
|---|
| 249 |     ~Howard() { | 
|---|
| 250 |       if (_local_path) delete _cycle_path; | 
|---|
| 251 |     } | 
|---|
| 252 |  | 
|---|
| 253 |     /// \brief Set the path structure for storing the found cycle. | 
|---|
| 254 |     /// | 
|---|
| 255 |     /// This function sets an external path structure for storing the | 
|---|
| 256 |     /// found cycle. | 
|---|
| 257 |     /// | 
|---|
| 258 |     /// If you don't call this function before calling \ref run() or | 
|---|
| 259 |     /// \ref findMinMean(), it will allocate a local \ref Path "path" | 
|---|
| 260 |     /// structure. The destuctor deallocates this automatically | 
|---|
| 261 |     /// allocated object, of course. | 
|---|
| 262 |     /// | 
|---|
| 263 |     /// \note The algorithm calls only the \ref lemon::Path::addBack() | 
|---|
| 264 |     /// "addBack()" function of the given path structure. | 
|---|
| 265 |     /// | 
|---|
| 266 |     /// \return <tt>(*this)</tt> | 
|---|
| 267 |     Howard& cycle(Path &path) { | 
|---|
| 268 |       if (_local_path) { | 
|---|
| 269 |         delete _cycle_path; | 
|---|
| 270 |         _local_path = false; | 
|---|
| 271 |       } | 
|---|
| 272 |       _cycle_path = &path; | 
|---|
| 273 |       return *this; | 
|---|
| 274 |     } | 
|---|
| 275 |  | 
|---|
| 276 |     /// \name Execution control | 
|---|
| 277 |     /// The simplest way to execute the algorithm is to call the \ref run() | 
|---|
| 278 |     /// function.\n | 
|---|
| 279 |     /// If you only need the minimum mean length, you may call | 
|---|
| 280 |     /// \ref findMinMean(). | 
|---|
| 281 |  | 
|---|
| 282 |     /// @{ | 
|---|
| 283 |  | 
|---|
| 284 |     /// \brief Run the algorithm. | 
|---|
| 285 |     /// | 
|---|
| 286 |     /// This function runs the algorithm. | 
|---|
| 287 |     /// It can be called more than once (e.g. if the underlying digraph | 
|---|
| 288 |     /// and/or the arc lengths have been modified). | 
|---|
| 289 |     /// | 
|---|
| 290 |     /// \return \c true if a directed cycle exists in the digraph. | 
|---|
| 291 |     /// | 
|---|
| 292 |     /// \note <tt>mmc.run()</tt> is just a shortcut of the following code. | 
|---|
| 293 |     /// \code | 
|---|
| 294 |     ///   return mmc.findMinMean() && mmc.findCycle(); | 
|---|
| 295 |     /// \endcode | 
|---|
| 296 |     bool run() { | 
|---|
| 297 |       return findMinMean() && findCycle(); | 
|---|
| 298 |     } | 
|---|
| 299 |  | 
|---|
| 300 |     /// \brief Find the minimum cycle mean. | 
|---|
| 301 |     /// | 
|---|
| 302 |     /// This function finds the minimum mean length of the directed | 
|---|
| 303 |     /// cycles in the digraph. | 
|---|
| 304 |     /// | 
|---|
| 305 |     /// \return \c true if a directed cycle exists in the digraph. | 
|---|
| 306 |     bool findMinMean() { | 
|---|
| 307 |       // Initialize and find strongly connected components | 
|---|
| 308 |       init(); | 
|---|
| 309 |       findComponents(); | 
|---|
| 310 |        | 
|---|
| 311 |       // Find the minimum cycle mean in the components | 
|---|
| 312 |       for (int comp = 0; comp < _comp_num; ++comp) { | 
|---|
| 313 |         // Find the minimum mean cycle in the current component | 
|---|
| 314 |         if (!buildPolicyGraph(comp)) continue; | 
|---|
| 315 |         while (true) { | 
|---|
| 316 |           findPolicyCycle(); | 
|---|
| 317 |           if (!computeNodeDistances()) break; | 
|---|
| 318 |         } | 
|---|
| 319 |         // Update the best cycle (global minimum mean cycle) | 
|---|
| 320 |         if ( _curr_found && (!_best_found || | 
|---|
| 321 |              _curr_length * _best_size < _best_length * _curr_size) ) { | 
|---|
| 322 |           _best_found = true; | 
|---|
| 323 |           _best_length = _curr_length; | 
|---|
| 324 |           _best_size = _curr_size; | 
|---|
| 325 |           _best_node = _curr_node; | 
|---|
| 326 |         } | 
|---|
| 327 |       } | 
|---|
| 328 |       return _best_found; | 
|---|
| 329 |     } | 
|---|
| 330 |  | 
|---|
| 331 |     /// \brief Find a minimum mean directed cycle. | 
|---|
| 332 |     /// | 
|---|
| 333 |     /// This function finds a directed cycle of minimum mean length | 
|---|
| 334 |     /// in the digraph using the data computed by findMinMean(). | 
|---|
| 335 |     /// | 
|---|
| 336 |     /// \return \c true if a directed cycle exists in the digraph. | 
|---|
| 337 |     /// | 
|---|
| 338 |     /// \pre \ref findMinMean() must be called before using this function. | 
|---|
| 339 |     bool findCycle() { | 
|---|
| 340 |       if (!_best_found) return false; | 
|---|
| 341 |       _cycle_path->addBack(_policy[_best_node]); | 
|---|
| 342 |       for ( Node v = _best_node; | 
|---|
| 343 |             (v = _gr.target(_policy[v])) != _best_node; ) { | 
|---|
| 344 |         _cycle_path->addBack(_policy[v]); | 
|---|
| 345 |       } | 
|---|
| 346 |       return true; | 
|---|
| 347 |     } | 
|---|
| 348 |  | 
|---|
| 349 |     /// @} | 
|---|
| 350 |  | 
|---|
| 351 |     /// \name Query Functions | 
|---|
| 352 |     /// The results of the algorithm can be obtained using these | 
|---|
| 353 |     /// functions.\n | 
|---|
| 354 |     /// The algorithm should be executed before using them. | 
|---|
| 355 |  | 
|---|
| 356 |     /// @{ | 
|---|
| 357 |  | 
|---|
| 358 |     /// \brief Return the total length of the found cycle. | 
|---|
| 359 |     /// | 
|---|
| 360 |     /// This function returns the total length of the found cycle. | 
|---|
| 361 |     /// | 
|---|
| 362 |     /// \pre \ref run() or \ref findMinMean() must be called before | 
|---|
| 363 |     /// using this function. | 
|---|
| 364 |     LargeValue cycleLength() const { | 
|---|
| 365 |       return _best_length; | 
|---|
| 366 |     } | 
|---|
| 367 |  | 
|---|
| 368 |     /// \brief Return the number of arcs on the found cycle. | 
|---|
| 369 |     /// | 
|---|
| 370 |     /// This function returns the number of arcs on the found cycle. | 
|---|
| 371 |     /// | 
|---|
| 372 |     /// \pre \ref run() or \ref findMinMean() must be called before | 
|---|
| 373 |     /// using this function. | 
|---|
| 374 |     int cycleArcNum() const { | 
|---|
| 375 |       return _best_size; | 
|---|
| 376 |     } | 
|---|
| 377 |  | 
|---|
| 378 |     /// \brief Return the mean length of the found cycle. | 
|---|
| 379 |     /// | 
|---|
| 380 |     /// This function returns the mean length of the found cycle. | 
|---|
| 381 |     /// | 
|---|
| 382 |     /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the | 
|---|
| 383 |     /// following code. | 
|---|
| 384 |     /// \code | 
|---|
| 385 |     ///   return static_cast<double>(alg.cycleLength()) / alg.cycleArcNum(); | 
|---|
| 386 |     /// \endcode | 
|---|
| 387 |     /// | 
|---|
| 388 |     /// \pre \ref run() or \ref findMinMean() must be called before | 
|---|
| 389 |     /// using this function. | 
|---|
| 390 |     double cycleMean() const { | 
|---|
| 391 |       return static_cast<double>(_best_length) / _best_size; | 
|---|
| 392 |     } | 
|---|
| 393 |  | 
|---|
| 394 |     /// \brief Return the found cycle. | 
|---|
| 395 |     /// | 
|---|
| 396 |     /// This function returns a const reference to the path structure | 
|---|
| 397 |     /// storing the found cycle. | 
|---|
| 398 |     /// | 
|---|
| 399 |     /// \pre \ref run() or \ref findCycle() must be called before using | 
|---|
| 400 |     /// this function. | 
|---|
| 401 |     const Path& cycle() const { | 
|---|
| 402 |       return *_cycle_path; | 
|---|
| 403 |     } | 
|---|
| 404 |  | 
|---|
| 405 |     ///@} | 
|---|
| 406 |  | 
|---|
| 407 |   private: | 
|---|
| 408 |  | 
|---|
| 409 |     // Initialize | 
|---|
| 410 |     void init() { | 
|---|
| 411 |       if (!_cycle_path) { | 
|---|
| 412 |         _local_path = true; | 
|---|
| 413 |         _cycle_path = new Path; | 
|---|
| 414 |       } | 
|---|
| 415 |       _queue.resize(countNodes(_gr)); | 
|---|
| 416 |       _best_found = false; | 
|---|
| 417 |       _best_length = 0; | 
|---|
| 418 |       _best_size = 1; | 
|---|
| 419 |       _cycle_path->clear(); | 
|---|
| 420 |     } | 
|---|
| 421 |      | 
|---|
| 422 |     // Find strongly connected components and initialize _comp_nodes | 
|---|
| 423 |     // and _in_arcs | 
|---|
| 424 |     void findComponents() { | 
|---|
| 425 |       _comp_num = stronglyConnectedComponents(_gr, _comp); | 
|---|
| 426 |       _comp_nodes.resize(_comp_num); | 
|---|
| 427 |       if (_comp_num == 1) { | 
|---|
| 428 |         _comp_nodes[0].clear(); | 
|---|
| 429 |         for (NodeIt n(_gr); n != INVALID; ++n) { | 
|---|
| 430 |           _comp_nodes[0].push_back(n); | 
|---|
| 431 |           _in_arcs[n].clear(); | 
|---|
| 432 |           for (InArcIt a(_gr, n); a != INVALID; ++a) { | 
|---|
| 433 |             _in_arcs[n].push_back(a); | 
|---|
| 434 |           } | 
|---|
| 435 |         } | 
|---|
| 436 |       } else { | 
|---|
| 437 |         for (int i = 0; i < _comp_num; ++i) | 
|---|
| 438 |           _comp_nodes[i].clear(); | 
|---|
| 439 |         for (NodeIt n(_gr); n != INVALID; ++n) { | 
|---|
| 440 |           int k = _comp[n]; | 
|---|
| 441 |           _comp_nodes[k].push_back(n); | 
|---|
| 442 |           _in_arcs[n].clear(); | 
|---|
| 443 |           for (InArcIt a(_gr, n); a != INVALID; ++a) { | 
|---|
| 444 |             if (_comp[_gr.source(a)] == k) _in_arcs[n].push_back(a); | 
|---|
| 445 |           } | 
|---|
| 446 |         } | 
|---|
| 447 |       } | 
|---|
| 448 |     } | 
|---|
| 449 |  | 
|---|
| 450 |     // Build the policy graph in the given strongly connected component | 
|---|
| 451 |     // (the out-degree of every node is 1) | 
|---|
| 452 |     bool buildPolicyGraph(int comp) { | 
|---|
| 453 |       _nodes = &(_comp_nodes[comp]); | 
|---|
| 454 |       if (_nodes->size() < 1 || | 
|---|
| 455 |           (_nodes->size() == 1 && _in_arcs[(*_nodes)[0]].size() == 0)) { | 
|---|
| 456 |         return false; | 
|---|
| 457 |       } | 
|---|
| 458 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 459 |         _dist[(*_nodes)[i]] = INF; | 
|---|
| 460 |       } | 
|---|
| 461 |       Node u, v; | 
|---|
| 462 |       Arc e; | 
|---|
| 463 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 464 |         v = (*_nodes)[i]; | 
|---|
| 465 |         for (int j = 0; j < int(_in_arcs[v].size()); ++j) { | 
|---|
| 466 |           e = _in_arcs[v][j]; | 
|---|
| 467 |           u = _gr.source(e); | 
|---|
| 468 |           if (_length[e] < _dist[u]) { | 
|---|
| 469 |             _dist[u] = _length[e]; | 
|---|
| 470 |             _policy[u] = e; | 
|---|
| 471 |           } | 
|---|
| 472 |         } | 
|---|
| 473 |       } | 
|---|
| 474 |       return true; | 
|---|
| 475 |     } | 
|---|
| 476 |  | 
|---|
| 477 |     // Find the minimum mean cycle in the policy graph | 
|---|
| 478 |     void findPolicyCycle() { | 
|---|
| 479 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 480 |         _level[(*_nodes)[i]] = -1; | 
|---|
| 481 |       } | 
|---|
| 482 |       LargeValue clength; | 
|---|
| 483 |       int csize; | 
|---|
| 484 |       Node u, v; | 
|---|
| 485 |       _curr_found = false; | 
|---|
| 486 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 487 |         u = (*_nodes)[i]; | 
|---|
| 488 |         if (_level[u] >= 0) continue; | 
|---|
| 489 |         for (; _level[u] < 0; u = _gr.target(_policy[u])) { | 
|---|
| 490 |           _level[u] = i; | 
|---|
| 491 |         } | 
|---|
| 492 |         if (_level[u] == i) { | 
|---|
| 493 |           // A cycle is found | 
|---|
| 494 |           clength = _length[_policy[u]]; | 
|---|
| 495 |           csize = 1; | 
|---|
| 496 |           for (v = u; (v = _gr.target(_policy[v])) != u; ) { | 
|---|
| 497 |             clength += _length[_policy[v]]; | 
|---|
| 498 |             ++csize; | 
|---|
| 499 |           } | 
|---|
| 500 |           if ( !_curr_found || | 
|---|
| 501 |                (clength * _curr_size < _curr_length * csize) ) { | 
|---|
| 502 |             _curr_found = true; | 
|---|
| 503 |             _curr_length = clength; | 
|---|
| 504 |             _curr_size = csize; | 
|---|
| 505 |             _curr_node = u; | 
|---|
| 506 |           } | 
|---|
| 507 |         } | 
|---|
| 508 |       } | 
|---|
| 509 |     } | 
|---|
| 510 |  | 
|---|
| 511 |     // Contract the policy graph and compute node distances | 
|---|
| 512 |     bool computeNodeDistances() { | 
|---|
| 513 |       // Find the component of the main cycle and compute node distances | 
|---|
| 514 |       // using reverse BFS | 
|---|
| 515 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 516 |         _reached[(*_nodes)[i]] = false; | 
|---|
| 517 |       } | 
|---|
| 518 |       _qfront = _qback = 0; | 
|---|
| 519 |       _queue[0] = _curr_node; | 
|---|
| 520 |       _reached[_curr_node] = true; | 
|---|
| 521 |       _dist[_curr_node] = 0; | 
|---|
| 522 |       Node u, v; | 
|---|
| 523 |       Arc e; | 
|---|
| 524 |       while (_qfront <= _qback) { | 
|---|
| 525 |         v = _queue[_qfront++]; | 
|---|
| 526 |         for (int j = 0; j < int(_in_arcs[v].size()); ++j) { | 
|---|
| 527 |           e = _in_arcs[v][j]; | 
|---|
| 528 |           u = _gr.source(e); | 
|---|
| 529 |           if (_policy[u] == e && !_reached[u]) { | 
|---|
| 530 |             _reached[u] = true; | 
|---|
| 531 |             _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length; | 
|---|
| 532 |             _queue[++_qback] = u; | 
|---|
| 533 |           } | 
|---|
| 534 |         } | 
|---|
| 535 |       } | 
|---|
| 536 |  | 
|---|
| 537 |       // Connect all other nodes to this component and compute node | 
|---|
| 538 |       // distances using reverse BFS | 
|---|
| 539 |       _qfront = 0; | 
|---|
| 540 |       while (_qback < int(_nodes->size())-1) { | 
|---|
| 541 |         v = _queue[_qfront++]; | 
|---|
| 542 |         for (int j = 0; j < int(_in_arcs[v].size()); ++j) { | 
|---|
| 543 |           e = _in_arcs[v][j]; | 
|---|
| 544 |           u = _gr.source(e); | 
|---|
| 545 |           if (!_reached[u]) { | 
|---|
| 546 |             _reached[u] = true; | 
|---|
| 547 |             _policy[u] = e; | 
|---|
| 548 |             _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length; | 
|---|
| 549 |             _queue[++_qback] = u; | 
|---|
| 550 |           } | 
|---|
| 551 |         } | 
|---|
| 552 |       } | 
|---|
| 553 |  | 
|---|
| 554 |       // Improve node distances | 
|---|
| 555 |       bool improved = false; | 
|---|
| 556 |       for (int i = 0; i < int(_nodes->size()); ++i) { | 
|---|
| 557 |         v = (*_nodes)[i]; | 
|---|
| 558 |         for (int j = 0; j < int(_in_arcs[v].size()); ++j) { | 
|---|
| 559 |           e = _in_arcs[v][j]; | 
|---|
| 560 |           u = _gr.source(e); | 
|---|
| 561 |           LargeValue delta = _dist[v] + _length[e] * _curr_size - _curr_length; | 
|---|
| 562 |           if (_tolerance.less(delta, _dist[u])) { | 
|---|
| 563 |             _dist[u] = delta; | 
|---|
| 564 |             _policy[u] = e; | 
|---|
| 565 |             improved = true; | 
|---|
| 566 |           } | 
|---|
| 567 |         } | 
|---|
| 568 |       } | 
|---|
| 569 |       return improved; | 
|---|
| 570 |     } | 
|---|
| 571 |  | 
|---|
| 572 |   }; //class Howard | 
|---|
| 573 |  | 
|---|
| 574 |   ///@} | 
|---|
| 575 |  | 
|---|
| 576 | } //namespace lemon | 
|---|
| 577 |  | 
|---|
| 578 | #endif //LEMON_HOWARD_H | 
|---|