lemon/tabu_search.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2067 cd414bfbe38b
child 2370 ed6539025f27
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
deba@2067
     1
/* -*- C++ -*-
deba@2067
     2
 *
deba@2067
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2067
     4
 *
deba@2067
     5
 * Copyright (C) 2003-2006
deba@2067
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2067
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2067
     8
 *
deba@2067
     9
 * Permission to use, modify and distribute this software is granted
deba@2067
    10
 * provided that this copyright notice appears in all copies. For
deba@2067
    11
 * precise terms see the accompanying LICENSE file.
deba@2067
    12
 *
deba@2067
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2067
    14
 * express or implied, and with no claim as to its suitability for any
deba@2067
    15
 * purpose.
deba@2067
    16
 *
deba@2067
    17
 */
deba@2067
    18
deba@2067
    19
deba@2067
    20
#ifndef LEMON_TABU_SEARCH_H
deba@2067
    21
#define LEMON_TABU_SEARCH_H
deba@2067
    22
deba@2067
    23
/// \ingroup experimental
deba@2067
    24
/// \file
deba@2067
    25
/// \brief TabuSearch algorithm.
deba@2067
    26
///
deba@2067
    27
/// \author Szabadkai Mark
deba@2067
    28
deba@2067
    29
#include <lemon/bits/utility.h>
deba@2067
    30
#include <lemon/error.h>
deba@2067
    31
#include <lemon/time_measure.h>
deba@2067
    32
#include <functional>
deba@2067
    33
#include <deque>
deba@2067
    34
deba@2067
    35
deba@2067
    36
namespace lemon {
deba@2067
    37
deba@2067
    38
  /// \brief Default Traits for TabuSearch class.
deba@2067
    39
  /// 
deba@2067
    40
  /// This template defines the needed types for the \ref TabuSearch class.
deba@2067
    41
  /// Is main purpos is to simplify the main class's template interface,
deba@2067
    42
  /// but it provides the EdgeIt type, passing to the concrete graph wheter
deba@2067
    43
  /// it is directed or undirected.
deba@2067
    44
#ifdef DOXYGEN
deba@2067
    45
  template< typename GRAPH, typename VALUE, 
deba@2067
    46
            typename HEIGHTMAP, typename BETTER, bool UNDIR >
deba@2067
    47
#else
deba@2067
    48
  template< typename GRAPH, typename VALUE,
deba@2067
    49
            typename HEIGHTMAP = typename GRAPH::template NodeMap<VALUE>,
deba@2067
    50
            typename BETTER = std::less<VALUE>,
deba@2067
    51
            bool UNDIR = UndirectedTagIndicator<GRAPH>::value >
deba@2067
    52
#endif
deba@2067
    53
  struct TabuSearchDefaultTraits {
deba@2067
    54
    typedef  VALUE  Value; 
deba@2067
    55
    typedef  BETTER  Better;
deba@2067
    56
deba@2067
    57
    typedef  GRAPH  Graph;
deba@2067
    58
    typedef  typename GRAPH::Node  Node;
deba@2067
    59
    typedef  HEIGHTMAP  HeightMap;
deba@2067
    60
deba@2067
    61
    typedef  typename GRAPH::IncEdgeIt  EdgeIt;
deba@2067
    62
  };
deba@2067
    63
deba@2067
    64
  template< typename GRAPH, typename VALUE, 
deba@2067
    65
            typename HEIGHTMAP, typename BETTER >
deba@2067
    66
  struct TabuSearchDefaultTraits< GRAPH, VALUE, HEIGHTMAP, BETTER, false > {
deba@2067
    67
    typedef  VALUE  Value;
deba@2067
    68
    typedef  BETTER  Better;
deba@2067
    69
deba@2067
    70
    typedef  GRAPH  Graph;
deba@2067
    71
    typedef  typename GRAPH::Node  Node;
deba@2067
    72
    typedef  HEIGHTMAP  HeightMap;
deba@2067
    73
deba@2067
    74
    typedef  typename GRAPH::OutEdgeIt  EdgeIt;
deba@2067
    75
  };
deba@2067
    76
deba@2067
    77
deba@2067
    78
deba@2067
    79
  /// \brief Policy hierarchy to controll the search algorithm.
deba@2067
    80
  ///
deba@2067
    81
  /// The fallowing template hierarchy offers a clean interface to define own
deba@2067
    82
  /// policies, and combine existing ones.
deba@2067
    83
  template< typename TS >
deba@2067
    84
  struct TabuSearchPolicyConcept {
deba@2067
    85
    void  target( TS *ts ) {}
deba@2067
    86
deba@2067
    87
    void  reset()  {}
deba@2067
    88
    bool  onStep() { return false; }
deba@2067
    89
    bool  onStick() { return false; }
deba@2067
    90
    bool  onImprove( const typename TS::Value &best ) { return false; }
deba@2067
    91
  };
deba@2067
    92
deba@2067
    93
  template< typename TS >
deba@2067
    94
  struct YesPolicy {
deba@2067
    95
    void  target( TS *ts ) {}
deba@2067
    96
deba@2067
    97
    void  reset()  {}
deba@2067
    98
    bool  onStep() { return true; }
deba@2067
    99
    bool  onStick() { return true; }
deba@2067
   100
    bool  onImprove( const typename TS::Value &best ) { return true; }
deba@2067
   101
  };
deba@2067
   102
deba@2067
   103
  template< typename TS >
deba@2067
   104
  struct NoPolicy : public TabuSearchPolicyConcept<TS> {};
deba@2067
   105
deba@2067
   106
  /// \brief Some basic methode, how tow Policies can be combined
deba@2067
   107
  struct PolicyAndCombination {
deba@2067
   108
    static bool  evaluate( const bool r1, const bool r2 ) {
deba@2067
   109
      return r1 && r2;
deba@2067
   110
    }
deba@2067
   111
  };
deba@2067
   112
deba@2067
   113
  struct PolicyOrCombination {
deba@2067
   114
    static bool  evaluate( const bool r1, const bool r2 ) {
deba@2067
   115
      return r1 || r2;
deba@2067
   116
    }
deba@2067
   117
  };
deba@2067
   118
deba@2067
   119
  /// \brief CombinePolicies
deba@2067
   120
  ///
deba@2067
   121
  /// It combines tow policies using the given combination methode (mainly
deba@2067
   122
  /// some of the basic logical methodes) to create a new one.
deba@2067
   123
#ifdef DOXYGEN
deba@2067
   124
  template< template<typename> class CP1, template<typename> class CP2, 
deba@2067
   125
            typename COMBINATION >
deba@2067
   126
#else
deba@2067
   127
  template< template<typename> class CP1, template<typename> class CP2,
deba@2067
   128
            typename COMBINATION = PolicyAndCombination >
deba@2067
   129
#endif
deba@2067
   130
  struct CombinePolicies {
deba@2067
   131
    template< typename TS >
deba@2067
   132
    struct Policy {
deba@2067
   133
      typedef CP1<TS>  Policy1;
deba@2067
   134
      typedef CP2<TS>  Policy2;
deba@2067
   135
      
deba@2067
   136
      Policy1  policy1;
deba@2067
   137
      Policy2  policy2;
deba@2067
   138
deba@2067
   139
      inline Policy() : policy1(), policy2() {}
deba@2067
   140
      inline Policy( const Policy1 &cp1, const Policy2 &cp2 ) 
deba@2067
   141
        : policy1(cp1), policy2(cp2) {}
deba@2067
   142
deba@2067
   143
      void  target( TS *ts ) {
deba@2067
   144
        policy1.target(ts), policy2.target(ts);
deba@2067
   145
      };
deba@2067
   146
deba@2067
   147
      void  reset() {
deba@2067
   148
        policy1.reset(), policy2.reset();
deba@2067
   149
      }
deba@2067
   150
deba@2067
   151
      bool  onStep() {
deba@2067
   152
        return cmb.evaluate( policy1.onStep(), policy2.onStep() );
deba@2067
   153
      }
deba@2067
   154
deba@2067
   155
      bool  onStick() {
deba@2067
   156
        return cmb.evaluate( policy1.onStick(), policy2.onStick() );
deba@2067
   157
      }
deba@2067
   158
deba@2067
   159
      bool  onImprove( const typename TS::Value &best ) {
deba@2067
   160
        return cmb.evaluate( policy1.onImprove(best), 
deba@2067
   161
                             policy2.onImprove(best) );
deba@2067
   162
      }
deba@2067
   163
deba@2067
   164
    private:
deba@2067
   165
      COMBINATION cmb;
deba@2067
   166
    };
deba@2067
   167
  };
deba@2067
   168
deba@2067
   169
deba@2067
   170
  /// \brief IterationPolicy limits the number of iterations and the
deba@2067
   171
  /// number of iterations without improvement
deba@2067
   172
  template< typename TS >
deba@2067
   173
  struct IterationPolicy {
deba@2067
   174
    IterationPolicy() : _it_lim(100000), _noimpr_it_lim(5000) {}
deba@2067
   175
    IterationPolicy( const long int itl, const long int noimpritl )
deba@2067
   176
      : _it_lim(itl), _noimpr_it_lim(noimpritl)
deba@2067
   177
    {}
deba@2067
   178
deba@2067
   179
    void  target( TS *ts ) {}
deba@2067
   180
deba@2067
   181
    void  reset() {
deba@2067
   182
      _it = _noimpr_it = 0;
deba@2067
   183
    }
deba@2067
   184
deba@2067
   185
    bool  onStep() {
deba@2067
   186
      ++_it; ++_noimpr_it;
deba@2067
   187
      return (_it <= _it_lim) && (_noimpr_it <= _noimpr_it_lim);
deba@2067
   188
    }
deba@2067
   189
		
deba@2067
   190
    bool  onStick() {
deba@2067
   191
      return false;
deba@2067
   192
    }
deba@2067
   193
deba@2067
   194
    bool  onImprove( const typename TS::Value &best ) {
deba@2067
   195
      _noimpr_it = 0;
deba@2067
   196
      return true;
deba@2067
   197
    }
deba@2067
   198
deba@2067
   199
    long int  iterationLimit() const {
deba@2067
   200
      return _it_lim;
deba@2067
   201
    }
deba@2067
   202
deba@2067
   203
    void  iterationLimit( const long int itl ) {
deba@2067
   204
      _it_lim = itl;
deba@2067
   205
    }
deba@2067
   206
deba@2067
   207
    long int  noImprovementIterationLimit() const {
deba@2067
   208
      return _noimpr_it_lim;
deba@2067
   209
    }
deba@2067
   210
deba@2067
   211
    void  noImprovementIterationLimit( const long int noimpritl ) {
deba@2067
   212
      _noimpr_it_lim = noimpritl;
deba@2067
   213
    }
deba@2067
   214
deba@2067
   215
  private:
deba@2067
   216
    long int  _it_lim, _noimpr_it_lim;
deba@2067
   217
    long int  _it, _noimpr_it;
deba@2067
   218
  };
deba@2067
   219
deba@2067
   220
  /// \brief HeightPolicy stops the search when a given height is reached or
deba@2067
   221
  /// exceeds
deba@2067
   222
  template< typename TS >
deba@2067
   223
  struct HeightPolicy {
deba@2067
   224
    typedef typename TS::Value  Value;
deba@2067
   225
deba@2067
   226
    HeightPolicy() : _height_lim(), _found(false) {}
deba@2067
   227
    HeightPolicy( const Value &hl ) : _height_lim(hl), _found(false) {}
deba@2067
   228
deba@2067
   229
    void  target( TS *ts ) {}
deba@2067
   230
deba@2067
   231
    void  reset() {
deba@2067
   232
      _found = false;
deba@2067
   233
    }
deba@2067
   234
deba@2067
   235
    bool  onStep() {
deba@2067
   236
      return !_found;
deba@2067
   237
    }
deba@2067
   238
deba@2067
   239
    bool  onStick() {
deba@2067
   240
      return false;
deba@2067
   241
    }
deba@2067
   242
deba@2067
   243
    bool  onImprove( const Value &best ) {
deba@2067
   244
      typename TS::Better  better;
deba@2067
   245
      _found = better(best, _height_lim) || (best == _height_lim);
deba@2067
   246
      return !_found;
deba@2067
   247
    }
deba@2067
   248
deba@2067
   249
    Value  heightLimi() const {
deba@2067
   250
      return _height_lim;
deba@2067
   251
    }
deba@2067
   252
deba@2067
   253
    void  heightLimi( const Value &hl ) {
deba@2067
   254
      _height_lim = hl;
deba@2067
   255
    }
deba@2067
   256
deba@2067
   257
  private:
deba@2067
   258
    Value  _height_lim;
deba@2067
   259
    bool  _found;
deba@2067
   260
  };
deba@2067
   261
deba@2067
   262
  /// \brief TimePolicy limits the time for searching.
deba@2067
   263
  template< typename TS >
deba@2067
   264
  struct TimePolicy {
deba@2067
   265
    TimePolicy() : _time_lim(60.0), _timeisup(false) {}
deba@2067
   266
    TimePolicy( const double tl ) : _time_lim(tl), _timeisup(false) {}
deba@2067
   267
deba@2067
   268
    void  target( TS *ts ) {}
deba@2067
   269
deba@2067
   270
    void  reset() {
deba@2067
   271
      _timeisup = false;
deba@2067
   272
      _t.reset();
deba@2067
   273
    }
deba@2067
   274
deba@2067
   275
    bool  onStep() {
deba@2067
   276
      update();
deba@2067
   277
      return !_timeisup;
deba@2067
   278
    }
deba@2067
   279
deba@2067
   280
    bool  onStick() {
deba@2067
   281
      return false;
deba@2067
   282
    }
deba@2067
   283
deba@2067
   284
    bool  onImprove( const typename TS::Value &best ) {
deba@2067
   285
      update();
deba@2067
   286
      return !_timeisup;
deba@2067
   287
    }
deba@2067
   288
deba@2067
   289
    double timeLimit() const {
deba@2067
   290
      return _time_lim;
deba@2067
   291
    }
deba@2067
   292
deba@2067
   293
    void  setTimeLimit( const double tl ) {
deba@2067
   294
      _time_lim = tl;
deba@2067
   295
      update();
deba@2067
   296
    }
deba@2067
   297
deba@2067
   298
  private:
deba@2067
   299
    lemon::Timer  _t;
deba@2067
   300
    double  _time_lim;
deba@2067
   301
    bool  _timeisup;
deba@2067
   302
deba@2067
   303
    inline void  update() {
deba@2067
   304
      _timeisup = _t.realTime() > _time_lim;
deba@2067
   305
    }
deba@2067
   306
  };
deba@2067
   307
deba@2067
   308
deba@2067
   309
deba@2067
   310
  /// \brief TabuSearch main class
deba@2067
   311
  ///
deba@2067
   312
  /// This class offers the implementation of tabu-search algorithm. The
deba@2067
   313
  /// tabu-serach is a local-search. It starts from a specified point of the
deba@2067
   314
  /// problem's graph representation, and in every step it goes to the localy
deba@2067
   315
  /// best next Node except those in tabu set. The maximum size of this tabu
deba@2067
   316
  /// set defines how many Node will be remembered. The best Node ever found
deba@2067
   317
  /// will also stored, so we wont lose it, even is the search continues.
deba@2067
   318
  /// The class can be used on any kind of Graph and with any kind of Value
deba@2067
   319
  /// with a total-settlement on it.
deba@2067
   320
  ///
deba@2067
   321
  /// \param _Graph The graph type the algorithm runs on.
deba@2067
   322
  /// \param _Value The values' type associated to the nodes.
deba@2067
   323
  /// \param _Policy Controlls the search. Determinates when to stop, or how
deba@2067
   324
  /// manage stuck search. Default value is \ref IterationPolicy .
deba@2067
   325
  /// \param _Traits Collection of needed types. Default value is
deba@2067
   326
  /// \ref TabuSearchDefaultTraits .
deba@2067
   327
  ///
deba@2067
   328
  /// \author Szabadkai Mark
deba@2067
   329
#ifdef DOXYGEN
deba@2067
   330
  template< typename GRAPH, typename VALUE, template<typename> class POLICY, typename TRAITS >
deba@2067
   331
#else
deba@2067
   332
  template< typename GRAPH, typename VALUE,
deba@2067
   333
            template<typename> class POLICY = IterationPolicy,
deba@2067
   334
            typename TRAITS = TabuSearchDefaultTraits<GRAPH, VALUE> >
deba@2067
   335
#endif
deba@2067
   336
  class TabuSearch
deba@2067
   337
  {
deba@2067
   338
  public:
deba@2067
   339
deba@2067
   340
    /// \brief Thrown by setting the size of the tabu-set and the given size
deba@2067
   341
    /// is less than 2.
deba@2067
   342
    class BadParameterError : public lemon::LogicError {
deba@2067
   343
    public:
alpar@2151
   344
      virtual const char* what() const throw() {
deba@2067
   345
        return "lemon::TabuSearch::BadParameterError";
deba@2067
   346
      }
deba@2067
   347
    };
deba@2067
   348
deba@2067
   349
    ///Public types
deba@2067
   350
    typedef  TabuSearch<GRAPH,VALUE,POLICY,TRAITS>  SelfType;
deba@2067
   351
deba@2067
   352
    typedef  typename TRAITS::Graph  Graph;
deba@2067
   353
    typedef  typename TRAITS::Node  Node;
deba@2067
   354
    typedef  typename TRAITS::Value  Value;
deba@2067
   355
    typedef  typename TRAITS::HeightMap  HeightMap;
deba@2067
   356
    typedef  typename TRAITS::Better  Better;
deba@2067
   357
    typedef  typename std::deque< Node >::const_iterator  TabuIterator;
deba@2067
   358
deba@2067
   359
    typedef  POLICY<SelfType>  Policy;
deba@2067
   360
deba@2067
   361
  protected:
deba@2067
   362
    typedef  typename TRAITS::EdgeIt  EdgeIt;
deba@2067
   363
deba@2067
   364
    const Graph  &gr;
deba@2067
   365
    const HeightMap  &height;
deba@2067
   366
    /// The tabu set. Teh current node is the first
deba@2067
   367
    std::deque< Node >  tabu;
deba@2067
   368
    /// Maximal tabu size
deba@2067
   369
    unsigned int  mts;
deba@2067
   370
    /// The best Node found
deba@2067
   371
    Node  b;
deba@2067
   372
deba@2067
   373
    Better  better;
deba@2067
   374
    Policy  pol;
deba@2067
   375
deba@2067
   376
  public:
deba@2067
   377
    /// \brief Constructor
deba@2067
   378
    ///
deba@2067
   379
    /// \param graph the graph the algorithm will run on.
deba@2067
   380
    /// \param hm the height map used by the algorithm.
deba@2067
   381
    /// \param tabusz the maximal size of the tabu set. Default value is 3
deba@2067
   382
    /// \param p the Policy controlling the search.
deba@2067
   383
    TabuSearch( const Graph &graph, const HeightMap &hm, 
deba@2067
   384
                const int tabusz = 3, Policy p = Policy() )
deba@2067
   385
      : gr(graph), height(hm), mts(tabusz), pol(p)
deba@2067
   386
    {
deba@2067
   387
      pol.target(this);
deba@2067
   388
    }
deba@2067
   389
deba@2067
   390
    /// \brief Destructor
deba@2067
   391
    ~TabuSearch() {
deba@2067
   392
      pol.target(NULL);
deba@2067
   393
    }
deba@2067
   394
deba@2067
   395
    /// Set/Get the size of the tabu set
deba@2067
   396
    void  tabuSize( const unsigned int size )
deba@2067
   397
    {
deba@2067
   398
      if( size < 2 )
deba@2067
   399
      throw BadParameterError( "Tabu size must be at least 2!" );
deba@2067
   400
      mts = size;
deba@2067
   401
      while( mts < tabu.size() )
deba@2067
   402
      tabu.pop_back();
deba@2067
   403
    }
deba@2067
   404
deba@2067
   405
    unsigned int  tabuSize() const {
deba@2067
   406
      return mts;
deba@2067
   407
    }
deba@2067
   408
deba@2067
   409
    /// Set/Get Policy
deba@2067
   410
    void  policy( Policy p ) {
deba@2067
   411
      pol.target(NULL);
deba@2067
   412
      pol = p;
deba@2067
   413
      pol.target(this);
deba@2067
   414
    }
deba@2067
   415
		
deba@2067
   416
    Policy& policy()  {
deba@2067
   417
      return pol;
deba@2067
   418
    }
deba@2067
   419
deba@2067
   420
    /// \name Execution control
deba@2067
   421
    /// The simplest way to execute the algorithm is to use the member
deba@2067
   422
    /// functions called \c run( 'startnode' ).
deba@2067
   423
    ///@{
deba@2067
   424
deba@2067
   425
    /// \brief Initializes the internal data.
deba@2067
   426
    ///
deba@2067
   427
    /// \param startn The start node where the search begins.
deba@2067
   428
    void  init( const Node startn ) {
deba@2067
   429
      tabu.clear();
deba@2067
   430
      tabu.push_front( startn );
deba@2067
   431
      b = startn;
deba@2067
   432
      pol.reset();
deba@2067
   433
    }
deba@2067
   434
deba@2067
   435
    /// \brief Does one iteration
deba@2067
   436
    ///
deba@2067
   437
    /// If the Policy allows it searches for the best next node, then steps
deba@2067
   438
    /// onto it.
deba@2067
   439
    /// \return %False if one Policy condition wants to stop the search.
deba@2067
   440
    bool  step()
deba@2067
   441
    {
deba@2067
   442
      ///Request premmision from ControllPolicy
deba@2067
   443
      if( !pol.onStep() )
deba@2067
   444
      return false;
deba@2067
   445
	
deba@2067
   446
      ///Find the best next potential node
deba@2067
   447
      Node n; bool found = false;
deba@2067
   448
      for( EdgeIt e(gr,tabu[0]); e != INVALID; ++e )
deba@2067
   449
      {
deba@2067
   450
        Node m = (gr.source(e) == tabu[0]) ? gr.target(e) : gr.source(e);
deba@2067
   451
        bool wrong = false;
deba@2067
   452
        for( int i = 1; i != (signed int)tabu.size(); ++i )
deba@2067
   453
          if( m == tabu[i] ) {
deba@2067
   454
            wrong = true;
deba@2067
   455
            break;
deba@2067
   456
          }
deba@2067
   457
        if( wrong )
deba@2067
   458
          continue;
deba@2067
   459
deba@2067
   460
        if( !found ) {
deba@2067
   461
          n = m;
deba@2067
   462
          found = true;
deba@2067
   463
        } else
deba@2067
   464
          if( better(height[m], height[n]) ) {
deba@2067
   465
            n = m;
deba@2067
   466
          }
deba@2067
   467
      }
deba@2067
   468
deba@2067
   469
      ///Handle stuck search
deba@2067
   470
      if( !found ) {
deba@2067
   471
        return pol.onStick();
deba@2067
   472
      }
deba@2067
   473
deba@2067
   474
      ///Move on...
deba@2067
   475
      tabu.push_front(n);
deba@2067
   476
      while( mts < tabu.size() ) {
deba@2067
   477
        tabu.pop_back();
deba@2067
   478
      }
deba@2067
   479
      if( better(height[n], height[b]) ) {
deba@2067
   480
        b = n;
deba@2067
   481
        if( !pol.onImprove(height[b]) )
deba@2067
   482
        return false;
deba@2067
   483
      }
deba@2067
   484
deba@2067
   485
      return true;
deba@2067
   486
    }
deba@2067
   487
deba@2067
   488
    /// \brief Runs a search while the Policy stops it.
deba@2067
   489
    ///
deba@2067
   490
    /// \param startn The start node where the search begins.
deba@2067
   491
    inline void  run( const Node startn ) {
deba@2067
   492
      std::cin.unsetf( std::ios_base::skipws );
deba@2067
   493
      char c;
deba@2067
   494
      init( startn );
deba@2067
   495
      while( step() )
deba@2067
   496
      std::cin >> c;
deba@2067
   497
      std::cin.setf( std::ios_base::skipws );
deba@2067
   498
    }
deba@2067
   499
deba@2067
   500
    ///@}
deba@2067
   501
deba@2067
   502
    /// \name Query Functions
deba@2067
   503
    /// The result of the TabuSearch algorithm can be obtained using these
deba@2067
   504
    /// functions.\n
deba@2067
   505
    ///@{
deba@2067
   506
deba@2067
   507
    /// \brief The node, the search is standing on.
deba@2067
   508
    inline Node  current() const {
deba@2067
   509
      return tabu[0];
deba@2067
   510
    }
deba@2067
   511
deba@2067
   512
    /// \brief The best node found until now.
deba@2067
   513
    inline Node  best() const {
deba@2067
   514
      return b;
deba@2067
   515
    }
deba@2067
   516
deba@2067
   517
    /// \brief Beginning to iterate on the current tabu set.
deba@2067
   518
    inline TabuIterator  tabu_begin() const {
deba@2067
   519
      return tabu.begin();
deba@2067
   520
    }
deba@2067
   521
deba@2067
   522
    /// \brief Ending to iterate on the current tabu set.
deba@2067
   523
    inline TabuIterator  tabu_end() const {
deba@2067
   524
      return tabu.end();
deba@2067
   525
    }
deba@2067
   526
deba@2067
   527
    ///@}
deba@2067
   528
  };
deba@2067
   529
}
deba@2067
   530
#endif