Implement floyd-warshall algorithm for course 4 assignment 1
This commit is contained in:
47979
data/c4a1_g1.txt
Normal file
47979
data/c4a1_g1.txt
Normal file
File diff suppressed because it is too large
Load Diff
47979
data/c4a1_g2.txt
Normal file
47979
data/c4a1_g2.txt
Normal file
File diff suppressed because it is too large
Load Diff
47979
data/c4a1_g3.txt
Normal file
47979
data/c4a1_g3.txt
Normal file
File diff suppressed because it is too large
Load Diff
77
src/floyd_warshall.rs
Normal file
77
src/floyd_warshall.rs
Normal 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)
|
||||||
|
}
|
||||||
@@ -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()
|
||||||
}
|
}
|
||||||
42
src/main.rs
42
src/main.rs
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
81
src/mwis.rs
81
src/mwis.rs
@@ -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
|
|
||||||
}
|
}
|
||||||
47
src/util.rs
47
src/util.rs
@@ -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};
|
||||||
@@ -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)
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user