From b9e8f74bb007a24ccc7bdb2f24ec6df7812a36f9 Mon Sep 17 00:00:00 2001 From: jacekpoz Date: Sat, 22 Jun 2024 17:06:24 +0200 Subject: [PATCH] big changes --- lab5/zad1/src/main.rs | 211 +++++++++++++++++++++++++++++------------- 1 file changed, 145 insertions(+), 66 deletions(-) diff --git a/lab5/zad1/src/main.rs b/lab5/zad1/src/main.rs index 77c9eb2..cf07dd9 100644 --- a/lab5/zad1/src/main.rs +++ b/lab5/zad1/src/main.rs @@ -1,84 +1,173 @@ #![feature(exitcode_exit_method)] -use std::{fmt::Display, fs::OpenOptions, io::{self, Write}, process::ExitCode, sync::Arc, time::Instant}; +use std::{cmp::{Ordering, Reverse}, collections::{BinaryHeap, HashSet}, fmt::Display, fs::OpenOptions, hash::Hash, io::{self, Write}, process::ExitCode, sync::Arc, time::Instant}; use dashmap::DashMap; use rand::{thread_rng, Rng}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; -#[derive(Clone, Copy)] +#[derive(Clone, Copy, Debug)] pub struct Edge { - pub u: usize, - pub v: usize, - pub w: f64, + pub src: usize, + pub dst: usize, + pub weight: f64, +} + +impl Hash for Edge { + fn hash(&self, state: &mut H) { + self.src.hash(state); + self.dst.hash(state); + } +} + +impl PartialOrd for Edge { + fn partial_cmp(&self, other: &Self) -> Option { + self.weight.partial_cmp(&other.weight) + } +} + +impl PartialEq for Edge { + fn eq(&self, other: &Self) -> bool { + self.weight == other.weight + } +} + +impl Eq for Edge {} + +impl Ord for Edge { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + self.weight.total_cmp(&other.weight) + } } pub struct Graph { pub size: usize, - pub edges: Vec>, + pub edges: Vec, } impl Graph { pub fn new(size: usize) -> Self { Self { size, - edges: (0..size) - .map(|i| - (0..size) - .map(|j| - if i == j { 0.0 } - else { thread_rng().gen::() } - ) - .collect::>() - ) - .collect::>(), + edges: (0..size).map(|u| + (0..size).map(|v| + Edge { src: u, dst: v, weight: 0.0 } + ).collect::>() + ).flatten() + .collect::>(), } } - fn min(&self, key: &Vec, mst: &Vec) -> usize { - let mut min = f64::INFINITY; - let mut min_index = usize::MAX; + pub fn new_rand(size: usize) -> Self { + Self { + size, + edges: (0..size).map(|u| + (0..size).map(|v| + Edge { + src: u, + dst: v, + weight: if u == v { 0.0 } + else { thread_rng().gen::() } + } + ).collect::>() + ).flatten() + .collect::>(), + } + } - for i in 0..self.size { - if mst[i] == false && key[i] < min { - min = key[i]; - min_index = i; - } + pub fn vertex(&self, u: usize, v: usize) -> Option { + if u >= self.size || v >= self.size { + return None; } - min_index + Some(self.edges.iter().find(|e| e.src == u && e.dst == v).unwrap().weight) } pub fn prim(&self) -> Vec { - let mut parent = vec![0; self.size]; + // Associate with each vertex v of the graph a number C[v] (the cheapest cost of a connection to v) and an edge E[v] (the edge providing that cheapest connection). To initialize these values, set all values of C[v] to +∞ (or to any number larger than the maximum edge weight) and set each E[v] to a special flag value indicating that there is no edge connecting v to earlier vertices. + let mut min_edges = (0..self.size) + .map(|i| + *self.edges.iter() + .filter(|e| (e.src == i || e.dst == i) && e.src != e.dst) + .min() + .unwrap() + ).collect::>(); + // dbg!(&min_edges); - let mut key = vec![f64::INFINITY; self.size]; + // helper struct for the queue + #[derive(Clone, Debug)] + struct Vertex { + index: usize, + min_weight: f64, + } - let mut mst = vec![false; self.size]; + impl Hash for Vertex { + fn hash(&self, state: &mut H) { + self.index.hash(state); + } + } - key[0] = 0.0; - parent[0] = usize::MAX; + impl PartialEq for Vertex { + fn eq(&self, other: &Self) -> bool { + self.min_weight == other.min_weight + } + } - for _ in 0..(self.size - 1) { - let u = self.min(&key, &mst); - mst[u] = true; + impl Eq for Vertex {} - for j in 0..self.size { - if self.edges[u][j] != 0.0 && mst[j] == false && self.edges[u][j] < key[j] { - parent[j] = u; - key[j] = self.edges[u][j]; + impl PartialOrd for Vertex { + fn partial_cmp(&self, other: &Self) -> Option { + self.min_weight.partial_cmp(&other.min_weight) + } + } + + impl Ord for Vertex { + fn cmp(&self, other: &Self) -> Ordering { + self.min_weight.total_cmp(&other.min_weight) + } + } + + // Initialize an empty forest F + let mut forest = vec![]; + // and a set Q of vertices + let mut queue = BinaryHeap::>::new(); + + // that have not yet been included in F (initially, all vertices). + (0..self.size) + .map(|i| Vertex { index: i, min_weight: min_edges[i].weight }) + .for_each(|v| queue.push(Reverse(v))); + + // Repeat the following steps until Q is empty: + // Find and remove a vertex v from Q having the minimum possible value of C[v] + while let Some(Reverse(v)) = queue.pop() { + // Add v to F + forest.push(v.clone()); + + // Loop over the edges vw connecting v to other vertices w. + for vw in self.edges.iter() + .filter(|e| (e.src == v.index || e.dst == v.index) && e.src != e.dst) { + + // the vertex in the current edge that isn't v.src + let w = if vw.src == v.index { vw.dst } else { vw.src }; + + // For each such edge, if w still belongs to Q and vw has smaller weight than C[w], perform the following steps: + if queue.clone().iter().any(|Reverse(e)| e.index == w || e.index == w) && vw.weight < min_edges[w].weight { + dbg!(&w); + // Set C[w] to the cost of edge vw + // Set E[w] to point to edge vw. + min_edges[w] = *vw; } } } - (0..self.size) - .filter(|i| parent[*i] != usize::MAX) - .map(|i| Edge { - u: parent[i], - v: i, - w: self.edges[i][parent[i]], - }) - .collect() + // dbg!(&min_edges); + // Return F, which specifically includes the corresponding edges in E + forest.iter() + .map(|i| min_edges[i.index]) + .collect::>() + .iter() + .map(|e| *e) + .collect::>() } fn find_id(belongs: &mut Vec, i: usize) -> usize { @@ -104,21 +193,11 @@ impl Graph { } pub fn kruskal(&self) -> Vec { - let mut edges = vec![]; - - for i in 0..self.size { - for j in 0..i { - if self.edges[i][j] != 0.0 { - edges.push(Edge { - u: i, - v: j, - w: self.edges[i][j], - }); - } - } - } + let mut edges = self.edges.iter() + .filter(|e| e.weight != 0.0) + .collect::>(); - edges.sort_by(|e1, e2| e1.w.total_cmp(&e2.w)); + edges.sort(); let mut belongs = (0..self.size).collect::>(); let mut rank = vec![0; self.size]; @@ -126,11 +205,11 @@ impl Graph { let mut mst = Vec::with_capacity(self.size); for i in 0..edges.len() { - let a = Self::find_id(&mut belongs, edges[i].u); - let b = Self::find_id(&mut belongs, edges[i].v); + let a = Self::find_id(&mut belongs, edges[i].src); + let b = Self::find_id(&mut belongs, edges[i].dst); if a != b { - mst.push(edges[i]); + mst.push(*edges[i]); Self::union(&mut belongs, &mut rank, a, b); } @@ -144,7 +223,7 @@ impl Display for Graph { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { for i in 0..self.size { for j in 0..self.size { - write!(f, "{weight:.6} ", weight = self.edges[i][j])?; + write!(f, "{weight:.6} ", weight = self.vertex(i, j).unwrap())?; } write!(f, "\n")?; } @@ -157,7 +236,7 @@ fn print_mst(mst: &Vec) { println!("vertex\t\tweight"); for edge in mst { - println!("{} - {}\t\t{:.6}", edge.u, edge.v, edge.w); + println!("{} - {}\t\t{:.6}", edge.src, edge.dst, edge.weight); } } @@ -190,7 +269,7 @@ fn test() { println!("{n}: starting"); (0..rep).into_par_iter().for_each(|k| { println!("\t{n}: iteration {k}"); - let graph = Graph::new(n); + let graph = Graph::new_rand(n); let prim_timer = Instant::now(); graph.prim(); @@ -239,7 +318,7 @@ fn show() { .parse::() .expect("graph size should be usize"); - let graph = Graph::new(size); + let graph = Graph::new_rand(size); println!(); println!("graph:");