/* -*- mode: C++; indent-tabs-mode: nil; -*- * * This file is a part of LEMON, a generic C++ optimization library. * * Copyright (C) 2003-2010 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ #ifndef LEMON_OPT2_TSP_H #define LEMON_OPT2_TSP_H /// \ingroup tsp /// \file /// \brief 2-opt algorithm for symmetric TSP #include #include namespace lemon { /// \brief 2-opt algorithm for symmetric TSP. /// /// Opt2Tsp implements the 2-opt heuristic for solving /// symmetric \ref tsp "TSP". /// /// This algorithm starts with an initial tour and iteratively improves it. /// At each step, it removes two edges and the reconnects the created two /// paths in the other way if the resulting tour is shorter. /// The algorithm finishes when no such 2-opt move can be applied, and so /// the tour is 2-optimal. /// /// If no starting tour is given to the \ref run() function, then the /// algorithm uses the node sequence determined by the node IDs. /// Oherwise, it starts with the given tour. /// /// This is a relatively slow but powerful method. /// A typical usage of it is the improvement of a solution that is resulted /// by a fast tour construction heuristic (e.g. the InsertionTsp algorithm). /// /// \tparam CM Type of the cost map. template class Opt2Tsp { public: /// Type of the cost map typedef CM CostMap; /// Type of the edge costs typedef typename CM::Value Cost; private: GRAPH_TYPEDEFS(FullGraph); const FullGraph &_gr; const CostMap &_cost; Cost _sum; std::vector _plist; std::vector _path; public: /// \brief Constructor /// /// Constructor. /// \param gr The \ref FullGraph "full graph" the algorithm runs on. /// \param cost The cost map. Opt2Tsp(const FullGraph &gr, const CostMap &cost) : _gr(gr), _cost(cost) {} /// \name Execution Control /// @{ /// \brief Runs the algorithm from scratch. /// /// This function runs the algorithm starting from the tour that is /// determined by the node ID sequence. /// /// \return The total cost of the found tour. Cost run() { _path.clear(); if (_gr.nodeNum() == 0) return _sum = 0; else if (_gr.nodeNum() == 1) { _path.push_back(_gr(0)); return _sum = 0; } else if (_gr.nodeNum() == 2) { _path.push_back(_gr(0)); _path.push_back(_gr(1)); return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))]; } _plist.resize(2*_gr.nodeNum()); for (int i = 1; i < _gr.nodeNum()-1; ++i) { _plist[2*i] = i-1; _plist[2*i+1] = i+1; } _plist[0] = _gr.nodeNum()-1; _plist[1] = 1; _plist[2*_gr.nodeNum()-2] = _gr.nodeNum()-2; _plist[2*_gr.nodeNum()-1] = 0; return start(); } /// \brief Runs the algorithm from the given tour. /// /// This function runs the algorithm starting from the given tour. /// /// \param tour The tour as a path structure. It must be a /// \ref checkPath() "valid path" containing excactly n arcs. /// /// \return The total cost of the found tour. template Cost run(const Path& tour) { _path.clear(); if (_gr.nodeNum() == 0) return _sum = 0; else if (_gr.nodeNum() == 1) { _path.push_back(_gr(0)); return _sum = 0; } else if (_gr.nodeNum() == 2) { _path.push_back(_gr(0)); _path.push_back(_gr(1)); return _sum = 2 * _cost[_gr.edge(_gr(0), _gr(1))]; } _plist.resize(2*_gr.nodeNum()); typename Path::ArcIt it(tour); int first = _gr.id(_gr.source(it)), prev = first, curr = _gr.id(_gr.target(it)), next = -1; _plist[2*first+1] = curr; for (++it; it != INVALID; ++it) { next = _gr.id(_gr.target(it)); _plist[2*curr] = prev; _plist[2*curr+1] = next; prev = curr; curr = next; } _plist[2*first] = prev; return start(); } /// \brief Runs the algorithm from the given tour. /// /// This function runs the algorithm starting from the given tour. /// /// \param tour The tour as a node sequence. It must be a standard /// sequence container storing all Nodes in the desired order. /// /// \return The total cost of the found tour. template