rosa/src/main.cpp

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);
}
}