1extern crate flame_clustering;
7
8use flame_clustering::{distance, DistanceGraph};
9use std::env;
10use std::fs::File;
11use std::io::{self, Write};
12use std::process::exit;
13
14fn read_data(reader: impl io::BufRead) -> io::Result<Vec<Vec<f64>>> {
15 let mut lines = reader
16 .lines()
17 .map(|x| x.unwrap().trim().to_string())
18 .filter(|x| !x.is_empty());
19
20 let header = lines
21 .next()
22 .unwrap()
23 .split_whitespace()
24 .map(|n| n.parse::<usize>().unwrap())
25 .collect::<Vec<usize>>();
26 let n = header[0];
27 let m = header[1];
28 println!("Reading dataset with {} rows and {} columns", n, m);
29
30 let mut out = Vec::with_capacity(n);
31 for line in lines {
32 let v = line
33 .split_whitespace()
34 .map(|n| n.parse::<f64>().unwrap())
35 .collect::<Vec<f64>>();
36 assert_eq!(v.len(), m);
37 out.push(v);
38 }
39 Ok(out)
40}
41
42fn print_cluster(cluster: &[usize]) {
43 for (j, v) in cluster.iter().enumerate() {
44 if j > 0 {
45 print!(",");
46 if j % 10 == 0 {
47 println!();
48 }
49 }
50 print!("{:5}", v);
51 }
52 println!();
53}
54
55fn main() -> io::Result<()> {
56 let filename = env::args().nth(1);
57 if filename.is_none() {
58 eprintln!("No input file");
59 exit(1);
60 }
61 let data = read_data(io::BufReader::new(File::open(filename.unwrap())?))?;
62 let flame = DistanceGraph::build(&data, distance::euclidean);
63
64 print!("Detecting Cluster Supporting Objects ...");
65 io::stdout().flush()?;
66 let supports = flame.find_supporting_objects(10, -2.0);
67 println!("done, found {}", supports.count());
68
69 print!("Propagating fuzzy memberships ... ");
70 io::stdout().flush()?;
71 let fuzzyships = supports
72 .approximate_fuzzy_memberships(500, 1e-6)
73 .assign_outliers();
74 println!("done");
75
76 print!("Defining clusters from fuzzy memberships ... ");
77 io::stdout().flush()?;
78 let (clusters, outliers) = fuzzyships.make_clusters(-1.0);
79 println!("done");
80
81 for (i, cluster) in clusters.iter().enumerate() {
82 print!("\nCluster {:3}, with {:6} members:\n", i + 1, cluster.len());
83 print_cluster(cluster);
84 }
85 print!("\nCluster outliers, with {:6} members:\n", outliers.len());
86 print_cluster(&outliers);
87
88 Ok(())
89}