Finish course 4 assignment 3 TSP with heuristic

This commit is contained in:
Felix Martin 2021-02-28 14:42:37 -05:00
parent dfa9c9d27f
commit 78b8cf95b6
4 changed files with 102 additions and 30 deletions

View File

@ -21,56 +21,56 @@ pub struct Edge {
} }
pub fn floyd_warshall(g: Graph) -> Option<i64> { pub fn floyd_warshall(g: Graph) -> Option<i64> {
let n = g.n_nodes; let n = g.n_nodes;
let mut a: Vec<Vec<i64>> = vec![vec![std::i64::MAX; n]; n]; let mut a: Vec<Vec<i64>> = vec![vec![std::i64::MAX; n]; n];
// nodes have lengths of 0 to themself // nodes have lengths of 0 to themself
for i in 0..n { for i in 0..n {
a[i][i] = 0; a[i][i] = 0;
} }
// nodes that are connected get the length of their edge // nodes that are connected get the length of their edge
for n in &g.nodes { for n in &g.nodes {
for e in &n.edges { for e in &n.edges {
a[e.source][e.target] = e.length; a[e.source][e.target] = e.length;
} }
} }
// main workloop // main workloop
for k in 0..n { for k in 0..n {
let mut new_a = a.to_vec(); let mut new_a = a.to_vec();
for i in 0..n { for i in 0..n {
for j in 0..n { for j in 0..n {
let case_1 = a[i][j]; let case_1 = a[i][j];
let case_2 = match a[i][k].checked_add(a[k][j]) { let case_2 = match a[i][k].checked_add(a[k][j]) {
Some(v) => v, Some(v) => v,
None => std::i64::MAX, None => std::i64::MAX,
}; };
new_a[i][j] = min(case_1, case_2); new_a[i][j] = min(case_1, case_2);
} }
} }
a = new_a; a = new_a;
} }
// node to itself is negative means we have negative cost cycles // node to itself is negative means we have negative cost cycles
for i in 0..n { for i in 0..n {
if a[i][i] < 0 { if a[i][i] < 0 {
return None; return None;
} }
} }
// find min path from v to u // find min path from v to u
let mut r = std::i64::MAX; let mut r = std::i64::MAX;
for i in 0..n { for i in 0..n {
for j in 0..n { for j in 0..n {
if i != j { if i != j {
let d = a[i][j]; let d = a[i][j];
if d < r { if d < r {
r = d; r = d;
} }
} }
} }
} }
Some(r) Some(r)

View File

@ -12,6 +12,7 @@ mod mwis;
mod prims; mod prims;
mod quick_sort; mod quick_sort;
mod ssc; mod ssc;
mod tsp;
mod two_sum; mod two_sum;
mod util; mod util;
@ -27,6 +28,7 @@ use crate::mwis::mwis;
use crate::prims::prims; use crate::prims::prims;
use crate::quick_sort::quick_sort; use crate::quick_sort::quick_sort;
use crate::ssc::ssc; use crate::ssc::ssc;
use crate::tsp::tsp_heuristic;
use crate::two_sum::find_two_sums; use crate::two_sum::find_two_sums;
use std::cmp::min; use std::cmp::min;
@ -163,12 +165,14 @@ fn c4a2() {
#[allow(dead_code)] #[allow(dead_code)]
fn c4a3() { fn c4a3() {
println!("Continue here"); let g = util::read_tsp_graph("data/c4a3_tsp.txt").unwrap();
let r = tsp_heuristic(g);
println!("r = {}", r);
} }
#[allow(dead_code)] #[allow(dead_code)]
fn c4a4() { fn c4a4() {
println!("we are done!"); println!("we are done soon!");
} }
fn main() { fn main() {

39
src/tsp.rs Normal file
View File

@ -0,0 +1,39 @@
#[derive(Debug)]
pub struct Graph {
pub n_nodes: usize,
pub nodes: Vec<Node>,
}
#[derive(Debug, Copy, Clone)]
pub struct Node {
pub id: usize,
pub x: f64,
pub y: f64,
}
fn distance(a: &Node, b: &Node) -> f64 {
((a.x - b.x).powf(2.0) + (a.y - b.y).powf(2.0)).sqrt()
}
pub fn tsp_heuristic(mut g: Graph) -> f64 {
let mut dist: f64 = 0.0;
let mut current_node = g.nodes.remove(0);
let first_node = current_node;
while g.nodes.len() > 0 {
let mut min_dist = f64::MAX;
let mut min_id = 0;
for i in 0..g.nodes.len() {
let node = &g.nodes[i];
let new_dist = distance(node, &current_node);
if new_dist < min_dist {
min_dist = new_dist;
min_id = i;
}
}
current_node = g.nodes.remove(min_id);
dist += min_dist;
}
dist += distance(&current_node, &first_node);
dist
}

View File

@ -8,6 +8,7 @@ use crate::min_cut;
use crate::mwis; use crate::mwis;
use crate::prims; use crate::prims;
use crate::ssc; use crate::ssc;
use crate::tsp;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
use std::io::{BufRead, BufReader, Error, ErrorKind}; use std::io::{BufRead, BufReader, Error, ErrorKind};
@ -353,3 +354,31 @@ pub fn read_floyd_warshall_graph(path: &str) -> Result<floyd_warshall::Graph, io
Ok(g) Ok(g)
} }
pub fn read_tsp_graph(path: &str) -> Result<tsp::Graph, io::Error> {
let file = File::open(path)?;
let mut lines = BufReader::new(file).lines();
let line = lines.next().unwrap()?;
let n_nodes = line.parse().unwrap();
let mut g = tsp::Graph {
n_nodes: n_nodes,
nodes: Vec::new(),
};
for line in lines {
let line = line?;
let mut it = line.split_whitespace();
let node_id: usize = it.next().unwrap().parse().unwrap();
let x = it.next().unwrap().parse().unwrap();
let y = it.next().unwrap().parse().unwrap();
let n = tsp::Node {
id: node_id - 1,
x: x,
y: y,
};
g.nodes.push(n);
}
Ok(g)
}