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 ↑
Show white space 192 line context
... ...
@@ -189,192 +189,210 @@
189 189
    // The processed nodes in the last round
190 190
    std::vector<Node> _process;
191 191

	
192 192
    Tolerance _tolerance;
193 193

	
194 194
    // Infinite constant
195 195
    const LargeValue INF;
196 196

	
197 197
  public:
198 198

	
199 199
    /// \name Named Template Parameters
200 200
    /// @{
201 201

	
202 202
    template <typename T>
203 203
    struct SetLargeValueTraits : public Traits {
204 204
      typedef T LargeValue;
205 205
      typedef lemon::Tolerance<T> Tolerance;
206 206
    };
207 207

	
208 208
    /// \brief \ref named-templ-param "Named parameter" for setting
209 209
    /// \c LargeValue type.
210 210
    ///
211 211
    /// \ref named-templ-param "Named parameter" for setting \c LargeValue
212 212
    /// type. It is used for internal computations in the algorithm.
213 213
    template <typename T>
214 214
    struct SetLargeValue
215 215
      : public HartmannOrlin<GR, LEN, SetLargeValueTraits<T> > {
216 216
      typedef HartmannOrlin<GR, LEN, SetLargeValueTraits<T> > Create;
217 217
    };
218 218

	
219 219
    template <typename T>
220 220
    struct SetPathTraits : public Traits {
221 221
      typedef T Path;
222 222
    };
223 223

	
224 224
    /// \brief \ref named-templ-param "Named parameter" for setting
225 225
    /// \c %Path type.
226 226
    ///
227 227
    /// \ref named-templ-param "Named parameter" for setting the \c %Path
228 228
    /// type of the found cycles.
229 229
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
230 230
    /// and it must have an \c addFront() function.
231 231
    template <typename T>
232 232
    struct SetPath
233 233
      : public HartmannOrlin<GR, LEN, SetPathTraits<T> > {
234 234
      typedef HartmannOrlin<GR, LEN, SetPathTraits<T> > Create;
235 235
    };
236 236

	
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;
333 351
        }
334 352
      }
335 353
      return _best_found;
336 354
    }
337 355

	
338 356
    /// \brief Find a minimum mean directed cycle.
339 357
    ///
340 358
    /// This function finds a directed cycle of minimum mean length
341 359
    /// in the digraph using the data computed by findMinMean().
342 360
    ///
343 361
    /// \return \c true if a directed cycle exists in the digraph.
344 362
    ///
345 363
    /// \pre \ref findMinMean() must be called before using this function.
346 364
    bool findCycle() {
347 365
      if (!_best_found) return false;
348 366
      IntNodeMap reached(_gr, -1);
349 367
      int r = _best_level + 1;
350 368
      Node u = _best_node;
351 369
      while (reached[u] < 0) {
352 370
        reached[u] = --r;
353 371
        u = _gr.source(_data[u][r].pred);
354 372
      }
355 373
      r = reached[u];
356 374
      Arc e = _data[u][r].pred;
357 375
      _cycle_path->addFront(e);
358 376
      _best_length = _length[e];
359 377
      _best_size = 1;
360 378
      Node v;
361 379
      while ((v = _gr.source(e)) != u) {
362 380
        e = _data[v][--r].pred;
363 381
        _cycle_path->addFront(e);
364 382
        _best_length += _length[e];
365 383
        ++_best_size;
366 384
      }
367 385
      return true;
368 386
    }
369 387

	
370 388
    /// @}
371 389

	
372 390
    /// \name Query Functions
373 391
    /// The results of the algorithm can be obtained using these
374 392
    /// functions.\n
375 393
    /// The algorithm should be executed before using them.
376 394

	
377 395
    /// @{
378 396

	
379 397
    /// \brief Return the total length of the found cycle.
380 398
    ///
Show white space 192 line context
... ...
@@ -180,192 +180,210 @@
180 180
    int _qfront, _qback;
181 181

	
182 182
    Tolerance _tolerance;
183 183
  
184 184
    // Infinite constant
185 185
    const LargeValue INF;
186 186

	
187 187
  public:
188 188
  
189 189
    /// \name Named Template Parameters
190 190
    /// @{
191 191

	
192 192
    template <typename T>
193 193
    struct SetLargeValueTraits : public Traits {
194 194
      typedef T LargeValue;
195 195
      typedef lemon::Tolerance<T> Tolerance;
196 196
    };
197 197

	
198 198
    /// \brief \ref named-templ-param "Named parameter" for setting
199 199
    /// \c LargeValue type.
200 200
    ///
201 201
    /// \ref named-templ-param "Named parameter" for setting \c LargeValue
202 202
    /// type. It is used for internal computations in the algorithm.
203 203
    template <typename T>
204 204
    struct SetLargeValue
205 205
      : public Howard<GR, LEN, SetLargeValueTraits<T> > {
206 206
      typedef Howard<GR, LEN, SetLargeValueTraits<T> > Create;
207 207
    };
208 208

	
209 209
    template <typename T>
210 210
    struct SetPathTraits : public Traits {
211 211
      typedef T Path;
212 212
    };
213 213

	
214 214
    /// \brief \ref named-templ-param "Named parameter" for setting
215 215
    /// \c %Path type.
216 216
    ///
217 217
    /// \ref named-templ-param "Named parameter" for setting the \c %Path
218 218
    /// type of the found cycles.
219 219
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
220 220
    /// and it must have an \c addBack() function.
221 221
    template <typename T>
222 222
    struct SetPath
223 223
      : public Howard<GR, LEN, SetPathTraits<T> > {
224 224
      typedef Howard<GR, LEN, SetPathTraits<T> > Create;
225 225
    };
226 226
    
227 227
    /// @}
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;
324 342
          _best_size = _curr_size;
325 343
          _best_node = _curr_node;
326 344
        }
327 345
      }
328 346
      return _best_found;
329 347
    }
330 348

	
331 349
    /// \brief Find a minimum mean directed cycle.
332 350
    ///
333 351
    /// This function finds a directed cycle of minimum mean length
334 352
    /// in the digraph using the data computed by findMinMean().
335 353
    ///
336 354
    /// \return \c true if a directed cycle exists in the digraph.
337 355
    ///
338 356
    /// \pre \ref findMinMean() must be called before using this function.
339 357
    bool findCycle() {
340 358
      if (!_best_found) return false;
341 359
      _cycle_path->addBack(_policy[_best_node]);
342 360
      for ( Node v = _best_node;
343 361
            (v = _gr.target(_policy[v])) != _best_node; ) {
344 362
        _cycle_path->addBack(_policy[v]);
345 363
      }
346 364
      return true;
347 365
    }
348 366

	
349 367
    /// @}
350 368

	
351 369
    /// \name Query Functions
352 370
    /// The results of the algorithm can be obtained using these
353 371
    /// functions.\n
354 372
    /// The algorithm should be executed before using them.
355 373

	
356 374
    /// @{
357 375

	
358 376
    /// \brief Return the total length of the found cycle.
359 377
    ///
360 378
    /// This function returns the total length of the found cycle.
361 379
    ///
362 380
    /// \pre \ref run() or \ref findMinMean() must be called before
363 381
    /// using this function.
364 382
    LargeValue cycleLength() const {
365 383
      return _best_length;
366 384
    }
367 385

	
368 386
    /// \brief Return the number of arcs on the found cycle.
369 387
    ///
370 388
    /// This function returns the number of arcs on the found cycle.
371 389
    ///
Show white space 192 line context
... ...
@@ -185,192 +185,210 @@
185 185
    // The processed nodes in the last round
186 186
    std::vector<Node> _process;
187 187

	
188 188
    Tolerance _tolerance;
189 189
    
190 190
    // Infinite constant
191 191
    const LargeValue INF;
192 192

	
193 193
  public:
194 194

	
195 195
    /// \name Named Template Parameters
196 196
    /// @{
197 197

	
198 198
    template <typename T>
199 199
    struct SetLargeValueTraits : public Traits {
200 200
      typedef T LargeValue;
201 201
      typedef lemon::Tolerance<T> Tolerance;
202 202
    };
203 203

	
204 204
    /// \brief \ref named-templ-param "Named parameter" for setting
205 205
    /// \c LargeValue type.
206 206
    ///
207 207
    /// \ref named-templ-param "Named parameter" for setting \c LargeValue
208 208
    /// type. It is used for internal computations in the algorithm.
209 209
    template <typename T>
210 210
    struct SetLargeValue
211 211
      : public Karp<GR, LEN, SetLargeValueTraits<T> > {
212 212
      typedef Karp<GR, LEN, SetLargeValueTraits<T> > Create;
213 213
    };
214 214

	
215 215
    template <typename T>
216 216
    struct SetPathTraits : public Traits {
217 217
      typedef T Path;
218 218
    };
219 219

	
220 220
    /// \brief \ref named-templ-param "Named parameter" for setting
221 221
    /// \c %Path type.
222 222
    ///
223 223
    /// \ref named-templ-param "Named parameter" for setting the \c %Path
224 224
    /// type of the found cycles.
225 225
    /// It must conform to the \ref lemon::concepts::Path "Path" concept
226 226
    /// and it must have an \c addFront() function.
227 227
    template <typename T>
228 228
    struct SetPath
229 229
      : public Karp<GR, LEN, SetPathTraits<T> > {
230 230
      typedef Karp<GR, LEN, SetPathTraits<T> > Create;
231 231
    };
232 232

	
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().
329 347
    ///
330 348
    /// \return \c true if a directed cycle exists in the digraph.
331 349
    ///
332 350
    /// \pre \ref findMinMean() must be called before using this function.
333 351
    bool findCycle() {
334 352
      if (_cycle_node == INVALID) return false;
335 353
      IntNodeMap reached(_gr, -1);
336 354
      int r = _data[_cycle_node].size();
337 355
      Node u = _cycle_node;
338 356
      while (reached[u] < 0) {
339 357
        reached[u] = --r;
340 358
        u = _gr.source(_data[u][r].pred);
341 359
      }
342 360
      r = reached[u];
343 361
      Arc e = _data[u][r].pred;
344 362
      _cycle_path->addFront(e);
345 363
      _cycle_length = _length[e];
346 364
      _cycle_size = 1;
347 365
      Node v;
348 366
      while ((v = _gr.source(e)) != u) {
349 367
        e = _data[v][--r].pred;
350 368
        _cycle_path->addFront(e);
351 369
        _cycle_length += _length[e];
352 370
        ++_cycle_size;
353 371
      }
354 372
      return true;
355 373
    }
356 374

	
357 375
    /// @}
358 376

	
359 377
    /// \name Query Functions
360 378
    /// The results of the algorithm can be obtained using these
361 379
    /// functions.\n
362 380
    /// The algorithm should be executed before using them.
363 381

	
364 382
    /// @{
365 383

	
366 384
    /// \brief Return the total length of the found cycle.
367 385
    ///
368 386
    /// This function returns the total length of the found cycle.
369 387
    ///
370 388
    /// \pre \ref run() or \ref findMinMean() must be called before
371 389
    /// using this function.
372 390
    LargeValue cycleLength() const {
373 391
      return _cycle_length;
374 392
    }
375 393

	
376 394
    /// \brief Return the number of arcs on the found cycle.
Show white space 192 line context
1 1
/* -*- mode: C++; indent-tabs-mode: nil; -*-
2 2
 *
3 3
 * This file is a part of LEMON, a generic C++ optimization library.
4 4
 *
5 5
 * Copyright (C) 2003-2009
6 6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
8 8
 *
9 9
 * Permission to use, modify and distribute this software is granted
10 10
 * provided that this copyright notice appears in all copies. For
11 11
 * precise terms see the accompanying LICENSE file.
12 12
 *
13 13
 * This software is provided "AS IS" with no warranty of any kind,
14 14
 * express or implied, and with no claim as to its suitability for any
15 15
 * purpose.
16 16
 *
17 17
 */
18 18

	
19 19
#include <iostream>
20 20
#include <sstream>
21 21

	
22 22
#include <lemon/smart_graph.h>
23 23
#include <lemon/lgf_reader.h>
24 24
#include <lemon/path.h>
25 25
#include <lemon/concepts/digraph.h>
26 26
#include <lemon/concept_check.h>
27 27

	
28 28
#include <lemon/karp.h>
29 29
#include <lemon/hartmann_orlin.h>
30 30
#include <lemon/howard.h>
31 31

	
32 32
#include "test_tools.h"
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;
129 132
};
130 133

	
131 134
template <typename T>
132 135
struct IsSameType<T,T> {
133 136
  static const int result = 1;
134 137
};
135 138

	
136 139

	
137 140
int main() {
138 141
  #ifdef LEMON_HAVE_LONG_LONG
139 142
    typedef long long long_int;
140 143
  #else
141 144
    typedef long long_int;
142 145
  #endif
143 146

	
144 147
  // Check the interface
145 148
  {
146 149
    typedef concepts::Digraph GR;
147 150

	
148 151
    // Karp
149 152
    checkConcept< MmcClassConcept<GR, int>,
150 153
                  Karp<GR, concepts::ReadMap<GR::Arc, int> > >();
151 154
    checkConcept< MmcClassConcept<GR, float>,
152 155
                  Karp<GR, concepts::ReadMap<GR::Arc, float> > >();
153 156
    
154 157
    // HartmannOrlin
155 158
    checkConcept< MmcClassConcept<GR, int>,
156 159
                  HartmannOrlin<GR, concepts::ReadMap<GR::Arc, int> > >();
157 160
    checkConcept< MmcClassConcept<GR, float>,
158 161
                  HartmannOrlin<GR, concepts::ReadMap<GR::Arc, float> > >();
159 162
    
160 163
    // Howard
161 164
    checkConcept< MmcClassConcept<GR, int>,
162 165
                  Howard<GR, concepts::ReadMap<GR::Arc, int> > >();
163 166
    checkConcept< MmcClassConcept<GR, float>,
164 167
                  Howard<GR, concepts::ReadMap<GR::Arc, float> > >();
165 168

	
166 169
    if (IsSameType<Howard<GR, concepts::ReadMap<GR::Arc, int> >::LargeValue,
167 170
          long_int>::result == 0) check(false, "Wrong LargeValue type");
168 171
    if (IsSameType<Howard<GR, concepts::ReadMap<GR::Arc, float> >::LargeValue,
169 172
          double>::result == 0) check(false, "Wrong LargeValue type");
170 173
  }
171 174

	
172 175
  // Run various tests
173 176
  {
174 177
    typedef SmartDigraph GR;
175 178
    DIGRAPH_TYPEDEFS(GR);
176 179
    
0 comments (0 inline)