gravatar
kpeter (Peter Kovacs)
kpeter@inf.elte.hu
Add tolerance() functions for MMC classes (#179)
0 4 0
default
4 files changed with 57 insertions and 0 deletions:
↑ Collapse diff ↑
Ignore white space 6 line context
... ...
@@ -237,96 +237,114 @@
237 237
    /// @}
238 238

	
239 239
  public:
240 240

	
241 241
    /// \brief Constructor.
242 242
    ///
243 243
    /// The constructor of the class.
244 244
    ///
245 245
    /// \param digraph The digraph the algorithm runs on.
246 246
    /// \param length The lengths (costs) of the arcs.
247 247
    HartmannOrlin( const Digraph &digraph,
248 248
                   const LengthMap &length ) :
249 249
      _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph),
250 250
      _best_found(false), _best_length(0), _best_size(1),
251 251
      _cycle_path(NULL), _local_path(false), _data(digraph),
252 252
      INF(std::numeric_limits<LargeValue>::has_infinity ?
253 253
          std::numeric_limits<LargeValue>::infinity() :
254 254
          std::numeric_limits<LargeValue>::max())
255 255
    {}
256 256

	
257 257
    /// Destructor.
258 258
    ~HartmannOrlin() {
259 259
      if (_local_path) delete _cycle_path;
260 260
    }
261 261

	
262 262
    /// \brief Set the path structure for storing the found cycle.
263 263
    ///
264 264
    /// This function sets an external path structure for storing the
265 265
    /// found cycle.
266 266
    ///
267 267
    /// If you don't call this function before calling \ref run() or
268 268
    /// \ref findMinMean(), it will allocate a local \ref Path "path"
269 269
    /// structure. The destuctor deallocates this automatically
270 270
    /// allocated object, of course.
271 271
    ///
272 272
    /// \note The algorithm calls only the \ref lemon::Path::addFront()
273 273
    /// "addFront()" function of the given path structure.
274 274
    ///
275 275
    /// \return <tt>(*this)</tt>
276 276
    HartmannOrlin& cycle(Path &path) {
277 277
      if (_local_path) {
278 278
        delete _cycle_path;
279 279
        _local_path = false;
280 280
      }
281 281
      _cycle_path = &path;
282 282
      return *this;
283 283
    }
284 284

	
285
    /// \brief Set the tolerance used by the algorithm.
286
    ///
287
    /// This function sets the tolerance object used by the algorithm.
288
    ///
289
    /// \return <tt>(*this)</tt>
290
    HartmannOrlin& tolerance(const Tolerance& tolerance) {
291
      _tolerance = tolerance;
292
      return *this;
293
    }
294

	
295
    /// \brief Return a const reference to the tolerance.
296
    ///
297
    /// This function returns a const reference to the tolerance object
298
    /// used by the algorithm.
299
    const Tolerance& tolerance() const {
300
      return _tolerance;
301
    }
302

	
285 303
    /// \name Execution control
286 304
    /// The simplest way to execute the algorithm is to call the \ref run()
287 305
    /// function.\n
288 306
    /// If you only need the minimum mean length, you may call
289 307
    /// \ref findMinMean().
290 308

	
291 309
    /// @{
292 310

	
293 311
    /// \brief Run the algorithm.
294 312
    ///
295 313
    /// This function runs the algorithm.
296 314
    /// It can be called more than once (e.g. if the underlying digraph
297 315
    /// and/or the arc lengths have been modified).
298 316
    ///
299 317
    /// \return \c true if a directed cycle exists in the digraph.
300 318
    ///
301 319
    /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
302 320
    /// \code
303 321
    ///   return mmc.findMinMean() && mmc.findCycle();
304 322
    /// \endcode
305 323
    bool run() {
306 324
      return findMinMean() && findCycle();
307 325
    }
308 326

	
309 327
    /// \brief Find the minimum cycle mean.
310 328
    ///
311 329
    /// This function finds the minimum mean length of the directed
312 330
    /// cycles in the digraph.
313 331
    ///
314 332
    /// \return \c true if a directed cycle exists in the digraph.
315 333
    bool findMinMean() {
316 334
      // Initialization and find strongly connected components
317 335
      init();
318 336
      findComponents();
319 337
      
320 338
      // Find the minimum cycle mean in the components
321 339
      for (int comp = 0; comp < _comp_num; ++comp) {
322 340
        if (!initComponent(comp)) continue;
323 341
        processRounds();
324 342
        
325 343
        // Update the best cycle (global minimum mean cycle)
326 344
        if ( _curr_found && (!_best_found || 
327 345
             _curr_length * _best_size < _best_length * _curr_size) ) {
328 346
          _best_found = true;
329 347
          _best_length = _curr_length;
330 348
          _best_size = _curr_size;
331 349
          _best_node = _curr_node;
332 350
          _best_level = _curr_level;
Ignore white space 6 line context
... ...
@@ -228,96 +228,114 @@
228 228

	
229 229
  public:
230 230

	
231 231
    /// \brief Constructor.
232 232
    ///
233 233
    /// The constructor of the class.
234 234
    ///
235 235
    /// \param digraph The digraph the algorithm runs on.
236 236
    /// \param length The lengths (costs) of the arcs.
237 237
    Howard( const Digraph &digraph,
238 238
            const LengthMap &length ) :
239 239
      _gr(digraph), _length(length), _best_found(false),
240 240
      _best_length(0), _best_size(1), _cycle_path(NULL), _local_path(false),
241 241
      _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph),
242 242
      _comp(digraph), _in_arcs(digraph),
243 243
      INF(std::numeric_limits<LargeValue>::has_infinity ?
244 244
          std::numeric_limits<LargeValue>::infinity() :
245 245
          std::numeric_limits<LargeValue>::max())
246 246
    {}
247 247

	
248 248
    /// Destructor.
249 249
    ~Howard() {
250 250
      if (_local_path) delete _cycle_path;
251 251
    }
252 252

	
253 253
    /// \brief Set the path structure for storing the found cycle.
254 254
    ///
255 255
    /// This function sets an external path structure for storing the
256 256
    /// found cycle.
257 257
    ///
258 258
    /// If you don't call this function before calling \ref run() or
259 259
    /// \ref findMinMean(), it will allocate a local \ref Path "path"
260 260
    /// structure. The destuctor deallocates this automatically
261 261
    /// allocated object, of course.
262 262
    ///
263 263
    /// \note The algorithm calls only the \ref lemon::Path::addBack()
264 264
    /// "addBack()" function of the given path structure.
265 265
    ///
266 266
    /// \return <tt>(*this)</tt>
267 267
    Howard& cycle(Path &path) {
268 268
      if (_local_path) {
269 269
        delete _cycle_path;
270 270
        _local_path = false;
271 271
      }
272 272
      _cycle_path = &path;
273 273
      return *this;
274 274
    }
275 275

	
276
    /// \brief Set the tolerance used by the algorithm.
277
    ///
278
    /// This function sets the tolerance object used by the algorithm.
279
    ///
280
    /// \return <tt>(*this)</tt>
281
    Howard& tolerance(const Tolerance& tolerance) {
282
      _tolerance = tolerance;
283
      return *this;
284
    }
285

	
286
    /// \brief Return a const reference to the tolerance.
287
    ///
288
    /// This function returns a const reference to the tolerance object
289
    /// used by the algorithm.
290
    const Tolerance& tolerance() const {
291
      return _tolerance;
292
    }
293

	
276 294
    /// \name Execution control
277 295
    /// The simplest way to execute the algorithm is to call the \ref run()
278 296
    /// function.\n
279 297
    /// If you only need the minimum mean length, you may call
280 298
    /// \ref findMinMean().
281 299

	
282 300
    /// @{
283 301

	
284 302
    /// \brief Run the algorithm.
285 303
    ///
286 304
    /// This function runs the algorithm.
287 305
    /// It can be called more than once (e.g. if the underlying digraph
288 306
    /// and/or the arc lengths have been modified).
289 307
    ///
290 308
    /// \return \c true if a directed cycle exists in the digraph.
291 309
    ///
292 310
    /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
293 311
    /// \code
294 312
    ///   return mmc.findMinMean() && mmc.findCycle();
295 313
    /// \endcode
296 314
    bool run() {
297 315
      return findMinMean() && findCycle();
298 316
    }
299 317

	
300 318
    /// \brief Find the minimum cycle mean.
301 319
    ///
302 320
    /// This function finds the minimum mean length of the directed
303 321
    /// cycles in the digraph.
304 322
    ///
305 323
    /// \return \c true if a directed cycle exists in the digraph.
306 324
    bool findMinMean() {
307 325
      // Initialize and find strongly connected components
308 326
      init();
309 327
      findComponents();
310 328
      
311 329
      // Find the minimum cycle mean in the components
312 330
      for (int comp = 0; comp < _comp_num; ++comp) {
313 331
        // Find the minimum mean cycle in the current component
314 332
        if (!buildPolicyGraph(comp)) continue;
315 333
        while (true) {
316 334
          findPolicyCycle();
317 335
          if (!computeNodeDistances()) break;
318 336
        }
319 337
        // Update the best cycle (global minimum mean cycle)
320 338
        if ( _curr_found && (!_best_found ||
321 339
             _curr_length * _best_size < _best_length * _curr_size) ) {
322 340
          _best_found = true;
323 341
          _best_length = _curr_length;
Ignore white space 96 line context
... ...
@@ -233,96 +233,114 @@
233 233
    /// @}
234 234

	
235 235
  public:
236 236

	
237 237
    /// \brief Constructor.
238 238
    ///
239 239
    /// The constructor of the class.
240 240
    ///
241 241
    /// \param digraph The digraph the algorithm runs on.
242 242
    /// \param length The lengths (costs) of the arcs.
243 243
    Karp( const Digraph &digraph,
244 244
          const LengthMap &length ) :
245 245
      _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph),
246 246
      _cycle_length(0), _cycle_size(1), _cycle_node(INVALID),
247 247
      _cycle_path(NULL), _local_path(false), _data(digraph),
248 248
      INF(std::numeric_limits<LargeValue>::has_infinity ?
249 249
          std::numeric_limits<LargeValue>::infinity() :
250 250
          std::numeric_limits<LargeValue>::max())
251 251
    {}
252 252

	
253 253
    /// Destructor.
254 254
    ~Karp() {
255 255
      if (_local_path) delete _cycle_path;
256 256
    }
257 257

	
258 258
    /// \brief Set the path structure for storing the found cycle.
259 259
    ///
260 260
    /// This function sets an external path structure for storing the
261 261
    /// found cycle.
262 262
    ///
263 263
    /// If you don't call this function before calling \ref run() or
264 264
    /// \ref findMinMean(), it will allocate a local \ref Path "path"
265 265
    /// structure. The destuctor deallocates this automatically
266 266
    /// allocated object, of course.
267 267
    ///
268 268
    /// \note The algorithm calls only the \ref lemon::Path::addFront()
269 269
    /// "addFront()" function of the given path structure.
270 270
    ///
271 271
    /// \return <tt>(*this)</tt>
272 272
    Karp& cycle(Path &path) {
273 273
      if (_local_path) {
274 274
        delete _cycle_path;
275 275
        _local_path = false;
276 276
      }
277 277
      _cycle_path = &path;
278 278
      return *this;
279 279
    }
280 280

	
281
    /// \brief Set the tolerance used by the algorithm.
282
    ///
283
    /// This function sets the tolerance object used by the algorithm.
284
    ///
285
    /// \return <tt>(*this)</tt>
286
    Karp& tolerance(const Tolerance& tolerance) {
287
      _tolerance = tolerance;
288
      return *this;
289
    }
290

	
291
    /// \brief Return a const reference to the tolerance.
292
    ///
293
    /// This function returns a const reference to the tolerance object
294
    /// used by the algorithm.
295
    const Tolerance& tolerance() const {
296
      return _tolerance;
297
    }
298

	
281 299
    /// \name Execution control
282 300
    /// The simplest way to execute the algorithm is to call the \ref run()
283 301
    /// function.\n
284 302
    /// If you only need the minimum mean length, you may call
285 303
    /// \ref findMinMean().
286 304

	
287 305
    /// @{
288 306

	
289 307
    /// \brief Run the algorithm.
290 308
    ///
291 309
    /// This function runs the algorithm.
292 310
    /// It can be called more than once (e.g. if the underlying digraph
293 311
    /// and/or the arc lengths have been modified).
294 312
    ///
295 313
    /// \return \c true if a directed cycle exists in the digraph.
296 314
    ///
297 315
    /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
298 316
    /// \code
299 317
    ///   return mmc.findMinMean() && mmc.findCycle();
300 318
    /// \endcode
301 319
    bool run() {
302 320
      return findMinMean() && findCycle();
303 321
    }
304 322

	
305 323
    /// \brief Find the minimum cycle mean.
306 324
    ///
307 325
    /// This function finds the minimum mean length of the directed
308 326
    /// cycles in the digraph.
309 327
    ///
310 328
    /// \return \c true if a directed cycle exists in the digraph.
311 329
    bool findMinMean() {
312 330
      // Initialization and find strongly connected components
313 331
      init();
314 332
      findComponents();
315 333
      
316 334
      // Find the minimum cycle mean in the components
317 335
      for (int comp = 0; comp < _comp_num; ++comp) {
318 336
        if (!initComponent(comp)) continue;
319 337
        processRounds();
320 338
        updateMinMean();
321 339
      }
322 340
      return (_cycle_node != INVALID);
323 341
    }
324 342

	
325 343
    /// \brief Find a minimum mean directed cycle.
326 344
    ///
327 345
    /// This function finds a directed cycle of minimum mean length
328 346
    /// in the digraph using the data computed by findMinMean().
Ignore white space 6 line context
... ...
@@ -33,96 +33,99 @@
33 33

	
34 34
using namespace lemon;
35 35

	
36 36
char test_lgf[] =
37 37
  "@nodes\n"
38 38
  "label\n"
39 39
  "1\n"
40 40
  "2\n"
41 41
  "3\n"
42 42
  "4\n"
43 43
  "5\n"
44 44
  "6\n"
45 45
  "7\n"
46 46
  "@arcs\n"
47 47
  "    len1 len2 len3 len4  c1 c2 c3 c4\n"
48 48
  "1 2    1    1    1    1   0  0  0  0\n"
49 49
  "2 4    5    5    5    5   1  0  0  0\n"
50 50
  "2 3    8    8    8    8   0  0  0  0\n"
51 51
  "3 2   -2    0    0    0   1  0  0  0\n"
52 52
  "3 4    4    4    4    4   0  0  0  0\n"
53 53
  "3 7   -4   -4   -4   -4   0  0  0  0\n"
54 54
  "4 1    2    2    2    2   0  0  0  0\n"
55 55
  "4 3    3    3    3    3   1  0  0  0\n"
56 56
  "4 4    3    3    0    0   0  0  1  0\n"
57 57
  "5 2    4    4    4    4   0  0  0  0\n"
58 58
  "5 6    3    3    3    3   0  1  0  0\n"
59 59
  "6 5    2    2    2    2   0  1  0  0\n"
60 60
  "6 4   -1   -1   -1   -1   0  0  0  0\n"
61 61
  "6 7    1    1    1    1   0  0  0  0\n"
62 62
  "7 7    4    4    4   -1   0  0  0  1\n";
63 63

	
64 64
                        
65 65
// Check the interface of an MMC algorithm
66 66
template <typename GR, typename Value>
67 67
struct MmcClassConcept
68 68
{
69 69
  template <typename MMC>
70 70
  struct Constraints {
71 71
    void constraints() {
72 72
      const Constraints& me = *this;
73 73

	
74 74
      typedef typename MMC
75 75
        ::template SetPath<ListPath<GR> >
76 76
        ::template SetLargeValue<Value>
77 77
        ::Create MmcAlg;
78 78
      MmcAlg mmc(me.g, me.length);
79 79
      const MmcAlg& const_mmc = mmc;
80 80
      
81
      typename MmcAlg::Tolerance tol = const_mmc.tolerance();
82
      mmc.tolerance(tol);
83
      
81 84
      b = mmc.cycle(p).run();
82 85
      b = mmc.findMinMean();
83 86
      b = mmc.findCycle();
84 87

	
85 88
      v = const_mmc.cycleLength();
86 89
      i = const_mmc.cycleArcNum();
87 90
      d = const_mmc.cycleMean();
88 91
      p = const_mmc.cycle();
89 92
    }
90 93

	
91 94
    typedef concepts::ReadMap<typename GR::Arc, Value> LM;
92 95
  
93 96
    GR g;
94 97
    LM length;
95 98
    ListPath<GR> p;
96 99
    Value v;
97 100
    int i;
98 101
    double d;
99 102
    bool b;
100 103
  };
101 104
};
102 105

	
103 106
// Perform a test with the given parameters
104 107
template <typename MMC>
105 108
void checkMmcAlg(const SmartDigraph& gr,
106 109
                 const SmartDigraph::ArcMap<int>& lm,
107 110
                 const SmartDigraph::ArcMap<int>& cm,
108 111
                 int length, int size) {
109 112
  MMC alg(gr, lm);
110 113
  alg.findMinMean();
111 114
  check(alg.cycleMean() == static_cast<double>(length) / size,
112 115
        "Wrong cycle mean");
113 116
  alg.findCycle();
114 117
  check(alg.cycleLength() == length && alg.cycleArcNum() == size,
115 118
        "Wrong path");
116 119
  SmartDigraph::ArcMap<int> cycle(gr, 0);
117 120
  for (typename MMC::Path::ArcIt a(alg.cycle()); a != INVALID; ++a) {
118 121
    ++cycle[a];
119 122
  }
120 123
  for (SmartDigraph::ArcIt a(gr); a != INVALID; ++a) {
121 124
    check(cm[a] == cycle[a], "Wrong path");
122 125
  }
123 126
}
124 127

	
125 128
// Class for comparing types
126 129
template <typename T1, typename T2>
127 130
struct IsSameType {
128 131
  static const int result = 0;
0 comments (0 inline)