Skip to content

Commit

Permalink
Use FromPrimitive instead of From<u32>
Browse files Browse the repository at this point in the history
This allows `f32` to be used as the element type for `HDBSCAN`.
  • Loading branch information
msk committed Nov 2, 2024
1 parent 97c1824 commit 5e18b04
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 17 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ file is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and
this project adheres to [Semantic
Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

### Added

- `HDbscan` now accepts `f32`, in addion to `f64`, as the element type of the
input matrix.

## [0.9.0] - 2024-08-09

### Changed
Expand Down Expand Up @@ -111,6 +118,7 @@ Versioning](https://semver.org/spec/v2.0.0.html).
- The [OPTICS](https://en.wikipedia.org/wiki/OPTICS_algorithm) clustering
algorithm.

[Unreleased]: https://github.com/petabi/petal-clustering/compare/0.9.0...main
[0.9.0]: https://github.com/petabi/petal-clustering/compare/0.8.0...0.9.0
[0.8.0]: https://github.com/petabi/petal-clustering/compare/0.7.0...0.8.0
[0.7.0]: https://github.com/petabi/petal-clustering/compare/0.6.0...0.7.0
Expand Down
56 changes: 39 additions & 17 deletions src/hdbscan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,7 @@ where

impl<S, A, M> Fit<ArrayBase<S, Ix2>, (HashMap<usize, Vec<usize>>, Vec<usize>)> for HDbscan<A, M>
where
A: AddAssign + DivAssign + FloatCore + FromPrimitive + Sync + Send + TryFrom<u32>,
<A as std::convert::TryFrom<u32>>::Error: Debug,
A: AddAssign + DivAssign + FloatCore + FromPrimitive + Sync + Send,
S: Data<Elem = A>,
M: Metric<A> + Clone + Sync + Send,
{
Expand Down Expand Up @@ -276,12 +275,9 @@ fn condense_mst<A: FloatCore + Div>(
result
}

fn get_stability<A: FloatCore + AddAssign + Sub + TryFrom<u32>>(
fn get_stability<A: FloatCore + FromPrimitive + AddAssign + Sub>(
condensed_tree: &ArrayView1<(usize, usize, A, usize)>,
) -> HashMap<usize, A>
where
<A as TryFrom<u32>>::Error: Debug,
{
) -> HashMap<usize, A> {
let mut births: HashMap<_, _> = condensed_tree.iter().fold(HashMap::new(), |mut births, v| {
let entry = births.entry(v.1).or_insert(v.2);
if *entry > v.2 {
Expand All @@ -304,19 +300,15 @@ where
|mut stability, (parent, _child, lambda, size)| {
let entry = stability.entry(*parent).or_insert_with(A::zero);
let birth = births.get(parent).expect("invalid child node.");
*entry += (*lambda - *birth)
* A::try_from(u32::try_from(*size).expect("out of bound")).expect("out of bound");
*entry += (*lambda - *birth) * A::from_usize(*size).expect("infallible");
stability
},
)
}

fn find_clusters<A: FloatCore + AddAssign + Sub + TryFrom<u32>>(
fn find_clusters<A: FloatCore + FromPrimitive + AddAssign + Sub>(
condensed_tree: &ArrayView1<(usize, usize, A, usize)>,
) -> (HashMap<usize, Vec<usize>>, Vec<usize>)
where
<A as TryFrom<u32>>::Error: Debug,
{
) -> (HashMap<usize, Vec<usize>>, Vec<usize>) {
let mut stability = get_stability(condensed_tree);
let mut nodes: Vec<_> = stability.keys().copied().collect();
nodes.sort_unstable();
Expand Down Expand Up @@ -918,15 +910,45 @@ impl Components {
}

mod test {
#[test]
fn hdbscan32() {
use ndarray::{array, Array2};
use petal_neighbors::distance::Euclidean;

use crate::Fit;

let data: Array2<f32> = array![
[1.0, 2.0],
[1.1, 2.2],
[0.9, 1.9],
[1.0, 2.1],
[-2.0, 3.0],
[-2.2, 3.1],
];
let mut hdbscan = super::HDbscan {
eps: 0.5,
alpha: 1.,
min_samples: 2,
min_cluster_size: 2,
metric: Euclidean::default(),
boruvka: false,
};
let (clusters, outliers) = hdbscan.fit(&data);
assert_eq!(clusters.len(), 2);
assert_eq!(
outliers.len(),
data.nrows() - clusters.values().fold(0, |acc, v| acc + v.len())
);
}

#[test]
fn hdbscan() {
use ndarray::array;
fn hdbscan64() {
use ndarray::{array, Array2};
use petal_neighbors::distance::Euclidean;

use crate::Fit;

let data = array![
let data: Array2<f64> = array![
[1.0, 2.0],
[1.1, 2.2],
[0.9, 1.9],
Expand Down

0 comments on commit 5e18b04

Please sign in to comment.