Skip to content

Commit

Permalink
Permutation problem tests. Added a subsequence inversion move.
Browse files Browse the repository at this point in the history
  • Loading branch information
baol committed Oct 20, 2009
1 parent 7c3c31f commit d2ba296
Show file tree
Hide file tree
Showing 5 changed files with 203 additions and 3 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -29,4 +29,5 @@ metslib/observer.h -text
metslib/simulated-annealing.cc -text
metslib/tabu-search.cc -text
test/Makefile.am -text
test/permutation_problem_test.cc -text
test/tabu_list_test.cc -text
27 changes: 27 additions & 0 deletions metslib/mets.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,33 @@ mets::swap_elements::operator==(const mets::mana_move& o) const
}
}

//________________________________________________________________________

void
mets::swap_subsequence::apply(mets::feasible_solution& s)
{
mets::permutation_problem& sol =
reinterpret_cast<mets::permutation_problem&>(s);
int size = sol.size();
int top = p1 < p2 ? (p2-p1+1) : (size+p2-p1+1);
for(int ii(0); ii!=top/2; ++ii)
{
sol.swap((p1+ii)%size, (p2-ii)%size);
}
}

bool
mets::swap_subsequence::operator==(const mets::mana_move& o) const
{
try {
const mets::swap_subsequence& other =
dynamic_cast<const mets::swap_subsequence&>(o);
return (this->p1 == other.p1 && this->p2 == other.p2);
} catch (std::bad_cast& e) {
return false;
}
}

//________________________________________________________________________
mets::complex_mana_move::complex_mana_move(const mets::complex_mana_move& o)
: mana_move(), moves_m(o.moves_m.size())
Expand Down
59 changes: 59 additions & 0 deletions metslib/mets.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,10 @@ namespace mets {
class permutation_problem: public feasible_solution
{
public:

/// @brief Unimplemented.
permutation_problem();

/// @brief Inizialize pi_m = {0, 1, 2, ..., n-1}.
permutation_problem(int n) : pi_m(n)
{ std::generate(pi_m.begin(), pi_m.end(), sequence(0)); }
Expand Down Expand Up @@ -374,6 +378,61 @@ namespace mets {
bool
operator==(const mets::mana_move& o) const;

void change(int from, int to)
{ p1 = std::min(from,to); p2 = std::max(from,to); }

protected:
int p1; ///< the first element to swap
int p2; ///< the second element to swap

template <typename>
friend class swap_neighborhood;
};

/// @brief A mets::mana_move that swaps a subsequence of elements in
/// a mets::permutation_problem.
///
/// @see mets::permutation_problem, mets::mana_move
///
class swap_subsequence : public mets::mana_move
{
public:

/// @brief A move that swaps from and to.
swap_subsequence(int from, int to)
: p1(from), p2(to)
{ }

/// @brief Virtual method that applies the move on a point
void
apply(mets::feasible_solution& s);

/// @brief Unapply the last move: in case of a swap the inverse move
/// is just the same swap.
void
unapply(mets::feasible_solution& s)
{ this->apply(s); }

/// @brief A method to clone self. Needed to insert the move in a
/// tabu list.
mana_move*
clone() const
{ return new swap_subsequence(p1, p2); }

/// @brief An hash function used by the tabu list (the hash value is
/// used to insert the move in an hash set).
size_t
hash() const
{ return (p1)<<16^(p2); }

/// @brief Comparison operator used to tell if this move is equal to
/// a move in the tabu list.
bool
operator==(const mets::mana_move& o) const;

void change(int from, int to)
{ p1 = from; p2 = to; }

protected:
int p1; ///< the first element to swap
int p2; ///< the second element to swap
Expand Down
8 changes: 5 additions & 3 deletions test/Makefile.am
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
check_PROGRAMS = tabu_list_test
check_PROGRAMS = tabu_list_test permutation_problem_test

AM_LDFLAGS = -L../metslib/.libs/ -lmetslib

tabu_list_test_SOURCES = tabu_list_test.cc
tabu_list_test_SOURCES = tabu_list_test.cc

TESTS = tabu_list_test
permutation_problem_test_SOURCES = permutation_problem_test.cc

TESTS = tabu_list_test permutation_problem_test
111 changes: 111 additions & 0 deletions test/permutation_problem_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
#include <iostream>
#include "../metslib/mets.h"

using namespace std;

class p : public mets::permutation_problem
{
public:

p();

p(int n) :
permutation_problem(n)
{}

~p();

mets::gol_type cost_function() const;

friend int main();
};

p::~p() {}

mets::gol_type p::cost_function() const
{ return 0.0; }

int main()
{
// test swap_elements
{
p pi(10);
mets::swap_elements move(0,0);
for(int ii(0); ii!=9; ++ii)
{
move.change(ii, ii+1);
move.apply(pi);
}

int check[]={1,2,3,4,5,6,7,8,9,0};

if(pi.pi_m != std::vector<int>(&check[0], &check[10]))
{
cerr << "Failed swap_elements." << endl;
return 1;
}
}
// test swap_subsequence (1)
{
p pi(10);
mets::swap_subsequence move(0,9);
move.apply(pi);

int check[]={9,8,7,6,5,4,3,2,1,0};
if(pi.pi_m != std::vector<int>(&check[0], &check[10]))
{
cerr << "Failed swap_subsequence (1)." << endl;
return 1;
}
}
// test swap_subsequence (2)
{
p pi(9);
mets::swap_subsequence move(0,8);
move.apply(pi);

int check[]={8,7,6,5,4,3,2,1,0};

if(pi.pi_m != std::vector<int>(&check[0], &check[9]))
{
cerr << "Failed swap_subsequence (2)." << endl;
return 1;
}
}

// test swap_subsequence (3)
{
p pi(9);
mets::swap_subsequence move(2,5);
move.apply(pi);

int check[]={0,1,5,4,3,2,6,7,8};

if(pi.pi_m != std::vector<int>(&check[0], &check[9]))
{
cerr << "Failed swap_subsequence (3)." << endl;
return 1;
}
}

// test swap_subsequence (4)
{
p pi(9);
mets::swap_subsequence move(5,2);
move.apply(pi);

int check[]={7,6,5,3,4,2,1,0,8};

for(int ii(0); ii!=9; ++ii)
cerr << pi.pi_m[ii] << "(" << check[ii] << ") ";
cerr << endl;

if(pi.pi_m != std::vector<int>(&check[0], &check[9]))
{
cerr << "Failed swap_subsequence (4)." << endl;
return 1;
}
}

return 0;
}

0 comments on commit d2ba296

Please sign in to comment.