kpeter@1033: /* -*- mode: C++; indent-tabs-mode: nil; -*- kpeter@1033: * kpeter@1033: * This file is a part of LEMON, a generic C++ optimization library. kpeter@1033: * alpar@1092: * Copyright (C) 2003-2013 kpeter@1033: * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport kpeter@1033: * (Egervary Research Group on Combinatorial Optimization, EGRES). kpeter@1033: * kpeter@1033: * Permission to use, modify and distribute this software is granted kpeter@1033: * provided that this copyright notice appears in all copies. For kpeter@1033: * precise terms see the accompanying LICENSE file. kpeter@1033: * kpeter@1033: * This software is provided "AS IS" with no warranty of any kind, kpeter@1033: * express or implied, and with no claim as to its suitability for any kpeter@1033: * purpose. kpeter@1033: * kpeter@1033: */ kpeter@1033: f4c3@1031: #ifndef LEMON_NEAREST_NEIGHBOUR_TSP_H f4c3@1031: #define LEMON_NEAREST_NEIGHBOUR_TSP_H f4c3@1031: kpeter@1033: /// \ingroup tsp kpeter@1033: /// \file kpeter@1033: /// \brief Nearest neighbor algorithm for symmetric TSP kpeter@1033: f4c3@1031: #include kpeter@1034: #include kpeter@1033: #include f4c3@1031: #include f4c3@1031: #include f4c3@1031: f4c3@1031: namespace lemon { f4c3@1031: kpeter@1034: /// \ingroup tsp kpeter@1034: /// kpeter@1033: /// \brief Nearest neighbor algorithm for symmetric TSP. kpeter@1033: /// kpeter@1033: /// NearestNeighborTsp implements the nearest neighbor heuristic for solving kpeter@1033: /// symmetric \ref tsp "TSP". kpeter@1033: /// kpeter@1033: /// This is probably the simplest TSP heuristic. kpeter@1033: /// It starts with a minimum cost edge and at each step, it connects the kpeter@1033: /// nearest unvisited node to the current path. kpeter@1033: /// Finally, it connects the two end points of the path to form a tour. kpeter@1033: /// kpeter@1033: /// This method runs in O(n2) time. kpeter@1036: /// It quickly finds a relatively short tour for most TSP instances, kpeter@1036: /// but it could also yield a really bad (or even the worst) solution kpeter@1036: /// in special cases. kpeter@1033: /// kpeter@1033: /// \tparam CM Type of the cost map. f4c3@1031: template kpeter@1033: class NearestNeighborTsp kpeter@1033: { kpeter@1033: public: kpeter@1033: kpeter@1033: /// Type of the cost map kpeter@1033: typedef CM CostMap; kpeter@1033: /// Type of the edge costs kpeter@1033: typedef typename CM::Value Cost; kpeter@1033: f4c3@1031: private: kpeter@1033: f4c3@1031: GRAPH_TYPEDEFS(FullGraph); f4c3@1031: kpeter@1033: const FullGraph &_gr; kpeter@1033: const CostMap &_cost; kpeter@1033: Cost _sum; kpeter@1034: std::vector _path; kpeter@1033: f4c3@1031: public: f4c3@1031: kpeter@1033: /// \brief Constructor kpeter@1033: /// kpeter@1033: /// Constructor. kpeter@1033: /// \param gr The \ref FullGraph "full graph" the algorithm runs on. kpeter@1033: /// \param cost The cost map. kpeter@1033: NearestNeighborTsp(const FullGraph &gr, const CostMap &cost) kpeter@1033: : _gr(gr), _cost(cost) {} kpeter@1033: kpeter@1033: /// \name Execution Control kpeter@1033: /// @{ kpeter@1033: kpeter@1033: /// \brief Runs the algorithm. kpeter@1033: /// kpeter@1033: /// This function runs the algorithm. kpeter@1033: /// kpeter@1033: /// \return The total cost of the found tour. f4c3@1031: Cost run() { f4c3@1031: _path.clear(); kpeter@1034: if (_gr.nodeNum() == 0) { kpeter@1034: return _sum = 0; kpeter@1034: } kpeter@1033: else if (_gr.nodeNum() == 1) { kpeter@1033: _path.push_back(_gr(0)); kpeter@1033: return _sum = 0; kpeter@1033: } kpeter@1033: kpeter@1034: std::deque path_dq; f4c3@1031: Edge min_edge1 = INVALID, f4c3@1031: min_edge2 = INVALID; kpeter@1033: f4c3@1031: min_edge1 = mapMin(_gr, _cost); kpeter@1033: Node n1 = _gr.u(min_edge1), f4c3@1031: n2 = _gr.v(min_edge1); kpeter@1034: path_dq.push_back(n1); kpeter@1034: path_dq.push_back(n2); f4c3@1031: kpeter@1033: FullGraph::NodeMap used(_gr, false); f4c3@1031: used[n1] = true; f4c3@1031: used[n2] = true; f4c3@1031: f4c3@1031: min_edge1 = INVALID; kpeter@1034: while (int(path_dq.size()) != _gr.nodeNum()) { f4c3@1031: if (min_edge1 == INVALID) { kpeter@1033: for (IncEdgeIt e(_gr, n1); e != INVALID; ++e) { kpeter@1033: if (!used[_gr.runningNode(e)] && kpeter@1033: (_cost[e] < _cost[min_edge1] || min_edge1 == INVALID)) { kpeter@1033: min_edge1 = e; f4c3@1031: } f4c3@1031: } f4c3@1031: } f4c3@1031: f4c3@1031: if (min_edge2 == INVALID) { kpeter@1033: for (IncEdgeIt e(_gr, n2); e != INVALID; ++e) { kpeter@1033: if (!used[_gr.runningNode(e)] && kpeter@1033: (_cost[e] < _cost[min_edge2] || min_edge2 == INVALID)) { kpeter@1033: min_edge2 = e; f4c3@1031: } f4c3@1031: } f4c3@1031: } f4c3@1031: kpeter@1033: if (_cost[min_edge1] < _cost[min_edge2]) { kpeter@1033: n1 = _gr.oppositeNode(n1, min_edge1); kpeter@1034: path_dq.push_front(n1); f4c3@1031: f4c3@1031: used[n1] = true; f4c3@1031: min_edge1 = INVALID; f4c3@1031: kpeter@1033: if (_gr.u(min_edge2) == n1 || _gr.v(min_edge2) == n1) f4c3@1031: min_edge2 = INVALID; f4c3@1031: } else { kpeter@1033: n2 = _gr.oppositeNode(n2, min_edge2); kpeter@1034: path_dq.push_back(n2); f4c3@1031: f4c3@1031: used[n2] = true; f4c3@1031: min_edge2 = INVALID; f4c3@1031: kpeter@1033: if (_gr.u(min_edge1) == n2 || _gr.v(min_edge1) == n2) f4c3@1031: min_edge1 = INVALID; f4c3@1031: } f4c3@1031: } f4c3@1031: kpeter@1034: n1 = path_dq.back(); kpeter@1034: n2 = path_dq.front(); kpeter@1034: _path.push_back(n2); kpeter@1034: _sum = _cost[_gr.edge(n1, n2)]; kpeter@1034: for (int i = 1; i < int(path_dq.size()); ++i) { kpeter@1034: n1 = n2; kpeter@1034: n2 = path_dq[i]; kpeter@1034: _path.push_back(n2); kpeter@1034: _sum += _cost[_gr.edge(n1, n2)]; kpeter@1033: } f4c3@1031: f4c3@1031: return _sum; f4c3@1031: } f4c3@1031: kpeter@1033: /// @} kpeter@1033: kpeter@1033: /// \name Query Functions kpeter@1033: /// @{ kpeter@1033: kpeter@1033: /// \brief The total cost of the found tour. kpeter@1033: /// kpeter@1033: /// This function returns the total cost of the found tour. kpeter@1033: /// kpeter@1033: /// \pre run() must be called before using this function. kpeter@1033: Cost tourCost() const { kpeter@1033: return _sum; f4c3@1031: } f4c3@1031: kpeter@1033: /// \brief Returns a const reference to the node sequence of the kpeter@1033: /// found tour. kpeter@1033: /// kpeter@1034: /// This function returns a const reference to a vector kpeter@1033: /// that stores the node sequence of the found tour. kpeter@1033: /// kpeter@1033: /// \pre run() must be called before using this function. kpeter@1034: const std::vector& tourNodes() const { f4c3@1031: return _path; f4c3@1031: } kpeter@1033: kpeter@1033: /// \brief Gives back the node sequence of the found tour. kpeter@1033: /// kpeter@1033: /// This function copies the node sequence of the found tour into kpeter@1037: /// an STL container through the given output iterator. The kpeter@1037: /// value_type of the container must be FullGraph::Node. kpeter@1037: /// For example, kpeter@1037: /// \code kpeter@1037: /// std::vector nodes(countNodes(graph)); kpeter@1037: /// tsp.tourNodes(nodes.begin()); kpeter@1037: /// \endcode kpeter@1037: /// or kpeter@1037: /// \code kpeter@1037: /// std::list nodes; kpeter@1037: /// tsp.tourNodes(std::back_inserter(nodes)); kpeter@1037: /// \endcode kpeter@1033: /// kpeter@1033: /// \pre run() must be called before using this function. kpeter@1037: template kpeter@1037: void tourNodes(Iterator out) const { kpeter@1037: std::copy(_path.begin(), _path.end(), out); kpeter@1033: } kpeter@1033: kpeter@1033: /// \brief Gives back the found tour as a path. kpeter@1033: /// kpeter@1033: /// This function copies the found tour as a list of arcs/edges into alpar@1074: /// the given \ref lemon::concepts::Path "path structure". kpeter@1033: /// kpeter@1033: /// \pre run() must be called before using this function. kpeter@1033: template kpeter@1033: void tour(Path &path) const { kpeter@1033: path.clear(); kpeter@1033: for (int i = 0; i < int(_path.size()) - 1; ++i) { kpeter@1033: path.addBack(_gr.arc(_path[i], _path[i+1])); f4c3@1031: } kpeter@1033: if (int(_path.size()) >= 2) { kpeter@1033: path.addBack(_gr.arc(_path.back(), _path.front())); kpeter@1033: } f4c3@1031: } f4c3@1031: kpeter@1033: /// @} kpeter@1033: f4c3@1031: }; f4c3@1031: f4c3@1031: }; // namespace lemon f4c3@1031: f4c3@1031: #endif