From a6cc4056ab01c2cb652c35763fd9aa2632b04692 Mon Sep 17 00:00:00 2001 From: DanArmor <39347109+DanArmor@users.noreply.github.com> Date: Thu, 5 Oct 2023 02:49:55 +0300 Subject: [PATCH 1/4] feat: ability to inverse weights of WalkerTableBuilder --- CHANGELOG.md | 6 ++++++ Cargo.lock | 2 +- Cargo.toml | 4 ++-- src/builder.rs | 14 ++++++++++++++ src/util.rs | 1 - 5 files changed, 23 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bac5768..f706da2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Change Log +## 0.4.2 - 2023-10-2 + +### Changes + +- [#5](https://github.com/ichi-h/weighted_rand/pull/5) Thanks [@DanArmor](https://github.com/DanArmor)! - fix: return 1 for gcd_for_slice if all elements are 0.0 + ## 0.4.1 - 2023-7-3 ### Changes diff --git a/Cargo.lock b/Cargo.lock index 8ff6801..f927bb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -628,7 +628,7 @@ dependencies = [ [[package]] name = "weighted_rand" -version = "0.4.1" +version = "0.4.2" dependencies = [ "criterion", "rand", diff --git a/Cargo.toml b/Cargo.toml index 083e471..8632bab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "weighted_rand" -version = "0.4.1" +version = "0.4.2" authors = ["Ichi "] description = "A weighted random sampling crate using Walker's Alias Method." documentation = "https://docs.rs/weighted_rand" @@ -14,7 +14,7 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -serde = { version="1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive"] } rand = "0.8" [dev-dependencies] diff --git a/src/builder.rs b/src/builder.rs index 5280c0b..c9450f2 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -86,6 +86,20 @@ impl WalkerTableBuilder { WalkerTable::new(aliases, probs) } + pub fn inverse(self) -> WalkerTableBuilder { + let min_value = match self.index_weights.iter().min() { + Some(v) => *v, + None => 0 + }; + let max_value = match self.index_weights.iter().max() { + Some(v) => *v, + None => 0 + }; + Self { + index_weights: self.index_weights.into_iter().map(|x| max_value + min_value - x).collect() + } + } + /// Calculates the sum of `index_weights`. fn sum(&self) -> u32 { self.index_weights.iter().fold(0, |acc, cur| acc + cur) diff --git a/src/util.rs b/src/util.rs index f454393..bbe7d14 100644 --- a/src/util.rs +++ b/src/util.rs @@ -14,7 +14,6 @@ pub mod math { return 0; } - let first = slice[0]; let mut iter = slice.iter().skip_while(|x| x == &&0); let first = match iter.next() { Some(v) => *v, From df6b5934bf412c95df383dba66c780858dcf4331 Mon Sep 17 00:00:00 2001 From: DanArmor <39347109+DanArmor@users.noreply.github.com> Date: Sun, 8 Oct 2023 22:24:55 +0300 Subject: [PATCH 2/4] fix: prevented overflow --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index c9450f2..9d0bcad 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -96,7 +96,7 @@ impl WalkerTableBuilder { None => 0 }; Self { - index_weights: self.index_weights.into_iter().map(|x| max_value + min_value - x).collect() + index_weights: self.index_weights.into_iter().map(|x| max_value - x + min_value).collect() } } From 0269f87232fbc4dd4374cd20a175ce0c4ab71f99 Mon Sep 17 00:00:00 2001 From: DanArmor <39347109+DanArmor@users.noreply.github.com> Date: Sun, 8 Oct 2023 22:28:28 +0300 Subject: [PATCH 3/4] docs: added comment for inverse --- src/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builder.rs b/src/builder.rs index 9d0bcad..1069035 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -86,6 +86,7 @@ impl WalkerTableBuilder { WalkerTable::new(aliases, probs) } + /// Inverses given weights pub fn inverse(self) -> WalkerTableBuilder { let min_value = match self.index_weights.iter().min() { Some(v) => *v, From 298aef5e69908efd5fed3be05713f4f04aef4e08 Mon Sep 17 00:00:00 2001 From: DanArmor <39347109+DanArmor@users.noreply.github.com> Date: Sun, 8 Oct 2023 22:51:22 +0300 Subject: [PATCH 4/4] fix: min and max values during inverse fix: min and max values during inverse --- src/builder.rs | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 1069035..6ff57a9 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -90,15 +90,27 @@ impl WalkerTableBuilder { pub fn inverse(self) -> WalkerTableBuilder { let min_value = match self.index_weights.iter().min() { Some(v) => *v, - None => 0 + None => 0, }; let max_value = match self.index_weights.iter().max() { Some(v) => *v, - None => 0 + None => 0, }; Self { - index_weights: self.index_weights.into_iter().map(|x| max_value - x + min_value).collect() - } + index_weights: self + .index_weights + .into_iter() + .map(|x| { + if x == max_value { + min_value + } else if x == min_value { + max_value + } else { + max_value - x + } + }) + .collect(), + } } /// Calculates the sum of `index_weights`.