Implement floyd-warshall algorithm for course 4 assignment 1

master
Felix Martin 2021-02-23 10:40:15 -05:00
parent 82cbb528b1
commit 1a9f178c97
8 changed files with 144150 additions and 83 deletions

47979
data/c4a1_g1.txt Normal file

File diff suppressed because it is too large Load Diff

47979
data/c4a1_g2.txt Normal file

File diff suppressed because it is too large Load Diff

47979
data/c4a1_g3.txt Normal file

File diff suppressed because it is too large Load Diff

77
src/floyd_warshall.rs Normal file
View File

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

View File

@ -1,4 +1,3 @@
#[derive(Debug)] #[derive(Debug)]
pub struct Knapsack { pub struct Knapsack {
pub size: usize, pub size: usize,
@ -8,26 +7,26 @@ pub struct Knapsack {
#[derive(Debug)] #[derive(Debug)]
pub struct Item { pub struct Item {
pub value: usize, pub value: usize,
pub weight: usize, pub weight: usize,
} }
pub fn knapsack(k: &Knapsack) -> usize { pub fn knapsack(k: &Knapsack) -> usize {
let mut weight_to_value = vec![0; k.size]; let mut weight_to_value = vec![0; k.size];
for item_index in 0..k.n_items { for item_index in 0..k.n_items {
let mut new_weight_to_value = weight_to_value.to_vec(); let mut new_weight_to_value = weight_to_value.to_vec();
let item = &k.items[item_index]; let item = &k.items[item_index];
for weight in 0..k.size { for weight in 0..k.size {
if weight >= item.weight { if weight >= item.weight {
let current_value = weight_to_value[weight]; let current_value = weight_to_value[weight];
let new_value = weight_to_value[weight - item.weight] + item.value; let new_value = weight_to_value[weight - item.weight] + item.value;
if new_value > current_value { if new_value > current_value {
new_weight_to_value[weight] = new_value; new_weight_to_value[weight] = new_value;
} }
} }
} }
weight_to_value = new_weight_to_value; weight_to_value = new_weight_to_value;
} }
weight_to_value.pop().unwrap() weight_to_value.pop().unwrap()
} }

View File

@ -1,32 +1,33 @@
mod dijkstra; mod dijkstra;
mod floyd_warshall;
mod heap; mod heap;
mod huffman; mod huffman;
mod jobs; mod jobs;
mod k_clustering; mod k_clustering;
mod k_clustering_big; mod k_clustering_big;
mod mwis; mod knapsack;
mod merge_sort; mod merge_sort;
mod min_cut; mod min_cut;
mod mwis;
mod prims; mod prims;
mod quick_sort; mod quick_sort;
mod ssc; mod ssc;
mod two_sum; mod two_sum;
mod util; mod util;
mod knapsack;
use crate::dijkstra::dijkstra; use crate::dijkstra::dijkstra;
use crate::heap::heap; use crate::heap::heap;
use crate::jobs::{jobs_1, jobs_2}; use crate::jobs::{jobs_1, jobs_2};
use crate::k_clustering::k_clustering; use crate::k_clustering::k_clustering;
use crate::k_clustering_big::k_clustering_big; use crate::k_clustering_big::k_clustering_big;
use crate::knapsack::knapsack;
use crate::merge_sort::merge_sort_inversions; use crate::merge_sort::merge_sort_inversions;
use crate::min_cut::min_cut; use crate::min_cut::min_cut;
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::two_sum::find_two_sums; use crate::two_sum::find_two_sums;
use crate::mwis::mwis;
use crate::knapsack::knapsack;
use std::cmp::min; use std::cmp::min;
#[allow(dead_code)] #[allow(dead_code)]
@ -133,18 +134,30 @@ fn c3a3() {
#[allow(dead_code)] #[allow(dead_code)]
fn c3a4() { fn c3a4() {
let k1 = util::read_knapsack("data/c3a4_knapsack1.txt").unwrap(); let k1 = util::read_knapsack("data/c3a4_knapsack1.txt").unwrap();
let r1 = knapsack::knapsack(&k1); let r1 = knapsack::knapsack(&k1);
let k2 = util::read_knapsack("data/c3a4_knapsack_big.txt").unwrap(); let k2 = util::read_knapsack("data/c3a4_knapsack_big.txt").unwrap();
let r2 = knapsack::knapsack(&k2); let r2 = knapsack::knapsack(&k2);
println!("r1 = {} r2 = {}", r1, r2); println!("r1 = {} r2 = {}", r1, r2);
// r1 = 2493893 r2 = 4243395 // r1 = 2493893 r2 = 4243395
} }
#[allow(dead_code)] #[allow(dead_code)]
fn c4a4() { fn c4a1() {
println!("Final course!"); let g1 = util::read_floyd_warshall_graph("data/c4a1_g1.txt").unwrap();
let r1 = floyd_warshall::floyd_warshall(g1);
let g2 = util::read_floyd_warshall_graph("data/c4a1_g2.txt").unwrap();
let r2 = floyd_warshall::floyd_warshall(g2);
let g3 = util::read_floyd_warshall_graph("data/c4a1_g3.txt").unwrap();
let r3 = floyd_warshall::floyd_warshall(g3);
println!("r1 = {:?} r2 = {:?} r3 = {:?}", r1, r2, r3);
// r = -19
}
#[allow(dead_code)]
fn c4a2() {
println!("continue here");
} }
fn main() { fn main() {
@ -158,6 +171,7 @@ fn main() {
// c3a1(); // c3a1();
// c3a2(); // c3a2();
// c3a3(); // c3a3();
c3a4(); // c3a4();
c4a4(); // c4a1();
c4a2();
} }

View File

@ -1,4 +1,3 @@
#[derive(Debug)] #[derive(Debug)]
pub struct IndependentSet { pub struct IndependentSet {
pub length: usize, pub length: usize,
@ -7,54 +6,52 @@ pub struct IndependentSet {
#[derive(Debug)] #[derive(Debug)]
struct Solution { struct Solution {
weight: u64, weight: u64,
nodes: Vec<usize>, nodes: Vec<usize>,
} }
pub fn mwis(s: &IndependentSet) -> Vec<usize> { pub fn mwis(s: &IndependentSet) -> Vec<usize> {
let mut solutions: Vec<Solution> = Vec::new(); let mut solutions: Vec<Solution> = Vec::new();
solutions.push(Solution {
weight: s.weights[0],
nodes: vec![0],
});
solutions.push(Solution { solutions.push(Solution {
weight: s.weights[0], weight: s.weights[1],
nodes: vec![0], nodes: vec![1],
}); });
solutions.push(Solution { for i in 2..s.weights.len() {
weight: s.weights[1], let s1 = Solution {
nodes: vec![1], weight: solutions[i - 1].weight,
}); nodes: solutions[i - 1].nodes.to_vec(),
};
for i in 2..s.weights.len() { let mut s2_vec = solutions[i - 2].nodes.to_vec();
let s1 = Solution { s2_vec.push(i);
weight: solutions[i - 1].weight, let s2 = Solution {
nodes: solutions[i - 1].nodes.to_vec(), weight: solutions[i - 2].weight + s.weights[i],
}; nodes: s2_vec,
};
let mut s2_vec = solutions[i - 2].nodes.to_vec(); if s1.weight > s2.weight {
s2_vec.push(i); solutions.push(s1);
let s2 = Solution { } else {
weight: solutions[i - 2].weight + s.weights[i], solutions.push(s2);
nodes: s2_vec, }
}; }
if s1.weight > s2.weight { let solution = solutions.pop().unwrap();
solutions.push(s1); let mut result = Vec::new();
} else { let vertices = vec![0, 1, 2, 3, 16, 116, 516, 996];
solutions.push(s2); for v in &vertices {
} if solution.nodes.contains(v) {
result.push(1);
} } else {
result.push(0);
let solution = solutions.pop().unwrap(); }
let mut result = Vec::new(); }
let vertices = vec![0, 1, 2, 3, 16, 116, 516, 996]; result
for v in &vertices { }
if solution.nodes.contains(v) {
result.push(1);
} else {
result.push(0);
}
}
result
}

View File

@ -1,12 +1,13 @@
use crate::floyd_warshall;
use crate::huffman; use crate::huffman;
use crate::jobs; use crate::jobs;
use crate::k_clustering; use crate::k_clustering;
use crate::k_clustering_big; use crate::k_clustering_big;
use crate::knapsack;
use crate::min_cut; use crate::min_cut;
use crate::mwis;
use crate::prims; use crate::prims;
use crate::ssc; use crate::ssc;
use crate::mwis;
use crate::knapsack;
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};
@ -288,8 +289,8 @@ pub fn read_knapsack(path: &str) -> Result<knapsack::Knapsack, io::Error> {
let mut lines = BufReader::new(file).lines(); let mut lines = BufReader::new(file).lines();
let line = lines.next().unwrap().unwrap(); let line = lines.next().unwrap().unwrap();
let mut fields = line.split_whitespace(); let mut fields = line.split_whitespace();
let knapsack_size = fields.next().unwrap().parse().unwrap(); let knapsack_size = fields.next().unwrap().parse().unwrap();
let number_of_items = fields.next().unwrap().parse().unwrap(); let number_of_items = fields.next().unwrap().parse().unwrap();
let mut k = knapsack::Knapsack { let mut k = knapsack::Knapsack {
size: knapsack_size, size: knapsack_size,
n_items: number_of_items, n_items: number_of_items,
@ -299,8 +300,8 @@ pub fn read_knapsack(path: &str) -> Result<knapsack::Knapsack, io::Error> {
for line in lines { for line in lines {
let line = line?; let line = line?;
let mut fields = line.split_whitespace(); let mut fields = line.split_whitespace();
let value = fields.next().unwrap().parse().unwrap(); let value = fields.next().unwrap().parse().unwrap();
let weight = fields.next().unwrap().parse().unwrap(); let weight = fields.next().unwrap().parse().unwrap();
let item = knapsack::Item { let item = knapsack::Item {
value: value, value: value,
weight: weight, weight: weight,
@ -310,3 +311,45 @@ pub fn read_knapsack(path: &str) -> Result<knapsack::Knapsack, io::Error> {
Ok(k) Ok(k)
} }
pub fn read_floyd_warshall_graph(path: &str) -> Result<floyd_warshall::Graph, io::Error> {
let file = File::open(path)?;
let mut lines = BufReader::new(file).lines();
let line = lines.next().unwrap()?;
let mut fields = line.split_whitespace();
let n_nodes = fields.next().unwrap().parse().unwrap();
let n_edges = fields.next().unwrap().parse().unwrap();
let mut g = floyd_warshall::Graph {
n_nodes: n_nodes,
n_edges: n_edges,
nodes: Vec::new(),
};
for i in 0..n_nodes {
let n = floyd_warshall::Node {
id: i,
edges: Vec::new(),
};
g.nodes.push(n);
}
for line in lines {
let line = line?;
let mut it = line.split_whitespace();
let mut source = it.next().unwrap().parse().unwrap();
let mut target = it.next().unwrap().parse().unwrap();
let length = it.next().unwrap().parse().unwrap();
source = source - 1;
target = target - 1;
let e = floyd_warshall::Edge {
source: source,
target: target,
length: length,
};
g.nodes[source].edges.push(e);
}
Ok(g)
}