1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
//! Travelling Salesman Problem Solvers.
//!
//! The aim of this crate is to host various Travelling Salesman Problem solvers. Patches
//! implementing useful algorithms most welcome.
//!
//! # Examples
//! ```
//! extern crate travelling_salesman;
//!
//! use travelling_salesman::brute_force;
//!
//! fn main() {
//!     let cities = [
//!         (27.0, 78.0),
//!         (18.0, 24.0),
//!         (48.0, 62.0),
//!         (83.0, 17.0),
//!     ];
//!
//!     let tour = brute_force::solve(&cities);
//!     println!("tour distance: {}, tour route: {:?}", tour.distance, tour.route);
//! }
//!
//! ```

pub mod brute_force;

/// Represents a tour of the travelling salesman
pub struct Tour {
    /// the total distance travelled following this tour
    pub distance: f64,
    /// the ordered route for this tour
    pub route:    Vec<u32>,
}

/// Utility function to convert city coordinates to a distance matrix
///
/// # Examples
/// ```
/// extern crate travelling_salesman;
///
/// use travelling_salesman::*;
///
/// fn main() {
///     let cities = [
///         (27.0, 78.0),
///         (18.0, 24.0),
///         (48.0, 62.0),
///         (83.0, 17.0),
///     ];
///
///     let distance_matrix = get_distance_matrix(&cities);
///
///     assert!(distance_matrix[0][0] == 0.0);
///     assert!(distance_matrix[1][2] == distance_matrix[2][1]);
///     assert!((distance_matrix[0][3] - 82.807005).abs() < 0.000001);
/// }
/// ```
pub fn get_distance_matrix(cities: &[(f64, f64)]) -> Vec<Vec<f64>> {
    cities.iter().map(|row| {
        cities.iter().map(|column| {
            ((column.0 - row.0).powi(2) + (column.1 - row.1).powi(2)).sqrt()
        }).collect::<Vec<f64>>()
    }).collect::<Vec<Vec<f64>>>()
}

/// Utility function to calculate the distance travelled following the specified route
///
/// # Examples
/// ```
/// extern crate travelling_salesman;
///
/// use travelling_salesman::*;
///
/// fn main() {
///     let cities = [
///         (27.0, 78.0),
///         (18.0, 24.0),
///         (48.0, 62.0),
///         (83.0, 17.0),
///     ];
///
///     let distance_matrix = get_distance_matrix(&cities);
///     let route_distance  = get_route_distance(&distance_matrix, &vec![3, 0, 2, 1, 3]);
///
///     assert!((route_distance - 222.998472).abs() < 0.000001);
/// }
/// ```
pub fn get_route_distance(distance_matrix: &Vec<Vec<f64>>, route: &Vec<u32>) -> f64 {
    let mut route_iter   = route.iter();
    let mut current_city = match route_iter.next() {
        None    => return 0.0,
        Some(v) => *v,
    };

    route_iter.fold(0.0, |mut total_distance, &next_city| {
        total_distance += distance_matrix[current_city as usize][next_city as usize];
        current_city    = next_city;
        total_distance
    })
}