lemon/christofides_tsp.h
author Peter Kovacs <kpeter@inf.elte.hu>
Sat, 08 Jan 2011 22:49:09 +0100
changeset 1032 62ba43576f85
child 1033 9a51db038228
permissions -rw-r--r--
Doc group for TSP algorithms (#386)
f4c3@1031
     1
#ifndef LEMON_CHRISTOFIDES_TSP_H
f4c3@1031
     2
#define LEMON_CHRISTOFIDES_TSP_H
f4c3@1031
     3
f4c3@1031
     4
#include <lemon/full_graph.h>
f4c3@1031
     5
#include <lemon/smart_graph.h>
f4c3@1031
     6
#include <lemon/path.h>
f4c3@1031
     7
#include <lemon/kruskal.h>
f4c3@1031
     8
#include <lemon/matching.h>
f4c3@1031
     9
#include <lemon/adaptors.h>
f4c3@1031
    10
#include <lemon/maps.h>
f4c3@1031
    11
#include <lemon/euler.h>
f4c3@1031
    12
f4c3@1031
    13
namespace lemon {
f4c3@1031
    14
  
f4c3@1031
    15
  namespace christofides_helper {
f4c3@1031
    16
    template <class L>
f4c3@1031
    17
    L vectorConvert(const std::vector<FullGraph::Node> &_path) {
f4c3@1031
    18
      return L(_path.begin(), _path.end());
f4c3@1031
    19
    }
f4c3@1031
    20
  
f4c3@1031
    21
    template <>
f4c3@1031
    22
    std::vector<FullGraph::Node> vectorConvert(const std::vector<FullGraph::Node> &_path) {
f4c3@1031
    23
      return _path;
f4c3@1031
    24
    }
f4c3@1031
    25
  }
f4c3@1031
    26
  
f4c3@1031
    27
  template <typename CM>
f4c3@1031
    28
  class ChristofidesTsp {
f4c3@1031
    29
    private:
f4c3@1031
    30
      GRAPH_TYPEDEFS(SmartGraph);
f4c3@1031
    31
f4c3@1031
    32
    public:
f4c3@1031
    33
      typedef typename CM::Value Cost;
f4c3@1031
    34
      typedef SmartGraph::EdgeMap<Cost> CostMap;
f4c3@1031
    35
    
f4c3@1031
    36
      ChristofidesTsp(const FullGraph &gr, const CM &cost) : _cost(_gr), fullg(gr), fullcost(cost), nr(_gr) {
f4c3@1031
    37
        graphCopy(gr, _gr).nodeCrossRef(nr).edgeMap(cost, _cost).run();
f4c3@1031
    38
      }
f4c3@1031
    39
f4c3@1031
    40
      Cost run() {
f4c3@1031
    41
        _path.clear();
f4c3@1031
    42
        
f4c3@1031
    43
        SmartGraph::EdgeMap<bool> tree(_gr);
f4c3@1031
    44
        kruskal(_gr, _cost, tree);
f4c3@1031
    45
        
f4c3@1031
    46
        FilterEdges<SmartGraph> treefiltered(_gr, tree);
f4c3@1031
    47
        InDegMap<FilterEdges<SmartGraph> > deg(treefiltered);
f4c3@1031
    48
        
f4c3@1031
    49
        SmartGraph::NodeMap<bool> oddfilter(_gr, false);
f4c3@1031
    50
        FilterNodes<SmartGraph> oddNodes(_gr, oddfilter);
f4c3@1031
    51
        
f4c3@1031
    52
        for (NodeIt n(_gr); n!=INVALID; ++n) {
f4c3@1031
    53
          if (deg[n]%2 == 1) {
f4c3@1031
    54
            oddNodes.enable(n);
f4c3@1031
    55
          }
f4c3@1031
    56
        }
f4c3@1031
    57
        
f4c3@1031
    58
        NegMap<CostMap> negmap(_cost);
f4c3@1031
    59
        MaxWeightedPerfectMatching<FilterNodes<SmartGraph>,
f4c3@1031
    60
                  NegMap<CostMap> > perfmatch(oddNodes, negmap);
f4c3@1031
    61
        perfmatch.run();
f4c3@1031
    62
        
f4c3@1031
    63
        for (FilterNodes<SmartGraph>::EdgeIt e(oddNodes); e!=INVALID; ++e) {
f4c3@1031
    64
          if (perfmatch.matching(e)) {
f4c3@1031
    65
            treefiltered.enable(_gr.addEdge(_gr.u(e), _gr.v(e)));
f4c3@1031
    66
          }
f4c3@1031
    67
        }
f4c3@1031
    68
        
f4c3@1031
    69
        FilterEdges<SmartGraph>::NodeMap<bool> seen(treefiltered, false);
f4c3@1031
    70
        for (EulerIt<FilterEdges<SmartGraph> > e(treefiltered); e!=INVALID; ++e) {
f4c3@1031
    71
          if (seen[treefiltered.target(e)]==false) {
f4c3@1031
    72
            _path.push_back(nr[treefiltered.target(e)]);
f4c3@1031
    73
            seen[treefiltered.target(e)] = true;
f4c3@1031
    74
          }
f4c3@1031
    75
        }
f4c3@1031
    76
f4c3@1031
    77
        _sum = fullcost[ fullg.edge(_path.back(), _path.front()) ];
f4c3@1031
    78
        for (unsigned int i=0; i<_path.size()-1; ++i)
f4c3@1031
    79
          _sum += fullcost[ fullg.edge(_path[i], _path[i+1]) ];
f4c3@1031
    80
f4c3@1031
    81
        return _sum;
f4c3@1031
    82
      }
f4c3@1031
    83
f4c3@1031
    84
      template <typename L>
f4c3@1031
    85
      void tourNodes(L &container) {
f4c3@1031
    86
        container(christofides_helper::vectorConvert<L>(_path));
f4c3@1031
    87
      }
f4c3@1031
    88
      
f4c3@1031
    89
      template <template <typename> class L>
f4c3@1031
    90
      L<FullGraph::Node> tourNodes() {
f4c3@1031
    91
        return christofides_helper::vectorConvert<L<FullGraph::Node> >(_path);
f4c3@1031
    92
      }
f4c3@1031
    93
f4c3@1031
    94
      const std::vector<Node>& tourNodes() {
f4c3@1031
    95
        return _path;
f4c3@1031
    96
      }
f4c3@1031
    97
      
f4c3@1031
    98
      Path<FullGraph> tour() {
f4c3@1031
    99
        Path<FullGraph> p;
f4c3@1031
   100
        if (_path.size()<2)
f4c3@1031
   101
          return p;
f4c3@1031
   102
f4c3@1031
   103
        for (unsigned int i=0; i<_path.size()-1; ++i) {
f4c3@1031
   104
          p.addBack(fullg.arc(_path[i], _path[i+1]));
f4c3@1031
   105
        }
f4c3@1031
   106
        p.addBack(fullg.arc(_path.back(), _path.front()));
f4c3@1031
   107
        
f4c3@1031
   108
        return p;
f4c3@1031
   109
      }
f4c3@1031
   110
      
f4c3@1031
   111
      Cost tourCost() {
f4c3@1031
   112
        return _sum;
f4c3@1031
   113
      }
f4c3@1031
   114
      
f4c3@1031
   115
f4c3@1031
   116
  private:
f4c3@1031
   117
    SmartGraph _gr;
f4c3@1031
   118
    CostMap _cost;
f4c3@1031
   119
    Cost _sum;
f4c3@1031
   120
    const FullGraph &fullg;
f4c3@1031
   121
    const CM &fullcost;
f4c3@1031
   122
    std::vector<FullGraph::Node> _path;
f4c3@1031
   123
    SmartGraph::NodeMap<FullGraph::Node> nr;
f4c3@1031
   124
  };
f4c3@1031
   125
f4c3@1031
   126
f4c3@1031
   127
}; // namespace lemon
f4c3@1031
   128
f4c3@1031
   129
#endif