#ifndef LEMON_OPT2_TSP_H #define LEMON_OPT2_TSP_H #include #include #include namespace lemon { namespace opt2_helper { template L vectorConvert(const std::vector &_path) { return L(_path.begin(), _path.end()); } template <> std::vector vectorConvert(const std::vector &_path) { return _path; } } template class Opt2Tsp { private: GRAPH_TYPEDEFS(FullGraph); public: typedef CM CostMap; typedef typename CM::Value Cost; Opt2Tsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost), tmppath(_gr.nodeNum()*2) { for (int i=1; i<_gr.nodeNum()-1; ++i) { tmppath[2*i] = i-1; tmppath[2*i+1] = i+1; } tmppath[0] = _gr.nodeNum()-1; tmppath[1] = 1; tmppath[2*(_gr.nodeNum()-1)] = _gr.nodeNum()-2; tmppath[2*(_gr.nodeNum()-1)+1] = 0; } Opt2Tsp(const FullGraph &gr, const CostMap &cost, const std::vector &path) : _gr(gr), _cost(cost), tmppath(_gr.nodeNum()*2) { for (unsigned int i=1; i &path, int i=0) : tmppath(path), act(i), last(tmppath[2*act]) {} It(const std::vector &path, int i, int l) : tmppath(path), act(i), last(l) {} int next_index() const { return (tmppath[2*act]==last)? 2*act+1 : 2*act; } int prev_index() const { return (tmppath[2*act]==last)? 2*act : 2*act+1; } int next() const { return tmppath[next_index()]; } int prev() const { return tmppath[prev_index()]; } It& operator++() { int tmp = act; act = next(); last = tmp; return *this; } operator int() const { return act; } private: const std::vector &tmppath; int act; int last; }; bool check(std::vector &path, It i, It j) { if (c(i, i.next()) + c(j, j.next()) > c(i, j) + c(j.next(), i.next())) { path[ It(path, i.next(), i).prev_index() ] = j.next(); path[ It(path, j.next(), j).prev_index() ] = i.next(); path[i.next_index()] = j; path[j.next_index()] = i; return true; } return false; } public: Cost run() { _path.clear(); if (_gr.nodeNum()>3) { opt2_tsp_label: It i(tmppath); It j(tmppath, i, i.prev()); ++j; ++j; for (; j.next()!=0; ++j) { if (check(tmppath, i, j)) goto opt2_tsp_label; } for (++i; i.next()!=0; ++i) { It j(tmppath, i, i.prev()); if (++j==0) break; if (++j==0) break; for (; j!=0; ++j) { if (check(tmppath, i, j)) goto opt2_tsp_label; } } } It k(tmppath); _path.push_back(_gr.nodeFromId(k)); for (++k; k!=0; ++k) _path.push_back(_gr.nodeFromId(k)); _sum = _cost[ _gr.edge(_path.back(), _path.front()) ]; for (unsigned int i=0; i<_path.size()-1; ++i) _sum += _cost[ _gr.edge(_path[i], _path[i+1]) ]; return _sum; } template void tourNodes(L &container) { container(opt2_helper::vectorConvert(_path)); } template