Please tell me anything that comes to mind. However, I am most interested in ways to make my code more idiomatic (modern) C++.
tsp.h:
// File: tsp.h
// Author: Rodion "rodde" Efremov; Aug 21, 2016
// License: there is no such, you can use it freely in your projects. However,
// if the code in this file fails, I am not to be held responsible.
#ifndef TSP_H
#define TSP_H
#include <vector>
namespace net {
namespace coderodde {
namespace tsp {
//////////////////////////////////////////
//// Computes the length of a tour. ////
//////////////////////////////////////////
double
get_tour_length(const std::vector<int>& tour,
const std::vector<std::vector<double>>& distance_matrix);
////////////////////////////////////////////////////////////////////////////
//// Solves the travelling salesman problem. The undirected graph ////
//// is specified by the adjacency matrix, that is expected to be ////
//// a square matrix. ////
////////////////////////////////////////////////////////////////////////////
std::vector<int>
travelling_salesman(std::vector<std::vector<double>>& distance_matrix);
} // End of net::coderodde::tsp
} // End of net::coderodde
} // End of net
#endif // TSP_H
tsp.cpp:
// File: tsp.cpp - implementation of tsp.h
// Author: Rodion "rodde" Efremov; Aug 21, 2016
// License: there is no such, you can use it freely in your projects. However,
// if the code in this file fails, I am not to be held responsible.
#ifndef TSP_H
#define TSP_H
#include "tsp.h"
#include <vector>
namespace net {
namespace coderodde {
namespace tsp {
//////////////////////////////////////////
//// Computes the length of a tour. ////
//////////////////////////////////////////
double
get_tour_length(const std::vector<int>& tour,
const std::vector<std::vector<double>>& distance_matrix)
{
double tour_length = 0.0;
for (size_t index = 0; index < tour.size(); ++index)
{
const size_t next_index = (index + 1) % tour.size();
const int node = tour[index];
const int next_node = tour[next_index];
tour_length += distance_matrix[node][next_node];
}
return tour_length;
}
////////////////////////////////////////////////////////////////////////////
//// Solves the travelling salesman problem. The undirected graph ////
//// is specified by the adjacency matrix, that is expected to be ////
//// a square matrix. ////
////////////////////////////////////////////////////////////////////////////
std::vector<int>
travelling_salesman(std::vector<std::vector<double>>& distance_matrix)
{
int n = 0;
std::vector<int> ret(distance_matrix.size());
std::generate(ret.begin(), ret.end(), [&n]{ return n++; });
std::vector<int> best_tour;
double best_tour_length = std::numeric_limits<double>::max();
do
{
double tentative_tour_length = get_tour_length(ret, distance_matrix);
if (best_tour_length > tentative_tour_length)
{
best_tour_length = tentative_tour_length;
best_tour = ret;
}
} while (std::next_permutation(ret.begin(), ret.end()));
return best_tour;
}
} // End of net::coderodde::tsp
} // End of net::coderodde
} // End of net
#endif // TSP_H
main.cpp:
#include <iostream>
#include <vector>
#include "tsp.h"
using net::coderodde::tsp::get_tour_length;
using net::coderodde::tsp::travelling_salesman;
/*******************************************************************************
* The demo graph is a clique of 4 nodes with the following weights:
*
* a - b: 4
* a - c: 1
* a - d: 6
* b - c: 5
* b - d: 3
* c - d: 2
*******************************************************************************/
int main(int argc, char** argv) {
std::vector<std::vector<double>> distance_matrix = {
// a, b, c, d:
{ 0.0, 4.0, 1.0, 6.0 }, // a
{ 4.0, 0.0, 5.0, 3.0 }, // b
{ 1.0, 5.0, 0.0, 2.0 }, // c
{ 6.0, 3.0, 2.0, 0.0 } //
};
std::vector<int> best_tour = travelling_salesman(distance_matrix);
std::cout << "Best tour: ";
for (auto i : best_tour)
{
std::cout << i << " -> ";
}
std::cout << best_tour[0]
<< ", cost: "
<< get_tour_length(best_tour, distance_matrix)
<< std::endl;
return 0;
}