1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
use ndarray::Array2;
use crate::{Error, Result};
/// Fitted DBSCAN radius-voting prediction state.
#[derive(Clone, Debug, PartialEq)]
pub struct DbscanModel {
/// Training samples retained by the fitted neighbor index.
pub samples: Array2<f64>,
/// Training cluster indices; negative values represent noise.
pub cluster_indices: Vec<i64>,
/// Number of non-noise clusters.
pub n_clusters: usize,
/// Inclusive Euclidean neighborhood radius.
pub epsilon: f64,
}
impl DbscanModel {
/// Creates validated DBSCAN inference state.
pub fn new(
samples: Array2<f64>,
cluster_indices: Vec<i64>,
n_clusters: usize,
epsilon: f64,
) -> Result<Self> {
if samples.nrows() == 0
|| samples.ncols() == 0
|| cluster_indices.len() != samples.nrows()
|| n_clusters == 0
|| !epsilon.is_finite()
|| epsilon <= 0.0
|| cluster_indices
.iter()
.any(|&label| label >= n_clusters as i64)
{
return Err(Error::InvalidModel("invalid DBSCAN inference state".into()));
}
Ok(Self {
samples,
cluster_indices,
n_clusters,
epsilon,
})
}
}