l5
This commit is contained in:
parent
a475e4f7cf
commit
e8a615111c
8 changed files with 1119 additions and 0 deletions
4
lab5/zad1/.gitignore
vendored
Normal file
4
lab5/zad1/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
target
|
||||
results
|
||||
times.gp
|
||||
times.pdf
|
273
lab5/zad1/Cargo.lock
generated
Normal file
273
lab5/zad1/Cargo.lock
generated
Normal file
|
@ -0,0 +1,273 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "zad1"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dashmap",
|
||||
"rand",
|
||||
"rayon",
|
||||
]
|
9
lab5/zad1/Cargo.toml
Normal file
9
lab5/zad1/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "zad1"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
rayon = "1.10.0"
|
||||
dashmap = "5.5.3"
|
283
lab5/zad1/src/main.rs
Normal file
283
lab5/zad1/src/main.rs
Normal file
|
@ -0,0 +1,283 @@
|
|||
#![feature(exitcode_exit_method)]
|
||||
|
||||
use std::{fmt::Display, fs::OpenOptions, 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)]
|
||||
pub struct Edge {
|
||||
pub u: usize,
|
||||
pub v: usize,
|
||||
pub w: f64,
|
||||
}
|
||||
|
||||
pub struct Graph {
|
||||
pub size: usize,
|
||||
pub edges: Vec<Vec<f64>>,
|
||||
}
|
||||
|
||||
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::<f64>() }
|
||||
)
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
}
|
||||
|
||||
fn min(&self, key: &Vec<f64>, mst: &Vec<bool>) -> usize {
|
||||
let mut min = f64::INFINITY;
|
||||
let mut min_index = usize::MAX;
|
||||
|
||||
for i in 0..self.size {
|
||||
if mst[i] == false && key[i] < min {
|
||||
min = key[i];
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
min_index
|
||||
}
|
||||
|
||||
pub fn prim(&self) -> Vec<Edge> {
|
||||
let mut parent = vec![0; self.size];
|
||||
|
||||
let mut key = vec![f64::INFINITY; self.size];
|
||||
|
||||
let mut mst = vec![false; self.size];
|
||||
|
||||
key[0] = 0.0;
|
||||
parent[0] = usize::MAX;
|
||||
|
||||
for _ in 0..(self.size - 1) {
|
||||
let u = self.min(&key, &mst);
|
||||
mst[u] = true;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(0..self.size)
|
||||
.filter(|i| parent[*i] != usize::MAX)
|
||||
.map(|i| Edge {
|
||||
u: parent[i],
|
||||
v: i,
|
||||
w: self.edges[i][parent[i]],
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn find_id(belongs: &mut Vec<usize>, i: usize) -> usize {
|
||||
if belongs[i] != i {
|
||||
belongs[i] = Self::find_id(belongs, belongs[i]);
|
||||
}
|
||||
|
||||
return belongs[i];
|
||||
}
|
||||
|
||||
fn union(belongs: &mut Vec<usize>, rank: &mut Vec<usize>, x: usize, y: usize) {
|
||||
let x_root = Self::find_id(belongs, x);
|
||||
let y_root = Self::find_id(belongs, y);
|
||||
|
||||
if rank[x_root] < rank[y_root] {
|
||||
belongs[x_root] = y_root;
|
||||
} else if rank[x_root] > rank[y_root] {
|
||||
belongs[y_root] = x_root;
|
||||
} else {
|
||||
belongs[y_root] = x_root;
|
||||
rank[x_root] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub fn kruskal(&self) -> Vec<Edge> {
|
||||
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],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edges.sort_by(|e1, e2| e1.w.total_cmp(&e2.w));
|
||||
|
||||
let mut belongs = (0..self.size).collect::<Vec<_>>();
|
||||
let mut rank = vec![0; self.size];
|
||||
|
||||
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);
|
||||
|
||||
if a != b {
|
||||
mst.push(edges[i]);
|
||||
|
||||
Self::union(&mut belongs, &mut rank, a, b);
|
||||
}
|
||||
}
|
||||
|
||||
mst
|
||||
}
|
||||
}
|
||||
|
||||
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, "\n")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn print_mst(mst: &Vec<Edge>) {
|
||||
println!("vertex\t\tweight");
|
||||
|
||||
for edge in mst {
|
||||
println!("{} - {}\t\t{:.6}", edge.u, edge.v, edge.w);
|
||||
}
|
||||
}
|
||||
|
||||
fn time_avg(results_map: &DashMap<usize, Vec<u128>>) -> DashMap<usize, f64> {
|
||||
results_map.iter()
|
||||
.map(|ref_multi| {
|
||||
let (i, results) = ref_multi.pair();
|
||||
(*i, (results.iter()
|
||||
.sum::<u128>() as f64 / results.len() as f64))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let n_min = 1000usize;
|
||||
let n_max = 10000usize;
|
||||
let step = 1000usize;
|
||||
let rep = 10usize;
|
||||
|
||||
let prim_times: Arc<DashMap<usize, Vec<u128>>> = Arc::new(DashMap::new());
|
||||
let kruskal_times: Arc<DashMap<usize, Vec<u128>>> = Arc::new(DashMap::new());
|
||||
|
||||
let prim_times_clone = Arc::clone(&prim_times);
|
||||
let kruskal_times_clone = Arc::clone(&kruskal_times);
|
||||
|
||||
// step_by isn't implemented for the ..= iter :-(
|
||||
(n_min..(n_max + 1)).into_par_iter().step_by(step).for_each(|n| {
|
||||
prim_times_clone.insert(n, vec![]);
|
||||
kruskal_times_clone.insert(n, vec![]);
|
||||
println!("{n}: starting");
|
||||
(0..rep).into_par_iter().for_each(|k| {
|
||||
println!("\t{n}: iteration {k}");
|
||||
let graph = Graph::new(n);
|
||||
|
||||
let prim_timer = Instant::now();
|
||||
graph.prim();
|
||||
let prim_time = prim_timer.elapsed().as_millis();
|
||||
|
||||
prim_times_clone.get_mut(&n).unwrap().push(prim_time);
|
||||
|
||||
let kruskal_timer = Instant::now();
|
||||
graph.kruskal();
|
||||
let kruskal_time = kruskal_timer.elapsed().as_millis();
|
||||
|
||||
kruskal_times_clone.get_mut(&n).unwrap().push(kruskal_time);
|
||||
});
|
||||
println!("{n}: finished");
|
||||
});
|
||||
|
||||
let prim_time_averages = time_avg(&prim_times);
|
||||
let kruskal_time_averages = time_avg(&kruskal_times);
|
||||
|
||||
let mut results_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open("./results")
|
||||
.expect("can't open file");
|
||||
|
||||
for n in (n_min..=n_max).step_by(step) {
|
||||
writeln!(results_file, "{n} {} {}",
|
||||
prim_time_averages.get(&n).unwrap().value(),
|
||||
kruskal_time_averages.get(&n).unwrap().value(),
|
||||
).expect("can't write to file");
|
||||
}
|
||||
}
|
||||
|
||||
fn show() {
|
||||
let mut input = String::new();
|
||||
|
||||
print!("graph size: ");
|
||||
_ = io::stdout().flush();
|
||||
|
||||
io::stdin()
|
||||
.read_line(&mut input)
|
||||
.expect("pass the graph size");
|
||||
|
||||
let size = input.trim()
|
||||
.parse::<usize>()
|
||||
.expect("graph size should be usize");
|
||||
|
||||
let graph = Graph::new(size);
|
||||
|
||||
println!();
|
||||
println!("graph:");
|
||||
println!("{}", graph);
|
||||
|
||||
println!("prim:");
|
||||
println!();
|
||||
let mst_prim = graph.prim();
|
||||
|
||||
print_mst(&mst_prim);
|
||||
|
||||
println!();
|
||||
|
||||
println!("kruskal:");
|
||||
println!();
|
||||
let mst_kruskal = graph.kruskal();
|
||||
|
||||
print_mst(&mst_kruskal);
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match std::env::args().nth(1) {
|
||||
Some(s) => {
|
||||
match s.as_str() {
|
||||
"--test" => {
|
||||
test();
|
||||
ExitCode::SUCCESS.exit_process();
|
||||
},
|
||||
"--show" => {
|
||||
show();
|
||||
ExitCode::SUCCESS.exit_process();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
|
||||
eprintln!("pass either --test or --show");
|
||||
ExitCode::FAILURE.exit_process();
|
||||
}
|
4
lab5/zad2/.gitignore
vendored
Normal file
4
lab5/zad2/.gitignore
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
target/
|
||||
results
|
||||
rounds.gp
|
||||
rounds.pdf
|
273
lab5/zad2/Cargo.lock
generated
Normal file
273
lab5/zad2/Cargo.lock
generated
Normal file
|
@ -0,0 +1,273 @@
|
|||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-deque"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||
dependencies = [
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||
dependencies = [
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80"
|
||||
|
||||
[[package]]
|
||||
name = "dashmap"
|
||||
version = "5.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"hashbrown",
|
||||
"lock_api",
|
||||
"once_cell",
|
||||
"parking_lot_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hashbrown"
|
||||
version = "0.14.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"scopeguard",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.19.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.9.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"smallvec",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon"
|
||||
version = "1.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa"
|
||||
dependencies = [
|
||||
"either",
|
||||
"rayon-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rayon-core"
|
||||
version = "1.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2"
|
||||
dependencies = [
|
||||
"crossbeam-deque",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c82cf8cff14456045f55ec4241383baeff27af886adb72ffb2162f99911de0fd"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
version = "1.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
|
||||
[[package]]
|
||||
name = "zad2"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dashmap",
|
||||
"rand",
|
||||
"rayon",
|
||||
]
|
9
lab5/zad2/Cargo.toml
Normal file
9
lab5/zad2/Cargo.toml
Normal file
|
@ -0,0 +1,9 @@
|
|||
[package]
|
||||
name = "zad2"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
rand = "0.8.5"
|
||||
rayon = "1.10.0"
|
||||
dashmap = "5.5.3"
|
264
lab5/zad2/src/main.rs
Normal file
264
lab5/zad2/src/main.rs
Normal file
|
@ -0,0 +1,264 @@
|
|||
#![feature(exitcode_exit_method)]
|
||||
|
||||
use std::{fmt::Display, fs::OpenOptions, io::{self, Write}, process::ExitCode, sync::Arc};
|
||||
|
||||
use dashmap::DashMap;
|
||||
use rand::{thread_rng, Rng};
|
||||
use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator};
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub struct Edge {
|
||||
pub u: usize,
|
||||
pub v: usize,
|
||||
pub w: f64,
|
||||
}
|
||||
|
||||
pub struct Graph {
|
||||
pub size: usize,
|
||||
pub edges: Vec<Vec<f64>>,
|
||||
}
|
||||
|
||||
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::<f64>() }
|
||||
)
|
||||
.collect::<Vec<_>>()
|
||||
)
|
||||
.collect::<Vec<_>>(),
|
||||
}
|
||||
}
|
||||
|
||||
fn min(&self, key: &Vec<f64>, mst: &Vec<bool>) -> usize {
|
||||
let mut min = f64::INFINITY;
|
||||
let mut min_index = usize::MAX;
|
||||
|
||||
for i in 0..self.size {
|
||||
if mst[i] == false && key[i] < min {
|
||||
min = key[i];
|
||||
min_index = i;
|
||||
}
|
||||
}
|
||||
|
||||
min_index
|
||||
}
|
||||
|
||||
pub fn prim(&self) -> Vec<Edge> {
|
||||
let mut parent = vec![0; self.size];
|
||||
|
||||
let mut key = vec![f64::INFINITY; self.size];
|
||||
|
||||
let mut mst = vec![false; self.size];
|
||||
|
||||
key[0] = 0.0;
|
||||
parent[0] = usize::MAX;
|
||||
|
||||
for _ in 0..(self.size - 1) {
|
||||
let u = self.min(&key, &mst);
|
||||
mst[u] = true;
|
||||
|
||||
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];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
(0..self.size)
|
||||
.filter(|i| parent[*i] != usize::MAX)
|
||||
.map(|i| Edge {
|
||||
u: parent[i],
|
||||
v: i,
|
||||
w: self.edges[i][parent[i]],
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn make_round(&self, vertex_index: usize, visited: &mut Vec<bool>, mst: &Vec<Edge>) -> u64 {
|
||||
let mut children_rounds = vec![];
|
||||
visited[vertex_index] = true;
|
||||
|
||||
let mut in_mst = vec![vec![false; self.size]; self.size];
|
||||
for e in mst {
|
||||
in_mst[e.v][e.u] = true;
|
||||
in_mst[e.u][e.v] = true;
|
||||
}
|
||||
|
||||
for i in 0..self.size {
|
||||
if in_mst[vertex_index][i] == true {
|
||||
if visited[i] == false {
|
||||
let child_rounds = self.make_round(i, visited, mst);
|
||||
children_rounds.push(child_rounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(max) = children_rounds.iter().max() {
|
||||
return max + 1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
fn calculate_rounds(&self, mst: &Vec<Edge>) -> u64 {
|
||||
let mut visited = vec![false; self.size];
|
||||
|
||||
let rand_vertex_index = thread_rng().gen_range(0..self.size);
|
||||
|
||||
return self.make_round(rand_vertex_index, &mut visited, mst);
|
||||
}
|
||||
}
|
||||
|
||||
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, "\n")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn print_mst(mst: &Vec<Edge>) {
|
||||
println!("vertex\t\tweight");
|
||||
|
||||
for edge in mst {
|
||||
println!("{} - {}\t\t{:.6}", edge.u, edge.v, edge.w);
|
||||
}
|
||||
}
|
||||
|
||||
fn round_avg(results_map: &DashMap<usize, Vec<u64>>) -> DashMap<usize, f64> {
|
||||
results_map.iter()
|
||||
.map(|ref_multi| {
|
||||
let (i, results) = ref_multi.pair();
|
||||
(*i, (results.iter()
|
||||
.sum::<u64>() as f64 / results.len() as f64))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn round_max(results_map: &DashMap<usize, Vec<u64>>) -> DashMap<usize, u64> {
|
||||
results_map.iter()
|
||||
.map(|ref_multi| {
|
||||
let (i, results) = ref_multi.pair();
|
||||
(*i, (*results.iter().max().unwrap()))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn round_min(results_map: &DashMap<usize, Vec<u64>>) -> DashMap<usize, u64> {
|
||||
results_map.iter()
|
||||
.map(|ref_multi| {
|
||||
let (i, results) = ref_multi.pair();
|
||||
(*i, (*results.iter().min().unwrap()))
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn test() {
|
||||
let n_min = 100usize;
|
||||
let n_max = 2500usize;
|
||||
let step = 100usize;
|
||||
let rep = 10usize;
|
||||
|
||||
let rounds: Arc<DashMap<usize, Vec<u64>>> = Arc::new(DashMap::new());
|
||||
|
||||
let rounds_clone = Arc::clone(&rounds);
|
||||
|
||||
// step_by isn't implemented for the ..= iter :-(
|
||||
(n_min..(n_max + 1)).into_par_iter().step_by(step).for_each(|n| {
|
||||
rounds_clone.insert(n, vec![]);
|
||||
println!("{n}: starting");
|
||||
(0..rep).into_par_iter().for_each(|k| {
|
||||
println!("\t{n}: iteration {k}");
|
||||
let graph = Graph::new(n);
|
||||
|
||||
let mst = graph.prim();
|
||||
|
||||
let rounds = graph.calculate_rounds(&mst);
|
||||
|
||||
rounds_clone.get_mut(&n).unwrap().push(rounds);
|
||||
});
|
||||
println!("{n}: finished");
|
||||
});
|
||||
|
||||
let round_averages = round_avg(&rounds);
|
||||
let round_maxes = round_max(&rounds);
|
||||
let round_mins = round_min(&rounds);
|
||||
|
||||
let mut results_file = OpenOptions::new()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.truncate(true)
|
||||
.open("./results")
|
||||
.expect("can't open file");
|
||||
|
||||
for n in (n_min..=n_max).step_by(step) {
|
||||
writeln!(results_file, "{n} {} {} {}",
|
||||
round_averages.get(&n).unwrap().value(),
|
||||
round_maxes.get(&n).unwrap().value(),
|
||||
round_mins.get(&n).unwrap().value(),
|
||||
).expect("can't write to file");
|
||||
}
|
||||
}
|
||||
|
||||
fn show() {
|
||||
let mut input = String::new();
|
||||
|
||||
print!("graph size: ");
|
||||
_ = io::stdout().flush();
|
||||
|
||||
io::stdin()
|
||||
.read_line(&mut input)
|
||||
.expect("pass the graph size");
|
||||
|
||||
let size = input.trim()
|
||||
.parse::<usize>()
|
||||
.expect("graph size should be usize");
|
||||
|
||||
let graph = Graph::new(size);
|
||||
|
||||
println!();
|
||||
println!("graph:");
|
||||
println!("{}", graph);
|
||||
|
||||
println!("prim:");
|
||||
println!();
|
||||
let mst_prim = graph.prim();
|
||||
|
||||
print_mst(&mst_prim);
|
||||
|
||||
println!("rounds: {}", graph.calculate_rounds(&mst_prim));
|
||||
}
|
||||
|
||||
fn main() {
|
||||
match std::env::args().nth(1) {
|
||||
Some(s) => {
|
||||
match s.as_str() {
|
||||
"--test" => {
|
||||
test();
|
||||
ExitCode::SUCCESS.exit_process();
|
||||
},
|
||||
"--show" => {
|
||||
show();
|
||||
ExitCode::SUCCESS.exit_process();
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
},
|
||||
None => {},
|
||||
}
|
||||
|
||||
eprintln!("pass either --test or --show");
|
||||
ExitCode::FAILURE.exit_process();
|
||||
}
|
Loading…
Reference in a new issue