extern crate fuzzy_dbscan;
extern crate utils;
use fuzzy_dbscan::*;
use utils::*;
#[macro_export]
macro_rules! assert_any {
( $clusters:ident, $pred:expr, $res:expr ) => {
assert!(
$clusters.iter().all(|ref c| c.iter().any($pred)) == $res,
concat!("(", stringify!($pred), ") != ", stringify!($res))
);
};
}
const BASE_N: usize = 400;
const BASE_R: f64 = 10.0;
fn unimodal_gaussian() -> Vec<Point> {
flat_vec![gaussian_circle(BASE_N, 0.0, 0.0, BASE_R)]
}
fn mixed_gaussian() -> Vec<Point> {
flat_vec![
gaussian_circle(BASE_N, 0.0, 0.0, BASE_R),
gaussian_circle(BASE_N, BASE_R * 2.0, 0.0, BASE_R),
gaussian_circle(BASE_N / 8, BASE_R, 0.0, BASE_R / 2.0),
]
}
#[test]
fn reduce_to_dbscan() {
let points = unimodal_gaussian();
let fuzzy_dbscan = FuzzyDBSCAN {
eps_min: BASE_R,
eps_max: BASE_R,
pts_min: 1.0,
pts_max: 1.0,
};
let clusters = fuzzy_dbscan.cluster(&points);
dump_svg("reduce_to_dbscan", &points, &clusters);
assert_eq!(clusters.len(), 1);
assert_any!(clusters, |ref a| a.label != 1.0, false);
assert_any!(clusters, |ref a| a.category != Category::Core, false);
}
#[test]
fn reduce_to_fuzzy_core_dbscan() {
let points = unimodal_gaussian();
let fuzzy_dbscan = FuzzyDBSCAN {
eps_min: BASE_R,
eps_max: BASE_R,
pts_min: 1.0,
pts_max: BASE_N as f64,
};
let clusters = fuzzy_dbscan.cluster(&points);
dump_svg("reduce_to_fuzzy_core_dbscan", &points, &clusters);
assert_eq!(clusters.len(), 1);
assert_any!(
clusters,
|ref a| a.category == Category::Core && a.label != 1.0,
true
);
assert_any!(clusters, |ref a| a.category == Category::Border, false);
assert_any!(clusters, |ref a| a.category == Category::Noise, false);
}
#[test]
fn reduce_to_fuzzy_border_dbscan() {
let points = unimodal_gaussian();
let fuzzy_dbscan = FuzzyDBSCAN {
eps_min: 1.0,
eps_max: BASE_R,
pts_min: (BASE_N / 2) as f64,
pts_max: (BASE_N / 2) as f64,
};
let clusters = fuzzy_dbscan.cluster(&points);
dump_svg("reduce_to_fuzzy_border_dbscan", &points, &clusters);
assert_eq!(clusters.len(), 1);
assert_any!(
clusters,
|ref a| a.category == Category::Core && a.label != 1.0,
false
);
assert_any!(clusters, |ref a| a.category == Category::Border, true);
}
#[test]
fn full_fuzzy_dbscan() {
let points = mixed_gaussian();
let fuzzy_dbscan = FuzzyDBSCAN {
eps_min: BASE_R / 3.0,
eps_max: BASE_R / 3.0 * 2.0,
pts_min: (BASE_N / 2) as f64 * 0.68,
pts_max: (BASE_N / 2) as f64 * 0.95,
};
let clusters = fuzzy_dbscan.cluster(&points);
dump_svg("full_fuzzy_dbscan", &points, &clusters);
assert_eq!(clusters.len(), 2);
assert_any!(
clusters,
|ref a| a.category == Category::Core && a.label != 1.0,
true
);
assert_any!(
clusters,
|ref a| a.category == Category::Border && a.label != 1.0,
true
);
assert_any!(clusters, |ref a| a.category == Category::Noise, false);
}
#[test]
fn noise() {
let points = unimodal_gaussian();
let fuzzy_dbscan = FuzzyDBSCAN {
eps_min: BASE_R * 2.0,
eps_max: BASE_R * 4.0,
pts_min: BASE_N as f64 * 2.0,
pts_max: BASE_N as f64 * 4.0,
};
let clusters = fuzzy_dbscan.cluster(&points);
dump_svg("noise", &points, &clusters);
assert_eq!(clusters.len(), 1);;
assert_any!(clusters, |ref a| a.category != Category::Noise, false);
}