Skip to content

Commit fd1169b

Browse files
authored
Merge branch 'development' into feature/generic_ensemble
2 parents 5bb78eb + 66f77af commit fd1169b

9 files changed

Lines changed: 53 additions & 41 deletions

File tree

Cargo.toml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,7 @@ cfg-if = "1.0.0"
2525
ndarray = { version = "0.15", optional = true }
2626
num-traits = "0.2.12"
2727
num = "0.4"
28-
rand = { version = "0.9", default-features = false, features = ["small_rng"] }
29-
rand_distr = { version = "0.5", optional = true }
28+
rand = { version = "0.10.1", default-features = false, features = ["alloc"] }
3029
serde = { version = "1", features = ["derive"], optional = true }
3130
ordered-float = "5.1.0"
3231

@@ -37,13 +36,13 @@ typetag = { version = "0.2", optional = true }
3736
default = []
3837
serde = ["dep:serde", "dep:typetag"]
3938
ndarray-bindings = ["dep:ndarray"]
40-
datasets = ["dep:rand_distr", "std_rand", "serde"]
39+
datasets = ["std_rand", "serde"]
4140
std_rand = ["rand/std_rng", "rand/std", "rand/thread_rng"]
4241
# used by wasm32-unknown-unknown for in-browser usage
4342
js = ["getrandom/wasm_js"]
4443

4544
[target.'cfg(target_arch = "wasm32")'.dependencies]
46-
getrandom = { version = "0.3", optional = true }
45+
getrandom = { version = "0.4", optional = true }
4746

4847
[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dev-dependencies]
4948
wasm-bindgen-test = "0.3"

src/cluster/kmeans.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
use std::fmt::Debug;
5656
use std::marker::PhantomData;
5757

58-
use rand::Rng;
58+
use rand::RngExt;
5959
#[cfg(feature = "serde")]
6060
use serde::{Deserialize, Serialize};
6161

src/dataset/generator.rs

Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
11
//! # Dataset Generators
22
//!
3+
use rand::distr::Distribution;
34
use rand::distr::Uniform;
4-
use rand::prelude::*;
5-
use rand_distr::Normal;
65

76
use crate::dataset::Dataset;
87

8+
/// Sample from N(mean, std) via Box-Muller transform using only rand 0.10
9+
#[inline]
10+
fn sample_normal(mean: f32, std: f32, rng: &mut impl rand::Rng) -> f32 {
11+
let unit = Uniform::new(f32::EPSILON, 1.0f32).unwrap();
12+
let u1 = unit.sample(rng);
13+
let u2 = unit.sample(rng);
14+
let z = (-2.0 * u1.ln()).sqrt() * (2.0 * std::f32::consts::PI * u2).cos();
15+
mean + std * z
16+
}
17+
918
/// Generate `num_centers` clusters of normally distributed points
1019
pub fn make_blobs(
1120
num_samples: usize,
1221
num_features: usize,
1322
num_centers: usize,
1423
) -> Dataset<f32, f32> {
15-
let center_box = Uniform::new(-10.0, 10.0).expect("Invalid uniform range");
16-
let cluster_std = 1.0;
17-
let mut centers: Vec<Vec<Normal<f32>>> = Vec::with_capacity(num_centers);
18-
24+
let center_box = Uniform::new(-10.0f32, 10.0f32).expect("Invalid uniform range");
25+
let cluster_std = 1.0f32;
1926
let mut rng = rand::rng();
20-
for _ in 0..num_centers {
21-
centers.push(
27+
28+
// Pre-compute cluster centers (one mean per feature per cluster)
29+
let centers: Vec<Vec<f32>> = (0..num_centers)
30+
.map(|_| {
2231
(0..num_features)
23-
.map(|_| Normal::new(center_box.sample(&mut rng), cluster_std).unwrap())
24-
.collect(),
25-
);
26-
}
32+
.map(|_| center_box.sample(&mut rng))
33+
.collect()
34+
})
35+
.collect();
2736

2837
let mut y: Vec<f32> = Vec::with_capacity(num_samples);
29-
let mut x: Vec<f32> = Vec::with_capacity(num_samples);
38+
let mut x: Vec<f32> = Vec::with_capacity(num_samples * num_features);
3039

3140
for i in 0..num_samples {
3241
let label = i % num_centers;
3342
y.push(label as f32);
3443
for j in 0..num_features {
35-
x.push(centers[label][j].sample(&mut rng));
44+
x.push(sample_normal(centers[label][j], cluster_std, &mut rng));
3645
}
3746
}
3847

@@ -59,21 +68,20 @@ pub fn make_circles(num_samples: usize, factor: f32, noise: f32) -> Dataset<f32,
5968
let linspace_out = linspace(0.0, 2.0 * std::f32::consts::PI, num_samples_out);
6069
let linspace_in = linspace(0.0, 2.0 * std::f32::consts::PI, num_samples_in);
6170

62-
let noise = Normal::new(0.0, noise).unwrap();
6371
let mut rng = rand::rng();
6472

6573
let mut x: Vec<f32> = Vec::with_capacity(num_samples * 2);
6674
let mut y: Vec<f32> = Vec::with_capacity(num_samples);
6775

6876
for v in linspace_out {
69-
x.push(v.cos() + noise.sample(&mut rng));
70-
x.push(v.sin() + noise.sample(&mut rng));
77+
x.push(v.cos() + sample_normal(0.0, noise, &mut rng));
78+
x.push(v.sin() + sample_normal(0.0, noise, &mut rng));
7179
y.push(0.0);
7280
}
7381

7482
for v in linspace_in {
75-
x.push(v.cos() * factor + noise.sample(&mut rng));
76-
x.push(v.sin() * factor + noise.sample(&mut rng));
83+
x.push(v.cos() * factor + sample_normal(0.0, noise, &mut rng));
84+
x.push(v.sin() * factor + sample_normal(0.0, noise, &mut rng));
7785
y.push(1.0);
7886
}
7987

@@ -96,21 +104,20 @@ pub fn make_moons(num_samples: usize, noise: f32) -> Dataset<f32, u32> {
96104
let linspace_out = linspace(0.0, std::f32::consts::PI, num_samples_out);
97105
let linspace_in = linspace(0.0, std::f32::consts::PI, num_samples_in);
98106

99-
let noise = Normal::new(0.0, noise).unwrap();
100107
let mut rng = rand::rng();
101108

102109
let mut x: Vec<f32> = Vec::with_capacity(num_samples * 2);
103110
let mut y: Vec<f32> = Vec::with_capacity(num_samples);
104111

105112
for v in linspace_out {
106-
x.push(v.cos() + noise.sample(&mut rng));
107-
x.push(v.sin() + noise.sample(&mut rng));
113+
x.push(v.cos() + sample_normal(0.0, noise, &mut rng));
114+
x.push(v.sin() + sample_normal(0.0, noise, &mut rng));
108115
y.push(0.0);
109116
}
110117

111118
for v in linspace_in {
112-
x.push(1.0 - v.cos() + noise.sample(&mut rng));
113-
x.push(1.0 - v.sin() + noise.sample(&mut rng) - 0.5);
119+
x.push(1.0 - v.cos() + sample_normal(0.0, noise, &mut rng));
120+
x.push(1.0 - v.sin() + sample_normal(0.0, noise, &mut rng) - 0.5);
114121
y.push(1.0);
115122
}
116123

src/ensemble/base_forest_regressor.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use rand::Rng;
1+
use rand::RngExt;
22
use std::fmt::Debug;
33

44
#[cfg(feature = "serde")]
@@ -209,7 +209,7 @@ impl<TX: Number + FloatNumber + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1
209209
result / TY::from(n_trees).unwrap()
210210
}
211211

212-
fn sample_with_replacement(nrows: usize, rng: &mut impl Rng) -> Vec<usize> {
212+
fn sample_with_replacement(nrows: usize, rng: &mut impl rand::Rng) -> Vec<usize> {
213213
let mut samples = vec![0; nrows];
214214
for _ in 0..nrows {
215215
let xi = rng.random_range(0..nrows);

src/ensemble/random_forest_classifier.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
//!
4646
//! <script src="https://polyfill.io/v3/polyfill.min.js?features=es6"></script>
4747
//! <script id="MathJax-script" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
48-
use rand::Rng;
48+
use rand::RngExt;
4949

5050
use std::default::Default;
5151
use std::fmt::Debug;
@@ -587,7 +587,11 @@ impl<TX: FloatNumber + PartialOrd, TY: Number + Ord, X: Array2<TX>, Y: Array1<TY
587587
which_max(&result)
588588
}
589589

590-
fn sample_with_replacement(y: &[usize], num_classes: usize, rng: &mut impl Rng) -> Vec<usize> {
590+
fn sample_with_replacement(
591+
y: &[usize],
592+
num_classes: usize,
593+
rng: &mut impl rand::Rng,
594+
) -> Vec<usize> {
591595
let class_weight = vec![1.; num_classes];
592596
let nrows = y.len();
593597
let mut samples = vec![0; nrows];

src/numbers/floatnum.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ impl FloatNumber for f64 {
5656
}
5757

5858
fn rand() -> f64 {
59-
use rand::Rng;
59+
use rand::RngExt;
6060
let mut rng = get_rng_impl(None);
6161
rng.random()
6262
}
@@ -98,7 +98,7 @@ impl FloatNumber for f32 {
9898
}
9999

100100
fn rand() -> f32 {
101-
use rand::Rng;
101+
use rand::RngExt;
102102
let mut rng = get_rng_impl(None);
103103
rng.random()
104104
}

src/numbers/realnum.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
//! This module defines real number and some useful functions that are used in [Linear Algebra](../../linalg/index.html) module.
44
55
use rand::rngs::SmallRng;
6-
use rand::{Rng, SeedableRng};
6+
use rand::{RngExt, SeedableRng};
77

88
use num_traits::Float;
99

src/rand_custom.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ pub fn get_rng_impl(seed: Option<u64>) -> RngImpl {
1111
None => {
1212
cfg_if::cfg_if! {
1313
if #[cfg(feature = "std_rand")] {
14-
use rand::RngCore;
14+
use rand::Rng;
1515
// FIX: thread_rng() deprecated in rand 0.9 → use rng()
16+
// FIX: rand 0.10 no longer re-exports RngCore at root;
17+
// import rand::Rng (supertrait) instead so next_u64() resolves
1618
RngImpl::seed_from_u64(rand::rng().next_u64())
1719
} else {
1820
// no std_random feature build, use getrandom

src/tree/base_tree_regressor.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use std::fmt::Debug;
44
use std::marker::PhantomData;
55

66
use rand::seq::SliceRandom;
7-
use rand::Rng;
7+
use rand::RngExt;
88

99
#[cfg(feature = "serde")]
1010
use serde::{Deserialize, Serialize};
@@ -292,7 +292,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
292292
&mut self,
293293
visitor: &mut NodeVisitor<'_, TX, TY, X, Y>,
294294
mtry: usize,
295-
rng: &mut impl Rng,
295+
rng: &mut impl rand::Rng,
296296
) -> bool {
297297
let (_, n_attr) = visitor.x.shape();
298298

@@ -336,7 +336,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
336336
sum: f64,
337337
parent_gain: f64,
338338
j: usize,
339-
rng: &mut impl Rng,
339+
rng: &mut impl rand::Rng,
340340
) {
341341
let (min_val, max_val) = {
342342
let mut min_opt = None;
@@ -476,7 +476,7 @@ impl<TX: Number + PartialOrd, TY: Number, X: Array2<TX>, Y: Array1<TY>>
476476
mut visitor: NodeVisitor<'a, TX, TY, X, Y>,
477477
mtry: usize,
478478
visitor_queue: &mut LinkedList<NodeVisitor<'a, TX, TY, X, Y>>,
479-
rng: &mut impl Rng,
479+
rng: &mut impl rand::Rng,
480480
) -> bool {
481481
let (n, _) = visitor.x.shape();
482482
let mut tc = 0;

0 commit comments

Comments
 (0)