big changes
This commit is contained in:
parent
e8a615111c
commit
b9e8f74bb0
1 changed files with 145 additions and 66 deletions
|
@ -1,84 +1,173 @@
|
||||||
#![feature(exitcode_exit_method)]
|
#![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 dashmap::DashMap;
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||||
|
|
||||||
#[derive(Clone, Copy)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct Edge {
|
pub struct Edge {
|
||||||
pub u: usize,
|
pub src: usize,
|
||||||
pub v: usize,
|
pub dst: usize,
|
||||||
pub w: f64,
|
pub weight: f64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hash for Edge {
|
||||||
|
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.src.hash(state);
|
||||||
|
self.dst.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialOrd for Edge {
|
||||||
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
|
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 struct Graph {
|
||||||
pub size: usize,
|
pub size: usize,
|
||||||
pub edges: Vec<Vec<f64>>,
|
pub edges: Vec<Edge>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Graph {
|
impl Graph {
|
||||||
pub fn new(size: usize) -> Self {
|
pub fn new(size: usize) -> Self {
|
||||||
Self {
|
Self {
|
||||||
size,
|
size,
|
||||||
edges: (0..size)
|
edges: (0..size).map(|u|
|
||||||
.map(|i|
|
(0..size).map(|v|
|
||||||
(0..size)
|
Edge { src: u, dst: v, weight: 0.0 }
|
||||||
.map(|j|
|
).collect::<Vec<_>>()
|
||||||
if i == j { 0.0 }
|
).flatten()
|
||||||
else { thread_rng().gen::<f64>() }
|
.collect::<Vec<_>>(),
|
||||||
)
|
|
||||||
.collect::<Vec<_>>()
|
|
||||||
)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn min(&self, key: &Vec<f64>, mst: &Vec<bool>) -> usize {
|
pub fn new_rand(size: usize) -> Self {
|
||||||
let mut min = f64::INFINITY;
|
Self {
|
||||||
let mut min_index = usize::MAX;
|
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::<f64>() }
|
||||||
|
}
|
||||||
|
).collect::<Vec<_>>()
|
||||||
|
).flatten()
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for i in 0..self.size {
|
pub fn vertex(&self, u: usize, v: usize) -> Option<f64> {
|
||||||
if mst[i] == false && key[i] < min {
|
if u >= self.size || v >= self.size {
|
||||||
min = key[i];
|
return None;
|
||||||
min_index = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
min_index
|
Some(self.edges.iter().find(|e| e.src == u && e.dst == v).unwrap().weight)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn prim(&self) -> Vec<Edge> {
|
pub fn prim(&self) -> Vec<Edge> {
|
||||||
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::<Vec<_>>();
|
||||||
|
// 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<H: std::hash::Hasher>(&self, state: &mut H) {
|
||||||
|
self.index.hash(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
key[0] = 0.0;
|
impl PartialEq for Vertex {
|
||||||
parent[0] = usize::MAX;
|
fn eq(&self, other: &Self) -> bool {
|
||||||
|
self.min_weight == other.min_weight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for _ in 0..(self.size - 1) {
|
impl Eq for Vertex {}
|
||||||
let u = self.min(&key, &mst);
|
|
||||||
mst[u] = true;
|
|
||||||
|
|
||||||
for j in 0..self.size {
|
impl PartialOrd for Vertex {
|
||||||
if self.edges[u][j] != 0.0 && mst[j] == false && self.edges[u][j] < key[j] {
|
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
|
||||||
parent[j] = u;
|
self.min_weight.partial_cmp(&other.min_weight)
|
||||||
key[j] = self.edges[u][j];
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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::<Reverse<Vertex>>::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)
|
// dbg!(&min_edges);
|
||||||
.filter(|i| parent[*i] != usize::MAX)
|
// Return F, which specifically includes the corresponding edges in E
|
||||||
.map(|i| Edge {
|
forest.iter()
|
||||||
u: parent[i],
|
.map(|i| min_edges[i.index])
|
||||||
v: i,
|
.collect::<HashSet<_>>()
|
||||||
w: self.edges[i][parent[i]],
|
.iter()
|
||||||
})
|
.map(|e| *e)
|
||||||
.collect()
|
.collect::<Vec<_>>()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_id(belongs: &mut Vec<usize>, i: usize) -> usize {
|
fn find_id(belongs: &mut Vec<usize>, i: usize) -> usize {
|
||||||
|
@ -104,21 +193,11 @@ impl Graph {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn kruskal(&self) -> Vec<Edge> {
|
pub fn kruskal(&self) -> Vec<Edge> {
|
||||||
let mut edges = vec![];
|
let mut edges = self.edges.iter()
|
||||||
|
.filter(|e| e.weight != 0.0)
|
||||||
for i in 0..self.size {
|
.collect::<Vec<_>>();
|
||||||
for j in 0..i {
|
|
||||||
if self.edges[i][j] != 0.0 {
|
|
||||||
edges.push(Edge {
|
|
||||||
u: i,
|
|
||||||
v: j,
|
|
||||||
w: self.edges[i][j],
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
edges.sort_by(|e1, e2| e1.w.total_cmp(&e2.w));
|
edges.sort();
|
||||||
|
|
||||||
let mut belongs = (0..self.size).collect::<Vec<_>>();
|
let mut belongs = (0..self.size).collect::<Vec<_>>();
|
||||||
let mut rank = vec![0; self.size];
|
let mut rank = vec![0; self.size];
|
||||||
|
@ -126,11 +205,11 @@ impl Graph {
|
||||||
let mut mst = Vec::with_capacity(self.size);
|
let mut mst = Vec::with_capacity(self.size);
|
||||||
|
|
||||||
for i in 0..edges.len() {
|
for i in 0..edges.len() {
|
||||||
let a = Self::find_id(&mut belongs, edges[i].u);
|
let a = Self::find_id(&mut belongs, edges[i].src);
|
||||||
let b = Self::find_id(&mut belongs, edges[i].v);
|
let b = Self::find_id(&mut belongs, edges[i].dst);
|
||||||
|
|
||||||
if a != b {
|
if a != b {
|
||||||
mst.push(edges[i]);
|
mst.push(*edges[i]);
|
||||||
|
|
||||||
Self::union(&mut belongs, &mut rank, a, b);
|
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 {
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
for i in 0..self.size {
|
for i in 0..self.size {
|
||||||
for j 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")?;
|
write!(f, "\n")?;
|
||||||
}
|
}
|
||||||
|
@ -157,7 +236,7 @@ fn print_mst(mst: &Vec<Edge>) {
|
||||||
println!("vertex\t\tweight");
|
println!("vertex\t\tweight");
|
||||||
|
|
||||||
for edge in mst {
|
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");
|
println!("{n}: starting");
|
||||||
(0..rep).into_par_iter().for_each(|k| {
|
(0..rep).into_par_iter().for_each(|k| {
|
||||||
println!("\t{n}: iteration {k}");
|
println!("\t{n}: iteration {k}");
|
||||||
let graph = Graph::new(n);
|
let graph = Graph::new_rand(n);
|
||||||
|
|
||||||
let prim_timer = Instant::now();
|
let prim_timer = Instant::now();
|
||||||
graph.prim();
|
graph.prim();
|
||||||
|
@ -239,7 +318,7 @@ fn show() {
|
||||||
.parse::<usize>()
|
.parse::<usize>()
|
||||||
.expect("graph size should be usize");
|
.expect("graph size should be usize");
|
||||||
|
|
||||||
let graph = Graph::new(size);
|
let graph = Graph::new_rand(size);
|
||||||
|
|
||||||
println!();
|
println!();
|
||||||
println!("graph:");
|
println!("graph:");
|
||||||
|
|
Loading…
Reference in a new issue