170 lines
3.8 KiB
C++
170 lines
3.8 KiB
C++
#include <algorithm>
|
|
#include <cassert>
|
|
#include <fstream>
|
|
#include <iostream>
|
|
|
|
#include "rosa/els.h"
|
|
#include "rosa/grasp.h"
|
|
#include "rosa/tabu_search.h"
|
|
|
|
#include "muscles/descent.h"
|
|
#include "muscles/move2opt.h"
|
|
#include "muscles/rgreedy.h"
|
|
#include "muscles/tabu_search.h"
|
|
|
|
#include "tsp/problem.h"
|
|
#include "tsp/solution.h"
|
|
#include "tsp/tsp.h"
|
|
|
|
// using RNG = std::mt19937;
|
|
|
|
struct RNG {
|
|
using type = std::mt19937;
|
|
type _rng;
|
|
|
|
using result_type = type::result_type;
|
|
|
|
template<typename T>
|
|
RNG(T&& v): _rng{std::forward<T>(v)} {}
|
|
auto operator()() { return _rng(); }
|
|
auto min() const { return _rng.min(); }
|
|
auto max() const { return _rng.max(); }
|
|
};
|
|
|
|
struct SelectMin {
|
|
template<typename T>
|
|
T operator()(T const&a, T const&b) { return a<b? a:b; }
|
|
};
|
|
|
|
tsp::Solution selectMin(tsp::Solution const&a, tsp::Solution const&b) {
|
|
return a<b? a:b;
|
|
}
|
|
|
|
using ELS = rosa::SkelEls<
|
|
tsp::Solution,
|
|
Descent,
|
|
Move2Opt, Descent,
|
|
FN(selectMin)
|
|
>;
|
|
|
|
using GRASPxELS = rosa::SkelGrasp<
|
|
tsp::Problem, tsp::Solution,
|
|
RGreedy<tsp::Solution>, ELS,
|
|
FN(selectMin)
|
|
>;
|
|
|
|
auto mainGraspEls(tsp::Problem const&problem) {
|
|
using namespace alsk::tag;
|
|
|
|
// auto selectMin = [](tsp::Solution const&a, tsp::Solution const&b) { return a<b? a:b; };
|
|
// auto selectMin = [](auto const&a, auto const&b) { return a<b? a:b; };
|
|
|
|
// implementation
|
|
auto graspEls = alsk::implement<alsk::exec::StaticPool, GRASPxELS>();
|
|
graspEls.skeleton.task.task<0>() = RGreedy<tsp::Solution>{2};
|
|
// graspEls.skeleton.task.task<1>().task<1>().select = selectMin;
|
|
// graspEls.skeleton.task.task<1>().task<1>().task.select = fSelectMin;
|
|
graspEls.skeleton.task.task<1>().task<1>().n = 15;
|
|
graspEls.skeleton.task.task<1>().task<1>().task.n = 20;
|
|
// graspEls.skeleton.select = selectMin;
|
|
graspEls.skeleton.n = 10;
|
|
|
|
graspEls.executor.cores = 7;
|
|
|
|
// actual call
|
|
tsp::Solution solution;
|
|
solution = graspEls(problem);
|
|
return solution;
|
|
}
|
|
|
|
using TabuList = std::vector<tsp::Solution>;
|
|
|
|
struct InitTabuList {
|
|
auto operator()() const { return TabuList{}; }
|
|
};
|
|
|
|
class StopCriteria {
|
|
int _failCount;
|
|
int _maxFail;
|
|
tsp::Solution best;
|
|
|
|
public:
|
|
StopCriteria() = default;
|
|
StopCriteria(int maxFail): _failCount{}, _maxFail{maxFail} {}
|
|
|
|
bool operator()(tsp::Solution& cur) {
|
|
if(cur < best) {
|
|
best = cur;
|
|
_failCount = 0;
|
|
} else ++_failCount;
|
|
return _failCount < _maxFail;
|
|
}
|
|
};
|
|
|
|
struct FindNeighbour {
|
|
TabuList tabu;
|
|
tsp::Solution scur;
|
|
|
|
~FindNeighbour() {}
|
|
|
|
void operator()(tsp::Solution& best, tsp::Solution const&cur) {
|
|
assert(cur.size());
|
|
if(scur.empty()) scur = cur;
|
|
// std::printf("before: %lf\n", scur.value());
|
|
scur = bestNeighbour2Opt<tsp::Solution>(scur, tabu);
|
|
if(scur < best) {
|
|
best = scur;
|
|
// std::printf("v: %lf\n", scur.value());
|
|
} else {
|
|
// std::printf("%lf >= %lf\n", scur.value(), best.value());
|
|
}
|
|
}
|
|
};
|
|
|
|
using MyTabuSearch = rosa::SkelTabuSearch<
|
|
tsp::Problem, tsp::Solution,
|
|
RGreedy<tsp::Solution>, StopCriteria, FindNeighbour
|
|
>;
|
|
|
|
auto mainTabuSearch(tsp::Problem const&problem) {
|
|
using namespace alsk::tag;
|
|
|
|
tsp::Solution solution;
|
|
/*
|
|
solution = tabuSearch<tsp::Solution>(problem,
|
|
RGreedy<tsp::Solution>{2},
|
|
bestNeighbour2Opt<tsp::Solution, std::list<tsp::Solution>>
|
|
);
|
|
*/
|
|
|
|
// implementation
|
|
auto tabuSearch = alsk::implement<alsk::exec::FirstLevelEqui, MyTabuSearch>();
|
|
tabuSearch.skeleton.task<0>() = RGreedy<tsp::Solution>{2};
|
|
tabuSearch.skeleton.task<2>().test = StopCriteria{200};
|
|
tabuSearch.skeleton.task<2>().task = FindNeighbour{};
|
|
|
|
tabuSearch(solution, problem);
|
|
|
|
return solution;
|
|
}
|
|
|
|
int main() {
|
|
tsp::Tsp tspData{"../data/dj38"};
|
|
tsp::Problem const&problem = tspData.points();
|
|
tsp::Solution solution;
|
|
|
|
solution = mainGraspEls(problem);
|
|
|
|
std::cout << "distance: " << solution.value() << std::endl;
|
|
|
|
// save
|
|
{
|
|
std::ofstream ofs{"solution"};
|
|
ofs << solution;
|
|
}
|
|
{
|
|
std::ofstream ofs{"solution.ids"};
|
|
solution.printIndices(ofs);
|
|
}
|
|
}
|