This commit is contained in:
jacekpoz 2024-06-20 13:36:52 +02:00
parent a475e4f7cf
commit e8a615111c
Signed by: poz
SSH key fingerprint: SHA256:JyLeVWE4bF3tDnFeUpUaJsPsNlJyBldDGV/dIKSLyN8
8 changed files with 1119 additions and 0 deletions

4
lab5/zad1/.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
target
results
times.gp
times.pdf

273
lab5/zad1/Cargo.lock generated Normal file
View 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
View 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
View 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
View file

@ -0,0 +1,4 @@
target/
results
rounds.gp
rounds.pdf

273
lab5/zad2/Cargo.lock generated Normal file
View 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
View 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
View 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();
}