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 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120
//! Find an exact solution to the Travelling Salesman Problem using Brute Force
//!
//! **Note: This isn't really a useful algorithm as Brute force is `O(n!)`, and is only included
//! for completeness.**
//!
//!# Examples
//!
//!```
//!extern crate travelling_salesman;
//!
//!fn main() {
//! let tour = travelling_salesman::brute_force::solve(
//! &[
//! (27.0, 78.0),
//! (18.0, 24.0),
//! (48.0, 62.0),
//! (83.0, 77.0),
//! (55.0, 56.0),
//! ],
//! );
//!
//! println!("Tour distance: {}, route: {:?}", tour.distance, tour.route);
//!}
//!```
//!
use std::collections::HashSet;
use std::iter::FromIterator;
use super::{get_distance_matrix, get_route_distance, Tour};
/// Returns an exact solution to the Travelling Salesman Problem using Brute Force
///
/// **Note: This isn't really a useful algorithm as Brute force is `O(n!)`, and is only included
/// for completeness.**
///
///# Parameters and Return Type
///
/// `cities` is an array slice, containing `(x,y)` tuple coordinates for each city.
///
/// Returns a `travelling_salesman::Tour` struct, representing the approximate solution found.
///
///# Examples
///
///```
///extern crate travelling_salesman;
///
///fn main() {
/// let tour = travelling_salesman::brute_force::solve(
/// &[
/// (27.0, 78.0),
/// (18.0, 24.0),
/// (48.0, 62.0),
/// (83.0, 77.0),
/// (55.0, 56.0),
/// ],
/// );
///
/// println!("Tour distance: {}, route: {:?}", tour.distance, tour.route);
///}
///```
pub fn solve(cities: &[(f64, f64)]) -> Tour {
let mut smallest_tour = Tour {
distance: 0.0,
route: vec![],
};
if cities.is_empty() {
return smallest_tour;
}
let mut unvisited_cities =
HashSet::<usize>::from_iter((0..cities.len()).collect::<Vec<usize>>());
let current_route = vec![0];
unvisited_cities.remove(&0);
_brute_force(
&get_distance_matrix(cities),
unvisited_cities,
current_route,
&mut smallest_tour,
);
smallest_tour
}
fn _brute_force(
distance_matrix: &[Vec<f64>],
unvisited_cities: HashSet<usize>,
current_route: Vec<usize>,
smallest_tour: &mut Tour,
) {
for unvisited_city in &unvisited_cities {
let mut my_unvisited_cities = unvisited_cities.clone();
my_unvisited_cities.remove(unvisited_city);
let mut my_route = current_route.clone();
my_route.push(*unvisited_city);
if my_unvisited_cities.is_empty() {
let home_city = my_route[0];
my_route.push(home_city);
let my_route_distance = get_route_distance(distance_matrix, &my_route);
if (smallest_tour.distance == 0.0) || (my_route_distance < smallest_tour.distance) {
smallest_tour.distance = my_route_distance;
smallest_tour.route = my_route;
}
return;
}
_brute_force(
distance_matrix,
my_unvisited_cities,
my_route,
smallest_tour,
);
}
}