Implement floyd-warshall algorithm for course 4 assignment 1
parent
82cbb528b1
commit
1a9f178c97
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -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)
|
||||
}
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Knapsack {
|
||||
pub size: usize,
|
||||
|
@ -8,26 +7,26 @@ pub struct Knapsack {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct Item {
|
||||
pub value: usize,
|
||||
pub weight: usize,
|
||||
pub value: usize,
|
||||
pub weight: usize,
|
||||
}
|
||||
|
||||
pub fn knapsack(k: &Knapsack) -> usize {
|
||||
let mut weight_to_value = vec![0; k.size];
|
||||
for item_index in 0..k.n_items {
|
||||
let mut new_weight_to_value = weight_to_value.to_vec();
|
||||
let item = &k.items[item_index];
|
||||
for weight in 0..k.size {
|
||||
if weight >= item.weight {
|
||||
let current_value = weight_to_value[weight];
|
||||
let new_value = weight_to_value[weight - item.weight] + item.value;
|
||||
if new_value > current_value {
|
||||
new_weight_to_value[weight] = new_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
weight_to_value = new_weight_to_value;
|
||||
}
|
||||
let mut weight_to_value = vec![0; k.size];
|
||||
for item_index in 0..k.n_items {
|
||||
let mut new_weight_to_value = weight_to_value.to_vec();
|
||||
let item = &k.items[item_index];
|
||||
for weight in 0..k.size {
|
||||
if weight >= item.weight {
|
||||
let current_value = weight_to_value[weight];
|
||||
let new_value = weight_to_value[weight - item.weight] + item.value;
|
||||
if new_value > current_value {
|
||||
new_weight_to_value[weight] = new_value;
|
||||
}
|
||||
}
|
||||
}
|
||||
weight_to_value = new_weight_to_value;
|
||||
}
|
||||
|
||||
weight_to_value.pop().unwrap()
|
||||
}
|
||||
weight_to_value.pop().unwrap()
|
||||
}
|
||||
|
|
42
src/main.rs
42
src/main.rs
|
@ -1,32 +1,33 @@
|
|||
mod dijkstra;
|
||||
mod floyd_warshall;
|
||||
mod heap;
|
||||
mod huffman;
|
||||
mod jobs;
|
||||
mod k_clustering;
|
||||
mod k_clustering_big;
|
||||
mod mwis;
|
||||
mod knapsack;
|
||||
mod merge_sort;
|
||||
mod min_cut;
|
||||
mod mwis;
|
||||
mod prims;
|
||||
mod quick_sort;
|
||||
mod ssc;
|
||||
mod two_sum;
|
||||
mod util;
|
||||
mod knapsack;
|
||||
|
||||
use crate::dijkstra::dijkstra;
|
||||
use crate::heap::heap;
|
||||
use crate::jobs::{jobs_1, jobs_2};
|
||||
use crate::k_clustering::k_clustering;
|
||||
use crate::k_clustering_big::k_clustering_big;
|
||||
use crate::knapsack::knapsack;
|
||||
use crate::merge_sort::merge_sort_inversions;
|
||||
use crate::min_cut::min_cut;
|
||||
use crate::mwis::mwis;
|
||||
use crate::prims::prims;
|
||||
use crate::quick_sort::quick_sort;
|
||||
use crate::ssc::ssc;
|
||||
use crate::two_sum::find_two_sums;
|
||||
use crate::mwis::mwis;
|
||||
use crate::knapsack::knapsack;
|
||||
use std::cmp::min;
|
||||
|
||||
#[allow(dead_code)]
|
||||
|
@ -133,18 +134,30 @@ fn c3a3() {
|
|||
|
||||
#[allow(dead_code)]
|
||||
fn c3a4() {
|
||||
let k1 = util::read_knapsack("data/c3a4_knapsack1.txt").unwrap();
|
||||
let r1 = knapsack::knapsack(&k1);
|
||||
let k1 = util::read_knapsack("data/c3a4_knapsack1.txt").unwrap();
|
||||
let r1 = knapsack::knapsack(&k1);
|
||||
|
||||
let k2 = util::read_knapsack("data/c3a4_knapsack_big.txt").unwrap();
|
||||
let r2 = knapsack::knapsack(&k2);
|
||||
println!("r1 = {} r2 = {}", r1, r2);
|
||||
// r1 = 2493893 r2 = 4243395
|
||||
let k2 = util::read_knapsack("data/c3a4_knapsack_big.txt").unwrap();
|
||||
let r2 = knapsack::knapsack(&k2);
|
||||
println!("r1 = {} r2 = {}", r1, r2);
|
||||
// r1 = 2493893 r2 = 4243395
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn c4a4() {
|
||||
println!("Final course!");
|
||||
fn c4a1() {
|
||||
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() {
|
||||
|
@ -158,6 +171,7 @@ fn main() {
|
|||
// c3a1();
|
||||
// c3a2();
|
||||
// c3a3();
|
||||
c3a4();
|
||||
c4a4();
|
||||
// c3a4();
|
||||
// c4a1();
|
||||
c4a2();
|
||||
}
|
||||
|
|
83
src/mwis.rs
83
src/mwis.rs
|
@ -1,4 +1,3 @@
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct IndependentSet {
|
||||
pub length: usize,
|
||||
|
@ -7,54 +6,52 @@ pub struct IndependentSet {
|
|||
|
||||
#[derive(Debug)]
|
||||
struct Solution {
|
||||
weight: u64,
|
||||
nodes: Vec<usize>,
|
||||
weight: u64,
|
||||
nodes: 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 {
|
||||
weight: s.weights[0],
|
||||
nodes: vec![0],
|
||||
});
|
||||
solutions.push(Solution {
|
||||
weight: s.weights[1],
|
||||
nodes: vec![1],
|
||||
});
|
||||
|
||||
solutions.push(Solution {
|
||||
weight: s.weights[1],
|
||||
nodes: vec![1],
|
||||
});
|
||||
for i in 2..s.weights.len() {
|
||||
let s1 = Solution {
|
||||
weight: solutions[i - 1].weight,
|
||||
nodes: solutions[i - 1].nodes.to_vec(),
|
||||
};
|
||||
|
||||
for i in 2..s.weights.len() {
|
||||
let s1 = Solution {
|
||||
weight: solutions[i - 1].weight,
|
||||
nodes: solutions[i - 1].nodes.to_vec(),
|
||||
};
|
||||
let mut s2_vec = solutions[i - 2].nodes.to_vec();
|
||||
s2_vec.push(i);
|
||||
let s2 = Solution {
|
||||
weight: solutions[i - 2].weight + s.weights[i],
|
||||
nodes: s2_vec,
|
||||
};
|
||||
|
||||
let mut s2_vec = solutions[i - 2].nodes.to_vec();
|
||||
s2_vec.push(i);
|
||||
let s2 = Solution {
|
||||
weight: solutions[i - 2].weight + s.weights[i],
|
||||
nodes: s2_vec,
|
||||
};
|
||||
if s1.weight > s2.weight {
|
||||
solutions.push(s1);
|
||||
} else {
|
||||
solutions.push(s2);
|
||||
}
|
||||
}
|
||||
|
||||
if s1.weight > s2.weight {
|
||||
solutions.push(s1);
|
||||
} else {
|
||||
solutions.push(s2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
let solution = solutions.pop().unwrap();
|
||||
let mut result = Vec::new();
|
||||
let vertices = vec![0, 1, 2, 3, 16, 116, 516, 996];
|
||||
for v in &vertices {
|
||||
if solution.nodes.contains(v) {
|
||||
result.push(1);
|
||||
} else {
|
||||
result.push(0);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
let solution = solutions.pop().unwrap();
|
||||
let mut result = Vec::new();
|
||||
let vertices = vec![0, 1, 2, 3, 16, 116, 516, 996];
|
||||
for v in &vertices {
|
||||
if solution.nodes.contains(v) {
|
||||
result.push(1);
|
||||
} else {
|
||||
result.push(0);
|
||||
}
|
||||
}
|
||||
result
|
||||
}
|
||||
|
|
55
src/util.rs
55
src/util.rs
|
@ -1,12 +1,13 @@
|
|||
use crate::floyd_warshall;
|
||||
use crate::huffman;
|
||||
use crate::jobs;
|
||||
use crate::k_clustering;
|
||||
use crate::k_clustering_big;
|
||||
use crate::knapsack;
|
||||
use crate::min_cut;
|
||||
use crate::mwis;
|
||||
use crate::prims;
|
||||
use crate::ssc;
|
||||
use crate::mwis;
|
||||
use crate::knapsack;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
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 line = lines.next().unwrap().unwrap();
|
||||
let mut fields = line.split_whitespace();
|
||||
let knapsack_size = fields.next().unwrap().parse().unwrap();
|
||||
let number_of_items = fields.next().unwrap().parse().unwrap();
|
||||
let knapsack_size = fields.next().unwrap().parse().unwrap();
|
||||
let number_of_items = fields.next().unwrap().parse().unwrap();
|
||||
let mut k = knapsack::Knapsack {
|
||||
size: knapsack_size,
|
||||
n_items: number_of_items,
|
||||
|
@ -299,8 +300,8 @@ pub fn read_knapsack(path: &str) -> Result<knapsack::Knapsack, io::Error> {
|
|||
for line in lines {
|
||||
let line = line?;
|
||||
let mut fields = line.split_whitespace();
|
||||
let value = fields.next().unwrap().parse().unwrap();
|
||||
let weight = fields.next().unwrap().parse().unwrap();
|
||||
let value = fields.next().unwrap().parse().unwrap();
|
||||
let weight = fields.next().unwrap().parse().unwrap();
|
||||
let item = knapsack::Item {
|
||||
value: value,
|
||||
weight: weight,
|
||||
|
@ -310,3 +311,45 @@ pub fn read_knapsack(path: &str) -> Result<knapsack::Knapsack, io::Error> {
|
|||
|
||||
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue