00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef METS_MODEL_HH_
00036 #define METS_MODEL_HH_
00037
00038 namespace mets {
00039
00045 typedef double gol_type;
00046
00049 class no_moves_error
00050 : public std::runtime_error
00051 {
00052 public:
00053 no_moves_error()
00054 : std::runtime_error("There are no more available moves.") {}
00055 no_moves_error(const std::string message)
00056 : std::runtime_error(message) {}
00057 };
00058
00063 class sequence
00064 {
00065 public:
00067 sequence(int start = 0)
00068 : value_m(start)
00069 { }
00072 int operator()()
00073 { return value_m++; }
00074 protected:
00075 int value_m;
00076 };
00077
00079 class clonable {
00080 public:
00081 virtual
00082 ~clonable() {};
00083 virtual clonable*
00084 clone() const = 0;
00085 };
00086
00088 class hashable {
00089 public:
00090 virtual
00091 ~hashable() {};
00092 virtual size_t
00093 hash() const = 0;
00094 };
00095
00097 class copyable {
00098 public:
00099 virtual
00100 ~copyable() {};
00101 virtual void
00102 copy_from(const copyable&) = 0;
00103 };
00104
00106 class printable {
00107 public:
00108 virtual
00109 ~printable() {}
00110 virtual void
00111 print(std::ostream& ) const { };
00112 };
00113
00116
00134 class feasible_solution
00135 {
00136 public:
00138 virtual
00139 ~feasible_solution()
00140 { }
00141
00142 };
00143
00144
00155 class evaluable_solution : public feasible_solution,
00156 public copyable
00157 {
00158 public:
00166 virtual gol_type
00167 cost_function() const = 0;
00168 };
00169
00182 class permutation_problem: public evaluable_solution
00183 {
00184 public:
00185
00187 permutation_problem();
00188
00190 permutation_problem(int n) : pi_m(n), cost_m(0.0)
00191 { std::generate(pi_m.begin(), pi_m.end(), sequence(0)); }
00192
00198 void copy_from(const copyable& other);
00199
00203 virtual gol_type
00204 compute_cost() const = 0;
00205
00217 virtual gol_type
00218 evaluate_swap(int i, int j) const = 0;
00219
00222 size_t
00223 size() const
00224 { return pi_m.size(); }
00225
00230 gol_type cost_function() const
00231 { return cost_m; }
00232
00235 void
00236 update_cost()
00237 { cost_m = compute_cost(); }
00238
00241 void
00242 apply_swap(int i, int j)
00243 { cost_m += evaluate_swap(i,j); std::swap(pi_m[i], pi_m[j]); }
00244
00245
00246 protected:
00247 std::vector<int> pi_m;
00248 gol_type cost_m;
00249 template<typename random_generator>
00250 friend void random_shuffle(permutation_problem& p, random_generator& rng);
00251 };
00252
00253
00257 template<typename random_generator>
00258 void random_shuffle(permutation_problem& p, random_generator& rng)
00259 {
00260 #if defined (METSLIB_TR1_BOOST)
00261 boost::uniform_int<size_t> unigen;
00262 boost::variate_generator<random_generator&,
00263 boost::uniform_int<size_t> >gen(rng, unigen);
00264 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00265 std::uniform_int<size_t> unigen;
00266 std::variate_generator<random_generator&,
00267 std::uniform_int<size_t> >gen(rng, unigen);
00268 #else
00269 std::tr1::uniform_int<size_t> unigen;
00270 std::tr1::variate_generator<random_generator&,
00271 std::tr1::uniform_int<size_t> >gen(rng, unigen);
00272 #endif
00273 std::random_shuffle(p.pi_m.begin(), p.pi_m.end(), gen);
00274 p.update_cost();
00275 }
00276
00280 template<typename random_generator>
00281 void perturbate(permutation_problem& p, unsigned int n, random_generator& rng)
00282 {
00283 #if defined (METSLIB_TR1_BOOST)
00284 boost::uniform_int<> int_range;
00285 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00286 std::uniform_int<> int_range;
00287 #else
00288 std::tr1::uniform_int<> int_range;
00289 #endif
00290 for(unsigned int ii=0; ii!=n;++ii)
00291 {
00292 int p1 = int_range(rng, p.size());
00293 int p2 = int_range(rng, p.size());
00294 while(p1 == p2)
00295 p2 = int_range(rng, p.size());
00296 p.apply_swap(p1, p2);
00297 }
00298 }
00299
00309 class move
00310 {
00311 public:
00312
00313 virtual
00314 ~move()
00315 { };
00316
00324 virtual gol_type
00325 evaluate(const feasible_solution& sol) const = 0;
00326
00331 virtual void
00332 apply(feasible_solution& sol) const = 0;
00333
00334
00335 };
00336
00351 class mana_move :
00352 public move,
00353 public clonable,
00354 public hashable
00355 {
00356 public:
00357
00366 virtual mana_move*
00367 opposite_of() const
00368 { return static_cast<mana_move*>(clone()); }
00369
00372 virtual bool
00373 operator==(const mana_move& other) const = 0;
00374
00375 };
00376
00377 template<typename rndgen> class swap_neighborhood;
00378
00386 class swap_elements : public mets::mana_move
00387 {
00388 public:
00389
00391 swap_elements(int from, int to)
00392 : p1(std::min(from,to)), p2(std::max(from,to))
00393 { }
00394
00396 gol_type
00397 evaluate(const mets::feasible_solution& s) const
00398 { const permutation_problem& sol =
00399 static_cast<const permutation_problem&>(s);
00400 return sol.cost_function() + sol.evaluate_swap(p1, p2); }
00401
00403 void
00404 apply(mets::feasible_solution& s) const
00405 { permutation_problem& sol = static_cast<permutation_problem&>(s);
00406 sol.apply_swap(p1, p2); }
00407
00409 clonable*
00410 clone() const
00411 { return new swap_elements(p1, p2); }
00412
00415 size_t
00416 hash() const
00417 { return (p1)<<16^(p2); }
00418
00421 bool
00422 operator==(const mets::mana_move& o) const;
00423
00425 void change(int from, int to)
00426 { p1 = std::min(from,to); p2 = std::max(from,to); }
00427
00428 protected:
00429 int p1;
00430 int p2;
00431
00432 template <typename>
00433 friend class swap_neighborhood;
00434 };
00435
00441 class invert_subsequence : public mets::mana_move
00442 {
00443 public:
00444
00446 invert_subsequence(int from, int to)
00447 : p1(from), p2(to)
00448 { }
00449
00451 gol_type
00452 evaluate(const mets::feasible_solution& s) const;
00453
00455 void
00456 apply(mets::feasible_solution& s) const;
00457
00458 clonable*
00459 clone() const
00460 { return new invert_subsequence(p1, p2); }
00461
00464 size_t
00465 hash() const
00466 { return (p1)<<16^(p2); }
00467
00470 bool
00471 operator==(const mets::mana_move& o) const;
00472
00473 void change(int from, int to)
00474 { p1 = from; p2 = to; }
00475
00476 protected:
00477 int p1;
00478 int p2;
00479
00480
00481
00482 };
00483
00507 class move_manager
00508 {
00509 public:
00512 move_manager()
00513 : moves_m()
00514 { }
00515
00517 virtual ~move_manager()
00518 { }
00519
00521 virtual void
00522 refresh(mets::feasible_solution& s) = 0;
00523
00525 typedef std::deque<move*>::iterator iterator;
00526
00528 typedef std::deque<move*>::size_type size_type;
00529
00531 iterator begin()
00532 { return moves_m.begin(); }
00533
00535 iterator end()
00536 { return moves_m.end(); }
00537
00539 size_type size() const
00540 { return moves_m.size(); }
00541
00542 protected:
00543 std::deque<move*> moves_m;
00544 move_manager(const move_manager&);
00545 };
00546
00547
00549 #if defined (METSLIB_TR1_BOOST)
00550 template<typename random_generator = boost::minstd_rand0>
00551 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00552 template<typename random_generator = std::minstd_rand0>
00553 #else
00554 template<typename random_generator = std::tr1::minstd_rand0>
00555 #endif
00556 class swap_neighborhood : public mets::move_manager
00557 {
00558 public:
00568 swap_neighborhood(random_generator& r,
00569 unsigned int moves);
00570
00572 ~swap_neighborhood();
00573
00575 void refresh(mets::feasible_solution& s);
00576
00577 protected:
00578 random_generator& rng;
00579
00580 #if defined (METSLIB_TR1_BOOST)
00581 boost::uniform_int<> int_range;
00582 #elif defined (METSLIB_HAVE_UNORDERED_MAP) && !defined (METSLIB_TR1_MIXED_NAMESPACE)
00583 std::uniform_int<> int_range;
00584 #else
00585 std::tr1::uniform_int<> int_range;
00586 #endif
00587 unsigned int n;
00588
00589 void randomize_move(swap_elements& m, unsigned int size);
00590 };
00591
00592
00593 template<typename random_generator>
00594 mets::swap_neighborhood< random_generator
00595 >::swap_neighborhood(random_generator& r,
00596 unsigned int moves)
00597 : mets::move_manager(), rng(r), int_range(0), n(moves)
00598 {
00599
00600 for(unsigned int ii = 0; ii != n; ++ii)
00601 moves_m.push_back(new swap_elements(0,0));
00602 }
00603
00604 template<typename random_generator>
00605 mets::swap_neighborhood<random_generator>::~swap_neighborhood()
00606 {
00607
00608 for(iterator ii = begin(); ii != end(); ++ii)
00609 delete (*ii);
00610 }
00611
00612 template<typename random_generator>
00613 void
00614 mets::swap_neighborhood<random_generator>::refresh(mets::feasible_solution& s)
00615 {
00616 permutation_problem& sol = dynamic_cast<permutation_problem&>(s);
00617 iterator ii = begin();
00618
00619
00620 for(unsigned int cnt = 0; cnt != n; ++cnt)
00621 {
00622 swap_elements* m = static_cast<swap_elements*>(*ii);
00623 randomize_move(*m, sol.size());
00624 ++ii;
00625 }
00626
00627 }
00628
00629 template<typename random_generator>
00630 void
00631 mets::swap_neighborhood<random_generator
00632 >::randomize_move(swap_elements& m, unsigned int size)
00633 {
00634 int p1 = int_range(rng, size);
00635 int p2 = int_range(rng, size);
00636 while(p1 == p2)
00637 p2 = int_range(rng, size);
00638
00639
00640 m.p1 = std::min(p1,p2);
00641 m.p2 = std::max(p1,p2);
00642 }
00643
00645 class swap_full_neighborhood : public mets::move_manager
00646 {
00647 public:
00653 swap_full_neighborhood(int size) : move_manager()
00654 {
00655 for(int ii(0); ii!=size-1; ++ii)
00656 for(int jj(ii+1); jj!=size; ++jj)
00657 moves_m.push_back(new swap_elements(ii,jj));
00658 }
00659
00661 ~swap_full_neighborhood() {
00662 for(move_manager::iterator it = moves_m.begin();
00663 it != moves_m.end(); ++it)
00664 delete *it;
00665 }
00666
00668 void refresh(mets::feasible_solution& ) { }
00669
00670 };
00671
00672
00674 class invert_full_neighborhood : public mets::move_manager
00675 {
00676 public:
00677 invert_full_neighborhood(int size) : move_manager()
00678 {
00679 for(int ii(0); ii!=size; ++ii)
00680 for(int jj(0); jj!=size; ++jj)
00681 if(ii != jj)
00682 moves_m.push_back(new invert_subsequence(ii,jj));
00683 }
00684
00686 ~invert_full_neighborhood() {
00687 for(std::deque<move*>::iterator it = moves_m.begin();
00688 it != moves_m.end(); ++it)
00689 delete *it;
00690 }
00691
00693 void
00694 refresh(mets::feasible_solution& )
00695 { }
00696
00697 };
00698
00700
00702 class mana_move_hash
00703 {
00704 public:
00705 size_t operator()(mana_move const* mov) const
00706 {return mov->hash();}
00707 };
00708
00710 template<typename Tp>
00711 struct dereferenced_equal_to
00712 {
00713 bool operator()(const Tp l,
00714 const Tp r) const
00715 { return l->operator==(*r); }
00716 };
00717
00718 }
00719
00720
00721 inline void
00722 mets::permutation_problem::copy_from(const mets::copyable& other)
00723 {
00724 const mets::permutation_problem& o =
00725 dynamic_cast<const mets::permutation_problem&>(other);
00726 pi_m = o.pi_m;
00727 cost_m = o.cost_m;
00728 }
00729
00730
00731 inline bool
00732 mets::swap_elements::operator==(const mets::mana_move& o) const
00733 {
00734 try {
00735 const mets::swap_elements& other =
00736 dynamic_cast<const mets::swap_elements&>(o);
00737 return (this->p1 == other.p1 && this->p2 == other.p2);
00738 } catch (std::bad_cast& e) {
00739 return false;
00740 }
00741 }
00742
00743
00744
00745 inline void
00746 mets::invert_subsequence::apply(mets::feasible_solution& s) const
00747 {
00748 mets::permutation_problem& sol =
00749 static_cast<mets::permutation_problem&>(s);
00750 int size = static_cast<int>(sol.size());
00751 int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
00752 for(int ii(0); ii!=top/2; ++ii)
00753 {
00754 int from = (p1+ii)%size;
00755 int to = (size+p2-ii)%size;
00756 assert(from >= 0 && from < size);
00757 assert(to >= 0 && to < size);
00758 sol.apply_swap(from, to);
00759 }
00760 }
00761
00762 inline mets::gol_type
00763 mets::invert_subsequence::evaluate(const mets::feasible_solution& s) const
00764 {
00765 const mets::permutation_problem& sol =
00766 static_cast<const mets::permutation_problem&>(s);
00767 int size = static_cast<int>(sol.size());
00768 int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
00769 mets::gol_type eval = 0.0;
00770 for(int ii(0); ii!=top/2; ++ii)
00771 {
00772 int from = (p1+ii)%size;
00773 int to = (size+p2-ii)%size;
00774 assert(from >= 0 && from < size);
00775 assert(to >= 0 && to < size);
00776 eval += sol.evaluate_swap(from, to);
00777 }
00778 return eval;
00779 }
00780
00781 inline bool
00782 mets::invert_subsequence::operator==(const mets::mana_move& o) const
00783 {
00784 try {
00785 const mets::invert_subsequence& other =
00786 dynamic_cast<const mets::invert_subsequence&>(o);
00787 return (this->p1 == other.p1 && this->p2 == other.p2);
00788 } catch (std::bad_cast& e) {
00789 return false;
00790 }
00791 }
00792
00793 #endif